X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Fbnxt_filter.c;fp=drivers%2Fnet%2Fbnxt%2Fbnxt_filter.c;h=e36da9977154d05afd96eb86d472d81e37d0e076;hb=15dedf321036ae67c61f35a3ab55de767b07801f;hp=032e8eed00aba4ecee3fe0e0513f4b0cd5fd1aa0;hpb=9f3a8cb4cfe59ea63e267f69700fb0fde13d7dd3;p=deb_dpdk.git diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c index 032e8eed..e36da997 100644 --- a/drivers/net/bnxt/bnxt_filter.c +++ b/drivers/net/bnxt/bnxt_filter.c @@ -1,38 +1,11 @@ -/*- - * BSD LICENSE - * - * Copyright(c) Broadcom Limited. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Broadcom Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2014-2018 Broadcom + * All rights reserved. */ #include +#include #include #include #include @@ -96,9 +69,9 @@ void bnxt_init_filters(struct bnxt *bp) STAILQ_INIT(&bp->free_filter_list); for (i = 0; i < max_filters; i++) { filter = &bp->filter_info[i]; - filter->fw_l2_filter_id = -1; - filter->fw_em_filter_id = -1; - filter->fw_ntuple_filter_id = -1; + filter->fw_l2_filter_id = UINT64_MAX; + filter->fw_em_filter_id = UINT64_MAX; + filter->fw_ntuple_filter_id = UINT64_MAX; STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); } } @@ -159,6 +132,14 @@ void bnxt_free_filter_mem(struct bnxt *bp) rte_free(bp->filter_info); bp->filter_info = NULL; + + for (i = 0; i < bp->pf.max_vfs; i++) { + STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) { + rte_free(filter); + STAILQ_REMOVE(&bp->pf.vf_info[i].filter, filter, + bnxt_filter_info, next); + } + } } int bnxt_alloc_filter_mem(struct bnxt *bp) @@ -250,7 +231,7 @@ nxt_non_void_action(const struct rte_flow_action *cur) } } -int check_zero_bytes(const uint8_t *bytes, int len) +int bnxt_check_zero_bytes(const uint8_t *bytes, int len) { int i; for (i = 0; i < len; i++) @@ -302,6 +283,7 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[], static int bnxt_validate_and_parse_flow_type(struct bnxt *bp, + const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], struct rte_flow_error *error, struct bnxt_filter_info *filter) @@ -326,6 +308,7 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, uint32_t vf = 0; int use_ntuple; uint32_t en = 0; + uint32_t en_ethertype; int dflt_vnic; use_ntuple = bnxt_filter_type_check(pattern, error); @@ -335,6 +318,9 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, filter->filter_type = use_ntuple ? HWRM_CFA_NTUPLE_FILTER : HWRM_CFA_EM_FILTER; + en_ethertype = use_ntuple ? + NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE : + EM_FLOW_ALLOC_INPUT_EN_ETHERTYPE; while (item->type != RTE_FLOW_ITEM_TYPE_END) { if (item->last) { @@ -354,8 +340,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } switch (item->type) { case RTE_FLOW_ITEM_TYPE_ETH: - eth_spec = (const struct rte_flow_item_eth *)item->spec; - eth_mask = (const struct rte_flow_item_eth *)item->mask; + eth_spec = item->spec; + eth_mask = item->mask; /* Source MAC address mask cannot be partially set. * Should be All 0's or all 1's. @@ -374,7 +360,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } /* Mask is not allowed. Only exact matches are */ - if ((eth_mask->type & UINT16_MAX) != UINT16_MAX) { + if (eth_mask->type && + eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -400,41 +387,58 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, * RTE_LOG(ERR, PMD, "Handle this condition\n"); * } */ - if (eth_spec->type) { + if (eth_mask->type) { filter->ethertype = rte_be_to_cpu_16(eth_spec->type); - en |= use_ntuple ? - NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE : - EM_FLOW_ALLOC_INPUT_EN_ETHERTYPE; + en |= en_ethertype; } break; case RTE_FLOW_ITEM_TYPE_VLAN: - vlan_spec = - (const struct rte_flow_item_vlan *)item->spec; - vlan_mask = - (const struct rte_flow_item_vlan *)item->mask; - if (vlan_mask->tci & 0xFFFF && !vlan_mask->tpid) { + vlan_spec = item->spec; + vlan_mask = item->mask; + if (en & en_ethertype) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "VLAN TPID matching is not" + " supported"); + return -rte_errno; + } + if (vlan_mask->tci && + vlan_mask->tci == RTE_BE16(0x0fff)) { /* Only the VLAN ID can be matched. */ filter->l2_ovlan = rte_be_to_cpu_16(vlan_spec->tci & - 0xFFF); + RTE_BE16(0x0fff)); en |= EM_FLOW_ALLOC_INPUT_EN_OVLAN_VID; - } else { + } else if (vlan_mask->tci) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "VLAN mask is invalid"); return -rte_errno; } + if (vlan_mask->inner_type && + vlan_mask->inner_type != RTE_BE16(0xffff)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "inner ethertype mask not" + " valid"); + return -rte_errno; + } + if (vlan_mask->inner_type) { + filter->ethertype = + rte_be_to_cpu_16(vlan_spec->inner_type); + en |= en_ethertype; + } break; case RTE_FLOW_ITEM_TYPE_IPV4: /* If mask is not involved, we could use EM filters. */ - ipv4_spec = - (const struct rte_flow_item_ipv4 *)item->spec; - ipv4_mask = - (const struct rte_flow_item_ipv4 *)item->mask; + ipv4_spec = item->spec; + ipv4_mask = item->mask; /* Only IP DST and SRC fields are maskable. */ if (ipv4_mask->hdr.version_ihl || ipv4_mask->hdr.type_of_service || @@ -483,10 +487,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } break; case RTE_FLOW_ITEM_TYPE_IPV6: - ipv6_spec = - (const struct rte_flow_item_ipv6 *)item->spec; - ipv6_mask = - (const struct rte_flow_item_ipv6 *)item->mask; + ipv6_spec = item->spec; + ipv6_mask = item->mask; /* Only IP DST and SRC fields are maskable. */ if (ipv6_mask->hdr.vtc_flow || @@ -510,13 +512,15 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, ipv6_spec->hdr.src_addr, 16); rte_memcpy(filter->dst_ipaddr, ipv6_spec->hdr.dst_addr, 16); - if (!check_zero_bytes(ipv6_mask->hdr.src_addr, 16)) { + if (!bnxt_check_zero_bytes(ipv6_mask->hdr.src_addr, + 16)) { rte_memcpy(filter->src_ipaddr_mask, ipv6_mask->hdr.src_addr, 16); en |= !use_ntuple ? 0 : NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK; } - if (!check_zero_bytes(ipv6_mask->hdr.dst_addr, 16)) { + if (!bnxt_check_zero_bytes(ipv6_mask->hdr.dst_addr, + 16)) { rte_memcpy(filter->dst_ipaddr_mask, ipv6_mask->hdr.dst_addr, 16); en |= !use_ntuple ? 0 : @@ -527,8 +531,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6; break; case RTE_FLOW_ITEM_TYPE_TCP: - tcp_spec = (const struct rte_flow_item_tcp *)item->spec; - tcp_mask = (const struct rte_flow_item_tcp *)item->mask; + tcp_spec = item->spec; + tcp_mask = item->mask; /* Check TCP mask. Only DST & SRC ports are maskable */ if (tcp_mask->hdr.sent_seq || @@ -564,8 +568,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } break; case RTE_FLOW_ITEM_TYPE_UDP: - udp_spec = (const struct rte_flow_item_udp *)item->spec; - udp_mask = (const struct rte_flow_item_udp *)item->mask; + udp_spec = item->spec; + udp_mask = item->mask; if (udp_mask->hdr.dgram_len || udp_mask->hdr.dgram_cksum) { @@ -597,10 +601,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } break; case RTE_FLOW_ITEM_TYPE_VXLAN: - vxlan_spec = - (const struct rte_flow_item_vxlan *)item->spec; - vxlan_mask = - (const struct rte_flow_item_vxlan *)item->mask; + vxlan_spec = item->spec; + vxlan_mask = item->mask; /* Check if VXLAN item is used to describe protocol. * If yes, both spec and mask should be NULL. * If no, both spec and mask shouldn't be NULL. @@ -646,10 +648,8 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } break; case RTE_FLOW_ITEM_TYPE_NVGRE: - nvgre_spec = - (const struct rte_flow_item_nvgre *)item->spec; - nvgre_mask = - (const struct rte_flow_item_nvgre *)item->mask; + nvgre_spec = item->spec; + nvgre_mask = item->mask; /* Check if NVGRE item is used to describe protocol. * If yes, both spec and mask should be NULL. * If no, both spec and mask shouldn't be NULL. @@ -692,7 +692,7 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } break; case RTE_FLOW_ITEM_TYPE_VF: - vf_spec = (const struct rte_flow_item_vf *)item->spec; + vf_spec = item->spec; vf = vf_spec->id; if (!BNXT_PF(bp)) { rte_flow_error_set(error, EINVAL, @@ -710,6 +710,16 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, return -rte_errno; } + if (!attr->transfer) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Matching VF traffic without" + " affecting it (transfer attribute)" + " is unsupported"); + return -rte_errno; + } + filter->mirror_vnic_id = dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf); if (dflt_vnic < 0) { @@ -836,7 +846,8 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, goto ret; } - rc = bnxt_validate_and_parse_flow_type(bp, pattern, error, filter); + rc = bnxt_validate_and_parse_flow_type(bp, attr, pattern, error, + filter); if (rc != 0) goto ret; @@ -844,7 +855,8 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, if (rc != 0) goto ret; //Since we support ingress attribute only - right now. - filter->flags = HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX; + if (filter->filter_type == HWRM_CFA_EM_FILTER) + filter->flags = HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX; switch (act->type) { case RTE_FLOW_ACTION_TYPE_QUEUE: @@ -956,11 +968,6 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, goto ret; } - if (filter1) { - bnxt_free_filter(bp, filter1); - filter1->fw_l2_filter_id = -1; - } - act = nxt_non_void_action(++act); if (act->type != RTE_FLOW_ACTION_TYPE_END) { rte_flow_error_set(error, EINVAL, @@ -997,7 +1004,7 @@ bnxt_flow_validate(struct rte_eth_dev *dev, ret = bnxt_validate_and_parse_flow(dev, pattern, actions, attr, error, filter); /* No need to hold on to this filter if we are just validating flow */ - filter->fw_l2_filter_id = -1; + filter->fw_l2_filter_id = UINT64_MAX; bnxt_free_filter(bp, filter); return ret; @@ -1186,8 +1193,8 @@ bnxt_flow_destroy(struct rte_eth_dev *dev, ret = bnxt_hwrm_clear_em_filter(bp, filter); if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER) ret = bnxt_hwrm_clear_ntuple_filter(bp, filter); - - bnxt_hwrm_clear_l2_filter(bp, filter); + else + ret = bnxt_hwrm_clear_l2_filter(bp, filter); if (!ret) { STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next); rte_free(flow);