1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2017 6WIND S.A. 3 * Copyright 2017 Mellanox Technologies, Ltd 4 */ 5 6 #include <stdbool.h> 7 8 #include <rte_alarm.h> 9 #include <rte_malloc.h> 10 #include <rte_ethdev_driver.h> 11 #include <rte_ethdev_vdev.h> 12 #include <rte_devargs.h> 13 #include <rte_kvargs.h> 14 #include <rte_bus_vdev.h> 15 16 #include "failsafe_private.h" 17 18 const char pmd_failsafe_driver_name[] = FAILSAFE_DRIVER_NAME; 19 static const struct rte_eth_link eth_link = { 20 .link_speed = ETH_SPEED_NUM_10G, 21 .link_duplex = ETH_LINK_FULL_DUPLEX, 22 .link_status = ETH_LINK_UP, 23 .link_autoneg = ETH_LINK_AUTONEG, 24 }; 25 26 static int 27 fs_sub_device_alloc(struct rte_eth_dev *dev, 28 const char *params) 29 { 30 uint8_t nb_subs; 31 int ret; 32 int i; 33 struct sub_device *sdev; 34 uint8_t sdev_iterator; 35 36 ret = failsafe_args_count_subdevice(dev, params); 37 if (ret) 38 return ret; 39 if (PRIV(dev)->subs_tail > FAILSAFE_MAX_ETHPORTS) { 40 ERROR("Cannot allocate more than %d ports", 41 FAILSAFE_MAX_ETHPORTS); 42 return -ENOSPC; 43 } 44 nb_subs = PRIV(dev)->subs_tail; 45 PRIV(dev)->subs = rte_zmalloc(NULL, 46 sizeof(struct sub_device) * nb_subs, 47 RTE_CACHE_LINE_SIZE); 48 if (PRIV(dev)->subs == NULL) { 49 ERROR("Could not allocate sub_devices"); 50 return -ENOMEM; 51 } 52 /* Initiate static sub devices linked list. */ 53 for (i = 1; i < nb_subs; i++) 54 PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs + i; 55 PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs; 56 57 FOREACH_SUBDEV(sdev, sdev_iterator, dev) { 58 sdev->sdev_port_id = RTE_MAX_ETHPORTS; 59 } 60 return 0; 61 } 62 63 static void 64 fs_sub_device_free(struct rte_eth_dev *dev) 65 { 66 rte_free(PRIV(dev)->subs); 67 } 68 69 static void fs_hotplug_alarm(void *arg); 70 71 int 72 failsafe_hotplug_alarm_install(struct rte_eth_dev *dev) 73 { 74 int ret; 75 76 if (dev == NULL) 77 return -EINVAL; 78 if (PRIV(dev)->pending_alarm) 79 return 0; 80 ret = rte_eal_alarm_set(failsafe_hotplug_poll * 1000, 81 fs_hotplug_alarm, 82 dev); 83 if (ret) { 84 ERROR("Could not set up plug-in event detection"); 85 return ret; 86 } 87 PRIV(dev)->pending_alarm = 1; 88 return 0; 89 } 90 91 int 92 failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev) 93 { 94 int ret = 0; 95 96 rte_errno = 0; 97 rte_eal_alarm_cancel(fs_hotplug_alarm, dev); 98 if (rte_errno) { 99 ERROR("rte_eal_alarm_cancel failed (errno: %s)", 100 strerror(rte_errno)); 101 ret = -rte_errno; 102 } else { 103 PRIV(dev)->pending_alarm = 0; 104 } 105 return ret; 106 } 107 108 static void 109 fs_hotplug_alarm(void *arg) 110 { 111 struct rte_eth_dev *dev = arg; 112 struct sub_device *sdev; 113 int ret; 114 uint8_t i; 115 116 if (!PRIV(dev)->pending_alarm) 117 return; 118 PRIV(dev)->pending_alarm = 0; 119 FOREACH_SUBDEV(sdev, i, dev) 120 if (sdev->state != PRIV(dev)->state) 121 break; 122 /* if we have non-probed device */ 123 if (i != PRIV(dev)->subs_tail) { 124 if (fs_lock(dev, 1) != 0) 125 goto reinstall; 126 ret = failsafe_eth_dev_state_sync(dev); 127 fs_unlock(dev, 1); 128 if (ret) 129 ERROR("Unable to synchronize sub_device state"); 130 } 131 failsafe_dev_remove(dev); 132 reinstall: 133 ret = failsafe_hotplug_alarm_install(dev); 134 if (ret) 135 ERROR("Unable to set up next alarm"); 136 } 137 138 static int 139 fs_mutex_init(struct fs_priv *priv) 140 { 141 int ret; 142 pthread_mutexattr_t attr; 143 144 ret = pthread_mutexattr_init(&attr); 145 if (ret) { 146 ERROR("Cannot initiate mutex attributes - %s", strerror(ret)); 147 return ret; 148 } 149 /* Allow mutex relocks for the thread holding the mutex. */ 150 ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 151 if (ret) { 152 ERROR("Cannot set mutex type - %s", strerror(ret)); 153 return ret; 154 } 155 ret = pthread_mutex_init(&priv->hotplug_mutex, &attr); 156 if (ret) { 157 ERROR("Cannot initiate mutex - %s", strerror(ret)); 158 return ret; 159 } 160 return 0; 161 } 162 163 static int 164 fs_eth_dev_create(struct rte_vdev_device *vdev) 165 { 166 struct rte_eth_dev *dev; 167 struct rte_ether_addr *mac; 168 struct fs_priv *priv; 169 struct sub_device *sdev; 170 const char *params; 171 unsigned int socket_id; 172 uint8_t i; 173 int ret; 174 175 dev = NULL; 176 priv = NULL; 177 socket_id = rte_socket_id(); 178 INFO("Creating fail-safe device on NUMA socket %u", socket_id); 179 params = rte_vdev_device_args(vdev); 180 if (params == NULL) { 181 ERROR("This PMD requires sub-devices, none provided"); 182 return -1; 183 } 184 dev = rte_eth_vdev_allocate(vdev, sizeof(*priv)); 185 if (dev == NULL) { 186 ERROR("Unable to allocate rte_eth_dev"); 187 return -1; 188 } 189 priv = PRIV(dev); 190 priv->data = dev->data; 191 priv->rxp = FS_RX_PROXY_INIT; 192 dev->dev_ops = &failsafe_ops; 193 dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0]; 194 dev->data->dev_link = eth_link; 195 PRIV(dev)->nb_mac_addr = 1; 196 TAILQ_INIT(&PRIV(dev)->flow_list); 197 dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 198 dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 199 ret = fs_sub_device_alloc(dev, params); 200 if (ret) { 201 ERROR("Could not allocate sub_devices"); 202 goto free_dev; 203 } 204 ret = failsafe_args_parse(dev, params); 205 if (ret) 206 goto free_subs; 207 ret = rte_eth_dev_owner_new(&priv->my_owner.id); 208 if (ret) { 209 ERROR("Failed to get unique owner identifier"); 210 goto free_args; 211 } 212 snprintf(priv->my_owner.name, sizeof(priv->my_owner.name), 213 FAILSAFE_OWNER_NAME); 214 DEBUG("Failsafe port %u owner info: %s_%016"PRIX64, dev->data->port_id, 215 priv->my_owner.name, priv->my_owner.id); 216 ret = rte_eth_dev_callback_register(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 217 failsafe_eth_new_event_callback, 218 dev); 219 if (ret) { 220 ERROR("Failed to register NEW callback"); 221 goto free_args; 222 } 223 ret = failsafe_eal_init(dev); 224 if (ret) 225 goto unregister_new_callback; 226 ret = fs_mutex_init(priv); 227 if (ret) 228 goto unregister_new_callback; 229 ret = failsafe_hotplug_alarm_install(dev); 230 if (ret) { 231 ERROR("Could not set up plug-in event detection"); 232 goto unregister_new_callback; 233 } 234 mac = &dev->data->mac_addrs[0]; 235 if (failsafe_mac_from_arg) { 236 /* 237 * If MAC address was provided as a parameter, 238 * apply to all probed slaves. 239 */ 240 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { 241 ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 242 mac); 243 if (ret) { 244 ERROR("Failed to set default MAC address"); 245 goto cancel_alarm; 246 } 247 } 248 } else { 249 /* 250 * Use the ether_addr from first probed 251 * device, either preferred or fallback. 252 */ 253 FOREACH_SUBDEV(sdev, i, dev) 254 if (sdev->state >= DEV_PROBED) { 255 rte_ether_addr_copy( 256 Ð(sdev)->data->mac_addrs[0], mac); 257 break; 258 } 259 /* 260 * If no device has been probed and no ether_addr 261 * has been provided on the command line, use a random 262 * valid one. 263 * It will be applied during future slave state syncs to 264 * probed slaves. 265 */ 266 if (i == priv->subs_tail) 267 rte_eth_random_addr(&mac->addr_bytes[0]); 268 } 269 INFO("MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 270 mac->addr_bytes[0], mac->addr_bytes[1], 271 mac->addr_bytes[2], mac->addr_bytes[3], 272 mac->addr_bytes[4], mac->addr_bytes[5]); 273 dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 274 PRIV(dev)->intr_handle = (struct rte_intr_handle){ 275 .fd = -1, 276 .type = RTE_INTR_HANDLE_EXT, 277 }; 278 rte_eth_dev_probing_finish(dev); 279 return 0; 280 cancel_alarm: 281 failsafe_hotplug_alarm_cancel(dev); 282 unregister_new_callback: 283 rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 284 failsafe_eth_new_event_callback, dev); 285 free_args: 286 failsafe_args_free(dev); 287 free_subs: 288 fs_sub_device_free(dev); 289 free_dev: 290 /* mac_addrs must not be freed alone because part of dev_private */ 291 dev->data->mac_addrs = NULL; 292 rte_eth_dev_release_port(dev); 293 return -1; 294 } 295 296 static int 297 fs_rte_eth_free(const char *name) 298 { 299 struct rte_eth_dev *dev; 300 int ret; 301 302 dev = rte_eth_dev_allocated(name); 303 if (dev == NULL) 304 return -ENODEV; 305 rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW, 306 failsafe_eth_new_event_callback, dev); 307 ret = failsafe_eal_uninit(dev); 308 if (ret) 309 ERROR("Error while uninitializing sub-EAL"); 310 failsafe_args_free(dev); 311 fs_sub_device_free(dev); 312 ret = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex); 313 if (ret) 314 ERROR("Error while destroying hotplug mutex"); 315 rte_free(PRIV(dev)->mcast_addrs); 316 /* mac_addrs must not be freed alone because part of dev_private */ 317 dev->data->mac_addrs = NULL; 318 rte_eth_dev_release_port(dev); 319 return ret; 320 } 321 322 static bool 323 devargs_already_listed(struct rte_devargs *devargs) 324 { 325 struct rte_devargs *list_da; 326 327 RTE_EAL_DEVARGS_FOREACH(devargs->bus->name, list_da) { 328 if (strcmp(list_da->name, devargs->name) == 0) 329 /* devargs already in the list */ 330 return true; 331 } 332 return false; 333 } 334 335 static int 336 rte_pmd_failsafe_probe(struct rte_vdev_device *vdev) 337 { 338 const char *name; 339 struct rte_eth_dev *eth_dev; 340 struct sub_device *sdev; 341 struct rte_devargs devargs; 342 uint8_t i; 343 int ret; 344 345 name = rte_vdev_device_name(vdev); 346 INFO("Initializing " FAILSAFE_DRIVER_NAME " for %s", 347 name); 348 349 if (rte_eal_process_type() == RTE_PROC_SECONDARY && 350 strlen(rte_vdev_device_args(vdev)) == 0) { 351 eth_dev = rte_eth_dev_attach_secondary(name); 352 if (!eth_dev) { 353 ERROR("Failed to probe %s", name); 354 return -1; 355 } 356 eth_dev->dev_ops = &failsafe_ops; 357 eth_dev->device = &vdev->device; 358 eth_dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; 359 eth_dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; 360 /* 361 * Failsafe will attempt to probe all of its sub-devices. 362 * Any failure in sub-devices is not a fatal error. 363 * A sub-device can be plugged later. 364 */ 365 FOREACH_SUBDEV(sdev, i, eth_dev) { 366 /* skip empty devargs */ 367 if (sdev->devargs.name[0] == '\0') 368 continue; 369 370 /* rebuild devargs to be able to get the bus name. */ 371 ret = rte_devargs_parse(&devargs, 372 sdev->devargs.name); 373 if (ret != 0) { 374 ERROR("Failed to parse devargs %s", 375 devargs.name); 376 continue; 377 } 378 if (!devargs_already_listed(&devargs)) { 379 ret = rte_dev_probe(devargs.name); 380 if (ret < 0) { 381 ERROR("Failed to probe devargs %s", 382 devargs.name); 383 continue; 384 } 385 } 386 } 387 rte_eth_dev_probing_finish(eth_dev); 388 return 0; 389 } 390 391 return fs_eth_dev_create(vdev); 392 } 393 394 static int 395 rte_pmd_failsafe_remove(struct rte_vdev_device *vdev) 396 { 397 const char *name; 398 399 name = rte_vdev_device_name(vdev); 400 INFO("Uninitializing " FAILSAFE_DRIVER_NAME " for %s", name); 401 return fs_rte_eth_free(name); 402 } 403 404 static struct rte_vdev_driver failsafe_drv = { 405 .probe = rte_pmd_failsafe_probe, 406 .remove = rte_pmd_failsafe_remove, 407 }; 408 409 RTE_PMD_REGISTER_VDEV(net_failsafe, failsafe_drv); 410 RTE_PMD_REGISTER_PARAM_STRING(net_failsafe, PMD_FAILSAFE_PARAM_STRING); 411 RTE_LOG_REGISTER(failsafe_logtype, pmd.net.failsafe, NOTICE) 412