/* Update device bond info */ static void dpdk_ethdev_bond_info_update(struct vr_dpdk_ethdev *ethdev) { int i, slave_port_id; int port_id = ethdev->ethdev_port_id; struct rte_pci_addr *pci_addr; struct ether_addr bond_mac, mac_addr; struct ether_addr lacp_mac = { .addr_bytes = {0x01, 0x80, 0xc2, 0, 0, 0x02} }; if (rte_eth_bond_mode_get(port_id) == -1) { ethdev->ethdev_nb_slaves = -1; } else { ethdev->ethdev_nb_slaves = rte_eth_bond_slaves_get(port_id, ethdev->ethdev_slaves, sizeof(ethdev->ethdev_slaves)); memset(&mac_addr, 0, sizeof(bond_mac)); rte_eth_macaddr_get(port_id, &bond_mac); RTE_LOG(INFO, VROUTER, " bond eth device %" PRIu8 " configured MAC " MAC_FORMAT "\n", port_id, MAC_VALUE(bond_mac.addr_bytes)); /* log out and configure bond members */ for (i = 0; i < ethdev->ethdev_nb_slaves; i++) { slave_port_id = ethdev->ethdev_slaves[i]; memset(&mac_addr, 0, sizeof(mac_addr)); rte_eth_macaddr_get(slave_port_id, &mac_addr); pci_addr = &rte_eth_devices[slave_port_id].pci_dev->addr; RTE_LOG(INFO, VROUTER, " bond member eth device %" PRIu8 " PCI " PCI_PRI_FMT " MAC " MAC_FORMAT "\n", slave_port_id, pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function, MAC_VALUE(mac_addr.addr_bytes)); /* try to add bond mac and LACP multicast MACs */ if (rte_eth_dev_mac_addr_add(slave_port_id, &bond_mac, 0) == 0 && rte_eth_dev_mac_addr_add(slave_port_id, &lacp_mac, 0) == 0) { /* disable the promisc mode enabled by default */ rte_eth_promiscuous_disable(ethdev->ethdev_port_id); RTE_LOG(INFO, VROUTER, " bond member eth device %" PRIu8 " promisc mode disabled\n", slave_port_id); } else { RTE_LOG(INFO, VROUTER, " bond member eth device %" PRIu8 ": unable to add MAC addresses\n", slave_port_id); } } /* In LACP mode all the bond members are in the promisc mode * by default (see bond_mode_8023ad_activate_slave() * But we need also to put the bond interface in promisc to get * the broadcasts. Seems to be a bug in bond_ethdev_rx_burst_8023ad()? */ rte_eth_promiscuous_enable(port_id); } }
int rw_piot_mac_addr_add(rw_piot_api_handle_t api_handle, struct ether_addr *addr, uint32_t pool) { rw_piot_device_t *rw_piot_dev = RWPIOT_GET_DEVICE(api_handle); ASSERT(RWPIOT_VALID_DEVICE(rw_piot_dev)); if (NULL == rw_piot_dev) { RW_PIOT_LOG(RTE_LOG_ERR, "PIOT Could not find device by handle\n"); return -1; } return(rte_eth_dev_mac_addr_add(rw_piot_dev->rte_port_id, addr, pool)); }
/* * This function registers mac along with a * vlan tag to a VMDQ. */ static int link_vmdq(struct virtio_net *dev) { int ret; struct virtio_net_data_ll *dev_ll; dev_ll = ll_root_used; while (dev_ll != NULL) { if ((dev != dev_ll->dev) && ether_addr_cmp(&dev->mac_address, &dev_ll->dev->mac_address)) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing MAC address and has not been registered.\n", dev->device_fh); return -1; } dev_ll = dev_ll->next; } /* vlan_tag currently uses the device_id. */ dev->vlan_tag = vlan_tags[dev->device_fh]; dev->vmdq_rx_q = dev->device_fh * (num_queues/num_devices); /* Print out VMDQ registration info. */ RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n", dev->device_fh, dev->mac_address.addr_bytes[0], dev->mac_address.addr_bytes[1], dev->mac_address.addr_bytes[2], dev->mac_address.addr_bytes[3], dev->mac_address.addr_bytes[4], dev->mac_address.addr_bytes[5], dev->vlan_tag); /* Register the MAC address. */ ret = rte_eth_dev_mac_addr_add(ports[0], &dev->mac_address, (uint32_t)dev->device_fh); if (ret) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n", dev->device_fh); return -1; } /* Enable stripping of the vlan tag as we handle routing. */ rte_eth_dev_set_vlan_strip_on_queue(ports[0], dev->vmdq_rx_q, 1); rte_compiler_barrier(); /* Set device as ready for RX. */ dev->ready = DEVICE_READY; return 0; }
/* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_dev_info dev_info; struct rte_eth_rxconf *rxconf; struct rte_eth_conf port_conf; uint16_t rxRings, txRings; const uint16_t rxRingSize = RTE_TEST_RX_DESC_DEFAULT, txRingSize = RTE_TEST_TX_DESC_DEFAULT; int retval; uint16_t q; uint16_t queues_per_pool; uint32_t max_nb_pools; /* * The max pool number from dev_info will be used to validate the pool * number specified in cmd line */ rte_eth_dev_info_get(port, &dev_info); max_nb_pools = (uint32_t)dev_info.max_vmdq_pools; /* * We allow to process part of VMDQ pools specified by num_pools in * command line. */ if (num_pools > max_nb_pools) { printf("num_pools %d >max_nb_pools %d\n", num_pools, max_nb_pools); return -1; } retval = get_eth_conf(&port_conf, max_nb_pools); if (retval < 0) return retval; /* * NIC queues are divided into pf queues and vmdq queues. */ /* There is assumption here all ports have the same configuration! */ num_pf_queues = dev_info.max_rx_queues - dev_info.vmdq_queue_num; queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools; num_vmdq_queues = num_pools * queues_per_pool; num_queues = num_pf_queues + num_vmdq_queues; vmdq_queue_base = dev_info.vmdq_queue_base; vmdq_pool_base = dev_info.vmdq_pool_base; printf("pf queue num: %u, configured vmdq pool num: %u," " each vmdq pool has %u queues\n", num_pf_queues, num_pools, queues_per_pool); printf("vmdq queue base: %d pool base %d\n", vmdq_queue_base, vmdq_pool_base); if (port >= rte_eth_dev_count()) return -1; /* * Though in this example, we only receive packets from the first queue * of each pool and send packets through first rte_lcore_count() tx * queues of vmdq queues, all queues including pf queues are setup. * This is because VMDQ queues doesn't always start from zero, and the * PMD layer doesn't support selectively initialising part of rx/tx * queues. */ rxRings = (uint16_t)dev_info.max_rx_queues; txRings = (uint16_t)dev_info.max_tx_queues; retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; rte_eth_dev_info_get(port, &dev_info); rxconf = &dev_info.default_rxconf; rxconf->rx_drop_en = 1; for (q = 0; q < rxRings; q++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, rte_eth_dev_socket_id(port), rxconf, mbuf_pool); if (retval < 0) { printf("initialise rx queue %d failed\n", q); return retval; } } for (q = 0; q < txRings; q++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, rte_eth_dev_socket_id(port), NULL); if (retval < 0) { printf("initialise tx queue %d failed\n", q); return retval; } } retval = rte_eth_dev_start(port); if (retval < 0) { printf("port %d start failed\n", port); return retval; } rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, vmdq_ports_eth_addr[port].addr_bytes[0], vmdq_ports_eth_addr[port].addr_bytes[1], vmdq_ports_eth_addr[port].addr_bytes[2], vmdq_ports_eth_addr[port].addr_bytes[3], vmdq_ports_eth_addr[port].addr_bytes[4], vmdq_ports_eth_addr[port].addr_bytes[5]); /* * Set mac for each pool. * There is no default mac for the pools in i40. * Removes this after i40e fixes this issue. */ for (q = 0; q < num_pools; q++) { struct ether_addr mac; mac = pool_addr_template; mac.addr_bytes[4] = port; mac.addr_bytes[5] = q; printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n", port, q, mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); retval = rte_eth_dev_mac_addr_add(port, &mac, q + vmdq_pool_base); if (retval) { printf("mac addr add failed at pool %d\n", q); return retval; } } return 0; }
/* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint16_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_dev_info dev_info; struct rte_eth_conf port_conf = {0}; uint16_t rxRingSize = RTE_TEST_RX_DESC_DEFAULT; uint16_t txRingSize = RTE_TEST_TX_DESC_DEFAULT; int retval; uint16_t q; uint16_t queues_per_pool; uint32_t max_nb_pools; /* * The max pool number from dev_info will be used to validate the pool * number specified in cmd line */ rte_eth_dev_info_get(port, &dev_info); max_nb_pools = (uint32_t)dev_info.max_vmdq_pools; /* * We allow to process part of VMDQ pools specified by num_pools in * command line. */ if (num_pools > max_nb_pools) { printf("num_pools %d >max_nb_pools %d\n", num_pools, max_nb_pools); return -1; } /* * NIC queues are divided into pf queues and vmdq queues. * There is assumption here all ports have the same configuration! */ vmdq_queue_base = dev_info.vmdq_queue_base; vmdq_pool_base = dev_info.vmdq_pool_base; printf("vmdq queue base: %d pool base %d\n", vmdq_queue_base, vmdq_pool_base); if (vmdq_pool_base == 0) { num_vmdq_queues = dev_info.max_rx_queues; num_queues = dev_info.max_rx_queues; if (num_tcs != num_vmdq_queues / num_pools) { printf("nb_tcs %d is invalid considering with" " nb_pools %d, nb_tcs * nb_pools should = %d\n", num_tcs, num_pools, num_vmdq_queues); return -1; } } else { queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools; if (num_tcs > queues_per_pool) { printf("num_tcs %d > num of queues per pool %d\n", num_tcs, queues_per_pool); return -1; } num_vmdq_queues = num_pools * queues_per_pool; num_queues = vmdq_queue_base + num_vmdq_queues; printf("Configured vmdq pool num: %u," " each vmdq pool has %u queues\n", num_pools, queues_per_pool); } if (port >= rte_eth_dev_count()) return -1; retval = get_eth_conf(&port_conf); if (retval < 0) return retval; /* * Though in this example, all queues including pf queues are setup. * This is because VMDQ queues doesn't always start from zero, and the * PMD layer doesn't support selectively initialising part of rx/tx * queues. */ retval = rte_eth_dev_configure(port, num_queues, num_queues, &port_conf); if (retval != 0) return retval; retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &rxRingSize, &txRingSize); if (retval != 0) return retval; if (RTE_MAX(rxRingSize, txRingSize) > RTE_MAX(RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT)) { printf("Mbuf pool has an insufficient size for port %u.\n", port); return -1; } for (q = 0; q < num_queues; q++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) { printf("initialize rx queue %d failed\n", q); return retval; } } for (q = 0; q < num_queues; q++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, rte_eth_dev_socket_id(port), NULL); if (retval < 0) { printf("initialize tx queue %d failed\n", q); return retval; } } retval = rte_eth_dev_start(port); if (retval < 0) { printf("port %d start failed\n", port); return retval; } rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, vmdq_ports_eth_addr[port].addr_bytes[0], vmdq_ports_eth_addr[port].addr_bytes[1], vmdq_ports_eth_addr[port].addr_bytes[2], vmdq_ports_eth_addr[port].addr_bytes[3], vmdq_ports_eth_addr[port].addr_bytes[4], vmdq_ports_eth_addr[port].addr_bytes[5]); /* Set mac for each pool.*/ for (q = 0; q < num_pools; q++) { struct ether_addr mac; mac = pool_addr_template; mac.addr_bytes[4] = port; mac.addr_bytes[5] = q; printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n", port, q, mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); retval = rte_eth_dev_mac_addr_add(port, &mac, q + vmdq_pool_base); if (retval) { printf("mac addr add failed at pool %d\n", q); return retval; } } return 0; }