From 4c902280da076ad7e88923875b39423226e76e44 Mon Sep 17 00:00:00 2001 From: Shihuan Liu Date: Fri, 4 Aug 2017 11:00:00 -0700 Subject: msm: ipa: add new IP filtering bitmaps Add new IP filtering bitmaps to match TCP SYN packets. Change-Id: I73ab2944c3d351fdb57f147d3efedd1b5829835e Acked-by: Pooja Kumari Signed-off-by: Mohammed Javid Acked-by: Shihuan Liu Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 6 + .../platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c | 187 +++++++++++++++++++++ include/uapi/linux/msm_ipa.h | 2 + 3 files changed, 195 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 71da7d28a451..cd39a46037f1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -505,6 +505,12 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) pr_err("ether_type:%x ", attrib->ether_type); + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) + pr_err("tcp syn "); + + if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP) + pr_err("tcp syn l2tp "); + pr_err("\n"); return 0; } 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 b7ed529e9160..b5916cd1fbf6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -664,6 +664,21 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ihl_ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* 12 => offset of SYN after v4 header */ + extra = ipa_write_8(12, extra); + rest = ipa_write_32(0x20000, rest); + rest = ipa_write_32(0x20000, rest); + ihl_ofst_meq32++; + } + if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_METADATA_COMPARE); rest = ipa_write_32(attrib->meta_data_mask, rest); @@ -970,6 +985,57 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, ihl_ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* 12 => offset of SYN after v4 header */ + extra = ipa_write_8(12, extra); + rest = ipa_write_32(0x20000, rest); + rest = ipa_write_32(0x20000, rest); + ihl_ofst_meq32++; + } + + if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32) || IPA_IS_RAN_OUT_OF_EQ( + ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32 + 1)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32 + 1]); + + /* populate TCP protocol eq */ + if (attrib->ether_type == 0x0800) { + extra = ipa_write_8(30, extra); + rest = ipa_write_32(0xFF0000, rest); + rest = ipa_write_32(0x60000, rest); + } else { + extra = ipa_write_8(26, extra); + rest = ipa_write_32(0xFF00, rest); + rest = ipa_write_32(0x600, rest); + } + + /* populate TCP SYN eq */ + if (attrib->ether_type == 0x0800) { + extra = ipa_write_8(54, extra); + rest = ipa_write_32(0x20000, rest); + rest = ipa_write_32(0x20000, rest); + } else { + extra = ipa_write_8(74, extra); + rest = ipa_write_32(0x20000, rest); + rest = ipa_write_32(0x20000, rest); + } + ihl_ofst_meq32 += 2; + } + if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_METADATA_COMPARE); rest = ipa_write_32(attrib->meta_data_mask, rest); @@ -1044,6 +1110,27 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, ihl_ofst_rng16++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_rng16, + ihl_ofst_rng16)) { + IPAHAL_ERR("ran out of ihl_rng16 eq\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_rng16[ihl_ofst_rng16]); + /* 20 => offset of Ethertype after v4 header */ + if (attrib->ether_type == 0x0800) { + extra = ipa_write_8(21, extra); + rest = ipa_write_16(0x0045, rest); + rest = ipa_write_16(0x0045, rest); + } else { + extra = ipa_write_8(20, extra); + rest = ipa_write_16(attrib->ether_type, rest); + rest = ipa_write_16(attrib->ether_type, rest); + } + ihl_ofst_rng16++; + } + if (attrib->attrib_mask & IPA_FLT_FLOW_LABEL) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_FL_EQ); rest = ipa_write_32(attrib->u.v6.flow_label & 0xFFFFF, @@ -1480,6 +1567,21 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ofst_meq128++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* 12 => offset of SYN after v4 header */ + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 12; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = 0x20000; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = 0x20000; + ihl_ofst_meq32++; + } + if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_ERR("ran out of meq32 eq\n"); @@ -1843,6 +1945,65 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, ofst_meq128++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* 12 => offset of SYN after v4 header */ + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 12; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = 0x20000; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = 0x20000; + ihl_ofst_meq32++; + } + + if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32) || IPA_IS_RAN_OUT_OF_EQ( + ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32 + 1)) { + IPAHAL_ERR("ran out of ihl_meq32 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32 + 1]); + + /* populate TCP protocol eq */ + if (attrib->ether_type == 0x0800) { + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 30; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = + 0xFF0000; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = + 0x60000; + } else { + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 26; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = + 0xFF00; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = + 0x600; + } + + /* populate TCP SYN eq */ + if (attrib->ether_type == 0x0800) { + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 54; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = + 0x20000; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = + 0x20000; + } else { + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 74; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = + 0x20000; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = + 0x20000; + } + ihl_ofst_meq32 += 2; + } + if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_ERR("ran out of meq32 eq\n"); @@ -1985,6 +2146,32 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, ihl_ofst_rng16++; } + if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_rng16, + ihl_ofst_rng16)) { + IPAHAL_ERR("ran out of ihl_rng16 eq\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_rng16[ihl_ofst_rng16]); + if (attrib->ether_type == 0x0800) { + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].offset + = 21; + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].range_low + = 0x0045; + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].range_high + = 0x0045; + } else { + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].offset = + 20; + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].range_low + = attrib->ether_type; + eq_atrb->ihl_offset_range_16[ihl_ofst_rng16].range_high + = attrib->ether_type; + } + ihl_ofst_rng16++; + } + if (attrib->attrib_mask & IPA_FLT_FLOW_LABEL) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_FL_EQ); eq_atrb->fl_eq_present = 1; diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 0bdfc9741d19..3d330990676c 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -163,6 +163,8 @@ #define IPA_FLT_MAC_SRC_ADDR_802_3 (1ul << 19) #define IPA_FLT_MAC_DST_ADDR_802_3 (1ul << 20) #define IPA_FLT_MAC_ETHER_TYPE (1ul << 21) +#define IPA_FLT_TCP_SYN (1ul << 23) +#define IPA_FLT_TCP_SYN_L2TP (1ul << 24) /** * maximal number of NAT PDNs in the PDN config table -- cgit v1.2.3