add prefix to cache line macros
[dpdk.git] / lib / librte_ether / rte_ethdev.c
index 8dccc6f..95f2ceb 100644 (file)
@@ -114,6 +114,48 @@ static uint8_t nb_ports = 0;
 /* spinlock for eth device callbacks */
 static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER;
 
+/* store statistics names and its offset in stats structure  */
+struct rte_eth_xstats_name_off {
+       char name[RTE_ETH_XSTATS_NAME_SIZE];
+       unsigned offset;
+};
+
+static struct rte_eth_xstats_name_off rte_stats_strings[] = {
+        {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
+        {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
+        {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
+        {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
+        {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+        {"rx_missed_errors", offsetof(struct rte_eth_stats, imissed)},
+        {"rx_crc_errors", offsetof(struct rte_eth_stats, ibadcrc)},
+        {"rx_bad_length_errors", offsetof(struct rte_eth_stats, ibadlen)},
+        {"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
+        {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+        {"fdir_match", offsetof(struct rte_eth_stats, fdirmatch)},
+        {"fdir_miss", offsetof(struct rte_eth_stats, fdirmiss)},
+        {"tx_flow_control_xon", offsetof(struct rte_eth_stats, tx_pause_xon)},
+        {"rx_flow_control_xon", offsetof(struct rte_eth_stats, rx_pause_xon)},
+        {"tx_flow_control_xoff", offsetof(struct rte_eth_stats, tx_pause_xoff)},
+        {"rx_flow_control_xoff", offsetof(struct rte_eth_stats, rx_pause_xoff)},
+};
+#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
+
+static struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
+       {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
+       {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+};
+#define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) /      \
+               sizeof(rte_rxq_stats_strings[0]))
+
+static struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
+       {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
+       {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
+       {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+};
+#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /      \
+               sizeof(rte_txq_stats_strings[0]))
+
+
 /**
  * The user application callback description.
  *
@@ -180,7 +222,7 @@ rte_eth_dev_allocate(const char *name)
                rte_eth_dev_data_alloc();
 
        if (rte_eth_dev_allocated(name) != NULL) {
-               PMD_DEBUG_TRACE("Ethernet Device with name %s already allocated!\n");
+               PMD_DEBUG_TRACE("Ethernet Device with name %s already allocated!\n", name);
                return NULL;
        }
 
@@ -214,7 +256,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv,
        if (rte_eal_process_type() == RTE_PROC_PRIMARY){
                eth_dev->data->dev_private = rte_zmalloc("ethdev private structure",
                                  eth_drv->dev_private_size,
-                                 CACHE_LINE_SIZE);
+                                 RTE_CACHE_LINE_SIZE);
                if (eth_dev->data->dev_private == NULL)
                        rte_panic("Cannot allocate memzone for private port data\n");
        }
@@ -290,7 +332,7 @@ rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
        if (dev->data->rx_queues == NULL) { /* first time configuration */
                dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues",
                                sizeof(dev->data->rx_queues[0]) * nb_queues,
-                               CACHE_LINE_SIZE);
+                               RTE_CACHE_LINE_SIZE);
                if (dev->data->rx_queues == NULL) {
                        dev->data->nb_rx_queues = 0;
                        return -(ENOMEM);
@@ -303,7 +345,7 @@ rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
                for (i = nb_queues; i < old_nb_queues; i++)
                        (*dev->dev_ops->rx_queue_release)(rxq[i]);
                rxq = rte_realloc(rxq, sizeof(rxq[0]) * nb_queues,
-                               CACHE_LINE_SIZE);
+                               RTE_CACHE_LINE_SIZE);
                if (rxq == NULL)
                        return -(ENOMEM);
 
@@ -432,7 +474,7 @@ rte_eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
        if (dev->data->tx_queues == NULL) { /* first time configuration */
                dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues",
                                sizeof(dev->data->tx_queues[0]) * nb_queues,
-                               CACHE_LINE_SIZE);
+                               RTE_CACHE_LINE_SIZE);
                if (dev->data->tx_queues == NULL) {
                        dev->data->nb_tx_queues = 0;
                        return -(ENOMEM);
@@ -445,7 +487,7 @@ rte_eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
                for (i = nb_queues; i < old_nb_queues; i++)
                        (*dev->dev_ops->tx_queue_release)(txq[i]);
                txq = rte_realloc(txq, sizeof(txq[0]) * nb_queues,
-                               CACHE_LINE_SIZE);
+                               RTE_CACHE_LINE_SIZE);
                if (txq == NULL)
                        return -(ENOMEM);
 
@@ -771,7 +813,8 @@ rte_eth_dev_config_restore(uint8_t port_id)
                        continue;
 
                /* add address to the hardware */
-               if  (*dev->dev_ops->mac_addr_add)
+               if  (*dev->dev_ops->mac_addr_add &&
+                       dev->data->mac_pool_sel[i] & (1ULL << pool))
                        (*dev->dev_ops->mac_addr_add)(dev, &addr, i, pool);
                else {
                        PMD_DEBUG_TRACE("port %d: MAC address array not supported\n",
@@ -957,7 +1000,7 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
         * This value must be provided in the private data of the memory pool.
         * First check that the memory pool has a valid private data.
         */
-       (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
+       rte_eth_dev_info_get(port_id, &dev_info);
        if (mp->private_data_size < sizeof(struct rte_pktmbuf_pool_private)) {
                PMD_DEBUG_TRACE("%s private_data_size %d < %d\n",
                                mp->name, (int) mp->private_data_size,
@@ -980,6 +1023,9 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
                return (-EINVAL);
        }
 
+       if (rx_conf == NULL)
+               rx_conf = &dev_info.default_rxconf;
+
        ret = (*dev->dev_ops->rx_queue_setup)(dev, rx_queue_id, nb_rx_desc,
                                              socket_id, rx_conf, mp);
        if (!ret) {
@@ -997,6 +1043,7 @@ rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
                       const struct rte_eth_txconf *tx_conf)
 {
        struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
 
        /* This function is only safe when called from the primary process
         * in a multi-process setup*/
@@ -1018,7 +1065,14 @@ rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
                return -EBUSY;
        }
 
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_setup, -ENOTSUP);
+
+       rte_eth_dev_info_get(port_id, &dev_info);
+
+       if (tx_conf == NULL)
+               tx_conf = &dev_info.default_txconf;
+
        return (*dev->dev_ops->tx_queue_setup)(dev, tx_queue_id, nb_tx_desc,
                                               socket_id, tx_conf);
 }
@@ -1201,6 +1255,101 @@ rte_eth_stats_reset(uint8_t port_id)
        (*dev->dev_ops->stats_reset)(dev);
 }
 
+/* retrieve ethdev extended statistics */
+int
+rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+       unsigned n)
+{
+       struct rte_eth_stats eth_stats;
+       struct rte_eth_dev *dev;
+       unsigned count, i, q;
+       uint64_t val;
+       char *stats_ptr;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -1;
+       }
+       dev = &rte_eth_devices[port_id];
+
+       /* implemented by the driver */
+       if (dev->dev_ops->xstats_get != NULL)
+               return (*dev->dev_ops->xstats_get)(dev, xstats, n);
+
+       /* else, return generic statistics */
+       count = RTE_NB_STATS;
+       count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+       count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+       if (n < count)
+               return count;
+
+       /* now fill the xstats structure */
+
+       count = 0;
+       memset(&eth_stats, 0, sizeof(eth_stats));
+       rte_eth_stats_get(port_id, &eth_stats);
+
+       /* global stats */
+       for (i = 0; i < RTE_NB_STATS; i++) {
+               stats_ptr = (char *)&eth_stats + rte_stats_strings[i].offset;
+               val = *(uint64_t *)stats_ptr;
+               snprintf(xstats[count].name, sizeof(xstats[count].name),
+                       "%s", rte_stats_strings[i].name);
+               xstats[count++].value = val;
+       }
+
+       /* per-rxq stats */
+       for (q = 0; q < dev->data->nb_rx_queues; q++) {
+               for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
+                       stats_ptr = (char *)&eth_stats;
+                       stats_ptr += rte_rxq_stats_strings[i].offset;
+                       stats_ptr += q * sizeof(uint64_t);
+                       val = *(uint64_t *)stats_ptr;
+                       snprintf(xstats[count].name, sizeof(xstats[count].name),
+                               "rx_queue_%u_%s", q,
+                               rte_rxq_stats_strings[i].name);
+                       xstats[count++].value = val;
+               }
+       }
+
+       /* per-txq stats */
+       for (q = 0; q < dev->data->nb_tx_queues; q++) {
+               for (i = 0; i < RTE_NB_TXQ_STATS; i++) {
+                       stats_ptr = (char *)&eth_stats;
+                       stats_ptr += rte_txq_stats_strings[i].offset;
+                       stats_ptr += q * sizeof(uint64_t);
+                       val = *(uint64_t *)stats_ptr;
+                       snprintf(xstats[count].name, sizeof(xstats[count].name),
+                               "tx_queue_%u_%s", q,
+                               rte_txq_stats_strings[i].name);
+                       xstats[count++].value = val;
+               }
+       }
+
+       return count;
+}
+
+/* reset ethdev extended statistics */
+void
+rte_eth_xstats_reset(uint8_t port_id)
+{
+       struct rte_eth_dev *dev;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return;
+       }
+       dev = &rte_eth_devices[port_id];
+
+       /* implemented by the driver */
+       if (dev->dev_ops->xstats_reset != NULL) {
+               (*dev->dev_ops->xstats_reset)(dev);
+               return;
+       }
+
+       /* fallback to default */
+       rte_eth_stats_reset(port_id);
+}
 
 static int
 set_queue_stats_mapping(uint8_t port_id, uint16_t queue_id, uint8_t stat_idx,
@@ -1249,10 +1398,8 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
        }
        dev = &rte_eth_devices[port_id];
 
-       /* Default device offload capabilities to zero */
-       dev_info->rx_offload_capa = 0;
-       dev_info->tx_offload_capa = 0;
-       dev_info->if_index = 0;
+       memset(dev_info, 0, sizeof(struct rte_eth_dev_info));
+
        FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
        (*dev->dev_ops->dev_infos_get)(dev, dev_info);
        dev_info->pci_dev = dev->pci_dev;
@@ -1780,78 +1927,111 @@ rte_eth_dev_priority_flow_ctrl_set(uint8_t port_id, struct rte_eth_pfc_conf *pfc
        return (-ENOTSUP);
 }
 
-int
-rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+static inline int
+rte_eth_check_reta_mask(struct rte_eth_rss_reta_entry64 *reta_conf,
+                       uint16_t reta_size)
 {
-       struct rte_eth_dev *dev;
-       uint16_t max_rxq;
-       uint8_t i,j;
+       uint16_t i, num;
 
-       if (port_id >= nb_ports) {
-               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
-               return (-ENODEV);
+       if (!reta_conf)
+               return -EINVAL;
+
+       if (reta_size != RTE_ALIGN(reta_size, RTE_RETA_GROUP_SIZE)) {
+               PMD_DEBUG_TRACE("Invalid reta size, should be %u aligned\n",
+                                                       RTE_RETA_GROUP_SIZE);
+               return -EINVAL;
        }
 
-       /* Invalid mask bit(s) setting */
-       if ((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
-               PMD_DEBUG_TRACE("Invalid update mask bits for port=%d\n",port_id);
-               return (-EINVAL);
+       num = reta_size / RTE_RETA_GROUP_SIZE;
+       for (i = 0; i < num; i++) {
+               if (reta_conf[i].mask)
+                       return 0;
        }
 
-       dev = &rte_eth_devices[port_id];
-       max_rxq = (dev->data->nb_rx_queues <= ETH_RSS_RETA_MAX_QUEUE) ?
-               dev->data->nb_rx_queues : ETH_RSS_RETA_MAX_QUEUE;
-       if (reta_conf->mask_lo != 0) {
-               for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-                       if ((reta_conf->mask_lo & (1ULL << i)) &&
-                               (reta_conf->reta[i] >= max_rxq)) {
-                               PMD_DEBUG_TRACE("RETA hash index output"
-                                       "configration for port=%d,invalid"
-                                       "queue=%d\n",port_id,reta_conf->reta[i]);
+       return -EINVAL;
+}
 
-                               return (-EINVAL);
-                       }
+static inline int
+rte_eth_check_reta_entry(struct rte_eth_rss_reta_entry64 *reta_conf,
+                        uint16_t reta_size,
+                        uint8_t max_rxq)
+{
+       uint16_t i, idx, shift;
+
+       if (!reta_conf)
+               return -EINVAL;
+
+       if (max_rxq == 0) {
+               PMD_DEBUG_TRACE("No receive queue is available\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < reta_size; i++) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               if ((reta_conf[idx].mask & (1ULL << shift)) &&
+                       (reta_conf[idx].reta[shift] >= max_rxq)) {
+                       PMD_DEBUG_TRACE("reta_conf[%u]->reta[%u]: %u exceeds "
+                               "the maximum rxq index: %u\n", idx, shift,
+                               reta_conf[idx].reta[shift], max_rxq);
+                       return -EINVAL;
                }
        }
 
-       if (reta_conf->mask_hi != 0) {
-               for (i = 0; i< ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-                       j = (uint8_t)(i + ETH_RSS_RETA_NUM_ENTRIES/2);
+       return 0;
+}
 
-                       /* Check if the max entry >= 128 */
-                       if ((reta_conf->mask_hi & (1ULL << i)) &&
-                               (reta_conf->reta[j] >= max_rxq)) {
-                               PMD_DEBUG_TRACE("RETA hash index output"
-                                       "configration for port=%d,invalid"
-                                       "queue=%d\n",port_id,reta_conf->reta[j]);
+int
+rte_eth_dev_rss_reta_update(uint8_t port_id,
+                           struct rte_eth_rss_reta_entry64 *reta_conf,
+                           uint16_t reta_size)
+{
+       struct rte_eth_dev *dev;
+       int ret;
 
-                               return (-EINVAL);
-                       }
-               }
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
        }
 
+       /* Check mask bits */
+       ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+       if (ret < 0)
+               return ret;
+
+       dev = &rte_eth_devices[port_id];
+
+       /* Check entry value */
+       ret = rte_eth_check_reta_entry(reta_conf, reta_size,
+                               dev->data->nb_rx_queues);
+       if (ret < 0)
+               return ret;
+
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_update, -ENOTSUP);
-       return (*dev->dev_ops->reta_update)(dev, reta_conf);
+       return (*dev->dev_ops->reta_update)(dev, reta_conf, reta_size);
 }
 
 int
-rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+rte_eth_dev_rss_reta_query(uint8_t port_id,
+                          struct rte_eth_rss_reta_entry64 *reta_conf,
+                          uint16_t reta_size)
 {
        struct rte_eth_dev *dev;
+       int ret;
 
        if (port_id >= nb_ports) {
                PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
-               return (-ENODEV);
+               return -ENODEV;
        }
 
-       if((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
-               PMD_DEBUG_TRACE("Invalid update mask bits for the port=%d\n",port_id);
-               return (-EINVAL);
-       }
+       /* Check mask bits */
+       ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+       if (ret < 0)
+               return ret;
 
        dev = &rte_eth_devices[port_id];
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_query, -ENOTSUP);
-       return (*dev->dev_ops->reta_query)(dev, reta_conf);
+       return (*dev->dev_ops->reta_query)(dev, reta_conf, reta_size);
 }
 
 int
@@ -1891,6 +2071,58 @@ rte_eth_dev_rss_hash_conf_get(uint8_t port_id,
        return (*dev->dev_ops->rss_hash_conf_get)(dev, rss_conf);
 }
 
+int
+rte_eth_dev_udp_tunnel_add(uint8_t port_id,
+                          struct rte_eth_udp_tunnel *udp_tunnel)
+{
+       struct rte_eth_dev *dev;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
+       }
+
+       if (udp_tunnel == NULL) {
+               PMD_DEBUG_TRACE("Invalid udp_tunnel parameter\n");
+               return -EINVAL;
+       }
+
+       if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) {
+               PMD_DEBUG_TRACE("Invalid tunnel type\n");
+               return -EINVAL;
+       }
+
+       dev = &rte_eth_devices[port_id];
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_add, -ENOTSUP);
+       return (*dev->dev_ops->udp_tunnel_add)(dev, udp_tunnel);
+}
+
+int
+rte_eth_dev_udp_tunnel_delete(uint8_t port_id,
+                             struct rte_eth_udp_tunnel *udp_tunnel)
+{
+       struct rte_eth_dev *dev;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
+       }
+       dev = &rte_eth_devices[port_id];
+
+       if (udp_tunnel == NULL) {
+               PMD_DEBUG_TRACE("Invalid udp_tunnel parametr\n");
+               return -EINVAL;
+       }
+
+       if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) {
+               PMD_DEBUG_TRACE("Invalid tunnel type\n");
+               return -EINVAL;
+       }
+
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_del, -ENOTSUP);
+       return (*dev->dev_ops->udp_tunnel_del)(dev, udp_tunnel);
+}
+
 int
 rte_eth_led_on(uint8_t port_id)
 {
@@ -2022,6 +2254,9 @@ rte_eth_dev_mac_addr_remove(uint8_t port_id, struct ether_addr *addr)
        /* Update address in NIC data structure */
        ether_addr_copy(&null_mac_addr, &dev->data->mac_addrs[index]);
 
+       /* reset pool bitmap */
+       dev->data->mac_pool_sel[index] = 0;
+
        return 0;
 }
 
@@ -2384,7 +2619,7 @@ rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id,
                return 0;
        }
        dev = &rte_eth_devices[port_id];
-       FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, -ENOTSUP);
+       FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, 0);
        if (queue_id >= dev->data->nb_rx_queues) {
                PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id);
                return 0;
@@ -2405,7 +2640,7 @@ rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id,
        }
        dev = &rte_eth_devices[port_id];
 
-       FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, -ENOTSUP);
+       FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, 0);
        if (queue_id >= dev->data->nb_tx_queues) {
                PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
                return 0;
@@ -2424,7 +2659,7 @@ rte_eth_rx_queue_count(uint8_t port_id, uint16_t queue_id)
                return 0;
        }
        dev = &rte_eth_devices[port_id];
-       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_count, -ENOTSUP);
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_count, 0);
        return (*dev->dev_ops->rx_queue_count)(dev, queue_id);
 }
 
@@ -3002,3 +3237,35 @@ rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
        return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
                                                rx_queue);
 }
+
+int
+rte_eth_dev_filter_supported(uint8_t port_id, enum rte_filter_type filter_type)
+{
+       struct rte_eth_dev *dev;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
+       }
+
+       dev = &rte_eth_devices[port_id];
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP);
+       return (*dev->dev_ops->filter_ctrl)(dev, filter_type,
+                               RTE_ETH_FILTER_NOP, NULL);
+}
+
+int
+rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type,
+                      enum rte_filter_op filter_op, void *arg)
+{
+       struct rte_eth_dev *dev;
+
+       if (port_id >= nb_ports) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
+       }
+
+       dev = &rte_eth_devices[port_id];
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP);
+       return (*dev->dev_ops->filter_ctrl)(dev, filter_type, filter_op, arg);
+}