static int dpdk_helper_link_status_get(dpdk_helper_ctx_t *phc) { dpdk_events_ctx_t *ec = DPDK_EVENTS_CTX_GET(phc); /* get Link Status values from DPDK */ uint8_t nb_ports = rte_eth_dev_count(); if (nb_ports == 0) { DPDK_CHILD_LOG("dpdkevent-helper: No DPDK ports available. " "Check bound devices to DPDK driver.\n"); return -ENODEV; } ec->nb_ports = nb_ports > RTE_MAX_ETHPORTS ? RTE_MAX_ETHPORTS : nb_ports; for (int i = 0; i < ec->nb_ports; i++) { if (ec->config.link_status.enabled_port_mask & (1 << i)) { struct rte_eth_link link; ec->link_info[i].read_time = cdtime(); rte_eth_link_get_nowait(i, &link); if ((link.link_status == ETH_LINK_NA) || (link.link_status != ec->link_info[i].link_status)) { ec->link_info[i].link_status = link.link_status; ec->link_info[i].status_updated = 1; DPDK_CHILD_LOG(" === PORT %d Link Status: %s\n", i, link.link_status ? "UP" : "DOWN"); } } } return 0; }
static void app_ports_check_link(void) { uint32_t all_ports_up, i; all_ports_up = 1; for (i = 0; i < app.n_ports; i++) { struct rte_eth_link link; uint8_t port; port = (uint8_t) app.ports[i]; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(port, &link); RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n", port, link.link_speed / 1000, link.link_status ? "UP" : "DOWN"); if (link.link_status == 0) all_ports_up = 0; } if (all_ports_up == 0) rte_panic("Some NIC ports are DOWN\n"); }
/* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint16_t portid; uint8_t count, all_ports_up, print_flag = 0; struct rte_eth_link link; uint32_t n_rx_queues, n_tx_queues; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; n_rx_queues = app_get_nic_rx_queues_per_port(portid); n_tx_queues = app.nic_tx_port_mask[portid]; if ((n_rx_queues == 0) && (n_tx_queues == 0)) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf( "Port%d Link Up - speed %uMbps - %s\n", portid, link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == ETH_LINK_DOWN) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } }
int tcpreplay_netport_init(struct arguments *args) { int ret; uint8_t rss_key [40]; struct rte_eth_link link; struct rte_eth_dev_info dev_info; struct rte_eth_rss_conf rss_conf; struct rte_eth_fdir fdir_conf; /* Retreiving and printing device infos */ rte_eth_dev_info_get(i, &dev_info); printf("Name:%s\n\tDriver name: %s\n\tMax rx queues: %d\n\tMax tx queues: %d\n", dev_info.pci_dev->driver->name,dev_info.driver_name, dev_info.max_rx_queues, dev_info.max_tx_queues); printf("\tPCI Adress: %04d:%02d:%02x:%01d\n", dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function); /* Configure device with '1' rx queues and 1 tx queue */ ret = rte_eth_dev_configure(i, 1, 1, &port_conf); if (ret < 0) rte_panic("Error configuring the port\n"); /* For each RX queue in each NIC */ /* Configure rx queue j of current device on current NUMA socket. It takes elements from the mempool */ ret = rte_eth_rx_queue_setup(i, 0, RX_QUEUE_SZ, rte_socket_id(), &rx_conf, pktmbuf_pool); if (ret < 0) FATAL_ERROR("Error configuring receiving queue\n"); /* Configure mapping [queue] -> [element in stats array] */ ret = rte_eth_dev_set_rx_queue_stats_mapping (i, 0, 0); if (ret < 0) FATAL_ERROR("Error configuring receiving queue stats\n"); /* Configure tx queue of current device on current NUMA socket. Mandatory configuration even if you want only rx packet */ ret = rte_eth_tx_queue_setup(i, 0, TX_QUEUE_SZ, rte_socket_id(), &tx_conf); if (ret < 0) FATAL_ERROR("Error configuring transmitting queue. Errno: %d (%d bad arg, %d no mem)\n", -ret, EINVAL ,ENOMEM); /* Start device */ ret = rte_eth_dev_start(i); if (ret < 0) FATAL_ERROR("Cannot start port\n"); /* Enable receipt in promiscuous mode for an Ethernet device */ rte_eth_promiscuous_enable(i); /* Print link status */ rte_eth_link_get_nowait(i, &link); if (link.link_status) printf("\tPort %d Link Up - speed %u Mbps - %s\n", (uint8_t)i, (unsigned)link.link_speed,(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?("full-duplex") : ("half-duplex\n")); else printf("\tPort %d Link Down\n",(uint8_t)i); /* Print RSS support, not reliable because a NIC could support rss configuration just in rte_eth_dev_configure whithout supporting rte_eth_dev_rss_hash_conf_get*/ rss_conf.rss_key = rss_key; ret = rte_eth_dev_rss_hash_conf_get (i,&rss_conf); if (ret == 0) printf("\tDevice supports RSS\n"); else printf("\tDevice DOES NOT support RSS\n"); /* Print Flow director support */ ret = rte_eth_dev_fdir_get_infos (i, &fdir_conf); if (ret == 0) printf("\tDevice supports Flow Director\n"); else printf("\tDevice DOES NOT support Flow Director\n"); if (args) return 1; return 1; }
/* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status() { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; LOG_RAW(INFO, "\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { if (sk.force_quit) return; all_ports_up = 1; for (int i = 0; i < sk.nr_ports; i++) { if (sk.force_quit) return; portid = (uint8_t )sk.port_ids[i]; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) LOG_RAW(INFO, "Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else LOG_RAW(INFO, "Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == ETH_LINK_DOWN) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { LOG_RAW(INFO, "."); fflush(sk.log_fp); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; LOG_RAW(INFO, "done\n"); } } }
/********************************************************************** *@description: * Check the link status of all ports in up to 9s, and print them finally * *@parameters: * [in]: * [in]: * *@return values: * **********************************************************************/ static void odp_check_ports_link_status(uint8_t port_num, uint32_t port_mask) { uint8_t check_interval = 100; /* 100ms */ uint8_t max_check_time = 90; /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status "); for (count = 0; count <= max_check_time; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); rte_delay_ms(check_interval); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (max_check_time - 1)) { print_flag = 1; printf("done\n"); } } }
int vfd_mlx5_set_qos_pf(uint16_t port_id, tc_class_t **tc_config, uint8_t ntcs) { char ifname[IF_NAMESIZE]; char cmd[256] = ""; struct mlx5_tc_cfg tc_cfg[MAX_TCS]; struct rte_eth_link link; int i, ret; if (vfd_mlx5_get_ifname(port_id, ifname)) return -1; if (ntcs != 8) { printf("mlx5 devices don't support 4 TC configuration\n"); return -2; } memset(tc_cfg, 0, sizeof(tc_cfg)); rte_eth_link_get_nowait(port_id, &link); for(i=0; i< ntcs; i++) { strcpy(tc_cfg[i].policy, (tc_config[i]->flags & TCF_LNK_STRICTP) ? "strict" : "ets"); tc_cfg[i].min_bw = (tc_config[i]->flags & TCF_LNK_STRICTP) ? 0 : tc_config[i]->min_bw; if (tc_config[i]->max_bw < 100) { tc_cfg[i].max_bw = (tc_config[i]->max_bw * link.link_speed) / 100; if (tc_cfg[i].max_bw < 1000) tc_cfg[i].max_bw = 1000; //move to Gbps tc_cfg[i].max_bw = tc_cfg[i].max_bw / 1000; } } sprintf(cmd, "mlnx_qos -i %s -s %s,%s,%s,%s,%s,%s,%s,%s -t %d,%d,%d,%d,%d,%d,%d,%d", ifname, tc_cfg[0].policy, tc_cfg[1].policy, tc_cfg[2].policy, tc_cfg[3].policy, tc_cfg[4].policy, tc_cfg[5].policy, tc_cfg[6].policy, tc_cfg[7].policy, tc_cfg[0].min_bw, tc_cfg[1].min_bw, tc_cfg[2].min_bw, tc_cfg[3].min_bw, tc_cfg[4].min_bw, tc_cfg[5].min_bw, tc_cfg[6].min_bw, tc_cfg[7].min_bw); ret = system(cmd); //set rate limiters sprintf(cmd, "mlnx_qos -i %s -r %d,%d,%d,%d,%d,%d,%d,%d", ifname, tc_cfg[0].max_bw, tc_cfg[1].max_bw, tc_cfg[2].max_bw, tc_cfg[3].max_bw, tc_cfg[4].max_bw, tc_cfg[5].max_bw, tc_cfg[6].max_bw, tc_cfg[7].max_bw); ret = system(cmd); if (ret < 0) { // printf("cmd exec returned %d\n", ret); } return 0; }
void rw_piot_get_link_info(rw_piot_api_handle_t api_handle, rw_piot_link_info_t *eth_link_info) { rw_piot_device_t *rw_piot_dev = RWPIOT_GET_DEVICE(api_handle); ASSERT(RWPIOT_VALID_DEVICE(rw_piot_dev)); if (NULL == rw_piot_dev || NULL == eth_link_info) { RW_PIOT_LOG(RTE_LOG_ERR, "PIOT Could not find device by handle or invalid input param\n"); return; } rte_eth_link_get_nowait(rw_piot_dev->rte_port_id, eth_link_info); return; }
/* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); rte_delay_ms(15000); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } }
int uhd_dpdk_port_link_status(unsigned int portid) { if (!ctx) return -ENODEV; struct uhd_dpdk_port *p = find_port(portid); if (p) { struct rte_eth_link link; rte_eth_link_get_nowait(p->id, &link); return link.link_status; } return -ENODEV; }
/** * @brief Get device link state * * @param devId uint8_t, ID of DPDK device * @param link EthLinkState_t*, pointer to buffer where device link state will be stored * * @return true if success and false otherwice */ bool DPDKAdapter::getDevLinkState(uint8_t devId, EthLinkState_t* link) { if(devId > RTE_MAX_ETHPORTS) { qCritical("Device ID is out of range"); return false; } memset(link, 0, sizeof(EthLinkState_t)); rte_eth_link_get_nowait(devId, link); return true; }
static void udpi_ports_check_link(void) { struct rte_eth_link link; uint32_t port_id; for (port_id=0; port_id<udpi.n_ports; port_id++) { memset(&link, 0, sizeof(struct rte_eth_link)); rte_eth_link_get_nowait(port_id, &link); RTE_LOG(INFO, PORT, "Port %u (%u Gbps) %s\n", port_id, link.link_speed / 1000, link.link_status ? "UP":"DOWN"); } return; }
void port_infos_display(struct cmdline *cl, portid_t port_id) { struct ether_addr mac_addr; struct rte_eth_link link; int vlan_offload; static const char *info_border = "====================="; rte_eth_link_get_nowait(port_id, &link); cmdline_printf(cl, "\n%s Infos for port %-2d %s\n", info_border, port_id, info_border); rte_eth_macaddr_get(port_id, &mac_addr); print_ethaddr(cl, "MAC address: ", &mac_addr); cmdline_printf(cl, "\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); cmdline_printf(cl, "Link speed: %u Mbps\n", (unsigned)link.link_speed); cmdline_printf(cl, "Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); cmdline_printf(cl, "Promiscuous mode: %s\n", rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled"); cmdline_printf(cl, "Allmulticast mode: %s\n", rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); vlan_offload = rte_eth_dev_get_vlan_offload(port_id); if (vlan_offload >= 0) { cmdline_printf(cl, "VLAN offload: \n"); if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) cmdline_printf(cl, " strip on \n"); else cmdline_printf(cl, " strip off \n"); if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) cmdline_printf(cl, " filter on \n"); else cmdline_printf(cl, " filter off \n"); if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) cmdline_printf(cl, " qinq(extend) on \n"); else cmdline_printf(cl, " qinq(extend) off \n"); } }
int linkStatusGet(const char* device) { int deviceId = 0; struct rte_eth_link link; if (device == NULL) { snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Invalid parameter"); return DPDKPCAP_FAILURE; } deviceId = findDevice(device, errbuf_g); rte_eth_link_get_nowait(deviceId, &link); return link.link_status; }
static void lsi_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param) { struct rte_eth_link link; RTE_SET_USED(param); printf("\n\nIn registered callback...\n"); printf("Event type: %s\n", type == RTE_ETH_EVENT_INTR_LSC ? "LSC interrupt" : "unknown event"); rte_eth_link_get_nowait(port_id, &link); if (link.link_status) { printf("Port %d Link Up - speed %u Mbps - %s\n\n", port_id, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); } else printf("Port %d Link Down\n\n", port_id); }
void init_port(int port_id) { struct rte_eth_dev_info dev_info; int ret; struct rte_eth_link link; rte_eth_dev_info_get(port_id, &dev_info); printf("Name:%s\n\tDriver name: %s\n\tMax rx queues: %d\n\tMax tx queues: %d\n", dev_info.pci_dev->driver->name,dev_info.driver_name, dev_info.max_rx_queues, dev_info.max_tx_queues); printf("\tPCI Adress: %04d:%02d:%02x:%01d\n", dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function); ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); if (ret < 0) rte_panic("Error configuring the port\n"); ret = rte_eth_rx_queue_setup(port_id, 0, RX_QUEUE_SZ, rte_socket_id(), &rx_conf, pktmbuf_pool); if (ret < 0) FATAL_ERROR("Error configuring receiving queue= %d\n", ret); // TODO: Need to check whether it is supported in the VMXNET /*ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, 0, 0); if (ret < 0) FATAL_ERROR("Error configuring receiving queue stats= %d [ENOTSUP= %d]\n", ret, ENOTSUP); */ ret = rte_eth_tx_queue_setup(port_id, 0, TX_QUEUE_SZ, rte_socket_id(), &tx_conf); if (ret < 0) FATAL_ERROR("Error configuring transmitting queue. Errno: %d (%d bad arg, %d no mem)\n", -ret, EINVAL ,ENOMEM); /* Start device */ ret = rte_eth_dev_start(port_id); if (ret < 0) FATAL_ERROR("Cannot start port\n"); /* Enable receipt in promiscuous mode for an Ethernet device */ //rte_eth_promiscuous_enable(port_id); /* Print link status */ rte_eth_link_get_nowait(port_id, &link); if (link.link_status) printf("\tPort %d Link Up - speed %u Mbps - %s\n", (uint8_t)port_id, (unsigned)link.link_speed,(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?("full-duplex") : ("half-duplex\n")); else printf("\tPort %d Link Down\n",(uint8_t)port_id); }
lagopus_result_t update_port_link_status(struct port *port) { struct rte_eth_link link; uint8_t portid; bool changed = false; portid = (uint8_t)port->ifindex; /* ofp_port.config is configured by the controller. */ /* other port status. */ /* OFPPF_* for OpenFlow 1.3 */ rte_eth_link_get_nowait(portid, &link); switch (link.link_speed) { case ETH_LINK_SPEED_10: port->ofp_port.curr_speed = 10* 1000; port->ofp_port.curr = OFPPF_10MB_FD; break; case ETH_LINK_SPEED_100: port->ofp_port.curr_speed = 100 * 1000; port->ofp_port.curr = OFPPF_100MB_FD; break; case ETH_LINK_SPEED_1000: port->ofp_port.curr_speed = 1000 * 1000; port->ofp_port.curr = OFPPF_1GB_FD; break; case ETH_LINK_SPEED_10000: port->ofp_port.curr_speed = 10000 * 1000; port->ofp_port.curr = OFPPF_10GB_FD; break; default: port->ofp_port.curr_speed = 0; port->ofp_port.curr = OFPPF_OTHER; break; } if (port->ofp_port.curr_speed != 0 && link.link_duplex != ETH_LINK_FULL_DUPLEX) { port->ofp_port.curr >>= 1; }
static int __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; struct bond_dev_private *internals; struct bond_dev_private *temp_internals; struct rte_eth_link link_props; struct rte_eth_dev_info dev_info; int i, j; if (valid_slave_port_id(slave_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; /* Verify that new slave device is not already a slave of another * bonded device */ for (i = rte_eth_dev_count()-1; i >= 0; i--) { if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) { temp_internals = rte_eth_devices[i].data->dev_private; for (j = 0; j < temp_internals->slave_count; j++) { /* Device already a slave of a bonded device */ if (temp_internals->slaves[j].port_id == slave_port_id) { RTE_BOND_LOG(ERR, "Slave port %d is already a slave", slave_port_id); return -1; } } } } slave_eth_dev = &rte_eth_devices[slave_port_id]; /* Add slave details to bonded device */ slave_add(internals, slave_eth_dev); memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(slave_port_id, &dev_info); if (internals->slave_count < 1) { /* if MAC is not user defined then use MAC of first slave add to * bonded device */ if (!internals->user_defined_mac) mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs); /* Inherit eth dev link properties from first slave */ link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); /* Make primary slave */ internals->primary_port = slave_port_id; /* Take the first dev's offload capabilities */ internals->rx_offload_capa = dev_info.rx_offload_capa; internals->tx_offload_capa = dev_info.tx_offload_capa; } else { /* Check slave link properties are supported if props are set, * all slaves must be the same */ if (internals->link_props_set) { if (link_properties_valid(&(bonded_eth_dev->data->dev_link), &(slave_eth_dev->data->dev_link))) { RTE_BOND_LOG(ERR, "Slave port %d link speed/duplex not supported", slave_port_id); return -1; } } else { link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); } internals->rx_offload_capa &= dev_info.rx_offload_capa; internals->tx_offload_capa &= dev_info.tx_offload_capa; } internals->slave_count++; /* Update all slave devices MACs*/ mac_address_slaves_update(bonded_eth_dev); if (bonded_eth_dev->data->dev_started) { if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) { RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d", slave_port_id); return -1; } } /* Register link status change callback with bonded device pointer as * argument*/ rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC, bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id); /* If bonded device is started then we can add the slave to our active * slave array */ if (bonded_eth_dev->data->dev_started) { rte_eth_link_get_nowait(slave_port_id, &link_props); if (link_props.link_status == 1) activate_slave(bonded_eth_dev, slave_port_id); } return 0; }
static int __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; struct bond_dev_private *internals; struct rte_eth_link link_props; struct rte_eth_dev_info dev_info; if (valid_slave_port_id(slave_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; slave_eth_dev = &rte_eth_devices[slave_port_id]; if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_BONDED_SLAVE) { RTE_BOND_LOG(ERR, "Slave device is already a slave of a bonded device"); return -1; } /* Add slave details to bonded device */ slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE; rte_eth_dev_info_get(slave_port_id, &dev_info); if (dev_info.max_rx_pktlen < internals->max_rx_pktlen) { RTE_BOND_LOG(ERR, "Slave (port %u) max_rx_pktlen too small", slave_port_id); return -1; } slave_add(internals, slave_eth_dev); /* We need to store slaves reta_size to be able to synchronize RETA for all * slave devices even if its sizes are different. */ internals->slaves[internals->slave_count].reta_size = dev_info.reta_size; if (internals->slave_count < 1) { /* if MAC is not user defined then use MAC of first slave add to * bonded device */ if (!internals->user_defined_mac) mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs); /* Inherit eth dev link properties from first slave */ link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); /* Make primary slave */ internals->primary_port = slave_port_id; internals->current_primary_port = slave_port_id; /* Inherit queues settings from first slave */ internals->nb_rx_queues = slave_eth_dev->data->nb_rx_queues; internals->nb_tx_queues = slave_eth_dev->data->nb_tx_queues; internals->reta_size = dev_info.reta_size; /* Take the first dev's offload capabilities */ internals->rx_offload_capa = dev_info.rx_offload_capa; internals->tx_offload_capa = dev_info.tx_offload_capa; internals->flow_type_rss_offloads = dev_info.flow_type_rss_offloads; /* Inherit first slave's max rx packet size */ internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen; } else { internals->rx_offload_capa &= dev_info.rx_offload_capa; internals->tx_offload_capa &= dev_info.tx_offload_capa; internals->flow_type_rss_offloads &= dev_info.flow_type_rss_offloads; /* RETA size is GCD of all slaves RETA sizes, so, if all sizes will be * the power of 2, the lower one is GCD */ if (internals->reta_size > dev_info.reta_size) internals->reta_size = dev_info.reta_size; if (!internals->max_rx_pktlen && dev_info.max_rx_pktlen < internals->candidate_max_rx_pktlen) internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen; } bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &= internals->flow_type_rss_offloads; internals->slave_count++; /* Update all slave devices MACs*/ mac_address_slaves_update(bonded_eth_dev); if (bonded_eth_dev->data->dev_started) { if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) { slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE); RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d", slave_port_id); return -1; } } /* Register link status change callback with bonded device pointer as * argument*/ rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC, bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id); /* If bonded device is started then we can add the slave to our active * slave array */ if (bonded_eth_dev->data->dev_started) { rte_eth_link_get_nowait(slave_port_id, &link_props); if (link_props.link_status == ETH_LINK_UP) { if (internals->active_slave_count == 0 && !internals->user_defined_primary_port) bond_ethdev_primary_set(internals, slave_port_id); if (find_slave_by_id(internals->active_slaves, internals->active_slave_count, slave_port_id) == internals->active_slave_count) activate_slave(bonded_eth_dev, slave_port_id); } } slave_vlan_filter_set(bonded_port_id, slave_port_id); return 0; }