linux/tools/testing/selftests/bpf/progs/test_tunnel_kern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2016 VMware
   3 * Copyright (c) 2016 Facebook
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of version 2 of the GNU General Public
   7 * License as published by the Free Software Foundation.
   8 */
   9#include <stddef.h>
  10#include <string.h>
  11#include <arpa/inet.h>
  12#include <linux/bpf.h>
  13#include <linux/if_ether.h>
  14#include <linux/if_packet.h>
  15#include <linux/ip.h>
  16#include <linux/ipv6.h>
  17#include <linux/types.h>
  18#include <linux/tcp.h>
  19#include <linux/socket.h>
  20#include <linux/pkt_cls.h>
  21#include <linux/erspan.h>
  22#include "bpf_helpers.h"
  23#include "bpf_endian.h"
  24
  25#define ERROR(ret) do {\
  26                char fmt[] = "ERROR line:%d ret:%d\n";\
  27                bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
  28        } while (0)
  29
  30int _version SEC("version") = 1;
  31
  32struct geneve_opt {
  33        __be16  opt_class;
  34        __u8    type;
  35        __u8    length:5;
  36        __u8    r3:1;
  37        __u8    r2:1;
  38        __u8    r1:1;
  39        __u8    opt_data[8]; /* hard-coded to 8 byte */
  40};
  41
  42struct vxlan_metadata {
  43        __u32     gbp;
  44};
  45
  46SEC("gre_set_tunnel")
  47int _gre_set_tunnel(struct __sk_buff *skb)
  48{
  49        int ret;
  50        struct bpf_tunnel_key key;
  51
  52        __builtin_memset(&key, 0x0, sizeof(key));
  53        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
  54        key.tunnel_id = 2;
  55        key.tunnel_tos = 0;
  56        key.tunnel_ttl = 64;
  57
  58        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
  59                                     BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);
  60        if (ret < 0) {
  61                ERROR(ret);
  62                return TC_ACT_SHOT;
  63        }
  64
  65        return TC_ACT_OK;
  66}
  67
  68SEC("gre_get_tunnel")
  69int _gre_get_tunnel(struct __sk_buff *skb)
  70{
  71        int ret;
  72        struct bpf_tunnel_key key;
  73        char fmt[] = "key %d remote ip 0x%x\n";
  74
  75        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
  76        if (ret < 0) {
  77                ERROR(ret);
  78                return TC_ACT_SHOT;
  79        }
  80
  81        bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
  82        return TC_ACT_OK;
  83}
  84
  85SEC("ip6gretap_set_tunnel")
  86int _ip6gretap_set_tunnel(struct __sk_buff *skb)
  87{
  88        struct bpf_tunnel_key key;
  89        int ret;
  90
  91        __builtin_memset(&key, 0x0, sizeof(key));
  92        key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
  93        key.tunnel_id = 2;
  94        key.tunnel_tos = 0;
  95        key.tunnel_ttl = 64;
  96        key.tunnel_label = 0xabcde;
  97
  98        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
  99                                     BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
 100                                     BPF_F_SEQ_NUMBER);
 101        if (ret < 0) {
 102                ERROR(ret);
 103                return TC_ACT_SHOT;
 104        }
 105
 106        return TC_ACT_OK;
 107}
 108
 109SEC("ip6gretap_get_tunnel")
 110int _ip6gretap_get_tunnel(struct __sk_buff *skb)
 111{
 112        char fmt[] = "key %d remote ip6 ::%x label %x\n";
 113        struct bpf_tunnel_key key;
 114        int ret;
 115
 116        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 117                                     BPF_F_TUNINFO_IPV6);
 118        if (ret < 0) {
 119                ERROR(ret);
 120                return TC_ACT_SHOT;
 121        }
 122
 123        bpf_trace_printk(fmt, sizeof(fmt),
 124                         key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
 125
 126        return TC_ACT_OK;
 127}
 128
 129SEC("erspan_set_tunnel")
 130int _erspan_set_tunnel(struct __sk_buff *skb)
 131{
 132        struct bpf_tunnel_key key;
 133        struct erspan_metadata md;
 134        int ret;
 135
 136        __builtin_memset(&key, 0x0, sizeof(key));
 137        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 138        key.tunnel_id = 2;
 139        key.tunnel_tos = 0;
 140        key.tunnel_ttl = 64;
 141
 142        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 143                                     BPF_F_ZERO_CSUM_TX);
 144        if (ret < 0) {
 145                ERROR(ret);
 146                return TC_ACT_SHOT;
 147        }
 148
 149        __builtin_memset(&md, 0, sizeof(md));
 150#ifdef ERSPAN_V1
 151        md.version = 1;
 152        md.u.index = bpf_htonl(123);
 153#else
 154        __u8 direction = 1;
 155        __u8 hwid = 7;
 156
 157        md.version = 2;
 158        md.u.md2.dir = direction;
 159        md.u.md2.hwid = hwid & 0xf;
 160        md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
 161#endif
 162
 163        ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
 164        if (ret < 0) {
 165                ERROR(ret);
 166                return TC_ACT_SHOT;
 167        }
 168
 169        return TC_ACT_OK;
 170}
 171
 172SEC("erspan_get_tunnel")
 173int _erspan_get_tunnel(struct __sk_buff *skb)
 174{
 175        char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
 176        struct bpf_tunnel_key key;
 177        struct erspan_metadata md;
 178        __u32 index;
 179        int ret;
 180
 181        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 182        if (ret < 0) {
 183                ERROR(ret);
 184                return TC_ACT_SHOT;
 185        }
 186
 187        ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
 188        if (ret < 0) {
 189                ERROR(ret);
 190                return TC_ACT_SHOT;
 191        }
 192
 193        bpf_trace_printk(fmt, sizeof(fmt),
 194                        key.tunnel_id, key.remote_ipv4, md.version);
 195
 196#ifdef ERSPAN_V1
 197        char fmt2[] = "\tindex %x\n";
 198
 199        index = bpf_ntohl(md.u.index);
 200        bpf_trace_printk(fmt2, sizeof(fmt2), index);
 201#else
 202        char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
 203
 204        bpf_trace_printk(fmt2, sizeof(fmt2),
 205                         md.u.md2.dir,
 206                         (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
 207                         bpf_ntohl(md.u.md2.timestamp));
 208#endif
 209
 210        return TC_ACT_OK;
 211}
 212
 213SEC("ip4ip6erspan_set_tunnel")
 214int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
 215{
 216        struct bpf_tunnel_key key;
 217        struct erspan_metadata md;
 218        int ret;
 219
 220        __builtin_memset(&key, 0x0, sizeof(key));
 221        key.remote_ipv6[3] = bpf_htonl(0x11);
 222        key.tunnel_id = 2;
 223        key.tunnel_tos = 0;
 224        key.tunnel_ttl = 64;
 225
 226        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 227                                     BPF_F_TUNINFO_IPV6);
 228        if (ret < 0) {
 229                ERROR(ret);
 230                return TC_ACT_SHOT;
 231        }
 232
 233        __builtin_memset(&md, 0, sizeof(md));
 234
 235#ifdef ERSPAN_V1
 236        md.u.index = bpf_htonl(123);
 237        md.version = 1;
 238#else
 239        __u8 direction = 0;
 240        __u8 hwid = 17;
 241
 242        md.version = 2;
 243        md.u.md2.dir = direction;
 244        md.u.md2.hwid = hwid & 0xf;
 245        md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
 246#endif
 247
 248        ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
 249        if (ret < 0) {
 250                ERROR(ret);
 251                return TC_ACT_SHOT;
 252        }
 253
 254        return TC_ACT_OK;
 255}
 256
 257SEC("ip4ip6erspan_get_tunnel")
 258int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
 259{
 260        char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
 261        struct bpf_tunnel_key key;
 262        struct erspan_metadata md;
 263        __u32 index;
 264        int ret;
 265
 266        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 267                                     BPF_F_TUNINFO_IPV6);
 268        if (ret < 0) {
 269                ERROR(ret);
 270                return TC_ACT_SHOT;
 271        }
 272
 273        ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
 274        if (ret < 0) {
 275                ERROR(ret);
 276                return TC_ACT_SHOT;
 277        }
 278
 279        bpf_trace_printk(fmt, sizeof(fmt),
 280                        key.tunnel_id, key.remote_ipv4, md.version);
 281
 282#ifdef ERSPAN_V1
 283        char fmt2[] = "\tindex %x\n";
 284
 285        index = bpf_ntohl(md.u.index);
 286        bpf_trace_printk(fmt2, sizeof(fmt2), index);
 287#else
 288        char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
 289
 290        bpf_trace_printk(fmt2, sizeof(fmt2),
 291                         md.u.md2.dir,
 292                         (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
 293                         bpf_ntohl(md.u.md2.timestamp));
 294#endif
 295
 296        return TC_ACT_OK;
 297}
 298
 299SEC("vxlan_set_tunnel")
 300int _vxlan_set_tunnel(struct __sk_buff *skb)
 301{
 302        int ret;
 303        struct bpf_tunnel_key key;
 304        struct vxlan_metadata md;
 305
 306        __builtin_memset(&key, 0x0, sizeof(key));
 307        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 308        key.tunnel_id = 2;
 309        key.tunnel_tos = 0;
 310        key.tunnel_ttl = 64;
 311
 312        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 313                                     BPF_F_ZERO_CSUM_TX);
 314        if (ret < 0) {
 315                ERROR(ret);
 316                return TC_ACT_SHOT;
 317        }
 318
 319        md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
 320        ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
 321        if (ret < 0) {
 322                ERROR(ret);
 323                return TC_ACT_SHOT;
 324        }
 325
 326        return TC_ACT_OK;
 327}
 328
 329SEC("vxlan_get_tunnel")
 330int _vxlan_get_tunnel(struct __sk_buff *skb)
 331{
 332        int ret;
 333        struct bpf_tunnel_key key;
 334        struct vxlan_metadata md;
 335        char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
 336
 337        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 338        if (ret < 0) {
 339                ERROR(ret);
 340                return TC_ACT_SHOT;
 341        }
 342
 343        ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
 344        if (ret < 0) {
 345                ERROR(ret);
 346                return TC_ACT_SHOT;
 347        }
 348
 349        bpf_trace_printk(fmt, sizeof(fmt),
 350                        key.tunnel_id, key.remote_ipv4, md.gbp);
 351
 352        return TC_ACT_OK;
 353}
 354
 355SEC("ip6vxlan_set_tunnel")
 356int _ip6vxlan_set_tunnel(struct __sk_buff *skb)
 357{
 358        struct bpf_tunnel_key key;
 359        int ret;
 360
 361        __builtin_memset(&key, 0x0, sizeof(key));
 362        key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
 363        key.tunnel_id = 22;
 364        key.tunnel_tos = 0;
 365        key.tunnel_ttl = 64;
 366
 367        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 368                                     BPF_F_TUNINFO_IPV6);
 369        if (ret < 0) {
 370                ERROR(ret);
 371                return TC_ACT_SHOT;
 372        }
 373
 374        return TC_ACT_OK;
 375}
 376
 377SEC("ip6vxlan_get_tunnel")
 378int _ip6vxlan_get_tunnel(struct __sk_buff *skb)
 379{
 380        char fmt[] = "key %d remote ip6 ::%x label %x\n";
 381        struct bpf_tunnel_key key;
 382        int ret;
 383
 384        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 385                                     BPF_F_TUNINFO_IPV6);
 386        if (ret < 0) {
 387                ERROR(ret);
 388                return TC_ACT_SHOT;
 389        }
 390
 391        bpf_trace_printk(fmt, sizeof(fmt),
 392                         key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
 393
 394        return TC_ACT_OK;
 395}
 396
 397SEC("geneve_set_tunnel")
 398int _geneve_set_tunnel(struct __sk_buff *skb)
 399{
 400        int ret, ret2;
 401        struct bpf_tunnel_key key;
 402        struct geneve_opt gopt;
 403
 404        __builtin_memset(&key, 0x0, sizeof(key));
 405        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 406        key.tunnel_id = 2;
 407        key.tunnel_tos = 0;
 408        key.tunnel_ttl = 64;
 409
 410        __builtin_memset(&gopt, 0x0, sizeof(gopt));
 411        gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
 412        gopt.type = 0x08;
 413        gopt.r1 = 0;
 414        gopt.r2 = 0;
 415        gopt.r3 = 0;
 416        gopt.length = 2; /* 4-byte multiple */
 417        *(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef);
 418
 419        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 420                                     BPF_F_ZERO_CSUM_TX);
 421        if (ret < 0) {
 422                ERROR(ret);
 423                return TC_ACT_SHOT;
 424        }
 425
 426        ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
 427        if (ret < 0) {
 428                ERROR(ret);
 429                return TC_ACT_SHOT;
 430        }
 431
 432        return TC_ACT_OK;
 433}
 434
 435SEC("geneve_get_tunnel")
 436int _geneve_get_tunnel(struct __sk_buff *skb)
 437{
 438        int ret;
 439        struct bpf_tunnel_key key;
 440        struct geneve_opt gopt;
 441        char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
 442
 443        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 444        if (ret < 0) {
 445                ERROR(ret);
 446                return TC_ACT_SHOT;
 447        }
 448
 449        ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
 450        if (ret < 0) {
 451                ERROR(ret);
 452                return TC_ACT_SHOT;
 453        }
 454
 455        bpf_trace_printk(fmt, sizeof(fmt),
 456                        key.tunnel_id, key.remote_ipv4, gopt.opt_class);
 457        return TC_ACT_OK;
 458}
 459
 460SEC("ip6geneve_set_tunnel")
 461int _ip6geneve_set_tunnel(struct __sk_buff *skb)
 462{
 463        struct bpf_tunnel_key key;
 464        struct geneve_opt gopt;
 465        int ret;
 466
 467        __builtin_memset(&key, 0x0, sizeof(key));
 468        key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
 469        key.tunnel_id = 22;
 470        key.tunnel_tos = 0;
 471        key.tunnel_ttl = 64;
 472
 473        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 474                                     BPF_F_TUNINFO_IPV6);
 475        if (ret < 0) {
 476                ERROR(ret);
 477                return TC_ACT_SHOT;
 478        }
 479
 480        __builtin_memset(&gopt, 0x0, sizeof(gopt));
 481        gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
 482        gopt.type = 0x08;
 483        gopt.r1 = 0;
 484        gopt.r2 = 0;
 485        gopt.r3 = 0;
 486        gopt.length = 2; /* 4-byte multiple */
 487        *(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
 488
 489        ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
 490        if (ret < 0) {
 491                ERROR(ret);
 492                return TC_ACT_SHOT;
 493        }
 494
 495        return TC_ACT_OK;
 496}
 497
 498SEC("ip6geneve_get_tunnel")
 499int _ip6geneve_get_tunnel(struct __sk_buff *skb)
 500{
 501        char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
 502        struct bpf_tunnel_key key;
 503        struct geneve_opt gopt;
 504        int ret;
 505
 506        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 507                                     BPF_F_TUNINFO_IPV6);
 508        if (ret < 0) {
 509                ERROR(ret);
 510                return TC_ACT_SHOT;
 511        }
 512
 513        ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
 514        if (ret < 0) {
 515                ERROR(ret);
 516                return TC_ACT_SHOT;
 517        }
 518
 519        bpf_trace_printk(fmt, sizeof(fmt),
 520                        key.tunnel_id, key.remote_ipv4, gopt.opt_class);
 521
 522        return TC_ACT_OK;
 523}
 524
 525SEC("ipip_set_tunnel")
 526int _ipip_set_tunnel(struct __sk_buff *skb)
 527{
 528        struct bpf_tunnel_key key = {};
 529        void *data = (void *)(long)skb->data;
 530        struct iphdr *iph = data;
 531        struct tcphdr *tcp = data + sizeof(*iph);
 532        void *data_end = (void *)(long)skb->data_end;
 533        int ret;
 534
 535        /* single length check */
 536        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 537                ERROR(1);
 538                return TC_ACT_SHOT;
 539        }
 540
 541        key.tunnel_ttl = 64;
 542        if (iph->protocol == IPPROTO_ICMP) {
 543                key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 544        } else {
 545                if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
 546                        return TC_ACT_SHOT;
 547
 548                if (tcp->dest == bpf_htons(5200))
 549                        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 550                else if (tcp->dest == bpf_htons(5201))
 551                        key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
 552                else
 553                        return TC_ACT_SHOT;
 554        }
 555
 556        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
 557        if (ret < 0) {
 558                ERROR(ret);
 559                return TC_ACT_SHOT;
 560        }
 561
 562        return TC_ACT_OK;
 563}
 564
 565SEC("ipip_get_tunnel")
 566int _ipip_get_tunnel(struct __sk_buff *skb)
 567{
 568        int ret;
 569        struct bpf_tunnel_key key;
 570        char fmt[] = "remote ip 0x%x\n";
 571
 572        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 573        if (ret < 0) {
 574                ERROR(ret);
 575                return TC_ACT_SHOT;
 576        }
 577
 578        bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
 579        return TC_ACT_OK;
 580}
 581
 582SEC("ipip6_set_tunnel")
 583int _ipip6_set_tunnel(struct __sk_buff *skb)
 584{
 585        struct bpf_tunnel_key key = {};
 586        void *data = (void *)(long)skb->data;
 587        struct iphdr *iph = data;
 588        struct tcphdr *tcp = data + sizeof(*iph);
 589        void *data_end = (void *)(long)skb->data_end;
 590        int ret;
 591
 592        /* single length check */
 593        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 594                ERROR(1);
 595                return TC_ACT_SHOT;
 596        }
 597
 598        __builtin_memset(&key, 0x0, sizeof(key));
 599        key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
 600        key.tunnel_ttl = 64;
 601
 602        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 603                                     BPF_F_TUNINFO_IPV6);
 604        if (ret < 0) {
 605                ERROR(ret);
 606                return TC_ACT_SHOT;
 607        }
 608
 609        return TC_ACT_OK;
 610}
 611
 612SEC("ipip6_get_tunnel")
 613int _ipip6_get_tunnel(struct __sk_buff *skb)
 614{
 615        int ret;
 616        struct bpf_tunnel_key key;
 617        char fmt[] = "remote ip6 %x::%x\n";
 618
 619        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 620                                     BPF_F_TUNINFO_IPV6);
 621        if (ret < 0) {
 622                ERROR(ret);
 623                return TC_ACT_SHOT;
 624        }
 625
 626        bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
 627                         bpf_htonl(key.remote_ipv6[3]));
 628        return TC_ACT_OK;
 629}
 630
 631SEC("ip6ip6_set_tunnel")
 632int _ip6ip6_set_tunnel(struct __sk_buff *skb)
 633{
 634        struct bpf_tunnel_key key = {};
 635        void *data = (void *)(long)skb->data;
 636        struct ipv6hdr *iph = data;
 637        struct tcphdr *tcp = data + sizeof(*iph);
 638        void *data_end = (void *)(long)skb->data_end;
 639        int ret;
 640
 641        /* single length check */
 642        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 643                ERROR(1);
 644                return TC_ACT_SHOT;
 645        }
 646
 647        key.remote_ipv6[0] = bpf_htonl(0x2401db00);
 648        key.tunnel_ttl = 64;
 649
 650        if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
 651                key.remote_ipv6[3] = bpf_htonl(1);
 652        } else {
 653                if (iph->nexthdr != 6 /* NEXTHDR_TCP */) {
 654                        ERROR(iph->nexthdr);
 655                        return TC_ACT_SHOT;
 656                }
 657
 658                if (tcp->dest == bpf_htons(5200)) {
 659                        key.remote_ipv6[3] = bpf_htonl(1);
 660                } else if (tcp->dest == bpf_htons(5201)) {
 661                        key.remote_ipv6[3] = bpf_htonl(2);
 662                } else {
 663                        ERROR(tcp->dest);
 664                        return TC_ACT_SHOT;
 665                }
 666        }
 667
 668        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
 669                                     BPF_F_TUNINFO_IPV6);
 670        if (ret < 0) {
 671                ERROR(ret);
 672                return TC_ACT_SHOT;
 673        }
 674
 675        return TC_ACT_OK;
 676}
 677
 678SEC("ip6ip6_get_tunnel")
 679int _ip6ip6_get_tunnel(struct __sk_buff *skb)
 680{
 681        int ret;
 682        struct bpf_tunnel_key key;
 683        char fmt[] = "remote ip6 %x::%x\n";
 684
 685        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
 686                                     BPF_F_TUNINFO_IPV6);
 687        if (ret < 0) {
 688                ERROR(ret);
 689                return TC_ACT_SHOT;
 690        }
 691
 692        bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
 693                         bpf_htonl(key.remote_ipv6[3]));
 694        return TC_ACT_OK;
 695}
 696
 697SEC("xfrm_get_state")
 698int _xfrm_get_state(struct __sk_buff *skb)
 699{
 700        struct bpf_xfrm_state x;
 701        char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
 702        int ret;
 703
 704        ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
 705        if (ret < 0)
 706                return TC_ACT_OK;
 707
 708        bpf_trace_printk(fmt, sizeof(fmt), x.reqid, bpf_ntohl(x.spi),
 709                         bpf_ntohl(x.remote_ipv4));
 710        return TC_ACT_OK;
 711}
 712
 713char _license[] SEC("license") = "GPL";
 714