msm: ipa4: add MAC filtering for 802_1Q packets

Add ability to filter MAC addresses from 802_1Q packets.
MAC address is located in a different offset than in ETH_II
header.

Change-Id: I4b808102dbb708779762bedb998c2477b5058886
Signed-off-by: Amir Levy <alevy@codeaurora.org>
This commit is contained in:
Amir Levy 2019-11-18 09:43:33 +02:00
commit ece40dea5e
3 changed files with 188 additions and 270 deletions

View file

@ -594,7 +594,8 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
"frg ");
if ((attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) ||
(attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3))
(attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) ||
(attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_1Q))
nbytes += scnprintf(
dbg_buff + nbytes,
IPA_MAX_MSG_LEN - nbytes,
@ -603,7 +604,8 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
if ((attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) ||
(attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) ||
(attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_L2TP))
(attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_L2TP ||
(attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_1Q))
nbytes += scnprintf(
dbg_buff + nbytes,
IPA_MAX_MSG_LEN - nbytes,

View file

@ -13,6 +13,11 @@
#include "ipahal_i.h"
#include "../../ipa_common_i.h"
#define IPA_MAC_FLT_BITS (IPA_FLT_MAC_DST_ADDR_ETHER_II | \
IPA_FLT_MAC_SRC_ADDR_ETHER_II | IPA_FLT_MAC_DST_ADDR_802_3 | \
IPA_FLT_MAC_SRC_ADDR_802_3 | IPA_FLT_MAC_DST_ADDR_802_1Q | \
IPA_FLT_MAC_SRC_ADDR_802_1Q)
/*
* struct ipahal_fltrt_obj - Flt/Rt H/W information for specific IPA version
* @support_hash: Is hashable tables supported
@ -847,6 +852,112 @@ static void ipa_fltrt_generate_mac_addr_hw_rule(u8 **extra, u8 **rest,
*rest = ipa_write_8(mac_addr[i], *rest);
}
static inline void ipa_fltrt_get_mac_data(const struct ipa_rule_attrib *attrib,
uint32_t attrib_mask, u8 *offset, const uint8_t **mac_addr,
const uint8_t **mac_addr_mask)
{
if (attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
*offset = -14;
*mac_addr = attrib->dst_mac_addr;
*mac_addr_mask = attrib->dst_mac_addr_mask;
return;
}
if (attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
*offset = -8;
*mac_addr = attrib->src_mac_addr;
*mac_addr_mask = attrib->src_mac_addr_mask;
return;
}
if (attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
*offset = -22;
*mac_addr = attrib->dst_mac_addr;
*mac_addr_mask = attrib->dst_mac_addr_mask;
return;
}
if (attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
*offset = -16;
*mac_addr = attrib->src_mac_addr;
*mac_addr_mask = attrib->src_mac_addr_mask;
return;
}
if (attrib_mask & IPA_FLT_MAC_DST_ADDR_802_1Q) {
*offset = -18;
*mac_addr = attrib->dst_mac_addr;
*mac_addr_mask = attrib->dst_mac_addr_mask;
return;
}
if (attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_1Q) {
*offset = -10;
*mac_addr = attrib->src_mac_addr;
*mac_addr_mask = attrib->src_mac_addr_mask;
return;
}
}
static int ipa_fltrt_generate_mac_hw_rule_bdy(u16 *en_rule,
const struct ipa_rule_attrib *attrib,
u8 *ofst_meq128, u8 **extra, u8 **rest)
{
u8 offset = 0;
const uint8_t *mac_addr = NULL;
const uint8_t *mac_addr_mask = NULL;
int i;
uint32_t attrib_mask;
for (i = 0; i < hweight_long(IPA_MAC_FLT_BITS); i++) {
switch (i) {
case 0:
attrib_mask = IPA_FLT_MAC_DST_ADDR_ETHER_II;
break;
case 1:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_ETHER_II;
break;
case 2:
attrib_mask = IPA_FLT_MAC_DST_ADDR_802_3;
break;
case 3:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_802_3;
break;
case 4:
attrib_mask = IPA_FLT_MAC_DST_ADDR_802_1Q;
break;
case 5:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_802_1Q;
break;
default:
return -EPERM;
}
attrib_mask &= attrib->attrib_mask;
if (!attrib_mask)
continue;
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, *ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[*ofst_meq128]);
ipa_fltrt_get_mac_data(attrib, attrib_mask, &offset,
&mac_addr, &mac_addr_mask);
ipa_fltrt_generate_mac_addr_hw_rule(extra, rest, offset,
mac_addr_mask,
mac_addr);
(*ofst_meq128)++;
}
return 0;
}
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)
@ -909,80 +1020,10 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule,
extra = ipa_write_8(attrib->u.v4.protocol, extra);
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
if (attrib->attrib_mask & IPA_MAC_FLT_BITS) {
if (ipa_fltrt_generate_mac_hw_rule_bdy(en_rule, attrib,
&ofst_meq128, &extra, &rest))
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -14 => offset of dst mac addr in Ethernet II hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-14,
attrib->dst_mac_addr_mask,
attrib->dst_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -8 => offset of src mac addr in Ethernet II hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-8,
attrib->src_mac_addr_mask,
attrib->src_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -22 => offset of dst mac addr in 802.3 hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-22,
attrib->dst_mac_addr_mask,
attrib->dst_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -16 => offset of src mac addr in 802.3 hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-16,
attrib->src_mac_addr_mask,
attrib->src_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
@ -1359,80 +1400,10 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule,
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
if (attrib->attrib_mask & IPA_MAC_FLT_BITS) {
if (ipa_fltrt_generate_mac_hw_rule_bdy(en_rule, attrib,
&ofst_meq128, &extra, &rest))
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -14 => offset of dst mac addr in Ethernet II hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-14,
attrib->dst_mac_addr_mask,
attrib->dst_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -8 => offset of src mac addr in Ethernet II hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-8,
attrib->src_mac_addr_mask,
attrib->src_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -22 => offset of dst mac addr in 802.3 hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-22,
attrib->dst_mac_addr_mask,
attrib->dst_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
goto err;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -16 => offset of src mac addr in 802.3 hdr */
ipa_fltrt_generate_mac_addr_hw_rule(
&extra,
&rest,
-16,
attrib->src_mac_addr_mask,
attrib->src_mac_addr);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) {
@ -2079,6 +2050,65 @@ static void ipa_flt_generate_mac_addr_eq(struct ipa_ipfltri_rule_eq *eq_atrb,
mac_addr[i];
}
static int ipa_flt_generate_mac_eq(
const struct ipa_rule_attrib *attrib, u16 *en_rule, u8 *ofst_meq128,
struct ipa_ipfltri_rule_eq *eq_atrb)
{
u8 offset = 0;
const uint8_t *mac_addr = NULL;
const uint8_t *mac_addr_mask = NULL;
int i;
uint32_t attrib_mask;
for (i = 0; i < hweight_long(IPA_MAC_FLT_BITS); i++) {
switch (i) {
case 0:
attrib_mask = IPA_FLT_MAC_DST_ADDR_ETHER_II;
break;
case 1:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_ETHER_II;
break;
case 2:
attrib_mask = IPA_FLT_MAC_DST_ADDR_802_3;
break;
case 3:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_802_3;
break;
case 4:
attrib_mask = IPA_FLT_MAC_DST_ADDR_802_1Q;
break;
case 5:
attrib_mask = IPA_FLT_MAC_SRC_ADDR_802_1Q;
break;
default:
return -EPERM;
}
attrib_mask &= attrib->attrib_mask;
if (!attrib_mask)
continue;
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, *ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[*ofst_meq128]);
ipa_fltrt_get_mac_data(attrib, attrib_mask, &offset,
&mac_addr, &mac_addr_mask);
ipa_flt_generate_mac_addr_eq(eq_atrb, offset,
mac_addr_mask, mac_addr,
*ofst_meq128);
(*ofst_meq128)++;
}
return 0;
}
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)
@ -2147,68 +2177,10 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip,
eq_atrb->protocol_eq = attrib->u.v4.protocol;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
if (attrib->attrib_mask & IPA_MAC_FLT_BITS) {
if (ipa_flt_generate_mac_eq(attrib, en_rule,
&ofst_meq128, eq_atrb))
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -14 => offset of dst mac addr in Ethernet II hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -14,
attrib->dst_mac_addr_mask, attrib->dst_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -8 => offset of src mac addr in Ethernet II hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -8,
attrib->src_mac_addr_mask, attrib->src_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -22 => offset of dst mac addr in 802.3 hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -22,
attrib->dst_mac_addr_mask, attrib->dst_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -16 => offset of src mac addr in 802.3 hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -16,
attrib->src_mac_addr_mask, attrib->src_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_L2TP) {
@ -2625,68 +2597,10 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip,
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR_RL("ran out of meq128 eq\n");
if (attrib->attrib_mask & IPA_MAC_FLT_BITS) {
if (ipa_flt_generate_mac_eq(attrib, en_rule,
&ofst_meq128, eq_atrb))
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -14 => offset of dst mac addr in Ethernet II hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -14,
attrib->dst_mac_addr_mask, attrib->dst_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR_RL("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -8 => offset of src mac addr in Ethernet II hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -8,
attrib->src_mac_addr_mask, attrib->src_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR_RL("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -22 => offset of dst mac addr in 802.3 hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -22,
attrib->dst_mac_addr_mask, attrib->dst_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq128, ofst_meq128)) {
IPAHAL_ERR_RL("ran out of meq128 eq\n");
return -EPERM;
}
*en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(
ipa3_0_ofst_meq128[ofst_meq128]);
/* -16 => offset of src mac addr in 802.3 hdr */
ipa_flt_generate_mac_addr_eq(eq_atrb, -16,
attrib->src_mac_addr_mask, attrib->src_mac_addr,
ofst_meq128);
ofst_meq128++;
}
if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_L2TP) {

View file

@ -211,6 +211,8 @@
#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)
#define IPA_FLT_MAC_SRC_ADDR_802_1Q (1ul << 29)
#define IPA_FLT_MAC_DST_ADDR_802_1Q (1ul << 30)
/**
* maximal number of NAT PDNs in the PDN config table