From 7a5b0874440e780074204f17927b874c78cb3e35 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Thu, 1 Jun 2017 12:07:20 -0500 Subject: [PATCH] net/bnxt: support to add a VF MAC address This patch adds support to allocate a filter and program it in the hardware for every MAC address added to the specified function. Signed-off-by: Stephen Hurd Signed-off-by: Ajit Khaparde --- drivers/net/bnxt/bnxt_filter.c | 22 +++++++ drivers/net/bnxt/bnxt_filter.h | 1 + drivers/net/bnxt/rte_pmd_bnxt.c | 76 +++++++++++++++++++++++ drivers/net/bnxt/rte_pmd_bnxt.h | 18 ++++++ drivers/net/bnxt/rte_pmd_bnxt_version.map | 1 + 5 files changed, 118 insertions(+) diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c index 0afde86481..e9aac27148 100644 --- a/drivers/net/bnxt/bnxt_filter.c +++ b/drivers/net/bnxt/bnxt_filter.c @@ -68,6 +68,22 @@ struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp) return filter; } +struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf) +{ + struct bnxt_filter_info *filter; + + filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0); + if (!filter) { + RTE_LOG(ERR, PMD, "Failed to alloc memory for VF %hu filters\n", + vf); + return NULL; + } + + filter->fw_l2_filter_id = UINT64_MAX; + STAILQ_INSERT_TAIL(&bp->pf.vf_info[vf].filter, filter, next); + return filter; +} + void bnxt_init_filters(struct bnxt *bp) { struct bnxt_filter_info *filter; @@ -102,6 +118,12 @@ void bnxt_free_all_filters(struct bnxt *bp) STAILQ_INIT(&vnic->filter); } } + + for (i = 0; i < bp->pf.max_vfs; i++) { + STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) { + bnxt_hwrm_clear_filter(bp, filter); + } + } } void bnxt_free_filter_mem(struct bnxt *bp) diff --git a/drivers/net/bnxt/bnxt_filter.h b/drivers/net/bnxt/bnxt_filter.h index 353b7f774a..613b2eeacb 100644 --- a/drivers/net/bnxt/bnxt_filter.h +++ b/drivers/net/bnxt/bnxt_filter.h @@ -68,6 +68,7 @@ struct bnxt_filter_info { }; struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp); +struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf); void bnxt_init_filters(struct bnxt *bp); void bnxt_free_all_filters(struct bnxt *bp); void bnxt_free_filter_mem(struct bnxt *bp); diff --git a/drivers/net/bnxt/rte_pmd_bnxt.c b/drivers/net/bnxt/rte_pmd_bnxt.c index 39428a84b0..59bd1ff301 100644 --- a/drivers/net/bnxt/rte_pmd_bnxt.c +++ b/drivers/net/bnxt/rte_pmd_bnxt.c @@ -568,3 +568,79 @@ int rte_pmd_bnxt_get_vf_tx_drop_count(uint8_t port, uint16_t vf_id, return bnxt_hwrm_func_qstats_tx_drop(bp, bp->pf.first_vf_id + vf_id, count); } + +int rte_pmd_bnxt_mac_addr_add(uint8_t port, struct ether_addr *addr, + uint32_t vf_id) +{ + struct rte_eth_dev *dev; + struct rte_eth_dev_info dev_info; + struct bnxt *bp; + struct bnxt_filter_info *filter; + struct bnxt_vnic_info vnic; + struct ether_addr dflt_mac; + int rc; + + dev = &rte_eth_devices[port]; + if (!is_bnxt_supported(dev)) + return -ENOTSUP; + + rte_eth_dev_info_get(port, &dev_info); + bp = (struct bnxt *)dev->data->dev_private; + + if (vf_id >= dev_info.max_vfs) + return -EINVAL; + + if (!BNXT_PF(bp)) { + RTE_LOG(ERR, PMD, + "Attempt to config VF %d MAC on non-PF port %d!\n", + vf_id, port); + return -ENOTSUP; + } + + /* If the VF currently uses a random MAC, update default to this one */ + if (bp->pf.vf_info[vf_id].random_mac) { + if (rte_pmd_bnxt_get_vf_rx_status(port, vf_id) <= 0) + rc = bnxt_hwrm_func_vf_mac(bp, vf_id, (uint8_t *)addr); + } + + /* query the default VNIC id used by the function */ + rc = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf_id); + if (rc < 0) + goto exit; + + memset(&vnic, 0, sizeof(struct bnxt_vnic_info)); + vnic.fw_vnic_id = rte_le_to_cpu_16(rc); + rc = bnxt_hwrm_vnic_qcfg(bp, &vnic, bp->pf.first_vf_id + vf_id); + if (rc < 0) + goto exit; + + STAILQ_FOREACH(filter, &bp->pf.vf_info[vf_id].filter, next) { + if (filter->flags == + HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX && + filter->enables == + (HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | + HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK) && + memcmp(addr, filter->l2_addr, ETHER_ADDR_LEN) == 0) { + bnxt_hwrm_clear_filter(bp, filter); + break; + } + } + + if (filter == NULL) + filter = bnxt_alloc_vf_filter(bp, vf_id); + + filter->fw_l2_filter_id = UINT64_MAX; + filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; + filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | + HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK; + memcpy(filter->l2_addr, addr, ETHER_ADDR_LEN); + memset(filter->l2_addr_mask, 0xff, ETHER_ADDR_LEN); + + /* Do not add a filter for the default MAC */ + if (bnxt_hwrm_func_qcfg_vf_default_mac(bp, vf_id, &dflt_mac) || + memcmp(filter->l2_addr, dflt_mac.addr_bytes, ETHER_ADDR_LEN)) + rc = bnxt_hwrm_set_filter(bp, vnic.fw_vnic_id, filter); + +exit: + return rc; +} diff --git a/drivers/net/bnxt/rte_pmd_bnxt.h b/drivers/net/bnxt/rte_pmd_bnxt.h index 0987c0f014..a523a956bd 100644 --- a/drivers/net/bnxt/rte_pmd_bnxt.h +++ b/drivers/net/bnxt/rte_pmd_bnxt.h @@ -250,4 +250,22 @@ int rte_pmd_bnxt_get_vf_rx_status(uint8_t port, uint16_t vf_id); */ int rte_pmd_bnxt_get_vf_tx_drop_count(uint8_t port, uint16_t vf_id, uint64_t *count); + +/** + * Programs the MAC address for the function specified + * + * @param port + * The port identifier of the Ethernet device. + * @param mac_addr + * The MAC address to be programmed in the filter. + * @param vf_id + * VF on which to get. + * @return + * - Positive Non-zero value - Error code from HWRM + * - (-EINVAL) invalid vf_id specified. + * - (-ENOTSUP) Ethernet device is not a PF + * - (-ENOMEM) on an allocation failure + */ +int rte_pmd_bnxt_mac_addr_add(uint8_t port, struct ether_addr *mac_addr, + uint32_t vf_id); #endif /* _PMD_BNXT_H_ */ diff --git a/drivers/net/bnxt/rte_pmd_bnxt_version.map b/drivers/net/bnxt/rte_pmd_bnxt_version.map index c9e53f5dd5..803c6f2a69 100644 --- a/drivers/net/bnxt/rte_pmd_bnxt_version.map +++ b/drivers/net/bnxt/rte_pmd_bnxt_version.map @@ -4,6 +4,7 @@ DPDK_17.08 { rte_pmd_bnxt_get_vf_rx_status; rte_pmd_bnxt_get_vf_stats; rte_pmd_bnxt_get_vf_tx_drop_count; + rte_pmd_bnxt_mac_addr_add; rte_pmd_bnxt_reset_vf_stats; rte_pmd_bnxt_set_all_queues_drop_en; rte_pmd_bnxt_set_tx_loopback; -- 2.20.1