dpdk bond

bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)
{
        struct bond_dev_private *internals;

        internals = eth_dev->data->dev_private;

        switch (mode) {
        case BONDING_MODE_ROUND_ROBIN:
                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_round_robin;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
                break;
        case BONDING_MODE_ACTIVE_BACKUP:
                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_active_backup;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
                break;
        case BONDING_MODE_BALANCE:
                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_balance;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
                break;
        case BONDING_MODE_BROADCAST:
                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
                break;
        case BONDING_MODE_8023AD:
                if (bond_mode_8023ad_enable(eth_dev) != 0)
                        return -1;

                if (internals->mode4.dedicated_queues.enabled == 0) {
                        eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_8023ad;
                        eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_8023ad;
                        RTE_BOND_LOG(WARNING,
                                "Using mode 4, it is necessary to do TX burst "
                                "and RX burst at least every 100ms.");
                } else {
                        /* Use flow director's optimization */
                        eth_dev->rx_pkt_burst =
                                        bond_ethdev_rx_burst_8023ad_fast_queue;
                        eth_dev->tx_pkt_burst =
                                        bond_ethdev_tx_burst_8023ad_fast_queue;
                }
                break;
        case BONDING_MODE_TLB:
                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_tlb;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
                break;
        case BONDING_MODE_ALB:
                if (bond_mode_alb_enable(eth_dev) != 0)
                        return -1;

                eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb;
                eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb;
                break;
        default:
                return -1;
        }

        internals->mode = mode;

        return 0;
}

bond_ethdev_rx_queue_setup

static int
bond_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
                uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
                const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool)
{
        struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)
                        rte_zmalloc_socket(NULL, sizeof(struct bond_rx_queue),
                                        0, dev->data->numa_node);
        if (bd_rx_q == NULL)
                return -1;

        bd_rx_q->queue_id = rx_queue_id;
        bd_rx_q->dev_private = dev->data->dev_private;

        bd_rx_q->nb_rx_desc = nb_rx_desc;

        memcpy(&(bd_rx_q->rx_conf), rx_conf, sizeof(struct rte_eth_rxconf));
        bd_rx_q->mb_pool = mb_pool;

        dev->data->rx_queues[rx_queue_id] = bd_rx_q;

        return 0;
}

bond_ethdev_rx_burst

static uint16_t
bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
        struct bond_dev_private *internals;

        uint16_t num_rx_total = 0;
        uint16_t slave_count;
        uint16_t active_slave;
        int i;

        /* Cast to structure, containing bonded device's port id and queue id */
        struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
        internals = bd_rx_q->dev_private;
        slave_count = internals->active_slave_count;
        active_slave = internals->active_slave;

        for (i = 0; i < slave_count && nb_pkts; i++) {
                uint16_t num_rx_slave;

                /* Offset of pointer to *bufs increases as packets are received
                 * from other slaves */
                num_rx_slave =
                        rte_eth_rx_burst(internals->active_slaves[active_slave],
                                         bd_rx_q->queue_id,
                                         bufs + num_rx_total, nb_pkts);
                num_rx_total += num_rx_slave;
                nb_pkts -= num_rx_slave;
                if (++active_slave == slave_count)
                        active_slave = 0;
        }

        if (++internals->active_slave >= slave_count)
                internals->active_slave = 0;
        return num_rx_total;
}

rte_eth_bond_slave_add

rte_eth_bond_slave_add(uint16_t bonded_port_id, uint16_t slave_port_id)
{
        struct rte_eth_dev *bonded_eth_dev;
        struct bond_dev_private *internals;

        int retval;

        /* Verify that port id's are valid bonded and slave ports */
        if (valid_bonded_port_id(bonded_port_id) != 0)
                return -1;

        bonded_eth_dev = &rte_eth_devices[bonded_port_id];
        internals = bonded_eth_dev->data->dev_private;

        rte_spinlock_lock(&internals->lock);

        retval = __eth_bond_slave_add_lock_free(bonded_port_id, slave_port_id);

        rte_spinlock_unlock(&internals->lock);

        return retval;
}
static int
__eth_bond_slave_add_lock_free(uint16_t bonded_port_id, uint16_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;
        int ret;

        bonded_eth_dev = &rte_eth_devices[bonded_port_id];
        internals = bonded_eth_dev->data->dev_private;

        if (valid_slave_port_id(slave_port_id, internals->mode) != 0)
                return -1;

        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;
        }

        ret = rte_eth_dev_info_get(slave_port_id, &dev_info);
        if (ret != 0) {
                RTE_BOND_LOG(ERR,
                        "%s: Error during getting device (port %u) info: %s
",
                        __func__, slave_port_id, strerror(-ret));

                return ret;
        }
        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) {
                        if (mac_address_set(bonded_eth_dev,
                                            slave_eth_dev->data->mac_addrs)) {
                                RTE_BOND_LOG(ERR, "Failed to set MAC address");
                                return -1;
                        }
                }

                /* 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;

                eth_bond_slave_inherit_dev_info_rx_first(internals, &dev_info);
                eth_bond_slave_inherit_dev_info_tx_first(internals, &dev_info);

                eth_bond_slave_inherit_desc_lim_first(&internals->rx_desc_lim,
                                                      &dev_info.rx_desc_lim);
                eth_bond_slave_inherit_desc_lim_first(&internals->tx_desc_lim,
                                                      &dev_info.tx_desc_lim);
        } else {
                int ret;

                eth_bond_slave_inherit_dev_info_rx_next(internals, &dev_info);
                eth_bond_slave_inherit_dev_info_tx_next(internals, &dev_info);

                ret = eth_bond_slave_inherit_desc_lim_next(
                                &internals->rx_desc_lim, &dev_info.rx_desc_lim);
                if (ret != 0)
                        return ret;

                ret = eth_bond_slave_inherit_desc_lim_next(
                                &internals->tx_desc_lim, &dev_info.tx_desc_lim);
                if (ret != 0)
                        return ret;
        }

        bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &=
                        internals->flow_type_rss_offloads;

        if (slave_rte_flow_prepare(internals->slave_count, internals) != 0) {
                RTE_BOND_LOG(ERR, "Failed to prepare new slave flows: port=%d",
                             slave_port_id);
                return -1;
        }

        /* Add additional MAC addresses to the slave */
        if (slave_add_mac_addresses(bonded_eth_dev, slave_port_id) != 0) {
                RTE_BOND_LOG(ERR, "Failed to add mac address(es) to slave %hu",
                                slave_port_id);
                return -1;
        }

        internals->slave_count++;

        if (bonded_eth_dev->data->dev_started) {
                if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
                        internals->slave_count--;
                        RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d",
                                        slave_port_id);
                        return -1;
                }
        }

        /* Update all slave devices MACs */
        mac_address_slaves_update(bonded_eth_dev);

        /* 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) {
                ret = rte_eth_link_get_nowait(slave_port_id, &link_props);
                if (ret < 0) {
                        rte_eth_dev_callback_unregister(slave_port_id,
                                        RTE_ETH_EVENT_INTR_LSC,
        /* If bonded device is started then we can add the slave to our active
         * slave array */
        if (bonded_eth_dev->data->dev_started) {
                ret = rte_eth_link_get_nowait(slave_port_id, &link_props);
                if (ret < 0) {
                        rte_eth_dev_callback_unregister(slave_port_id,
                                        RTE_ETH_EVENT_INTR_LSC,
                                        bond_ethdev_lsc_event_callback,
                                        &bonded_eth_dev->data->port_id);
                        internals->slave_count--;
                        RTE_BOND_LOG(ERR,
                                "Slave (port %u) link get failed: %s
",
                                slave_port_id, rte_strerror(-ret));
                        return -1;
                }

                 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);
                }
        }

        /* Add slave details to bonded device */
        slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE;

        slave_vlan_filter_set(bonded_port_id, slave_port_id);

        return 0;

}

eth_bond_slave_inherit_dev_info_rx_next

static void
eth_bond_slave_inherit_dev_info_rx_next(struct bond_dev_private *internals,
                                        const struct rte_eth_dev_info *di)
{
        struct rte_eth_rxconf *rxconf_i = &internals->default_rxconf;
        const struct rte_eth_rxconf *rxconf = &di->default_rxconf;

        internals->rx_offload_capa &= di->rx_offload_capa;
        internals->rx_queue_offload_capa &= di->rx_queue_offload_capa;
        internals->flow_type_rss_offloads &= di->flow_type_rss_offloads;

        /*
         * If at least one slave device suggests enabling this
         * setting by default, enable it for all slave devices
         * since disabling it may not be necessarily supported.
         */
        if (rxconf->rx_drop_en == 1)
                rxconf_i->rx_drop_en = 1;

        /*
         * Adding a new slave device may cause some of previously inherited
         * offloads to be withdrawn from the internal rx_queue_offload_capa
         * value. Thus, the new internal value of default Rx queue offloads
         * has to be masked by rx_queue_offload_capa to make sure that only
         * commonly supported offloads are preserved from both the previous
         * value and the value being inhereted from the new slave device.
         */
        rxconf_i->offloads = (rxconf_i->offloads | rxconf->offloads) &
                             internals->rx_queue_offload_capa;

        /*
         * 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 > di->reta_size)
                internals->reta_size = di->reta_size;

        if (!internals->max_rx_pktlen &&
            di->max_rx_pktlen < internals->candidate_max_rx_pktlen)
                internals->candidate_max_rx_pktlen = di->max_rx_pktlen;
}

primary

bond_ethdev_primary_set(struct bond_dev_private *internals,
                uint16_t slave_port_id)
{
        int i;

        if (internals->active_slave_count < 1)
                internals->current_primary_port = slave_port_id;
        else
                /* Search bonded device slave ports for new proposed primary port */
                for (i = 0; i < internals->active_slave_count; i++) {
                        if (internals->active_slaves[i] == slave_port_id)
                                internals->current_primary_port = slave_port_id;
                }
}
bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
{
        struct bond_dev_private *internals = eth_dev->data->dev_private;
        int i;
        int ret = 0;
        uint16_t port_id;

        switch (internals->mode) {
        /* Promiscuous mode is propagated to all slaves */
        case BONDING_MODE_ROUND_ROBIN:
        case BONDING_MODE_BALANCE:
        case BONDING_MODE_BROADCAST:
        case BONDING_MODE_8023AD: {
                unsigned int slave_ok = 0;

                for (i = 0; i < internals->slave_count; i++) {
                        port_id = internals->slaves[i].port_id;

                        ret = rte_eth_promiscuous_enable(port_id);
                        if (ret != 0)
                                RTE_BOND_LOG(ERR,
                                        "Failed to enable promiscuous mode for port %u: %s",
                                        port_id, rte_strerror(-ret));
                        else
                                slave_ok++;
                }
                /*
                 * Report success if operation is successful on at least
                 * on one slave. Otherwise return last error code.
                 */
                if (slave_ok > 0)
                        ret = 0;
                break;
        }
        /* Promiscuous mode is propagated only to primary slave */
        case BONDING_MODE_ACTIVE_BACKUP:
        case BONDING_MODE_TLB:
        case BONDING_MODE_ALB:
        default:
                /* Do not touch promisc when there cannot be primary ports */
                if (internals->slave_count == 0)
                        break;
                port_id = internals->current_primary_port;
                ret = rte_eth_promiscuous_enable(port_id);
                if (ret != 0)
                        RTE_BOND_LOG(ERR,
                                "Failed to enable promiscuous mode for port %u: %s",
                                port_id, rte_strerror(-ret));
        }

        return ret;
}
原文地址:https://www.cnblogs.com/dream397/p/14870529.html