examples/ip_pipeline: add CLI interface
[dpdk.git] / drivers / net / tap / rte_eth_tap.c
index fd42572..ed6d738 100644 (file)
@@ -15,6 +15,7 @@
 #include <rte_net.h>
 #include <rte_debug.h>
 #include <rte_ip.h>
+#include <rte_string_fns.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #define DEFAULT_TAP_NAME        "dtap"
 
 #define ETH_TAP_IFACE_ARG       "iface"
-#define ETH_TAP_SPEED_ARG       "speed"
 #define ETH_TAP_REMOTE_ARG      "remote"
 #define ETH_TAP_MAC_ARG         "mac"
 #define ETH_TAP_MAC_FIXED       "fixed"
 
+#define ETH_TAP_USR_MAC_FMT     "xx:xx:xx:xx:xx:xx"
+#define ETH_TAP_CMP_MAC_FMT     "0123456789ABCDEFabcdef"
+#define ETH_TAP_MAC_ARG_FMT     ETH_TAP_MAC_FIXED "|" ETH_TAP_USR_MAC_FMT
+
 static struct rte_vdev_driver pmd_tap_drv;
 
 static const char *valid_arguments[] = {
        ETH_TAP_IFACE_ARG,
-       ETH_TAP_SPEED_ARG,
        ETH_TAP_REMOTE_ARG,
        ETH_TAP_MAC_ARG,
        NULL
@@ -263,7 +266,8 @@ tap_rx_offload_get_port_capa(void)
        return DEV_RX_OFFLOAD_SCATTER |
               DEV_RX_OFFLOAD_IPV4_CKSUM |
               DEV_RX_OFFLOAD_UDP_CKSUM |
-              DEV_RX_OFFLOAD_TCP_CKSUM;
+              DEV_RX_OFFLOAD_TCP_CKSUM |
+              DEV_RX_OFFLOAD_CRC_STRIP;
 }
 
 static uint64_t
@@ -272,7 +276,8 @@ tap_rx_offload_get_queue_capa(void)
        return DEV_RX_OFFLOAD_SCATTER |
               DEV_RX_OFFLOAD_IPV4_CKSUM |
               DEV_RX_OFFLOAD_UDP_CKSUM |
-              DEV_RX_OFFLOAD_TCP_CKSUM;
+              DEV_RX_OFFLOAD_TCP_CKSUM |
+              DEV_RX_OFFLOAD_CRC_STRIP;
 }
 
 static bool
@@ -392,7 +397,8 @@ tap_tx_offload_get_port_capa(void)
         * In order to support legacy apps,
         * report capabilities also as port capabilities.
         */
-       return DEV_TX_OFFLOAD_IPV4_CKSUM |
+       return DEV_TX_OFFLOAD_MULTI_SEGS |
+              DEV_TX_OFFLOAD_IPV4_CKSUM |
               DEV_TX_OFFLOAD_UDP_CKSUM |
               DEV_TX_OFFLOAD_TCP_CKSUM;
 }
@@ -400,7 +406,8 @@ tap_tx_offload_get_port_capa(void)
 static uint64_t
 tap_tx_offload_get_queue_capa(void)
 {
-       return DEV_TX_OFFLOAD_IPV4_CKSUM |
+       return DEV_TX_OFFLOAD_MULTI_SEGS |
+              DEV_TX_OFFLOAD_IPV4_CKSUM |
               DEV_TX_OFFLOAD_UDP_CKSUM |
               DEV_TX_OFFLOAD_TCP_CKSUM;
 }
@@ -1218,7 +1225,7 @@ tap_dev_intr_handler(void *cb_arg)
 }
 
 static int
-tap_intr_handle_set(struct rte_eth_dev *dev, int set)
+tap_lsc_intr_handle_set(struct rte_eth_dev *dev, int set)
 {
        struct pmd_internals *pmd = dev->data->dev_private;
 
@@ -1243,6 +1250,20 @@ tap_intr_handle_set(struct rte_eth_dev *dev, int set)
                                            tap_dev_intr_handler, dev);
 }
 
+static int
+tap_intr_handle_set(struct rte_eth_dev *dev, int set)
+{
+       int err;
+
+       err = tap_lsc_intr_handle_set(dev, set);
+       if (err)
+               return err;
+       err = tap_rx_intr_vec_set(dev, set);
+       if (err && set)
+               tap_lsc_intr_handle_set(dev, 0);
+       return err;
+}
+
 static const uint32_t*
 tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 {
@@ -1321,7 +1342,7 @@ static const struct eth_dev_ops ops = {
 
 static int
 eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
-                  char *remote_iface, int fixed_mac_type)
+                  char *remote_iface, struct ether_addr *mac_addr)
 {
        int numa_node = rte_socket_id();
        struct rte_eth_dev *dev;
@@ -1335,13 +1356,13 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
        data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
        if (!data) {
                RTE_LOG(ERR, PMD, "TAP Failed to allocate data\n");
-               goto error_exit;
+               goto error_exit_nodev;
        }
 
        dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd));
        if (!dev) {
                RTE_LOG(ERR, PMD, "TAP Unable to allocate device struct\n");
-               goto error_exit;
+               goto error_exit_nodev;
        }
 
        pmd = dev->data->dev_private;
@@ -1375,6 +1396,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
 
        pmd->intr_handle.type = RTE_INTR_HANDLE_EXT;
        pmd->intr_handle.fd = -1;
+       dev->intr_handle = &pmd->intr_handle;
 
        /* Presetup the fds to -1 as being not valid */
        for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
@@ -1382,16 +1404,10 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
                pmd->txq[i].fd = -1;
        }
 
-       if (fixed_mac_type) {
-               /* fixed mac = 00:64:74:61:70:<iface_idx> */
-               static int iface_idx;
-               char mac[ETHER_ADDR_LEN] = "\0dtap";
-
-               mac[ETHER_ADDR_LEN - 1] = iface_idx++;
-               rte_memcpy(&pmd->eth_addr, mac, ETHER_ADDR_LEN);
-       } else {
+       if (is_zero_ether_addr(mac_addr))
                eth_random_addr((uint8_t *)&pmd->eth_addr);
-       }
+       else
+               rte_memcpy(&pmd->eth_addr, mac_addr, sizeof(mac_addr));
 
        /* Immediately create the netdevice (this will create the 1st queue). */
        /* rx queue */
@@ -1511,6 +1527,11 @@ error_remote:
        tap_flow_implicit_flush(pmd, NULL);
 
 error_exit:
+       if (pmd->ioctl_sock > 0)
+               close(pmd->ioctl_sock);
+       rte_eth_dev_release_port(dev);
+
+error_exit_nodev:
        RTE_LOG(ERR, PMD, "TAP Unable to initialize %s\n",
                rte_vdev_device_name(vdev));
 
@@ -1526,7 +1547,7 @@ set_interface_name(const char *key __rte_unused,
        char *name = (char *)extra_args;
 
        if (value)
-               snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+               strlcpy(name, value, RTE_ETH_NAME_MAX_LEN - 1);
        else
                snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
                         DEFAULT_TAP_NAME, (tap_unit - 1));
@@ -1534,16 +1555,6 @@ set_interface_name(const char *key __rte_unused,
        return 0;
 }
 
-static int
-set_interface_speed(const char *key __rte_unused,
-                   const char *value,
-                   void *extra_args)
-{
-       *(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
-
-       return 0;
-}
-
 static int
 set_remote_iface(const char *key __rte_unused,
                 const char *value,
@@ -1552,20 +1563,63 @@ set_remote_iface(const char *key __rte_unused,
        char *name = (char *)extra_args;
 
        if (value)
-               snprintf(name, RTE_ETH_NAME_MAX_LEN, "%s", value);
+               strlcpy(name, value, RTE_ETH_NAME_MAX_LEN);
 
        return 0;
 }
 
+static int parse_user_mac(struct ether_addr *user_mac,
+               const char *value)
+{
+       unsigned int index = 0;
+       char mac_temp[strlen(ETH_TAP_USR_MAC_FMT) + 1], *mac_byte = NULL;
+
+       if (user_mac == NULL || value == NULL)
+               return 0;
+
+       strlcpy(mac_temp, value, sizeof(mac_temp));
+       mac_byte = strtok(mac_temp, ":");
+
+       while ((mac_byte != NULL) &&
+                       (strlen(mac_byte) <= 2) &&
+                       (strlen(mac_byte) == strspn(mac_byte,
+                                       ETH_TAP_CMP_MAC_FMT))) {
+               user_mac->addr_bytes[index++] = strtoul(mac_byte, NULL, 16);
+               mac_byte = strtok(NULL, ":");
+       }
+
+       return index;
+}
+
 static int
 set_mac_type(const char *key __rte_unused,
             const char *value,
             void *extra_args)
 {
-       if (value &&
-           !strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED)))
-               *(int *)extra_args = 1;
+       struct ether_addr *user_mac = extra_args;
+
+       if (!value)
+               return 0;
+
+       if (!strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED))) {
+               static int iface_idx;
+
+               /* fixed mac = 00:64:74:61:70:<iface_idx> */
+               memcpy((char *)user_mac->addr_bytes, "\0dtap", ETHER_ADDR_LEN);
+               user_mac->addr_bytes[ETHER_ADDR_LEN - 1] = iface_idx++ + '0';
+               goto success;
+       }
+
+       if (parse_user_mac(user_mac, value) != 6)
+               goto error;
+success:
+       RTE_LOG(DEBUG, PMD, "TAP user MAC param (%s)\n", value);
        return 0;
+
+error:
+       RTE_LOG(ERR, PMD, "TAP user MAC (%s) is not in format (%s|%s)\n",
+               value, ETH_TAP_MAC_FIXED, ETH_TAP_USR_MAC_FMT);
+       return -1;
 }
 
 /* Open a TAP interface device.
@@ -1579,7 +1633,7 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
        int speed;
        char tap_name[RTE_ETH_NAME_MAX_LEN];
        char remote_iface[RTE_ETH_NAME_MAX_LEN];
-       int fixed_mac_type = 0;
+       struct ether_addr user_mac = { .addr_bytes = {0} };
 
        name = rte_vdev_device_name(dev);
        params = rte_vdev_device_args(dev);
@@ -1594,15 +1648,6 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
 
                kvlist = rte_kvargs_parse(params, valid_arguments);
                if (kvlist) {
-                       if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
-                               ret = rte_kvargs_process(kvlist,
-                                                        ETH_TAP_SPEED_ARG,
-                                                        &set_interface_speed,
-                                                        &speed);
-                               if (ret == -1)
-                                       goto leave;
-                       }
-
                        if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
                                ret = rte_kvargs_process(kvlist,
                                                         ETH_TAP_IFACE_ARG,
@@ -1625,7 +1670,7 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
                                ret = rte_kvargs_process(kvlist,
                                                         ETH_TAP_MAC_ARG,
                                                         &set_mac_type,
-                                                        &fixed_mac_type);
+                                                        &user_mac);
                                if (ret == -1)
                                        goto leave;
                        }
@@ -1636,7 +1681,7 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
        RTE_LOG(NOTICE, PMD, "Initializing pmd_tap for %s as %s\n",
                name, tap_name);
 
-       ret = eth_dev_tap_create(dev, tap_name, remote_iface, fixed_mac_type);
+       ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac);
 
 leave:
        if (ret == -1) {
@@ -1700,6 +1745,5 @@ RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
 RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
 RTE_PMD_REGISTER_PARAM_STRING(net_tap,
                              ETH_TAP_IFACE_ARG "=<string> "
-                             ETH_TAP_SPEED_ARG "=<int> "
-                             ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_FIXED " "
+                             ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_ARG_FMT " "
                              ETH_TAP_REMOTE_ARG "=<string>");