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

Generated by: LCOV version 1.14