Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
v6.8
   1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2/* Microsemi Ocelot Switch driver
   3 * Copyright (c) 2019 Microsemi Corporation
   4 */
   5
   6#include <net/pkt_cls.h>
   7#include <net/tc_act/tc_gact.h>
   8#include <soc/mscc/ocelot_vcap.h>
   9#include "ocelot_police.h"
  10#include "ocelot_vcap.h"
  11
  12/* Arbitrarily chosen constants for encoding the VCAP block and lookup number
  13 * into the chain number. This is UAPI.
  14 */
  15#define VCAP_BLOCK			10000
  16#define VCAP_LOOKUP			1000
  17#define VCAP_IS1_NUM_LOOKUPS		3
  18#define VCAP_IS2_NUM_LOOKUPS		2
  19#define VCAP_IS2_NUM_PAG		256
  20#define VCAP_IS1_CHAIN(lookup)		\
  21	(1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
  22#define VCAP_IS2_CHAIN(lookup, pag)	\
  23	(2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
  24/* PSFP chain and block ID */
  25#define PSFP_BLOCK_ID			OCELOT_NUM_VCAP_BLOCKS
  26#define OCELOT_PSFP_CHAIN		(3 * VCAP_BLOCK)
  27
  28static int ocelot_chain_to_block(int chain, bool ingress)
  29{
  30	int lookup, pag;
  31
  32	if (!ingress) {
  33		if (chain == 0)
  34			return VCAP_ES0;
  35		return -EOPNOTSUPP;
  36	}
  37
  38	/* Backwards compatibility with older, single-chain tc-flower
  39	 * offload support in Ocelot
  40	 */
  41	if (chain == 0)
  42		return VCAP_IS2;
  43
  44	for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
  45		if (chain == VCAP_IS1_CHAIN(lookup))
  46			return VCAP_IS1;
  47
  48	for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
  49		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  50			if (chain == VCAP_IS2_CHAIN(lookup, pag))
  51				return VCAP_IS2;
  52
  53	if (chain == OCELOT_PSFP_CHAIN)
  54		return PSFP_BLOCK_ID;
  55
  56	return -EOPNOTSUPP;
  57}
  58
  59/* Caller must ensure this is a valid IS1 or IS2 chain first,
  60 * by calling ocelot_chain_to_block.
  61 */
  62static int ocelot_chain_to_lookup(int chain)
  63{
  64	/* Backwards compatibility with older, single-chain tc-flower
  65	 * offload support in Ocelot
  66	 */
  67	if (chain == 0)
  68		return 0;
  69
  70	return (chain / VCAP_LOOKUP) % 10;
  71}
  72
  73/* Caller must ensure this is a valid IS2 chain first,
  74 * by calling ocelot_chain_to_block.
  75 */
  76static int ocelot_chain_to_pag(int chain)
  77{
  78	int lookup;
  79
  80	/* Backwards compatibility with older, single-chain tc-flower
  81	 * offload support in Ocelot
  82	 */
  83	if (chain == 0)
  84		return 0;
  85
  86	lookup = ocelot_chain_to_lookup(chain);
  87
  88	/* calculate PAG value as chain index relative to the first PAG */
  89	return chain - VCAP_IS2_CHAIN(lookup, 0);
  90}
  91
  92static bool ocelot_is_goto_target_valid(int goto_target, int chain,
  93					bool ingress)
  94{
  95	int pag;
  96
  97	/* Can't offload GOTO in VCAP ES0 */
  98	if (!ingress)
  99		return (goto_target < 0);
 100
 101	/* Non-optional GOTOs */
 102	if (chain == 0)
 103		/* VCAP IS1 can be skipped, either partially or completely */
 104		return (goto_target == VCAP_IS1_CHAIN(0) ||
 105			goto_target == VCAP_IS1_CHAIN(1) ||
 106			goto_target == VCAP_IS1_CHAIN(2) ||
 107			goto_target == VCAP_IS2_CHAIN(0, 0) ||
 108			goto_target == VCAP_IS2_CHAIN(1, 0) ||
 109			goto_target == OCELOT_PSFP_CHAIN);
 110
 111	if (chain == VCAP_IS1_CHAIN(0))
 112		return (goto_target == VCAP_IS1_CHAIN(1));
 113
 114	if (chain == VCAP_IS1_CHAIN(1))
 115		return (goto_target == VCAP_IS1_CHAIN(2));
 116
 117	/* Lookup 2 of VCAP IS1 can really support non-optional GOTOs,
 118	 * using a Policy Association Group (PAG) value, which is an 8-bit
 119	 * value encoding a VCAP IS2 target chain.
 120	 */
 121	if (chain == VCAP_IS1_CHAIN(2)) {
 122		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 123			if (goto_target == VCAP_IS2_CHAIN(0, pag))
 124				return true;
 125
 126		return false;
 127	}
 128
 129	/* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1.
 130	 * We cannot change the PAG at this point.
 131	 */
 132	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 133		if (chain == VCAP_IS2_CHAIN(0, pag))
 134			return (goto_target == VCAP_IS2_CHAIN(1, pag));
 135
 136	/* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
 137	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 138		if (chain == VCAP_IS2_CHAIN(1, pag))
 139			return (goto_target == OCELOT_PSFP_CHAIN);
 140
 141	return false;
 142}
 143
 144static struct ocelot_vcap_filter *
 145ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
 146{
 147	struct ocelot_vcap_filter *filter;
 148	struct ocelot_vcap_block *block;
 149	int block_id;
 150
 151	block_id = ocelot_chain_to_block(chain, true);
 152	if (block_id < 0)
 153		return NULL;
 154
 155	if (block_id == VCAP_IS2) {
 156		block = &ocelot->block[VCAP_IS1];
 157
 158		list_for_each_entry(filter, &block->rules, list)
 159			if (filter->type == OCELOT_VCAP_FILTER_PAG &&
 160			    filter->goto_target == chain)
 161				return filter;
 162	}
 163
 164	list_for_each_entry(filter, &ocelot->dummy_rules, list)
 165		if (filter->goto_target == chain)
 166			return filter;
 167
 168	return NULL;
 169}
 170
 171static int
 172ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
 173					struct ocelot_vcap_filter *filter,
 174					const struct flow_action_entry *a,
 175					struct netlink_ext_ack *extack)
 176{
 177	struct ocelot_port *ocelot_port = ocelot->ports[port];
 178
 179	if (filter->goto_target != -1) {
 180		NL_SET_ERR_MSG_MOD(extack,
 181				   "Last action must be GOTO");
 182		return -EOPNOTSUPP;
 183	}
 184
 185	if (!ocelot_port->vlan_aware) {
 186		NL_SET_ERR_MSG_MOD(extack,
 187				   "Can only modify VLAN under VLAN aware bridge");
 188		return -EOPNOTSUPP;
 189	}
 190
 191	filter->action.vid_replace_ena = true;
 192	filter->action.pcp_dei_ena = true;
 193	filter->action.vid = a->vlan.vid;
 194	filter->action.pcp = a->vlan.prio;
 195	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 196
 197	return 0;
 198}
 199
 200static int
 201ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
 202				       const struct flow_action_entry *a,
 203				       struct netlink_ext_ack *extack)
 204{
 205	enum ocelot_tag_tpid_sel tpid;
 206
 207	switch (ntohs(a->vlan.proto)) {
 208	case ETH_P_8021Q:
 209		tpid = OCELOT_TAG_TPID_SEL_8021Q;
 210		break;
 211	case ETH_P_8021AD:
 212		tpid = OCELOT_TAG_TPID_SEL_8021AD;
 213		break;
 214	default:
 215		NL_SET_ERR_MSG_MOD(extack,
 216				   "Cannot modify custom TPID");
 217		return -EOPNOTSUPP;
 218	}
 219
 220	filter->action.tag_a_tpid_sel = tpid;
 221	filter->action.push_outer_tag = OCELOT_ES0_TAG;
 222	filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
 223	filter->action.vid_a_val = a->vlan.vid;
 224	filter->action.pcp_a_val = a->vlan.prio;
 225	filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
 226	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 227
 228	return 0;
 229}
 230
 231static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 232				      bool ingress, struct flow_cls_offload *f,
 233				      struct ocelot_vcap_filter *filter)
 234{
 235	const struct flow_action *action = &f->rule->action;
 236	struct netlink_ext_ack *extack = f->common.extack;
 237	bool allow_missing_goto_target = false;
 238	const struct flow_action_entry *a;
 239	enum ocelot_tag_tpid_sel tpid;
 240	int i, chain, egress_port;
 241	u32 pol_ix, pol_max;
 242	u64 rate;
 243	int err;
 244
 245	if (!flow_action_basic_hw_stats_check(&f->rule->action,
 246					      f->common.extack))
 247		return -EOPNOTSUPP;
 248
 249	chain = f->common.chain_index;
 250	filter->block_id = ocelot_chain_to_block(chain, ingress);
 251	if (filter->block_id < 0) {
 252		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
 253		return -EOPNOTSUPP;
 254	}
 255	if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
 256		filter->lookup = ocelot_chain_to_lookup(chain);
 257	if (filter->block_id == VCAP_IS2)
 258		filter->pag = ocelot_chain_to_pag(chain);
 259
 260	filter->goto_target = -1;
 261	filter->type = OCELOT_VCAP_FILTER_DUMMY;
 262
 263	flow_action_for_each(i, a, action) {
 264		switch (a->id) {
 265		case FLOW_ACTION_DROP:
 266			if (filter->block_id != VCAP_IS2) {
 267				NL_SET_ERR_MSG_MOD(extack,
 268						   "Drop action can only be offloaded to VCAP IS2");
 269				return -EOPNOTSUPP;
 270			}
 271			if (filter->goto_target != -1) {
 272				NL_SET_ERR_MSG_MOD(extack,
 273						   "Last action must be GOTO");
 274				return -EOPNOTSUPP;
 275			}
 276			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
 277			filter->action.port_mask = 0;
 278			filter->action.police_ena = true;
 279			filter->action.pol_ix = OCELOT_POLICER_DISCARD;
 280			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 281			break;
 282		case FLOW_ACTION_ACCEPT:
 283			if (filter->block_id != VCAP_ES0 &&
 284			    filter->block_id != VCAP_IS1 &&
 285			    filter->block_id != VCAP_IS2) {
 286				NL_SET_ERR_MSG_MOD(extack,
 287						   "Accept action can only be offloaded to VCAP chains");
 288				return -EOPNOTSUPP;
 289			}
 290			if (filter->block_id != VCAP_ES0 &&
 291			    filter->goto_target != -1) {
 292				NL_SET_ERR_MSG_MOD(extack,
 293						   "Last action must be GOTO");
 294				return -EOPNOTSUPP;
 295			}
 296			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 297			break;
 298		case FLOW_ACTION_TRAP:
 299			if (filter->block_id != VCAP_IS2 ||
 300			    filter->lookup != 0) {
 301				NL_SET_ERR_MSG_MOD(extack,
 302						   "Trap action can only be offloaded to VCAP IS2 lookup 0");
 303				return -EOPNOTSUPP;
 304			}
 305			if (filter->goto_target != -1) {
 306				NL_SET_ERR_MSG_MOD(extack,
 307						   "Last action must be GOTO");
 308				return -EOPNOTSUPP;
 309			}
 310			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
 311			filter->action.port_mask = 0;
 312			filter->action.cpu_copy_ena = true;
 313			filter->action.cpu_qu_num = 0;
 314			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 315			filter->is_trap = true;
 316			break;
 317		case FLOW_ACTION_POLICE:
 318			if (filter->block_id == PSFP_BLOCK_ID) {
 319				filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
 320				break;
 321			}
 322			if (filter->block_id != VCAP_IS2 ||
 323			    filter->lookup != 0) {
 324				NL_SET_ERR_MSG_MOD(extack,
 325						   "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
 326				return -EOPNOTSUPP;
 327			}
 328			if (filter->goto_target != -1) {
 329				NL_SET_ERR_MSG_MOD(extack,
 330						   "Last action must be GOTO");
 331				return -EOPNOTSUPP;
 332			}
 333
 334			err = ocelot_policer_validate(action, a, extack);
 335			if (err)
 336				return err;
 337
 338			filter->action.police_ena = true;
 339
 340			pol_ix = a->hw_index + ocelot->vcap_pol.base;
 341			pol_max = ocelot->vcap_pol.max;
 342
 343			if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
 344				pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
 345				pol_max = ocelot->vcap_pol.max2;
 346			}
 347
 348			if (pol_ix >= pol_max)
 349				return -EINVAL;
 350
 351			filter->action.pol_ix = pol_ix;
 352
 353			rate = a->police.rate_bytes_ps;
 354			filter->action.pol.rate = div_u64(rate, 1000) * 8;
 355			filter->action.pol.burst = a->police.burst;
 356			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 357			break;
 358		case FLOW_ACTION_REDIRECT:
 359			if (filter->block_id != VCAP_IS2) {
 360				NL_SET_ERR_MSG_MOD(extack,
 361						   "Redirect action can only be offloaded to VCAP IS2");
 362				return -EOPNOTSUPP;
 363			}
 364			if (filter->goto_target != -1) {
 365				NL_SET_ERR_MSG_MOD(extack,
 366						   "Last action must be GOTO");
 367				return -EOPNOTSUPP;
 368			}
 369			egress_port = ocelot->ops->netdev_to_port(a->dev);
 370			if (egress_port < 0) {
 371				NL_SET_ERR_MSG_MOD(extack,
 372						   "Destination not an ocelot port");
 373				return -EOPNOTSUPP;
 374			}
 375			filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
 376			filter->action.port_mask = BIT(egress_port);
 377			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 378			break;
 379		case FLOW_ACTION_MIRRED:
 380			if (filter->block_id != VCAP_IS2) {
 381				NL_SET_ERR_MSG_MOD(extack,
 382						   "Mirror action can only be offloaded to VCAP IS2");
 383				return -EOPNOTSUPP;
 384			}
 385			if (filter->goto_target != -1) {
 386				NL_SET_ERR_MSG_MOD(extack,
 387						   "Last action must be GOTO");
 388				return -EOPNOTSUPP;
 389			}
 390			egress_port = ocelot->ops->netdev_to_port(a->dev);
 391			if (egress_port < 0) {
 392				NL_SET_ERR_MSG_MOD(extack,
 393						   "Destination not an ocelot port");
 394				return -EOPNOTSUPP;
 395			}
 396			filter->egress_port.value = egress_port;
 397			filter->action.mirror_ena = true;
 398			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 399			break;
 400		case FLOW_ACTION_VLAN_POP:
 401			if (filter->block_id != VCAP_IS1) {
 402				NL_SET_ERR_MSG_MOD(extack,
 403						   "VLAN pop action can only be offloaded to VCAP IS1");
 404				return -EOPNOTSUPP;
 405			}
 406			if (filter->goto_target != -1) {
 407				NL_SET_ERR_MSG_MOD(extack,
 408						   "Last action must be GOTO");
 409				return -EOPNOTSUPP;
 410			}
 411			filter->action.vlan_pop_cnt_ena = true;
 412			filter->action.vlan_pop_cnt++;
 413			if (filter->action.vlan_pop_cnt > 2) {
 414				NL_SET_ERR_MSG_MOD(extack,
 415						   "Cannot pop more than 2 VLAN headers");
 416				return -EOPNOTSUPP;
 417			}
 418			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 419			break;
 420		case FLOW_ACTION_VLAN_MANGLE:
 421			if (filter->block_id == VCAP_IS1) {
 422				err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
 423									      filter, a,
 424									      extack);
 425			} else if (filter->block_id == VCAP_ES0) {
 426				err = ocelot_flower_parse_egress_vlan_modify(filter, a,
 427									     extack);
 428			} else {
 429				NL_SET_ERR_MSG_MOD(extack,
 430						   "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
 431				err = -EOPNOTSUPP;
 432			}
 433			if (err)
 434				return err;
 435			break;
 436		case FLOW_ACTION_PRIORITY:
 437			if (filter->block_id != VCAP_IS1) {
 438				NL_SET_ERR_MSG_MOD(extack,
 439						   "Priority action can only be offloaded to VCAP IS1");
 440				return -EOPNOTSUPP;
 441			}
 442			if (filter->goto_target != -1) {
 443				NL_SET_ERR_MSG_MOD(extack,
 444						   "Last action must be GOTO");
 445				return -EOPNOTSUPP;
 446			}
 447			filter->action.qos_ena = true;
 448			filter->action.qos_val = a->priority;
 449			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 450			break;
 451		case FLOW_ACTION_GOTO:
 452			filter->goto_target = a->chain_index;
 453
 454			if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
 455				int pag = ocelot_chain_to_pag(filter->goto_target);
 456
 457				filter->action.pag_override_mask = 0xff;
 458				filter->action.pag_val = pag;
 459				filter->type = OCELOT_VCAP_FILTER_PAG;
 460			}
 461			break;
 462		case FLOW_ACTION_VLAN_PUSH:
 463			if (filter->block_id != VCAP_ES0) {
 464				NL_SET_ERR_MSG_MOD(extack,
 465						   "VLAN push action can only be offloaded to VCAP ES0");
 466				return -EOPNOTSUPP;
 467			}
 468			switch (ntohs(a->vlan.proto)) {
 469			case ETH_P_8021Q:
 470				tpid = OCELOT_TAG_TPID_SEL_8021Q;
 471				break;
 472			case ETH_P_8021AD:
 473				tpid = OCELOT_TAG_TPID_SEL_8021AD;
 474				break;
 475			default:
 476				NL_SET_ERR_MSG_MOD(extack,
 477						   "Cannot push custom TPID");
 478				return -EOPNOTSUPP;
 479			}
 480			filter->action.tag_a_tpid_sel = tpid;
 481			filter->action.push_outer_tag = OCELOT_ES0_TAG;
 482			filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
 483			filter->action.vid_a_val = a->vlan.vid;
 484			filter->action.pcp_a_val = a->vlan.prio;
 485			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 486			break;
 487		case FLOW_ACTION_GATE:
 488			if (filter->block_id != PSFP_BLOCK_ID) {
 489				NL_SET_ERR_MSG_MOD(extack,
 490						   "Gate action can only be offloaded to PSFP chain");
 491				return -EOPNOTSUPP;
 492			}
 493			filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
 494			break;
 495		default:
 496			NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
 497			return -EOPNOTSUPP;
 498		}
 499	}
 500
 501	if (filter->goto_target == -1) {
 502		if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
 503		    chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
 504			allow_missing_goto_target = true;
 505		} else {
 506			NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
 507			return -EOPNOTSUPP;
 508		}
 509	}
 510
 511	if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
 512	    !allow_missing_goto_target) {
 513		NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
 514		return -EOPNOTSUPP;
 515	}
 516
 517	return 0;
 518}
 519
 520static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
 521				     struct flow_cls_offload *f,
 522				     struct ocelot_vcap_filter *filter)
 523{
 524	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 525	const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
 526	int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
 527	struct netlink_ext_ack *extack = f->common.extack;
 528	struct net_device *dev, *indev;
 529	struct flow_match_meta match;
 530	int ingress_port;
 531
 532	flow_rule_match_meta(rule, &match);
 533
 534	if (!match.mask->ingress_ifindex)
 535		return 0;
 536
 537	if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
 538		NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
 539		return -EOPNOTSUPP;
 540	}
 541
 542	dev = ocelot->ops->port_to_netdev(ocelot, port);
 543	if (!dev)
 544		return -EINVAL;
 545
 546	indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
 547	if (!indev) {
 548		NL_SET_ERR_MSG_MOD(extack,
 549				   "Can't find the ingress port to match on");
 550		return -ENOENT;
 551	}
 552
 553	ingress_port = ocelot->ops->netdev_to_port(indev);
 554	if (ingress_port < 0) {
 555		NL_SET_ERR_MSG_MOD(extack,
 556				   "Can only offload an ocelot ingress port");
 557		return -EOPNOTSUPP;
 558	}
 559	if (ingress_port == port) {
 560		NL_SET_ERR_MSG_MOD(extack,
 561				   "Ingress port is equal to the egress port");
 562		return -EINVAL;
 563	}
 564
 565	filter->ingress_port.value = ingress_port;
 566	filter->ingress_port.mask = GENMASK(key_length - 1, 0);
 567
 568	return 0;
 569}
 570
 571static int
 572ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
 573			struct flow_cls_offload *f,
 574			struct ocelot_vcap_filter *filter)
 575{
 576	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 577	struct flow_dissector *dissector = rule->match.dissector;
 578	struct netlink_ext_ack *extack = f->common.extack;
 579	u16 proto = ntohs(f->common.protocol);
 580	bool match_protocol = true;
 581	int ret;
 582
 583	if (dissector->used_keys &
 584	    ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
 585	      BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
 586	      BIT_ULL(FLOW_DISSECTOR_KEY_META) |
 587	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
 588	      BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
 589	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
 590	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
 591	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
 592		return -EOPNOTSUPP;
 593	}
 594
 595	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
 596		struct flow_match_meta match;
 597
 598		flow_rule_match_meta(rule, &match);
 599		if (match.mask->l2_miss) {
 600			NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
 601			return -EOPNOTSUPP;
 602		}
 603	}
 604
 605	/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
 606	if (!ingress) {
 607		ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
 608		if (ret)
 609			return ret;
 610	}
 611
 612	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
 613		struct flow_match_control match;
 614
 615		flow_rule_match_control(rule, &match);
 616	}
 617
 618	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
 619		struct flow_match_vlan match;
 620
 621		flow_rule_match_vlan(rule, &match);
 622		filter->key_type = OCELOT_VCAP_KEY_ANY;
 623		filter->vlan.vid.value = match.key->vlan_id;
 624		filter->vlan.vid.mask = match.mask->vlan_id;
 625		filter->vlan.pcp.value[0] = match.key->vlan_priority;
 626		filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
 627		match_protocol = false;
 628	}
 629
 630	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
 631		struct flow_match_eth_addrs match;
 632
 633		if (filter->block_id == VCAP_ES0) {
 634			NL_SET_ERR_MSG_MOD(extack,
 635					   "VCAP ES0 cannot match on MAC address");
 636			return -EOPNOTSUPP;
 637		}
 638
 639		/* The hw support mac matches only for MAC_ETYPE key,
 640		 * therefore if other matches(port, tcp flags, etc) are added
 641		 * then just bail out
 642		 */
 643		if ((dissector->used_keys &
 644		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
 645		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
 646		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) !=
 647		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
 648		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
 649		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)))
 650			return -EOPNOTSUPP;
 651
 652		flow_rule_match_eth_addrs(rule, &match);
 653
 654		if (filter->block_id == VCAP_IS1 &&
 655		    !is_zero_ether_addr(match.mask->dst)) {
 656			NL_SET_ERR_MSG_MOD(extack,
 657					   "Key type S1_NORMAL cannot match on destination MAC");
 658			return -EOPNOTSUPP;
 659		}
 660
 661		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
 662		ether_addr_copy(filter->key.etype.dmac.value,
 663				match.key->dst);
 664		ether_addr_copy(filter->key.etype.smac.value,
 665				match.key->src);
 666		ether_addr_copy(filter->key.etype.dmac.mask,
 667				match.mask->dst);
 668		ether_addr_copy(filter->key.etype.smac.mask,
 669				match.mask->src);
 670		goto finished_key_parsing;
 671	}
 672
 673	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
 674		struct flow_match_basic match;
 675
 676		flow_rule_match_basic(rule, &match);
 677		if (ntohs(match.key->n_proto) == ETH_P_IP) {
 678			if (filter->block_id == VCAP_ES0) {
 679				NL_SET_ERR_MSG_MOD(extack,
 680						   "VCAP ES0 cannot match on IP protocol");
 681				return -EOPNOTSUPP;
 682			}
 683
 684			filter->key_type = OCELOT_VCAP_KEY_IPV4;
 685			filter->key.ipv4.proto.value[0] =
 686				match.key->ip_proto;
 687			filter->key.ipv4.proto.mask[0] =
 688				match.mask->ip_proto;
 689			match_protocol = false;
 690		}
 691		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
 692			if (filter->block_id == VCAP_ES0) {
 693				NL_SET_ERR_MSG_MOD(extack,
 694						   "VCAP ES0 cannot match on IP protocol");
 695				return -EOPNOTSUPP;
 696			}
 697
 698			filter->key_type = OCELOT_VCAP_KEY_IPV6;
 699			filter->key.ipv6.proto.value[0] =
 700				match.key->ip_proto;
 701			filter->key.ipv6.proto.mask[0] =
 702				match.mask->ip_proto;
 703			match_protocol = false;
 704		}
 705	}
 706
 707	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
 708	    proto == ETH_P_IP) {
 709		struct flow_match_ipv4_addrs match;
 710		u8 *tmp;
 711
 712		if (filter->block_id == VCAP_ES0) {
 713			NL_SET_ERR_MSG_MOD(extack,
 714					   "VCAP ES0 cannot match on IP address");
 715			return -EOPNOTSUPP;
 716		}
 717
 718		flow_rule_match_ipv4_addrs(rule, &match);
 719
 720		if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
 721			NL_SET_ERR_MSG_MOD(extack,
 722					   "Key type S1_NORMAL cannot match on destination IP");
 723			return -EOPNOTSUPP;
 724		}
 725
 726		tmp = &filter->key.ipv4.sip.value.addr[0];
 727		memcpy(tmp, &match.key->src, 4);
 728
 729		tmp = &filter->key.ipv4.sip.mask.addr[0];
 730		memcpy(tmp, &match.mask->src, 4);
 731
 732		tmp = &filter->key.ipv4.dip.value.addr[0];
 733		memcpy(tmp, &match.key->dst, 4);
 734
 735		tmp = &filter->key.ipv4.dip.mask.addr[0];
 736		memcpy(tmp, &match.mask->dst, 4);
 737		match_protocol = false;
 738	}
 739
 740	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
 741	    proto == ETH_P_IPV6) {
 742		return -EOPNOTSUPP;
 743	}
 744
 745	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
 746		struct flow_match_ports match;
 747
 748		if (filter->block_id == VCAP_ES0) {
 749			NL_SET_ERR_MSG_MOD(extack,
 750					   "VCAP ES0 cannot match on L4 ports");
 751			return -EOPNOTSUPP;
 752		}
 753
 754		flow_rule_match_ports(rule, &match);
 755		filter->key.ipv4.sport.value = ntohs(match.key->src);
 756		filter->key.ipv4.sport.mask = ntohs(match.mask->src);
 757		filter->key.ipv4.dport.value = ntohs(match.key->dst);
 758		filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
 759		match_protocol = false;
 760	}
 761
 762finished_key_parsing:
 763	if (match_protocol && proto != ETH_P_ALL) {
 764		if (filter->block_id == VCAP_ES0) {
 765			NL_SET_ERR_MSG_MOD(extack,
 766					   "VCAP ES0 cannot match on L2 proto");
 767			return -EOPNOTSUPP;
 768		}
 769
 770		/* TODO: support SNAP, LLC etc */
 771		if (proto < ETH_P_802_3_MIN)
 772			return -EOPNOTSUPP;
 773		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
 774		*(__be16 *)filter->key.etype.etype.value = htons(proto);
 775		*(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
 776	}
 777	/* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
 778
 779	return 0;
 780}
 781
 782static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
 783			       struct flow_cls_offload *f,
 784			       struct ocelot_vcap_filter *filter)
 785{
 786	int ret;
 787
 788	filter->prio = f->common.prio;
 789	filter->id.cookie = f->cookie;
 790	filter->id.tc_offload = true;
 791
 792	ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
 793	if (ret)
 794		return ret;
 795
 796	/* PSFP filter need to parse key by stream identification function. */
 797	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
 798		return 0;
 799
 800	return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
 801}
 802
 803static struct ocelot_vcap_filter
 804*ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
 805			   struct flow_cls_offload *f)
 806{
 807	struct ocelot_vcap_filter *filter;
 808
 809	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
 810	if (!filter)
 811		return NULL;
 812
 813	if (ingress) {
 814		filter->ingress_port_mask = BIT(port);
 815	} else {
 816		const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
 817		int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
 818
 819		filter->egress_port.value = port;
 820		filter->egress_port.mask = GENMASK(key_length - 1, 0);
 821	}
 822
 823	return filter;
 824}
 825
 826static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
 827					struct ocelot_vcap_filter *filter)
 828{
 829	list_add(&filter->list, &ocelot->dummy_rules);
 830
 831	return 0;
 832}
 833
 834static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
 835					struct ocelot_vcap_filter *filter)
 836{
 837	list_del(&filter->list);
 838	kfree(filter);
 839
 840	return 0;
 841}
 842
 843/* If we have an egress VLAN modification rule, we need to actually write the
 844 * delta between the input VLAN (from the key) and the output VLAN (from the
 845 * action), but the action was parsed first. So we need to patch the delta into
 846 * the action here.
 847 */
 848static int
 849ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
 850				    struct netlink_ext_ack *extack)
 851{
 852	if (filter->block_id != VCAP_ES0 ||
 853	    filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
 854		return 0;
 855
 856	if (filter->vlan.vid.mask != VLAN_VID_MASK) {
 857		NL_SET_ERR_MSG_MOD(extack,
 858				   "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
 859		return -EOPNOTSUPP;
 860	}
 861
 862	filter->action.vid_a_val -= filter->vlan.vid.value;
 863	filter->action.vid_a_val &= VLAN_VID_MASK;
 864
 865	return 0;
 866}
 867
 868int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 869			      struct flow_cls_offload *f, bool ingress)
 870{
 871	struct netlink_ext_ack *extack = f->common.extack;
 872	struct ocelot_vcap_filter *filter;
 873	int chain = f->common.chain_index;
 874	int block_id, ret;
 875
 876	if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
 877		NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
 878		return -EOPNOTSUPP;
 879	}
 880
 881	block_id = ocelot_chain_to_block(chain, ingress);
 882	if (block_id < 0) {
 883		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
 884		return -EOPNOTSUPP;
 885	}
 886
 887	filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
 888						     f->cookie, true);
 889	if (filter) {
 890		/* Filter already exists on other ports */
 891		if (!ingress) {
 892			NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
 893			return -EOPNOTSUPP;
 894		}
 895
 896		filter->ingress_port_mask |= BIT(port);
 897
 898		return ocelot_vcap_filter_replace(ocelot, filter);
 899	}
 900
 901	/* Filter didn't exist, create it now */
 902	filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
 903	if (!filter)
 904		return -ENOMEM;
 905
 906	ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
 907	if (ret) {
 908		kfree(filter);
 909		return ret;
 910	}
 911
 912	ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
 913	if (ret) {
 914		kfree(filter);
 915		return ret;
 916	}
 917
 918	/* The non-optional GOTOs for the TCAM skeleton don't need
 919	 * to be actually offloaded.
 920	 */
 921	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
 922		return ocelot_vcap_dummy_filter_add(ocelot, filter);
 923
 924	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
 925		kfree(filter);
 926		if (ocelot->ops->psfp_filter_add)
 927			return ocelot->ops->psfp_filter_add(ocelot, port, f);
 928
 929		NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
 930		return -EOPNOTSUPP;
 931	}
 932
 933	return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
 934}
 935EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 936
 937int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
 938			      struct flow_cls_offload *f, bool ingress)
 939{
 940	struct ocelot_vcap_filter *filter;
 941	struct ocelot_vcap_block *block;
 942	int block_id;
 943
 944	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
 945	if (block_id < 0)
 946		return 0;
 947
 948	if (block_id == PSFP_BLOCK_ID) {
 949		if (ocelot->ops->psfp_filter_del)
 950			return ocelot->ops->psfp_filter_del(ocelot, f);
 951
 952		return -EOPNOTSUPP;
 953	}
 954
 955	block = &ocelot->block[block_id];
 956
 957	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
 958	if (!filter)
 959		return 0;
 960
 961	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
 962		return ocelot_vcap_dummy_filter_del(ocelot, filter);
 963
 964	if (ingress) {
 965		filter->ingress_port_mask &= ~BIT(port);
 966		if (filter->ingress_port_mask)
 967			return ocelot_vcap_filter_replace(ocelot, filter);
 968	}
 969
 970	return ocelot_vcap_filter_del(ocelot, filter);
 971}
 972EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 973
 974int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
 975			    struct flow_cls_offload *f, bool ingress)
 976{
 977	struct ocelot_vcap_filter *filter;
 978	struct ocelot_vcap_block *block;
 979	struct flow_stats stats = {0};
 980	int block_id, ret;
 981
 982	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
 983	if (block_id < 0)
 984		return 0;
 985
 986	if (block_id == PSFP_BLOCK_ID) {
 987		if (ocelot->ops->psfp_stats_get) {
 988			ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
 989			if (ret)
 990				return ret;
 991
 992			goto stats_update;
 993		}
 994
 995		return -EOPNOTSUPP;
 996	}
 997
 998	block = &ocelot->block[block_id];
 999
1000	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
1001	if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
1002		return 0;
1003
1004	ret = ocelot_vcap_filter_stats_update(ocelot, filter);
1005	if (ret)
1006		return ret;
1007
1008	stats.pkts = filter->stats.pkts;
1009
1010stats_update:
1011	flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
1012			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1013	return 0;
1014}
1015EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
v6.2
   1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2/* Microsemi Ocelot Switch driver
   3 * Copyright (c) 2019 Microsemi Corporation
   4 */
   5
   6#include <net/pkt_cls.h>
   7#include <net/tc_act/tc_gact.h>
   8#include <soc/mscc/ocelot_vcap.h>
   9#include "ocelot_police.h"
  10#include "ocelot_vcap.h"
  11
  12/* Arbitrarily chosen constants for encoding the VCAP block and lookup number
  13 * into the chain number. This is UAPI.
  14 */
  15#define VCAP_BLOCK			10000
  16#define VCAP_LOOKUP			1000
  17#define VCAP_IS1_NUM_LOOKUPS		3
  18#define VCAP_IS2_NUM_LOOKUPS		2
  19#define VCAP_IS2_NUM_PAG		256
  20#define VCAP_IS1_CHAIN(lookup)		\
  21	(1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
  22#define VCAP_IS2_CHAIN(lookup, pag)	\
  23	(2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
  24/* PSFP chain and block ID */
  25#define PSFP_BLOCK_ID			OCELOT_NUM_VCAP_BLOCKS
  26#define OCELOT_PSFP_CHAIN		(3 * VCAP_BLOCK)
  27
  28static int ocelot_chain_to_block(int chain, bool ingress)
  29{
  30	int lookup, pag;
  31
  32	if (!ingress) {
  33		if (chain == 0)
  34			return VCAP_ES0;
  35		return -EOPNOTSUPP;
  36	}
  37
  38	/* Backwards compatibility with older, single-chain tc-flower
  39	 * offload support in Ocelot
  40	 */
  41	if (chain == 0)
  42		return VCAP_IS2;
  43
  44	for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
  45		if (chain == VCAP_IS1_CHAIN(lookup))
  46			return VCAP_IS1;
  47
  48	for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
  49		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  50			if (chain == VCAP_IS2_CHAIN(lookup, pag))
  51				return VCAP_IS2;
  52
  53	if (chain == OCELOT_PSFP_CHAIN)
  54		return PSFP_BLOCK_ID;
  55
  56	return -EOPNOTSUPP;
  57}
  58
  59/* Caller must ensure this is a valid IS1 or IS2 chain first,
  60 * by calling ocelot_chain_to_block.
  61 */
  62static int ocelot_chain_to_lookup(int chain)
  63{
  64	/* Backwards compatibility with older, single-chain tc-flower
  65	 * offload support in Ocelot
  66	 */
  67	if (chain == 0)
  68		return 0;
  69
  70	return (chain / VCAP_LOOKUP) % 10;
  71}
  72
  73/* Caller must ensure this is a valid IS2 chain first,
  74 * by calling ocelot_chain_to_block.
  75 */
  76static int ocelot_chain_to_pag(int chain)
  77{
  78	int lookup;
  79
  80	/* Backwards compatibility with older, single-chain tc-flower
  81	 * offload support in Ocelot
  82	 */
  83	if (chain == 0)
  84		return 0;
  85
  86	lookup = ocelot_chain_to_lookup(chain);
  87
  88	/* calculate PAG value as chain index relative to the first PAG */
  89	return chain - VCAP_IS2_CHAIN(lookup, 0);
  90}
  91
  92static bool ocelot_is_goto_target_valid(int goto_target, int chain,
  93					bool ingress)
  94{
  95	int pag;
  96
  97	/* Can't offload GOTO in VCAP ES0 */
  98	if (!ingress)
  99		return (goto_target < 0);
 100
 101	/* Non-optional GOTOs */
 102	if (chain == 0)
 103		/* VCAP IS1 can be skipped, either partially or completely */
 104		return (goto_target == VCAP_IS1_CHAIN(0) ||
 105			goto_target == VCAP_IS1_CHAIN(1) ||
 106			goto_target == VCAP_IS1_CHAIN(2) ||
 107			goto_target == VCAP_IS2_CHAIN(0, 0) ||
 108			goto_target == VCAP_IS2_CHAIN(1, 0) ||
 109			goto_target == OCELOT_PSFP_CHAIN);
 110
 111	if (chain == VCAP_IS1_CHAIN(0))
 112		return (goto_target == VCAP_IS1_CHAIN(1));
 113
 114	if (chain == VCAP_IS1_CHAIN(1))
 115		return (goto_target == VCAP_IS1_CHAIN(2));
 116
 117	/* Lookup 2 of VCAP IS1 can really support non-optional GOTOs,
 118	 * using a Policy Association Group (PAG) value, which is an 8-bit
 119	 * value encoding a VCAP IS2 target chain.
 120	 */
 121	if (chain == VCAP_IS1_CHAIN(2)) {
 122		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 123			if (goto_target == VCAP_IS2_CHAIN(0, pag))
 124				return true;
 125
 126		return false;
 127	}
 128
 129	/* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1.
 130	 * We cannot change the PAG at this point.
 131	 */
 132	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 133		if (chain == VCAP_IS2_CHAIN(0, pag))
 134			return (goto_target == VCAP_IS2_CHAIN(1, pag));
 135
 136	/* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
 137	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
 138		if (chain == VCAP_IS2_CHAIN(1, pag))
 139			return (goto_target == OCELOT_PSFP_CHAIN);
 140
 141	return false;
 142}
 143
 144static struct ocelot_vcap_filter *
 145ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
 146{
 147	struct ocelot_vcap_filter *filter;
 148	struct ocelot_vcap_block *block;
 149	int block_id;
 150
 151	block_id = ocelot_chain_to_block(chain, true);
 152	if (block_id < 0)
 153		return NULL;
 154
 155	if (block_id == VCAP_IS2) {
 156		block = &ocelot->block[VCAP_IS1];
 157
 158		list_for_each_entry(filter, &block->rules, list)
 159			if (filter->type == OCELOT_VCAP_FILTER_PAG &&
 160			    filter->goto_target == chain)
 161				return filter;
 162	}
 163
 164	list_for_each_entry(filter, &ocelot->dummy_rules, list)
 165		if (filter->goto_target == chain)
 166			return filter;
 167
 168	return NULL;
 169}
 170
 171static int
 172ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
 173					struct ocelot_vcap_filter *filter,
 174					const struct flow_action_entry *a,
 175					struct netlink_ext_ack *extack)
 176{
 177	struct ocelot_port *ocelot_port = ocelot->ports[port];
 178
 179	if (filter->goto_target != -1) {
 180		NL_SET_ERR_MSG_MOD(extack,
 181				   "Last action must be GOTO");
 182		return -EOPNOTSUPP;
 183	}
 184
 185	if (!ocelot_port->vlan_aware) {
 186		NL_SET_ERR_MSG_MOD(extack,
 187				   "Can only modify VLAN under VLAN aware bridge");
 188		return -EOPNOTSUPP;
 189	}
 190
 191	filter->action.vid_replace_ena = true;
 192	filter->action.pcp_dei_ena = true;
 193	filter->action.vid = a->vlan.vid;
 194	filter->action.pcp = a->vlan.prio;
 195	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 196
 197	return 0;
 198}
 199
 200static int
 201ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
 202				       const struct flow_action_entry *a,
 203				       struct netlink_ext_ack *extack)
 204{
 205	enum ocelot_tag_tpid_sel tpid;
 206
 207	switch (ntohs(a->vlan.proto)) {
 208	case ETH_P_8021Q:
 209		tpid = OCELOT_TAG_TPID_SEL_8021Q;
 210		break;
 211	case ETH_P_8021AD:
 212		tpid = OCELOT_TAG_TPID_SEL_8021AD;
 213		break;
 214	default:
 215		NL_SET_ERR_MSG_MOD(extack,
 216				   "Cannot modify custom TPID");
 217		return -EOPNOTSUPP;
 218	}
 219
 220	filter->action.tag_a_tpid_sel = tpid;
 221	filter->action.push_outer_tag = OCELOT_ES0_TAG;
 222	filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
 223	filter->action.vid_a_val = a->vlan.vid;
 224	filter->action.pcp_a_val = a->vlan.prio;
 225	filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
 226	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 227
 228	return 0;
 229}
 230
 231static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 232				      bool ingress, struct flow_cls_offload *f,
 233				      struct ocelot_vcap_filter *filter)
 234{
 235	const struct flow_action *action = &f->rule->action;
 236	struct netlink_ext_ack *extack = f->common.extack;
 237	bool allow_missing_goto_target = false;
 238	const struct flow_action_entry *a;
 239	enum ocelot_tag_tpid_sel tpid;
 240	int i, chain, egress_port;
 241	u32 pol_ix, pol_max;
 242	u64 rate;
 243	int err;
 244
 245	if (!flow_action_basic_hw_stats_check(&f->rule->action,
 246					      f->common.extack))
 247		return -EOPNOTSUPP;
 248
 249	chain = f->common.chain_index;
 250	filter->block_id = ocelot_chain_to_block(chain, ingress);
 251	if (filter->block_id < 0) {
 252		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
 253		return -EOPNOTSUPP;
 254	}
 255	if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
 256		filter->lookup = ocelot_chain_to_lookup(chain);
 257	if (filter->block_id == VCAP_IS2)
 258		filter->pag = ocelot_chain_to_pag(chain);
 259
 260	filter->goto_target = -1;
 261	filter->type = OCELOT_VCAP_FILTER_DUMMY;
 262
 263	flow_action_for_each(i, a, action) {
 264		switch (a->id) {
 265		case FLOW_ACTION_DROP:
 266			if (filter->block_id != VCAP_IS2) {
 267				NL_SET_ERR_MSG_MOD(extack,
 268						   "Drop action can only be offloaded to VCAP IS2");
 269				return -EOPNOTSUPP;
 270			}
 271			if (filter->goto_target != -1) {
 272				NL_SET_ERR_MSG_MOD(extack,
 273						   "Last action must be GOTO");
 274				return -EOPNOTSUPP;
 275			}
 276			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
 277			filter->action.port_mask = 0;
 278			filter->action.police_ena = true;
 279			filter->action.pol_ix = OCELOT_POLICER_DISCARD;
 280			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 281			break;
 282		case FLOW_ACTION_ACCEPT:
 283			if (filter->block_id != VCAP_ES0 &&
 284			    filter->block_id != VCAP_IS1 &&
 285			    filter->block_id != VCAP_IS2) {
 286				NL_SET_ERR_MSG_MOD(extack,
 287						   "Accept action can only be offloaded to VCAP chains");
 288				return -EOPNOTSUPP;
 289			}
 290			if (filter->block_id != VCAP_ES0 &&
 291			    filter->goto_target != -1) {
 292				NL_SET_ERR_MSG_MOD(extack,
 293						   "Last action must be GOTO");
 294				return -EOPNOTSUPP;
 295			}
 296			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 297			break;
 298		case FLOW_ACTION_TRAP:
 299			if (filter->block_id != VCAP_IS2 ||
 300			    filter->lookup != 0) {
 301				NL_SET_ERR_MSG_MOD(extack,
 302						   "Trap action can only be offloaded to VCAP IS2 lookup 0");
 303				return -EOPNOTSUPP;
 304			}
 305			if (filter->goto_target != -1) {
 306				NL_SET_ERR_MSG_MOD(extack,
 307						   "Last action must be GOTO");
 308				return -EOPNOTSUPP;
 309			}
 310			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
 311			filter->action.port_mask = 0;
 312			filter->action.cpu_copy_ena = true;
 313			filter->action.cpu_qu_num = 0;
 314			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 315			filter->is_trap = true;
 316			break;
 317		case FLOW_ACTION_POLICE:
 318			if (filter->block_id == PSFP_BLOCK_ID) {
 319				filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
 320				break;
 321			}
 322			if (filter->block_id != VCAP_IS2 ||
 323			    filter->lookup != 0) {
 324				NL_SET_ERR_MSG_MOD(extack,
 325						   "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
 326				return -EOPNOTSUPP;
 327			}
 328			if (filter->goto_target != -1) {
 329				NL_SET_ERR_MSG_MOD(extack,
 330						   "Last action must be GOTO");
 331				return -EOPNOTSUPP;
 332			}
 333
 334			err = ocelot_policer_validate(action, a, extack);
 335			if (err)
 336				return err;
 337
 338			filter->action.police_ena = true;
 339
 340			pol_ix = a->hw_index + ocelot->vcap_pol.base;
 341			pol_max = ocelot->vcap_pol.max;
 342
 343			if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
 344				pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
 345				pol_max = ocelot->vcap_pol.max2;
 346			}
 347
 348			if (pol_ix >= pol_max)
 349				return -EINVAL;
 350
 351			filter->action.pol_ix = pol_ix;
 352
 353			rate = a->police.rate_bytes_ps;
 354			filter->action.pol.rate = div_u64(rate, 1000) * 8;
 355			filter->action.pol.burst = a->police.burst;
 356			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 357			break;
 358		case FLOW_ACTION_REDIRECT:
 359			if (filter->block_id != VCAP_IS2) {
 360				NL_SET_ERR_MSG_MOD(extack,
 361						   "Redirect action can only be offloaded to VCAP IS2");
 362				return -EOPNOTSUPP;
 363			}
 364			if (filter->goto_target != -1) {
 365				NL_SET_ERR_MSG_MOD(extack,
 366						   "Last action must be GOTO");
 367				return -EOPNOTSUPP;
 368			}
 369			egress_port = ocelot->ops->netdev_to_port(a->dev);
 370			if (egress_port < 0) {
 371				NL_SET_ERR_MSG_MOD(extack,
 372						   "Destination not an ocelot port");
 373				return -EOPNOTSUPP;
 374			}
 375			filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
 376			filter->action.port_mask = BIT(egress_port);
 377			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 378			break;
 379		case FLOW_ACTION_MIRRED:
 380			if (filter->block_id != VCAP_IS2) {
 381				NL_SET_ERR_MSG_MOD(extack,
 382						   "Mirror action can only be offloaded to VCAP IS2");
 383				return -EOPNOTSUPP;
 384			}
 385			if (filter->goto_target != -1) {
 386				NL_SET_ERR_MSG_MOD(extack,
 387						   "Last action must be GOTO");
 388				return -EOPNOTSUPP;
 389			}
 390			egress_port = ocelot->ops->netdev_to_port(a->dev);
 391			if (egress_port < 0) {
 392				NL_SET_ERR_MSG_MOD(extack,
 393						   "Destination not an ocelot port");
 394				return -EOPNOTSUPP;
 395			}
 396			filter->egress_port.value = egress_port;
 397			filter->action.mirror_ena = true;
 398			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 399			break;
 400		case FLOW_ACTION_VLAN_POP:
 401			if (filter->block_id != VCAP_IS1) {
 402				NL_SET_ERR_MSG_MOD(extack,
 403						   "VLAN pop action can only be offloaded to VCAP IS1");
 404				return -EOPNOTSUPP;
 405			}
 406			if (filter->goto_target != -1) {
 407				NL_SET_ERR_MSG_MOD(extack,
 408						   "Last action must be GOTO");
 409				return -EOPNOTSUPP;
 410			}
 411			filter->action.vlan_pop_cnt_ena = true;
 412			filter->action.vlan_pop_cnt++;
 413			if (filter->action.vlan_pop_cnt > 2) {
 414				NL_SET_ERR_MSG_MOD(extack,
 415						   "Cannot pop more than 2 VLAN headers");
 416				return -EOPNOTSUPP;
 417			}
 418			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 419			break;
 420		case FLOW_ACTION_VLAN_MANGLE:
 421			if (filter->block_id == VCAP_IS1) {
 422				err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
 423									      filter, a,
 424									      extack);
 425			} else if (filter->block_id == VCAP_ES0) {
 426				err = ocelot_flower_parse_egress_vlan_modify(filter, a,
 427									     extack);
 428			} else {
 429				NL_SET_ERR_MSG_MOD(extack,
 430						   "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
 431				err = -EOPNOTSUPP;
 432			}
 433			if (err)
 434				return err;
 435			break;
 436		case FLOW_ACTION_PRIORITY:
 437			if (filter->block_id != VCAP_IS1) {
 438				NL_SET_ERR_MSG_MOD(extack,
 439						   "Priority action can only be offloaded to VCAP IS1");
 440				return -EOPNOTSUPP;
 441			}
 442			if (filter->goto_target != -1) {
 443				NL_SET_ERR_MSG_MOD(extack,
 444						   "Last action must be GOTO");
 445				return -EOPNOTSUPP;
 446			}
 447			filter->action.qos_ena = true;
 448			filter->action.qos_val = a->priority;
 449			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 450			break;
 451		case FLOW_ACTION_GOTO:
 452			filter->goto_target = a->chain_index;
 453
 454			if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
 455				int pag = ocelot_chain_to_pag(filter->goto_target);
 456
 457				filter->action.pag_override_mask = 0xff;
 458				filter->action.pag_val = pag;
 459				filter->type = OCELOT_VCAP_FILTER_PAG;
 460			}
 461			break;
 462		case FLOW_ACTION_VLAN_PUSH:
 463			if (filter->block_id != VCAP_ES0) {
 464				NL_SET_ERR_MSG_MOD(extack,
 465						   "VLAN push action can only be offloaded to VCAP ES0");
 466				return -EOPNOTSUPP;
 467			}
 468			switch (ntohs(a->vlan.proto)) {
 469			case ETH_P_8021Q:
 470				tpid = OCELOT_TAG_TPID_SEL_8021Q;
 471				break;
 472			case ETH_P_8021AD:
 473				tpid = OCELOT_TAG_TPID_SEL_8021AD;
 474				break;
 475			default:
 476				NL_SET_ERR_MSG_MOD(extack,
 477						   "Cannot push custom TPID");
 478				return -EOPNOTSUPP;
 479			}
 480			filter->action.tag_a_tpid_sel = tpid;
 481			filter->action.push_outer_tag = OCELOT_ES0_TAG;
 482			filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
 483			filter->action.vid_a_val = a->vlan.vid;
 484			filter->action.pcp_a_val = a->vlan.prio;
 485			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 486			break;
 487		case FLOW_ACTION_GATE:
 488			if (filter->block_id != PSFP_BLOCK_ID) {
 489				NL_SET_ERR_MSG_MOD(extack,
 490						   "Gate action can only be offloaded to PSFP chain");
 491				return -EOPNOTSUPP;
 492			}
 493			filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
 494			break;
 495		default:
 496			NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
 497			return -EOPNOTSUPP;
 498		}
 499	}
 500
 501	if (filter->goto_target == -1) {
 502		if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
 503		    chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
 504			allow_missing_goto_target = true;
 505		} else {
 506			NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
 507			return -EOPNOTSUPP;
 508		}
 509	}
 510
 511	if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
 512	    !allow_missing_goto_target) {
 513		NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
 514		return -EOPNOTSUPP;
 515	}
 516
 517	return 0;
 518}
 519
 520static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
 521				     struct flow_cls_offload *f,
 522				     struct ocelot_vcap_filter *filter)
 523{
 524	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 525	const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
 526	int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
 527	struct netlink_ext_ack *extack = f->common.extack;
 528	struct net_device *dev, *indev;
 529	struct flow_match_meta match;
 530	int ingress_port;
 531
 532	flow_rule_match_meta(rule, &match);
 533
 534	if (!match.mask->ingress_ifindex)
 535		return 0;
 536
 537	if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
 538		NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
 539		return -EOPNOTSUPP;
 540	}
 541
 542	dev = ocelot->ops->port_to_netdev(ocelot, port);
 543	if (!dev)
 544		return -EINVAL;
 545
 546	indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
 547	if (!indev) {
 548		NL_SET_ERR_MSG_MOD(extack,
 549				   "Can't find the ingress port to match on");
 550		return -ENOENT;
 551	}
 552
 553	ingress_port = ocelot->ops->netdev_to_port(indev);
 554	if (ingress_port < 0) {
 555		NL_SET_ERR_MSG_MOD(extack,
 556				   "Can only offload an ocelot ingress port");
 557		return -EOPNOTSUPP;
 558	}
 559	if (ingress_port == port) {
 560		NL_SET_ERR_MSG_MOD(extack,
 561				   "Ingress port is equal to the egress port");
 562		return -EINVAL;
 563	}
 564
 565	filter->ingress_port.value = ingress_port;
 566	filter->ingress_port.mask = GENMASK(key_length - 1, 0);
 567
 568	return 0;
 569}
 570
 571static int
 572ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
 573			struct flow_cls_offload *f,
 574			struct ocelot_vcap_filter *filter)
 575{
 576	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 577	struct flow_dissector *dissector = rule->match.dissector;
 578	struct netlink_ext_ack *extack = f->common.extack;
 579	u16 proto = ntohs(f->common.protocol);
 580	bool match_protocol = true;
 581	int ret;
 582
 583	if (dissector->used_keys &
 584	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
 585	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
 586	      BIT(FLOW_DISSECTOR_KEY_META) |
 587	      BIT(FLOW_DISSECTOR_KEY_PORTS) |
 588	      BIT(FLOW_DISSECTOR_KEY_VLAN) |
 589	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
 590	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
 591	      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
 592		return -EOPNOTSUPP;
 593	}
 594
 
 
 
 
 
 
 
 
 
 
 595	/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
 596	if (!ingress) {
 597		ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
 598		if (ret)
 599			return ret;
 600	}
 601
 602	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
 603		struct flow_match_control match;
 604
 605		flow_rule_match_control(rule, &match);
 606	}
 607
 608	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
 609		struct flow_match_vlan match;
 610
 611		flow_rule_match_vlan(rule, &match);
 612		filter->key_type = OCELOT_VCAP_KEY_ANY;
 613		filter->vlan.vid.value = match.key->vlan_id;
 614		filter->vlan.vid.mask = match.mask->vlan_id;
 615		filter->vlan.pcp.value[0] = match.key->vlan_priority;
 616		filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
 617		match_protocol = false;
 618	}
 619
 620	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
 621		struct flow_match_eth_addrs match;
 622
 623		if (filter->block_id == VCAP_ES0) {
 624			NL_SET_ERR_MSG_MOD(extack,
 625					   "VCAP ES0 cannot match on MAC address");
 626			return -EOPNOTSUPP;
 627		}
 628
 629		/* The hw support mac matches only for MAC_ETYPE key,
 630		 * therefore if other matches(port, tcp flags, etc) are added
 631		 * then just bail out
 632		 */
 633		if ((dissector->used_keys &
 634		    (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
 635		     BIT(FLOW_DISSECTOR_KEY_BASIC) |
 636		     BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
 637		    (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
 638		     BIT(FLOW_DISSECTOR_KEY_BASIC) |
 639		     BIT(FLOW_DISSECTOR_KEY_CONTROL)))
 640			return -EOPNOTSUPP;
 641
 642		flow_rule_match_eth_addrs(rule, &match);
 643
 644		if (filter->block_id == VCAP_IS1 &&
 645		    !is_zero_ether_addr(match.mask->dst)) {
 646			NL_SET_ERR_MSG_MOD(extack,
 647					   "Key type S1_NORMAL cannot match on destination MAC");
 648			return -EOPNOTSUPP;
 649		}
 650
 651		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
 652		ether_addr_copy(filter->key.etype.dmac.value,
 653				match.key->dst);
 654		ether_addr_copy(filter->key.etype.smac.value,
 655				match.key->src);
 656		ether_addr_copy(filter->key.etype.dmac.mask,
 657				match.mask->dst);
 658		ether_addr_copy(filter->key.etype.smac.mask,
 659				match.mask->src);
 660		goto finished_key_parsing;
 661	}
 662
 663	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
 664		struct flow_match_basic match;
 665
 666		flow_rule_match_basic(rule, &match);
 667		if (ntohs(match.key->n_proto) == ETH_P_IP) {
 668			if (filter->block_id == VCAP_ES0) {
 669				NL_SET_ERR_MSG_MOD(extack,
 670						   "VCAP ES0 cannot match on IP protocol");
 671				return -EOPNOTSUPP;
 672			}
 673
 674			filter->key_type = OCELOT_VCAP_KEY_IPV4;
 675			filter->key.ipv4.proto.value[0] =
 676				match.key->ip_proto;
 677			filter->key.ipv4.proto.mask[0] =
 678				match.mask->ip_proto;
 679			match_protocol = false;
 680		}
 681		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
 682			if (filter->block_id == VCAP_ES0) {
 683				NL_SET_ERR_MSG_MOD(extack,
 684						   "VCAP ES0 cannot match on IP protocol");
 685				return -EOPNOTSUPP;
 686			}
 687
 688			filter->key_type = OCELOT_VCAP_KEY_IPV6;
 689			filter->key.ipv6.proto.value[0] =
 690				match.key->ip_proto;
 691			filter->key.ipv6.proto.mask[0] =
 692				match.mask->ip_proto;
 693			match_protocol = false;
 694		}
 695	}
 696
 697	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
 698	    proto == ETH_P_IP) {
 699		struct flow_match_ipv4_addrs match;
 700		u8 *tmp;
 701
 702		if (filter->block_id == VCAP_ES0) {
 703			NL_SET_ERR_MSG_MOD(extack,
 704					   "VCAP ES0 cannot match on IP address");
 705			return -EOPNOTSUPP;
 706		}
 707
 708		flow_rule_match_ipv4_addrs(rule, &match);
 709
 710		if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
 711			NL_SET_ERR_MSG_MOD(extack,
 712					   "Key type S1_NORMAL cannot match on destination IP");
 713			return -EOPNOTSUPP;
 714		}
 715
 716		tmp = &filter->key.ipv4.sip.value.addr[0];
 717		memcpy(tmp, &match.key->src, 4);
 718
 719		tmp = &filter->key.ipv4.sip.mask.addr[0];
 720		memcpy(tmp, &match.mask->src, 4);
 721
 722		tmp = &filter->key.ipv4.dip.value.addr[0];
 723		memcpy(tmp, &match.key->dst, 4);
 724
 725		tmp = &filter->key.ipv4.dip.mask.addr[0];
 726		memcpy(tmp, &match.mask->dst, 4);
 727		match_protocol = false;
 728	}
 729
 730	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
 731	    proto == ETH_P_IPV6) {
 732		return -EOPNOTSUPP;
 733	}
 734
 735	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
 736		struct flow_match_ports match;
 737
 738		if (filter->block_id == VCAP_ES0) {
 739			NL_SET_ERR_MSG_MOD(extack,
 740					   "VCAP ES0 cannot match on L4 ports");
 741			return -EOPNOTSUPP;
 742		}
 743
 744		flow_rule_match_ports(rule, &match);
 745		filter->key.ipv4.sport.value = ntohs(match.key->src);
 746		filter->key.ipv4.sport.mask = ntohs(match.mask->src);
 747		filter->key.ipv4.dport.value = ntohs(match.key->dst);
 748		filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
 749		match_protocol = false;
 750	}
 751
 752finished_key_parsing:
 753	if (match_protocol && proto != ETH_P_ALL) {
 754		if (filter->block_id == VCAP_ES0) {
 755			NL_SET_ERR_MSG_MOD(extack,
 756					   "VCAP ES0 cannot match on L2 proto");
 757			return -EOPNOTSUPP;
 758		}
 759
 760		/* TODO: support SNAP, LLC etc */
 761		if (proto < ETH_P_802_3_MIN)
 762			return -EOPNOTSUPP;
 763		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
 764		*(__be16 *)filter->key.etype.etype.value = htons(proto);
 765		*(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
 766	}
 767	/* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
 768
 769	return 0;
 770}
 771
 772static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
 773			       struct flow_cls_offload *f,
 774			       struct ocelot_vcap_filter *filter)
 775{
 776	int ret;
 777
 778	filter->prio = f->common.prio;
 779	filter->id.cookie = f->cookie;
 780	filter->id.tc_offload = true;
 781
 782	ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
 783	if (ret)
 784		return ret;
 785
 786	/* PSFP filter need to parse key by stream identification function. */
 787	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
 788		return 0;
 789
 790	return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
 791}
 792
 793static struct ocelot_vcap_filter
 794*ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
 795			   struct flow_cls_offload *f)
 796{
 797	struct ocelot_vcap_filter *filter;
 798
 799	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
 800	if (!filter)
 801		return NULL;
 802
 803	if (ingress) {
 804		filter->ingress_port_mask = BIT(port);
 805	} else {
 806		const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
 807		int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
 808
 809		filter->egress_port.value = port;
 810		filter->egress_port.mask = GENMASK(key_length - 1, 0);
 811	}
 812
 813	return filter;
 814}
 815
 816static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
 817					struct ocelot_vcap_filter *filter)
 818{
 819	list_add(&filter->list, &ocelot->dummy_rules);
 820
 821	return 0;
 822}
 823
 824static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
 825					struct ocelot_vcap_filter *filter)
 826{
 827	list_del(&filter->list);
 828	kfree(filter);
 829
 830	return 0;
 831}
 832
 833/* If we have an egress VLAN modification rule, we need to actually write the
 834 * delta between the input VLAN (from the key) and the output VLAN (from the
 835 * action), but the action was parsed first. So we need to patch the delta into
 836 * the action here.
 837 */
 838static int
 839ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
 840				    struct netlink_ext_ack *extack)
 841{
 842	if (filter->block_id != VCAP_ES0 ||
 843	    filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
 844		return 0;
 845
 846	if (filter->vlan.vid.mask != VLAN_VID_MASK) {
 847		NL_SET_ERR_MSG_MOD(extack,
 848				   "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
 849		return -EOPNOTSUPP;
 850	}
 851
 852	filter->action.vid_a_val -= filter->vlan.vid.value;
 853	filter->action.vid_a_val &= VLAN_VID_MASK;
 854
 855	return 0;
 856}
 857
 858int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 859			      struct flow_cls_offload *f, bool ingress)
 860{
 861	struct netlink_ext_ack *extack = f->common.extack;
 862	struct ocelot_vcap_filter *filter;
 863	int chain = f->common.chain_index;
 864	int block_id, ret;
 865
 866	if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
 867		NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
 868		return -EOPNOTSUPP;
 869	}
 870
 871	block_id = ocelot_chain_to_block(chain, ingress);
 872	if (block_id < 0) {
 873		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
 874		return -EOPNOTSUPP;
 875	}
 876
 877	filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
 878						     f->cookie, true);
 879	if (filter) {
 880		/* Filter already exists on other ports */
 881		if (!ingress) {
 882			NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
 883			return -EOPNOTSUPP;
 884		}
 885
 886		filter->ingress_port_mask |= BIT(port);
 887
 888		return ocelot_vcap_filter_replace(ocelot, filter);
 889	}
 890
 891	/* Filter didn't exist, create it now */
 892	filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
 893	if (!filter)
 894		return -ENOMEM;
 895
 896	ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
 897	if (ret) {
 898		kfree(filter);
 899		return ret;
 900	}
 901
 902	ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
 903	if (ret) {
 904		kfree(filter);
 905		return ret;
 906	}
 907
 908	/* The non-optional GOTOs for the TCAM skeleton don't need
 909	 * to be actually offloaded.
 910	 */
 911	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
 912		return ocelot_vcap_dummy_filter_add(ocelot, filter);
 913
 914	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
 915		kfree(filter);
 916		if (ocelot->ops->psfp_filter_add)
 917			return ocelot->ops->psfp_filter_add(ocelot, port, f);
 918
 919		NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
 920		return -EOPNOTSUPP;
 921	}
 922
 923	return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
 924}
 925EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 926
 927int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
 928			      struct flow_cls_offload *f, bool ingress)
 929{
 930	struct ocelot_vcap_filter *filter;
 931	struct ocelot_vcap_block *block;
 932	int block_id;
 933
 934	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
 935	if (block_id < 0)
 936		return 0;
 937
 938	if (block_id == PSFP_BLOCK_ID) {
 939		if (ocelot->ops->psfp_filter_del)
 940			return ocelot->ops->psfp_filter_del(ocelot, f);
 941
 942		return -EOPNOTSUPP;
 943	}
 944
 945	block = &ocelot->block[block_id];
 946
 947	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
 948	if (!filter)
 949		return 0;
 950
 951	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
 952		return ocelot_vcap_dummy_filter_del(ocelot, filter);
 953
 954	if (ingress) {
 955		filter->ingress_port_mask &= ~BIT(port);
 956		if (filter->ingress_port_mask)
 957			return ocelot_vcap_filter_replace(ocelot, filter);
 958	}
 959
 960	return ocelot_vcap_filter_del(ocelot, filter);
 961}
 962EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 963
 964int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
 965			    struct flow_cls_offload *f, bool ingress)
 966{
 967	struct ocelot_vcap_filter *filter;
 968	struct ocelot_vcap_block *block;
 969	struct flow_stats stats = {0};
 970	int block_id, ret;
 971
 972	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
 973	if (block_id < 0)
 974		return 0;
 975
 976	if (block_id == PSFP_BLOCK_ID) {
 977		if (ocelot->ops->psfp_stats_get) {
 978			ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
 979			if (ret)
 980				return ret;
 981
 982			goto stats_update;
 983		}
 984
 985		return -EOPNOTSUPP;
 986	}
 987
 988	block = &ocelot->block[block_id];
 989
 990	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
 991	if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
 992		return 0;
 993
 994	ret = ocelot_vcap_filter_stats_update(ocelot, filter);
 995	if (ret)
 996		return ret;
 997
 998	stats.pkts = filter->stats.pkts;
 999
1000stats_update:
1001	flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
1002			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1003	return 0;
1004}
1005EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);