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 --- |