From e0947ed912f7d1f0bed79080d947f21504ed40ab Mon Sep 17 00:00:00 2001 From: Harish Patil Date: Wed, 18 Oct 2017 18:13:30 -0700 Subject: [PATCH] net/qede: add support for VXLAN UDP port config over VF - Allow VXLAN enable/disable over VF using udp_tunnel_port_add/del APIs. Only default MAC/VLAN classification is supported. - Enable VxLAN before UDP port configuration. - Change VxLAN default UDP port to 4789 instead of 8472. Signed-off-by: Harish Patil --- drivers/net/qede/qede_ethdev.c | 197 ++++++++++++++++++++------------- drivers/net/qede/qede_ethdev.h | 11 +- 2 files changed, 128 insertions(+), 80 deletions(-) diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c index dc67bfda9b..75690d94dc 100644 --- a/drivers/net/qede/qede_ethdev.c +++ b/drivers/net/qede/qede_ethdev.c @@ -602,15 +602,45 @@ qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev, return ecore_filter_accept_cmd(edev, 0, flags, false, false, ECORE_SPQ_MODE_CB, NULL); } -static void qede_set_cmn_tunn_param(struct ecore_tunnel_info *p_tunn, - uint8_t clss, bool mode, bool mask) + +static int +qede_vxlan_enable(struct rte_eth_dev *eth_dev, uint8_t clss, + bool enable, bool mask) { - memset(p_tunn, 0, sizeof(struct ecore_tunnel_info)); - p_tunn->vxlan.b_update_mode = mode; - p_tunn->vxlan.b_mode_enabled = mask; - p_tunn->b_update_rx_cls = true; - p_tunn->b_update_tx_cls = true; - p_tunn->vxlan.tun_cls = clss; + struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); + struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); + enum _ecore_status_t rc = ECORE_INVAL; + struct ecore_ptt *p_ptt; + struct ecore_tunnel_info tunn; + struct ecore_hwfn *p_hwfn; + int i; + + memset(&tunn, 0, sizeof(struct ecore_tunnel_info)); + tunn.vxlan.b_update_mode = enable; + tunn.vxlan.b_mode_enabled = mask; + tunn.b_update_rx_cls = true; + tunn.b_update_tx_cls = true; + tunn.vxlan.tun_cls = clss; + + for_each_hwfn(edev, i) { + p_hwfn = &edev->hwfns[i]; + p_ptt = IS_PF(edev) ? ecore_ptt_acquire(p_hwfn) : NULL; + rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, + &tunn, ECORE_SPQ_MODE_CB, NULL); + if (rc != ECORE_SUCCESS) { + DP_ERR(edev, "Failed to update tunn_clss %u\n", + tunn.vxlan.tun_cls); + break; + } + } + + if (rc == ECORE_SUCCESS) { + qdev->vxlan.enable = enable; + qdev->vxlan.udp_port = (enable) ? QEDE_VXLAN_DEF_PORT : 0; + DP_INFO(edev, "vxlan is %s\n", enable ? "enabled" : "disabled"); + } + + return rc; } static int @@ -2172,19 +2202,51 @@ qede_conf_udp_dst_port(struct rte_eth_dev *eth_dev, struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); struct ecore_tunnel_info tunn; /* @DPDK */ struct ecore_hwfn *p_hwfn; + struct ecore_ptt *p_ptt; + uint16_t udp_port; int rc, i; PMD_INIT_FUNC_TRACE(edev); memset(&tunn, 0, sizeof(tunn)); if (tunnel_udp->prot_type == RTE_TUNNEL_TYPE_VXLAN) { + /* Enable VxLAN tunnel if needed before UDP port update using + * default MAC/VLAN classification. + */ + if (add) { + if (qdev->vxlan.udp_port == tunnel_udp->udp_port) { + DP_INFO(edev, + "UDP port %u was already configured\n", + tunnel_udp->udp_port); + return ECORE_SUCCESS; + } + /* Enable VXLAN if it was not enabled while adding + * VXLAN filter. + */ + if (!qdev->vxlan.enable) { + rc = qede_vxlan_enable(eth_dev, + ECORE_TUNN_CLSS_MAC_VLAN, true, true); + if (rc != ECORE_SUCCESS) { + DP_ERR(edev, "Failed to enable VXLAN " + "prior to updating UDP port\n"); + return rc; + } + } + udp_port = tunnel_udp->udp_port; + } else { + if (qdev->vxlan.udp_port != tunnel_udp->udp_port) { + DP_ERR(edev, "UDP port %u doesn't exist\n", + tunnel_udp->udp_port); + return ECORE_INVAL; + } + udp_port = 0; + } + tunn.vxlan_port.b_update_port = true; - tunn.vxlan_port.port = (add) ? tunnel_udp->udp_port : - QEDE_VXLAN_DEF_PORT; + tunn.vxlan_port.port = udp_port; for_each_hwfn(edev, i) { p_hwfn = &edev->hwfns[i]; - struct ecore_ptt *p_ptt = IS_PF(edev) ? - ecore_ptt_acquire(p_hwfn) : NULL; + p_ptt = IS_PF(edev) ? ecore_ptt_acquire(p_hwfn) : NULL; rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, &tunn, ECORE_SPQ_MODE_CB, NULL); if (rc != ECORE_SUCCESS) { @@ -2195,6 +2257,15 @@ qede_conf_udp_dst_port(struct rte_eth_dev *eth_dev, return rc; } } + + qdev->vxlan.udp_port = udp_port; + /* If the request is to delete UDP port and if the number of + * VXLAN filters have reached 0 then VxLAN offload can be be + * disabled. + */ + if (!add && qdev->vxlan.enable && qdev->vxlan.num_filters == 0) + return qede_vxlan_enable(eth_dev, + ECORE_TUNN_CLSS_MAC_VLAN, false, true); } return 0; @@ -2284,35 +2355,38 @@ static int qede_vxlan_tunn_config(struct rte_eth_dev *eth_dev, { struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); - struct ecore_tunnel_info tunn; - struct ecore_hwfn *p_hwfn; enum ecore_filter_ucast_type type; - enum ecore_tunn_clss clss; - struct ecore_filter_ucast ucast; + enum ecore_tunn_clss clss = MAX_ECORE_TUNN_CLSS; + struct ecore_filter_ucast ucast = {0}; char str[80]; - uint16_t filter_type; - int rc, i; + uint16_t filter_type = 0; + int rc; PMD_INIT_FUNC_TRACE(edev); - filter_type = conf->filter_type | qdev->vxlan_filter_type; - /* First determine if the given filter classification is supported */ - qede_get_ecore_tunn_params(filter_type, &type, &clss, str); - if (clss == MAX_ECORE_TUNN_CLSS) { - DP_ERR(edev, "Wrong filter type\n"); - return -EINVAL; - } - /* Init tunnel ucast params */ - rc = qede_set_ucast_tunn_cmn_param(&ucast, conf, type); - if (rc != ECORE_SUCCESS) { - DP_ERR(edev, "Unsupported VxLAN filter type 0x%x\n", - conf->filter_type); - return rc; - } - DP_INFO(edev, "Rule: \"%s\", op %d, type 0x%x\n", - str, filter_op, ucast.type); switch (filter_op) { case RTE_ETH_FILTER_ADD: + if (IS_VF(edev)) + return qede_vxlan_enable(eth_dev, + ECORE_TUNN_CLSS_MAC_VLAN, true, true); + + filter_type = conf->filter_type; + /* Determine if the given filter classification is supported */ + qede_get_ecore_tunn_params(filter_type, &type, &clss, str); + if (clss == MAX_ECORE_TUNN_CLSS) { + DP_ERR(edev, "Unsupported filter type\n"); + return -EINVAL; + } + /* Init tunnel ucast params */ + rc = qede_set_ucast_tunn_cmn_param(&ucast, conf, type); + if (rc != ECORE_SUCCESS) { + DP_ERR(edev, "Unsupported VxLAN filter type 0x%x\n", + conf->filter_type); + return rc; + } + DP_INFO(edev, "Rule: \"%s\", op %d, type 0x%x\n", + str, filter_op, ucast.type); + ucast.opcode = ECORE_FILTER_ADD; /* Skip MAC/VLAN if filter is based on VNI */ @@ -2332,26 +2406,17 @@ static int qede_vxlan_tunn_config(struct rte_eth_dev *eth_dev, if (rc != ECORE_SUCCESS) return rc; - qdev->vxlan_filter_type = filter_type; + qdev->vxlan.num_filters++; + qdev->vxlan.filter_type = filter_type; + if (!qdev->vxlan.enable) + return qede_vxlan_enable(eth_dev, clss, true, true); - DP_INFO(edev, "Enabling VXLAN tunneling\n"); - qede_set_cmn_tunn_param(&tunn, clss, true, true); - for_each_hwfn(edev, i) { - p_hwfn = &edev->hwfns[i]; - struct ecore_ptt *p_ptt = IS_PF(edev) ? - ecore_ptt_acquire(p_hwfn) : NULL; - rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, - &tunn, ECORE_SPQ_MODE_CB, NULL); - if (rc != ECORE_SUCCESS) { - DP_ERR(edev, "Failed to update tunn_clss %u\n", - tunn.vxlan.tun_cls); - if (IS_PF(edev)) - ecore_ptt_release(p_hwfn, p_ptt); - } - } - qdev->num_tunn_filters++; /* Filter added successfully */ break; case RTE_ETH_FILTER_DELETE: + if (IS_VF(edev)) + return qede_vxlan_enable(eth_dev, + ECORE_TUNN_CLSS_MAC_VLAN, false, true); + ucast.opcode = ECORE_FILTER_REMOVE; if (!(filter_type & ETH_TUNNEL_FILTER_TENID)) { @@ -2365,38 +2430,14 @@ static int qede_vxlan_tunn_config(struct rte_eth_dev *eth_dev, if (rc != ECORE_SUCCESS) return rc; - qdev->vxlan_filter_type = filter_type; - qdev->num_tunn_filters--; - /* Disable VXLAN if VXLAN filters become 0 */ - if (qdev->num_tunn_filters == 0) { - DP_INFO(edev, "Disabling VXLAN tunneling\n"); - - /* Use 0 as tunnel mode */ - qede_set_cmn_tunn_param(&tunn, clss, false, true); - for_each_hwfn(edev, i) { - p_hwfn = &edev->hwfns[i]; - struct ecore_ptt *p_ptt = IS_PF(edev) ? - ecore_ptt_acquire(p_hwfn) : NULL; - rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, - &tunn, ECORE_SPQ_MODE_CB, NULL); - if (rc != ECORE_SUCCESS) { - DP_ERR(edev, - "Failed to update tunn_clss %u\n", - tunn.vxlan.tun_cls); - if (IS_PF(edev)) - ecore_ptt_release(p_hwfn, - p_ptt); - break; - } - } - } + if (qdev->vxlan.num_filters == 0) + return qede_vxlan_enable(eth_dev, clss, false, true); break; default: DP_ERR(edev, "Unsupported operation %d\n", filter_op); return -EINVAL; } - DP_INFO(edev, "Current VXLAN filters %d\n", qdev->num_tunn_filters); return 0; } @@ -2524,6 +2565,8 @@ static const struct eth_dev_ops qede_eth_vf_dev_ops = { .reta_update = qede_rss_reta_update, .reta_query = qede_rss_reta_query, .mtu_set = qede_set_mtu, + .udp_tunnel_port_add = qede_udp_dst_port_add, + .udp_tunnel_port_del = qede_udp_dst_port_del, }; static void qede_update_pf_params(struct ecore_dev *edev) diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h index 4543533c54..3212020ef6 100644 --- a/drivers/net/qede/qede_ethdev.h +++ b/drivers/net/qede/qede_ethdev.h @@ -122,7 +122,6 @@ #define PCI_DEVICE_ID_QLOGIC_AH_IOV CHIP_NUM_AH_IOV -#define QEDE_VXLAN_DEF_PORT 8472 extern char fw_file[]; @@ -171,6 +170,13 @@ struct qede_fdir_info { SLIST_HEAD(fdir_list_head, qede_fdir_entry)fdir_list_head; }; +struct qede_vxlan_tunn { + bool enable; + uint16_t num_filters; + uint16_t filter_type; +#define QEDE_VXLAN_DEF_PORT (4789) + uint16_t udp_port; +}; /* * Structure to store private data for each port. @@ -200,8 +206,7 @@ struct qede_dev { SLIST_HEAD(uc_list_head, qede_ucast_entry) uc_list_head; uint16_t num_uc_addr; bool handle_hw_err; - uint16_t num_tunn_filters; - uint16_t vxlan_filter_type; + struct qede_vxlan_tunn vxlan; struct qede_fdir_info fdir_info; bool vlan_strip_flg; char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE]; -- 2.20.1