/* 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);
    }
}
Beispiel #2
0
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));
}
Beispiel #3
0
/*
 * 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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}