brintos

brintos / linux-shallow public Read only

0
0
Text · 9.5 KiB · 27e2dff Raw
413 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/* Microchip VCAP TC3 *4 * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.5 */6 7#include <net/flow_offload.h>8#include <net/ipv6.h>9#include <net/tcp.h>10 11#include "vcap_api_client.h"12#include "vcap_tc.h"13 14enum vcap_is2_arp_opcode {15	VCAP_IS2_ARP_REQUEST,16	VCAP_IS2_ARP_REPLY,17	VCAP_IS2_RARP_REQUEST,18	VCAP_IS2_RARP_REPLY,19};20 21enum vcap_arp_opcode {22	VCAP_ARP_OP_RESERVED,23	VCAP_ARP_OP_REQUEST,24	VCAP_ARP_OP_REPLY,25};26 27int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st)28{29	enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;30	enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC;31	struct flow_match_eth_addrs match;32	struct vcap_u48_key smac, dmac;33	int err = 0;34 35	flow_rule_match_eth_addrs(st->frule, &match);36 37	if (!is_zero_ether_addr(match.mask->src)) {38		vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN);39		vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN);40		err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac);41		if (err)42			goto out;43	}44 45	if (!is_zero_ether_addr(match.mask->dst)) {46		vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN);47		vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN);48		err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac);49		if (err)50			goto out;51	}52 53	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS);54 55	return err;56 57out:58	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error");59	return err;60}61EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ethaddr_usage);62 63int vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage *st)64{65	int err = 0;66 67	if (st->l3_proto == ETH_P_IP) {68		struct flow_match_ipv4_addrs mt;69 70		flow_rule_match_ipv4_addrs(st->frule, &mt);71		if (mt.mask->src) {72			err = vcap_rule_add_key_u32(st->vrule,73						    VCAP_KF_L3_IP4_SIP,74						    be32_to_cpu(mt.key->src),75						    be32_to_cpu(mt.mask->src));76			if (err)77				goto out;78		}79		if (mt.mask->dst) {80			err = vcap_rule_add_key_u32(st->vrule,81						    VCAP_KF_L3_IP4_DIP,82						    be32_to_cpu(mt.key->dst),83						    be32_to_cpu(mt.mask->dst));84			if (err)85				goto out;86		}87	}88 89	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS);90 91	return err;92 93out:94	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");95	return err;96}97EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv4_usage);98 99int vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage *st)100{101	int err = 0;102 103	if (st->l3_proto == ETH_P_IPV6) {104		struct flow_match_ipv6_addrs mt;105		struct vcap_u128_key sip;106		struct vcap_u128_key dip;107 108		flow_rule_match_ipv6_addrs(st->frule, &mt);109		/* Check if address masks are non-zero */110		if (!ipv6_addr_any(&mt.mask->src)) {111			vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16);112			vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16);113			err = vcap_rule_add_key_u128(st->vrule,114						     VCAP_KF_L3_IP6_SIP, &sip);115			if (err)116				goto out;117		}118		if (!ipv6_addr_any(&mt.mask->dst)) {119			vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16);120			vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16);121			err = vcap_rule_add_key_u128(st->vrule,122						     VCAP_KF_L3_IP6_DIP, &dip);123			if (err)124				goto out;125		}126	}127	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS);128	return err;129out:130	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");131	return err;132}133EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv6_usage);134 135int vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage *st)136{137	struct flow_match_ports mt;138	u16 value, mask;139	int err = 0;140 141	flow_rule_match_ports(st->frule, &mt);142 143	if (mt.mask->src) {144		value = be16_to_cpu(mt.key->src);145		mask = be16_to_cpu(mt.mask->src);146		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value,147					    mask);148		if (err)149			goto out;150	}151 152	if (mt.mask->dst) {153		value = be16_to_cpu(mt.key->dst);154		mask = be16_to_cpu(mt.mask->dst);155		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value,156					    mask);157		if (err)158			goto out;159	}160 161	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_PORTS);162 163	return err;164 165out:166	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");167	return err;168}169EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_portnum_usage);170 171int vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)172{173	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0;174	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0;175	struct flow_match_vlan mt;176	u16 tpid;177	int err;178 179	flow_rule_match_cvlan(st->frule, &mt);180 181	tpid = be16_to_cpu(mt.key->vlan_tpid);182 183	if (tpid == ETH_P_8021Q) {184		vid_key = VCAP_KF_8021Q_VID1;185		pcp_key = VCAP_KF_8021Q_PCP1;186	}187 188	if (mt.mask->vlan_id) {189		err = vcap_rule_add_key_u32(st->vrule, vid_key,190					    mt.key->vlan_id,191					    mt.mask->vlan_id);192		if (err)193			goto out;194	}195 196	if (mt.mask->vlan_priority) {197		err = vcap_rule_add_key_u32(st->vrule, pcp_key,198					    mt.key->vlan_priority,199					    mt.mask->vlan_priority);200		if (err)201			goto out;202	}203 204	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN);205 206	return 0;207out:208	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error");209	return err;210}211EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_cvlan_usage);212 213int vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st,214				      enum vcap_key_field vid_key,215				      enum vcap_key_field pcp_key)216{217	struct flow_match_vlan mt;218	int err;219 220	flow_rule_match_vlan(st->frule, &mt);221 222	if (mt.mask->vlan_id) {223		err = vcap_rule_add_key_u32(st->vrule, vid_key,224					    mt.key->vlan_id,225					    mt.mask->vlan_id);226		if (err)227			goto out;228	}229 230	if (mt.mask->vlan_priority) {231		err = vcap_rule_add_key_u32(st->vrule, pcp_key,232					    mt.key->vlan_priority,233					    mt.mask->vlan_priority);234		if (err)235			goto out;236	}237 238	if (mt.mask->vlan_tpid)239		st->tpid = be16_to_cpu(mt.key->vlan_tpid);240 241	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_VLAN);242 243	return 0;244out:245	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");246	return err;247}248EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_vlan_usage);249 250int vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage *st)251{252	struct flow_match_tcp mt;253	u16 tcp_flags_mask;254	u16 tcp_flags_key;255	enum vcap_bit val;256	int err = 0;257 258	flow_rule_match_tcp(st->frule, &mt);259	tcp_flags_key = be16_to_cpu(mt.key->flags);260	tcp_flags_mask = be16_to_cpu(mt.mask->flags);261 262	if (tcp_flags_mask & TCPHDR_FIN) {263		val = VCAP_BIT_0;264		if (tcp_flags_key & TCPHDR_FIN)265			val = VCAP_BIT_1;266		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val);267		if (err)268			goto out;269	}270 271	if (tcp_flags_mask & TCPHDR_SYN) {272		val = VCAP_BIT_0;273		if (tcp_flags_key & TCPHDR_SYN)274			val = VCAP_BIT_1;275		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val);276		if (err)277			goto out;278	}279 280	if (tcp_flags_mask & TCPHDR_RST) {281		val = VCAP_BIT_0;282		if (tcp_flags_key & TCPHDR_RST)283			val = VCAP_BIT_1;284		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val);285		if (err)286			goto out;287	}288 289	if (tcp_flags_mask & TCPHDR_PSH) {290		val = VCAP_BIT_0;291		if (tcp_flags_key & TCPHDR_PSH)292			val = VCAP_BIT_1;293		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val);294		if (err)295			goto out;296	}297 298	if (tcp_flags_mask & TCPHDR_ACK) {299		val = VCAP_BIT_0;300		if (tcp_flags_key & TCPHDR_ACK)301			val = VCAP_BIT_1;302		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val);303		if (err)304			goto out;305	}306 307	if (tcp_flags_mask & TCPHDR_URG) {308		val = VCAP_BIT_0;309		if (tcp_flags_key & TCPHDR_URG)310			val = VCAP_BIT_1;311		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val);312		if (err)313			goto out;314	}315 316	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_TCP);317 318	return err;319 320out:321	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");322	return err;323}324EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_tcp_usage);325 326int vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage *st)327{328	struct flow_match_arp mt;329	u16 value, mask;330	u32 ipval, ipmsk;331	int err;332 333	flow_rule_match_arp(st->frule, &mt);334 335	if (mt.mask->op) {336		mask = 0x3;337		if (st->l3_proto == ETH_P_ARP) {338			value = mt.key->op == VCAP_ARP_OP_REQUEST ?339					VCAP_IS2_ARP_REQUEST :340					VCAP_IS2_ARP_REPLY;341		} else { /* RARP */342			value = mt.key->op == VCAP_ARP_OP_REQUEST ?343					VCAP_IS2_RARP_REQUEST :344					VCAP_IS2_RARP_REPLY;345		}346		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE,347					    value, mask);348		if (err)349			goto out;350	}351 352	/* The IS2 ARP keyset does not support ARP hardware addresses */353	if (!is_zero_ether_addr(mt.mask->sha) ||354	    !is_zero_ether_addr(mt.mask->tha)) {355		err = -EINVAL;356		goto out;357	}358 359	if (mt.mask->sip) {360		ipval = be32_to_cpu((__force __be32)mt.key->sip);361		ipmsk = be32_to_cpu((__force __be32)mt.mask->sip);362 363		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP,364					    ipval, ipmsk);365		if (err)366			goto out;367	}368 369	if (mt.mask->tip) {370		ipval = be32_to_cpu((__force __be32)mt.key->tip);371		ipmsk = be32_to_cpu((__force __be32)mt.mask->tip);372 373		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP,374					    ipval, ipmsk);375		if (err)376			goto out;377	}378 379	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ARP);380 381	return 0;382 383out:384	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");385	return err;386}387EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_arp_usage);388 389int vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage *st)390{391	struct flow_match_ip mt;392	int err = 0;393 394	flow_rule_match_ip(st->frule, &mt);395 396	if (mt.mask->tos) {397		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS,398					    mt.key->tos,399					    mt.mask->tos);400		if (err)401			goto out;402	}403 404	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IP);405 406	return err;407 408out:409	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");410	return err;411}412EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ip_usage);413