replace snprintf with strlcpy without adding extra include
[dpdk.git] / lib / librte_ethdev / rte_ethdev.c
index b2ac590..8b25c2a 100644 (file)
@@ -48,7 +48,6 @@ int rte_eth_dev_logtype;
 
 static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";
 struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS];
-static uint16_t eth_dev_last_created_port;
 
 /* spinlock for eth device callbacks */
 static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER;
@@ -187,7 +186,7 @@ enum {
        STAT_QMAP_RX
 };
 
-int __rte_experimental
+int
 rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 {
        int ret;
@@ -288,7 +287,7 @@ error:
        return ret;
 }
 
-uint16_t __rte_experimental
+uint16_t
 rte_eth_iterator_next(struct rte_dev_iterator *iter)
 {
        if (iter->cls == NULL) /* invalid ethdev iterator */
@@ -317,7 +316,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
        return RTE_MAX_ETHPORTS;
 }
 
-void __rte_experimental
+void
 rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
 {
        if (iter->bus_str == NULL)
@@ -431,8 +430,6 @@ eth_dev_get(uint16_t port_id)
 
        eth_dev->data = &rte_eth_dev_shared_data->data[port_id];
 
-       eth_dev_last_created_port = port_id;
-
        return eth_dev;
 }
 
@@ -441,6 +438,18 @@ rte_eth_dev_allocate(const char *name)
 {
        uint16_t port_id;
        struct rte_eth_dev *eth_dev = NULL;
+       size_t name_len;
+
+       name_len = strnlen(name, RTE_ETH_NAME_MAX_LEN);
+       if (name_len == 0) {
+               RTE_ETHDEV_LOG(ERR, "Zero length Ethernet device name\n");
+               return NULL;
+       }
+
+       if (name_len >= RTE_ETH_NAME_MAX_LEN) {
+               RTE_ETHDEV_LOG(ERR, "Ethernet device name is too long\n");
+               return NULL;
+       }
 
        rte_eth_dev_shared_data_prepare();
 
@@ -462,7 +471,7 @@ rte_eth_dev_allocate(const char *name)
        }
 
        eth_dev = eth_dev_get(port_id);
-       snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name);
+       strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
        eth_dev->data->port_id = port_id;
        eth_dev->data->mtu = ETHER_MTU;
 
@@ -588,7 +597,6 @@ _rte_eth_dev_owner_set(const uint16_t port_id, const uint64_t old_owner_id,
 {
        struct rte_eth_dev *ethdev = &rte_eth_devices[port_id];
        struct rte_eth_dev_owner *port_owner;
-       int sret;
 
        if (port_id >= RTE_MAX_ETHPORTS || !is_allocated(ethdev)) {
                RTE_ETHDEV_LOG(ERR, "Port id %"PRIu16" is not allocated\n",
@@ -612,11 +620,8 @@ _rte_eth_dev_owner_set(const uint16_t port_id, const uint64_t old_owner_id,
                return -EPERM;
        }
 
-       sret = snprintf(port_owner->name, RTE_ETH_MAX_OWNER_NAME_LEN, "%s",
-                       new_owner->name);
-       if (sret < 0 || sret >= RTE_ETH_MAX_OWNER_NAME_LEN)
-               RTE_ETHDEV_LOG(ERR, "Port %u owner name was truncated\n",
-                       port_id);
+       /* can not truncate (same structure) */
+       strlcpy(port_owner->name, new_owner->name, RTE_ETH_MAX_OWNER_NAME_LEN);
 
        port_owner->id = new_owner->id;
 
@@ -1092,8 +1097,9 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 {
        struct rte_eth_dev *dev;
        struct rte_eth_dev_info dev_info;
-       struct rte_eth_conf local_conf = *dev_conf;
+       struct rte_eth_conf orig_conf;
        int diag;
+       int ret;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
@@ -1102,6 +1108,22 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
 
+       if (dev->data->dev_started) {
+               RTE_ETHDEV_LOG(ERR,
+                       "Port %u must be stopped to allow configuration\n",
+                       port_id);
+               return -EBUSY;
+       }
+
+        /* Store original config, as rollback required on failure */
+       memcpy(&orig_conf, &dev->data->dev_conf, sizeof(dev->data->dev_conf));
+
+       /*
+        * Copy the dev_conf parameter into the dev structure.
+        * rte_eth_dev_info_get() requires dev_conf, copy it before dev_info get
+        */
+       memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf));
+
        rte_eth_dev_info_get(port_id, &dev_info);
 
        /* If number of queues specified by application for both Rx and Tx is
@@ -1123,26 +1145,18 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                RTE_ETHDEV_LOG(ERR,
                        "Number of RX queues requested (%u) is greater than max supported(%d)\n",
                        nb_rx_q, RTE_MAX_QUEUES_PER_PORT);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        if (nb_tx_q > RTE_MAX_QUEUES_PER_PORT) {
                RTE_ETHDEV_LOG(ERR,
                        "Number of TX queues requested (%u) is greater than max supported(%d)\n",
                        nb_tx_q, RTE_MAX_QUEUES_PER_PORT);
-               return -EINVAL;
-       }
-
-       if (dev->data->dev_started) {
-               RTE_ETHDEV_LOG(ERR,
-                       "Port %u must be stopped to allow configuration\n",
-                       port_id);
-               return -EBUSY;
+               ret = -EINVAL;
+               goto rollback;
        }
 
-       /* Copy the dev_conf parameter into the dev structure */
-       memcpy(&dev->data->dev_conf, &local_conf, sizeof(dev->data->dev_conf));
-
        /*
         * Check that the numbers of RX and TX queues are not greater
         * than the maximum number of RX and TX queues supported by the
@@ -1151,13 +1165,15 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
        if (nb_rx_q > dev_info.max_rx_queues) {
                RTE_ETHDEV_LOG(ERR, "Ethdev port_id=%u nb_rx_queues=%u > %u\n",
                        port_id, nb_rx_q, dev_info.max_rx_queues);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        if (nb_tx_q > dev_info.max_tx_queues) {
                RTE_ETHDEV_LOG(ERR, "Ethdev port_id=%u nb_tx_queues=%u > %u\n",
                        port_id, nb_tx_q, dev_info.max_tx_queues);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        /* Check that the device supports requested interrupts */
@@ -1165,32 +1181,36 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                        (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC))) {
                RTE_ETHDEV_LOG(ERR, "Driver %s does not support lsc\n",
                        dev->device->driver->name);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
        if ((dev_conf->intr_conf.rmv == 1) &&
                        (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_RMV))) {
                RTE_ETHDEV_LOG(ERR, "Driver %s does not support rmv\n",
                        dev->device->driver->name);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        /*
         * If jumbo frames are enabled, check that the maximum RX packet
         * length is supported by the configured device.
         */
-       if (local_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
+       if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
                if (dev_conf->rxmode.max_rx_pkt_len > dev_info.max_rx_pktlen) {
                        RTE_ETHDEV_LOG(ERR,
                                "Ethdev port_id=%u max_rx_pkt_len %u > max valid value %u\n",
                                port_id, dev_conf->rxmode.max_rx_pkt_len,
                                dev_info.max_rx_pktlen);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto rollback;
                } else if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN) {
                        RTE_ETHDEV_LOG(ERR,
                                "Ethdev port_id=%u max_rx_pkt_len %u < min valid value %u\n",
                                port_id, dev_conf->rxmode.max_rx_pkt_len,
                                (unsigned)ETHER_MIN_LEN);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto rollback;
                }
        } else {
                if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN ||
@@ -1201,25 +1221,27 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
        }
 
        /* Any requested offloading must be within its device capabilities */
-       if ((local_conf.rxmode.offloads & dev_info.rx_offload_capa) !=
-            local_conf.rxmode.offloads) {
+       if ((dev_conf->rxmode.offloads & dev_info.rx_offload_capa) !=
+            dev_conf->rxmode.offloads) {
                RTE_ETHDEV_LOG(ERR,
                        "Ethdev port_id=%u requested Rx offloads 0x%"PRIx64" doesn't match Rx offloads "
                        "capabilities 0x%"PRIx64" in %s()\n",
-                       port_id, local_conf.rxmode.offloads,
+                       port_id, dev_conf->rxmode.offloads,
                        dev_info.rx_offload_capa,
                        __func__);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
-       if ((local_conf.txmode.offloads & dev_info.tx_offload_capa) !=
-            local_conf.txmode.offloads) {
+       if ((dev_conf->txmode.offloads & dev_info.tx_offload_capa) !=
+            dev_conf->txmode.offloads) {
                RTE_ETHDEV_LOG(ERR,
                        "Ethdev port_id=%u requested Tx offloads 0x%"PRIx64" doesn't match Tx offloads "
                        "capabilities 0x%"PRIx64" in %s()\n",
-                       port_id, local_conf.txmode.offloads,
+                       port_id, dev_conf->txmode.offloads,
                        dev_info.tx_offload_capa,
                        __func__);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        /* Check that device supports requested rss hash functions. */
@@ -1230,7 +1252,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                        "Ethdev port_id=%u invalid rss_hf: 0x%"PRIx64", valid value: 0x%"PRIx64"\n",
                        port_id, dev_conf->rx_adv_conf.rss_conf.rss_hf,
                        dev_info.flow_type_rss_offloads);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto rollback;
        }
 
        /*
@@ -1241,7 +1264,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                RTE_ETHDEV_LOG(ERR,
                        "Port%u rte_eth_dev_rx_queue_config = %d\n",
                        port_id, diag);
-               return diag;
+               ret = diag;
+               goto rollback;
        }
 
        diag = rte_eth_dev_tx_queue_config(dev, nb_tx_q);
@@ -1250,7 +1274,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                        "Port%u rte_eth_dev_tx_queue_config = %d\n",
                        port_id, diag);
                rte_eth_dev_rx_queue_config(dev, 0);
-               return diag;
+               ret = diag;
+               goto rollback;
        }
 
        diag = (*dev->dev_ops->dev_configure)(dev);
@@ -1259,7 +1284,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                        port_id, diag);
                rte_eth_dev_rx_queue_config(dev, 0);
                rte_eth_dev_tx_queue_config(dev, 0);
-               return eth_err(port_id, diag);
+               ret = eth_err(port_id, diag);
+               goto rollback;
        }
 
        /* Initialize Rx profiling if enabled at compilation time. */
@@ -1269,10 +1295,16 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                        port_id, diag);
                rte_eth_dev_rx_queue_config(dev, 0);
                rte_eth_dev_tx_queue_config(dev, 0);
-               return eth_err(port_id, diag);
+               ret = eth_err(port_id, diag);
+               goto rollback;
        }
 
        return 0;
+
+rollback:
+       memcpy(&dev->data->dev_conf, &orig_conf, sizeof(dev->data->dev_conf));
+
+       return ret;
 }
 
 void
@@ -1567,7 +1599,7 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
                        nb_rx_desc % dev_info.rx_desc_lim.nb_align != 0) {
 
                RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for nb_rx_desc(=%hu), should be: <= %hu, = %hu, and a product of %hu\n",
+                       "Invalid value for nb_rx_desc(=%hu), should be: <= %hu, >= %hu, and a product of %hu\n",
                        nb_rx_desc, dev_info.rx_desc_lim.nb_max,
                        dev_info.rx_desc_lim.nb_min,
                        dev_info.rx_desc_lim.nb_align);
@@ -1671,7 +1703,7 @@ rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
            nb_tx_desc < dev_info.tx_desc_lim.nb_min ||
            nb_tx_desc % dev_info.tx_desc_lim.nb_align != 0) {
                RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for nb_tx_desc(=%hu), should be: <= %hu, = %hu, and a product of %hu\n",
+                       "Invalid value for nb_tx_desc(=%hu), should be: <= %hu, >= %hu, and a product of %hu\n",
                        nb_tx_desc, dev_info.tx_desc_lim.nb_max,
                        dev_info.tx_desc_lim.nb_min,
                        dev_info.tx_desc_lim.nb_align);
@@ -2036,9 +2068,9 @@ rte_eth_basic_stats_get_names(struct rte_eth_dev *dev,
        uint16_t num_q;
 
        for (idx = 0; idx < RTE_NB_STATS; idx++) {
-               snprintf(xstats_names[cnt_used_entries].name,
-                       sizeof(xstats_names[0].name),
-                       "%s", rte_stats_strings[idx].name);
+               strlcpy(xstats_names[cnt_used_entries].name,
+                       rte_stats_strings[idx].name,
+                       sizeof(xstats_names[0].name));
                cnt_used_entries++;
        }
        num_q = RTE_MIN(dev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
@@ -2500,6 +2532,8 @@ rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info)
        dev_info->rx_desc_lim = lim;
        dev_info->tx_desc_lim = lim;
        dev_info->device = dev->device;
+       dev_info->min_mtu = ETHER_MIN_MTU;
+       dev_info->max_mtu = UINT16_MAX;
 
        RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
        (*dev->dev_ops->dev_infos_get)(dev, dev_info);
@@ -2563,12 +2597,25 @@ int
 rte_eth_dev_set_mtu(uint16_t port_id, uint16_t mtu)
 {
        int ret;
+       struct rte_eth_dev_info dev_info;
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mtu_set, -ENOTSUP);
 
+       /*
+        * Check if the device supports dev_infos_get, if it does not
+        * skip min_mtu/max_mtu validation here as this requires values
+        * that are populated within the call to rte_eth_dev_info_get()
+        * which relies on dev->dev_ops->dev_infos_get.
+        */
+       if (*dev->dev_ops->dev_infos_get != NULL) {
+               rte_eth_dev_info_get(port_id, &dev_info);
+               if (mtu < dev_info.min_mtu || mtu > dev_info.max_mtu)
+                       return -EINVAL;
+       }
+
        ret = (*dev->dev_ops->mtu_set)(dev, mtu);
        if (!ret)
                dev->data->mtu = mtu;
@@ -3561,9 +3608,15 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
 {
        char z_name[RTE_MEMZONE_NAMESIZE];
        const struct rte_memzone *mz;
+       int rc;
 
-       snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
-                dev->data->port_id, queue_id, ring_name);
+       rc = snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
+                     dev->data->port_id, queue_id, ring_name);
+       if (rc >= RTE_MEMZONE_NAMESIZE) {
+               RTE_ETHDEV_LOG(ERR, "ring name too long\n");
+               rte_errno = ENAMETOOLONG;
+               return NULL;
+       }
 
        mz = rte_memzone_lookup(z_name);
        if (mz)
@@ -3647,11 +3700,10 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
                return -ENODEV;
 
        RTE_FUNC_PTR_OR_ERR_RET(*ethdev_uninit, -EINVAL);
-       if (ethdev_uninit) {
-               ret = ethdev_uninit(ethdev);
-               if (ret)
-                       return ret;
-       }
+
+       ret = ethdev_uninit(ethdev);
+       if (ret)
+               return ret;
 
        return rte_eth_dev_release_port(ethdev);
 }
@@ -4311,7 +4363,7 @@ enum rte_eth_switch_domain_state {
  * RTE_MAX_ETHPORTS elements as there cannot be more active switch domains than
  * ethdev ports in a single process.
  */
-struct rte_eth_dev_switch {
+static struct rte_eth_dev_switch {
        enum rte_eth_switch_domain_state state;
 } rte_eth_switch_domains[RTE_MAX_ETHPORTS];