0001
0002
0003
0004
0005
0006 #include <net/pkt_cls.h>
0007 #include <net/tc_act/tc_gact.h>
0008 #include <soc/mscc/ocelot_vcap.h>
0009 #include "ocelot_police.h"
0010 #include "ocelot_vcap.h"
0011
0012
0013
0014
0015 #define VCAP_BLOCK 10000
0016 #define VCAP_LOOKUP 1000
0017 #define VCAP_IS1_NUM_LOOKUPS 3
0018 #define VCAP_IS2_NUM_LOOKUPS 2
0019 #define VCAP_IS2_NUM_PAG 256
0020 #define VCAP_IS1_CHAIN(lookup) \
0021 (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
0022 #define VCAP_IS2_CHAIN(lookup, pag) \
0023 (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
0024
0025 #define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS
0026 #define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK)
0027
0028 static int ocelot_chain_to_block(int chain, bool ingress)
0029 {
0030 int lookup, pag;
0031
0032 if (!ingress) {
0033 if (chain == 0)
0034 return VCAP_ES0;
0035 return -EOPNOTSUPP;
0036 }
0037
0038
0039
0040
0041 if (chain == 0)
0042 return VCAP_IS2;
0043
0044 for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
0045 if (chain == VCAP_IS1_CHAIN(lookup))
0046 return VCAP_IS1;
0047
0048 for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
0049 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
0050 if (chain == VCAP_IS2_CHAIN(lookup, pag))
0051 return VCAP_IS2;
0052
0053 if (chain == OCELOT_PSFP_CHAIN)
0054 return PSFP_BLOCK_ID;
0055
0056 return -EOPNOTSUPP;
0057 }
0058
0059
0060
0061
0062 static int ocelot_chain_to_lookup(int chain)
0063 {
0064
0065
0066
0067 if (chain == 0)
0068 return 0;
0069
0070 return (chain / VCAP_LOOKUP) % 10;
0071 }
0072
0073
0074
0075
0076 static int ocelot_chain_to_pag(int chain)
0077 {
0078 int lookup;
0079
0080
0081
0082
0083 if (chain == 0)
0084 return 0;
0085
0086 lookup = ocelot_chain_to_lookup(chain);
0087
0088
0089 return chain - VCAP_IS2_CHAIN(lookup, 0);
0090 }
0091
0092 static bool ocelot_is_goto_target_valid(int goto_target, int chain,
0093 bool ingress)
0094 {
0095 int pag;
0096
0097
0098 if (!ingress)
0099 return (goto_target < 0);
0100
0101
0102 if (chain == 0)
0103
0104 return (goto_target == VCAP_IS1_CHAIN(0) ||
0105 goto_target == VCAP_IS1_CHAIN(1) ||
0106 goto_target == VCAP_IS1_CHAIN(2) ||
0107 goto_target == VCAP_IS2_CHAIN(0, 0) ||
0108 goto_target == VCAP_IS2_CHAIN(1, 0) ||
0109 goto_target == OCELOT_PSFP_CHAIN);
0110
0111 if (chain == VCAP_IS1_CHAIN(0))
0112 return (goto_target == VCAP_IS1_CHAIN(1));
0113
0114 if (chain == VCAP_IS1_CHAIN(1))
0115 return (goto_target == VCAP_IS1_CHAIN(2));
0116
0117
0118
0119
0120
0121 if (chain == VCAP_IS1_CHAIN(2)) {
0122 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
0123 if (goto_target == VCAP_IS2_CHAIN(0, pag))
0124 return true;
0125
0126 return false;
0127 }
0128
0129
0130
0131
0132 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
0133 if (chain == VCAP_IS2_CHAIN(0, pag))
0134 return (goto_target == VCAP_IS2_CHAIN(1, pag));
0135
0136
0137 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
0138 if (chain == VCAP_IS2_CHAIN(1, pag))
0139 return (goto_target == OCELOT_PSFP_CHAIN);
0140
0141 return false;
0142 }
0143
0144 static struct ocelot_vcap_filter *
0145 ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
0146 {
0147 struct ocelot_vcap_filter *filter;
0148 struct ocelot_vcap_block *block;
0149 int block_id;
0150
0151 block_id = ocelot_chain_to_block(chain, true);
0152 if (block_id < 0)
0153 return NULL;
0154
0155 if (block_id == VCAP_IS2) {
0156 block = &ocelot->block[VCAP_IS1];
0157
0158 list_for_each_entry(filter, &block->rules, list)
0159 if (filter->type == OCELOT_VCAP_FILTER_PAG &&
0160 filter->goto_target == chain)
0161 return filter;
0162 }
0163
0164 list_for_each_entry(filter, &ocelot->dummy_rules, list)
0165 if (filter->goto_target == chain)
0166 return filter;
0167
0168 return NULL;
0169 }
0170
0171 static int
0172 ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
0173 struct ocelot_vcap_filter *filter,
0174 const struct flow_action_entry *a,
0175 struct netlink_ext_ack *extack)
0176 {
0177 struct ocelot_port *ocelot_port = ocelot->ports[port];
0178
0179 if (filter->goto_target != -1) {
0180 NL_SET_ERR_MSG_MOD(extack,
0181 "Last action must be GOTO");
0182 return -EOPNOTSUPP;
0183 }
0184
0185 if (!ocelot_port->vlan_aware) {
0186 NL_SET_ERR_MSG_MOD(extack,
0187 "Can only modify VLAN under VLAN aware bridge");
0188 return -EOPNOTSUPP;
0189 }
0190
0191 filter->action.vid_replace_ena = true;
0192 filter->action.pcp_dei_ena = true;
0193 filter->action.vid = a->vlan.vid;
0194 filter->action.pcp = a->vlan.prio;
0195 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0196
0197 return 0;
0198 }
0199
0200 static int
0201 ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
0202 const struct flow_action_entry *a,
0203 struct netlink_ext_ack *extack)
0204 {
0205 enum ocelot_tag_tpid_sel tpid;
0206
0207 switch (ntohs(a->vlan.proto)) {
0208 case ETH_P_8021Q:
0209 tpid = OCELOT_TAG_TPID_SEL_8021Q;
0210 break;
0211 case ETH_P_8021AD:
0212 tpid = OCELOT_TAG_TPID_SEL_8021AD;
0213 break;
0214 default:
0215 NL_SET_ERR_MSG_MOD(extack,
0216 "Cannot modify custom TPID");
0217 return -EOPNOTSUPP;
0218 }
0219
0220 filter->action.tag_a_tpid_sel = tpid;
0221 filter->action.push_outer_tag = OCELOT_ES0_TAG;
0222 filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
0223 filter->action.vid_a_val = a->vlan.vid;
0224 filter->action.pcp_a_val = a->vlan.prio;
0225 filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
0226 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0227
0228 return 0;
0229 }
0230
0231 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
0232 bool ingress, struct flow_cls_offload *f,
0233 struct ocelot_vcap_filter *filter)
0234 {
0235 const struct flow_action *action = &f->rule->action;
0236 struct netlink_ext_ack *extack = f->common.extack;
0237 bool allow_missing_goto_target = false;
0238 const struct flow_action_entry *a;
0239 enum ocelot_tag_tpid_sel tpid;
0240 int i, chain, egress_port;
0241 u32 pol_ix, pol_max;
0242 u64 rate;
0243 int err;
0244
0245 if (!flow_action_basic_hw_stats_check(&f->rule->action,
0246 f->common.extack))
0247 return -EOPNOTSUPP;
0248
0249 chain = f->common.chain_index;
0250 filter->block_id = ocelot_chain_to_block(chain, ingress);
0251 if (filter->block_id < 0) {
0252 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
0253 return -EOPNOTSUPP;
0254 }
0255 if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
0256 filter->lookup = ocelot_chain_to_lookup(chain);
0257 if (filter->block_id == VCAP_IS2)
0258 filter->pag = ocelot_chain_to_pag(chain);
0259
0260 filter->goto_target = -1;
0261 filter->type = OCELOT_VCAP_FILTER_DUMMY;
0262
0263 flow_action_for_each(i, a, action) {
0264 switch (a->id) {
0265 case FLOW_ACTION_DROP:
0266 if (filter->block_id != VCAP_IS2) {
0267 NL_SET_ERR_MSG_MOD(extack,
0268 "Drop action can only be offloaded to VCAP IS2");
0269 return -EOPNOTSUPP;
0270 }
0271 if (filter->goto_target != -1) {
0272 NL_SET_ERR_MSG_MOD(extack,
0273 "Last action must be GOTO");
0274 return -EOPNOTSUPP;
0275 }
0276 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
0277 filter->action.port_mask = 0;
0278 filter->action.police_ena = true;
0279 filter->action.pol_ix = OCELOT_POLICER_DISCARD;
0280 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0281 break;
0282 case FLOW_ACTION_ACCEPT:
0283 if (filter->block_id != VCAP_ES0 &&
0284 filter->block_id != VCAP_IS1 &&
0285 filter->block_id != VCAP_IS2) {
0286 NL_SET_ERR_MSG_MOD(extack,
0287 "Accept action can only be offloaded to VCAP chains");
0288 return -EOPNOTSUPP;
0289 }
0290 if (filter->block_id != VCAP_ES0 &&
0291 filter->goto_target != -1) {
0292 NL_SET_ERR_MSG_MOD(extack,
0293 "Last action must be GOTO");
0294 return -EOPNOTSUPP;
0295 }
0296 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0297 break;
0298 case FLOW_ACTION_TRAP:
0299 if (filter->block_id != VCAP_IS2 ||
0300 filter->lookup != 0) {
0301 NL_SET_ERR_MSG_MOD(extack,
0302 "Trap action can only be offloaded to VCAP IS2 lookup 0");
0303 return -EOPNOTSUPP;
0304 }
0305 if (filter->goto_target != -1) {
0306 NL_SET_ERR_MSG_MOD(extack,
0307 "Last action must be GOTO");
0308 return -EOPNOTSUPP;
0309 }
0310 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
0311 filter->action.port_mask = 0;
0312 filter->action.cpu_copy_ena = true;
0313 filter->action.cpu_qu_num = 0;
0314 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0315 filter->is_trap = true;
0316 break;
0317 case FLOW_ACTION_POLICE:
0318 if (filter->block_id == PSFP_BLOCK_ID) {
0319 filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
0320 break;
0321 }
0322 if (filter->block_id != VCAP_IS2 ||
0323 filter->lookup != 0) {
0324 NL_SET_ERR_MSG_MOD(extack,
0325 "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
0326 return -EOPNOTSUPP;
0327 }
0328 if (filter->goto_target != -1) {
0329 NL_SET_ERR_MSG_MOD(extack,
0330 "Last action must be GOTO");
0331 return -EOPNOTSUPP;
0332 }
0333
0334 err = ocelot_policer_validate(action, a, extack);
0335 if (err)
0336 return err;
0337
0338 filter->action.police_ena = true;
0339
0340 pol_ix = a->hw_index + ocelot->vcap_pol.base;
0341 pol_max = ocelot->vcap_pol.max;
0342
0343 if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
0344 pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
0345 pol_max = ocelot->vcap_pol.max2;
0346 }
0347
0348 if (pol_ix >= pol_max)
0349 return -EINVAL;
0350
0351 filter->action.pol_ix = pol_ix;
0352
0353 rate = a->police.rate_bytes_ps;
0354 filter->action.pol.rate = div_u64(rate, 1000) * 8;
0355 filter->action.pol.burst = a->police.burst;
0356 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0357 break;
0358 case FLOW_ACTION_REDIRECT:
0359 if (filter->block_id != VCAP_IS2) {
0360 NL_SET_ERR_MSG_MOD(extack,
0361 "Redirect action can only be offloaded to VCAP IS2");
0362 return -EOPNOTSUPP;
0363 }
0364 if (filter->goto_target != -1) {
0365 NL_SET_ERR_MSG_MOD(extack,
0366 "Last action must be GOTO");
0367 return -EOPNOTSUPP;
0368 }
0369 egress_port = ocelot->ops->netdev_to_port(a->dev);
0370 if (egress_port < 0) {
0371 NL_SET_ERR_MSG_MOD(extack,
0372 "Destination not an ocelot port");
0373 return -EOPNOTSUPP;
0374 }
0375 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
0376 filter->action.port_mask = BIT(egress_port);
0377 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0378 break;
0379 case FLOW_ACTION_MIRRED:
0380 if (filter->block_id != VCAP_IS2) {
0381 NL_SET_ERR_MSG_MOD(extack,
0382 "Mirror action can only be offloaded to VCAP IS2");
0383 return -EOPNOTSUPP;
0384 }
0385 if (filter->goto_target != -1) {
0386 NL_SET_ERR_MSG_MOD(extack,
0387 "Last action must be GOTO");
0388 return -EOPNOTSUPP;
0389 }
0390 egress_port = ocelot->ops->netdev_to_port(a->dev);
0391 if (egress_port < 0) {
0392 NL_SET_ERR_MSG_MOD(extack,
0393 "Destination not an ocelot port");
0394 return -EOPNOTSUPP;
0395 }
0396 filter->egress_port.value = egress_port;
0397 filter->action.mirror_ena = true;
0398 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0399 break;
0400 case FLOW_ACTION_VLAN_POP:
0401 if (filter->block_id != VCAP_IS1) {
0402 NL_SET_ERR_MSG_MOD(extack,
0403 "VLAN pop action can only be offloaded to VCAP IS1");
0404 return -EOPNOTSUPP;
0405 }
0406 if (filter->goto_target != -1) {
0407 NL_SET_ERR_MSG_MOD(extack,
0408 "Last action must be GOTO");
0409 return -EOPNOTSUPP;
0410 }
0411 filter->action.vlan_pop_cnt_ena = true;
0412 filter->action.vlan_pop_cnt++;
0413 if (filter->action.vlan_pop_cnt > 2) {
0414 NL_SET_ERR_MSG_MOD(extack,
0415 "Cannot pop more than 2 VLAN headers");
0416 return -EOPNOTSUPP;
0417 }
0418 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0419 break;
0420 case FLOW_ACTION_VLAN_MANGLE:
0421 if (filter->block_id == VCAP_IS1) {
0422 err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
0423 filter, a,
0424 extack);
0425 } else if (filter->block_id == VCAP_ES0) {
0426 err = ocelot_flower_parse_egress_vlan_modify(filter, a,
0427 extack);
0428 } else {
0429 NL_SET_ERR_MSG_MOD(extack,
0430 "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
0431 err = -EOPNOTSUPP;
0432 }
0433 if (err)
0434 return err;
0435 break;
0436 case FLOW_ACTION_PRIORITY:
0437 if (filter->block_id != VCAP_IS1) {
0438 NL_SET_ERR_MSG_MOD(extack,
0439 "Priority action can only be offloaded to VCAP IS1");
0440 return -EOPNOTSUPP;
0441 }
0442 if (filter->goto_target != -1) {
0443 NL_SET_ERR_MSG_MOD(extack,
0444 "Last action must be GOTO");
0445 return -EOPNOTSUPP;
0446 }
0447 filter->action.qos_ena = true;
0448 filter->action.qos_val = a->priority;
0449 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0450 break;
0451 case FLOW_ACTION_GOTO:
0452 filter->goto_target = a->chain_index;
0453
0454 if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
0455 int pag = ocelot_chain_to_pag(filter->goto_target);
0456
0457 filter->action.pag_override_mask = 0xff;
0458 filter->action.pag_val = pag;
0459 filter->type = OCELOT_VCAP_FILTER_PAG;
0460 }
0461 break;
0462 case FLOW_ACTION_VLAN_PUSH:
0463 if (filter->block_id != VCAP_ES0) {
0464 NL_SET_ERR_MSG_MOD(extack,
0465 "VLAN push action can only be offloaded to VCAP ES0");
0466 return -EOPNOTSUPP;
0467 }
0468 switch (ntohs(a->vlan.proto)) {
0469 case ETH_P_8021Q:
0470 tpid = OCELOT_TAG_TPID_SEL_8021Q;
0471 break;
0472 case ETH_P_8021AD:
0473 tpid = OCELOT_TAG_TPID_SEL_8021AD;
0474 break;
0475 default:
0476 NL_SET_ERR_MSG_MOD(extack,
0477 "Cannot push custom TPID");
0478 return -EOPNOTSUPP;
0479 }
0480 filter->action.tag_a_tpid_sel = tpid;
0481 filter->action.push_outer_tag = OCELOT_ES0_TAG;
0482 filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
0483 filter->action.vid_a_val = a->vlan.vid;
0484 filter->action.pcp_a_val = a->vlan.prio;
0485 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
0486 break;
0487 case FLOW_ACTION_GATE:
0488 if (filter->block_id != PSFP_BLOCK_ID) {
0489 NL_SET_ERR_MSG_MOD(extack,
0490 "Gate action can only be offloaded to PSFP chain");
0491 return -EOPNOTSUPP;
0492 }
0493 filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
0494 break;
0495 default:
0496 NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
0497 return -EOPNOTSUPP;
0498 }
0499 }
0500
0501 if (filter->goto_target == -1) {
0502 if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
0503 chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
0504 allow_missing_goto_target = true;
0505 } else {
0506 NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
0507 return -EOPNOTSUPP;
0508 }
0509 }
0510
0511 if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
0512 !allow_missing_goto_target) {
0513 NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
0514 return -EOPNOTSUPP;
0515 }
0516
0517 return 0;
0518 }
0519
0520 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
0521 struct flow_cls_offload *f,
0522 struct ocelot_vcap_filter *filter)
0523 {
0524 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
0525 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
0526 int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
0527 struct netlink_ext_ack *extack = f->common.extack;
0528 struct net_device *dev, *indev;
0529 struct flow_match_meta match;
0530 int ingress_port;
0531
0532 flow_rule_match_meta(rule, &match);
0533
0534 if (!match.mask->ingress_ifindex)
0535 return 0;
0536
0537 if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
0538 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
0539 return -EOPNOTSUPP;
0540 }
0541
0542 dev = ocelot->ops->port_to_netdev(ocelot, port);
0543 if (!dev)
0544 return -EINVAL;
0545
0546 indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
0547 if (!indev) {
0548 NL_SET_ERR_MSG_MOD(extack,
0549 "Can't find the ingress port to match on");
0550 return -ENOENT;
0551 }
0552
0553 ingress_port = ocelot->ops->netdev_to_port(indev);
0554 if (ingress_port < 0) {
0555 NL_SET_ERR_MSG_MOD(extack,
0556 "Can only offload an ocelot ingress port");
0557 return -EOPNOTSUPP;
0558 }
0559 if (ingress_port == port) {
0560 NL_SET_ERR_MSG_MOD(extack,
0561 "Ingress port is equal to the egress port");
0562 return -EINVAL;
0563 }
0564
0565 filter->ingress_port.value = ingress_port;
0566 filter->ingress_port.mask = GENMASK(key_length - 1, 0);
0567
0568 return 0;
0569 }
0570
0571 static int
0572 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
0573 struct flow_cls_offload *f,
0574 struct ocelot_vcap_filter *filter)
0575 {
0576 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
0577 struct flow_dissector *dissector = rule->match.dissector;
0578 struct netlink_ext_ack *extack = f->common.extack;
0579 u16 proto = ntohs(f->common.protocol);
0580 bool match_protocol = true;
0581 int ret;
0582
0583 if (dissector->used_keys &
0584 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
0585 BIT(FLOW_DISSECTOR_KEY_BASIC) |
0586 BIT(FLOW_DISSECTOR_KEY_META) |
0587 BIT(FLOW_DISSECTOR_KEY_PORTS) |
0588 BIT(FLOW_DISSECTOR_KEY_VLAN) |
0589 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
0590 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
0591 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
0592 return -EOPNOTSUPP;
0593 }
0594
0595
0596 if (!ingress) {
0597 ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
0598 if (ret)
0599 return ret;
0600 }
0601
0602 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
0603 struct flow_match_control match;
0604
0605 flow_rule_match_control(rule, &match);
0606 }
0607
0608 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
0609 struct flow_match_eth_addrs match;
0610
0611 if (filter->block_id == VCAP_ES0) {
0612 NL_SET_ERR_MSG_MOD(extack,
0613 "VCAP ES0 cannot match on MAC address");
0614 return -EOPNOTSUPP;
0615 }
0616
0617
0618
0619
0620
0621 if ((dissector->used_keys &
0622 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
0623 BIT(FLOW_DISSECTOR_KEY_BASIC) |
0624 BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
0625 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
0626 BIT(FLOW_DISSECTOR_KEY_BASIC) |
0627 BIT(FLOW_DISSECTOR_KEY_CONTROL)))
0628 return -EOPNOTSUPP;
0629
0630 flow_rule_match_eth_addrs(rule, &match);
0631
0632 if (filter->block_id == VCAP_IS1 &&
0633 !is_zero_ether_addr(match.mask->dst)) {
0634 NL_SET_ERR_MSG_MOD(extack,
0635 "Key type S1_NORMAL cannot match on destination MAC");
0636 return -EOPNOTSUPP;
0637 }
0638
0639 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
0640 ether_addr_copy(filter->key.etype.dmac.value,
0641 match.key->dst);
0642 ether_addr_copy(filter->key.etype.smac.value,
0643 match.key->src);
0644 ether_addr_copy(filter->key.etype.dmac.mask,
0645 match.mask->dst);
0646 ether_addr_copy(filter->key.etype.smac.mask,
0647 match.mask->src);
0648 goto finished_key_parsing;
0649 }
0650
0651 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
0652 struct flow_match_basic match;
0653
0654 flow_rule_match_basic(rule, &match);
0655 if (ntohs(match.key->n_proto) == ETH_P_IP) {
0656 if (filter->block_id == VCAP_ES0) {
0657 NL_SET_ERR_MSG_MOD(extack,
0658 "VCAP ES0 cannot match on IP protocol");
0659 return -EOPNOTSUPP;
0660 }
0661
0662 filter->key_type = OCELOT_VCAP_KEY_IPV4;
0663 filter->key.ipv4.proto.value[0] =
0664 match.key->ip_proto;
0665 filter->key.ipv4.proto.mask[0] =
0666 match.mask->ip_proto;
0667 match_protocol = false;
0668 }
0669 if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
0670 if (filter->block_id == VCAP_ES0) {
0671 NL_SET_ERR_MSG_MOD(extack,
0672 "VCAP ES0 cannot match on IP protocol");
0673 return -EOPNOTSUPP;
0674 }
0675
0676 filter->key_type = OCELOT_VCAP_KEY_IPV6;
0677 filter->key.ipv6.proto.value[0] =
0678 match.key->ip_proto;
0679 filter->key.ipv6.proto.mask[0] =
0680 match.mask->ip_proto;
0681 match_protocol = false;
0682 }
0683 }
0684
0685 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
0686 proto == ETH_P_IP) {
0687 struct flow_match_ipv4_addrs match;
0688 u8 *tmp;
0689
0690 if (filter->block_id == VCAP_ES0) {
0691 NL_SET_ERR_MSG_MOD(extack,
0692 "VCAP ES0 cannot match on IP address");
0693 return -EOPNOTSUPP;
0694 }
0695
0696 flow_rule_match_ipv4_addrs(rule, &match);
0697
0698 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
0699 NL_SET_ERR_MSG_MOD(extack,
0700 "Key type S1_NORMAL cannot match on destination IP");
0701 return -EOPNOTSUPP;
0702 }
0703
0704 tmp = &filter->key.ipv4.sip.value.addr[0];
0705 memcpy(tmp, &match.key->src, 4);
0706
0707 tmp = &filter->key.ipv4.sip.mask.addr[0];
0708 memcpy(tmp, &match.mask->src, 4);
0709
0710 tmp = &filter->key.ipv4.dip.value.addr[0];
0711 memcpy(tmp, &match.key->dst, 4);
0712
0713 tmp = &filter->key.ipv4.dip.mask.addr[0];
0714 memcpy(tmp, &match.mask->dst, 4);
0715 match_protocol = false;
0716 }
0717
0718 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
0719 proto == ETH_P_IPV6) {
0720 return -EOPNOTSUPP;
0721 }
0722
0723 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
0724 struct flow_match_ports match;
0725
0726 if (filter->block_id == VCAP_ES0) {
0727 NL_SET_ERR_MSG_MOD(extack,
0728 "VCAP ES0 cannot match on L4 ports");
0729 return -EOPNOTSUPP;
0730 }
0731
0732 flow_rule_match_ports(rule, &match);
0733 filter->key.ipv4.sport.value = ntohs(match.key->src);
0734 filter->key.ipv4.sport.mask = ntohs(match.mask->src);
0735 filter->key.ipv4.dport.value = ntohs(match.key->dst);
0736 filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
0737 match_protocol = false;
0738 }
0739
0740 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
0741 struct flow_match_vlan match;
0742
0743 flow_rule_match_vlan(rule, &match);
0744 filter->key_type = OCELOT_VCAP_KEY_ANY;
0745 filter->vlan.vid.value = match.key->vlan_id;
0746 filter->vlan.vid.mask = match.mask->vlan_id;
0747 filter->vlan.pcp.value[0] = match.key->vlan_priority;
0748 filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
0749 match_protocol = false;
0750 }
0751
0752 finished_key_parsing:
0753 if (match_protocol && proto != ETH_P_ALL) {
0754 if (filter->block_id == VCAP_ES0) {
0755 NL_SET_ERR_MSG_MOD(extack,
0756 "VCAP ES0 cannot match on L2 proto");
0757 return -EOPNOTSUPP;
0758 }
0759
0760
0761 if (proto < ETH_P_802_3_MIN)
0762 return -EOPNOTSUPP;
0763 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
0764 *(__be16 *)filter->key.etype.etype.value = htons(proto);
0765 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
0766 }
0767
0768
0769 return 0;
0770 }
0771
0772 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
0773 struct flow_cls_offload *f,
0774 struct ocelot_vcap_filter *filter)
0775 {
0776 int ret;
0777
0778 filter->prio = f->common.prio;
0779 filter->id.cookie = f->cookie;
0780 filter->id.tc_offload = true;
0781
0782 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
0783 if (ret)
0784 return ret;
0785
0786
0787 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
0788 return 0;
0789
0790 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
0791 }
0792
0793 static struct ocelot_vcap_filter
0794 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
0795 struct flow_cls_offload *f)
0796 {
0797 struct ocelot_vcap_filter *filter;
0798
0799 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
0800 if (!filter)
0801 return NULL;
0802
0803 if (ingress) {
0804 filter->ingress_port_mask = BIT(port);
0805 } else {
0806 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
0807 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
0808
0809 filter->egress_port.value = port;
0810 filter->egress_port.mask = GENMASK(key_length - 1, 0);
0811 }
0812
0813 return filter;
0814 }
0815
0816 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
0817 struct ocelot_vcap_filter *filter)
0818 {
0819 list_add(&filter->list, &ocelot->dummy_rules);
0820
0821 return 0;
0822 }
0823
0824 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
0825 struct ocelot_vcap_filter *filter)
0826 {
0827 list_del(&filter->list);
0828 kfree(filter);
0829
0830 return 0;
0831 }
0832
0833
0834
0835
0836
0837
0838 static int
0839 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
0840 struct netlink_ext_ack *extack)
0841 {
0842 if (filter->block_id != VCAP_ES0 ||
0843 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
0844 return 0;
0845
0846 if (filter->vlan.vid.mask != VLAN_VID_MASK) {
0847 NL_SET_ERR_MSG_MOD(extack,
0848 "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
0849 return -EOPNOTSUPP;
0850 }
0851
0852 filter->action.vid_a_val -= filter->vlan.vid.value;
0853 filter->action.vid_a_val &= VLAN_VID_MASK;
0854
0855 return 0;
0856 }
0857
0858 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
0859 struct flow_cls_offload *f, bool ingress)
0860 {
0861 struct netlink_ext_ack *extack = f->common.extack;
0862 struct ocelot_vcap_filter *filter;
0863 int chain = f->common.chain_index;
0864 int block_id, ret;
0865
0866 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
0867 NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
0868 return -EOPNOTSUPP;
0869 }
0870
0871 block_id = ocelot_chain_to_block(chain, ingress);
0872 if (block_id < 0) {
0873 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
0874 return -EOPNOTSUPP;
0875 }
0876
0877 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
0878 f->cookie, true);
0879 if (filter) {
0880
0881 if (!ingress) {
0882 NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
0883 return -EOPNOTSUPP;
0884 }
0885
0886 filter->ingress_port_mask |= BIT(port);
0887
0888 return ocelot_vcap_filter_replace(ocelot, filter);
0889 }
0890
0891
0892 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
0893 if (!filter)
0894 return -ENOMEM;
0895
0896 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
0897 if (ret) {
0898 kfree(filter);
0899 return ret;
0900 }
0901
0902 ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
0903 if (ret) {
0904 kfree(filter);
0905 return ret;
0906 }
0907
0908
0909
0910
0911 if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
0912 return ocelot_vcap_dummy_filter_add(ocelot, filter);
0913
0914 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
0915 kfree(filter);
0916 if (ocelot->ops->psfp_filter_add)
0917 return ocelot->ops->psfp_filter_add(ocelot, port, f);
0918
0919 NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
0920 return -EOPNOTSUPP;
0921 }
0922
0923 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
0924 }
0925 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
0926
0927 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
0928 struct flow_cls_offload *f, bool ingress)
0929 {
0930 struct ocelot_vcap_filter *filter;
0931 struct ocelot_vcap_block *block;
0932 int block_id;
0933
0934 block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
0935 if (block_id < 0)
0936 return 0;
0937
0938 if (block_id == PSFP_BLOCK_ID) {
0939 if (ocelot->ops->psfp_filter_del)
0940 return ocelot->ops->psfp_filter_del(ocelot, f);
0941
0942 return -EOPNOTSUPP;
0943 }
0944
0945 block = &ocelot->block[block_id];
0946
0947 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
0948 if (!filter)
0949 return 0;
0950
0951 if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
0952 return ocelot_vcap_dummy_filter_del(ocelot, filter);
0953
0954 if (ingress) {
0955 filter->ingress_port_mask &= ~BIT(port);
0956 if (filter->ingress_port_mask)
0957 return ocelot_vcap_filter_replace(ocelot, filter);
0958 }
0959
0960 return ocelot_vcap_filter_del(ocelot, filter);
0961 }
0962 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
0963
0964 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
0965 struct flow_cls_offload *f, bool ingress)
0966 {
0967 struct ocelot_vcap_filter *filter;
0968 struct ocelot_vcap_block *block;
0969 struct flow_stats stats = {0};
0970 int block_id, ret;
0971
0972 block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
0973 if (block_id < 0)
0974 return 0;
0975
0976 if (block_id == PSFP_BLOCK_ID) {
0977 if (ocelot->ops->psfp_stats_get) {
0978 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
0979 if (ret)
0980 return ret;
0981
0982 goto stats_update;
0983 }
0984
0985 return -EOPNOTSUPP;
0986 }
0987
0988 block = &ocelot->block[block_id];
0989
0990 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
0991 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
0992 return 0;
0993
0994 ret = ocelot_vcap_filter_stats_update(ocelot, filter);
0995 if (ret)
0996 return ret;
0997
0998 stats.pkts = filter->stats.pkts;
0999
1000 stats_update:
1001 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
1002 FLOW_ACTION_HW_STATS_IMMEDIATE);
1003 return 0;
1004 }
1005 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);