Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: ioam: refactoring to align with the fix

ioam6_parser uses a packet socket. After the fix to prevent writing to
cloned skb's, the receiver does not see its IOAM data anymore, which
makes input/forward ioam-selftests to fail. As a workaround,
ioam6_parser now uses an IPv6 raw socket and leverages ancillary data to
get hop-by-hop options. As a consequence, the hook is "after" the IOAM
data insertion by the receiver and all tests are working again.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Justin Iurman and committed by
Paolo Abeni
187bbb69 f198d933

+65 -66
+17 -19
tools/testing/selftests/net/ioam6.sh
··· 367 367 local desc=$2 368 368 local node_src=$3 369 369 local node_dst=$4 370 - local ip6_src=$5 371 - local ip6_dst=$6 372 - local if_dst=$7 373 - local trace_type=$8 374 - local ioam_ns=$9 370 + local ip6_dst=$5 371 + local trace_type=$6 372 + local ioam_ns=$7 373 + local type=$8 375 374 376 - ip netns exec $node_dst ./ioam6_parser $if_dst $name $ip6_src $ip6_dst \ 377 - $trace_type $ioam_ns & 375 + ip netns exec $node_dst ./ioam6_parser $name $trace_type $ioam_ns $type & 378 376 local spid=$! 379 377 sleep 0.1 380 378 ··· 487 489 trace prealloc type 0x800000 ns 0 size 4 dev veth0 488 490 489 491 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 490 - db01::2 db01::1 veth0 0x800000 0 492 + db01::1 0x800000 0 $1 491 493 492 494 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 493 495 } ··· 507 509 trace prealloc type 0xc00000 ns 123 size 4 dev veth0 508 510 509 511 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 510 - db01::2 db01::1 veth0 0xc00000 123 512 + db01::1 0xc00000 123 $1 511 513 512 514 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 513 515 } ··· 541 543 if [ $cmd_res != 0 ] 542 544 then 543 545 npassed=$((npassed+1)) 544 - log_test_passed "$descr" 546 + log_test_passed "$descr ($1 mode)" 545 547 else 546 548 nfailed=$((nfailed+1)) 547 - log_test_failed "$descr" 549 + log_test_failed "$descr ($1 mode)" 548 550 fi 549 551 else 550 552 run_test "out_bit$i" "$descr ($1 mode)" $ioam_node_alpha \ 551 - $ioam_node_beta db01::2 db01::1 veth0 ${bit2type[$i]} 123 553 + $ioam_node_beta db01::1 ${bit2type[$i]} 123 $1 552 554 fi 553 555 done 554 556 ··· 572 574 trace prealloc type 0xfff002 ns 123 size 100 dev veth0 573 575 574 576 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 575 - db01::2 db01::1 veth0 0xfff002 123 577 + db01::1 0xfff002 123 $1 576 578 577 579 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 578 580 } ··· 602 604 trace prealloc type 0x800000 ns 0 size 4 dev veth0 603 605 604 606 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 605 - db01::2 db01::1 veth0 0x800000 0 607 + db01::1 0x800000 0 $1 606 608 607 609 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 608 610 } ··· 622 624 trace prealloc type 0xc00000 ns 123 size 4 dev veth0 623 625 624 626 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 625 - db01::2 db01::1 veth0 0xc00000 123 627 + db01::1 0xc00000 123 $1 626 628 627 629 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 628 630 } ··· 649 651 dev veth0 650 652 651 653 run_test "in_bit$i" "${desc/<n>/$i} ($1 mode)" $ioam_node_alpha \ 652 - $ioam_node_beta db01::2 db01::1 veth0 ${bit2type[$i]} 123 654 + $ioam_node_beta db01::1 ${bit2type[$i]} 123 $1 653 655 done 654 656 655 657 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down ··· 677 679 trace prealloc type 0xc00000 ns 123 size 4 dev veth0 678 680 679 681 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 680 - db01::2 db01::1 veth0 0xc00000 123 682 + db01::1 0xc00000 123 $1 681 683 682 684 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 683 685 ··· 701 703 trace prealloc type 0xfff002 ns 123 size 80 dev veth0 702 704 703 705 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_beta \ 704 - db01::2 db01::1 veth0 0xfff002 123 706 + db01::1 0xfff002 123 $1 705 707 706 708 [ "$1" = "encap" ] && ip -netns $ioam_node_beta link set ip6tnl0 down 707 709 } ··· 729 731 trace prealloc type 0xfff002 ns 123 size 244 via db01::1 dev veth0 730 732 731 733 run_test ${FUNCNAME[0]} "${desc} ($1 mode)" $ioam_node_alpha $ioam_node_gamma \ 732 - db01::2 db02::2 veth0 0xfff002 123 734 + db02::2 0xfff002 123 $1 733 735 734 736 [ "$1" = "encap" ] && ip -netns $ioam_node_gamma link set ip6tnl0 down 735 737 }
+48 -47
tools/testing/selftests/net/ioam6_parser.c
··· 8 8 #include <errno.h> 9 9 #include <limits.h> 10 10 #include <linux/const.h> 11 - #include <linux/if_ether.h> 12 11 #include <linux/ioam6.h> 13 12 #include <linux/ipv6.h> 14 13 #include <stdlib.h> ··· 511 512 return -1; 512 513 } 513 514 514 - static int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) 515 - { 516 - return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | 517 - (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | 518 - (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | 519 - (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0; 520 - } 521 - 522 515 static int get_u32(__u32 *val, const char *arg, int base) 523 516 { 524 517 unsigned long res; ··· 594 603 595 604 int main(int argc, char **argv) 596 605 { 597 - int fd, size, hoplen, tid, ret = 1; 598 - struct in6_addr src, dst; 606 + int fd, size, hoplen, tid, ret = 1, on = 1; 599 607 struct ioam6_hdr *opt; 600 - struct ipv6hdr *ip6h; 601 - __u8 buffer[400], *p; 602 - __u16 ioam_ns; 608 + struct cmsghdr *cmsg; 609 + struct msghdr msg; 610 + struct iovec iov; 611 + __u8 buffer[512]; 603 612 __u32 tr_type; 613 + __u16 ioam_ns; 614 + __u8 *ptr; 604 615 605 - if (argc != 7) 616 + if (argc != 5) 606 617 goto out; 607 618 608 - tid = str2id(argv[2]); 619 + tid = str2id(argv[1]); 609 620 if (tid < 0 || !func[tid]) 610 621 goto out; 611 622 612 - if (inet_pton(AF_INET6, argv[3], &src) != 1 || 613 - inet_pton(AF_INET6, argv[4], &dst) != 1) 623 + if (get_u32(&tr_type, argv[2], 16) || 624 + get_u16(&ioam_ns, argv[3], 0)) 614 625 goto out; 615 626 616 - if (get_u32(&tr_type, argv[5], 16) || 617 - get_u16(&ioam_ns, argv[6], 0)) 627 + fd = socket(PF_INET6, SOCK_RAW, 628 + !strcmp(argv[4], "encap") ? IPPROTO_IPV6 : IPPROTO_ICMPV6); 629 + if (fd < 0) 618 630 goto out; 619 631 620 - fd = socket(AF_PACKET, SOCK_DGRAM, __cpu_to_be16(ETH_P_IPV6)); 621 - if (!fd) 622 - goto out; 632 + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &on, sizeof(on)); 623 633 624 - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, 625 - argv[1], strlen(argv[1]))) 634 + iov.iov_len = 1; 635 + iov.iov_base = malloc(CMSG_SPACE(sizeof(buffer))); 636 + if (!iov.iov_base) 626 637 goto close; 627 - 628 638 recv: 629 - size = recv(fd, buffer, sizeof(buffer), 0); 639 + memset(&msg, 0, sizeof(msg)); 640 + msg.msg_iov = &iov; 641 + msg.msg_iovlen = 1; 642 + msg.msg_control = buffer; 643 + msg.msg_controllen = CMSG_SPACE(sizeof(buffer)); 644 + 645 + size = recvmsg(fd, &msg, 0); 630 646 if (size <= 0) 631 647 goto close; 632 648 633 - ip6h = (struct ipv6hdr *)buffer; 649 + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 650 + if (cmsg->cmsg_level != IPPROTO_IPV6 || 651 + cmsg->cmsg_type != IPV6_HOPOPTS || 652 + cmsg->cmsg_len < sizeof(struct ipv6_hopopt_hdr)) 653 + continue; 634 654 635 - if (!ipv6_addr_equal(&ip6h->saddr, &src) || 636 - !ipv6_addr_equal(&ip6h->daddr, &dst)) 637 - goto recv; 655 + ptr = (__u8 *)CMSG_DATA(cmsg); 638 656 639 - if (ip6h->nexthdr != IPPROTO_HOPOPTS) 640 - goto close; 657 + hoplen = (ptr[1] + 1) << 3; 658 + ptr += sizeof(struct ipv6_hopopt_hdr); 641 659 642 - p = buffer + sizeof(*ip6h); 643 - hoplen = (p[1] + 1) << 3; 644 - p += sizeof(struct ipv6_hopopt_hdr); 660 + while (hoplen > 0) { 661 + opt = (struct ioam6_hdr *)ptr; 645 662 646 - while (hoplen > 0) { 647 - opt = (struct ioam6_hdr *)p; 663 + if (opt->opt_type == IPV6_TLV_IOAM && 664 + opt->type == IOAM6_TYPE_PREALLOC) { 665 + ptr += sizeof(*opt); 666 + ret = func[tid](tid, 667 + (struct ioam6_trace_hdr *)ptr, 668 + tr_type, ioam_ns); 669 + goto close; 670 + } 648 671 649 - if (opt->opt_type == IPV6_TLV_IOAM && 650 - opt->type == IOAM6_TYPE_PREALLOC) { 651 - p += sizeof(*opt); 652 - ret = func[tid](tid, (struct ioam6_trace_hdr *)p, 653 - tr_type, ioam_ns); 654 - break; 672 + ptr += opt->opt_len + 2; 673 + hoplen -= opt->opt_len + 2; 655 674 } 656 - 657 - p += opt->opt_len + 2; 658 - hoplen -= opt->opt_len + 2; 659 675 } 676 + 677 + goto recv; 660 678 close: 679 + free(iov.iov_base); 661 680 close(fd); 662 681 out: 663 682 return ret;