1*1bdbe1afSAdrien Mazarguil /*- 2*1bdbe1afSAdrien Mazarguil * BSD LICENSE 3*1bdbe1afSAdrien Mazarguil * 4*1bdbe1afSAdrien Mazarguil * Copyright 2015 6WIND S.A. 5*1bdbe1afSAdrien Mazarguil * Copyright 2015 Mellanox. 6*1bdbe1afSAdrien Mazarguil * 7*1bdbe1afSAdrien Mazarguil * Redistribution and use in source and binary forms, with or without 8*1bdbe1afSAdrien Mazarguil * modification, are permitted provided that the following conditions 9*1bdbe1afSAdrien Mazarguil * are met: 10*1bdbe1afSAdrien Mazarguil * 11*1bdbe1afSAdrien Mazarguil * * Redistributions of source code must retain the above copyright 12*1bdbe1afSAdrien Mazarguil * notice, this list of conditions and the following disclaimer. 13*1bdbe1afSAdrien Mazarguil * * Redistributions in binary form must reproduce the above copyright 14*1bdbe1afSAdrien Mazarguil * notice, this list of conditions and the following disclaimer in 15*1bdbe1afSAdrien Mazarguil * the documentation and/or other materials provided with the 16*1bdbe1afSAdrien Mazarguil * distribution. 17*1bdbe1afSAdrien Mazarguil * * Neither the name of 6WIND S.A. nor the names of its 18*1bdbe1afSAdrien Mazarguil * contributors may be used to endorse or promote products derived 19*1bdbe1afSAdrien Mazarguil * from this software without specific prior written permission. 20*1bdbe1afSAdrien Mazarguil * 21*1bdbe1afSAdrien Mazarguil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*1bdbe1afSAdrien Mazarguil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*1bdbe1afSAdrien Mazarguil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*1bdbe1afSAdrien Mazarguil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*1bdbe1afSAdrien Mazarguil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*1bdbe1afSAdrien Mazarguil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*1bdbe1afSAdrien Mazarguil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*1bdbe1afSAdrien Mazarguil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*1bdbe1afSAdrien Mazarguil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*1bdbe1afSAdrien Mazarguil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*1bdbe1afSAdrien Mazarguil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*1bdbe1afSAdrien Mazarguil */ 33*1bdbe1afSAdrien Mazarguil 34*1bdbe1afSAdrien Mazarguil #include <stddef.h> 35*1bdbe1afSAdrien Mazarguil #include <errno.h> 36*1bdbe1afSAdrien Mazarguil #include <string.h> 37*1bdbe1afSAdrien Mazarguil 38*1bdbe1afSAdrien Mazarguil /* Verbs header. */ 39*1bdbe1afSAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 40*1bdbe1afSAdrien Mazarguil #ifdef PEDANTIC 41*1bdbe1afSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic" 42*1bdbe1afSAdrien Mazarguil #endif 43*1bdbe1afSAdrien Mazarguil #include <infiniband/verbs.h> 44*1bdbe1afSAdrien Mazarguil #ifdef PEDANTIC 45*1bdbe1afSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic" 46*1bdbe1afSAdrien Mazarguil #endif 47*1bdbe1afSAdrien Mazarguil 48*1bdbe1afSAdrien Mazarguil /* DPDK headers don't like -pedantic. */ 49*1bdbe1afSAdrien Mazarguil #ifdef PEDANTIC 50*1bdbe1afSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic" 51*1bdbe1afSAdrien Mazarguil #endif 52*1bdbe1afSAdrien Mazarguil #include <rte_ethdev.h> 53*1bdbe1afSAdrien Mazarguil #ifdef PEDANTIC 54*1bdbe1afSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic" 55*1bdbe1afSAdrien Mazarguil #endif 56*1bdbe1afSAdrien Mazarguil 57*1bdbe1afSAdrien Mazarguil #include "mlx5.h" 58*1bdbe1afSAdrien Mazarguil #include "mlx5_rxtx.h" 59*1bdbe1afSAdrien Mazarguil #include "mlx5_utils.h" 60*1bdbe1afSAdrien Mazarguil 61*1bdbe1afSAdrien Mazarguil /** 62*1bdbe1afSAdrien Mazarguil * Enable promiscuous mode in a RX queue. 63*1bdbe1afSAdrien Mazarguil * 64*1bdbe1afSAdrien Mazarguil * @param rxq 65*1bdbe1afSAdrien Mazarguil * Pointer to RX queue structure. 66*1bdbe1afSAdrien Mazarguil * 67*1bdbe1afSAdrien Mazarguil * @return 68*1bdbe1afSAdrien Mazarguil * 0 on success, errno value on failure. 69*1bdbe1afSAdrien Mazarguil */ 70*1bdbe1afSAdrien Mazarguil int 71*1bdbe1afSAdrien Mazarguil rxq_promiscuous_enable(struct rxq *rxq) 72*1bdbe1afSAdrien Mazarguil { 73*1bdbe1afSAdrien Mazarguil struct ibv_flow *flow; 74*1bdbe1afSAdrien Mazarguil struct ibv_flow_attr attr = { 75*1bdbe1afSAdrien Mazarguil .type = IBV_FLOW_ATTR_ALL_DEFAULT, 76*1bdbe1afSAdrien Mazarguil .num_of_specs = 0, 77*1bdbe1afSAdrien Mazarguil .port = rxq->priv->port, 78*1bdbe1afSAdrien Mazarguil .flags = 0 79*1bdbe1afSAdrien Mazarguil }; 80*1bdbe1afSAdrien Mazarguil 81*1bdbe1afSAdrien Mazarguil if (rxq->priv->vf) 82*1bdbe1afSAdrien Mazarguil return 0; 83*1bdbe1afSAdrien Mazarguil if (rxq->promisc_flow != NULL) 84*1bdbe1afSAdrien Mazarguil return 0; 85*1bdbe1afSAdrien Mazarguil DEBUG("%p: enabling promiscuous mode", (void *)rxq); 86*1bdbe1afSAdrien Mazarguil errno = 0; 87*1bdbe1afSAdrien Mazarguil flow = ibv_create_flow(rxq->qp, &attr); 88*1bdbe1afSAdrien Mazarguil if (flow == NULL) { 89*1bdbe1afSAdrien Mazarguil /* It's not clear whether errno is always set in this case. */ 90*1bdbe1afSAdrien Mazarguil ERROR("%p: flow configuration failed, errno=%d: %s", 91*1bdbe1afSAdrien Mazarguil (void *)rxq, errno, 92*1bdbe1afSAdrien Mazarguil (errno ? strerror(errno) : "Unknown error")); 93*1bdbe1afSAdrien Mazarguil if (errno) 94*1bdbe1afSAdrien Mazarguil return errno; 95*1bdbe1afSAdrien Mazarguil return EINVAL; 96*1bdbe1afSAdrien Mazarguil } 97*1bdbe1afSAdrien Mazarguil rxq->promisc_flow = flow; 98*1bdbe1afSAdrien Mazarguil DEBUG("%p: promiscuous mode enabled", (void *)rxq); 99*1bdbe1afSAdrien Mazarguil return 0; 100*1bdbe1afSAdrien Mazarguil } 101*1bdbe1afSAdrien Mazarguil 102*1bdbe1afSAdrien Mazarguil /** 103*1bdbe1afSAdrien Mazarguil * DPDK callback to enable promiscuous mode. 104*1bdbe1afSAdrien Mazarguil * 105*1bdbe1afSAdrien Mazarguil * @param dev 106*1bdbe1afSAdrien Mazarguil * Pointer to Ethernet device structure. 107*1bdbe1afSAdrien Mazarguil */ 108*1bdbe1afSAdrien Mazarguil void 109*1bdbe1afSAdrien Mazarguil mlx5_promiscuous_enable(struct rte_eth_dev *dev) 110*1bdbe1afSAdrien Mazarguil { 111*1bdbe1afSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 112*1bdbe1afSAdrien Mazarguil unsigned int i; 113*1bdbe1afSAdrien Mazarguil int ret; 114*1bdbe1afSAdrien Mazarguil 115*1bdbe1afSAdrien Mazarguil priv_lock(priv); 116*1bdbe1afSAdrien Mazarguil priv->promisc_req = 1; 117*1bdbe1afSAdrien Mazarguil /* If device isn't started, this is all we need to do. */ 118*1bdbe1afSAdrien Mazarguil if (!priv->started) 119*1bdbe1afSAdrien Mazarguil goto end; 120*1bdbe1afSAdrien Mazarguil if (priv->rss) { 121*1bdbe1afSAdrien Mazarguil ret = rxq_promiscuous_enable(&priv->rxq_parent); 122*1bdbe1afSAdrien Mazarguil if (ret) { 123*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 124*1bdbe1afSAdrien Mazarguil return; 125*1bdbe1afSAdrien Mazarguil } 126*1bdbe1afSAdrien Mazarguil goto end; 127*1bdbe1afSAdrien Mazarguil } 128*1bdbe1afSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) { 129*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[i] == NULL) 130*1bdbe1afSAdrien Mazarguil continue; 131*1bdbe1afSAdrien Mazarguil ret = rxq_promiscuous_enable((*priv->rxqs)[i]); 132*1bdbe1afSAdrien Mazarguil if (!ret) 133*1bdbe1afSAdrien Mazarguil continue; 134*1bdbe1afSAdrien Mazarguil /* Failure, rollback. */ 135*1bdbe1afSAdrien Mazarguil while (i != 0) 136*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[--i] != NULL) 137*1bdbe1afSAdrien Mazarguil rxq_promiscuous_disable((*priv->rxqs)[i]); 138*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 139*1bdbe1afSAdrien Mazarguil return; 140*1bdbe1afSAdrien Mazarguil } 141*1bdbe1afSAdrien Mazarguil end: 142*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 143*1bdbe1afSAdrien Mazarguil } 144*1bdbe1afSAdrien Mazarguil 145*1bdbe1afSAdrien Mazarguil /** 146*1bdbe1afSAdrien Mazarguil * Disable promiscuous mode in a RX queue. 147*1bdbe1afSAdrien Mazarguil * 148*1bdbe1afSAdrien Mazarguil * @param rxq 149*1bdbe1afSAdrien Mazarguil * Pointer to RX queue structure. 150*1bdbe1afSAdrien Mazarguil */ 151*1bdbe1afSAdrien Mazarguil void 152*1bdbe1afSAdrien Mazarguil rxq_promiscuous_disable(struct rxq *rxq) 153*1bdbe1afSAdrien Mazarguil { 154*1bdbe1afSAdrien Mazarguil if (rxq->priv->vf) 155*1bdbe1afSAdrien Mazarguil return; 156*1bdbe1afSAdrien Mazarguil if (rxq->promisc_flow == NULL) 157*1bdbe1afSAdrien Mazarguil return; 158*1bdbe1afSAdrien Mazarguil DEBUG("%p: disabling promiscuous mode", (void *)rxq); 159*1bdbe1afSAdrien Mazarguil claim_zero(ibv_destroy_flow(rxq->promisc_flow)); 160*1bdbe1afSAdrien Mazarguil rxq->promisc_flow = NULL; 161*1bdbe1afSAdrien Mazarguil DEBUG("%p: promiscuous mode disabled", (void *)rxq); 162*1bdbe1afSAdrien Mazarguil } 163*1bdbe1afSAdrien Mazarguil 164*1bdbe1afSAdrien Mazarguil /** 165*1bdbe1afSAdrien Mazarguil * DPDK callback to disable promiscuous mode. 166*1bdbe1afSAdrien Mazarguil * 167*1bdbe1afSAdrien Mazarguil * @param dev 168*1bdbe1afSAdrien Mazarguil * Pointer to Ethernet device structure. 169*1bdbe1afSAdrien Mazarguil */ 170*1bdbe1afSAdrien Mazarguil void 171*1bdbe1afSAdrien Mazarguil mlx5_promiscuous_disable(struct rte_eth_dev *dev) 172*1bdbe1afSAdrien Mazarguil { 173*1bdbe1afSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 174*1bdbe1afSAdrien Mazarguil unsigned int i; 175*1bdbe1afSAdrien Mazarguil 176*1bdbe1afSAdrien Mazarguil priv_lock(priv); 177*1bdbe1afSAdrien Mazarguil priv->promisc_req = 0; 178*1bdbe1afSAdrien Mazarguil if (priv->rss) { 179*1bdbe1afSAdrien Mazarguil rxq_promiscuous_disable(&priv->rxq_parent); 180*1bdbe1afSAdrien Mazarguil goto end; 181*1bdbe1afSAdrien Mazarguil } 182*1bdbe1afSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) 183*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[i] != NULL) 184*1bdbe1afSAdrien Mazarguil rxq_promiscuous_disable((*priv->rxqs)[i]); 185*1bdbe1afSAdrien Mazarguil end: 186*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 187*1bdbe1afSAdrien Mazarguil } 188*1bdbe1afSAdrien Mazarguil 189*1bdbe1afSAdrien Mazarguil /** 190*1bdbe1afSAdrien Mazarguil * Enable allmulti mode in a RX queue. 191*1bdbe1afSAdrien Mazarguil * 192*1bdbe1afSAdrien Mazarguil * @param rxq 193*1bdbe1afSAdrien Mazarguil * Pointer to RX queue structure. 194*1bdbe1afSAdrien Mazarguil * 195*1bdbe1afSAdrien Mazarguil * @return 196*1bdbe1afSAdrien Mazarguil * 0 on success, errno value on failure. 197*1bdbe1afSAdrien Mazarguil */ 198*1bdbe1afSAdrien Mazarguil int 199*1bdbe1afSAdrien Mazarguil rxq_allmulticast_enable(struct rxq *rxq) 200*1bdbe1afSAdrien Mazarguil { 201*1bdbe1afSAdrien Mazarguil struct ibv_flow *flow; 202*1bdbe1afSAdrien Mazarguil struct ibv_flow_attr attr = { 203*1bdbe1afSAdrien Mazarguil .type = IBV_FLOW_ATTR_MC_DEFAULT, 204*1bdbe1afSAdrien Mazarguil .num_of_specs = 0, 205*1bdbe1afSAdrien Mazarguil .port = rxq->priv->port, 206*1bdbe1afSAdrien Mazarguil .flags = 0 207*1bdbe1afSAdrien Mazarguil }; 208*1bdbe1afSAdrien Mazarguil 209*1bdbe1afSAdrien Mazarguil if (rxq->allmulti_flow != NULL) 210*1bdbe1afSAdrien Mazarguil return 0; 211*1bdbe1afSAdrien Mazarguil DEBUG("%p: enabling allmulticast mode", (void *)rxq); 212*1bdbe1afSAdrien Mazarguil errno = 0; 213*1bdbe1afSAdrien Mazarguil flow = ibv_create_flow(rxq->qp, &attr); 214*1bdbe1afSAdrien Mazarguil if (flow == NULL) { 215*1bdbe1afSAdrien Mazarguil /* It's not clear whether errno is always set in this case. */ 216*1bdbe1afSAdrien Mazarguil ERROR("%p: flow configuration failed, errno=%d: %s", 217*1bdbe1afSAdrien Mazarguil (void *)rxq, errno, 218*1bdbe1afSAdrien Mazarguil (errno ? strerror(errno) : "Unknown error")); 219*1bdbe1afSAdrien Mazarguil if (errno) 220*1bdbe1afSAdrien Mazarguil return errno; 221*1bdbe1afSAdrien Mazarguil return EINVAL; 222*1bdbe1afSAdrien Mazarguil } 223*1bdbe1afSAdrien Mazarguil rxq->allmulti_flow = flow; 224*1bdbe1afSAdrien Mazarguil DEBUG("%p: allmulticast mode enabled", (void *)rxq); 225*1bdbe1afSAdrien Mazarguil return 0; 226*1bdbe1afSAdrien Mazarguil } 227*1bdbe1afSAdrien Mazarguil 228*1bdbe1afSAdrien Mazarguil /** 229*1bdbe1afSAdrien Mazarguil * DPDK callback to enable allmulti mode. 230*1bdbe1afSAdrien Mazarguil * 231*1bdbe1afSAdrien Mazarguil * @param dev 232*1bdbe1afSAdrien Mazarguil * Pointer to Ethernet device structure. 233*1bdbe1afSAdrien Mazarguil */ 234*1bdbe1afSAdrien Mazarguil void 235*1bdbe1afSAdrien Mazarguil mlx5_allmulticast_enable(struct rte_eth_dev *dev) 236*1bdbe1afSAdrien Mazarguil { 237*1bdbe1afSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 238*1bdbe1afSAdrien Mazarguil unsigned int i; 239*1bdbe1afSAdrien Mazarguil int ret; 240*1bdbe1afSAdrien Mazarguil 241*1bdbe1afSAdrien Mazarguil priv_lock(priv); 242*1bdbe1afSAdrien Mazarguil priv->allmulti_req = 1; 243*1bdbe1afSAdrien Mazarguil /* If device isn't started, this is all we need to do. */ 244*1bdbe1afSAdrien Mazarguil if (!priv->started) 245*1bdbe1afSAdrien Mazarguil goto end; 246*1bdbe1afSAdrien Mazarguil if (priv->rss) { 247*1bdbe1afSAdrien Mazarguil ret = rxq_allmulticast_enable(&priv->rxq_parent); 248*1bdbe1afSAdrien Mazarguil if (ret) { 249*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 250*1bdbe1afSAdrien Mazarguil return; 251*1bdbe1afSAdrien Mazarguil } 252*1bdbe1afSAdrien Mazarguil goto end; 253*1bdbe1afSAdrien Mazarguil } 254*1bdbe1afSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) { 255*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[i] == NULL) 256*1bdbe1afSAdrien Mazarguil continue; 257*1bdbe1afSAdrien Mazarguil ret = rxq_allmulticast_enable((*priv->rxqs)[i]); 258*1bdbe1afSAdrien Mazarguil if (!ret) 259*1bdbe1afSAdrien Mazarguil continue; 260*1bdbe1afSAdrien Mazarguil /* Failure, rollback. */ 261*1bdbe1afSAdrien Mazarguil while (i != 0) 262*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[--i] != NULL) 263*1bdbe1afSAdrien Mazarguil rxq_allmulticast_disable((*priv->rxqs)[i]); 264*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 265*1bdbe1afSAdrien Mazarguil return; 266*1bdbe1afSAdrien Mazarguil } 267*1bdbe1afSAdrien Mazarguil end: 268*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 269*1bdbe1afSAdrien Mazarguil } 270*1bdbe1afSAdrien Mazarguil 271*1bdbe1afSAdrien Mazarguil /** 272*1bdbe1afSAdrien Mazarguil * Disable allmulti mode in a RX queue. 273*1bdbe1afSAdrien Mazarguil * 274*1bdbe1afSAdrien Mazarguil * @param rxq 275*1bdbe1afSAdrien Mazarguil * Pointer to RX queue structure. 276*1bdbe1afSAdrien Mazarguil */ 277*1bdbe1afSAdrien Mazarguil void 278*1bdbe1afSAdrien Mazarguil rxq_allmulticast_disable(struct rxq *rxq) 279*1bdbe1afSAdrien Mazarguil { 280*1bdbe1afSAdrien Mazarguil if (rxq->allmulti_flow == NULL) 281*1bdbe1afSAdrien Mazarguil return; 282*1bdbe1afSAdrien Mazarguil DEBUG("%p: disabling allmulticast mode", (void *)rxq); 283*1bdbe1afSAdrien Mazarguil claim_zero(ibv_destroy_flow(rxq->allmulti_flow)); 284*1bdbe1afSAdrien Mazarguil rxq->allmulti_flow = NULL; 285*1bdbe1afSAdrien Mazarguil DEBUG("%p: allmulticast mode disabled", (void *)rxq); 286*1bdbe1afSAdrien Mazarguil } 287*1bdbe1afSAdrien Mazarguil 288*1bdbe1afSAdrien Mazarguil /** 289*1bdbe1afSAdrien Mazarguil * DPDK callback to disable allmulti mode. 290*1bdbe1afSAdrien Mazarguil * 291*1bdbe1afSAdrien Mazarguil * @param dev 292*1bdbe1afSAdrien Mazarguil * Pointer to Ethernet device structure. 293*1bdbe1afSAdrien Mazarguil */ 294*1bdbe1afSAdrien Mazarguil void 295*1bdbe1afSAdrien Mazarguil mlx5_allmulticast_disable(struct rte_eth_dev *dev) 296*1bdbe1afSAdrien Mazarguil { 297*1bdbe1afSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 298*1bdbe1afSAdrien Mazarguil unsigned int i; 299*1bdbe1afSAdrien Mazarguil 300*1bdbe1afSAdrien Mazarguil priv_lock(priv); 301*1bdbe1afSAdrien Mazarguil priv->allmulti_req = 0; 302*1bdbe1afSAdrien Mazarguil if (priv->rss) { 303*1bdbe1afSAdrien Mazarguil rxq_allmulticast_disable(&priv->rxq_parent); 304*1bdbe1afSAdrien Mazarguil goto end; 305*1bdbe1afSAdrien Mazarguil } 306*1bdbe1afSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) 307*1bdbe1afSAdrien Mazarguil if ((*priv->rxqs)[i] != NULL) 308*1bdbe1afSAdrien Mazarguil rxq_allmulticast_disable((*priv->rxqs)[i]); 309*1bdbe1afSAdrien Mazarguil end: 310*1bdbe1afSAdrien Mazarguil priv_unlock(priv); 311*1bdbe1afSAdrien Mazarguil } 312