LCOV - code coverage report
Current view: top level - lib/graph - graph_pcap.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 5 99 5.1 %
Date: 2026-04-01 20:02:27 Functions: 2 8 25.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 50 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2023 Marvell International Ltd.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <errno.h>
       6                 :            : #include <pwd.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <unistd.h>
       9                 :            : 
      10                 :            : #include <rte_ethdev.h>
      11                 :            : #include <rte_mbuf.h>
      12                 :            : #include <rte_pcapng.h>
      13                 :            : 
      14                 :            : #include "rte_graph_worker.h"
      15                 :            : 
      16                 :            : #include "graph_pcap_private.h"
      17                 :            : 
      18                 :            : #define GRAPH_PCAP_NUM_PACKETS  1024
      19                 :            : #define GRAPH_PCAP_PKT_POOL     "graph_pcap_pkt_pool"
      20                 :            : #define GRAPH_PCAP_FILE_NAME    "dpdk_graph_pcap_capture_XXXXXX.pcapng"
      21                 :            : 
      22                 :            : /* For multi-process, packets are captured in separate files. */
      23                 :            : static rte_pcapng_t *pcapng_fd;
      24                 :            : static bool pcap_enable;
      25                 :            : struct rte_mempool *pkt_mp;
      26                 :            : 
      27                 :            : void
      28                 :          8 : graph_pcap_enable(bool val)
      29                 :            : {
      30                 :          8 :         pcap_enable = val;
      31                 :          8 : }
      32                 :            : 
      33                 :            : int
      34                 :        109 : graph_pcap_is_enable(void)
      35                 :            : {
      36                 :        109 :         return pcap_enable;
      37                 :            : }
      38                 :            : 
      39                 :            : void
      40                 :          0 : graph_pcap_exit(struct rte_graph *graph)
      41                 :            : {
      42         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
      43                 :          0 :                 rte_mempool_free(pkt_mp);
      44                 :            : 
      45         [ #  # ]:          0 :         if (pcapng_fd) {
      46                 :          0 :                 rte_pcapng_close(pcapng_fd);
      47                 :          0 :                 pcapng_fd = NULL;
      48                 :            :         }
      49                 :            : 
      50                 :            :         /* Disable pcap. */
      51                 :          0 :         graph->pcap_enable = 0;
      52                 :          0 :         graph_pcap_enable(0);
      53                 :          0 : }
      54                 :            : 
      55                 :            : static int
      56                 :          0 : graph_pcap_default_path_get(char **dir_path)
      57                 :            : {
      58                 :            :         struct passwd *pwd;
      59                 :            :         char *home_dir;
      60                 :            : 
      61                 :            :         /* First check for shell environment variable */
      62                 :          0 :         home_dir = getenv("HOME");
      63         [ #  # ]:          0 :         if (home_dir == NULL) {
      64                 :          0 :                 graph_warn("Home env not preset.");
      65                 :            :                 /* Fallback to password file entry */
      66                 :          0 :                 pwd = getpwuid(getuid());
      67         [ #  # ]:          0 :                 if (pwd == NULL)
      68                 :            :                         return -EINVAL;
      69                 :            : 
      70                 :          0 :                 home_dir = pwd->pw_dir;
      71                 :            :         }
      72                 :            : 
      73                 :            :         /* Append default pcap file to directory */
      74         [ #  # ]:          0 :         if (asprintf(dir_path, "%s/%s", home_dir, GRAPH_PCAP_FILE_NAME) == -1)
      75                 :          0 :                 return -ENOMEM;
      76                 :            : 
      77                 :            :         return 0;
      78                 :            : }
      79                 :            : 
      80                 :            : int
      81                 :          0 : graph_pcap_file_open(const char *filename)
      82                 :            : {
      83                 :            :         int fd, ret;
      84                 :            :         uint16_t portid;
      85                 :            :         char file_name[RTE_GRAPH_PCAP_FILE_SZ];
      86                 :            :         char *pcap_dir;
      87                 :            : 
      88         [ #  # ]:          0 :         if (pcapng_fd)
      89                 :          0 :                 goto done;
      90                 :            : 
      91   [ #  #  #  # ]:          0 :         if (!filename || filename[0] == '\0') {
      92         [ #  # ]:          0 :                 if (graph_pcap_default_path_get(&pcap_dir) < 0)
      93                 :            :                         return -1;
      94                 :          0 :                 snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s", pcap_dir);
      95                 :          0 :                 free(pcap_dir);
      96                 :            :         } else {
      97                 :            :                 snprintf(file_name, RTE_GRAPH_PCAP_FILE_SZ, "%s_XXXXXX.pcapng",
      98                 :            :                          filename);
      99                 :            :         }
     100                 :            : 
     101                 :          0 :         fd = mkstemps(file_name, strlen(".pcapng"));
     102         [ #  # ]:          0 :         if (fd < 0) {
     103                 :          0 :                 graph_err("mkstemps() failure");
     104                 :          0 :                 return -1;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         graph_info("pcap filename: %s", file_name);
     108                 :            : 
     109                 :            :         /* Open a capture file */
     110                 :          0 :         pcapng_fd = rte_pcapng_fdopen(fd, NULL, NULL, "Graph pcap tracer",
     111                 :            :                                       NULL);
     112         [ #  # ]:          0 :         if (pcapng_fd == NULL) {
     113                 :          0 :                 graph_err("Graph rte_pcapng_fdopen failed.");
     114                 :          0 :                 goto error;
     115                 :            :         }
     116                 :            : 
     117                 :            :         /* Add the configured interfaces as possible capture ports */
     118         [ #  # ]:          0 :         RTE_ETH_FOREACH_DEV(portid) {
     119                 :          0 :                 ret = rte_pcapng_add_interface(pcapng_fd, portid, DLT_EN10MB,
     120                 :            :                                                NULL, NULL, NULL);
     121         [ #  # ]:          0 :                 if (ret < 0) {
     122                 :          0 :                         graph_err("Graph rte_pcapng_add_interface port %u failed: %d",
     123                 :            :                                   portid, ret);
     124                 :          0 :                         goto error;
     125                 :            :                 }
     126                 :            :         }
     127                 :            : 
     128                 :          0 : done:
     129                 :            :         return 0;
     130                 :          0 : error:
     131         [ #  # ]:          0 :         if (pcapng_fd != NULL) {
     132                 :          0 :                 rte_pcapng_close(pcapng_fd);
     133                 :          0 :                 pcapng_fd = NULL;
     134                 :            :         }
     135                 :          0 :         close(fd);
     136                 :          0 :         return -1;
     137                 :            : }
     138                 :            : 
     139                 :            : int
     140                 :          0 : graph_pcap_mp_init(void)
     141                 :            : {
     142                 :          0 :         pkt_mp = rte_mempool_lookup(GRAPH_PCAP_PKT_POOL);
     143         [ #  # ]:          0 :         if (pkt_mp)
     144                 :          0 :                 goto done;
     145                 :            : 
     146                 :            :         /* Make a pool for cloned packets */
     147                 :          0 :         pkt_mp = rte_pktmbuf_pool_create_by_ops(GRAPH_PCAP_PKT_POOL,
     148                 :            :                         IOV_MAX + RTE_GRAPH_BURST_SIZE, 0, 0,
     149                 :          0 :                         rte_pcapng_mbuf_size(RTE_MBUF_DEFAULT_BUF_SIZE),
     150                 :            :                         SOCKET_ID_ANY, "ring_mp_mc");
     151         [ #  # ]:          0 :         if (pkt_mp == NULL) {
     152                 :          0 :                 graph_err("Cannot create mempool for graph pcap capture.");
     153                 :          0 :                 return -1;
     154                 :            :         }
     155                 :            : 
     156                 :          0 : done:
     157                 :            :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :            : int
     161                 :          0 : graph_pcap_init(struct graph *graph)
     162                 :            : {
     163                 :          0 :         struct rte_graph *graph_data = graph->graph;
     164                 :            : 
     165         [ #  # ]:          0 :         if (graph_pcap_file_open(graph->pcap_filename) < 0)
     166                 :          0 :                 goto error;
     167                 :            : 
     168         [ #  # ]:          0 :         if (graph_pcap_mp_init() < 0)
     169                 :          0 :                 goto error;
     170                 :            : 
     171                 :            :         /* User configured number of packets to capture. */
     172         [ #  # ]:          0 :         if (graph->num_pkt_to_capture)
     173                 :          0 :                 graph_data->nb_pkt_to_capture = graph->num_pkt_to_capture;
     174                 :            :         else
     175                 :          0 :                 graph_data->nb_pkt_to_capture = GRAPH_PCAP_NUM_PACKETS;
     176                 :            : 
     177                 :            :         /* All good. Now populate data for secondary process. */
     178                 :          0 :         rte_strscpy(graph_data->pcap_filename, graph->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ);
     179                 :          0 :         graph_data->pcap_enable = 1;
     180                 :            : 
     181                 :          0 :         return 0;
     182                 :            : 
     183                 :          0 : error:
     184                 :          0 :         graph_pcap_exit(graph_data);
     185                 :          0 :         graph_pcap_enable(0);
     186                 :          0 :         graph_err("Graph pcap initialization failed. Disabling pcap trace.");
     187                 :          0 :         return -1;
     188                 :            : }
     189                 :            : 
     190                 :            : uint16_t
     191                 :          0 : graph_pcap_dispatch(struct rte_graph *graph,
     192                 :            :                               struct rte_node *node, void **objs,
     193                 :            :                               uint16_t nb_objs)
     194                 :            : {
     195                 :            :         struct rte_mbuf *mbuf_clones[RTE_GRAPH_BURST_SIZE];
     196                 :            :         uint64_t i, num_packets;
     197                 :            :         struct rte_mbuf *mbuf;
     198                 :            :         char *comment;
     199                 :            :         ssize_t len;
     200                 :            : 
     201   [ #  #  #  # ]:          0 :         if (!nb_objs || (graph->nb_pkt_captured >= graph->nb_pkt_to_capture))
     202                 :          0 :                 goto done;
     203                 :            : 
     204                 :          0 :         num_packets = graph->nb_pkt_to_capture - graph->nb_pkt_captured;
     205                 :            :         /* nb_objs will never be greater than RTE_GRAPH_BURST_SIZE */
     206                 :          0 :         if (num_packets > nb_objs)
     207                 :            :                 num_packets = nb_objs;
     208                 :            : 
     209                 :            :         /* put a comment on all these packets */
     210         [ #  # ]:          0 :         if (asprintf(&comment, "%s: %s", graph->name, node->name) < 0) {
     211                 :          0 :                 graph_err("asprintf for comment failed.");
     212                 :          0 :                 comment = NULL;
     213                 :            :         }
     214                 :            : 
     215         [ #  # ]:          0 :         for (i = 0; i < num_packets; i++) {
     216                 :            :                 struct rte_mbuf *mc;
     217                 :          0 :                 mbuf = (struct rte_mbuf *)objs[i];
     218                 :            : 
     219                 :          0 :                 mc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len, 0, comment);
     220         [ #  # ]:          0 :                 if (mc == NULL)
     221                 :            :                         break;
     222                 :            : 
     223                 :          0 :                 mbuf_clones[i] = mc;
     224                 :            :         }
     225                 :          0 :         free(comment);
     226                 :            : 
     227                 :            :         /* write it to capture file */
     228                 :          0 :         len = rte_pcapng_write_packets(pcapng_fd, mbuf_clones, i);
     229                 :          0 :         rte_pktmbuf_free_bulk(mbuf_clones, i);
     230         [ #  # ]:          0 :         if (len <= 0)
     231                 :          0 :                 goto done;
     232                 :            : 
     233                 :          0 :         graph->nb_pkt_captured += i;
     234                 :            : 
     235                 :          0 : done:
     236                 :          0 :         return node->original_process(graph, node, objs, nb_objs);
     237                 :            : }

Generated by: LCOV version 1.14