示例#1
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 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;

}