pcap: save if_index of the bound device
[dpdk.git] / lib / librte_pmd_pcap / rte_eth_pcap.c
index 50de885..03e6e6c 100644 (file)
@@ -1,7 +1,8 @@
 /*-
  *   BSD LICENSE
  * 
- *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2014 6WIND S.A.
  *   All rights reserved.
  * 
  *   Redistribution and use in source and binary forms, with or without
 #include <rte_memcpy.h>
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
+#include <rte_kvargs.h>
+
+#include <net/if.h>
 
 #include "rte_eth_pcap.h"
-#include "rte_eth_pcap_arg_parser.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN 4096
 #define RTE_ETH_PCAP_PROMISC 1
 #define RTE_ETH_PCAP_TIMEOUT -1
-#define RTE_ETH_PCAP_MBUFS 64
 #define ETH_PCAP_RX_PCAP_ARG   "rx_pcap"
 #define ETH_PCAP_TX_PCAP_ARG   "tx_pcap"
 #define ETH_PCAP_RX_IFACE_ARG  "rx_iface"
@@ -87,6 +89,8 @@ struct pmd_internals {
        unsigned nb_rx_queues;
        unsigned nb_tx_queues;
 
+       int if_index;
+
        struct pcap_rx_queue rx_queue[RTE_PMD_RING_MAX_RX_RINGS];
        struct pcap_tx_queue tx_queue[RTE_PMD_RING_MAX_TX_RINGS];
 };
@@ -118,32 +122,46 @@ eth_pcap_rx(void *queue,
        struct pcap_pkthdr header;
        const u_char *packet;
        struct rte_mbuf *mbuf;
-       static struct rte_mbuf *mbufs[RTE_ETH_PCAP_MBUFS] = { 0 };
        struct pcap_rx_queue *pcap_q = queue;
+       struct rte_pktmbuf_pool_private *mbp_priv;
        uint16_t num_rx = 0;
+       uint16_t buf_size;
 
        if (unlikely(pcap_q->pcap == NULL || nb_pkts == 0))
                return 0;
 
-       if(unlikely(!mbufs[0]))
-               for (i = 0; i < RTE_ETH_PCAP_MBUFS; i++)
-                       mbufs[i] = rte_pktmbuf_alloc(pcap_q->mb_pool);
-
        /* Reads the given number of packets from the pcap file one by one
         * and copies the packet data into a newly allocated mbuf to return.
         */
        for (i = 0; i < nb_pkts; i++) {
-               mbuf = mbufs[i % RTE_ETH_PCAP_MBUFS];
+               /* Get the next PCAP packet */
                packet = pcap_next(pcap_q->pcap, &header);
                if (unlikely(packet == NULL))
                        break;
+               else 
+                       mbuf = rte_pktmbuf_alloc(pcap_q->mb_pool);
                if (unlikely(mbuf == NULL))
                        break;
-               rte_memcpy(mbuf->pkt.data, packet, header.len);
-               mbuf->pkt.data_len = (uint16_t)header.len;
-               mbuf->pkt.pkt_len = mbuf->pkt.data_len;
-               bufs[i] = mbuf;
-               num_rx++;
+
+               /* Now get the space available for data in the mbuf */
+               mbp_priv =  rte_mempool_get_priv(pcap_q->mb_pool);
+               buf_size = (uint16_t) (mbp_priv->mbuf_data_room_size -
+                               RTE_PKTMBUF_HEADROOM);
+
+               if (header.len <= buf_size) {
+                       /* pcap packet will fit in the mbuf, go ahead and copy */
+                       rte_memcpy(mbuf->pkt.data, packet, header.len);
+                       mbuf->pkt.data_len = (uint16_t)header.len;
+                       mbuf->pkt.pkt_len = mbuf->pkt.data_len;
+                       bufs[i] = mbuf;
+                       num_rx++;
+               } else {
+                       /* pcap packet will not fit in the mbuf, so drop packet */
+                       RTE_LOG(ERR, PMD, 
+                                       "PCAP packet %d bytes will not fit in mbuf (%d bytes)\n",
+                                       header.len, buf_size);
+                       rte_pktmbuf_free(mbuf);
+               }
        }
        pcap_q->rx_pkts += num_rx;
        return num_rx;
@@ -199,6 +217,7 @@ eth_pcap_tx_dumper(void *queue,
        return num_tx;
 }
 
+#ifdef PCAP_CAN_SEND
 /*
  * Callback to handle sending packets through a real NIC.
  */
@@ -229,6 +248,17 @@ eth_pcap_tx(void *queue,
        tx_queue->err_pkts += nb_pkts - num_tx;
        return num_tx;
 }
+#else
+static uint16_t
+eth_pcap_tx(__rte_unused void *queue,
+               __rte_unused struct rte_mbuf **bufs,
+               __rte_unused uint16_t nb_pkts)
+{
+       RTE_LOG(ERR, PMD, "pcap library cannot send packets, please rebuild "
+                         "with a more up to date libpcap\n");
+       return -1;
+}
+#endif
 
 static int
 eth_dev_start(struct rte_eth_dev *dev)
@@ -274,6 +304,7 @@ eth_dev_info(struct rte_eth_dev *dev,
 {
        struct pmd_internals *internals = dev->data->dev_private;
        dev_info->driver_name = drivername;
+       dev_info->if_index = internals->if_index;
        dev_info->max_mac_addrs = 1;
        dev_info->max_rx_pktlen = (uint32_t) -1;
        dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
@@ -388,10 +419,10 @@ static struct eth_dev_ops ops = {
  * reference of it for use it later on.
  */
 static int
-open_rx_pcap(char *value, void *extra_args)
+open_rx_pcap(const char *key __rte_unused, const char *value, void *extra_args)
 {
        unsigned i;
-       char *pcap_filename = value;
+       const char *pcap_filename = value;
        struct rx_pcaps *pcaps = extra_args;
        pcap_t *rx_pcap;
 
@@ -411,10 +442,10 @@ open_rx_pcap(char *value, void *extra_args)
  * for use it later on.
  */
 static int
-open_tx_pcap(char *value, void *extra_args)
+open_tx_pcap(const char *key __rte_unused, const char *value, void *extra_args)
 {
        unsigned i;
-       char *pcap_filename = value;
+       const char *pcap_filename = value;
        struct tx_pcaps *dumpers = extra_args;
        pcap_t *tx_pcap;
        pcap_dumper_t *dumper;
@@ -461,7 +492,7 @@ open_iface_live(const char *iface, pcap_t **pcap) {
  * Opens an interface for reading and writing
  */
 static inline int
-open_rx_tx_iface(char *value, void *extra_args)
+open_rx_tx_iface(const char *key __rte_unused, const char *value, void *extra_args)
 {
        const char *iface = value;
        pcap_t **pcap = extra_args;
@@ -475,7 +506,7 @@ open_rx_tx_iface(char *value, void *extra_args)
  * Opens a NIC for reading packets from it
  */
 static inline int
-open_rx_iface(char *value, void *extra_args)
+open_rx_iface(const char *key __rte_unused, const char *value, void *extra_args)
 {
        unsigned i;
        const char *iface = value;
@@ -495,7 +526,7 @@ open_rx_iface(char *value, void *extra_args)
  * Opens a NIC for writing packets to it
  */
 static inline int
-open_tx_iface(char *value, void *extra_args)
+open_tx_iface(const char *key __rte_unused, const char *value, void *extra_args)
 {
        unsigned i;
        const char *iface = value;
@@ -517,10 +548,19 @@ rte_pmd_init_internals(const unsigned nb_rx_queues,
                const unsigned nb_tx_queues,
                const unsigned numa_node,
                struct pmd_internals **internals,
-               struct rte_eth_dev **eth_dev)
+               struct rte_eth_dev **eth_dev,
+               struct args_dict *dict)
 {
        struct rte_eth_dev_data *data = NULL;
        struct rte_pci_device *pci_dev = NULL;
+       unsigned k_idx;
+       struct key_value *pair = NULL;
+
+       for (k_idx = 0; k_idx < dict->index; k_idx++) {
+               pair = &dict->pairs[k_idx];
+               if (strstr(pair->key, ETH_PCAP_IFACE_ARG) != NULL)
+                       break;
+       }
 
        RTE_LOG(INFO, PMD,
                        "Creating pcap-backed ethdev on numa socket %u\n", numa_node);
@@ -557,6 +597,11 @@ rte_pmd_init_internals(const unsigned nb_rx_queues,
        (*internals)->nb_rx_queues = nb_rx_queues;
        (*internals)->nb_tx_queues = nb_tx_queues;
 
+       if (pair == NULL)
+               (*internals)->if_index = 0;
+       else
+               (*internals)->if_index = if_nametoindex(pair->value);
+
        pci_dev->numa_node = numa_node;
 
        data->dev_private = *internals;
@@ -586,7 +631,8 @@ rte_eth_from_pcaps_n_dumpers(pcap_t * const rx_queues[],
                const unsigned nb_rx_queues,
                pcap_dumper_t * const tx_queues[],
                const unsigned nb_tx_queues,
-               const unsigned numa_node)
+               const unsigned numa_node,
+               struct args_dict *dict)
 {
        struct pmd_internals *internals = NULL;
        struct rte_eth_dev *eth_dev = NULL;
@@ -599,7 +645,7 @@ rte_eth_from_pcaps_n_dumpers(pcap_t * const rx_queues[],
                return -1;
 
        if (rte_pmd_init_internals(nb_rx_queues, nb_tx_queues, numa_node,
-                       &internals, &eth_dev) < 0)
+                       &internals, &eth_dev, dict) < 0)
                return -1;
 
        for (i = 0; i < nb_rx_queues; i++) {
@@ -620,7 +666,8 @@ rte_eth_from_pcaps(pcap_t * const rx_queues[],
                const unsigned nb_rx_queues,
                pcap_t * const tx_queues[],
                const unsigned nb_tx_queues,
-               const unsigned numa_node)
+               const unsigned numa_node,
+               struct args_dict *dict)
 {
        struct pmd_internals *internals = NULL;
        struct rte_eth_dev *eth_dev = NULL;
@@ -633,7 +680,7 @@ rte_eth_from_pcaps(pcap_t * const rx_queues[],
                return -1;
 
        if (rte_pmd_init_internals(nb_rx_queues, nb_tx_queues, numa_node,
-                       &internals, &eth_dev) < 0)
+                       &internals, &eth_dev, dict) < 0)
                return -1;
 
        for (i = 0; i < nb_rx_queues; i++) {
@@ -655,11 +702,11 @@ rte_pmd_pcap_init(const char *name, const char *params)
 {
        unsigned numa_node, using_dumpers = 0;
        int ret;
-       struct args_dict dict;
+       struct rte_kvargs *kvlist;
        struct rx_pcaps pcaps;
        struct tx_pcaps dumpers;
 
-       rte_eth_pcap_init_args_dict(&dict);
+       RTE_LOG(INFO, PMD, "Initializing pmd_pcap for %s\n", name);
 
        numa_node = rte_socket_id();
 
@@ -667,34 +714,35 @@ rte_pmd_pcap_init(const char *name, const char *params)
        start_cycles = rte_get_timer_cycles();
        hz = rte_get_timer_hz();
 
-       if (rte_eth_pcap_parse_args(&dict, name, params, valid_arguments) < 0)
+       kvlist = rte_kvargs_parse(params, valid_arguments);
+       if (kvlist == NULL)
                return -1;
 
        /*
         * If iface argument is passed we open the NICs and use them for
         * reading / writing
         */
-       if (rte_eth_pcap_num_of_args(&dict, ETH_PCAP_IFACE_ARG) == 1) {
+       if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {
 
-               ret = rte_eth_pcap_post_process_arguments(&dict, ETH_PCAP_IFACE_ARG,
+               ret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,
                                &open_rx_tx_iface, &pcaps.pcaps[0]);
                if (ret < 0)
                        return -1;
 
-               return rte_eth_from_pcaps(pcaps.pcaps, 1, pcaps.pcaps, 1, numa_node);
+               return rte_eth_from_pcaps(pcaps.pcaps, 1, pcaps.pcaps, 1, numa_node, &dict);
        }
 
        /*
         * We check whether we want to open a RX stream from a real NIC or a
         * pcap file
         */
-       if ((pcaps.num_of_rx = rte_eth_pcap_num_of_args(&dict, ETH_PCAP_RX_PCAP_ARG))) {
-               ret = rte_eth_pcap_post_process_arguments(&dict, ETH_PCAP_RX_PCAP_ARG,
+       if ((pcaps.num_of_rx = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG))) {
+               ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,
                                &open_rx_pcap, &pcaps);
        } else {
-               pcaps.num_of_rx = rte_eth_pcap_num_of_args(&dict,
+               pcaps.num_of_rx = rte_kvargs_count(kvlist,
                                ETH_PCAP_RX_IFACE_ARG);
-               ret = rte_eth_pcap_post_process_arguments(&dict, ETH_PCAP_RX_IFACE_ARG,
+               ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_IFACE_ARG,
                                &open_rx_iface, &pcaps);
        }
 
@@ -705,15 +753,15 @@ rte_pmd_pcap_init(const char *name, const char *params)
         * We check whether we want to open a TX stream to a real NIC or a
         * pcap file
         */
-       if ((dumpers.num_of_tx = rte_eth_pcap_num_of_args(&dict,
+       if ((dumpers.num_of_tx = rte_kvargs_count(kvlist,
                        ETH_PCAP_TX_PCAP_ARG))) {
-               ret = rte_eth_pcap_post_process_arguments(&dict, ETH_PCAP_TX_PCAP_ARG,
+               ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG,
                                &open_tx_pcap, &dumpers);
                using_dumpers = 1;
        } else {
-               dumpers.num_of_tx = rte_eth_pcap_num_of_args(&dict,
+               dumpers.num_of_tx = rte_kvargs_count(kvlist,
                                ETH_PCAP_TX_IFACE_ARG);
-               ret = rte_eth_pcap_post_process_arguments(&dict, ETH_PCAP_TX_IFACE_ARG,
+               ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_IFACE_ARG,
                                &open_tx_iface, &dumpers);
        }
 
@@ -722,10 +770,10 @@ rte_pmd_pcap_init(const char *name, const char *params)
 
        if (using_dumpers)
                return rte_eth_from_pcaps_n_dumpers(pcaps.pcaps, pcaps.num_of_rx,
-                               dumpers.dumpers, dumpers.num_of_tx, numa_node);
+                               dumpers.dumpers, dumpers.num_of_tx, numa_node, &dict);
 
        return rte_eth_from_pcaps(pcaps.pcaps, pcaps.num_of_rx, dumpers.pcaps,
-                       dumpers.num_of_tx, numa_node);
+                       dumpers.num_of_tx, numa_node, &dict);
 
 }