Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5a6b9e4 authored by Amir Levy's avatar Amir Levy
Browse files

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: default avatarAmir Levy <alevy@codeaurora.org>
parent 78327398
Loading
Loading
Loading
Loading
+31 −28
Original line number Diff line number Diff line
@@ -440,24 +440,24 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
	int i;

	if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK)
		pr_err("is_pure_ack ");
		pr_cont("is_pure_ack ");

	if (attrib->attrib_mask & IPA_FLT_TOS)
		pr_err("tos:%d ", attrib->u.v4.tos);
		pr_cont("tos:%d ", attrib->u.v4.tos);

	if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
		pr_err("tos_value:%d ", attrib->tos_value);
		pr_err("tos_mask:%d ", attrib->tos_mask);
		pr_cont("tos_value:%d ", attrib->tos_value);
		pr_cont("tos_mask:%d ", attrib->tos_mask);
	}

	if (attrib->attrib_mask & IPA_FLT_PROTOCOL)
		pr_err("protocol:%d ", attrib->u.v4.protocol);
		pr_cont("protocol:%d ", attrib->u.v4.protocol);

	if (attrib->attrib_mask & IPA_FLT_SRC_ADDR) {
		if (ip == IPA_IP_v4) {
			addr[0] = htonl(attrib->u.v4.src_addr);
			mask[0] = htonl(attrib->u.v4.src_addr_mask);
			pr_err(
			pr_cont(
					"src_addr:%pI4 src_addr_mask:%pI4 ",
					addr + 0, mask + 0);
		} else if (ip == IPA_IP_v6) {
@@ -465,7 +465,7 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
				addr[i] = htonl(attrib->u.v6.src_addr[i]);
				mask[i] = htonl(attrib->u.v6.src_addr_mask[i]);
			}
			pr_err(
			pr_cont(
					   "src_addr:%pI6 src_addr_mask:%pI6 ",
					   addr + 0, mask + 0);
		}
@@ -474,7 +474,7 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
		if (ip == IPA_IP_v4) {
			addr[0] = htonl(attrib->u.v4.dst_addr);
			mask[0] = htonl(attrib->u.v4.dst_addr_mask);
			pr_err(
			pr_cont(
					   "dst_addr:%pI4 dst_addr_mask:%pI4 ",
					   addr + 0, mask + 0);
		} else if (ip == IPA_IP_v6) {
@@ -482,81 +482,84 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib,
				addr[i] = htonl(attrib->u.v6.dst_addr[i]);
				mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]);
			}
			pr_err(
			pr_cont(
					   "dst_addr:%pI6 dst_addr_mask:%pI6 ",
					   addr + 0, mask + 0);
		}
	}
	if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) {
		pr_err("src_port_range:%u %u ",
		pr_cont("src_port_range:%u %u ",
				   attrib->src_port_lo,
			     attrib->src_port_hi);
	}
	if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) {
		pr_err("dst_port_range:%u %u ",
		pr_cont("dst_port_range:%u %u ",
				   attrib->dst_port_lo,
			     attrib->dst_port_hi);
	}
	if (attrib->attrib_mask & IPA_FLT_TYPE)
		pr_err("type:%d ", attrib->type);
		pr_cont("type:%d ", attrib->type);

	if (attrib->attrib_mask & IPA_FLT_CODE)
		pr_err("code:%d ", attrib->code);
		pr_cont("code:%d ", attrib->code);

	if (attrib->attrib_mask & IPA_FLT_SPI)
		pr_err("spi:%x ", attrib->spi);
		pr_cont("spi:%x ", attrib->spi);

	if (attrib->attrib_mask & IPA_FLT_SRC_PORT)
		pr_err("src_port:%u ", attrib->src_port);
		pr_cont("src_port:%u ", attrib->src_port);

	if (attrib->attrib_mask & IPA_FLT_DST_PORT)
		pr_err("dst_port:%u ", attrib->dst_port);
		pr_cont("dst_port:%u ", attrib->dst_port);

	if (attrib->attrib_mask & IPA_FLT_TC)
		pr_err("tc:%d ", attrib->u.v6.tc);
		pr_cont("tc:%d ", attrib->u.v6.tc);

	if (attrib->attrib_mask & IPA_FLT_FLOW_LABEL)
		pr_err("flow_label:%x ", attrib->u.v6.flow_label);
		pr_cont("flow_label:%x ", attrib->u.v6.flow_label);

	if (attrib->attrib_mask & IPA_FLT_NEXT_HDR)
		pr_err("next_hdr:%d ", attrib->u.v6.next_hdr);
		pr_cont("next_hdr:%d ", attrib->u.v6.next_hdr);

	if (attrib->attrib_mask & IPA_FLT_META_DATA) {
		pr_err(
		pr_cont(
				   "metadata:%x metadata_mask:%x ",
				   attrib->meta_data, attrib->meta_data_mask);
	}

	if (attrib->attrib_mask & IPA_FLT_FRAGMENT)
		pr_err("frg ");
		pr_cont("frg ");

	if ((attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) ||
		(attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3)) {
		pr_err("src_mac_addr:%pM ", attrib->src_mac_addr);
		pr_cont("src_mac_addr:%pM ", attrib->src_mac_addr);
	}

	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)) {
		pr_err("dst_mac_addr:%pM ", attrib->dst_mac_addr);
		pr_cont("dst_mac_addr:%pM ", attrib->dst_mac_addr);
	}

	if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE)
		pr_err("ether_type:%x ", attrib->ether_type);
		pr_cont("ether_type:%x ", attrib->ether_type);

	if (attrib->attrib_mask & IPA_FLT_VLAN_ID)
		pr_cont("vlan_id:%x ", attrib->vlan_id);

	if (attrib->attrib_mask & IPA_FLT_TCP_SYN)
		pr_err("tcp syn ");
		pr_cont("tcp syn ");

	if (attrib->attrib_mask & IPA_FLT_TCP_SYN_L2TP)
		pr_err("tcp syn l2tp ");
		pr_cont("tcp syn l2tp ");

	if (attrib->attrib_mask & IPA_FLT_L2TP_INNER_IP_TYPE)
		pr_err("l2tp inner ip type: %d ", attrib->type);
		pr_cont("l2tp inner ip type: %d ", attrib->type);

	if (attrib->attrib_mask & IPA_FLT_L2TP_INNER_IPV4_DST_ADDR) {
		addr[0] = htonl(attrib->u.v4.dst_addr);
		mask[0] = htonl(attrib->u.v4.dst_addr_mask);
		pr_err("dst_addr:%pI4 dst_addr_mask:%pI4 ", addr, mask);
		pr_cont("dst_addr:%pI4 dst_addr_mask:%pI4 ", addr, mask);
	}

	pr_err("\n");
+64 −0
Original line number Diff line number Diff line
@@ -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)) {
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -815,6 +816,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;
@@ -855,6 +857,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 */