0001
0002
0003
0004 #include "prestera.h"
0005 #include "prestera_acl.h"
0006 #include "prestera_flow.h"
0007 #include "prestera_flower.h"
0008
0009 struct prestera_flower_template {
0010 struct prestera_acl_ruleset *ruleset;
0011 struct list_head list;
0012 u32 chain_index;
0013 };
0014
0015 static void
0016 prestera_flower_template_free(struct prestera_flower_template *template)
0017 {
0018 prestera_acl_ruleset_put(template->ruleset);
0019 list_del(&template->list);
0020 kfree(template);
0021 }
0022
0023 void prestera_flower_template_cleanup(struct prestera_flow_block *block)
0024 {
0025 struct prestera_flower_template *template, *tmp;
0026
0027
0028 list_for_each_entry_safe(template, tmp, &block->template_list, list)
0029 prestera_flower_template_free(template);
0030 }
0031
0032 static int
0033 prestera_flower_parse_goto_action(struct prestera_flow_block *block,
0034 struct prestera_acl_rule *rule,
0035 u32 chain_index,
0036 const struct flow_action_entry *act)
0037 {
0038 struct prestera_acl_ruleset *ruleset;
0039
0040 if (act->chain_index <= chain_index)
0041
0042 return -EINVAL;
0043
0044 if (rule->re_arg.jump.valid)
0045 return -EEXIST;
0046
0047 ruleset = prestera_acl_ruleset_get(block->sw->acl, block,
0048 act->chain_index);
0049 if (IS_ERR(ruleset))
0050 return PTR_ERR(ruleset);
0051
0052 rule->re_arg.jump.valid = 1;
0053 rule->re_arg.jump.i.index = prestera_acl_ruleset_index_get(ruleset);
0054
0055 rule->jump_ruleset = ruleset;
0056
0057 return 0;
0058 }
0059
0060 static int prestera_flower_parse_actions(struct prestera_flow_block *block,
0061 struct prestera_acl_rule *rule,
0062 struct flow_action *flow_action,
0063 u32 chain_index,
0064 struct netlink_ext_ack *extack)
0065 {
0066 const struct flow_action_entry *act;
0067 int err, i;
0068
0069
0070 if (!flow_action_has_entries(flow_action))
0071 return 0;
0072
0073 if (!flow_action_mixed_hw_stats_check(flow_action, extack))
0074 return -EOPNOTSUPP;
0075
0076 act = flow_action_first_entry_get(flow_action);
0077 if (act->hw_stats & FLOW_ACTION_HW_STATS_DISABLED) {
0078
0079 } else if (act->hw_stats & FLOW_ACTION_HW_STATS_DELAYED) {
0080
0081 rule->re_arg.count.valid = true;
0082 err = prestera_acl_chain_to_client(chain_index, block->ingress,
0083 &rule->re_arg.count.client);
0084 if (err)
0085 return err;
0086 } else {
0087 NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type");
0088 return -EOPNOTSUPP;
0089 }
0090
0091 flow_action_for_each(i, act, flow_action) {
0092 switch (act->id) {
0093 case FLOW_ACTION_ACCEPT:
0094 if (rule->re_arg.accept.valid)
0095 return -EEXIST;
0096
0097 rule->re_arg.accept.valid = 1;
0098 break;
0099 case FLOW_ACTION_DROP:
0100 if (rule->re_arg.drop.valid)
0101 return -EEXIST;
0102
0103 rule->re_arg.drop.valid = 1;
0104 break;
0105 case FLOW_ACTION_TRAP:
0106 if (rule->re_arg.trap.valid)
0107 return -EEXIST;
0108
0109 rule->re_arg.trap.valid = 1;
0110 break;
0111 case FLOW_ACTION_POLICE:
0112 if (rule->re_arg.police.valid)
0113 return -EEXIST;
0114
0115 rule->re_arg.police.valid = 1;
0116 rule->re_arg.police.rate =
0117 act->police.rate_bytes_ps;
0118 rule->re_arg.police.burst = act->police.burst;
0119 rule->re_arg.police.ingress = block->ingress;
0120 break;
0121 case FLOW_ACTION_GOTO:
0122 err = prestera_flower_parse_goto_action(block, rule,
0123 chain_index,
0124 act);
0125 if (err)
0126 return err;
0127 break;
0128 default:
0129 NL_SET_ERR_MSG_MOD(extack, "Unsupported action");
0130 pr_err("Unsupported action\n");
0131 return -EOPNOTSUPP;
0132 }
0133 }
0134
0135 return 0;
0136 }
0137
0138 static int prestera_flower_parse_meta(struct prestera_acl_rule *rule,
0139 struct flow_cls_offload *f,
0140 struct prestera_flow_block *block)
0141 {
0142 struct flow_rule *f_rule = flow_cls_offload_flow_rule(f);
0143 struct prestera_acl_match *r_match = &rule->re_key.match;
0144 struct prestera_port *port;
0145 struct net_device *ingress_dev;
0146 struct flow_match_meta match;
0147 __be16 key, mask;
0148
0149 flow_rule_match_meta(f_rule, &match);
0150 if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
0151 NL_SET_ERR_MSG_MOD(f->common.extack,
0152 "Unsupported ingress ifindex mask");
0153 return -EINVAL;
0154 }
0155
0156 ingress_dev = __dev_get_by_index(block->net,
0157 match.key->ingress_ifindex);
0158 if (!ingress_dev) {
0159 NL_SET_ERR_MSG_MOD(f->common.extack,
0160 "Can't find specified ingress port to match on");
0161 return -EINVAL;
0162 }
0163
0164 if (!prestera_netdev_check(ingress_dev)) {
0165 NL_SET_ERR_MSG_MOD(f->common.extack,
0166 "Can't match on switchdev ingress port");
0167 return -EINVAL;
0168 }
0169 port = netdev_priv(ingress_dev);
0170
0171 mask = htons(0x1FFF << 3);
0172 key = htons(port->hw_id << 3);
0173 rule_match_set(r_match->key, SYS_PORT, key);
0174 rule_match_set(r_match->mask, SYS_PORT, mask);
0175
0176 mask = htons(0x3FF);
0177 key = htons(port->dev_id);
0178 rule_match_set(r_match->key, SYS_DEV, key);
0179 rule_match_set(r_match->mask, SYS_DEV, mask);
0180
0181 return 0;
0182 }
0183
0184 static int prestera_flower_parse(struct prestera_flow_block *block,
0185 struct prestera_acl_rule *rule,
0186 struct flow_cls_offload *f)
0187 {
0188 struct flow_rule *f_rule = flow_cls_offload_flow_rule(f);
0189 struct flow_dissector *dissector = f_rule->match.dissector;
0190 struct prestera_acl_match *r_match = &rule->re_key.match;
0191 __be16 n_proto_mask = 0;
0192 __be16 n_proto_key = 0;
0193 u16 addr_type = 0;
0194 u8 ip_proto = 0;
0195 int err;
0196
0197 if (dissector->used_keys &
0198 ~(BIT(FLOW_DISSECTOR_KEY_META) |
0199 BIT(FLOW_DISSECTOR_KEY_CONTROL) |
0200 BIT(FLOW_DISSECTOR_KEY_BASIC) |
0201 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
0202 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
0203 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
0204 BIT(FLOW_DISSECTOR_KEY_ICMP) |
0205 BIT(FLOW_DISSECTOR_KEY_PORTS) |
0206 BIT(FLOW_DISSECTOR_KEY_PORTS_RANGE) |
0207 BIT(FLOW_DISSECTOR_KEY_VLAN))) {
0208 NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported key");
0209 return -EOPNOTSUPP;
0210 }
0211
0212 prestera_acl_rule_priority_set(rule, f->common.prio);
0213
0214 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_META)) {
0215 err = prestera_flower_parse_meta(rule, f, block);
0216 if (err)
0217 return err;
0218 }
0219
0220 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_CONTROL)) {
0221 struct flow_match_control match;
0222
0223 flow_rule_match_control(f_rule, &match);
0224 addr_type = match.key->addr_type;
0225 }
0226
0227 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_BASIC)) {
0228 struct flow_match_basic match;
0229
0230 flow_rule_match_basic(f_rule, &match);
0231 n_proto_key = match.key->n_proto;
0232 n_proto_mask = match.mask->n_proto;
0233
0234 if (ntohs(match.key->n_proto) == ETH_P_ALL) {
0235 n_proto_key = 0;
0236 n_proto_mask = 0;
0237 }
0238
0239 rule_match_set(r_match->key, ETH_TYPE, n_proto_key);
0240 rule_match_set(r_match->mask, ETH_TYPE, n_proto_mask);
0241
0242 rule_match_set(r_match->key, IP_PROTO, match.key->ip_proto);
0243 rule_match_set(r_match->mask, IP_PROTO, match.mask->ip_proto);
0244 ip_proto = match.key->ip_proto;
0245 }
0246
0247 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
0248 struct flow_match_eth_addrs match;
0249
0250 flow_rule_match_eth_addrs(f_rule, &match);
0251
0252
0253 rule_match_set_n(r_match->key,
0254 ETH_DMAC_0, &match.key->dst[0], 4);
0255 rule_match_set_n(r_match->key,
0256 ETH_DMAC_1, &match.key->dst[4], 2);
0257
0258 rule_match_set_n(r_match->mask,
0259 ETH_DMAC_0, &match.mask->dst[0], 4);
0260 rule_match_set_n(r_match->mask,
0261 ETH_DMAC_1, &match.mask->dst[4], 2);
0262
0263
0264 rule_match_set_n(r_match->key,
0265 ETH_SMAC_0, &match.key->src[0], 4);
0266 rule_match_set_n(r_match->key,
0267 ETH_SMAC_1, &match.key->src[4], 2);
0268
0269 rule_match_set_n(r_match->mask,
0270 ETH_SMAC_0, &match.mask->src[0], 4);
0271 rule_match_set_n(r_match->mask,
0272 ETH_SMAC_1, &match.mask->src[4], 2);
0273 }
0274
0275 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
0276 struct flow_match_ipv4_addrs match;
0277
0278 flow_rule_match_ipv4_addrs(f_rule, &match);
0279
0280 rule_match_set(r_match->key, IP_SRC, match.key->src);
0281 rule_match_set(r_match->mask, IP_SRC, match.mask->src);
0282
0283 rule_match_set(r_match->key, IP_DST, match.key->dst);
0284 rule_match_set(r_match->mask, IP_DST, match.mask->dst);
0285 }
0286
0287 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_PORTS)) {
0288 struct flow_match_ports match;
0289
0290 if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
0291 NL_SET_ERR_MSG_MOD
0292 (f->common.extack,
0293 "Only UDP and TCP keys are supported");
0294 return -EINVAL;
0295 }
0296
0297 flow_rule_match_ports(f_rule, &match);
0298
0299 rule_match_set(r_match->key, L4_PORT_SRC, match.key->src);
0300 rule_match_set(r_match->mask, L4_PORT_SRC, match.mask->src);
0301
0302 rule_match_set(r_match->key, L4_PORT_DST, match.key->dst);
0303 rule_match_set(r_match->mask, L4_PORT_DST, match.mask->dst);
0304 }
0305
0306 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_PORTS_RANGE)) {
0307 struct flow_match_ports_range match;
0308 __be32 tp_key, tp_mask;
0309
0310 flow_rule_match_ports_range(f_rule, &match);
0311
0312
0313 tp_key = htonl(ntohs(match.key->tp_min.src) |
0314 (ntohs(match.key->tp_max.src) << 16));
0315 tp_mask = htonl(ntohs(match.mask->tp_min.src) |
0316 (ntohs(match.mask->tp_max.src) << 16));
0317 rule_match_set(r_match->key, L4_PORT_RANGE_SRC, tp_key);
0318 rule_match_set(r_match->mask, L4_PORT_RANGE_SRC, tp_mask);
0319
0320
0321 tp_key = htonl(ntohs(match.key->tp_min.dst) |
0322 (ntohs(match.key->tp_max.dst) << 16));
0323 tp_mask = htonl(ntohs(match.mask->tp_min.dst) |
0324 (ntohs(match.mask->tp_max.dst) << 16));
0325 rule_match_set(r_match->key, L4_PORT_RANGE_DST, tp_key);
0326 rule_match_set(r_match->mask, L4_PORT_RANGE_DST, tp_mask);
0327 }
0328
0329 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_VLAN)) {
0330 struct flow_match_vlan match;
0331
0332 flow_rule_match_vlan(f_rule, &match);
0333
0334 if (match.mask->vlan_id != 0) {
0335 __be16 key = cpu_to_be16(match.key->vlan_id);
0336 __be16 mask = cpu_to_be16(match.mask->vlan_id);
0337
0338 rule_match_set(r_match->key, VLAN_ID, key);
0339 rule_match_set(r_match->mask, VLAN_ID, mask);
0340 }
0341
0342 rule_match_set(r_match->key, VLAN_TPID, match.key->vlan_tpid);
0343 rule_match_set(r_match->mask, VLAN_TPID, match.mask->vlan_tpid);
0344 }
0345
0346 if (flow_rule_match_key(f_rule, FLOW_DISSECTOR_KEY_ICMP)) {
0347 struct flow_match_icmp match;
0348
0349 flow_rule_match_icmp(f_rule, &match);
0350
0351 rule_match_set(r_match->key, ICMP_TYPE, match.key->type);
0352 rule_match_set(r_match->mask, ICMP_TYPE, match.mask->type);
0353
0354 rule_match_set(r_match->key, ICMP_CODE, match.key->code);
0355 rule_match_set(r_match->mask, ICMP_CODE, match.mask->code);
0356 }
0357
0358 return prestera_flower_parse_actions(block, rule, &f->rule->action,
0359 f->common.chain_index,
0360 f->common.extack);
0361 }
0362
0363 int prestera_flower_replace(struct prestera_flow_block *block,
0364 struct flow_cls_offload *f)
0365 {
0366 struct prestera_acl_ruleset *ruleset;
0367 struct prestera_acl *acl = block->sw->acl;
0368 struct prestera_acl_rule *rule;
0369 int err;
0370
0371 ruleset = prestera_acl_ruleset_get(acl, block, f->common.chain_index);
0372 if (IS_ERR(ruleset))
0373 return PTR_ERR(ruleset);
0374
0375
0376 rule = prestera_acl_rule_create(ruleset, f->cookie,
0377 f->common.chain_index);
0378 if (IS_ERR(rule)) {
0379 err = PTR_ERR(rule);
0380 goto err_rule_create;
0381 }
0382
0383 err = prestera_flower_parse(block, rule, f);
0384 if (err)
0385 goto err_rule_add;
0386
0387 if (!prestera_acl_ruleset_is_offload(ruleset)) {
0388 err = prestera_acl_ruleset_offload(ruleset);
0389 if (err)
0390 goto err_ruleset_offload;
0391 }
0392
0393 err = prestera_acl_rule_add(block->sw, rule);
0394 if (err)
0395 goto err_rule_add;
0396
0397 prestera_acl_ruleset_put(ruleset);
0398 return 0;
0399
0400 err_ruleset_offload:
0401 err_rule_add:
0402 prestera_acl_rule_destroy(rule);
0403 err_rule_create:
0404 prestera_acl_ruleset_put(ruleset);
0405 return err;
0406 }
0407
0408 void prestera_flower_destroy(struct prestera_flow_block *block,
0409 struct flow_cls_offload *f)
0410 {
0411 struct prestera_acl_ruleset *ruleset;
0412 struct prestera_acl_rule *rule;
0413
0414 ruleset = prestera_acl_ruleset_lookup(block->sw->acl, block,
0415 f->common.chain_index);
0416 if (IS_ERR(ruleset))
0417 return;
0418
0419 rule = prestera_acl_rule_lookup(ruleset, f->cookie);
0420 if (rule) {
0421 prestera_acl_rule_del(block->sw, rule);
0422 prestera_acl_rule_destroy(rule);
0423 }
0424 prestera_acl_ruleset_put(ruleset);
0425 }
0426
0427 int prestera_flower_tmplt_create(struct prestera_flow_block *block,
0428 struct flow_cls_offload *f)
0429 {
0430 struct prestera_flower_template *template;
0431 struct prestera_acl_ruleset *ruleset;
0432 struct prestera_acl_rule rule;
0433 int err;
0434
0435 memset(&rule, 0, sizeof(rule));
0436 err = prestera_flower_parse(block, &rule, f);
0437 if (err)
0438 return err;
0439
0440 template = kmalloc(sizeof(*template), GFP_KERNEL);
0441 if (!template) {
0442 err = -ENOMEM;
0443 goto err_malloc;
0444 }
0445
0446 prestera_acl_rule_keymask_pcl_id_set(&rule, 0);
0447 ruleset = prestera_acl_ruleset_get(block->sw->acl, block,
0448 f->common.chain_index);
0449 if (IS_ERR_OR_NULL(ruleset)) {
0450 err = -EINVAL;
0451 goto err_ruleset_get;
0452 }
0453
0454
0455 prestera_acl_ruleset_keymask_set(ruleset, rule.re_key.match.mask);
0456
0457
0458
0459
0460
0461
0462
0463 prestera_acl_ruleset_offload(ruleset);
0464
0465
0466 template->ruleset = ruleset;
0467 template->chain_index = f->common.chain_index;
0468 list_add_rcu(&template->list, &block->template_list);
0469 return 0;
0470
0471 err_ruleset_get:
0472 kfree(template);
0473 err_malloc:
0474 NL_SET_ERR_MSG_MOD(f->common.extack, "Create chain template failed");
0475 return err;
0476 }
0477
0478 void prestera_flower_tmplt_destroy(struct prestera_flow_block *block,
0479 struct flow_cls_offload *f)
0480 {
0481 struct prestera_flower_template *template, *tmp;
0482
0483 list_for_each_entry_safe(template, tmp, &block->template_list, list)
0484 if (template->chain_index == f->common.chain_index) {
0485
0486 prestera_flower_template_free(template);
0487 return;
0488 }
0489 }
0490
0491 int prestera_flower_stats(struct prestera_flow_block *block,
0492 struct flow_cls_offload *f)
0493 {
0494 struct prestera_acl_ruleset *ruleset;
0495 struct prestera_acl_rule *rule;
0496 u64 packets;
0497 u64 lastuse;
0498 u64 bytes;
0499 int err;
0500
0501 ruleset = prestera_acl_ruleset_lookup(block->sw->acl, block,
0502 f->common.chain_index);
0503 if (IS_ERR(ruleset))
0504 return PTR_ERR(ruleset);
0505
0506 rule = prestera_acl_rule_lookup(ruleset, f->cookie);
0507 if (!rule) {
0508 err = -EINVAL;
0509 goto err_rule_get_stats;
0510 }
0511
0512 err = prestera_acl_rule_get_stats(block->sw->acl, rule, &packets,
0513 &bytes, &lastuse);
0514 if (err)
0515 goto err_rule_get_stats;
0516
0517 flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
0518 FLOW_ACTION_HW_STATS_DELAYED);
0519
0520 err_rule_get_stats:
0521 prestera_acl_ruleset_put(ruleset);
0522 return err;
0523 }