From: Tonghao Zhang <xiangxia.m....@gmail.com> This patch implements, mostly the dpdk-bond support. vswitchd try to parse devargs as dpdk-bond device. If success, create a bond device and add slave ports to it. And the bond device id will be set to dev->port_id as a normal interface.
* check pci whether it's valid or not. On success, next step. * check whether the dpdk-bond was created. * create a new bond device and add slave ports to it. * update the netdev_dpdk_bond struct. By default, the mode of dpdk-bond device is active-backup. Signed-off-by: Tonghao Zhang <xiangxia.m....@gmail.com> --- lib/netdev-dpdk.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 8cba466..e1285d1 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -143,6 +143,12 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); #define DPDK_ETH_PORT_ID_INVALID RTE_MAX_ETHPORTS #define DPDK_BOND_SLAVE_MAX RTE_MAX_ETHPORTS +#define DPDK_BOND_NAME_MAX (RTE_MAX_ETHPORTS + 10) +#define DPDK_BOND_NAME_FMT "eth_bond%s" + +#define LIST_EACH_VALID_BOND_SLAVE(SLAVES) \ + for (int i = 0; i < DPDK_BOND_SLAVE_MAX && \ + SLAVES[i] != DPDK_ETH_PORT_ID_INVALID; i++) /* DPDK library uses uint16_t for port_id. */ typedef uint16_t dpdk_port_t; @@ -901,6 +907,7 @@ netdev_dpdk_alloc_txq(unsigned int n_txqs) static void netdev_dpdk_bond_init(struct netdev_dpdk *dev); static void netdev_dpdk_bond_uninit(struct netdev_dpdk *dev); +static void netdev_dpdk_bond_slave_del(dpdk_port_t bp, dpdk_port_t *rs); static int common_construct(struct netdev *netdev, dpdk_port_t port_no, @@ -1396,20 +1403,171 @@ netdev_dpdk_get_port_by_mac(const char *mac_str) } static void +netdev_dpdk_bond_slave_init(dpdk_port_t *s) +{ + for (int i = 0; i < DPDK_BOND_SLAVE_MAX; i++) { + s[i] = DPDK_ETH_PORT_ID_INVALID; + } +} + +static void netdev_dpdk_bond_init(struct netdev_dpdk *dev) { dev->bond = xmalloc(sizeof *dev->bond); dev->bond->name = NULL; dev->bond->mode = MODE_ACTIVE_BACKUP; + + netdev_dpdk_bond_slave_init(dev->bond->slaves); } static void netdev_dpdk_bond_uninit(struct netdev_dpdk *dev) { + /* The interface may be created as bond device. + * Try to release it as a bond device. */ + netdev_dpdk_bond_slave_del(dev->port_id, dev->bond->slaves); + rte_eth_bond_free(dev->bond->name); + free(dev->bond->name); free(dev->bond); } +/* Check the PCIs or device names requested whether + * it's valid or not. */ +static bool +netdev_dpdk_bond_slave_request(const struct netdev_dpdk *dev OVS_UNUSED, + const char *devargs, dpdk_port_t *rs) +{ + dpdk_port_t port_id = DPDK_ETH_PORT_ID_INVALID; + char *pci = NULL, *save_ptr = NULL; + char *args = xstrdup(devargs); + int i; + + netdev_dpdk_bond_slave_init(rs); + + for (pci = strtok_r(args, ",", &save_ptr), i = 0; + pci != NULL; pci = strtok_r(NULL, ",", &save_ptr), i++) { + + if (rte_eth_dev_get_port_by_name(pci, &port_id) || + !rte_eth_dev_is_valid_port(port_id)) { + + VLOG_INFO("Could not get the port id from pci address " + "or device name: %s, or the device is not attached, " + "or has been used by openvswitch.\n", pci); + free(args); + return false; + } + + rs[i] = port_id; + } + + free(args); + return true; +} + +static bool +netdev_dpdk_bond_slave_eq(dpdk_port_t *a, dpdk_port_t *b) +{ + return memcmp(a, b, DPDK_BOND_SLAVE_MAX * sizeof(*a)) == 0; +} + +static void +netdev_dpdk_bond_update(struct netdev_dpdk *dev, + char *namebuf, dpdk_port_t *rs) +{ + memcpy(dev->bond->slaves, rs, + DPDK_BOND_SLAVE_MAX * sizeof(*rs)); + + free(dev->bond->name); + dev->bond->name = xstrdup(namebuf); +} + +static void +netdev_dpdk_bond_slave_del(dpdk_port_t bp, dpdk_port_t *rs) +{ + LIST_EACH_VALID_BOND_SLAVE(rs) { + rte_eth_bond_slave_remove(bp, rs[i]); + } +} + +static int +netdev_dpdk_bond_slave_add(dpdk_port_t bp, dpdk_port_t *rs) +{ + LIST_EACH_VALID_BOND_SLAVE(rs) { + if (rte_eth_bond_slave_add(bp, rs[i])) { + goto out; + } + } + + return true; + +out: + netdev_dpdk_bond_slave_del(bp, rs); + return false; +} + +static char * +netdev_dpdk_bond_name_key(char *key, dpdk_port_t *rs) +{ + LIST_EACH_VALID_BOND_SLAVE(rs) { + key[i] = '0' + rs[i]; + } + + return key; +} + +/* Try to parse devargs as dpdk-bond device. If success, + * create a bond device and add slave ports to it. And the + * bond devcie id will be set to dev->port_id as a normal + * interface. */ +static dpdk_port_t +netdev_dpdk_bond_devargs(struct netdev_dpdk *dev, const char *devargs) +{ + dpdk_port_t request_slaves[DPDK_BOND_SLAVE_MAX]; + char namebuf[DPDK_BOND_NAME_MAX]; + char namekey[DPDK_BOND_NAME_MAX]; + int bond_port; + + if (!netdev_dpdk_bond_slave_request(dev, devargs, request_slaves)) { + return DPDK_ETH_PORT_ID_INVALID; + } + + if (netdev_dpdk_bond_slave_eq(dev->bond->slaves, request_slaves)) { + /* Already created, return its id directly. */ + return dev->port_id; + } + + snprintf(namebuf, sizeof(namebuf) - 1, + DPDK_BOND_NAME_FMT, + netdev_dpdk_bond_name_key(namekey, request_slaves)); + + bond_port = rte_eth_bond_create(namebuf, + dev->bond->mode, + rte_socket_id()); + + if (bond_port < 0) { + VLOG_INFO("Try to new a bond device with name: %s, but failed.\n", + namebuf); + return DPDK_ETH_PORT_ID_INVALID; + } + + if (!netdev_dpdk_bond_slave_add(bond_port, request_slaves)) { + VLOG_INFO("Add slave ports to new bond device, but failed.\n"); + + rte_eth_bond_free(namebuf); + return DPDK_ETH_PORT_ID_INVALID; + } + + /* Free the old slave ports and master port. */ + netdev_dpdk_bond_slave_del(dev->port_id, dev->bond->slaves); + rte_eth_bond_free(dev->bond->name); + + netdev_dpdk_bond_update(dev, namebuf, request_slaves); + + /* Do not update: dev->port_id = bond_port. */ + return bond_port; +} + /* * Normally, a PCI id is enough for identifying a specific DPDK port. * However, for some NICs having multiple ports sharing the same PCI @@ -1439,8 +1597,8 @@ netdev_dpdk_process_devargs(struct netdev_dpdk *dev, dev->attached = true; VLOG_INFO("Device '%s' attached to DPDK", devargs); } else { - /* Attach unsuccessful */ - new_port_id = DPDK_ETH_PORT_ID_INVALID; + /* Try to parse it as dpdk-bond args. */ + new_port_id = netdev_dpdk_bond_devargs(dev, devargs); } } free(name); -- 1.8.3.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev