xref: /openbmc/linux/drivers/net/ethernet/microchip/vcap/vcap_tc.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
147400aaeSHoratiu Vultur // SPDX-License-Identifier: GPL-2.0+
247400aaeSHoratiu Vultur /* Microchip VCAP TC
347400aaeSHoratiu Vultur  *
447400aaeSHoratiu Vultur  * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.
547400aaeSHoratiu Vultur  */
647400aaeSHoratiu Vultur 
747400aaeSHoratiu Vultur #include <net/flow_offload.h>
847400aaeSHoratiu Vultur #include <net/ipv6.h>
947400aaeSHoratiu Vultur #include <net/tcp.h>
1047400aaeSHoratiu Vultur 
1147400aaeSHoratiu Vultur #include "vcap_api_client.h"
1247400aaeSHoratiu Vultur #include "vcap_tc.h"
1347400aaeSHoratiu Vultur 
1447400aaeSHoratiu Vultur enum vcap_is2_arp_opcode {
1547400aaeSHoratiu Vultur 	VCAP_IS2_ARP_REQUEST,
1647400aaeSHoratiu Vultur 	VCAP_IS2_ARP_REPLY,
1747400aaeSHoratiu Vultur 	VCAP_IS2_RARP_REQUEST,
1847400aaeSHoratiu Vultur 	VCAP_IS2_RARP_REPLY,
1947400aaeSHoratiu Vultur };
2047400aaeSHoratiu Vultur 
2147400aaeSHoratiu Vultur enum vcap_arp_opcode {
2247400aaeSHoratiu Vultur 	VCAP_ARP_OP_RESERVED,
2347400aaeSHoratiu Vultur 	VCAP_ARP_OP_REQUEST,
2447400aaeSHoratiu Vultur 	VCAP_ARP_OP_REPLY,
2547400aaeSHoratiu Vultur };
2647400aaeSHoratiu Vultur 
vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage * st)2747400aaeSHoratiu Vultur int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st)
2847400aaeSHoratiu Vultur {
2947400aaeSHoratiu Vultur 	enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;
3047400aaeSHoratiu Vultur 	enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC;
3147400aaeSHoratiu Vultur 	struct flow_match_eth_addrs match;
3247400aaeSHoratiu Vultur 	struct vcap_u48_key smac, dmac;
3347400aaeSHoratiu Vultur 	int err = 0;
3447400aaeSHoratiu Vultur 
3547400aaeSHoratiu Vultur 	flow_rule_match_eth_addrs(st->frule, &match);
3647400aaeSHoratiu Vultur 
3747400aaeSHoratiu Vultur 	if (!is_zero_ether_addr(match.mask->src)) {
3847400aaeSHoratiu Vultur 		vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN);
3947400aaeSHoratiu Vultur 		vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN);
4047400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac);
4147400aaeSHoratiu Vultur 		if (err)
4247400aaeSHoratiu Vultur 			goto out;
4347400aaeSHoratiu Vultur 	}
4447400aaeSHoratiu Vultur 
4547400aaeSHoratiu Vultur 	if (!is_zero_ether_addr(match.mask->dst)) {
4647400aaeSHoratiu Vultur 		vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN);
4747400aaeSHoratiu Vultur 		vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN);
4847400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac);
4947400aaeSHoratiu Vultur 		if (err)
5047400aaeSHoratiu Vultur 			goto out;
5147400aaeSHoratiu Vultur 	}
5247400aaeSHoratiu Vultur 
53*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS);
5447400aaeSHoratiu Vultur 
5547400aaeSHoratiu Vultur 	return err;
5647400aaeSHoratiu Vultur 
5747400aaeSHoratiu Vultur out:
5847400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error");
5947400aaeSHoratiu Vultur 	return err;
6047400aaeSHoratiu Vultur }
6147400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ethaddr_usage);
6247400aaeSHoratiu Vultur 
vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage * st)6347400aaeSHoratiu Vultur int vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage *st)
6447400aaeSHoratiu Vultur {
6547400aaeSHoratiu Vultur 	int err = 0;
6647400aaeSHoratiu Vultur 
6747400aaeSHoratiu Vultur 	if (st->l3_proto == ETH_P_IP) {
6847400aaeSHoratiu Vultur 		struct flow_match_ipv4_addrs mt;
6947400aaeSHoratiu Vultur 
7047400aaeSHoratiu Vultur 		flow_rule_match_ipv4_addrs(st->frule, &mt);
7147400aaeSHoratiu Vultur 		if (mt.mask->src) {
7247400aaeSHoratiu Vultur 			err = vcap_rule_add_key_u32(st->vrule,
7347400aaeSHoratiu Vultur 						    VCAP_KF_L3_IP4_SIP,
7447400aaeSHoratiu Vultur 						    be32_to_cpu(mt.key->src),
7547400aaeSHoratiu Vultur 						    be32_to_cpu(mt.mask->src));
7647400aaeSHoratiu Vultur 			if (err)
7747400aaeSHoratiu Vultur 				goto out;
7847400aaeSHoratiu Vultur 		}
7947400aaeSHoratiu Vultur 		if (mt.mask->dst) {
8047400aaeSHoratiu Vultur 			err = vcap_rule_add_key_u32(st->vrule,
8147400aaeSHoratiu Vultur 						    VCAP_KF_L3_IP4_DIP,
8247400aaeSHoratiu Vultur 						    be32_to_cpu(mt.key->dst),
8347400aaeSHoratiu Vultur 						    be32_to_cpu(mt.mask->dst));
8447400aaeSHoratiu Vultur 			if (err)
8547400aaeSHoratiu Vultur 				goto out;
8647400aaeSHoratiu Vultur 		}
8747400aaeSHoratiu Vultur 	}
8847400aaeSHoratiu Vultur 
89*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS);
9047400aaeSHoratiu Vultur 
9147400aaeSHoratiu Vultur 	return err;
9247400aaeSHoratiu Vultur 
9347400aaeSHoratiu Vultur out:
9447400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");
9547400aaeSHoratiu Vultur 	return err;
9647400aaeSHoratiu Vultur }
9747400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv4_usage);
9847400aaeSHoratiu Vultur 
vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage * st)9947400aaeSHoratiu Vultur int vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage *st)
10047400aaeSHoratiu Vultur {
10147400aaeSHoratiu Vultur 	int err = 0;
10247400aaeSHoratiu Vultur 
10347400aaeSHoratiu Vultur 	if (st->l3_proto == ETH_P_IPV6) {
10447400aaeSHoratiu Vultur 		struct flow_match_ipv6_addrs mt;
10547400aaeSHoratiu Vultur 		struct vcap_u128_key sip;
10647400aaeSHoratiu Vultur 		struct vcap_u128_key dip;
10747400aaeSHoratiu Vultur 
10847400aaeSHoratiu Vultur 		flow_rule_match_ipv6_addrs(st->frule, &mt);
10947400aaeSHoratiu Vultur 		/* Check if address masks are non-zero */
11047400aaeSHoratiu Vultur 		if (!ipv6_addr_any(&mt.mask->src)) {
11147400aaeSHoratiu Vultur 			vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16);
11247400aaeSHoratiu Vultur 			vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16);
11347400aaeSHoratiu Vultur 			err = vcap_rule_add_key_u128(st->vrule,
11447400aaeSHoratiu Vultur 						     VCAP_KF_L3_IP6_SIP, &sip);
11547400aaeSHoratiu Vultur 			if (err)
11647400aaeSHoratiu Vultur 				goto out;
11747400aaeSHoratiu Vultur 		}
11847400aaeSHoratiu Vultur 		if (!ipv6_addr_any(&mt.mask->dst)) {
11947400aaeSHoratiu Vultur 			vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16);
12047400aaeSHoratiu Vultur 			vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16);
12147400aaeSHoratiu Vultur 			err = vcap_rule_add_key_u128(st->vrule,
12247400aaeSHoratiu Vultur 						     VCAP_KF_L3_IP6_DIP, &dip);
12347400aaeSHoratiu Vultur 			if (err)
12447400aaeSHoratiu Vultur 				goto out;
12547400aaeSHoratiu Vultur 		}
12647400aaeSHoratiu Vultur 	}
127*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS);
12847400aaeSHoratiu Vultur 	return err;
12947400aaeSHoratiu Vultur out:
13047400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");
13147400aaeSHoratiu Vultur 	return err;
13247400aaeSHoratiu Vultur }
13347400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv6_usage);
13447400aaeSHoratiu Vultur 
vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage * st)13547400aaeSHoratiu Vultur int vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage *st)
13647400aaeSHoratiu Vultur {
13747400aaeSHoratiu Vultur 	struct flow_match_ports mt;
13847400aaeSHoratiu Vultur 	u16 value, mask;
13947400aaeSHoratiu Vultur 	int err = 0;
14047400aaeSHoratiu Vultur 
14147400aaeSHoratiu Vultur 	flow_rule_match_ports(st->frule, &mt);
14247400aaeSHoratiu Vultur 
14347400aaeSHoratiu Vultur 	if (mt.mask->src) {
14447400aaeSHoratiu Vultur 		value = be16_to_cpu(mt.key->src);
14547400aaeSHoratiu Vultur 		mask = be16_to_cpu(mt.mask->src);
14647400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value,
14747400aaeSHoratiu Vultur 					    mask);
14847400aaeSHoratiu Vultur 		if (err)
14947400aaeSHoratiu Vultur 			goto out;
15047400aaeSHoratiu Vultur 	}
15147400aaeSHoratiu Vultur 
15247400aaeSHoratiu Vultur 	if (mt.mask->dst) {
15347400aaeSHoratiu Vultur 		value = be16_to_cpu(mt.key->dst);
15447400aaeSHoratiu Vultur 		mask = be16_to_cpu(mt.mask->dst);
15547400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value,
15647400aaeSHoratiu Vultur 					    mask);
15747400aaeSHoratiu Vultur 		if (err)
15847400aaeSHoratiu Vultur 			goto out;
15947400aaeSHoratiu Vultur 	}
16047400aaeSHoratiu Vultur 
161*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_PORTS);
16247400aaeSHoratiu Vultur 
16347400aaeSHoratiu Vultur 	return err;
16447400aaeSHoratiu Vultur 
16547400aaeSHoratiu Vultur out:
16647400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");
16747400aaeSHoratiu Vultur 	return err;
16847400aaeSHoratiu Vultur }
16947400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_portnum_usage);
17047400aaeSHoratiu Vultur 
vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage * st)17147400aaeSHoratiu Vultur int vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
17247400aaeSHoratiu Vultur {
17347400aaeSHoratiu Vultur 	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0;
17447400aaeSHoratiu Vultur 	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0;
17547400aaeSHoratiu Vultur 	struct flow_match_vlan mt;
17647400aaeSHoratiu Vultur 	u16 tpid;
17747400aaeSHoratiu Vultur 	int err;
17847400aaeSHoratiu Vultur 
17947400aaeSHoratiu Vultur 	flow_rule_match_cvlan(st->frule, &mt);
18047400aaeSHoratiu Vultur 
18147400aaeSHoratiu Vultur 	tpid = be16_to_cpu(mt.key->vlan_tpid);
18247400aaeSHoratiu Vultur 
18347400aaeSHoratiu Vultur 	if (tpid == ETH_P_8021Q) {
18447400aaeSHoratiu Vultur 		vid_key = VCAP_KF_8021Q_VID1;
18547400aaeSHoratiu Vultur 		pcp_key = VCAP_KF_8021Q_PCP1;
18647400aaeSHoratiu Vultur 	}
18747400aaeSHoratiu Vultur 
18847400aaeSHoratiu Vultur 	if (mt.mask->vlan_id) {
18947400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, vid_key,
19047400aaeSHoratiu Vultur 					    mt.key->vlan_id,
19147400aaeSHoratiu Vultur 					    mt.mask->vlan_id);
19247400aaeSHoratiu Vultur 		if (err)
19347400aaeSHoratiu Vultur 			goto out;
19447400aaeSHoratiu Vultur 	}
19547400aaeSHoratiu Vultur 
19647400aaeSHoratiu Vultur 	if (mt.mask->vlan_priority) {
19747400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
19847400aaeSHoratiu Vultur 					    mt.key->vlan_priority,
19947400aaeSHoratiu Vultur 					    mt.mask->vlan_priority);
20047400aaeSHoratiu Vultur 		if (err)
20147400aaeSHoratiu Vultur 			goto out;
20247400aaeSHoratiu Vultur 	}
20347400aaeSHoratiu Vultur 
204*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN);
20547400aaeSHoratiu Vultur 
20647400aaeSHoratiu Vultur 	return 0;
20747400aaeSHoratiu Vultur out:
20847400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error");
20947400aaeSHoratiu Vultur 	return err;
21047400aaeSHoratiu Vultur }
21147400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_cvlan_usage);
21247400aaeSHoratiu Vultur 
vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage * st,enum vcap_key_field vid_key,enum vcap_key_field pcp_key)21347400aaeSHoratiu Vultur int vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st,
21447400aaeSHoratiu Vultur 				      enum vcap_key_field vid_key,
21547400aaeSHoratiu Vultur 				      enum vcap_key_field pcp_key)
21647400aaeSHoratiu Vultur {
21747400aaeSHoratiu Vultur 	struct flow_match_vlan mt;
21847400aaeSHoratiu Vultur 	int err;
21947400aaeSHoratiu Vultur 
22047400aaeSHoratiu Vultur 	flow_rule_match_vlan(st->frule, &mt);
22147400aaeSHoratiu Vultur 
22247400aaeSHoratiu Vultur 	if (mt.mask->vlan_id) {
22347400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, vid_key,
22447400aaeSHoratiu Vultur 					    mt.key->vlan_id,
22547400aaeSHoratiu Vultur 					    mt.mask->vlan_id);
22647400aaeSHoratiu Vultur 		if (err)
22747400aaeSHoratiu Vultur 			goto out;
22847400aaeSHoratiu Vultur 	}
22947400aaeSHoratiu Vultur 
23047400aaeSHoratiu Vultur 	if (mt.mask->vlan_priority) {
23147400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
23247400aaeSHoratiu Vultur 					    mt.key->vlan_priority,
23347400aaeSHoratiu Vultur 					    mt.mask->vlan_priority);
23447400aaeSHoratiu Vultur 		if (err)
23547400aaeSHoratiu Vultur 			goto out;
23647400aaeSHoratiu Vultur 	}
23747400aaeSHoratiu Vultur 
238ebf44dedSSteen Hegelund 	if (mt.mask->vlan_tpid)
239ebf44dedSSteen Hegelund 		st->tpid = be16_to_cpu(mt.key->vlan_tpid);
240ebf44dedSSteen Hegelund 
241*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_VLAN);
24247400aaeSHoratiu Vultur 
24347400aaeSHoratiu Vultur 	return 0;
24447400aaeSHoratiu Vultur out:
24547400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");
24647400aaeSHoratiu Vultur 	return err;
24747400aaeSHoratiu Vultur }
24847400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_vlan_usage);
24947400aaeSHoratiu Vultur 
vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage * st)25047400aaeSHoratiu Vultur int vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage *st)
25147400aaeSHoratiu Vultur {
25247400aaeSHoratiu Vultur 	struct flow_match_tcp mt;
25347400aaeSHoratiu Vultur 	u16 tcp_flags_mask;
25447400aaeSHoratiu Vultur 	u16 tcp_flags_key;
25547400aaeSHoratiu Vultur 	enum vcap_bit val;
25647400aaeSHoratiu Vultur 	int err = 0;
25747400aaeSHoratiu Vultur 
25847400aaeSHoratiu Vultur 	flow_rule_match_tcp(st->frule, &mt);
25947400aaeSHoratiu Vultur 	tcp_flags_key = be16_to_cpu(mt.key->flags);
26047400aaeSHoratiu Vultur 	tcp_flags_mask = be16_to_cpu(mt.mask->flags);
26147400aaeSHoratiu Vultur 
26247400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_FIN) {
26347400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
26447400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_FIN)
26547400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
26647400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val);
26747400aaeSHoratiu Vultur 		if (err)
26847400aaeSHoratiu Vultur 			goto out;
26947400aaeSHoratiu Vultur 	}
27047400aaeSHoratiu Vultur 
27147400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_SYN) {
27247400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
27347400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_SYN)
27447400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
27547400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val);
27647400aaeSHoratiu Vultur 		if (err)
27747400aaeSHoratiu Vultur 			goto out;
27847400aaeSHoratiu Vultur 	}
27947400aaeSHoratiu Vultur 
28047400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_RST) {
28147400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
28247400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_RST)
28347400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
28447400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val);
28547400aaeSHoratiu Vultur 		if (err)
28647400aaeSHoratiu Vultur 			goto out;
28747400aaeSHoratiu Vultur 	}
28847400aaeSHoratiu Vultur 
28947400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_PSH) {
29047400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
29147400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_PSH)
29247400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
29347400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val);
29447400aaeSHoratiu Vultur 		if (err)
29547400aaeSHoratiu Vultur 			goto out;
29647400aaeSHoratiu Vultur 	}
29747400aaeSHoratiu Vultur 
29847400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_ACK) {
29947400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
30047400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_ACK)
30147400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
30247400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val);
30347400aaeSHoratiu Vultur 		if (err)
30447400aaeSHoratiu Vultur 			goto out;
30547400aaeSHoratiu Vultur 	}
30647400aaeSHoratiu Vultur 
30747400aaeSHoratiu Vultur 	if (tcp_flags_mask & TCPHDR_URG) {
30847400aaeSHoratiu Vultur 		val = VCAP_BIT_0;
30947400aaeSHoratiu Vultur 		if (tcp_flags_key & TCPHDR_URG)
31047400aaeSHoratiu Vultur 			val = VCAP_BIT_1;
31147400aaeSHoratiu Vultur 		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val);
31247400aaeSHoratiu Vultur 		if (err)
31347400aaeSHoratiu Vultur 			goto out;
31447400aaeSHoratiu Vultur 	}
31547400aaeSHoratiu Vultur 
316*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_TCP);
31747400aaeSHoratiu Vultur 
31847400aaeSHoratiu Vultur 	return err;
31947400aaeSHoratiu Vultur 
32047400aaeSHoratiu Vultur out:
32147400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");
32247400aaeSHoratiu Vultur 	return err;
32347400aaeSHoratiu Vultur }
32447400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_tcp_usage);
32547400aaeSHoratiu Vultur 
vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage * st)32647400aaeSHoratiu Vultur int vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage *st)
32747400aaeSHoratiu Vultur {
32847400aaeSHoratiu Vultur 	struct flow_match_arp mt;
32947400aaeSHoratiu Vultur 	u16 value, mask;
33047400aaeSHoratiu Vultur 	u32 ipval, ipmsk;
33147400aaeSHoratiu Vultur 	int err;
33247400aaeSHoratiu Vultur 
33347400aaeSHoratiu Vultur 	flow_rule_match_arp(st->frule, &mt);
33447400aaeSHoratiu Vultur 
33547400aaeSHoratiu Vultur 	if (mt.mask->op) {
33647400aaeSHoratiu Vultur 		mask = 0x3;
33747400aaeSHoratiu Vultur 		if (st->l3_proto == ETH_P_ARP) {
33847400aaeSHoratiu Vultur 			value = mt.key->op == VCAP_ARP_OP_REQUEST ?
33947400aaeSHoratiu Vultur 					VCAP_IS2_ARP_REQUEST :
34047400aaeSHoratiu Vultur 					VCAP_IS2_ARP_REPLY;
34147400aaeSHoratiu Vultur 		} else { /* RARP */
34247400aaeSHoratiu Vultur 			value = mt.key->op == VCAP_ARP_OP_REQUEST ?
34347400aaeSHoratiu Vultur 					VCAP_IS2_RARP_REQUEST :
34447400aaeSHoratiu Vultur 					VCAP_IS2_RARP_REPLY;
34547400aaeSHoratiu Vultur 		}
34647400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE,
34747400aaeSHoratiu Vultur 					    value, mask);
34847400aaeSHoratiu Vultur 		if (err)
34947400aaeSHoratiu Vultur 			goto out;
35047400aaeSHoratiu Vultur 	}
35147400aaeSHoratiu Vultur 
35247400aaeSHoratiu Vultur 	/* The IS2 ARP keyset does not support ARP hardware addresses */
35347400aaeSHoratiu Vultur 	if (!is_zero_ether_addr(mt.mask->sha) ||
35447400aaeSHoratiu Vultur 	    !is_zero_ether_addr(mt.mask->tha)) {
35547400aaeSHoratiu Vultur 		err = -EINVAL;
35647400aaeSHoratiu Vultur 		goto out;
35747400aaeSHoratiu Vultur 	}
35847400aaeSHoratiu Vultur 
35947400aaeSHoratiu Vultur 	if (mt.mask->sip) {
36047400aaeSHoratiu Vultur 		ipval = be32_to_cpu((__force __be32)mt.key->sip);
36147400aaeSHoratiu Vultur 		ipmsk = be32_to_cpu((__force __be32)mt.mask->sip);
36247400aaeSHoratiu Vultur 
36347400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP,
36447400aaeSHoratiu Vultur 					    ipval, ipmsk);
36547400aaeSHoratiu Vultur 		if (err)
36647400aaeSHoratiu Vultur 			goto out;
36747400aaeSHoratiu Vultur 	}
36847400aaeSHoratiu Vultur 
36947400aaeSHoratiu Vultur 	if (mt.mask->tip) {
37047400aaeSHoratiu Vultur 		ipval = be32_to_cpu((__force __be32)mt.key->tip);
37147400aaeSHoratiu Vultur 		ipmsk = be32_to_cpu((__force __be32)mt.mask->tip);
37247400aaeSHoratiu Vultur 
37347400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP,
37447400aaeSHoratiu Vultur 					    ipval, ipmsk);
37547400aaeSHoratiu Vultur 		if (err)
37647400aaeSHoratiu Vultur 			goto out;
37747400aaeSHoratiu Vultur 	}
37847400aaeSHoratiu Vultur 
379*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ARP);
38047400aaeSHoratiu Vultur 
38147400aaeSHoratiu Vultur 	return 0;
38247400aaeSHoratiu Vultur 
38347400aaeSHoratiu Vultur out:
38447400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");
38547400aaeSHoratiu Vultur 	return err;
38647400aaeSHoratiu Vultur }
38747400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_arp_usage);
38847400aaeSHoratiu Vultur 
vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage * st)38947400aaeSHoratiu Vultur int vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage *st)
39047400aaeSHoratiu Vultur {
39147400aaeSHoratiu Vultur 	struct flow_match_ip mt;
39247400aaeSHoratiu Vultur 	int err = 0;
39347400aaeSHoratiu Vultur 
39447400aaeSHoratiu Vultur 	flow_rule_match_ip(st->frule, &mt);
39547400aaeSHoratiu Vultur 
39647400aaeSHoratiu Vultur 	if (mt.mask->tos) {
39747400aaeSHoratiu Vultur 		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS,
39847400aaeSHoratiu Vultur 					    mt.key->tos,
39947400aaeSHoratiu Vultur 					    mt.mask->tos);
40047400aaeSHoratiu Vultur 		if (err)
40147400aaeSHoratiu Vultur 			goto out;
40247400aaeSHoratiu Vultur 	}
40347400aaeSHoratiu Vultur 
404*2b3082c6SRatheesh Kannoth 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IP);
40547400aaeSHoratiu Vultur 
40647400aaeSHoratiu Vultur 	return err;
40747400aaeSHoratiu Vultur 
40847400aaeSHoratiu Vultur out:
40947400aaeSHoratiu Vultur 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");
41047400aaeSHoratiu Vultur 	return err;
41147400aaeSHoratiu Vultur }
41247400aaeSHoratiu Vultur EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ip_usage);
413