1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * net/sched/ife.c Inter-FE action based on ForCES WG InterFE LFB 4 * 5 * Refer to: 6 * draft-ietf-forces-interfelfb-03 7 * and 8 * netdev01 paper: 9 * "Distributing Linux Traffic Control Classifier-Action 10 * Subsystem" 11 * Authors: Jamal Hadi Salim and Damascene M. Joachimpillai 12 * 13 * copyright Jamal Hadi Salim (2015) 14 */ 15 16 #include <linux/types.h> 17 #include <linux/kernel.h> 18 #include <linux/string.h> 19 #include <linux/errno.h> 20 #include <linux/skbuff.h> 21 #include <linux/rtnetlink.h> 22 #include <linux/module.h> 23 #include <linux/init.h> 24 #include <net/net_namespace.h> 25 #include <net/netlink.h> 26 #include <net/pkt_sched.h> 27 #include <net/pkt_cls.h> 28 #include <uapi/linux/tc_act/tc_ife.h> 29 #include <net/tc_act/tc_ife.h> 30 #include <linux/etherdevice.h> 31 #include <linux/if_arp.h> 32 #include <net/ife.h> 33 #include <net/tc_wrapper.h> 34 35 static int max_metacnt = IFE_META_MAX + 1; 36 static struct tc_action_ops act_ife_ops; 37 38 static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { 39 [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, 40 [TCA_IFE_DMAC] = { .len = ETH_ALEN}, 41 [TCA_IFE_SMAC] = { .len = ETH_ALEN}, 42 [TCA_IFE_TYPE] = { .type = NLA_U16}, 43 }; 44 45 int ife_encode_meta_u16(u16 metaval, void *skbdata, struct tcf_meta_info *mi) 46 { 47 u16 edata = 0; 48 49 if (mi->metaval) 50 edata = *(u16 *)mi->metaval; 51 else if (metaval) 52 edata = metaval; 53 54 if (!edata) /* will not encode */ 55 return 0; 56 57 edata = htons(edata); 58 return ife_tlv_meta_encode(skbdata, mi->metaid, 2, &edata); 59 } 60 EXPORT_SYMBOL_GPL(ife_encode_meta_u16); 61 62 int ife_get_meta_u32(struct sk_buff *skb, struct tcf_meta_info *mi) 63 { 64 if (mi->metaval) 65 return nla_put_u32(skb, mi->metaid, *(u32 *)mi->metaval); 66 else 67 return nla_put(skb, mi->metaid, 0, NULL); 68 } 69 EXPORT_SYMBOL_GPL(ife_get_meta_u32); 70 71 int ife_check_meta_u32(u32 metaval, struct tcf_meta_info *mi) 72 { 73 if (metaval || mi->metaval) 74 return 8; /* T+L+V == 2+2+4 */ 75 76 return 0; 77 } 78 EXPORT_SYMBOL_GPL(ife_check_meta_u32); 79 80 int ife_check_meta_u16(u16 metaval, struct tcf_meta_info *mi) 81 { 82 if (metaval || mi->metaval) 83 return 8; /* T+L+(V) == 2+2+(2+2bytepad) */ 84 85 return 0; 86 } 87 EXPORT_SYMBOL_GPL(ife_check_meta_u16); 88 89 int ife_encode_meta_u32(u32 metaval, void *skbdata, struct tcf_meta_info *mi) 90 { 91 u32 edata = metaval; 92 93 if (mi->metaval) 94 edata = *(u32 *)mi->metaval; 95 else if (metaval) 96 edata = metaval; 97 98 if (!edata) /* will not encode */ 99 return 0; 100 101 edata = htonl(edata); 102 return ife_tlv_meta_encode(skbdata, mi->metaid, 4, &edata); 103 } 104 EXPORT_SYMBOL_GPL(ife_encode_meta_u32); 105 106 int ife_get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi) 107 { 108 if (mi->metaval) 109 return nla_put_u16(skb, mi->metaid, *(u16 *)mi->metaval); 110 else 111 return nla_put(skb, mi->metaid, 0, NULL); 112 } 113 EXPORT_SYMBOL_GPL(ife_get_meta_u16); 114 115 int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp) 116 { 117 mi->metaval = kmemdup(metaval, sizeof(u32), gfp); 118 if (!mi->metaval) 119 return -ENOMEM; 120 121 return 0; 122 } 123 EXPORT_SYMBOL_GPL(ife_alloc_meta_u32); 124 125 int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp) 126 { 127 mi->metaval = kmemdup(metaval, sizeof(u16), gfp); 128 if (!mi->metaval) 129 return -ENOMEM; 130 131 return 0; 132 } 133 EXPORT_SYMBOL_GPL(ife_alloc_meta_u16); 134 135 void ife_release_meta_gen(struct tcf_meta_info *mi) 136 { 137 kfree(mi->metaval); 138 } 139 EXPORT_SYMBOL_GPL(ife_release_meta_gen); 140 141 int ife_validate_meta_u32(void *val, int len) 142 { 143 if (len == sizeof(u32)) 144 return 0; 145 146 return -EINVAL; 147 } 148 EXPORT_SYMBOL_GPL(ife_validate_meta_u32); 149 150 int ife_validate_meta_u16(void *val, int len) 151 { 152 /* length will not include padding */ 153 if (len == sizeof(u16)) 154 return 0; 155 156 return -EINVAL; 157 } 158 EXPORT_SYMBOL_GPL(ife_validate_meta_u16); 159 160 static LIST_HEAD(ifeoplist); 161 static DEFINE_RWLOCK(ife_mod_lock); 162 163 static struct tcf_meta_ops *find_ife_oplist(u16 metaid) 164 { 165 struct tcf_meta_ops *o; 166 167 read_lock(&ife_mod_lock); 168 list_for_each_entry(o, &ifeoplist, list) { 169 if (o->metaid == metaid) { 170 if (!try_module_get(o->owner)) 171 o = NULL; 172 read_unlock(&ife_mod_lock); 173 return o; 174 } 175 } 176 read_unlock(&ife_mod_lock); 177 178 return NULL; 179 } 180 181 int register_ife_op(struct tcf_meta_ops *mops) 182 { 183 struct tcf_meta_ops *m; 184 185 if (!mops->metaid || !mops->metatype || !mops->name || 186 !mops->check_presence || !mops->encode || !mops->decode || 187 !mops->get || !mops->alloc) 188 return -EINVAL; 189 190 write_lock(&ife_mod_lock); 191 192 list_for_each_entry(m, &ifeoplist, list) { 193 if (m->metaid == mops->metaid || 194 (strcmp(mops->name, m->name) == 0)) { 195 write_unlock(&ife_mod_lock); 196 return -EEXIST; 197 } 198 } 199 200 if (!mops->release) 201 mops->release = ife_release_meta_gen; 202 203 list_add_tail(&mops->list, &ifeoplist); 204 write_unlock(&ife_mod_lock); 205 return 0; 206 } 207 EXPORT_SYMBOL_GPL(unregister_ife_op); 208 209 int unregister_ife_op(struct tcf_meta_ops *mops) 210 { 211 struct tcf_meta_ops *m; 212 int err = -ENOENT; 213 214 write_lock(&ife_mod_lock); 215 list_for_each_entry(m, &ifeoplist, list) { 216 if (m->metaid == mops->metaid) { 217 list_del(&mops->list); 218 err = 0; 219 break; 220 } 221 } 222 write_unlock(&ife_mod_lock); 223 224 return err; 225 } 226 EXPORT_SYMBOL_GPL(register_ife_op); 227 228 static int ife_validate_metatype(struct tcf_meta_ops *ops, void *val, int len) 229 { 230 int ret = 0; 231 /* XXX: unfortunately cant use nla_policy at this point 232 * because a length of 0 is valid in the case of 233 * "allow". "use" semantics do enforce for proper 234 * length and i couldve use nla_policy but it makes it hard 235 * to use it just for that.. 236 */ 237 if (ops->validate) 238 return ops->validate(val, len); 239 240 if (ops->metatype == NLA_U32) 241 ret = ife_validate_meta_u32(val, len); 242 else if (ops->metatype == NLA_U16) 243 ret = ife_validate_meta_u16(val, len); 244 245 return ret; 246 } 247 248 #ifdef CONFIG_MODULES 249 static const char *ife_meta_id2name(u32 metaid) 250 { 251 switch (metaid) { 252 case IFE_META_SKBMARK: 253 return "skbmark"; 254 case IFE_META_PRIO: 255 return "skbprio"; 256 case IFE_META_TCINDEX: 257 return "tcindex"; 258 default: 259 return "unknown"; 260 } 261 } 262 #endif 263 264 /* called when adding new meta information 265 */ 266 static int load_metaops_and_vet(u32 metaid, void *val, int len, bool rtnl_held) 267 { 268 struct tcf_meta_ops *ops = find_ife_oplist(metaid); 269 int ret = 0; 270 271 if (!ops) { 272 ret = -ENOENT; 273 #ifdef CONFIG_MODULES 274 if (rtnl_held) 275 rtnl_unlock(); 276 request_module("ife-meta-%s", ife_meta_id2name(metaid)); 277 if (rtnl_held) 278 rtnl_lock(); 279 ops = find_ife_oplist(metaid); 280 #endif 281 } 282 283 if (ops) { 284 ret = 0; 285 if (len) 286 ret = ife_validate_metatype(ops, val, len); 287 288 module_put(ops->owner); 289 } 290 291 return ret; 292 } 293 294 /* called when adding new meta information 295 */ 296 static int __add_metainfo(const struct tcf_meta_ops *ops, 297 struct tcf_ife_params *p, u32 metaid, void *metaval, 298 int len, bool atomic) 299 { 300 struct tcf_meta_info *mi = NULL; 301 int ret = 0; 302 303 mi = kzalloc_obj(*mi, atomic ? GFP_ATOMIC : GFP_KERNEL); 304 if (!mi) 305 return -ENOMEM; 306 307 mi->metaid = metaid; 308 mi->ops = ops; 309 if (len > 0) { 310 ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL); 311 if (ret != 0) { 312 kfree(mi); 313 return ret; 314 } 315 } 316 317 list_add_tail(&mi->metalist, &p->metalist); 318 319 return ret; 320 } 321 322 static int add_metainfo_and_get_ops(const struct tcf_meta_ops *ops, 323 struct tcf_ife_params *p, u32 metaid) 324 { 325 int ret; 326 327 if (!try_module_get(ops->owner)) 328 return -ENOENT; 329 ret = __add_metainfo(ops, p, metaid, NULL, 0, true); 330 if (ret) 331 module_put(ops->owner); 332 return ret; 333 } 334 335 static int add_metainfo(struct tcf_ife_params *p, u32 metaid, void *metaval, 336 int len) 337 { 338 const struct tcf_meta_ops *ops = find_ife_oplist(metaid); 339 int ret; 340 341 if (!ops) 342 return -ENOENT; 343 ret = __add_metainfo(ops, p, metaid, metaval, len, false); 344 if (ret) 345 /*put back what find_ife_oplist took */ 346 module_put(ops->owner); 347 return ret; 348 } 349 350 static int use_all_metadata(struct tcf_ife_params *p) 351 { 352 struct tcf_meta_ops *o; 353 int rc = 0; 354 int installed = 0; 355 356 read_lock(&ife_mod_lock); 357 list_for_each_entry(o, &ifeoplist, list) { 358 rc = add_metainfo_and_get_ops(o, p, o->metaid); 359 if (rc == 0) 360 installed += 1; 361 } 362 read_unlock(&ife_mod_lock); 363 364 if (installed) 365 return 0; 366 else 367 return -EINVAL; 368 } 369 370 static int dump_metalist(struct sk_buff *skb, struct tcf_ife_params *p) 371 { 372 struct tcf_meta_info *e; 373 struct nlattr *nest; 374 unsigned char *b = skb_tail_pointer(skb); 375 int total_encoded = 0; 376 377 /*can only happen on decode */ 378 if (list_empty(&p->metalist)) 379 return 0; 380 381 nest = nla_nest_start_noflag(skb, TCA_IFE_METALST); 382 if (!nest) 383 goto out_nlmsg_trim; 384 385 list_for_each_entry(e, &p->metalist, metalist) { 386 if (!e->ops->get(skb, e)) 387 total_encoded += 1; 388 } 389 390 if (!total_encoded) 391 goto out_nlmsg_trim; 392 393 nla_nest_end(skb, nest); 394 395 return 0; 396 397 out_nlmsg_trim: 398 nlmsg_trim(skb, b); 399 return -1; 400 } 401 402 static void __tcf_ife_cleanup(struct tcf_ife_params *p) 403 { 404 struct tcf_meta_info *e, *n; 405 406 list_for_each_entry_safe(e, n, &p->metalist, metalist) { 407 list_del(&e->metalist); 408 if (e->metaval) { 409 if (e->ops->release) 410 e->ops->release(e); 411 else 412 kfree(e->metaval); 413 } 414 module_put(e->ops->owner); 415 kfree(e); 416 } 417 } 418 419 static void tcf_ife_cleanup_params(struct rcu_head *head) 420 { 421 struct tcf_ife_params *p = container_of(head, struct tcf_ife_params, 422 rcu); 423 424 __tcf_ife_cleanup(p); 425 kfree(p); 426 } 427 428 static void tcf_ife_cleanup(struct tc_action *a) 429 { 430 struct tcf_ife_info *ife = to_ife(a); 431 struct tcf_ife_params *p; 432 433 p = rcu_dereference_protected(ife->params, 1); 434 if (p) 435 call_rcu(&p->rcu, tcf_ife_cleanup_params); 436 } 437 438 static int load_metalist(struct nlattr **tb, bool rtnl_held) 439 { 440 int i; 441 442 for (i = 1; i < max_metacnt; i++) { 443 if (tb[i]) { 444 void *val = nla_data(tb[i]); 445 int len = nla_len(tb[i]); 446 int rc; 447 448 rc = load_metaops_and_vet(i, val, len, rtnl_held); 449 if (rc != 0) 450 return rc; 451 } 452 } 453 454 return 0; 455 } 456 457 static int populate_metalist(struct tcf_ife_params *p, struct nlattr **tb) 458 { 459 int len = 0; 460 int rc = 0; 461 int i = 0; 462 void *val; 463 464 for (i = 1; i < max_metacnt; i++) { 465 if (tb[i]) { 466 val = nla_data(tb[i]); 467 len = nla_len(tb[i]); 468 469 rc = add_metainfo(p, i, val, len); 470 if (rc) 471 return rc; 472 } 473 } 474 475 return rc; 476 } 477 478 static int tcf_ife_init(struct net *net, struct nlattr *nla, 479 struct nlattr *est, struct tc_action **a, 480 struct tcf_proto *tp, u32 flags, 481 struct netlink_ext_ack *extack) 482 { 483 struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); 484 bool bind = flags & TCA_ACT_FLAGS_BIND; 485 struct nlattr *tb[TCA_IFE_MAX + 1]; 486 struct nlattr *tb2[IFE_META_MAX + 1]; 487 struct tcf_chain *goto_ch = NULL; 488 struct tcf_ife_params *p; 489 struct tcf_ife_info *ife; 490 u16 ife_type = ETH_P_IFE; 491 struct tc_ife *parm; 492 u8 *daddr = NULL; 493 u8 *saddr = NULL; 494 bool exists = false; 495 int ret = 0; 496 u32 index; 497 int err; 498 499 if (!nla) { 500 NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed"); 501 return -EINVAL; 502 } 503 504 err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy, 505 NULL); 506 if (err < 0) 507 return err; 508 509 if (!tb[TCA_IFE_PARMS]) 510 return -EINVAL; 511 512 parm = nla_data(tb[TCA_IFE_PARMS]); 513 514 /* IFE_DECODE is 0 and indicates the opposite of IFE_ENCODE because 515 * they cannot run as the same time. Check on all other values which 516 * are not supported right now. 517 */ 518 if (parm->flags & ~IFE_ENCODE) 519 return -EINVAL; 520 521 p = kzalloc_obj(*p); 522 if (!p) 523 return -ENOMEM; 524 INIT_LIST_HEAD(&p->metalist); 525 526 if (tb[TCA_IFE_METALST]) { 527 err = nla_parse_nested_deprecated(tb2, IFE_META_MAX, 528 tb[TCA_IFE_METALST], NULL, 529 NULL); 530 if (err) { 531 kfree(p); 532 return err; 533 } 534 err = load_metalist(tb2, !(flags & TCA_ACT_FLAGS_NO_RTNL)); 535 if (err) { 536 kfree(p); 537 return err; 538 } 539 } 540 541 index = parm->index; 542 err = tcf_idr_check_alloc(tn, &index, a, bind); 543 if (err < 0) { 544 kfree(p); 545 return err; 546 } 547 exists = err; 548 if (exists && bind) { 549 kfree(p); 550 return ACT_P_BOUND; 551 } 552 553 if (!exists) { 554 ret = tcf_idr_create(tn, index, est, a, &act_ife_ops, 555 bind, true, flags); 556 if (ret) { 557 tcf_idr_cleanup(tn, index); 558 kfree(p); 559 return ret; 560 } 561 ret = ACT_P_CREATED; 562 } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) { 563 tcf_idr_release(*a, bind); 564 kfree(p); 565 return -EEXIST; 566 } 567 568 ife = to_ife(*a); 569 570 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); 571 if (err < 0) 572 goto release_idr; 573 574 p->flags = parm->flags; 575 576 if (parm->flags & IFE_ENCODE) { 577 if (tb[TCA_IFE_TYPE]) 578 ife_type = nla_get_u16(tb[TCA_IFE_TYPE]); 579 if (tb[TCA_IFE_DMAC]) 580 daddr = nla_data(tb[TCA_IFE_DMAC]); 581 if (tb[TCA_IFE_SMAC]) 582 saddr = nla_data(tb[TCA_IFE_SMAC]); 583 } 584 585 if (parm->flags & IFE_ENCODE) { 586 if (daddr) 587 ether_addr_copy(p->eth_dst, daddr); 588 else 589 eth_zero_addr(p->eth_dst); 590 591 if (saddr) 592 ether_addr_copy(p->eth_src, saddr); 593 else 594 eth_zero_addr(p->eth_src); 595 596 p->eth_type = ife_type; 597 } 598 599 if (tb[TCA_IFE_METALST]) { 600 err = populate_metalist(p, tb2); 601 if (err) 602 goto metadata_parse_err; 603 } else { 604 /* if no passed metadata allow list or passed allow-all 605 * then here we process by adding as many supported metadatum 606 * as we can. You better have at least one else we are 607 * going to bail out 608 */ 609 err = use_all_metadata(p); 610 if (err) 611 goto metadata_parse_err; 612 } 613 614 if (exists) 615 spin_lock_bh(&ife->tcf_lock); 616 /* protected by tcf_lock when modifying existing action */ 617 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); 618 p = rcu_replace_pointer(ife->params, p, 1); 619 620 if (exists) 621 spin_unlock_bh(&ife->tcf_lock); 622 if (goto_ch) 623 tcf_chain_put_by_act(goto_ch); 624 if (p) 625 call_rcu(&p->rcu, tcf_ife_cleanup_params); 626 627 return ret; 628 metadata_parse_err: 629 if (goto_ch) 630 tcf_chain_put_by_act(goto_ch); 631 release_idr: 632 __tcf_ife_cleanup(p); 633 kfree(p); 634 tcf_idr_release(*a, bind); 635 return err; 636 } 637 638 static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, 639 int ref) 640 { 641 unsigned char *b = skb_tail_pointer(skb); 642 struct tcf_ife_info *ife = to_ife(a); 643 struct tcf_ife_params *p; 644 struct tc_ife opt; 645 struct tcf_t t; 646 647 memset(&opt, 0, sizeof(opt)); 648 649 opt.index = ife->tcf_index; 650 opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref; 651 opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind; 652 653 spin_lock_bh(&ife->tcf_lock); 654 opt.action = ife->tcf_action; 655 p = rcu_dereference_protected(ife->params, 656 lockdep_is_held(&ife->tcf_lock)); 657 opt.flags = p->flags; 658 659 if (nla_put(skb, TCA_IFE_PARMS, sizeof(opt), &opt)) 660 goto nla_put_failure; 661 662 tcf_tm_dump(&t, &ife->tcf_tm); 663 if (nla_put_64bit(skb, TCA_IFE_TM, sizeof(t), &t, TCA_IFE_PAD)) 664 goto nla_put_failure; 665 666 if (!is_zero_ether_addr(p->eth_dst)) { 667 if (nla_put(skb, TCA_IFE_DMAC, ETH_ALEN, p->eth_dst)) 668 goto nla_put_failure; 669 } 670 671 if (!is_zero_ether_addr(p->eth_src)) { 672 if (nla_put(skb, TCA_IFE_SMAC, ETH_ALEN, p->eth_src)) 673 goto nla_put_failure; 674 } 675 676 if (nla_put(skb, TCA_IFE_TYPE, 2, &p->eth_type)) 677 goto nla_put_failure; 678 679 if (dump_metalist(skb, p)) { 680 /*ignore failure to dump metalist */ 681 pr_info("Failed to dump metalist\n"); 682 } 683 684 spin_unlock_bh(&ife->tcf_lock); 685 return skb->len; 686 687 nla_put_failure: 688 spin_unlock_bh(&ife->tcf_lock); 689 nlmsg_trim(skb, b); 690 return -1; 691 } 692 693 static int find_decode_metaid(struct sk_buff *skb, struct tcf_ife_params *p, 694 u16 metaid, u16 mlen, void *mdata) 695 { 696 struct tcf_meta_info *e; 697 698 /* XXX: use hash to speed up */ 699 list_for_each_entry_rcu(e, &p->metalist, metalist) { 700 if (metaid == e->metaid) { 701 if (e->ops) { 702 /* We check for decode presence already */ 703 return e->ops->decode(skb, mdata, mlen); 704 } 705 } 706 } 707 708 return -ENOENT; 709 } 710 711 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, 712 struct tcf_result *res) 713 { 714 struct tcf_ife_info *ife = to_ife(a); 715 int action = ife->tcf_action; 716 struct tcf_ife_params *p; 717 u8 *ifehdr_end; 718 u8 *tlv_data; 719 u16 metalen; 720 721 p = rcu_dereference_bh(ife->params); 722 723 bstats_update(this_cpu_ptr(ife->common.cpu_bstats), skb); 724 tcf_lastuse_update(&ife->tcf_tm); 725 726 if (skb_at_tc_ingress(skb)) 727 skb_push(skb, ETH_HLEN); 728 729 tlv_data = ife_decode(skb, &metalen); 730 if (unlikely(!tlv_data)) { 731 qstats_cpu_drop_inc(ife->common.cpu_qstats); 732 return TC_ACT_SHOT; 733 } 734 735 ifehdr_end = tlv_data + metalen; 736 for (; tlv_data < ifehdr_end; tlv_data = ife_tlv_meta_next(tlv_data)) { 737 u8 *curr_data; 738 u16 mtype; 739 u16 dlen; 740 741 curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, &mtype, 742 &dlen, NULL); 743 if (!curr_data) { 744 qstats_cpu_drop_inc(ife->common.cpu_qstats); 745 return TC_ACT_SHOT; 746 } 747 748 if (find_decode_metaid(skb, p, mtype, dlen, curr_data)) { 749 /* abuse overlimits to count when we receive metadata 750 * but dont have an ops for it 751 */ 752 pr_info_ratelimited("Unknown metaid %d dlen %d\n", 753 mtype, dlen); 754 qstats_cpu_overlimit_inc(ife->common.cpu_qstats); 755 } 756 } 757 758 if (WARN_ON(tlv_data != ifehdr_end)) { 759 qstats_cpu_drop_inc(ife->common.cpu_qstats); 760 return TC_ACT_SHOT; 761 } 762 763 skb->protocol = eth_type_trans(skb, skb->dev); 764 skb_reset_network_header(skb); 765 766 return action; 767 } 768 769 /*XXX: check if we can do this at install time instead of current 770 * send data path 771 **/ 772 static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_params *p) 773 { 774 struct tcf_meta_info *e; 775 int tot_run_sz = 0, run_sz = 0; 776 777 list_for_each_entry_rcu(e, &p->metalist, metalist) { 778 if (e->ops->check_presence) { 779 run_sz = e->ops->check_presence(skb, e); 780 tot_run_sz += run_sz; 781 } 782 } 783 784 return tot_run_sz; 785 } 786 787 static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, 788 struct tcf_result *res, struct tcf_ife_params *p) 789 { 790 struct tcf_ife_info *ife = to_ife(a); 791 int action = ife->tcf_action; 792 struct ethhdr *oethh; /* outer ether header */ 793 struct tcf_meta_info *e; 794 /* 795 OUTERHDR:TOTMETALEN:{TLVHDR:Metadatum:TLVHDR..}:ORIGDATA 796 where ORIGDATA = original ethernet header ... 797 */ 798 u16 metalen = ife_get_sz(skb, p); 799 int hdrm = metalen + ETH_HLEN + IFE_METAHDRLEN; 800 unsigned int skboff = 0; 801 int new_len = skb->len + hdrm; 802 bool exceed_mtu = false; 803 void *ife_meta; 804 int err = 0; 805 806 if (!skb_at_tc_ingress(skb)) { 807 if (new_len > skb->dev->mtu) 808 exceed_mtu = true; 809 } 810 811 bstats_update(this_cpu_ptr(ife->common.cpu_bstats), skb); 812 tcf_lastuse_update(&ife->tcf_tm); 813 814 if (!metalen) { /* no metadata to send */ 815 /* abuse overlimits to count when we allow packet 816 * with no metadata 817 */ 818 qstats_cpu_overlimit_inc(ife->common.cpu_qstats); 819 return action; 820 } 821 /* could be stupid policy setup or mtu config 822 * so lets be conservative.. */ 823 if ((action == TC_ACT_SHOT) || exceed_mtu) { 824 drop: 825 qstats_cpu_drop_inc(ife->common.cpu_qstats); 826 return TC_ACT_SHOT; 827 } 828 829 if (skb_at_tc_ingress(skb)) 830 skb_push(skb, ETH_HLEN); 831 832 ife_meta = ife_encode(skb, metalen); 833 if (!ife_meta) 834 goto drop; 835 836 /* XXX: we dont have a clever way of telling encode to 837 * not repeat some of the computations that are done by 838 * ops->presence_check... 839 */ 840 list_for_each_entry_rcu(e, &p->metalist, metalist) { 841 if (e->ops->encode) { 842 err = e->ops->encode(skb, (void *)(ife_meta + skboff), 843 e); 844 } 845 if (err < 0) { 846 /* too corrupt to keep around if overwritten */ 847 goto drop; 848 } 849 skboff += err; 850 } 851 oethh = (struct ethhdr *)skb->data; 852 853 if (!is_zero_ether_addr(p->eth_src)) 854 ether_addr_copy(oethh->h_source, p->eth_src); 855 if (!is_zero_ether_addr(p->eth_dst)) 856 ether_addr_copy(oethh->h_dest, p->eth_dst); 857 oethh->h_proto = htons(p->eth_type); 858 859 if (skb_at_tc_ingress(skb)) 860 skb_pull(skb, ETH_HLEN); 861 862 return action; 863 } 864 865 /* IFE encapsulates the original Ethernet header and, on decode, expects to 866 * find one, so it can only ever work on skbs that carry one. Loopback carries 867 * Ethernet header as well, so it qualifies here. 868 * At ingress, also verify that the L2 header about to be pushed back really 869 * is an Ethernet header because the skb could've been redirected with mirred 870 * from a non-Ethernet device. 871 */ 872 static bool tcf_ife_is_eth_skb(const struct sk_buff *skb) 873 { 874 if (skb->dev->type != ARPHRD_ETHER && 875 skb->dev->type != ARPHRD_LOOPBACK) 876 return false; 877 878 return !skb_at_tc_ingress(skb) || skb->mac_len == ETH_HLEN; 879 } 880 881 TC_INDIRECT_SCOPE int tcf_ife_act(struct sk_buff *skb, 882 const struct tc_action *a, 883 struct tcf_result *res) 884 { 885 struct tcf_ife_info *ife = to_ife(a); 886 struct tcf_ife_params *p; 887 int ret; 888 889 if (unlikely(!tcf_ife_is_eth_skb(skb))) { 890 bstats_update(this_cpu_ptr(ife->common.cpu_bstats), skb); 891 tcf_lastuse_update(&ife->tcf_tm); 892 qstats_cpu_drop_inc(ife->common.cpu_qstats); 893 return TC_ACT_SHOT; 894 } 895 896 p = rcu_dereference_bh(ife->params); 897 if (p->flags & IFE_ENCODE) { 898 ret = tcf_ife_encode(skb, a, res, p); 899 return ret; 900 } 901 902 return tcf_ife_decode(skb, a, res); 903 } 904 905 static size_t tcf_ife_get_fill_size(const struct tc_action *act) 906 { 907 struct tcf_ife_info *ife = to_ife(act); 908 const struct tcf_ife_params *p; 909 struct tcf_meta_info *e; 910 size_t size = nla_total_size(sizeof(struct tc_ife)) /* TCA_IFE_PARMS */ 911 + nla_total_size(ETH_ALEN) /* TCA_IFE_DMAC */ 912 + nla_total_size(ETH_ALEN) /* TCA_IFE_SMAC */ 913 + nla_total_size(2) /* TCA_IFE_TYPE */ 914 + nla_total_size(0); /* TCA_IFE_METALST */ 915 916 rcu_read_lock(); 917 p = rcu_dereference(ife->params); 918 if (p) { 919 list_for_each_entry_rcu(e, &p->metalist, metalist) 920 size += nla_total_size(sizeof(u32)); 921 } 922 rcu_read_unlock(); 923 924 return size; 925 } 926 927 static struct tc_action_ops act_ife_ops = { 928 .kind = "ife", 929 .id = TCA_ID_IFE, 930 .owner = THIS_MODULE, 931 .act = tcf_ife_act, 932 .dump = tcf_ife_dump, 933 .cleanup = tcf_ife_cleanup, 934 .init = tcf_ife_init, 935 .get_fill_size = tcf_ife_get_fill_size, 936 .size = sizeof(struct tcf_ife_info), 937 }; 938 MODULE_ALIAS_NET_ACT("ife"); 939 940 static __net_init int ife_init_net(struct net *net) 941 { 942 struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); 943 944 return tc_action_net_init(net, tn, &act_ife_ops); 945 } 946 947 static void __net_exit ife_exit_net(struct list_head *net_list) 948 { 949 tc_action_net_exit(net_list, act_ife_ops.net_id); 950 } 951 952 static struct pernet_operations ife_net_ops = { 953 .init = ife_init_net, 954 .exit_batch = ife_exit_net, 955 .id = &act_ife_ops.net_id, 956 .size = sizeof(struct tc_action_net), 957 }; 958 959 static int __init ife_init_module(void) 960 { 961 return tcf_register_action(&act_ife_ops, &ife_net_ops); 962 } 963 964 static void __exit ife_cleanup_module(void) 965 { 966 tcf_unregister_action(&act_ife_ops, &ife_net_ops); 967 } 968 969 module_init(ife_init_module); 970 module_exit(ife_cleanup_module); 971 972 MODULE_AUTHOR("Jamal Hadi Salim(2015)"); 973 MODULE_DESCRIPTION("Inter-FE LFB action"); 974 MODULE_LICENSE("GPL"); 975