Linux Audio

Check our new training course

Loading...
v6.8
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Microchip VCAP API
   3 *
   4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
   5 */
   6
   7#include <net/tc_act/tc_gate.h>
   8#include <net/tcp.h>
   9
  10#include "sparx5_tc.h"
  11#include "vcap_api.h"
  12#include "vcap_api_client.h"
  13#include "vcap_tc.h"
  14#include "sparx5_main.h"
  15#include "sparx5_vcap_impl.h"
  16
  17#define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */
  18
  19/* Collect keysets and type ids for multiple rules per size */
  20struct sparx5_wildcard_rule {
  21	bool selected;
  22	u8 value;
  23	u8 mask;
  24	enum vcap_keyfield_set keyset;
  25};
  26
  27struct sparx5_multiple_rules {
  28	struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE];
  29};
  30
  31struct sparx5_tc_flower_template {
  32	struct list_head list; /* for insertion in the list of templates */
  33	int cid; /* chain id */
  34	enum vcap_keyfield_set orig; /* keyset used before the template */
  35	enum vcap_keyfield_set keyset; /* new keyset used by template */
  36	u16 l3_proto; /* protocol specified in the template */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  37};
  38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  39static int
  40sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
  41{
  42	int err = 0;
  43
  44	switch (st->tpid) {
  45	case ETH_P_8021Q:
  46		err = vcap_rule_add_key_u32(st->vrule,
  47					    VCAP_KF_8021Q_TPID,
  48					    SPX5_TPID_SEL_8100, ~0);
  49		break;
  50	case ETH_P_8021AD:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  51		err = vcap_rule_add_key_u32(st->vrule,
  52					    VCAP_KF_8021Q_TPID,
  53					    SPX5_TPID_SEL_88A8, ~0);
  54		break;
  55	default:
  56		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
  57				   "Invalid vlan proto");
  58		err = -EINVAL;
  59		break;
  60	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  61	return err;
  62}
  63
  64static int
  65sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
  66{
  67	struct flow_match_basic mt;
  68	int err = 0;
  69
  70	flow_rule_match_basic(st->frule, &mt);
  71
  72	if (mt.mask->n_proto) {
  73		st->l3_proto = be16_to_cpu(mt.key->n_proto);
  74		if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) {
  75			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
  76						    st->l3_proto, ~0);
  77			if (err)
  78				goto out;
  79		} else if (st->l3_proto == ETH_P_IP) {
  80			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
  81						    VCAP_BIT_1);
  82			if (err)
  83				goto out;
  84		} else if (st->l3_proto == ETH_P_IPV6) {
  85			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
  86						    VCAP_BIT_0);
  87			if (err)
  88				goto out;
  89			if (st->admin->vtype == VCAP_TYPE_IS0) {
  90				err = vcap_rule_add_key_bit(st->vrule,
  91							    VCAP_KF_IP_SNAP_IS,
  92							    VCAP_BIT_1);
  93				if (err)
  94					goto out;
  95			}
  96		}
  97	}
  98
  99	if (mt.mask->ip_proto) {
 100		st->l4_proto = mt.key->ip_proto;
 101		if (st->l4_proto == IPPROTO_TCP) {
 102			err = vcap_rule_add_key_bit(st->vrule,
 103						    VCAP_KF_TCP_IS,
 104						    VCAP_BIT_1);
 105			if (err)
 106				goto out;
 107		} else if (st->l4_proto == IPPROTO_UDP) {
 108			err = vcap_rule_add_key_bit(st->vrule,
 109						    VCAP_KF_TCP_IS,
 110						    VCAP_BIT_0);
 111			if (err)
 112				goto out;
 113			if (st->admin->vtype == VCAP_TYPE_IS0) {
 114				err = vcap_rule_add_key_bit(st->vrule,
 115							    VCAP_KF_TCP_UDP_IS,
 116							    VCAP_BIT_1);
 117				if (err)
 118					goto out;
 119			}
 120		} else {
 121			err = vcap_rule_add_key_u32(st->vrule,
 122						    VCAP_KF_L3_IP_PROTO,
 123						    st->l4_proto, ~0);
 124			if (err)
 125				goto out;
 126		}
 127	}
 128
 129	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC);
 130
 131	return err;
 132
 133out:
 134	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
 135	return err;
 136}
 137
 138static int
 139sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
 140{
 141	struct flow_match_control mt;
 142	u32 value, mask;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 143	int err = 0;
 144
 145	flow_rule_match_control(st->frule, &mt);
 
 
 
 
 
 
 
 
 
 
 
 146
 147	if (mt.mask->flags) {
 148		if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
 149			if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
 150				value = 1; /* initial fragment */
 151				mask = 0x3;
 152			} else {
 153				if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
 154					value = 3; /* follow up fragment */
 155					mask = 0x3;
 156				} else {
 157					value = 0; /* no fragment */
 158					mask = 0x3;
 159				}
 160			}
 161		} else {
 162			if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
 163				value = 3; /* follow up fragment */
 164				mask = 0x3;
 165			} else {
 166				value = 0; /* no fragment */
 167				mask = 0x3;
 168			}
 169		}
 170
 171		err = vcap_rule_add_key_u32(st->vrule,
 172					    VCAP_KF_L3_FRAGMENT_TYPE,
 173					    value, mask);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 174		if (err)
 175			goto out;
 176	}
 177
 178	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL);
 
 
 
 
 
 
 
 
 
 179
 180	return err;
 181
 182out:
 183	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
 184	return err;
 185}
 186
 187static int
 188sparx5_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
 189{
 190	if (st->admin->vtype != VCAP_TYPE_IS0) {
 191		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
 192				   "cvlan not supported in this VCAP");
 193		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 194	}
 195
 196	return vcap_tc_flower_handler_cvlan_usage(st);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 197}
 198
 199static int
 200sparx5_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)
 201{
 202	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
 203	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
 204	int err;
 205
 206	if (st->admin->vtype == VCAP_TYPE_IS0) {
 207		vid_key = VCAP_KF_8021Q_VID0;
 208		pcp_key = VCAP_KF_8021Q_PCP0;
 
 
 
 
 
 209	}
 210
 211	err = vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key);
 212	if (err)
 213		return err;
 214
 215	if (st->admin->vtype == VCAP_TYPE_ES0 && st->tpid)
 216		err = sparx5_tc_flower_es0_tpid(st);
 217
 
 
 218	return err;
 219}
 220
 221static int (*sparx5_tc_flower_usage_handlers[])(struct vcap_tc_flower_parse_usage *st) = {
 222	[FLOW_DISSECTOR_KEY_ETH_ADDRS] = vcap_tc_flower_handler_ethaddr_usage,
 223	[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = vcap_tc_flower_handler_ipv4_usage,
 224	[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = vcap_tc_flower_handler_ipv6_usage,
 225	[FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage,
 226	[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,
 227	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
 228	[FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage,
 229	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
 230	[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,
 231	[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage,
 232	[FLOW_DISSECTOR_KEY_IP] = vcap_tc_flower_handler_ip_usage,
 233};
 234
 235static int sparx5_tc_use_dissectors(struct vcap_tc_flower_parse_usage *st,
 236				    struct vcap_admin *admin,
 237				    struct vcap_rule *vrule)
 
 238{
 
 
 
 
 
 239	int idx, err = 0;
 240
 
 241	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) {
 242		if (!flow_rule_match_key(st->frule, idx))
 243			continue;
 244		if (!sparx5_tc_flower_usage_handlers[idx])
 245			continue;
 246		err = sparx5_tc_flower_usage_handlers[idx](st);
 247		if (err)
 248			return err;
 249	}
 250
 251	if (st->frule->match.dissector->used_keys ^ st->used_keys) {
 252		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
 253				   "Unsupported match item");
 254		return -ENOENT;
 255	}
 256
 
 
 257	return err;
 258}
 259
 260static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
 261					 struct net_device *ndev,
 262					 struct flow_cls_offload *fco,
 263					 bool ingress)
 264{
 265	struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
 266	struct flow_action_entry *actent, *last_actent = NULL;
 267	struct flow_action *act = &rule->action;
 268	u64 action_mask = 0;
 269	int idx;
 270
 271	if (!flow_action_has_entries(act)) {
 272		NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions");
 273		return -EINVAL;
 274	}
 275
 276	if (!flow_action_basic_hw_stats_check(act, fco->common.extack))
 277		return -EOPNOTSUPP;
 278
 279	flow_action_for_each(idx, actent, act) {
 280		if (action_mask & BIT(actent->id)) {
 281			NL_SET_ERR_MSG_MOD(fco->common.extack,
 282					   "More actions of the same type");
 283			return -EINVAL;
 284		}
 285		action_mask |= BIT(actent->id);
 286		last_actent = actent; /* Save last action for later check */
 287	}
 288
 289	/* Check if last action is a goto
 290	 * The last chain/lookup does not need to have a goto action
 291	 */
 292	if (last_actent->id == FLOW_ACTION_GOTO) {
 293		/* Check if the destination chain is in one of the VCAPs */
 294		if (!vcap_is_next_lookup(vctrl, fco->common.chain_index,
 295					 last_actent->chain_index)) {
 296			NL_SET_ERR_MSG_MOD(fco->common.extack,
 297					   "Invalid goto chain");
 298			return -EINVAL;
 299		}
 300	} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index,
 301				       ingress)) {
 302		NL_SET_ERR_MSG_MOD(fco->common.extack,
 303				   "Last action must be 'goto'");
 304		return -EINVAL;
 305	}
 306
 
 
 
 
 
 
 
 
 307	/* Catch unsupported combinations of actions */
 308	if (action_mask & BIT(FLOW_ACTION_TRAP) &&
 309	    action_mask & BIT(FLOW_ACTION_ACCEPT)) {
 310		NL_SET_ERR_MSG_MOD(fco->common.extack,
 311				   "Cannot combine pass and trap action");
 312		return -EOPNOTSUPP;
 313	}
 314
 315	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
 316	    action_mask & BIT(FLOW_ACTION_VLAN_POP)) {
 317		NL_SET_ERR_MSG_MOD(fco->common.extack,
 318				   "Cannot combine vlan push and pop action");
 319		return -EOPNOTSUPP;
 320	}
 321
 322	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
 323	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
 324		NL_SET_ERR_MSG_MOD(fco->common.extack,
 325				   "Cannot combine vlan push and modify action");
 326		return -EOPNOTSUPP;
 327	}
 328
 329	if (action_mask & BIT(FLOW_ACTION_VLAN_POP) &&
 330	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
 331		NL_SET_ERR_MSG_MOD(fco->common.extack,
 332				   "Cannot combine vlan pop and modify action");
 333		return -EOPNOTSUPP;
 334	}
 335
 336	return 0;
 337}
 338
 339/* Add a rule counter action */
 340static int sparx5_tc_add_rule_counter(struct vcap_admin *admin,
 341				      struct vcap_rule *vrule)
 342{
 343	int err;
 344
 345	switch (admin->vtype) {
 346	case VCAP_TYPE_IS0:
 347		break;
 348	case VCAP_TYPE_ES0:
 349		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX,
 350					       vrule->id);
 351		if (err)
 352			return err;
 353		vcap_rule_set_counter_id(vrule, vrule->id);
 354		break;
 355	case VCAP_TYPE_IS2:
 356	case VCAP_TYPE_ES2:
 357		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID,
 358					       vrule->id);
 359		if (err)
 360			return err;
 361		vcap_rule_set_counter_id(vrule, vrule->id);
 362		break;
 363	default:
 364		pr_err("%s:%d: vcap type: %d not supported\n",
 365		       __func__, __LINE__, admin->vtype);
 366		break;
 367	}
 368	return 0;
 369}
 370
 371/* Collect all port keysets and apply the first of them, possibly wildcarded */
 372static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,
 373					    struct vcap_rule *vrule,
 374					    struct vcap_admin *admin,
 375					    u16 l3_proto,
 376					    struct sparx5_multiple_rules *multi)
 377{
 378	struct sparx5_port *port = netdev_priv(ndev);
 379	struct vcap_keyset_list portkeysetlist = {};
 380	enum vcap_keyfield_set portkeysets[10] = {};
 381	struct vcap_keyset_list matches = {};
 382	enum vcap_keyfield_set keysets[10];
 383	int idx, jdx, err = 0, count = 0;
 384	struct sparx5_wildcard_rule *mru;
 385	const struct vcap_set *kinfo;
 386	struct vcap_control *vctrl;
 387
 388	vctrl = port->sparx5->vcap_ctrl;
 389
 390	/* Find the keysets that the rule can use */
 391	matches.keysets = keysets;
 392	matches.max = ARRAY_SIZE(keysets);
 393	if (!vcap_rule_find_keysets(vrule, &matches))
 394		return -EINVAL;
 395
 396	/* Find the keysets that the port configuration supports */
 397	portkeysetlist.max = ARRAY_SIZE(portkeysets);
 398	portkeysetlist.keysets = portkeysets;
 399	err = sparx5_vcap_get_port_keyset(ndev,
 400					  admin, vrule->vcap_chain_id,
 401					  l3_proto,
 402					  &portkeysetlist);
 403	if (err)
 404		return err;
 405
 406	/* Find the intersection of the two sets of keyset */
 407	for (idx = 0; idx < portkeysetlist.cnt; ++idx) {
 408		kinfo = vcap_keyfieldset(vctrl, admin->vtype,
 409					 portkeysetlist.keysets[idx]);
 410		if (!kinfo)
 411			continue;
 412
 413		/* Find a port keyset that matches the required keys
 414		 * If there are multiple keysets then compose a type id mask
 415		 */
 416		for (jdx = 0; jdx < matches.cnt; ++jdx) {
 417			if (portkeysetlist.keysets[idx] != matches.keysets[jdx])
 418				continue;
 419
 420			mru = &multi->rule[kinfo->sw_per_item];
 421			if (!mru->selected) {
 422				mru->selected = true;
 423				mru->keyset = portkeysetlist.keysets[idx];
 424				mru->value = kinfo->type_id;
 425			}
 426			mru->value &= kinfo->type_id;
 427			mru->mask |= kinfo->type_id;
 428			++count;
 429		}
 430	}
 431	if (count == 0)
 432		return -EPROTO;
 433
 434	if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt)
 435		return -ENOENT;
 436
 437	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 438		mru = &multi->rule[idx];
 439		if (!mru->selected)
 440			continue;
 441
 442		/* Align the mask to the combined value */
 443		mru->mask ^= mru->value;
 444	}
 445
 446	/* Set the chosen keyset on the rule and set a wildcarded type if there
 447	 * are more than one keyset
 448	 */
 449	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 450		mru = &multi->rule[idx];
 451		if (!mru->selected)
 452			continue;
 453
 454		vcap_set_rule_set_keyset(vrule, mru->keyset);
 455		if (count > 1)
 456			/* Some keysets do not have a type field */
 457			vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE,
 458					      mru->value,
 459					      ~mru->mask);
 460		mru->selected = false; /* mark as done */
 461		break; /* Stop here and add more rules later */
 462	}
 463	return err;
 464}
 465
 466static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl,
 467				   struct flow_cls_offload *fco,
 468				   struct vcap_rule *erule,
 469				   struct vcap_admin *admin,
 470				   struct sparx5_wildcard_rule *rule)
 471{
 472	enum vcap_key_field keylist[] = {
 473		VCAP_KF_IF_IGR_PORT_MASK,
 474		VCAP_KF_IF_IGR_PORT_MASK_SEL,
 475		VCAP_KF_IF_IGR_PORT_MASK_RNG,
 476		VCAP_KF_LOOKUP_FIRST_IS,
 477		VCAP_KF_TYPE,
 478	};
 479	struct vcap_rule *vrule;
 480	int err;
 481
 482	/* Add an extra rule with a special user and the new keyset */
 483	erule->user = VCAP_USER_TC_EXTRA;
 484	vrule = vcap_copy_rule(erule);
 485	if (IS_ERR(vrule))
 486		return PTR_ERR(vrule);
 487
 488	/* Link the new rule to the existing rule with the cookie */
 489	vrule->cookie = erule->cookie;
 490	vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true);
 491	err = vcap_set_rule_set_keyset(vrule, rule->keyset);
 492	if (err) {
 493		pr_err("%s:%d: could not set keyset %s in rule: %u\n",
 494		       __func__, __LINE__,
 495		       vcap_keyset_name(vctrl, rule->keyset),
 496		       vrule->id);
 497		goto out;
 498	}
 499
 500	/* Some keysets do not have a type field, so ignore return value */
 501	vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask);
 502
 503	err = vcap_set_rule_set_actionset(vrule, erule->actionset);
 504	if (err)
 505		goto out;
 506
 507	err = sparx5_tc_add_rule_counter(admin, vrule);
 508	if (err)
 509		goto out;
 510
 511	err = vcap_val_rule(vrule, ETH_P_ALL);
 512	if (err) {
 513		pr_err("%s:%d: could not validate rule: %u\n",
 514		       __func__, __LINE__, vrule->id);
 515		vcap_set_tc_exterr(fco, vrule);
 516		goto out;
 517	}
 518	err = vcap_add_rule(vrule);
 519	if (err) {
 520		pr_err("%s:%d: could not add rule: %u\n",
 521		       __func__, __LINE__, vrule->id);
 522		goto out;
 523	}
 524out:
 525	vcap_free_rule(vrule);
 526	return err;
 527}
 528
 529static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl,
 530					 struct flow_cls_offload *fco,
 531					 struct vcap_rule *erule,
 532					 struct vcap_admin *admin,
 533					 struct sparx5_multiple_rules *multi)
 534{
 535	int idx, err = 0;
 536
 537	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 538		if (!multi->rule[idx].selected)
 539			continue;
 540
 541		err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin,
 542					      &multi->rule[idx]);
 543		if (err)
 544			break;
 545	}
 546	return err;
 547}
 548
 549/* Add the actionset that is the default for the VCAP type */
 550static int sparx5_tc_set_actionset(struct vcap_admin *admin,
 551				   struct vcap_rule *vrule)
 552{
 553	enum vcap_actionfield_set aset;
 554	int err = 0;
 555
 556	switch (admin->vtype) {
 557	case VCAP_TYPE_IS0:
 558		aset = VCAP_AFS_CLASSIFICATION;
 559		break;
 560	case VCAP_TYPE_IS2:
 561		aset = VCAP_AFS_BASE_TYPE;
 562		break;
 563	case VCAP_TYPE_ES0:
 564		aset = VCAP_AFS_ES0;
 565		break;
 566	case VCAP_TYPE_ES2:
 567		aset = VCAP_AFS_BASE_TYPE;
 568		break;
 569	default:
 570		pr_err("%s:%d: %s\n", __func__, __LINE__, "Invalid VCAP type");
 571		return -EINVAL;
 572	}
 573	/* Do not overwrite any current actionset */
 574	if (vrule->actionset == VCAP_AFS_NO_VALUE)
 575		err = vcap_set_rule_set_actionset(vrule, aset);
 576	return err;
 577}
 578
 579/* Add the VCAP key to match on for a rule target value */
 580static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin,
 581					  struct vcap_rule *vrule,
 582					  int target_cid)
 583{
 584	int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
 585	int err;
 586
 587	if (!link_val)
 588		return 0;
 589
 590	switch (admin->vtype) {
 591	case VCAP_TYPE_IS0:
 592		/* Add NXT_IDX key for chaining rules between IS0 instances */
 593		err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
 594					    1, /* enable */
 595					    ~0);
 596		if (err)
 597			return err;
 598		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
 599					     link_val, /* target */
 600					     ~0);
 601	case VCAP_TYPE_IS2:
 602		/* Add PAG key for chaining rules from IS0 */
 603		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
 604					     link_val, /* target */
 605					     ~0);
 606	case VCAP_TYPE_ES0:
 607	case VCAP_TYPE_ES2:
 608		/* Add ISDX key for chaining rules from IS0 */
 609		return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS, link_val,
 610					     ~0);
 611	default:
 612		break;
 613	}
 614	return 0;
 615}
 616
 617/* Add the VCAP action that adds a target value to a rule */
 618static int sparx5_tc_add_rule_link(struct vcap_control *vctrl,
 619				   struct vcap_admin *admin,
 620				   struct vcap_rule *vrule,
 621				   int from_cid, int to_cid)
 622{
 623	struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
 624	int diff, err = 0;
 625
 626	if (!to_admin) {
 627		pr_err("%s:%d: unsupported chain direction: %d\n",
 628		       __func__, __LINE__, to_cid);
 629		return -EINVAL;
 630	}
 631
 632	diff = vcap_chain_offset(vctrl, from_cid, to_cid);
 633	if (!diff)
 634		return 0;
 635
 636	if (admin->vtype == VCAP_TYPE_IS0 &&
 637	    to_admin->vtype == VCAP_TYPE_IS0) {
 638		/* Between IS0 instances the G_IDX value is used */
 639		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff);
 640		if (err)
 641			goto out;
 642		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL,
 643					       1); /* Replace */
 644		if (err)
 645			goto out;
 646	} else if (admin->vtype == VCAP_TYPE_IS0 &&
 647		   to_admin->vtype == VCAP_TYPE_IS2) {
 648		/* Between IS0 and IS2 the PAG value is used */
 649		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
 650		if (err)
 651			goto out;
 652		err = vcap_rule_add_action_u32(vrule,
 653					       VCAP_AF_PAG_OVERRIDE_MASK,
 654					       0xff);
 655		if (err)
 656			goto out;
 657	} else if (admin->vtype == VCAP_TYPE_IS0 &&
 658		   (to_admin->vtype == VCAP_TYPE_ES0 ||
 659		    to_admin->vtype == VCAP_TYPE_ES2)) {
 660		/* Between IS0 and ES0/ES2 the ISDX value is used */
 661		err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL,
 662					       diff);
 663		if (err)
 664			goto out;
 665		err = vcap_rule_add_action_bit(vrule,
 666					       VCAP_AF_ISDX_ADD_REPLACE_SEL,
 667					       VCAP_BIT_1);
 668		if (err)
 669			goto out;
 670	} else {
 671		pr_err("%s:%d: unsupported chain destination: %d\n",
 672		       __func__, __LINE__, to_cid);
 673		err = -EOPNOTSUPP;
 674	}
 675out:
 676	return err;
 677}
 678
 679static int sparx5_tc_flower_parse_act_gate(struct sparx5_psfp_sg *sg,
 680					   struct flow_action_entry *act,
 681					   struct netlink_ext_ack *extack)
 682{
 683	int i;
 684
 685	if (act->gate.prio < -1 || act->gate.prio > SPX5_PSFP_SG_MAX_IPV) {
 686		NL_SET_ERR_MSG_MOD(extack, "Invalid gate priority");
 687		return -EINVAL;
 688	}
 689
 690	if (act->gate.cycletime < SPX5_PSFP_SG_MIN_CYCLE_TIME_NS ||
 691	    act->gate.cycletime > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
 692		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletime");
 693		return -EINVAL;
 694	}
 695
 696	if (act->gate.cycletimeext > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
 697		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletimeext");
 698		return -EINVAL;
 699	}
 700
 701	if (act->gate.num_entries >= SPX5_PSFP_GCE_CNT) {
 702		NL_SET_ERR_MSG_MOD(extack, "Invalid number of gate entries");
 703		return -EINVAL;
 704	}
 705
 706	sg->gate_state = true;
 707	sg->ipv = act->gate.prio;
 708	sg->num_entries = act->gate.num_entries;
 709	sg->cycletime = act->gate.cycletime;
 710	sg->cycletimeext = act->gate.cycletimeext;
 711
 712	for (i = 0; i < sg->num_entries; i++) {
 713		sg->gce[i].gate_state = !!act->gate.entries[i].gate_state;
 714		sg->gce[i].interval = act->gate.entries[i].interval;
 715		sg->gce[i].ipv = act->gate.entries[i].ipv;
 716		sg->gce[i].maxoctets = act->gate.entries[i].maxoctets;
 717	}
 718
 719	return 0;
 720}
 721
 722static int sparx5_tc_flower_parse_act_police(struct sparx5_policer *pol,
 723					     struct flow_action_entry *act,
 724					     struct netlink_ext_ack *extack)
 725{
 726	pol->type = SPX5_POL_SERVICE;
 727	pol->rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
 728	pol->burst = act->police.burst;
 729	pol->idx = act->hw_index;
 730
 731	/* rate is now in kbit */
 732	if (pol->rate > DIV_ROUND_UP(SPX5_SDLB_GROUP_RATE_MAX, 1000)) {
 733		NL_SET_ERR_MSG_MOD(extack, "Maximum rate exceeded");
 734		return -EINVAL;
 735	}
 736
 737	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
 738		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when exceed action is not drop");
 739		return -EOPNOTSUPP;
 740	}
 741
 742	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
 743	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
 744		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform action is not pipe or ok");
 745		return -EOPNOTSUPP;
 746	}
 747
 748	return 0;
 749}
 750
 751static int sparx5_tc_flower_psfp_setup(struct sparx5 *sparx5,
 752				       struct vcap_rule *vrule, int sg_idx,
 753				       int pol_idx, struct sparx5_psfp_sg *sg,
 754				       struct sparx5_psfp_fm *fm,
 755				       struct sparx5_psfp_sf *sf)
 756{
 757	u32 psfp_sfid = 0, psfp_fmid = 0, psfp_sgid = 0;
 758	int ret;
 759
 760	/* Must always have a stream gate - max sdu (filter option) is evaluated
 761	 * after frames have passed the gate, so in case of only a policer, we
 762	 * allocate a stream gate that is always open.
 763	 */
 764	if (sg_idx < 0) {
 765		sg_idx = sparx5_pool_idx_to_id(SPX5_PSFP_SG_OPEN);
 766		sg->ipv = 0; /* Disabled */
 767		sg->cycletime = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
 768		sg->num_entries = 1;
 769		sg->gate_state = 1; /* Open */
 770		sg->gate_enabled = 1;
 771		sg->gce[0].gate_state = 1;
 772		sg->gce[0].interval = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
 773		sg->gce[0].ipv = 0;
 774		sg->gce[0].maxoctets = 0; /* Disabled */
 775	}
 776
 777	ret = sparx5_psfp_sg_add(sparx5, sg_idx, sg, &psfp_sgid);
 778	if (ret < 0)
 779		return ret;
 780
 781	if (pol_idx >= 0) {
 782		/* Add new flow-meter */
 783		ret = sparx5_psfp_fm_add(sparx5, pol_idx, fm, &psfp_fmid);
 784		if (ret < 0)
 785			return ret;
 786	}
 787
 788	/* Map stream filter to stream gate */
 789	sf->sgid = psfp_sgid;
 790
 791	/* Add new stream-filter and map it to a steam gate */
 792	ret = sparx5_psfp_sf_add(sparx5, sf, &psfp_sfid);
 793	if (ret < 0)
 794		return ret;
 795
 796	/* Streams are classified by ISDX - map ISDX 1:1 to sfid for now. */
 797	sparx5_isdx_conf_set(sparx5, psfp_sfid, psfp_sfid, psfp_fmid);
 798
 799	ret = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_ADD_REPLACE_SEL,
 800				       VCAP_BIT_1);
 801	if (ret)
 802		return ret;
 803
 804	ret = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL, psfp_sfid);
 805	if (ret)
 806		return ret;
 807
 808	return 0;
 809}
 810
 811/* Handle the action trap for a VCAP rule */
 812static int sparx5_tc_action_trap(struct vcap_admin *admin,
 813				 struct vcap_rule *vrule,
 814				 struct flow_cls_offload *fco)
 815{
 816	int err = 0;
 817
 818	switch (admin->vtype) {
 819	case VCAP_TYPE_IS2:
 820		err = vcap_rule_add_action_bit(vrule,
 821					       VCAP_AF_CPU_COPY_ENA,
 822					       VCAP_BIT_1);
 823		if (err)
 824			break;
 825		err = vcap_rule_add_action_u32(vrule,
 826					       VCAP_AF_CPU_QUEUE_NUM, 0);
 827		if (err)
 828			break;
 829		err = vcap_rule_add_action_u32(vrule,
 830					       VCAP_AF_MASK_MODE,
 831					       SPX5_PMM_REPLACE_ALL);
 832		break;
 833	case VCAP_TYPE_ES0:
 834		err = vcap_rule_add_action_u32(vrule,
 835					       VCAP_AF_FWD_SEL,
 836					       SPX5_FWSEL_REDIRECT_TO_LOOPBACK);
 837		break;
 838	case VCAP_TYPE_ES2:
 839		err = vcap_rule_add_action_bit(vrule,
 840					       VCAP_AF_CPU_COPY_ENA,
 841					       VCAP_BIT_1);
 842		if (err)
 843			break;
 844		err = vcap_rule_add_action_u32(vrule,
 845					       VCAP_AF_CPU_QUEUE_NUM, 0);
 846		break;
 847	default:
 848		NL_SET_ERR_MSG_MOD(fco->common.extack,
 849				   "Trap action not supported in this VCAP");
 850		err = -EOPNOTSUPP;
 851		break;
 852	}
 853	return err;
 854}
 855
 856static int sparx5_tc_action_vlan_pop(struct vcap_admin *admin,
 857				     struct vcap_rule *vrule,
 858				     struct flow_cls_offload *fco,
 859				     u16 tpid)
 860{
 861	int err = 0;
 862
 863	switch (admin->vtype) {
 864	case VCAP_TYPE_ES0:
 865		break;
 866	default:
 867		NL_SET_ERR_MSG_MOD(fco->common.extack,
 868				   "VLAN pop action not supported in this VCAP");
 869		return -EOPNOTSUPP;
 870	}
 871
 872	switch (tpid) {
 873	case ETH_P_8021Q:
 874	case ETH_P_8021AD:
 875		err = vcap_rule_add_action_u32(vrule,
 876					       VCAP_AF_PUSH_OUTER_TAG,
 877					       SPX5_OTAG_UNTAG);
 878		break;
 879	default:
 880		NL_SET_ERR_MSG_MOD(fco->common.extack,
 881				   "Invalid vlan proto");
 882		err = -EINVAL;
 883	}
 884	return err;
 885}
 886
 887static int sparx5_tc_action_vlan_modify(struct vcap_admin *admin,
 888					struct vcap_rule *vrule,
 889					struct flow_cls_offload *fco,
 890					struct flow_action_entry *act,
 891					u16 tpid)
 892{
 893	int err = 0;
 894
 895	switch (admin->vtype) {
 896	case VCAP_TYPE_ES0:
 897		err = vcap_rule_add_action_u32(vrule,
 898					       VCAP_AF_PUSH_OUTER_TAG,
 899					       SPX5_OTAG_TAG_A);
 900		if (err)
 901			return err;
 902		break;
 903	default:
 904		NL_SET_ERR_MSG_MOD(fco->common.extack,
 905				   "VLAN modify action not supported in this VCAP");
 906		return -EOPNOTSUPP;
 907	}
 908
 909	switch (tpid) {
 910	case ETH_P_8021Q:
 911		err = vcap_rule_add_action_u32(vrule,
 912					       VCAP_AF_TAG_A_TPID_SEL,
 913					       SPX5_TPID_A_8100);
 914		break;
 915	case ETH_P_8021AD:
 916		err = vcap_rule_add_action_u32(vrule,
 917					       VCAP_AF_TAG_A_TPID_SEL,
 918					       SPX5_TPID_A_88A8);
 919		break;
 920	default:
 921		NL_SET_ERR_MSG_MOD(fco->common.extack,
 922				   "Invalid vlan proto");
 923		err = -EINVAL;
 924	}
 925	if (err)
 926		return err;
 927
 928	err = vcap_rule_add_action_u32(vrule,
 929				       VCAP_AF_TAG_A_VID_SEL,
 930				       SPX5_VID_A_VAL);
 931	if (err)
 932		return err;
 933
 934	err = vcap_rule_add_action_u32(vrule,
 935				       VCAP_AF_VID_A_VAL,
 936				       act->vlan.vid);
 937	if (err)
 938		return err;
 939
 940	err = vcap_rule_add_action_u32(vrule,
 941				       VCAP_AF_TAG_A_PCP_SEL,
 942				       SPX5_PCP_A_VAL);
 943	if (err)
 944		return err;
 945
 946	err = vcap_rule_add_action_u32(vrule,
 947				       VCAP_AF_PCP_A_VAL,
 948				       act->vlan.prio);
 949	if (err)
 950		return err;
 951
 952	return vcap_rule_add_action_u32(vrule,
 953					VCAP_AF_TAG_A_DEI_SEL,
 954					SPX5_DEI_A_CLASSIFIED);
 955}
 956
 957static int sparx5_tc_action_vlan_push(struct vcap_admin *admin,
 958				      struct vcap_rule *vrule,
 959				      struct flow_cls_offload *fco,
 960				      struct flow_action_entry *act,
 961				      u16 tpid)
 962{
 963	u16 act_tpid = be16_to_cpu(act->vlan.proto);
 964	int err = 0;
 965
 966	switch (admin->vtype) {
 967	case VCAP_TYPE_ES0:
 968		break;
 969	default:
 970		NL_SET_ERR_MSG_MOD(fco->common.extack,
 971				   "VLAN push action not supported in this VCAP");
 972		return -EOPNOTSUPP;
 973	}
 974
 975	if (tpid == ETH_P_8021AD) {
 976		NL_SET_ERR_MSG_MOD(fco->common.extack,
 977				   "Cannot push on double tagged frames");
 978		return -EOPNOTSUPP;
 979	}
 980
 981	err = sparx5_tc_action_vlan_modify(admin, vrule, fco, act, act_tpid);
 982	if (err)
 983		return err;
 984
 985	switch (act_tpid) {
 986	case ETH_P_8021Q:
 987		break;
 988	case ETH_P_8021AD:
 989		/* Push classified tag as inner tag */
 990		err = vcap_rule_add_action_u32(vrule,
 991					       VCAP_AF_PUSH_INNER_TAG,
 992					       SPX5_ITAG_PUSH_B_TAG);
 993		if (err)
 994			break;
 995		err = vcap_rule_add_action_u32(vrule,
 996					       VCAP_AF_TAG_B_TPID_SEL,
 997					       SPX5_TPID_B_CLASSIFIED);
 998		break;
 999	default:
1000		NL_SET_ERR_MSG_MOD(fco->common.extack,
1001				   "Invalid vlan proto");
1002		err = -EINVAL;
1003	}
1004	return err;
1005}
1006
1007/* Remove rule keys that may prevent templates from matching a keyset */
1008static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin,
1009					   struct vcap_rule *vrule,
1010					   u16 l3_proto)
1011{
1012	switch (admin->vtype) {
1013	case VCAP_TYPE_IS0:
1014		vcap_rule_rem_key(vrule, VCAP_KF_ETYPE);
1015		switch (l3_proto) {
1016		case ETH_P_IP:
1017			break;
1018		case ETH_P_IPV6:
1019			vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS);
1020			break;
1021		default:
1022			break;
1023		}
1024		break;
1025	case VCAP_TYPE_ES2:
1026		switch (l3_proto) {
1027		case ETH_P_IP:
1028			if (vrule->keyset == VCAP_KFS_IP4_OTHER)
1029				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1030			break;
1031		case ETH_P_IPV6:
1032			if (vrule->keyset == VCAP_KFS_IP6_STD)
1033				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1034			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1035			break;
1036		default:
1037			break;
1038		}
1039		break;
1040	case VCAP_TYPE_IS2:
1041		switch (l3_proto) {
1042		case ETH_P_IP:
1043		case ETH_P_IPV6:
1044			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1045			break;
1046		default:
1047			break;
1048		}
1049		break;
1050	default:
1051		break;
1052	}
1053}
1054
1055static bool sparx5_tc_flower_use_template(struct net_device *ndev,
1056					  struct flow_cls_offload *fco,
1057					  struct vcap_admin *admin,
1058					  struct vcap_rule *vrule)
1059{
1060	struct sparx5_port *port = netdev_priv(ndev);
1061	struct sparx5_tc_flower_template *ftp;
1062
1063	list_for_each_entry(ftp, &port->tc_templates, list) {
1064		if (ftp->cid != fco->common.chain_index)
1065			continue;
1066
1067		vcap_set_rule_set_keyset(vrule, ftp->keyset);
1068		sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto);
1069		return true;
1070	}
1071	return false;
1072}
1073
1074static int sparx5_tc_flower_replace(struct net_device *ndev,
1075				    struct flow_cls_offload *fco,
1076				    struct vcap_admin *admin,
1077				    bool ingress)
1078{
1079	struct sparx5_psfp_sf sf = { .max_sdu = SPX5_PSFP_SF_MAX_SDU };
1080	struct netlink_ext_ack *extack = fco->common.extack;
1081	int err, idx, tc_sg_idx = -1, tc_pol_idx = -1;
1082	struct vcap_tc_flower_parse_usage state = {
1083		.fco = fco,
1084		.l3_proto = ETH_P_ALL,
1085		.admin = admin,
1086	};
1087	struct sparx5_port *port = netdev_priv(ndev);
1088	struct sparx5_multiple_rules multi = {};
1089	struct sparx5 *sparx5 = port->sparx5;
1090	struct sparx5_psfp_sg sg = { 0 };
1091	struct sparx5_psfp_fm fm = { 0 };
1092	struct flow_action_entry *act;
1093	struct vcap_control *vctrl;
1094	struct flow_rule *frule;
1095	struct vcap_rule *vrule;
 
 
1096
1097	vctrl = port->sparx5->vcap_ctrl;
1098
1099	err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress);
1100	if (err)
1101		return err;
1102
1103	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC,
1104				fco->common.prio, 0);
1105	if (IS_ERR(vrule))
1106		return PTR_ERR(vrule);
1107
1108	vrule->cookie = fco->cookie;
1109
1110	state.vrule = vrule;
1111	state.frule = flow_cls_offload_flow_rule(fco);
1112	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1113	if (err)
1114		goto out;
1115
1116	err = sparx5_tc_add_rule_counter(admin, vrule);
1117	if (err)
1118		goto out;
1119
1120	err = sparx5_tc_add_rule_link_target(admin, vrule,
1121					     fco->common.chain_index);
1122	if (err)
1123		goto out;
1124
1125	frule = flow_cls_offload_flow_rule(fco);
1126	flow_action_for_each(idx, act, &frule->action) {
1127		switch (act->id) {
1128		case FLOW_ACTION_GATE: {
1129			err = sparx5_tc_flower_parse_act_gate(&sg, act, extack);
1130			if (err < 0)
1131				goto out;
1132
1133			tc_sg_idx = act->hw_index;
1134
1135			break;
1136		}
1137		case FLOW_ACTION_POLICE: {
1138			err = sparx5_tc_flower_parse_act_police(&fm.pol, act,
1139								extack);
1140			if (err < 0)
1141				goto out;
1142
1143			tc_pol_idx = fm.pol.idx;
1144			sf.max_sdu = act->police.mtu;
1145
1146			break;
1147		}
1148		case FLOW_ACTION_TRAP:
1149			err = sparx5_tc_action_trap(admin, vrule, fco);
 
 
1150			if (err)
1151				goto out;
1152			break;
1153		case FLOW_ACTION_ACCEPT:
1154			err = sparx5_tc_set_actionset(admin, vrule);
1155			if (err)
1156				goto out;
1157			break;
1158		case FLOW_ACTION_GOTO:
1159			err = sparx5_tc_set_actionset(admin, vrule);
1160			if (err)
1161				goto out;
1162			sparx5_tc_add_rule_link(vctrl, admin, vrule,
1163						fco->common.chain_index,
1164						act->chain_index);
1165			break;
1166		case FLOW_ACTION_VLAN_POP:
1167			err = sparx5_tc_action_vlan_pop(admin, vrule, fco,
1168							state.tpid);
1169			if (err)
1170				goto out;
1171			break;
1172		case FLOW_ACTION_VLAN_PUSH:
1173			err = sparx5_tc_action_vlan_push(admin, vrule, fco,
1174							 act, state.tpid);
 
1175			if (err)
1176				goto out;
1177			break;
1178		case FLOW_ACTION_VLAN_MANGLE:
1179			err = sparx5_tc_action_vlan_modify(admin, vrule, fco,
1180							   act, state.tpid);
1181			if (err)
1182				goto out;
1183			break;
1184		default:
1185			NL_SET_ERR_MSG_MOD(fco->common.extack,
1186					   "Unsupported TC action");
1187			err = -EOPNOTSUPP;
1188			goto out;
1189		}
1190	}
1191
1192	/* Setup PSFP */
1193	if (tc_sg_idx >= 0 || tc_pol_idx >= 0) {
1194		err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx,
1195						  tc_pol_idx, &sg, &fm, &sf);
1196		if (err)
1197			goto out;
1198	}
1199
1200	if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) {
1201		err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin,
1202						       state.l3_proto, &multi);
1203		if (err) {
1204			NL_SET_ERR_MSG_MOD(fco->common.extack,
1205					   "No matching port keyset for filter protocol and keys");
1206			goto out;
1207		}
1208	}
1209
1210	/* provide the l3 protocol to guide the keyset selection */
1211	err = vcap_val_rule(vrule, state.l3_proto);
1212	if (err) {
1213		vcap_set_tc_exterr(fco, vrule);
1214		goto out;
1215	}
1216	err = vcap_add_rule(vrule);
1217	if (err)
1218		NL_SET_ERR_MSG_MOD(fco->common.extack,
1219				   "Could not add the filter");
1220
1221	if (state.l3_proto == ETH_P_ALL)
1222		err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin,
1223						    &multi);
1224
1225out:
1226	vcap_free_rule(vrule);
1227	return err;
1228}
1229
1230static void sparx5_tc_free_psfp_resources(struct sparx5 *sparx5,
1231					  struct vcap_rule *vrule)
1232{
1233	struct vcap_client_actionfield *afield;
1234	u32 isdx, sfid, sgid, fmid;
1235
1236	/* Check if VCAP_AF_ISDX_VAL action is set for this rule - and if
1237	 * it is used for stream and/or flow-meter classification.
1238	 */
1239	afield = vcap_find_actionfield(vrule, VCAP_AF_ISDX_VAL);
1240	if (!afield)
1241		return;
1242
1243	isdx = afield->data.u32.value;
1244	sfid = sparx5_psfp_isdx_get_sf(sparx5, isdx);
1245
1246	if (!sfid)
1247		return;
1248
1249	fmid = sparx5_psfp_isdx_get_fm(sparx5, isdx);
1250	sgid = sparx5_psfp_sf_get_sg(sparx5, sfid);
1251
1252	if (fmid && sparx5_psfp_fm_del(sparx5, fmid) < 0)
1253		pr_err("%s:%d Could not delete invalid fmid: %d", __func__,
1254		       __LINE__, fmid);
1255
1256	if (sgid && sparx5_psfp_sg_del(sparx5, sgid) < 0)
1257		pr_err("%s:%d Could not delete invalid sgid: %d", __func__,
1258		       __LINE__, sgid);
1259
1260	if (sparx5_psfp_sf_del(sparx5, sfid) < 0)
1261		pr_err("%s:%d Could not delete invalid sfid: %d", __func__,
1262		       __LINE__, sfid);
1263
1264	sparx5_isdx_conf_set(sparx5, isdx, 0, 0);
1265}
1266
1267static int sparx5_tc_free_rule_resources(struct net_device *ndev,
1268					 struct vcap_control *vctrl,
1269					 int rule_id)
1270{
1271	struct sparx5_port *port = netdev_priv(ndev);
1272	struct sparx5 *sparx5 = port->sparx5;
1273	struct vcap_rule *vrule;
1274	int ret = 0;
1275
1276	vrule = vcap_get_rule(vctrl, rule_id);
1277	if (IS_ERR(vrule))
1278		return -EINVAL;
1279
1280	sparx5_tc_free_psfp_resources(sparx5, vrule);
1281
1282	vcap_free_rule(vrule);
1283	return ret;
1284}
1285
1286static int sparx5_tc_flower_destroy(struct net_device *ndev,
1287				    struct flow_cls_offload *fco,
1288				    struct vcap_admin *admin)
1289{
1290	struct sparx5_port *port = netdev_priv(ndev);
1291	int err = -ENOENT, count = 0, rule_id;
1292	struct vcap_control *vctrl;
 
1293
1294	vctrl = port->sparx5->vcap_ctrl;
1295	while (true) {
1296		rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie);
1297		if (rule_id <= 0)
1298			break;
1299		if (count == 0) {
1300			/* Resources are attached to the first rule of
1301			 * a set of rules. Only works if the rules are
1302			 * in the correct order.
1303			 */
1304			err = sparx5_tc_free_rule_resources(ndev, vctrl,
1305							    rule_id);
1306			if (err)
1307				pr_err("%s:%d: could not free resources %d\n",
1308				       __func__, __LINE__, rule_id);
1309		}
1310		err = vcap_del_rule(vctrl, ndev, rule_id);
1311		if (err) {
1312			pr_err("%s:%d: could not delete rule %d\n",
1313			       __func__, __LINE__, rule_id);
1314			break;
1315		}
1316	}
1317	return err;
1318}
1319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1320static int sparx5_tc_flower_stats(struct net_device *ndev,
1321				  struct flow_cls_offload *fco,
1322				  struct vcap_admin *admin)
1323{
1324	struct sparx5_port *port = netdev_priv(ndev);
1325	struct vcap_counter ctr = {};
1326	struct vcap_control *vctrl;
1327	ulong lastused = 0;
 
 
1328	int err;
1329
 
1330	vctrl = port->sparx5->vcap_ctrl;
1331	err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie);
1332	if (err)
1333		return err;
1334	flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused,
 
1335			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1336	return err;
1337}
1338
1339static int sparx5_tc_flower_template_create(struct net_device *ndev,
1340					    struct flow_cls_offload *fco,
1341					    struct vcap_admin *admin)
1342{
1343	struct sparx5_port *port = netdev_priv(ndev);
1344	struct vcap_tc_flower_parse_usage state = {
1345		.fco = fco,
1346		.l3_proto = ETH_P_ALL,
1347		.admin = admin,
1348	};
1349	struct sparx5_tc_flower_template *ftp;
1350	struct vcap_keyset_list kslist = {};
1351	enum vcap_keyfield_set keysets[10];
1352	struct vcap_control *vctrl;
1353	struct vcap_rule *vrule;
1354	int count, err;
1355
1356	if (admin->vtype == VCAP_TYPE_ES0) {
1357		pr_err("%s:%d: %s\n", __func__, __LINE__,
1358		       "VCAP does not support templates");
1359		return -EINVAL;
1360	}
1361
1362	count = vcap_admin_rule_count(admin, fco->common.chain_index);
1363	if (count > 0) {
1364		pr_err("%s:%d: %s\n", __func__, __LINE__,
1365		       "Filters are already present");
1366		return -EBUSY;
1367	}
1368
1369	ftp = kzalloc(sizeof(*ftp), GFP_KERNEL);
1370	if (!ftp)
1371		return -ENOMEM;
1372
1373	ftp->cid = fco->common.chain_index;
1374	ftp->orig = VCAP_KFS_NO_VALUE;
1375	ftp->keyset = VCAP_KFS_NO_VALUE;
1376
1377	vctrl = port->sparx5->vcap_ctrl;
1378	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index,
1379				VCAP_USER_TC, fco->common.prio, 0);
1380	if (IS_ERR(vrule)) {
1381		err = PTR_ERR(vrule);
1382		goto err_rule;
1383	}
1384
1385	state.vrule = vrule;
1386	state.frule = flow_cls_offload_flow_rule(fco);
1387	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1388	if (err) {
1389		pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err);
1390		goto out;
1391	}
1392
1393	ftp->l3_proto = state.l3_proto;
1394
1395	sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto);
1396
1397	/* Find the keysets that the rule can use */
1398	kslist.keysets = keysets;
1399	kslist.max = ARRAY_SIZE(keysets);
1400	if (!vcap_rule_find_keysets(vrule, &kslist)) {
1401		pr_err("%s:%d: %s\n", __func__, __LINE__,
1402		       "Could not find a suitable keyset");
1403		err = -ENOENT;
1404		goto out;
1405	}
1406
1407	ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist);
1408	kslist.cnt = 0;
1409	sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index,
1410				    state.l3_proto,
1411				    ftp->keyset,
1412				    &kslist);
1413
1414	if (kslist.cnt > 0)
1415		ftp->orig = kslist.keysets[0];
1416
1417	/* Store new template */
1418	list_add_tail(&ftp->list, &port->tc_templates);
1419	vcap_free_rule(vrule);
1420	return 0;
1421
1422out:
1423	vcap_free_rule(vrule);
1424err_rule:
1425	kfree(ftp);
1426	return err;
1427}
1428
1429static int sparx5_tc_flower_template_destroy(struct net_device *ndev,
1430					     struct flow_cls_offload *fco,
1431					     struct vcap_admin *admin)
1432{
1433	struct sparx5_port *port = netdev_priv(ndev);
1434	struct sparx5_tc_flower_template *ftp, *tmp;
1435	int err = -ENOENT;
1436
1437	/* Rules using the template are removed by the tc framework */
1438	list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) {
1439		if (ftp->cid != fco->common.chain_index)
1440			continue;
1441
1442		sparx5_vcap_set_port_keyset(ndev, admin,
1443					    fco->common.chain_index,
1444					    ftp->l3_proto, ftp->orig,
1445					    NULL);
1446		list_del(&ftp->list);
1447		kfree(ftp);
1448		break;
1449	}
1450	return err;
1451}
1452
1453int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
1454		     bool ingress)
1455{
1456	struct sparx5_port *port = netdev_priv(ndev);
1457	struct vcap_control *vctrl;
1458	struct vcap_admin *admin;
1459	int err = -EINVAL;
1460
1461	/* Get vcap instance from the chain id */
1462	vctrl = port->sparx5->vcap_ctrl;
1463	admin = vcap_find_admin(vctrl, fco->common.chain_index);
1464	if (!admin) {
1465		NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain");
1466		return err;
1467	}
1468
1469	switch (fco->command) {
1470	case FLOW_CLS_REPLACE:
1471		return sparx5_tc_flower_replace(ndev, fco, admin, ingress);
1472	case FLOW_CLS_DESTROY:
1473		return sparx5_tc_flower_destroy(ndev, fco, admin);
1474	case FLOW_CLS_STATS:
1475		return sparx5_tc_flower_stats(ndev, fco, admin);
1476	case FLOW_CLS_TMPLT_CREATE:
1477		return sparx5_tc_flower_template_create(ndev, fco, admin);
1478	case FLOW_CLS_TMPLT_DESTROY:
1479		return sparx5_tc_flower_template_destroy(ndev, fco, admin);
1480	default:
1481		return -EOPNOTSUPP;
1482	}
1483}
v6.2
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Microchip VCAP API
   3 *
   4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
   5 */
   6
 
   7#include <net/tcp.h>
   8
   9#include "sparx5_tc.h"
  10#include "vcap_api.h"
  11#include "vcap_api_client.h"
 
  12#include "sparx5_main.h"
  13#include "sparx5_vcap_impl.h"
  14
  15#define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */
  16
  17/* Collect keysets and type ids for multiple rules per size */
  18struct sparx5_wildcard_rule {
  19	bool selected;
  20	u8 value;
  21	u8 mask;
  22	enum vcap_keyfield_set keyset;
  23};
  24
  25struct sparx5_multiple_rules {
  26	struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE];
  27};
  28
  29struct sparx5_tc_flower_parse_usage {
  30	struct flow_cls_offload *fco;
  31	struct flow_rule *frule;
  32	struct vcap_rule *vrule;
  33	u16 l3_proto;
  34	u8 l4_proto;
  35	unsigned int used_keys;
  36};
  37
  38struct sparx5_tc_rule_pkt_cnt {
  39	u64 cookie;
  40	u32 pkts;
  41};
  42
  43/* These protocols have dedicated keysets in IS2 and a TC dissector
  44 * ETH_P_ARP does not have a TC dissector
  45 */
  46static u16 sparx5_tc_known_etypes[] = {
  47	ETH_P_ALL,
  48	ETH_P_ARP,
  49	ETH_P_IP,
  50	ETH_P_IPV6,
  51};
  52
  53enum sparx5_is2_arp_opcode {
  54	SPX5_IS2_ARP_REQUEST,
  55	SPX5_IS2_ARP_REPLY,
  56	SPX5_IS2_RARP_REQUEST,
  57	SPX5_IS2_RARP_REPLY,
  58};
  59
  60enum tc_arp_opcode {
  61	TC_ARP_OP_RESERVED,
  62	TC_ARP_OP_REQUEST,
  63	TC_ARP_OP_REPLY,
  64};
  65
  66static bool sparx5_tc_is_known_etype(u16 etype)
  67{
  68	int idx;
  69
  70	/* For now this only knows about IS2 traffic classification */
  71	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_known_etypes); ++idx)
  72		if (sparx5_tc_known_etypes[idx] == etype)
  73			return true;
  74
  75	return false;
  76}
  77
  78static int sparx5_tc_flower_handler_ethaddr_usage(struct sparx5_tc_flower_parse_usage *st)
  79{
  80	enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;
  81	enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC;
  82	struct flow_match_eth_addrs match;
  83	struct vcap_u48_key smac, dmac;
  84	int err = 0;
  85
  86	flow_rule_match_eth_addrs(st->frule, &match);
  87
  88	if (!is_zero_ether_addr(match.mask->src)) {
  89		vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN);
  90		vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN);
  91		err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac);
  92		if (err)
  93			goto out;
  94	}
  95
  96	if (!is_zero_ether_addr(match.mask->dst)) {
  97		vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN);
  98		vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN);
  99		err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac);
 100		if (err)
 101			goto out;
 102	}
 103
 104	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS);
 105
 106	return err;
 107
 108out:
 109	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error");
 110	return err;
 111}
 112
 113static int
 114sparx5_tc_flower_handler_ipv4_usage(struct sparx5_tc_flower_parse_usage *st)
 115{
 116	int err = 0;
 117
 118	if (st->l3_proto == ETH_P_IP) {
 119		struct flow_match_ipv4_addrs mt;
 120
 121		flow_rule_match_ipv4_addrs(st->frule, &mt);
 122		if (mt.mask->src) {
 123			err = vcap_rule_add_key_u32(st->vrule,
 124						    VCAP_KF_L3_IP4_SIP,
 125						    be32_to_cpu(mt.key->src),
 126						    be32_to_cpu(mt.mask->src));
 127			if (err)
 128				goto out;
 129		}
 130		if (mt.mask->dst) {
 131			err = vcap_rule_add_key_u32(st->vrule,
 132						    VCAP_KF_L3_IP4_DIP,
 133						    be32_to_cpu(mt.key->dst),
 134						    be32_to_cpu(mt.mask->dst));
 135			if (err)
 136				goto out;
 137		}
 138	}
 139
 140	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS);
 141
 142	return err;
 143
 144out:
 145	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");
 146	return err;
 147}
 148
 149static int
 150sparx5_tc_flower_handler_ipv6_usage(struct sparx5_tc_flower_parse_usage *st)
 151{
 152	int err = 0;
 153
 154	if (st->l3_proto == ETH_P_IPV6) {
 155		struct flow_match_ipv6_addrs mt;
 156		struct vcap_u128_key sip;
 157		struct vcap_u128_key dip;
 158
 159		flow_rule_match_ipv6_addrs(st->frule, &mt);
 160		/* Check if address masks are non-zero */
 161		if (!ipv6_addr_any(&mt.mask->src)) {
 162			vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16);
 163			vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16);
 164			err = vcap_rule_add_key_u128(st->vrule,
 165						     VCAP_KF_L3_IP6_SIP, &sip);
 166			if (err)
 167				goto out;
 168		}
 169		if (!ipv6_addr_any(&mt.mask->dst)) {
 170			vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16);
 171			vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16);
 172			err = vcap_rule_add_key_u128(st->vrule,
 173						     VCAP_KF_L3_IP6_DIP, &dip);
 174			if (err)
 175				goto out;
 176		}
 177	}
 178	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS);
 179	return err;
 180out:
 181	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");
 182	return err;
 183}
 184
 185static int
 186sparx5_tc_flower_handler_control_usage(struct sparx5_tc_flower_parse_usage *st)
 187{
 188	struct flow_match_control mt;
 189	u32 value, mask;
 190	int err = 0;
 191
 192	flow_rule_match_control(st->frule, &mt);
 193
 194	if (mt.mask->flags) {
 195		if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
 196			if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
 197				value = 1; /* initial fragment */
 198				mask = 0x3;
 199			} else {
 200				if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
 201					value = 3; /* follow up fragment */
 202					mask = 0x3;
 203				} else {
 204					value = 0; /* no fragment */
 205					mask = 0x3;
 206				}
 207			}
 208		} else {
 209			if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
 210				value = 3; /* follow up fragment */
 211				mask = 0x3;
 212			} else {
 213				value = 0; /* no fragment */
 214				mask = 0x3;
 215			}
 216		}
 217
 218		err = vcap_rule_add_key_u32(st->vrule,
 219					    VCAP_KF_L3_FRAGMENT_TYPE,
 220					    value, mask);
 221		if (err)
 222			goto out;
 
 
 
 
 223	}
 224
 225	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
 226
 227	return err;
 228
 229out:
 230	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
 231	return err;
 232}
 233
 234static int
 235sparx5_tc_flower_handler_portnum_usage(struct sparx5_tc_flower_parse_usage *st)
 236{
 237	struct flow_match_ports mt;
 238	u16 value, mask;
 239	int err = 0;
 240
 241	flow_rule_match_ports(st->frule, &mt);
 242
 243	if (mt.mask->src) {
 244		value = be16_to_cpu(mt.key->src);
 245		mask = be16_to_cpu(mt.mask->src);
 246		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value,
 247					    mask);
 248		if (err)
 249			goto out;
 250	}
 251
 252	if (mt.mask->dst) {
 253		value = be16_to_cpu(mt.key->dst);
 254		mask = be16_to_cpu(mt.mask->dst);
 255		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value,
 256					    mask);
 257		if (err)
 258			goto out;
 259	}
 260
 261	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS);
 262
 263	return err;
 264
 265out:
 266	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");
 267	return err;
 268}
 269
 270static int
 271sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st)
 272{
 273	struct flow_match_basic mt;
 274	int err = 0;
 275
 276	flow_rule_match_basic(st->frule, &mt);
 277
 278	if (mt.mask->n_proto) {
 279		st->l3_proto = be16_to_cpu(mt.key->n_proto);
 280		if (!sparx5_tc_is_known_etype(st->l3_proto)) {
 281			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
 282						    st->l3_proto, ~0);
 283			if (err)
 284				goto out;
 285		} else if (st->l3_proto == ETH_P_IP) {
 286			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
 287						    VCAP_BIT_1);
 288			if (err)
 289				goto out;
 290		} else if (st->l3_proto == ETH_P_IPV6) {
 291			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
 292						    VCAP_BIT_0);
 293			if (err)
 294				goto out;
 
 
 
 
 
 
 
 295		}
 296	}
 297
 298	if (mt.mask->ip_proto) {
 299		st->l4_proto = mt.key->ip_proto;
 300		if (st->l4_proto == IPPROTO_TCP) {
 301			err = vcap_rule_add_key_bit(st->vrule,
 302						    VCAP_KF_TCP_IS,
 303						    VCAP_BIT_1);
 304			if (err)
 305				goto out;
 306		} else if (st->l4_proto == IPPROTO_UDP) {
 307			err = vcap_rule_add_key_bit(st->vrule,
 308						    VCAP_KF_TCP_IS,
 309						    VCAP_BIT_0);
 310			if (err)
 311				goto out;
 
 
 
 
 
 
 
 312		} else {
 313			err = vcap_rule_add_key_u32(st->vrule,
 314						    VCAP_KF_L3_IP_PROTO,
 315						    st->l4_proto, ~0);
 316			if (err)
 317				goto out;
 318		}
 319	}
 320
 321	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC);
 322
 323	return err;
 324
 325out:
 326	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
 327	return err;
 328}
 329
 330static int
 331sparx5_tc_flower_handler_vlan_usage(struct sparx5_tc_flower_parse_usage *st)
 332{
 333	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
 334	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
 335	struct flow_match_vlan mt;
 336	int err;
 337
 338	flow_rule_match_vlan(st->frule, &mt);
 339
 340	if (mt.mask->vlan_id) {
 341		err = vcap_rule_add_key_u32(st->vrule, vid_key,
 342					    mt.key->vlan_id,
 343					    mt.mask->vlan_id);
 344		if (err)
 345			goto out;
 346	}
 347
 348	if (mt.mask->vlan_priority) {
 349		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
 350					    mt.key->vlan_priority,
 351					    mt.mask->vlan_priority);
 352		if (err)
 353			goto out;
 354	}
 355
 356	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_VLAN);
 357
 358	return 0;
 359out:
 360	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");
 361	return err;
 362}
 363
 364static int
 365sparx5_tc_flower_handler_tcp_usage(struct sparx5_tc_flower_parse_usage *st)
 366{
 367	struct flow_match_tcp mt;
 368	u16 tcp_flags_mask;
 369	u16 tcp_flags_key;
 370	enum vcap_bit val;
 371	int err = 0;
 372
 373	flow_rule_match_tcp(st->frule, &mt);
 374	tcp_flags_key = be16_to_cpu(mt.key->flags);
 375	tcp_flags_mask = be16_to_cpu(mt.mask->flags);
 376
 377	if (tcp_flags_mask & TCPHDR_FIN) {
 378		val = VCAP_BIT_0;
 379		if (tcp_flags_key & TCPHDR_FIN)
 380			val = VCAP_BIT_1;
 381		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val);
 382		if (err)
 383			goto out;
 384	}
 385
 386	if (tcp_flags_mask & TCPHDR_SYN) {
 387		val = VCAP_BIT_0;
 388		if (tcp_flags_key & TCPHDR_SYN)
 389			val = VCAP_BIT_1;
 390		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val);
 391		if (err)
 392			goto out;
 393	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 394
 395	if (tcp_flags_mask & TCPHDR_RST) {
 396		val = VCAP_BIT_0;
 397		if (tcp_flags_key & TCPHDR_RST)
 398			val = VCAP_BIT_1;
 399		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val);
 400		if (err)
 401			goto out;
 402	}
 403
 404	if (tcp_flags_mask & TCPHDR_PSH) {
 405		val = VCAP_BIT_0;
 406		if (tcp_flags_key & TCPHDR_PSH)
 407			val = VCAP_BIT_1;
 408		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val);
 409		if (err)
 410			goto out;
 411	}
 412
 413	if (tcp_flags_mask & TCPHDR_ACK) {
 414		val = VCAP_BIT_0;
 415		if (tcp_flags_key & TCPHDR_ACK)
 416			val = VCAP_BIT_1;
 417		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val);
 418		if (err)
 419			goto out;
 420	}
 421
 422	if (tcp_flags_mask & TCPHDR_URG) {
 423		val = VCAP_BIT_0;
 424		if (tcp_flags_key & TCPHDR_URG)
 425			val = VCAP_BIT_1;
 426		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val);
 427		if (err)
 428			goto out;
 429	}
 430
 431	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP);
 432
 433	return err;
 434
 435out:
 436	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");
 437	return err;
 438}
 439
 440static int
 441sparx5_tc_flower_handler_arp_usage(struct sparx5_tc_flower_parse_usage *st)
 442{
 443	struct flow_match_arp mt;
 444	u16 value, mask;
 445	u32 ipval, ipmsk;
 446	int err;
 447
 448	flow_rule_match_arp(st->frule, &mt);
 449
 450	if (mt.mask->op) {
 451		mask = 0x3;
 452		if (st->l3_proto == ETH_P_ARP) {
 453			value = mt.key->op == TC_ARP_OP_REQUEST ?
 454					SPX5_IS2_ARP_REQUEST :
 455					SPX5_IS2_ARP_REPLY;
 456		} else { /* RARP */
 457			value = mt.key->op == TC_ARP_OP_REQUEST ?
 458					SPX5_IS2_RARP_REQUEST :
 459					SPX5_IS2_RARP_REPLY;
 460		}
 461		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE,
 462					    value, mask);
 463		if (err)
 464			goto out;
 465	}
 466
 467	/* The IS2 ARP keyset does not support ARP hardware addresses */
 468	if (!is_zero_ether_addr(mt.mask->sha) ||
 469	    !is_zero_ether_addr(mt.mask->tha)) {
 470		err = -EINVAL;
 471		goto out;
 472	}
 473
 474	if (mt.mask->sip) {
 475		ipval = be32_to_cpu((__force __be32)mt.key->sip);
 476		ipmsk = be32_to_cpu((__force __be32)mt.mask->sip);
 477
 478		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP,
 479					    ipval, ipmsk);
 480		if (err)
 481			goto out;
 482	}
 483
 484	if (mt.mask->tip) {
 485		ipval = be32_to_cpu((__force __be32)mt.key->tip);
 486		ipmsk = be32_to_cpu((__force __be32)mt.mask->tip);
 487
 488		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP,
 489					    ipval, ipmsk);
 490		if (err)
 491			goto out;
 492	}
 493
 494	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ARP);
 495
 496	return 0;
 497
 498out:
 499	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");
 500	return err;
 501}
 502
 503static int
 504sparx5_tc_flower_handler_ip_usage(struct sparx5_tc_flower_parse_usage *st)
 505{
 506	struct flow_match_ip mt;
 507	int err = 0;
 
 508
 509	flow_rule_match_ip(st->frule, &mt);
 510
 511	if (mt.mask->tos) {
 512		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS,
 513					    mt.key->tos,
 514					    mt.mask->tos);
 515		if (err)
 516			goto out;
 517	}
 518
 519	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IP);
 
 
 520
 521	return err;
 
 522
 523out:
 524	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");
 525	return err;
 526}
 527
 528static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_usage *st) = {
 529	[FLOW_DISSECTOR_KEY_ETH_ADDRS] = sparx5_tc_flower_handler_ethaddr_usage,
 530	[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = sparx5_tc_flower_handler_ipv4_usage,
 531	[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = sparx5_tc_flower_handler_ipv6_usage,
 532	[FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage,
 533	[FLOW_DISSECTOR_KEY_PORTS] = sparx5_tc_flower_handler_portnum_usage,
 534	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
 
 535	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
 536	[FLOW_DISSECTOR_KEY_TCP] = sparx5_tc_flower_handler_tcp_usage,
 537	[FLOW_DISSECTOR_KEY_ARP] = sparx5_tc_flower_handler_arp_usage,
 538	[FLOW_DISSECTOR_KEY_IP] = sparx5_tc_flower_handler_ip_usage,
 539};
 540
 541static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
 542				    struct vcap_admin *admin,
 543				    struct vcap_rule *vrule,
 544				    u16 *l3_proto)
 545{
 546	struct sparx5_tc_flower_parse_usage state = {
 547		.fco = fco,
 548		.vrule = vrule,
 549		.l3_proto = ETH_P_ALL,
 550	};
 551	int idx, err = 0;
 552
 553	state.frule = flow_cls_offload_flow_rule(fco);
 554	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) {
 555		if (!flow_rule_match_key(state.frule, idx))
 556			continue;
 557		if (!sparx5_tc_flower_usage_handlers[idx])
 558			continue;
 559		err = sparx5_tc_flower_usage_handlers[idx](&state);
 560		if (err)
 561			return err;
 562	}
 563
 564	if (state.frule->match.dissector->used_keys ^ state.used_keys) {
 565		NL_SET_ERR_MSG_MOD(fco->common.extack,
 566				   "Unsupported match item");
 567		return -ENOENT;
 568	}
 569
 570	if (l3_proto)
 571		*l3_proto = state.l3_proto;
 572	return err;
 573}
 574
 575static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
 
 576					 struct flow_cls_offload *fco,
 577					 struct vcap_admin *admin)
 578{
 579	struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
 580	struct flow_action_entry *actent, *last_actent = NULL;
 581	struct flow_action *act = &rule->action;
 582	u64 action_mask = 0;
 583	int idx;
 584
 585	if (!flow_action_has_entries(act)) {
 586		NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions");
 587		return -EINVAL;
 588	}
 589
 590	if (!flow_action_basic_hw_stats_check(act, fco->common.extack))
 591		return -EOPNOTSUPP;
 592
 593	flow_action_for_each(idx, actent, act) {
 594		if (action_mask & BIT(actent->id)) {
 595			NL_SET_ERR_MSG_MOD(fco->common.extack,
 596					   "More actions of the same type");
 597			return -EINVAL;
 598		}
 599		action_mask |= BIT(actent->id);
 600		last_actent = actent; /* Save last action for later check */
 601	}
 602
 603	/* Check that last action is a goto */
 604	if (last_actent->id != FLOW_ACTION_GOTO) {
 
 
 
 
 
 
 
 
 
 
 
 605		NL_SET_ERR_MSG_MOD(fco->common.extack,
 606				   "Last action must be 'goto'");
 607		return -EINVAL;
 608	}
 609
 610	/* Check if the goto chain is in the next lookup */
 611	if (!vcap_is_next_lookup(vctrl, fco->common.chain_index,
 612				 last_actent->chain_index)) {
 613		NL_SET_ERR_MSG_MOD(fco->common.extack,
 614				   "Invalid goto chain");
 615		return -EINVAL;
 616	}
 617
 618	/* Catch unsupported combinations of actions */
 619	if (action_mask & BIT(FLOW_ACTION_TRAP) &&
 620	    action_mask & BIT(FLOW_ACTION_ACCEPT)) {
 621		NL_SET_ERR_MSG_MOD(fco->common.extack,
 622				   "Cannot combine pass and trap action");
 623		return -EOPNOTSUPP;
 624	}
 625
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 626	return 0;
 627}
 628
 629/* Add a rule counter action - only IS2 is considered for now */
 630static int sparx5_tc_add_rule_counter(struct vcap_admin *admin,
 631				      struct vcap_rule *vrule)
 632{
 633	int err;
 634
 635	err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID, vrule->id);
 636	if (err)
 637		return err;
 638
 639	vcap_rule_set_counter_id(vrule, vrule->id);
 640	return err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 641}
 642
 643/* Collect all port keysets and apply the first of them, possibly wildcarded */
 644static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,
 645					    struct vcap_rule *vrule,
 646					    struct vcap_admin *admin,
 647					    u16 l3_proto,
 648					    struct sparx5_multiple_rules *multi)
 649{
 650	struct sparx5_port *port = netdev_priv(ndev);
 651	struct vcap_keyset_list portkeysetlist = {};
 652	enum vcap_keyfield_set portkeysets[10] = {};
 653	struct vcap_keyset_list matches = {};
 654	enum vcap_keyfield_set keysets[10];
 655	int idx, jdx, err = 0, count = 0;
 656	struct sparx5_wildcard_rule *mru;
 657	const struct vcap_set *kinfo;
 658	struct vcap_control *vctrl;
 659
 660	vctrl = port->sparx5->vcap_ctrl;
 661
 662	/* Find the keysets that the rule can use */
 663	matches.keysets = keysets;
 664	matches.max = ARRAY_SIZE(keysets);
 665	if (vcap_rule_find_keysets(vrule, &matches) == 0)
 666		return -EINVAL;
 667
 668	/* Find the keysets that the port configuration supports */
 669	portkeysetlist.max = ARRAY_SIZE(portkeysets);
 670	portkeysetlist.keysets = portkeysets;
 671	err = sparx5_vcap_get_port_keyset(ndev,
 672					  admin, vrule->vcap_chain_id,
 673					  l3_proto,
 674					  &portkeysetlist);
 675	if (err)
 676		return err;
 677
 678	/* Find the intersection of the two sets of keyset */
 679	for (idx = 0; idx < portkeysetlist.cnt; ++idx) {
 680		kinfo = vcap_keyfieldset(vctrl, admin->vtype,
 681					 portkeysetlist.keysets[idx]);
 682		if (!kinfo)
 683			continue;
 684
 685		/* Find a port keyset that matches the required keys
 686		 * If there are multiple keysets then compose a type id mask
 687		 */
 688		for (jdx = 0; jdx < matches.cnt; ++jdx) {
 689			if (portkeysetlist.keysets[idx] != matches.keysets[jdx])
 690				continue;
 691
 692			mru = &multi->rule[kinfo->sw_per_item];
 693			if (!mru->selected) {
 694				mru->selected = true;
 695				mru->keyset = portkeysetlist.keysets[idx];
 696				mru->value = kinfo->type_id;
 697			}
 698			mru->value &= kinfo->type_id;
 699			mru->mask |= kinfo->type_id;
 700			++count;
 701		}
 702	}
 703	if (count == 0)
 704		return -EPROTO;
 705
 706	if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt)
 707		return -ENOENT;
 708
 709	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 710		mru = &multi->rule[idx];
 711		if (!mru->selected)
 712			continue;
 713
 714		/* Align the mask to the combined value */
 715		mru->mask ^= mru->value;
 716	}
 717
 718	/* Set the chosen keyset on the rule and set a wildcarded type if there
 719	 * are more than one keyset
 720	 */
 721	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 722		mru = &multi->rule[idx];
 723		if (!mru->selected)
 724			continue;
 725
 726		vcap_set_rule_set_keyset(vrule, mru->keyset);
 727		if (count > 1)
 728			/* Some keysets do not have a type field */
 729			vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE,
 730					      mru->value,
 731					      ~mru->mask);
 732		mru->selected = false; /* mark as done */
 733		break; /* Stop here and add more rules later */
 734	}
 735	return err;
 736}
 737
 738static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl,
 739				   struct flow_cls_offload *fco,
 740				   struct vcap_rule *erule,
 741				   struct vcap_admin *admin,
 742				   struct sparx5_wildcard_rule *rule)
 743{
 744	enum vcap_key_field keylist[] = {
 745		VCAP_KF_IF_IGR_PORT_MASK,
 746		VCAP_KF_IF_IGR_PORT_MASK_SEL,
 747		VCAP_KF_IF_IGR_PORT_MASK_RNG,
 748		VCAP_KF_LOOKUP_FIRST_IS,
 749		VCAP_KF_TYPE,
 750	};
 751	struct vcap_rule *vrule;
 752	int err;
 753
 754	/* Add an extra rule with a special user and the new keyset */
 755	erule->user = VCAP_USER_TC_EXTRA;
 756	vrule = vcap_copy_rule(erule);
 757	if (IS_ERR(vrule))
 758		return PTR_ERR(vrule);
 759
 760	/* Link the new rule to the existing rule with the cookie */
 761	vrule->cookie = erule->cookie;
 762	vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true);
 763	err = vcap_set_rule_set_keyset(vrule, rule->keyset);
 764	if (err) {
 765		pr_err("%s:%d: could not set keyset %s in rule: %u\n",
 766		       __func__, __LINE__,
 767		       vcap_keyset_name(vctrl, rule->keyset),
 768		       vrule->id);
 769		goto out;
 770	}
 771
 772	/* Some keysets do not have a type field, so ignore return value */
 773	vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask);
 774
 775	err = vcap_set_rule_set_actionset(vrule, erule->actionset);
 776	if (err)
 777		goto out;
 778
 779	err = sparx5_tc_add_rule_counter(admin, vrule);
 780	if (err)
 781		goto out;
 782
 783	err = vcap_val_rule(vrule, ETH_P_ALL);
 784	if (err) {
 785		pr_err("%s:%d: could not validate rule: %u\n",
 786		       __func__, __LINE__, vrule->id);
 787		vcap_set_tc_exterr(fco, vrule);
 788		goto out;
 789	}
 790	err = vcap_add_rule(vrule);
 791	if (err) {
 792		pr_err("%s:%d: could not add rule: %u\n",
 793		       __func__, __LINE__, vrule->id);
 794		goto out;
 795	}
 796out:
 797	vcap_free_rule(vrule);
 798	return err;
 799}
 800
 801static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl,
 802					 struct flow_cls_offload *fco,
 803					 struct vcap_rule *erule,
 804					 struct vcap_admin *admin,
 805					 struct sparx5_multiple_rules *multi)
 806{
 807	int idx, err = 0;
 808
 809	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
 810		if (!multi->rule[idx].selected)
 811			continue;
 812
 813		err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin,
 814					      &multi->rule[idx]);
 815		if (err)
 816			break;
 817	}
 818	return err;
 819}
 820
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 821static int sparx5_tc_flower_replace(struct net_device *ndev,
 822				    struct flow_cls_offload *fco,
 823				    struct vcap_admin *admin)
 
 824{
 
 
 
 
 
 
 
 
 825	struct sparx5_port *port = netdev_priv(ndev);
 826	struct sparx5_multiple_rules multi = {};
 
 
 
 827	struct flow_action_entry *act;
 828	struct vcap_control *vctrl;
 829	struct flow_rule *frule;
 830	struct vcap_rule *vrule;
 831	u16 l3_proto;
 832	int err, idx;
 833
 834	vctrl = port->sparx5->vcap_ctrl;
 835
 836	err = sparx5_tc_flower_action_check(vctrl, fco, admin);
 837	if (err)
 838		return err;
 839
 840	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC,
 841				fco->common.prio, 0);
 842	if (IS_ERR(vrule))
 843		return PTR_ERR(vrule);
 844
 845	vrule->cookie = fco->cookie;
 846
 847	l3_proto = ETH_P_ALL;
 848	err = sparx5_tc_use_dissectors(fco, admin, vrule, &l3_proto);
 
 849	if (err)
 850		goto out;
 851
 852	err = sparx5_tc_add_rule_counter(admin, vrule);
 853	if (err)
 854		goto out;
 855
 
 
 
 
 
 856	frule = flow_cls_offload_flow_rule(fco);
 857	flow_action_for_each(idx, act, &frule->action) {
 858		switch (act->id) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 859		case FLOW_ACTION_TRAP:
 860			err = vcap_rule_add_action_bit(vrule,
 861						       VCAP_AF_CPU_COPY_ENA,
 862						       VCAP_BIT_1);
 863			if (err)
 864				goto out;
 865			err = vcap_rule_add_action_u32(vrule,
 866						       VCAP_AF_CPU_QUEUE_NUM, 0);
 
 867			if (err)
 868				goto out;
 869			err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE,
 870						       SPX5_PMM_REPLACE_ALL);
 
 871			if (err)
 872				goto out;
 873			/* For now the actionset is hardcoded */
 874			err = vcap_set_rule_set_actionset(vrule,
 875							  VCAP_AFS_BASE_TYPE);
 
 
 
 
 876			if (err)
 877				goto out;
 878			break;
 879		case FLOW_ACTION_ACCEPT:
 880			/* For now the actionset is hardcoded */
 881			err = vcap_set_rule_set_actionset(vrule,
 882							  VCAP_AFS_BASE_TYPE);
 883			if (err)
 884				goto out;
 885			break;
 886		case FLOW_ACTION_GOTO:
 887			/* Links between VCAPs will be added later */
 
 
 
 888			break;
 889		default:
 890			NL_SET_ERR_MSG_MOD(fco->common.extack,
 891					   "Unsupported TC action");
 892			err = -EOPNOTSUPP;
 893			goto out;
 894		}
 895	}
 896
 897	err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin, l3_proto,
 898					       &multi);
 899	if (err) {
 900		NL_SET_ERR_MSG_MOD(fco->common.extack,
 901				   "No matching port keyset for filter protocol and keys");
 902		goto out;
 
 
 
 
 
 
 
 
 
 
 903	}
 904
 905	/* provide the l3 protocol to guide the keyset selection */
 906	err = vcap_val_rule(vrule, l3_proto);
 907	if (err) {
 908		vcap_set_tc_exterr(fco, vrule);
 909		goto out;
 910	}
 911	err = vcap_add_rule(vrule);
 912	if (err)
 913		NL_SET_ERR_MSG_MOD(fco->common.extack,
 914				   "Could not add the filter");
 915
 916	if (l3_proto == ETH_P_ALL)
 917		err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin,
 918						    &multi);
 919
 920out:
 921	vcap_free_rule(vrule);
 922	return err;
 923}
 924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 925static int sparx5_tc_flower_destroy(struct net_device *ndev,
 926				    struct flow_cls_offload *fco,
 927				    struct vcap_admin *admin)
 928{
 929	struct sparx5_port *port = netdev_priv(ndev);
 
 930	struct vcap_control *vctrl;
 931	int err = -ENOENT, rule_id;
 932
 933	vctrl = port->sparx5->vcap_ctrl;
 934	while (true) {
 935		rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie);
 936		if (rule_id <= 0)
 937			break;
 
 
 
 
 
 
 
 
 
 
 
 938		err = vcap_del_rule(vctrl, ndev, rule_id);
 939		if (err) {
 940			pr_err("%s:%d: could not delete rule %d\n",
 941			       __func__, __LINE__, rule_id);
 942			break;
 943		}
 944	}
 945	return err;
 946}
 947
 948/* Collect packet counts from all rules with the same cookie */
 949static int sparx5_tc_rule_counter_cb(void *arg, struct vcap_rule *rule)
 950{
 951	struct sparx5_tc_rule_pkt_cnt *rinfo = arg;
 952	struct vcap_counter counter;
 953	int err = 0;
 954
 955	if (rule->cookie == rinfo->cookie) {
 956		err = vcap_rule_get_counter(rule, &counter);
 957		if (err)
 958			return err;
 959		rinfo->pkts += counter.value;
 960		/* Reset the rule counter */
 961		counter.value = 0;
 962		vcap_rule_set_counter(rule, &counter);
 963	}
 964	return err;
 965}
 966
 967static int sparx5_tc_flower_stats(struct net_device *ndev,
 968				  struct flow_cls_offload *fco,
 969				  struct vcap_admin *admin)
 970{
 971	struct sparx5_port *port = netdev_priv(ndev);
 972	struct sparx5_tc_rule_pkt_cnt rinfo = {};
 973	struct vcap_control *vctrl;
 974	ulong lastused = 0;
 975	u64 drops = 0;
 976	u32 pkts = 0;
 977	int err;
 978
 979	rinfo.cookie = fco->cookie;
 980	vctrl = port->sparx5->vcap_ctrl;
 981	err = vcap_rule_iter(vctrl, sparx5_tc_rule_counter_cb, &rinfo);
 982	if (err)
 983		return err;
 984	pkts = rinfo.pkts;
 985	flow_stats_update(&fco->stats, 0x0, pkts, drops, lastused,
 986			  FLOW_ACTION_HW_STATS_IMMEDIATE);
 987	return err;
 988}
 989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 990int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
 991		     bool ingress)
 992{
 993	struct sparx5_port *port = netdev_priv(ndev);
 994	struct vcap_control *vctrl;
 995	struct vcap_admin *admin;
 996	int err = -EINVAL;
 997
 998	/* Get vcap instance from the chain id */
 999	vctrl = port->sparx5->vcap_ctrl;
1000	admin = vcap_find_admin(vctrl, fco->common.chain_index);
1001	if (!admin) {
1002		NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain");
1003		return err;
1004	}
1005
1006	switch (fco->command) {
1007	case FLOW_CLS_REPLACE:
1008		return sparx5_tc_flower_replace(ndev, fco, admin);
1009	case FLOW_CLS_DESTROY:
1010		return sparx5_tc_flower_destroy(ndev, fco, admin);
1011	case FLOW_CLS_STATS:
1012		return sparx5_tc_flower_stats(ndev, fco, admin);
 
 
 
 
1013	default:
1014		return -EOPNOTSUPP;
1015	}
1016}