Commit 3a344f99 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller
Browse files

net: microchip: sparx5: Add support for TC flower ARP dissector



This add support for Sparx5 for dissecting TC ARP flower filter keys and
sets up the Sparx5 IS2 VCAP to generate the ARP keyset for ARP frames.

Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 70ea86a0
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -26,10 +26,24 @@ struct sparx5_tc_flower_parse_usage {
 */
static u16 sparx5_tc_known_etypes[] = {
	ETH_P_ALL,
	ETH_P_ARP,
	ETH_P_IP,
	ETH_P_IPV6,
};

enum sparx5_is2_arp_opcode {
	SPX5_IS2_ARP_REQUEST,
	SPX5_IS2_ARP_REPLY,
	SPX5_IS2_RARP_REQUEST,
	SPX5_IS2_RARP_REPLY,
};

enum tc_arp_opcode {
	TC_ARP_OP_RESERVED,
	TC_ARP_OP_REQUEST,
	TC_ARP_OP_REPLY,
};

static bool sparx5_tc_is_known_etype(u16 etype)
{
	int idx;
@@ -404,6 +418,67 @@ sparx5_tc_flower_handler_tcp_usage(struct sparx5_tc_flower_parse_usage *st)
	return err;
}

static int
sparx5_tc_flower_handler_arp_usage(struct sparx5_tc_flower_parse_usage *st)
{
	struct flow_match_arp mt;
	u16 value, mask;
	u32 ipval, ipmsk;
	int err;

	flow_rule_match_arp(st->frule, &mt);

	if (mt.mask->op) {
		mask = 0x3;
		if (st->l3_proto == ETH_P_ARP) {
			value = mt.key->op == TC_ARP_OP_REQUEST ?
					SPX5_IS2_ARP_REQUEST :
					SPX5_IS2_ARP_REPLY;
		} else { /* RARP */
			value = mt.key->op == TC_ARP_OP_REQUEST ?
					SPX5_IS2_RARP_REQUEST :
					SPX5_IS2_RARP_REPLY;
		}
		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE,
					    value, mask);
		if (err)
			goto out;
	}

	/* The IS2 ARP keyset does not support ARP hardware addresses */
	if (!is_zero_ether_addr(mt.mask->sha) ||
	    !is_zero_ether_addr(mt.mask->tha))
		goto out;

	if (mt.mask->sip) {
		ipval = be32_to_cpu((__force __be32)mt.key->sip);
		ipmsk = be32_to_cpu((__force __be32)mt.mask->sip);

		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP,
					    ipval, ipmsk);
		if (err)
			goto out;
	}

	if (mt.mask->tip) {
		ipval = be32_to_cpu((__force __be32)mt.key->tip);
		ipmsk = be32_to_cpu((__force __be32)mt.mask->tip);

		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP,
					    ipval, ipmsk);
		if (err)
			goto out;
	}

	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ARP);

	return err;

out:
	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");
	return err;
}

static int
sparx5_tc_flower_handler_ip_usage(struct sparx5_tc_flower_parse_usage *st)
{
@@ -438,6 +513,7 @@ static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_us
	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
	[FLOW_DISSECTOR_KEY_TCP] = sparx5_tc_flower_handler_tcp_usage,
	[FLOW_DISSECTOR_KEY_ARP] = sparx5_tc_flower_handler_arp_usage,
	[FLOW_DISSECTOR_KEY_IP] = sparx5_tc_flower_handler_ip_usage,
};

+1 −1
Original line number Diff line number Diff line
@@ -540,7 +540,7 @@ static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5,
				 VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
				 VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
				 VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
				 VCAP_IS2_PS_ARP_MAC_ETYPE);
				 VCAP_IS2_PS_ARP_ARP);
	for (lookup = 0; lookup < admin->lookups; ++lookup) {
		for (portno = 0; portno < SPX5_PORTS; ++portno) {
			spx5_wr(keysel, sparx5,