1 /*- 2 * BSD LICENSE 3 * 4 * Copyright 2017 6WIND S.A. 5 * Copyright 2017 Mellanox. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of 6WIND S.A. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <unistd.h> 35 36 #include <rte_flow.h> 37 #include <rte_flow_driver.h> 38 39 #include "failsafe_private.h" 40 41 /** Print a message out of a flow error. */ 42 static int 43 fs_flow_complain(struct rte_flow_error *error) 44 { 45 static const char *const errstrlist[] = { 46 [RTE_FLOW_ERROR_TYPE_NONE] = "no error", 47 [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", 48 [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", 49 [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", 50 [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", 51 [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", 52 [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", 53 [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", 54 [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", 55 [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", 56 [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", 57 [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", 58 }; 59 const char *errstr; 60 char buf[32]; 61 int err = rte_errno; 62 63 if ((unsigned int)error->type >= RTE_DIM(errstrlist) || 64 !errstrlist[error->type]) 65 errstr = "unknown type"; 66 else 67 errstr = errstrlist[error->type]; 68 ERROR("Caught error type %d (%s): %s%s\n", 69 error->type, errstr, 70 error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", 71 error->cause), buf) : "", 72 error->message ? error->message : "(no stated reason)"); 73 return -err; 74 } 75 76 static int 77 eth_dev_flow_isolate_set(struct rte_eth_dev *dev, 78 struct sub_device *sdev) 79 { 80 struct rte_flow_error ferror; 81 int ret; 82 83 if (!PRIV(dev)->flow_isolated) { 84 DEBUG("Flow isolation already disabled"); 85 } else { 86 DEBUG("Enabling flow isolation"); 87 ret = rte_flow_isolate(PORT_ID(sdev), 88 PRIV(dev)->flow_isolated, 89 &ferror); 90 if (ret) { 91 fs_flow_complain(&ferror); 92 return ret; 93 } 94 } 95 return 0; 96 } 97 98 static int 99 fs_eth_dev_conf_apply(struct rte_eth_dev *dev, 100 struct sub_device *sdev) 101 { 102 struct rte_eth_dev *edev; 103 struct rte_vlan_filter_conf *vfc1; 104 struct rte_vlan_filter_conf *vfc2; 105 struct rte_flow *flow; 106 struct rte_flow_error ferror; 107 uint32_t i; 108 int ret; 109 110 edev = ETH(sdev); 111 /* RX queue setup */ 112 for (i = 0; i < dev->data->nb_rx_queues; i++) { 113 struct rxq *rxq; 114 115 rxq = dev->data->rx_queues[i]; 116 ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i, 117 rxq->info.nb_desc, rxq->socket_id, 118 &rxq->info.conf, rxq->info.mp); 119 if (ret) { 120 ERROR("rx_queue_setup failed"); 121 return ret; 122 } 123 } 124 /* TX queue setup */ 125 for (i = 0; i < dev->data->nb_tx_queues; i++) { 126 struct txq *txq; 127 128 txq = dev->data->tx_queues[i]; 129 ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i, 130 txq->info.nb_desc, txq->socket_id, 131 &txq->info.conf); 132 if (ret) { 133 ERROR("tx_queue_setup failed"); 134 return ret; 135 } 136 } 137 /* dev_link.link_status */ 138 if (dev->data->dev_link.link_status != 139 edev->data->dev_link.link_status) { 140 DEBUG("Configuring link_status"); 141 if (dev->data->dev_link.link_status) 142 ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); 143 else 144 ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); 145 if (ret) { 146 ERROR("Failed to apply link_status"); 147 return ret; 148 } 149 } else { 150 DEBUG("link_status already set"); 151 } 152 /* promiscuous */ 153 if (dev->data->promiscuous != edev->data->promiscuous) { 154 DEBUG("Configuring promiscuous"); 155 if (dev->data->promiscuous) 156 rte_eth_promiscuous_enable(PORT_ID(sdev)); 157 else 158 rte_eth_promiscuous_disable(PORT_ID(sdev)); 159 } else { 160 DEBUG("promiscuous already set"); 161 } 162 /* all_multicast */ 163 if (dev->data->all_multicast != edev->data->all_multicast) { 164 DEBUG("Configuring all_multicast"); 165 if (dev->data->all_multicast) 166 rte_eth_allmulticast_enable(PORT_ID(sdev)); 167 else 168 rte_eth_allmulticast_disable(PORT_ID(sdev)); 169 } else { 170 DEBUG("all_multicast already set"); 171 } 172 /* MTU */ 173 if (dev->data->mtu != edev->data->mtu) { 174 DEBUG("Configuring MTU"); 175 ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu); 176 if (ret) { 177 ERROR("Failed to apply MTU"); 178 return ret; 179 } 180 } else { 181 DEBUG("MTU already set"); 182 } 183 /* default MAC */ 184 DEBUG("Configuring default MAC address"); 185 ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 186 &dev->data->mac_addrs[0]); 187 if (ret) { 188 ERROR("Setting default MAC address failed"); 189 return ret; 190 } 191 /* additional MAC */ 192 if (PRIV(dev)->nb_mac_addr > 1) 193 DEBUG("Configure additional MAC address%s", 194 (PRIV(dev)->nb_mac_addr > 2 ? "es" : "")); 195 for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) { 196 struct ether_addr *ea; 197 198 ea = &dev->data->mac_addrs[i]; 199 ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea, 200 PRIV(dev)->mac_addr_pool[i]); 201 if (ret) { 202 char ea_fmt[ETHER_ADDR_FMT_SIZE]; 203 204 ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea); 205 ERROR("Adding MAC address %s failed", ea_fmt); 206 return ret; 207 } 208 } 209 /* VLAN filter */ 210 vfc1 = &dev->data->vlan_filter_conf; 211 vfc2 = &edev->data->vlan_filter_conf; 212 if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { 213 uint64_t vbit; 214 uint64_t ids; 215 size_t i; 216 uint16_t vlan_id; 217 218 DEBUG("Configuring VLAN filter"); 219 for (i = 0; i < RTE_DIM(vfc1->ids); i++) { 220 if (vfc1->ids[i] == 0) 221 continue; 222 ids = vfc1->ids[i]; 223 while (ids) { 224 vlan_id = 64 * i; 225 /* count trailing zeroes */ 226 vbit = ~ids & (ids - 1); 227 /* clear least significant bit set */ 228 ids ^= (ids ^ (ids - 1)) ^ vbit; 229 for (; vbit; vlan_id++) 230 vbit >>= 1; 231 ret = rte_eth_dev_vlan_filter( 232 PORT_ID(sdev), vlan_id, 1); 233 if (ret) { 234 ERROR("Failed to apply VLAN filter %hu", 235 vlan_id); 236 return ret; 237 } 238 } 239 } 240 } else { 241 DEBUG("VLAN filter already set"); 242 } 243 /* rte_flow */ 244 if (TAILQ_EMPTY(&PRIV(dev)->flow_list)) { 245 DEBUG("rte_flow already set"); 246 } else { 247 DEBUG("Resetting rte_flow configuration"); 248 ret = rte_flow_flush(PORT_ID(sdev), &ferror); 249 if (ret) { 250 fs_flow_complain(&ferror); 251 return ret; 252 } 253 i = 0; 254 rte_errno = 0; 255 DEBUG("Configuring rte_flow"); 256 TAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) { 257 DEBUG("Creating flow #%" PRIu32, i++); 258 flow->flows[SUB_ID(sdev)] = 259 rte_flow_create(PORT_ID(sdev), 260 &flow->fd->attr, 261 flow->fd->items, 262 flow->fd->actions, 263 &ferror); 264 ret = rte_errno; 265 if (ret) 266 break; 267 } 268 if (ret) { 269 fs_flow_complain(&ferror); 270 return ret; 271 } 272 } 273 return 0; 274 } 275 276 static void 277 fs_dev_remove(struct sub_device *sdev) 278 { 279 int ret; 280 281 if (sdev == NULL) 282 return; 283 switch (sdev->state) { 284 case DEV_STARTED: 285 rte_eth_dev_stop(PORT_ID(sdev)); 286 sdev->state = DEV_ACTIVE; 287 /* fallthrough */ 288 case DEV_ACTIVE: 289 rte_eth_dev_close(PORT_ID(sdev)); 290 sdev->state = DEV_PROBED; 291 /* fallthrough */ 292 case DEV_PROBED: 293 ret = rte_eal_hotplug_remove(sdev->bus->name, 294 sdev->dev->name); 295 if (ret) { 296 ERROR("Bus detach failed for sub_device %u", 297 SUB_ID(sdev)); 298 } else { 299 ETH(sdev)->state = RTE_ETH_DEV_UNUSED; 300 } 301 sdev->state = DEV_PARSED; 302 /* fallthrough */ 303 case DEV_PARSED: 304 case DEV_UNDEFINED: 305 sdev->state = DEV_UNDEFINED; 306 /* the end */ 307 break; 308 } 309 failsafe_hotplug_alarm_install(sdev->fs_dev); 310 } 311 312 static void 313 fs_dev_stats_save(struct sub_device *sdev) 314 { 315 failsafe_stats_increment(&PRIV(sdev->fs_dev)->stats_accumulator, 316 &sdev->stats_snapshot); 317 memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats)); 318 } 319 320 static inline int 321 fs_rxtx_clean(struct sub_device *sdev) 322 { 323 uint16_t i; 324 325 for (i = 0; i < ETH(sdev)->data->nb_rx_queues; i++) 326 if (FS_ATOMIC_RX(sdev, i)) 327 return 0; 328 for (i = 0; i < ETH(sdev)->data->nb_tx_queues; i++) 329 if (FS_ATOMIC_TX(sdev, i)) 330 return 0; 331 return 1; 332 } 333 334 void 335 failsafe_dev_remove(struct rte_eth_dev *dev) 336 { 337 struct sub_device *sdev; 338 uint8_t i; 339 340 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) 341 if (sdev->remove && fs_rxtx_clean(sdev)) { 342 fs_dev_stats_save(sdev); 343 fs_dev_remove(sdev); 344 } 345 } 346 347 int 348 failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) 349 { 350 struct sub_device *sdev; 351 uint32_t inactive; 352 int ret; 353 uint8_t i; 354 355 if (PRIV(dev)->state < DEV_PARSED) 356 return 0; 357 358 ret = failsafe_args_parse_subs(dev); 359 if (ret) 360 goto err_remove; 361 362 if (PRIV(dev)->state < DEV_PROBED) 363 return 0; 364 ret = failsafe_eal_init(dev); 365 if (ret) 366 goto err_remove; 367 if (PRIV(dev)->state < DEV_ACTIVE) 368 return 0; 369 inactive = 0; 370 FOREACH_SUBDEV(sdev, i, dev) { 371 if (sdev->state == DEV_PROBED) { 372 inactive |= UINT32_C(1) << i; 373 ret = eth_dev_flow_isolate_set(dev, sdev); 374 if (ret) { 375 ERROR("Could not apply configuration to sub_device %d", 376 i); 377 goto err_remove; 378 } 379 } 380 } 381 ret = dev->dev_ops->dev_configure(dev); 382 if (ret) 383 goto err_remove; 384 FOREACH_SUBDEV(sdev, i, dev) { 385 if (inactive & (UINT32_C(1) << i)) { 386 ret = fs_eth_dev_conf_apply(dev, sdev); 387 if (ret) { 388 ERROR("Could not apply configuration to sub_device %d", 389 i); 390 goto err_remove; 391 } 392 } 393 } 394 /* 395 * If new devices have been configured, check if 396 * the link state has changed. 397 */ 398 if (inactive) 399 dev->dev_ops->link_update(dev, 1); 400 if (PRIV(dev)->state < DEV_STARTED) 401 return 0; 402 ret = dev->dev_ops->dev_start(dev); 403 if (ret) 404 goto err_remove; 405 return 0; 406 err_remove: 407 FOREACH_SUBDEV(sdev, i, dev) 408 if (sdev->state != PRIV(dev)->state) 409 sdev->remove = 1; 410 return ret; 411 } 412 413 void 414 failsafe_stats_increment(struct rte_eth_stats *to, struct rte_eth_stats *from) 415 { 416 uint32_t i; 417 418 RTE_ASSERT(to != NULL && from != NULL); 419 to->ipackets += from->ipackets; 420 to->opackets += from->opackets; 421 to->ibytes += from->ibytes; 422 to->obytes += from->obytes; 423 to->imissed += from->imissed; 424 to->ierrors += from->ierrors; 425 to->oerrors += from->oerrors; 426 to->rx_nombuf += from->rx_nombuf; 427 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 428 to->q_ipackets[i] += from->q_ipackets[i]; 429 to->q_opackets[i] += from->q_opackets[i]; 430 to->q_ibytes[i] += from->q_ibytes[i]; 431 to->q_obytes[i] += from->q_obytes[i]; 432 to->q_errors[i] += from->q_errors[i]; 433 } 434 } 435 436 int 437 failsafe_eth_rmv_event_callback(uint16_t port_id __rte_unused, 438 enum rte_eth_event_type event __rte_unused, 439 void *cb_arg, void *out __rte_unused) 440 { 441 struct sub_device *sdev = cb_arg; 442 443 /* Switch as soon as possible tx_dev. */ 444 fs_switch_dev(sdev->fs_dev, sdev); 445 /* Use safe bursts in any case. */ 446 set_burst_fn(sdev->fs_dev, 1); 447 /* 448 * Async removal, the sub-PMD will try to unregister 449 * the callback at the source of the current thread context. 450 */ 451 sdev->remove = 1; 452 return 0; 453 } 454 455 int 456 failsafe_eth_lsc_event_callback(uint16_t port_id __rte_unused, 457 enum rte_eth_event_type event __rte_unused, 458 void *cb_arg, void *out __rte_unused) 459 { 460 struct rte_eth_dev *dev = cb_arg; 461 int ret; 462 463 ret = dev->dev_ops->link_update(dev, 0); 464 /* We must pass on the LSC event */ 465 if (ret) 466 return _rte_eth_dev_callback_process(dev, 467 RTE_ETH_EVENT_INTR_LSC, 468 NULL, NULL); 469 else 470 return 0; 471 } 472