seg6_local.c (7fa41efac14ffbe8db7660ad2da3928969d10caf) seg6_local.c (486cdf21583e5b1fad488a3e4f0a5242a31c0ffa)
1/*
2 * SR-IPv6 implementation
3 *
4 * Authors:
5 * David Lebrun <david.lebrun@uclouvain.be>
6 * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
7 *
8 *

--- 445 unchanged lines hidden (view full) ---

454
455drop:
456 kfree_skb(skb);
457 return err;
458}
459
460DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
461
1/*
2 * SR-IPv6 implementation
3 *
4 * Authors:
5 * David Lebrun <david.lebrun@uclouvain.be>
6 * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
7 *
8 *

--- 445 unchanged lines hidden (view full) ---

454
455drop:
456 kfree_skb(skb);
457 return err;
458}
459
460DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
461
462bool seg6_bpf_has_valid_srh(struct sk_buff *skb)
463{
464 struct seg6_bpf_srh_state *srh_state =
465 this_cpu_ptr(&seg6_bpf_srh_states);
466 struct ipv6_sr_hdr *srh = srh_state->srh;
467
468 if (unlikely(srh == NULL))
469 return false;
470
471 if (unlikely(!srh_state->valid)) {
472 if ((srh_state->hdrlen & 7) != 0)
473 return false;
474
475 srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
476 if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))
477 return false;
478
479 srh_state->valid = true;
480 }
481
482 return true;
483}
484
462static int input_action_end_bpf(struct sk_buff *skb,
463 struct seg6_local_lwt *slwt)
464{
465 struct seg6_bpf_srh_state *srh_state =
466 this_cpu_ptr(&seg6_bpf_srh_states);
485static int input_action_end_bpf(struct sk_buff *skb,
486 struct seg6_local_lwt *slwt)
487{
488 struct seg6_bpf_srh_state *srh_state =
489 this_cpu_ptr(&seg6_bpf_srh_states);
467 struct seg6_bpf_srh_state local_srh_state;
468 struct ipv6_sr_hdr *srh;
490 struct ipv6_sr_hdr *srh;
469 int srhoff = 0;
470 int ret;
471
472 srh = get_and_validate_srh(skb);
491 int ret;
492
493 srh = get_and_validate_srh(skb);
473 if (!srh)
474 goto drop;
494 if (!srh) {
495 kfree_skb(skb);
496 return -EINVAL;
497 }
475 advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
476
477 /* preempt_disable is needed to protect the per-CPU buffer srh_state,
478 * which is also accessed by the bpf_lwt_seg6_* helpers
479 */
480 preempt_disable();
498 advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
499
500 /* preempt_disable is needed to protect the per-CPU buffer srh_state,
501 * which is also accessed by the bpf_lwt_seg6_* helpers
502 */
503 preempt_disable();
504 srh_state->srh = srh;
481 srh_state->hdrlen = srh->hdrlen << 3;
505 srh_state->hdrlen = srh->hdrlen << 3;
482 srh_state->valid = 1;
506 srh_state->valid = true;
483
484 rcu_read_lock();
485 bpf_compute_data_pointers(skb);
486 ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
487 rcu_read_unlock();
488
507
508 rcu_read_lock();
509 bpf_compute_data_pointers(skb);
510 ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
511 rcu_read_unlock();
512
489 local_srh_state = *srh_state;
490 preempt_enable();
491
492 switch (ret) {
493 case BPF_OK:
494 case BPF_REDIRECT:
495 break;
496 case BPF_DROP:
497 goto drop;
498 default:
499 pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret);
500 goto drop;
501 }
502
513 switch (ret) {
514 case BPF_OK:
515 case BPF_REDIRECT:
516 break;
517 case BPF_DROP:
518 goto drop;
519 default:
520 pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret);
521 goto drop;
522 }
523
503 if (unlikely((local_srh_state.hdrlen & 7) != 0))
524 if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
504 goto drop;
505
525 goto drop;
526
506 if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
507 goto drop;
508 srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
509 srh->hdrlen = (u8)(local_srh_state.hdrlen >> 3);
510
511 if (!local_srh_state.valid &&
512 unlikely(!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3)))
513 goto drop;
514
527 preempt_enable();
515 if (ret != BPF_REDIRECT)
516 seg6_lookup_nexthop(skb, NULL, 0);
517
518 return dst_input(skb);
519
520drop:
528 if (ret != BPF_REDIRECT)
529 seg6_lookup_nexthop(skb, NULL, 0);
530
531 return dst_input(skb);
532
533drop:
534 preempt_enable();
521 kfree_skb(skb);
522 return -EINVAL;
523}
524
525static struct seg6_action_desc seg6_action_table[] = {
526 {
527 .action = SEG6_LOCAL_ACTION_END,
528 .attrs = 0,

--- 572 unchanged lines hidden ---
535 kfree_skb(skb);
536 return -EINVAL;
537}
538
539static struct seg6_action_desc seg6_action_table[] = {
540 {
541 .action = SEG6_LOCAL_ACTION_END,
542 .attrs = 0,

--- 572 unchanged lines hidden ---