Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
   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);