From ef34b5b9ab7723bd6e4cfa5eab87a05d8b8a066d Mon Sep 17 00:00:00 2001 From: Sai Rupesh Chevuru Date: Thu, 25 Aug 2022 10:26:44 +0530 Subject: [PATCH] qcacmn: Handling of IGMP packets in MLO Multipass Due to the CCE rule in QCN9224 IGMP packets will be routed to err ring. When multipass is enabled, perform multipass processing before handing over the packet to stack. Change-Id: I50b747710eb3c49eab60c81bbc61e75e2f8650ed CRs-Fixed: 3275888 --- dp/wifi3.0/be/dp_be_rx.c | 8 +++ qdf/inc/qdf_nbuf.h | 3 ++ qdf/linux/src/qdf_nbuf.c | 108 +++++++++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 15 deletions(-) diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index d664e5bc85..2d4fe727c2 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/dp/wifi3.0/be/dp_be_rx.c @@ -1218,6 +1218,14 @@ bool dp_rx_mlo_igmp_handler(struct dp_soc *soc, qdf_nbuf_is_ipv6_igmp_pkt(nbuf))) return false; + if (qdf_unlikely(vdev->multipass_en)) { + if (dp_rx_multipass_process(peer, nbuf, tid) == false) { + DP_PEER_PER_PKT_STATS_INC(peer, + rx.multipass_rx_pkt_drop, 1); + return false; + } + } + if (!peer->bss_peer) { if (dp_rx_intrabss_mcbc_fwd(soc, peer, NULL, nbuf, tid_stats)) dp_rx_err("forwarding failed"); diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index 6c33f0164b..22b91ec00b 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -66,14 +66,17 @@ #define QDF_NBUF_SRC_MAC_OFFSET 6 #define QDF_NBUF_TRAC_IPV4_TOS_OFFSET 15 #define QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET 23 +#define QDF_NBUF_TRAC_VLAN_IPV4_PROTO_TYPE_OFFSET 27 #define QDF_NBUF_TRAC_IPV4_DEST_ADDR_OFFSET 30 #define QDF_NBUF_TRAC_IPV4_SRC_ADDR_OFFSET 26 #define QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET 20 +#define QDF_NBUF_TRAC_VLAN_IPV6_PROTO_TYPE_OFFSET 24 #define QDF_NBUF_TRAC_IPV4_ADDR_MCAST_MASK 0xE0000000 #define QDF_NBUF_TRAC_IPV4_ADDR_BCAST_MASK 0xF0000000 #define QDF_NBUF_TRAC_IPV6_DEST_ADDR_OFFSET 38 #define QDF_NBUF_TRAC_IPV6_DEST_ADDR 0xFF00 #define QDF_NBUF_TRAC_IPV6_OFFSET 14 +#define QDF_NBUF_TRAC_VLAN_IPV6_OFFSET 18 #define QDF_NBUF_TRAC_IPV6_HEADER_SIZE 40 #define QDF_NBUF_TRAC_ICMP_TYPE 1 #define QDF_NBUF_TRAC_IGMP_TYPE 2 diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 5dda67edb0..bd5974b7fe 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -1873,6 +1873,56 @@ bool __qdf_nbuf_is_ipv4_wapi_pkt(struct sk_buff *skb) } qdf_export_symbol(__qdf_nbuf_is_ipv4_wapi_pkt); +/** + * qdf_nbuf_is_ipv6_vlan_pkt() - check wheather packet is vlan IPV6 + * @data: Pointer to network data buffer + * + * This api is for vlan header included ipv6 packet. + * + * Return: true if packet is vlan header included IPV6 + * false otherwise. + */ +static bool qdf_nbuf_is_ipv6_vlan_pkt(uint8_t *data) +{ + uint16_t ether_type; + + ether_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET); + + if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) { + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET); + + if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV6_ETH_TYPE)) + return true; + } + return false; +} + +/** + * qdf_nbuf_is_ipv4_vlan_pkt() - check wheather packet is vlan IPV4 + * @data: Pointer to network data buffer + * + * This api is for vlan header included ipv4 packet. + * + * Return: true if packet is vlan header included IPV4 + * false otherwise. + */ +static bool qdf_nbuf_is_ipv4_vlan_pkt(uint8_t *data) +{ + uint16_t ether_type; + + ether_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET); + + if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) { + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET); + + if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE)) + return true; + } + return false; +} + /** * __qdf_nbuf_data_is_ipv4_igmp_pkt() - check if skb data is a igmp packet * @data: Pointer to network data buffer @@ -1884,15 +1934,26 @@ qdf_export_symbol(__qdf_nbuf_is_ipv4_wapi_pkt); */ bool __qdf_nbuf_data_is_ipv4_igmp_pkt(uint8_t *data) { - if (__qdf_nbuf_data_is_ipv4_pkt(data)) { - uint8_t pkt_type; + uint8_t pkt_type; + if (__qdf_nbuf_data_is_ipv4_pkt(data)) { pkt_type = (uint8_t)(*(uint8_t *)(data + QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET)); - - if (pkt_type == QDF_NBUF_TRAC_IGMP_TYPE) - return true; + goto is_igmp; } + + if (qdf_nbuf_is_ipv4_vlan_pkt(data)) { + pkt_type = (uint8_t)(*(uint8_t *)( + data + + QDF_NBUF_TRAC_VLAN_IPV4_PROTO_TYPE_OFFSET)); + goto is_igmp; + } + + return false; +is_igmp: + if (pkt_type == QDF_NBUF_TRAC_IGMP_TYPE) + return true; + return false; } @@ -1909,21 +1970,38 @@ qdf_export_symbol(__qdf_nbuf_data_is_ipv4_igmp_pkt); */ bool __qdf_nbuf_data_is_ipv6_igmp_pkt(uint8_t *data) { - if (__qdf_nbuf_data_is_ipv6_pkt(data)) { - uint8_t pkt_type; - uint8_t next_hdr; + uint8_t pkt_type; + uint8_t next_hdr; + if (__qdf_nbuf_data_is_ipv6_pkt(data)) { pkt_type = (uint8_t)(*(uint8_t *)(data + QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET)); - next_hdr = (uint8_t)(*(uint8_t *)(data + + next_hdr = (uint8_t)(*(uint8_t *)( + data + + QDF_NBUF_TRAC_IPV6_OFFSET + QDF_NBUF_TRAC_IPV6_HEADER_SIZE)); - - if (pkt_type == QDF_NBUF_TRAC_ICMPV6_TYPE) - return true; - if ((pkt_type == QDF_NBUF_TRAC_HOPOPTS_TYPE) && - (next_hdr == QDF_NBUF_TRAC_HOPOPTS_TYPE)) - return true; + goto is_mld; } + + if (qdf_nbuf_is_ipv6_vlan_pkt(data)) { + pkt_type = (uint8_t)(*(uint8_t *)( + data + + QDF_NBUF_TRAC_VLAN_IPV6_PROTO_TYPE_OFFSET)); + next_hdr = (uint8_t)(*(uint8_t *)( + data + + QDF_NBUF_TRAC_VLAN_IPV6_OFFSET + + QDF_NBUF_TRAC_IPV6_HEADER_SIZE)); + goto is_mld; + } + + return false; +is_mld: + if (pkt_type == QDF_NBUF_TRAC_ICMPV6_TYPE) + return true; + if ((pkt_type == QDF_NBUF_TRAC_HOPOPTS_TYPE) && + (next_hdr == QDF_NBUF_TRAC_ICMPV6_TYPE)) + return true; + return false; }