From 888e63828bad480e1be924efff4b42a7514fb23e Mon Sep 17 00:00:00 2001 From: Amir Levy Date: Tue, 5 Nov 2019 14:06:44 +0200 Subject: [PATCH] msm: ipa3: add VLAN ID filtering Add the ability to filter VLAN ID from 802_1Q packets. filter VLAN packets TPID 0x8100 and VLAN ID according to parameter. CRs-Fixed: 2524793 Change-Id: Id3bf910636e46c819dc2fb0f7f9bc938e6dd61dd Signed-off-by: Amir Levy --- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 7 ++ .../msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c | 64 +++++++++++++++++++ include/uapi/linux/msm_ipa.h | 3 + 3 files changed, 74 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 5473da411932..1946d245a52b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -615,6 +615,13 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, "ether_type:%x ", attrib->ether_type); + if (attrib->attrib_mask & IPA_FLT_VLAN_ID) + nbytes += scnprintf( + dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "vlan_id:%x ", + attrib->vlan_id); + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) nbytes += scnprintf( dbg_buff + nbytes, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c index f371d83852bd..6b4c50abcef6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -847,6 +847,31 @@ static void ipa_fltrt_generate_mac_addr_hw_rule(u8 **extra, u8 **rest, *rest = ipa_write_8(mac_addr[i], *rest); } +static inline int ipa_fltrt_generate_vlan_hw_rule_bdy(u16 *en_rule, + const struct ipa_rule_attrib *attrib, + u8 *ofst_meq32, u8 **extra, u8 **rest) +{ + if (attrib->attrib_mask & IPA_FLT_VLAN_ID) { + uint32_t vlan_tag; + + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, *ofst_meq32)) { + IPAHAL_ERR("ran out of meq32 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ofst_meq32[*ofst_meq32]); + /* -6 => offset of 802_1Q tag in L2 hdr */ + *extra = ipa_write_8((u8)-6, *extra); + /* filter vlan packets: 0x8100 TPID + required VLAN ID */ + vlan_tag = (0x8100 << 16) | (attrib->vlan_id & 0xFFF); + *rest = ipa_write_32(0xFFFF0FFF, *rest); + *rest = ipa_write_32(vlan_tag, *rest); + (*ofst_meq32)++; + } + + return 0; +} + static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, const struct ipa_rule_attrib *attrib, u8 **extra_wrds, u8 **rest_wrds) @@ -1036,6 +1061,10 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, } } + if (ipa_fltrt_generate_vlan_hw_rule_bdy(en_rule, attrib, &ofst_meq32, + &extra, &rest)) + goto err; + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { @@ -1422,6 +1451,10 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, ofst_meq32++; } + if (ipa_fltrt_generate_vlan_hw_rule_bdy(en_rule, attrib, &ofst_meq32, + &extra, &rest)) + goto err; + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { @@ -2046,6 +2079,31 @@ static void ipa_flt_generate_mac_addr_eq(struct ipa_ipfltri_rule_eq *eq_atrb, mac_addr[i]; } +static inline int ipa_flt_generat_vlan_eq( + const struct ipa_rule_attrib *attrib, u16 *en_rule, u8 *ofst_meq32, + struct ipa_ipfltri_rule_eq *eq_atrb) +{ + if (attrib->attrib_mask & IPA_FLT_VLAN_ID) { + uint32_t vlan_tag; + + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, *ofst_meq32)) { + IPAHAL_ERR("ran out of meq32 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ofst_meq32[*ofst_meq32]); + /* -6 => offset of 802_1Q tag in L2 hdr */ + eq_atrb->offset_meq_32[*ofst_meq32].offset = -6; + /* filter vlan packets: 0x8100 TPID + required VLAN ID */ + vlan_tag = (0x8100 << 16) | (attrib->vlan_id & 0xFFF); + eq_atrb->offset_meq_32[*ofst_meq32].mask = 0xFFFF0FFF; + eq_atrb->offset_meq_32[*ofst_meq32].value = vlan_tag; + (*ofst_meq32)++; + } + + return 0; +} + static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, const struct ipa_rule_attrib *attrib, struct ipa_ipfltri_rule_eq *eq_atrb) @@ -2282,6 +2340,9 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, } } + if (ipa_flt_generat_vlan_eq(attrib, en_rule, &ofst_meq32, eq_atrb)) + return -EPERM; + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { @@ -2770,6 +2831,9 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, ofst_meq32++; } + if (ipa_flt_generat_vlan_eq(attrib, en_rule, &ofst_meq32, eq_atrb)) + return -EPERM; + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 0f2f299d0b33..40f179de6cb0 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -210,6 +210,7 @@ #define IPA_FLT_L2TP_INNER_IP_TYPE (1ul << 25) #define IPA_FLT_L2TP_INNER_IPV4_DST_ADDR (1ul << 26) #define IPA_FLT_IS_PURE_ACK (1ul << 27) +#define IPA_FLT_VLAN_ID (1ul << 28) /** * maximal number of NAT PDNs in the PDN config table @@ -818,6 +819,7 @@ enum ipa_hw_type { * @u.v6.src_addr_mask: src address mask * @u.v6.dst_addr: dst address val * @u.v6.dst_addr_mask: dst address mask + * @vlan_id: vlan id value */ struct ipa_rule_attrib { uint32_t attrib_mask; @@ -858,6 +860,7 @@ struct ipa_rule_attrib { uint32_t dst_addr_mask[4]; } v6; } u; + uint16_t vlan_id; }; /*! @brief The maximum number of Mask Equal 32 Eqns */