要实现f-stack bond 功能,
首先是传递参数到dpdk,一般是在config.ini文件添加dpdk_bond=eth_bond0,mode=2,slave=0000:00:04.0,slave=0000:00:05.0,xmit_policy=l34,怎么解析和传给dpdk自己得研究vpp或是ovs代码,实现dpdk bond有两种方法,一种是传上面参数给dpdk,还有一种是调用dpdk相应接口实现bond。
其次是要让bond口向slave口配置port_conf.rxmode.hw_vlan_strip = 1;,原有的代码只是设置了普通接口,bond口没有下发成功到slave口,我选择在bond 驱动文件里设置
最后是获取slave口的mac,设置到bond 口
修改dpdk bond驱动文件文件:rte_eth_bond.c,实现设置slave网口的hw_vlan_strip
int
slave_configure(struct rte_eth_dev *bonded_eth_dev,
struct rte_eth_dev *slave_eth_dev)
{
struct bond_rx_queue *bd_rx_q;
struct bond_tx_queue *bd_tx_q;
uint16_t old_nb_tx_queues = slave_eth_dev->data->nb_tx_queues;
uint16_t old_nb_rx_queues = slave_eth_dev->data->nb_rx_queues;
int errval;
uint16_t q_id;
/* Stop slave */
rte_eth_dev_stop(slave_eth_dev->data->port_id);
/* Enable interrupts on slave device if supported */
if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
slave_eth_dev->data->dev_conf.intr_conf.lsc = 1;
#if 1
if (bonded_eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
{
slave_eth_dev->data->dev_conf.rxmode.hw_vlan_strip = 1;
}
#endif
/* If RSS is enabled for bonding, try to enable it for slaves */
if (bonded_eth_dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
if (bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len
!= 0) {
slave_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len =
bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len;
slave_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key =
bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
} else {
slave_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
}
slave_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
slave_eth_dev->data->dev_conf.rxmode.mq_mode =
bonded_eth_dev->data->dev_conf.rxmode.mq_mode;
}
/* Configure device */
errval = rte_eth_dev_configure(slave_eth_dev->data->port_id,
bonded_eth_dev->data->nb_rx_queues,
bonded_eth_dev->data->nb_tx_queues,
&(slave_eth_dev->data->dev_conf));
if (errval != 0) {
RTE_BOND_LOG(ERR, "Cannot configure slave device: port %u , err (%d)",
slave_eth_dev->data->port_id, errval);
return errval;
}
/* Setup Rx Queues */
/* Use existing queues, if any */
for (q_id = old_nb_rx_queues;
q_id < bonded_eth_dev->data->nb_rx_queues; q_id++) {
bd_rx_q = (struct bond_rx_queue *)bonded_eth_dev->data->rx_queues[q_id];
errval = rte_eth_rx_queue_setup(slave_eth_dev->data->port_id, q_id,
bd_rx_q->nb_rx_desc,
rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
&(bd_rx_q->rx_conf), bd_rx_q->mb_pool);
if (errval != 0) {
RTE_BOND_LOG(ERR,
"rte_eth_rx_queue_setup: port=%d queue_id %d, err (%d)",
slave_eth_dev->data->port_id, q_id, errval);
return errval;
}
}
/* Setup Tx Queues */
/* Use existing queues, if any */
for (q_id = old_nb_tx_queues;
q_id < bonded_eth_dev->data->nb_tx_queues; q_id++) {
bd_tx_q = (struct bond_tx_queue *)bonded_eth_dev->data->tx_queues[q_id];
errval = rte_eth_tx_queue_setup(slave_eth_dev->data->port_id, q_id,
bd_tx_q->nb_tx_desc,
rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
&bd_tx_q->tx_conf);
if (errval != 0) {
RTE_BOND_LOG(ERR,
"rte_eth_tx_queue_setup: port=%d queue_id %d, err (%d)",
slave_eth_dev->data->port_id, q_id, errval);
return errval;
}
}
/* Start device */
errval = rte_eth_dev_start(slave_eth_dev->data->port_id);
if (errval != 0) {
RTE_BOND_LOG(ERR, "rte_eth_dev_start: port=%u, err (%d)",
slave_eth_dev->data->port_id, errval);
return -1;
}
/* If RSS is enabled for bonding, synchronize RETA */
if (bonded_eth_dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS) {
int i;
struct bond_dev_private *internals;
internals = bonded_eth_dev->data->dev_private;
for (i = 0; i < internals->slave_count; i++) {
if (internals->slaves[i].port_id == slave_eth_dev->data->port_id) {
errval = rte_eth_dev_rss_reta_update(
slave_eth_dev->data->port_id,
&internals->reta_conf[0],
internals->slaves[i].reta_size);
if (errval != 0) {
RTE_LOG(WARNING, PMD,
"rte_eth_dev_rss_reta_update on slave port %d fails (err %d)."
" RSS Configuration for bonding may be inconsistent.\n",
slave_eth_dev->data->port_id, errval);
}
break;
}
}
}
/* If lsc interrupt is set, check initial slave's link status */
if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
bond_ethdev_lsc_event_callback(slave_eth_dev->data->port_id,
RTE_ETH_EVENT_INTR_LSC, &bonded_eth_dev->data->port_id);
return 0;
}
修改f-stack lib文件:ff_dpdk_if.c,设置bond口的hw_vlan_strip,将第一个slave口的mac设置到bond 口
static int
init_port_start(void)
{
int nb_ports = ff_global_cfg.dpdk.nb_ports;
uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs;
unsigned socketid = rte_lcore_to_socket_id(rte_lcore_id());
struct rte_mempool *mbuf_pool = pktmbuf_pool[socketid];
uint16_t i;
printf("-------->[%s]:[%d] rte_eth_dev_count()= %d\n", __func__, __LINE__, rte_eth_dev_count());
for (i = 0; i < nb_ports; i++) {
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[i].port_id;
struct rte_eth_dev_info dev_info;
rte_eth_dev_info_get(port_id, &dev_info);
#if 1
if (strncmp (dev_info.driver_name, "rte_bond_pmd", 12) == 0)
{
dev_info.rx_offload_capa |= DEV_RX_OFFLOAD_VLAN_STRIP;
dev_info.tx_offload_capa |= DEV_TX_OFFLOAD_VLAN_INSERT;
}
#endif
if (nb_procs > dev_info.max_rx_queues) {
rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_rx_queues[%d]\n",
nb_procs,
dev_info.max_rx_queues);
}
if (nb_procs > dev_info.max_tx_queues) {
rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_tx_queues[%d]\n",
nb_procs,
dev_info.max_tx_queues);
}
struct ether_addr addr;
rte_eth_macaddr_get(port_id, &addr);
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
(unsigned)port_id,
addr.addr_bytes[0], addr.addr_bytes[1],
addr.addr_bytes[2], addr.addr_bytes[3],
addr.addr_bytes[4], addr.addr_bytes[5]);
rte_memcpy(ff_global_cfg.dpdk.port_cfgs[i].mac,
addr.addr_bytes, ETHER_ADDR_LEN);
/* Clear txq_flags - we do not need multi-mempool and refcnt */
dev_info.default_txconf.txq_flags = ETH_TXQ_FLAGS_NOMULTMEMP |
ETH_TXQ_FLAGS_NOREFCOUNT;
/* Disable features that are not supported by port's HW */
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMUDP;
}
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMTCP;
}
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP;
}
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOVLANOFFL;
}
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOVLANOFFL;
}
if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) &&
!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO)) {
dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
}
struct rte_eth_conf port_conf = {0};
#if 1
/* Set RSS mode */
port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_PROTO_MASK;
port_conf.rx_adv_conf.rss_conf.rss_key = default_rsskey_40bytes;
port_conf.rx_adv_conf.rss_conf.rss_key_len = 40;
#endif
printf("-------->[%s]:[%d]\n", __func__, __LINE__);
/* Set Rx VLAN stripping */
if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
printf("-------->[%s]:[%d]\n", __func__, __LINE__);
port_conf.rxmode.hw_vlan_strip = 1;
}
/* Enable HW CRC stripping */
port_conf.rxmode.hw_strip_crc = 1;
/* FIXME: Enable TCP LRO ?*/
#if 0
if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
printf("LRO is supported\n");
port_conf.rxmode.enable_lro = 1;
ff_global_cfg.dpdk.port_cfgs[i].hw_features.rx_lro = 1;
}
#endif
/* Set Rx checksum checking */
if ((dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) &&
(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) &&
(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) {
printf("RX checksum offload supported\n");
port_conf.rxmode.hw_ip_checksum = 1;
ff_global_cfg.dpdk.port_cfgs[i].hw_features.rx_csum = 1;
}
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
printf("TX ip checksum offload supported\n");
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_csum_ip = 1;
}
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) &&
(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) {
printf("TX TCP&UDP checksum offload supported\n");
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_csum_l4 = 1;
}
if (ff_global_cfg.dpdk.tso) {
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
printf("TSO is supported\n");
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_tso = 1;
}
} else {
printf("TSO is disabled\n");
}
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
return 0;
}
/* Currently, proc id 1:1 map to queue id per port. */
int ret = rte_eth_dev_configure(port_id, nb_procs, nb_procs, &port_conf);
if (ret != 0) {
return ret;
}
uint16_t q;
for (q = 0; q < nb_procs; q++) {
ret = rte_eth_tx_queue_setup(port_id, q, TX_QUEUE_SIZE,
socketid, &dev_info.default_txconf);
if (ret < 0) {
return ret;
}
ret = rte_eth_rx_queue_setup(port_id, q, RX_QUEUE_SIZE,
socketid, &dev_info.default_rxconf, mbuf_pool);
if (ret < 0) {
return ret;
}
}
if (strncmp (dev_info.driver_name, "rte_bond_pmd", 12) == 0)
{
unsigned char slink[16];
int nlink = rte_eth_bond_slaves_get (port_id, slink, 16);
if (nlink > 0)
{
int rv;
unsigned char addr[6];
/* Get MAC of 1st slave link */
rte_eth_macaddr_get (slink[0],
(struct ether_addr *) addr);
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
(unsigned)port_id,
addr[0], addr[1],
addr[2], addr[3],
addr[4], addr[5]);
/* Set MAC of bounded interface to that of 1st slave link */
rv =
rte_eth_bond_mac_address_set (port_id,
(struct ether_addr *)
addr);
if (rv < 0)
rte_exit(EXIT_FAILURE, "Failed to set MAC address");
}
printf("-------->[%s]:[%d] nlink = %d\n", __func__, __LINE__, nlink);
rte_eth_macaddr_get(port_id, &addr);
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
(unsigned)port_id,
addr.addr_bytes[0], addr.addr_bytes[1],
addr.addr_bytes[2], addr.addr_bytes[3],
addr.addr_bytes[4], addr.addr_bytes[5]);
rte_memcpy(ff_global_cfg.dpdk.port_cfgs[i].mac,
addr.addr_bytes, ETHER_ADDR_LEN);
}
ret = rte_eth_dev_start(port_id);
if (ret < 0) {
return ret;
}
/* Enable RX in promiscuous mode for the Ethernet device. */
if (ff_global_cfg.dpdk.promiscuous) {
rte_eth_promiscuous_enable(port_id);
ret = rte_eth_promiscuous_get(port_id);
if (ret == 1) {
printf("set port %u to promiscuous mode ok\n", port_id);
} else {
printf("set port %u to promiscuous mode error\n", port_id);
}
}
/* Enable pcap dump */
if (ff_global_cfg.dpdk.port_cfgs[i].pcap) {
ff_enable_pcap(ff_global_cfg.dpdk.port_cfgs[i].pcap);
}
}
return 0;
}