1a9643ea8Slogwang /*- 2a9643ea8Slogwang * BSD LICENSE 3a9643ea8Slogwang * 4a9643ea8Slogwang * Copyright 2015 6WIND S.A. 5a9643ea8Slogwang * Copyright 2015 Mellanox. 6a9643ea8Slogwang * 7a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 8a9643ea8Slogwang * modification, are permitted provided that the following conditions 9a9643ea8Slogwang * are met: 10a9643ea8Slogwang * 11a9643ea8Slogwang * * Redistributions of source code must retain the above copyright 12a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 13a9643ea8Slogwang * * Redistributions in binary form must reproduce the above copyright 14a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in 15a9643ea8Slogwang * the documentation and/or other materials provided with the 16a9643ea8Slogwang * distribution. 17a9643ea8Slogwang * * Neither the name of 6WIND S.A. nor the names of its 18a9643ea8Slogwang * contributors may be used to endorse or promote products derived 19a9643ea8Slogwang * from this software without specific prior written permission. 20a9643ea8Slogwang * 21a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22a9643ea8Slogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23a9643ea8Slogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24a9643ea8Slogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25a9643ea8Slogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26a9643ea8Slogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27a9643ea8Slogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28a9643ea8Slogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29a9643ea8Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31a9643ea8Slogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32a9643ea8Slogwang */ 332bfe3f2eSlogwang #include <unistd.h> 34a9643ea8Slogwang 35a9643ea8Slogwang #include <rte_ether.h> 36a9643ea8Slogwang #include <rte_ethdev.h> 37a9643ea8Slogwang #include <rte_interrupts.h> 38a9643ea8Slogwang #include <rte_alarm.h> 39a9643ea8Slogwang 40a9643ea8Slogwang #include "mlx5.h" 41a9643ea8Slogwang #include "mlx5_rxtx.h" 42a9643ea8Slogwang #include "mlx5_utils.h" 43a9643ea8Slogwang 44*579bf1e2Sjfb8856606 /** 45*579bf1e2Sjfb8856606 * Stop traffic on Tx queues. 46*579bf1e2Sjfb8856606 * 47*579bf1e2Sjfb8856606 * @param dev 48*579bf1e2Sjfb8856606 * Pointer to Ethernet device structure. 49*579bf1e2Sjfb8856606 */ 502bfe3f2eSlogwang static void 51*579bf1e2Sjfb8856606 mlx5_txq_stop(struct rte_eth_dev *dev) 522bfe3f2eSlogwang { 53*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 542bfe3f2eSlogwang unsigned int i; 552bfe3f2eSlogwang 562bfe3f2eSlogwang for (i = 0; i != priv->txqs_n; ++i) 57*579bf1e2Sjfb8856606 mlx5_txq_release(dev, i); 582bfe3f2eSlogwang } 592bfe3f2eSlogwang 60*579bf1e2Sjfb8856606 /** 61*579bf1e2Sjfb8856606 * Start traffic on Tx queues. 62*579bf1e2Sjfb8856606 * 63*579bf1e2Sjfb8856606 * @param dev 64*579bf1e2Sjfb8856606 * Pointer to Ethernet device structure. 65*579bf1e2Sjfb8856606 * 66*579bf1e2Sjfb8856606 * @return 67*579bf1e2Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set. 68*579bf1e2Sjfb8856606 */ 692bfe3f2eSlogwang static int 70*579bf1e2Sjfb8856606 mlx5_txq_start(struct rte_eth_dev *dev) 712bfe3f2eSlogwang { 72*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 732bfe3f2eSlogwang unsigned int i; 74*579bf1e2Sjfb8856606 int ret; 752bfe3f2eSlogwang 762bfe3f2eSlogwang for (i = 0; i != priv->txqs_n; ++i) { 772bfe3f2eSlogwang unsigned int idx = 0; 782bfe3f2eSlogwang struct mlx5_mr *mr; 79*579bf1e2Sjfb8856606 struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); 802bfe3f2eSlogwang 812bfe3f2eSlogwang if (!txq_ctrl) 822bfe3f2eSlogwang continue; 832bfe3f2eSlogwang LIST_FOREACH(mr, &priv->mr, next) { 84*579bf1e2Sjfb8856606 mlx5_txq_mp2mr_reg(&txq_ctrl->txq, mr->mp, idx++); 852bfe3f2eSlogwang if (idx == MLX5_PMD_TX_MP_CACHE) 862bfe3f2eSlogwang break; 872bfe3f2eSlogwang } 882bfe3f2eSlogwang txq_alloc_elts(txq_ctrl); 89*579bf1e2Sjfb8856606 txq_ctrl->ibv = mlx5_txq_ibv_new(dev, i); 902bfe3f2eSlogwang if (!txq_ctrl->ibv) { 91*579bf1e2Sjfb8856606 rte_errno = ENOMEM; 922bfe3f2eSlogwang goto error; 932bfe3f2eSlogwang } 942bfe3f2eSlogwang } 95*579bf1e2Sjfb8856606 ret = mlx5_tx_uar_remap(dev, priv->ctx->cmd_fd); 96*579bf1e2Sjfb8856606 if (ret) { 97*579bf1e2Sjfb8856606 /* Adjust index for rollback. */ 98*579bf1e2Sjfb8856606 i = priv->txqs_n - 1; 99*579bf1e2Sjfb8856606 goto error; 100*579bf1e2Sjfb8856606 } 101*579bf1e2Sjfb8856606 return 0; 1022bfe3f2eSlogwang error: 103*579bf1e2Sjfb8856606 ret = rte_errno; /* Save rte_errno before cleanup. */ 104*579bf1e2Sjfb8856606 do { 105*579bf1e2Sjfb8856606 mlx5_txq_release(dev, i); 106*579bf1e2Sjfb8856606 } while (i-- != 0); 107*579bf1e2Sjfb8856606 rte_errno = ret; /* Restore rte_errno. */ 108*579bf1e2Sjfb8856606 return -rte_errno; 1092bfe3f2eSlogwang } 1102bfe3f2eSlogwang 111*579bf1e2Sjfb8856606 /** 112*579bf1e2Sjfb8856606 * Stop traffic on Rx queues. 113*579bf1e2Sjfb8856606 * 114*579bf1e2Sjfb8856606 * @param dev 115*579bf1e2Sjfb8856606 * Pointer to Ethernet device structure. 116*579bf1e2Sjfb8856606 */ 1172bfe3f2eSlogwang static void 118*579bf1e2Sjfb8856606 mlx5_rxq_stop(struct rte_eth_dev *dev) 1192bfe3f2eSlogwang { 120*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 1212bfe3f2eSlogwang unsigned int i; 1222bfe3f2eSlogwang 1232bfe3f2eSlogwang for (i = 0; i != priv->rxqs_n; ++i) 124*579bf1e2Sjfb8856606 mlx5_rxq_release(dev, i); 1252bfe3f2eSlogwang } 1262bfe3f2eSlogwang 127*579bf1e2Sjfb8856606 /** 128*579bf1e2Sjfb8856606 * Start traffic on Rx queues. 129*579bf1e2Sjfb8856606 * 130*579bf1e2Sjfb8856606 * @param dev 131*579bf1e2Sjfb8856606 * Pointer to Ethernet device structure. 132*579bf1e2Sjfb8856606 * 133*579bf1e2Sjfb8856606 * @return 134*579bf1e2Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set. 135*579bf1e2Sjfb8856606 */ 1362bfe3f2eSlogwang static int 137*579bf1e2Sjfb8856606 mlx5_rxq_start(struct rte_eth_dev *dev) 1382bfe3f2eSlogwang { 139*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 1402bfe3f2eSlogwang unsigned int i; 1412bfe3f2eSlogwang int ret = 0; 1422bfe3f2eSlogwang 1432bfe3f2eSlogwang for (i = 0; i != priv->rxqs_n; ++i) { 144*579bf1e2Sjfb8856606 struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i); 1452bfe3f2eSlogwang 1462bfe3f2eSlogwang if (!rxq_ctrl) 1472bfe3f2eSlogwang continue; 1482bfe3f2eSlogwang ret = rxq_alloc_elts(rxq_ctrl); 1492bfe3f2eSlogwang if (ret) 1502bfe3f2eSlogwang goto error; 151*579bf1e2Sjfb8856606 rxq_ctrl->ibv = mlx5_rxq_ibv_new(dev, i); 152*579bf1e2Sjfb8856606 if (!rxq_ctrl->ibv) 1532bfe3f2eSlogwang goto error; 1542bfe3f2eSlogwang } 155*579bf1e2Sjfb8856606 return 0; 1562bfe3f2eSlogwang error: 157*579bf1e2Sjfb8856606 ret = rte_errno; /* Save rte_errno before cleanup. */ 158*579bf1e2Sjfb8856606 do { 159*579bf1e2Sjfb8856606 mlx5_rxq_release(dev, i); 160*579bf1e2Sjfb8856606 } while (i-- != 0); 161*579bf1e2Sjfb8856606 rte_errno = ret; /* Restore rte_errno. */ 162*579bf1e2Sjfb8856606 return -rte_errno; 1632bfe3f2eSlogwang } 1642bfe3f2eSlogwang 165a9643ea8Slogwang /** 166a9643ea8Slogwang * DPDK callback to start the device. 167a9643ea8Slogwang * 168a9643ea8Slogwang * Simulate device start by attaching all configured flows. 169a9643ea8Slogwang * 170a9643ea8Slogwang * @param dev 171a9643ea8Slogwang * Pointer to Ethernet device structure. 172a9643ea8Slogwang * 173a9643ea8Slogwang * @return 174*579bf1e2Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set. 175a9643ea8Slogwang */ 176a9643ea8Slogwang int 177a9643ea8Slogwang mlx5_dev_start(struct rte_eth_dev *dev) 178a9643ea8Slogwang { 179a9643ea8Slogwang struct priv *priv = dev->data->dev_private; 1802bfe3f2eSlogwang struct mlx5_mr *mr = NULL; 181*579bf1e2Sjfb8856606 int ret; 182a9643ea8Slogwang 183*579bf1e2Sjfb8856606 DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id); 184*579bf1e2Sjfb8856606 ret = mlx5_flow_create_drop_queue(dev); 185*579bf1e2Sjfb8856606 if (ret) { 186*579bf1e2Sjfb8856606 DRV_LOG(ERR, "port %u drop queue allocation failed: %s", 187*579bf1e2Sjfb8856606 dev->data->port_id, strerror(rte_errno)); 1882bfe3f2eSlogwang goto error; 189a9643ea8Slogwang } 1902bfe3f2eSlogwang rte_mempool_walk(mlx5_mp2mr_iter, priv); 191*579bf1e2Sjfb8856606 ret = mlx5_txq_start(dev); 192*579bf1e2Sjfb8856606 if (ret) { 193*579bf1e2Sjfb8856606 DRV_LOG(ERR, "port %u Tx queue allocation failed: %s", 194*579bf1e2Sjfb8856606 dev->data->port_id, strerror(rte_errno)); 195*579bf1e2Sjfb8856606 return -rte_errno; 196a9643ea8Slogwang } 197*579bf1e2Sjfb8856606 ret = mlx5_rxq_start(dev); 198*579bf1e2Sjfb8856606 if (ret) { 199*579bf1e2Sjfb8856606 DRV_LOG(ERR, "port %u Rx queue allocation failed: %s", 200*579bf1e2Sjfb8856606 dev->data->port_id, strerror(rte_errno)); 201*579bf1e2Sjfb8856606 mlx5_txq_stop(dev); 202*579bf1e2Sjfb8856606 return -rte_errno; 2032bfe3f2eSlogwang } 204*579bf1e2Sjfb8856606 dev->data->dev_started = 1; 205*579bf1e2Sjfb8856606 ret = mlx5_rx_intr_vec_enable(dev); 206*579bf1e2Sjfb8856606 if (ret) { 207*579bf1e2Sjfb8856606 DRV_LOG(ERR, "port %u Rx interrupt vector creation failed", 2082bfe3f2eSlogwang dev->data->port_id); 2092bfe3f2eSlogwang goto error; 2102bfe3f2eSlogwang } 211*579bf1e2Sjfb8856606 mlx5_xstats_init(dev); 212*579bf1e2Sjfb8856606 ret = mlx5_traffic_enable(dev); 213*579bf1e2Sjfb8856606 if (ret) { 214*579bf1e2Sjfb8856606 DRV_LOG(DEBUG, "port %u failed to set defaults flows", 215*579bf1e2Sjfb8856606 dev->data->port_id); 216*579bf1e2Sjfb8856606 goto error; 217*579bf1e2Sjfb8856606 } 218*579bf1e2Sjfb8856606 ret = mlx5_flow_start(dev, &priv->flows); 219*579bf1e2Sjfb8856606 if (ret) { 220*579bf1e2Sjfb8856606 DRV_LOG(DEBUG, "port %u failed to set flows", 221*579bf1e2Sjfb8856606 dev->data->port_id); 222*579bf1e2Sjfb8856606 goto error; 223*579bf1e2Sjfb8856606 } 224*579bf1e2Sjfb8856606 dev->tx_pkt_burst = mlx5_select_tx_function(dev); 225*579bf1e2Sjfb8856606 dev->rx_pkt_burst = mlx5_select_rx_function(dev); 226*579bf1e2Sjfb8856606 mlx5_dev_interrupt_handler_install(dev); 2272bfe3f2eSlogwang return 0; 2282bfe3f2eSlogwang error: 229*579bf1e2Sjfb8856606 ret = rte_errno; /* Save rte_errno before cleanup. */ 2302bfe3f2eSlogwang /* Rollback. */ 2312bfe3f2eSlogwang dev->data->dev_started = 0; 2322bfe3f2eSlogwang for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr)) 233*579bf1e2Sjfb8856606 mlx5_mr_release(mr); 234*579bf1e2Sjfb8856606 mlx5_flow_stop(dev, &priv->flows); 235*579bf1e2Sjfb8856606 mlx5_traffic_disable(dev); 236*579bf1e2Sjfb8856606 mlx5_txq_stop(dev); 237*579bf1e2Sjfb8856606 mlx5_rxq_stop(dev); 238*579bf1e2Sjfb8856606 mlx5_flow_delete_drop_queue(dev); 239*579bf1e2Sjfb8856606 rte_errno = ret; /* Restore rte_errno. */ 240*579bf1e2Sjfb8856606 return -rte_errno; 241a9643ea8Slogwang } 242a9643ea8Slogwang 243a9643ea8Slogwang /** 244a9643ea8Slogwang * DPDK callback to stop the device. 245a9643ea8Slogwang * 246a9643ea8Slogwang * Simulate device stop by detaching all configured flows. 247a9643ea8Slogwang * 248a9643ea8Slogwang * @param dev 249a9643ea8Slogwang * Pointer to Ethernet device structure. 250a9643ea8Slogwang */ 251a9643ea8Slogwang void 252a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev) 253a9643ea8Slogwang { 254a9643ea8Slogwang struct priv *priv = dev->data->dev_private; 2552bfe3f2eSlogwang struct mlx5_mr *mr; 256a9643ea8Slogwang 2572bfe3f2eSlogwang dev->data->dev_started = 0; 2582bfe3f2eSlogwang /* Prevent crashes when queues are still in use. */ 2592bfe3f2eSlogwang dev->rx_pkt_burst = removed_rx_burst; 2602bfe3f2eSlogwang dev->tx_pkt_burst = removed_tx_burst; 2612bfe3f2eSlogwang rte_wmb(); 2622bfe3f2eSlogwang usleep(1000 * priv->rxqs_n); 263*579bf1e2Sjfb8856606 DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id); 264*579bf1e2Sjfb8856606 mlx5_flow_stop(dev, &priv->flows); 265*579bf1e2Sjfb8856606 mlx5_traffic_disable(dev); 266*579bf1e2Sjfb8856606 mlx5_rx_intr_vec_disable(dev); 267*579bf1e2Sjfb8856606 mlx5_dev_interrupt_handler_uninstall(dev); 268*579bf1e2Sjfb8856606 mlx5_txq_stop(dev); 269*579bf1e2Sjfb8856606 mlx5_rxq_stop(dev); 2702bfe3f2eSlogwang for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr)) 271*579bf1e2Sjfb8856606 mlx5_mr_release(mr); 272*579bf1e2Sjfb8856606 mlx5_flow_delete_drop_queue(dev); 273a9643ea8Slogwang } 2742bfe3f2eSlogwang 2752bfe3f2eSlogwang /** 2762bfe3f2eSlogwang * Enable traffic flows configured by control plane 2772bfe3f2eSlogwang * 278*579bf1e2Sjfb8856606 * @param dev 2792bfe3f2eSlogwang * Pointer to Ethernet device private data. 2802bfe3f2eSlogwang * @param dev 2812bfe3f2eSlogwang * Pointer to Ethernet device structure. 2822bfe3f2eSlogwang * 2832bfe3f2eSlogwang * @return 284*579bf1e2Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set. 2852bfe3f2eSlogwang */ 2862bfe3f2eSlogwang int 287*579bf1e2Sjfb8856606 mlx5_traffic_enable(struct rte_eth_dev *dev) 2882bfe3f2eSlogwang { 289*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 2902bfe3f2eSlogwang struct rte_flow_item_eth bcast = { 2912bfe3f2eSlogwang .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 2922bfe3f2eSlogwang }; 2932bfe3f2eSlogwang struct rte_flow_item_eth ipv6_multi_spec = { 2942bfe3f2eSlogwang .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00", 2952bfe3f2eSlogwang }; 2962bfe3f2eSlogwang struct rte_flow_item_eth ipv6_multi_mask = { 2972bfe3f2eSlogwang .dst.addr_bytes = "\xff\xff\x00\x00\x00\x00", 2982bfe3f2eSlogwang }; 2992bfe3f2eSlogwang struct rte_flow_item_eth unicast = { 3002bfe3f2eSlogwang .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 3012bfe3f2eSlogwang }; 3022bfe3f2eSlogwang struct rte_flow_item_eth unicast_mask = { 3032bfe3f2eSlogwang .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 3042bfe3f2eSlogwang }; 3052bfe3f2eSlogwang const unsigned int vlan_filter_n = priv->vlan_filter_n; 3062bfe3f2eSlogwang const struct ether_addr cmp = { 3072bfe3f2eSlogwang .addr_bytes = "\x00\x00\x00\x00\x00\x00", 3082bfe3f2eSlogwang }; 3092bfe3f2eSlogwang unsigned int i; 3102bfe3f2eSlogwang unsigned int j; 3112bfe3f2eSlogwang int ret; 3122bfe3f2eSlogwang 3132bfe3f2eSlogwang if (priv->isolated) 3142bfe3f2eSlogwang return 0; 3152bfe3f2eSlogwang if (dev->data->promiscuous) { 3162bfe3f2eSlogwang struct rte_flow_item_eth promisc = { 3172bfe3f2eSlogwang .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00", 3182bfe3f2eSlogwang .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 3192bfe3f2eSlogwang .type = 0, 3202bfe3f2eSlogwang }; 3212bfe3f2eSlogwang 322*579bf1e2Sjfb8856606 ret = mlx5_ctrl_flow(dev, &promisc, &promisc); 323*579bf1e2Sjfb8856606 if (ret) 324*579bf1e2Sjfb8856606 goto error; 3252bfe3f2eSlogwang } 3262bfe3f2eSlogwang if (dev->data->all_multicast) { 3272bfe3f2eSlogwang struct rte_flow_item_eth multicast = { 3282bfe3f2eSlogwang .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", 3292bfe3f2eSlogwang .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 3302bfe3f2eSlogwang .type = 0, 3312bfe3f2eSlogwang }; 3322bfe3f2eSlogwang 333*579bf1e2Sjfb8856606 ret = mlx5_ctrl_flow(dev, &multicast, &multicast); 334*579bf1e2Sjfb8856606 if (ret) 335*579bf1e2Sjfb8856606 goto error; 3362bfe3f2eSlogwang } else { 3372bfe3f2eSlogwang /* Add broadcast/multicast flows. */ 3382bfe3f2eSlogwang for (i = 0; i != vlan_filter_n; ++i) { 3392bfe3f2eSlogwang uint16_t vlan = priv->vlan_filter[i]; 3402bfe3f2eSlogwang 3412bfe3f2eSlogwang struct rte_flow_item_vlan vlan_spec = { 3422bfe3f2eSlogwang .tci = rte_cpu_to_be_16(vlan), 3432bfe3f2eSlogwang }; 344*579bf1e2Sjfb8856606 struct rte_flow_item_vlan vlan_mask = 345*579bf1e2Sjfb8856606 rte_flow_item_vlan_mask; 3462bfe3f2eSlogwang 3472bfe3f2eSlogwang ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast, 3482bfe3f2eSlogwang &vlan_spec, &vlan_mask); 3492bfe3f2eSlogwang if (ret) 3502bfe3f2eSlogwang goto error; 3512bfe3f2eSlogwang ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec, 3522bfe3f2eSlogwang &ipv6_multi_mask, 3532bfe3f2eSlogwang &vlan_spec, &vlan_mask); 3542bfe3f2eSlogwang if (ret) 3552bfe3f2eSlogwang goto error; 3562bfe3f2eSlogwang } 3572bfe3f2eSlogwang if (!vlan_filter_n) { 3582bfe3f2eSlogwang ret = mlx5_ctrl_flow(dev, &bcast, &bcast); 3592bfe3f2eSlogwang if (ret) 3602bfe3f2eSlogwang goto error; 3612bfe3f2eSlogwang ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec, 3622bfe3f2eSlogwang &ipv6_multi_mask); 3632bfe3f2eSlogwang if (ret) 3642bfe3f2eSlogwang goto error; 3652bfe3f2eSlogwang } 3662bfe3f2eSlogwang } 3672bfe3f2eSlogwang /* Add MAC address flows. */ 3682bfe3f2eSlogwang for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) { 3692bfe3f2eSlogwang struct ether_addr *mac = &dev->data->mac_addrs[i]; 3702bfe3f2eSlogwang 3712bfe3f2eSlogwang if (!memcmp(mac, &cmp, sizeof(*mac))) 3722bfe3f2eSlogwang continue; 3732bfe3f2eSlogwang memcpy(&unicast.dst.addr_bytes, 3742bfe3f2eSlogwang mac->addr_bytes, 3752bfe3f2eSlogwang ETHER_ADDR_LEN); 3762bfe3f2eSlogwang for (j = 0; j != vlan_filter_n; ++j) { 3772bfe3f2eSlogwang uint16_t vlan = priv->vlan_filter[j]; 3782bfe3f2eSlogwang 3792bfe3f2eSlogwang struct rte_flow_item_vlan vlan_spec = { 3802bfe3f2eSlogwang .tci = rte_cpu_to_be_16(vlan), 3812bfe3f2eSlogwang }; 382*579bf1e2Sjfb8856606 struct rte_flow_item_vlan vlan_mask = 383*579bf1e2Sjfb8856606 rte_flow_item_vlan_mask; 3842bfe3f2eSlogwang 3852bfe3f2eSlogwang ret = mlx5_ctrl_flow_vlan(dev, &unicast, 3862bfe3f2eSlogwang &unicast_mask, 3872bfe3f2eSlogwang &vlan_spec, 3882bfe3f2eSlogwang &vlan_mask); 3892bfe3f2eSlogwang if (ret) 3902bfe3f2eSlogwang goto error; 3912bfe3f2eSlogwang } 3922bfe3f2eSlogwang if (!vlan_filter_n) { 393*579bf1e2Sjfb8856606 ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask); 3942bfe3f2eSlogwang if (ret) 3952bfe3f2eSlogwang goto error; 3962bfe3f2eSlogwang } 3972bfe3f2eSlogwang } 3982bfe3f2eSlogwang return 0; 3992bfe3f2eSlogwang error: 400*579bf1e2Sjfb8856606 ret = rte_errno; /* Save rte_errno before cleanup. */ 401*579bf1e2Sjfb8856606 mlx5_flow_list_flush(dev, &priv->ctrl_flows); 402*579bf1e2Sjfb8856606 rte_errno = ret; /* Restore rte_errno. */ 403*579bf1e2Sjfb8856606 return -rte_errno; 4042bfe3f2eSlogwang } 4052bfe3f2eSlogwang 4062bfe3f2eSlogwang 4072bfe3f2eSlogwang /** 4082bfe3f2eSlogwang * Disable traffic flows configured by control plane 4092bfe3f2eSlogwang * 4102bfe3f2eSlogwang * @param dev 411*579bf1e2Sjfb8856606 * Pointer to Ethernet device private data. 4122bfe3f2eSlogwang */ 413*579bf1e2Sjfb8856606 void 414*579bf1e2Sjfb8856606 mlx5_traffic_disable(struct rte_eth_dev *dev) 4152bfe3f2eSlogwang { 416*579bf1e2Sjfb8856606 struct priv *priv = dev->data->dev_private; 4172bfe3f2eSlogwang 418*579bf1e2Sjfb8856606 mlx5_flow_list_flush(dev, &priv->ctrl_flows); 4192bfe3f2eSlogwang } 4202bfe3f2eSlogwang 4212bfe3f2eSlogwang /** 4222bfe3f2eSlogwang * Restart traffic flows configured by control plane 4232bfe3f2eSlogwang * 4242bfe3f2eSlogwang * @param dev 425*579bf1e2Sjfb8856606 * Pointer to Ethernet device private data. 4262bfe3f2eSlogwang * 4272bfe3f2eSlogwang * @return 428*579bf1e2Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set. 4292bfe3f2eSlogwang */ 4302bfe3f2eSlogwang int 4312bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev) 4322bfe3f2eSlogwang { 433*579bf1e2Sjfb8856606 if (dev->data->dev_started) { 434*579bf1e2Sjfb8856606 mlx5_traffic_disable(dev); 435*579bf1e2Sjfb8856606 return mlx5_traffic_enable(dev); 436*579bf1e2Sjfb8856606 } 4372bfe3f2eSlogwang return 0; 4382bfe3f2eSlogwang } 439