linux/samples/bpf/tcbpf2_kern.c
<<
>>
Prefs
   1/* Copyright (c) 2016 VMware
   2 * Copyright (c) 2016 Facebook
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of version 2 of the GNU General Public
   6 * License as published by the Free Software Foundation.
   7 */
   8#define KBUILD_MODNAME "foo"
   9#include <uapi/linux/bpf.h>
  10#include <uapi/linux/if_ether.h>
  11#include <uapi/linux/if_packet.h>
  12#include <uapi/linux/ip.h>
  13#include <uapi/linux/ipv6.h>
  14#include <uapi/linux/in.h>
  15#include <uapi/linux/tcp.h>
  16#include <uapi/linux/filter.h>
  17#include <uapi/linux/pkt_cls.h>
  18#include <net/ipv6.h>
  19#include "bpf_helpers.h"
  20
  21#define _htonl __builtin_bswap32
  22#define ERROR(ret) do {\
  23                char fmt[] = "ERROR line:%d ret:%d\n";\
  24                bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
  25        } while(0)
  26
  27struct geneve_opt {
  28        __be16  opt_class;
  29        u8      type;
  30        u8      length:5;
  31        u8      r3:1;
  32        u8      r2:1;
  33        u8      r1:1;
  34        u8      opt_data[8]; /* hard-coded to 8 byte */
  35};
  36
  37struct vxlan_metadata {
  38        u32     gbp;
  39};
  40
  41SEC("gre_set_tunnel")
  42int _gre_set_tunnel(struct __sk_buff *skb)
  43{
  44        int ret;
  45        struct bpf_tunnel_key key;
  46
  47        __builtin_memset(&key, 0x0, sizeof(key));
  48        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
  49        key.tunnel_id = 2;
  50        key.tunnel_tos = 0;
  51        key.tunnel_ttl = 64;
  52
  53        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
  54        if (ret < 0) {
  55                ERROR(ret);
  56                return TC_ACT_SHOT;
  57        }
  58
  59        return TC_ACT_OK;
  60}
  61
  62SEC("gre_get_tunnel")
  63int _gre_get_tunnel(struct __sk_buff *skb)
  64{
  65        int ret;
  66        struct bpf_tunnel_key key;
  67        char fmt[] = "key %d remote ip 0x%x\n";
  68
  69        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
  70        if (ret < 0) {
  71                ERROR(ret);
  72                return TC_ACT_SHOT;
  73        }
  74
  75        bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
  76        return TC_ACT_OK;
  77}
  78
  79SEC("vxlan_set_tunnel")
  80int _vxlan_set_tunnel(struct __sk_buff *skb)
  81{
  82        int ret;
  83        struct bpf_tunnel_key key;
  84        struct vxlan_metadata md;
  85
  86        __builtin_memset(&key, 0x0, sizeof(key));
  87        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
  88        key.tunnel_id = 2;
  89        key.tunnel_tos = 0;
  90        key.tunnel_ttl = 64;
  91
  92        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
  93        if (ret < 0) {
  94                ERROR(ret);
  95                return TC_ACT_SHOT;
  96        }
  97
  98        md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
  99        ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
 100        if (ret < 0) {
 101                ERROR(ret);
 102                return TC_ACT_SHOT;
 103        }
 104
 105        return TC_ACT_OK;
 106}
 107
 108SEC("vxlan_get_tunnel")
 109int _vxlan_get_tunnel(struct __sk_buff *skb)
 110{
 111        int ret;
 112        struct bpf_tunnel_key key;
 113        struct vxlan_metadata md;
 114        char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
 115
 116        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 117        if (ret < 0) {
 118                ERROR(ret);
 119                return TC_ACT_SHOT;
 120        }
 121
 122        ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
 123        if (ret < 0) {
 124                ERROR(ret);
 125                return TC_ACT_SHOT;
 126        }
 127
 128        bpf_trace_printk(fmt, sizeof(fmt),
 129                        key.tunnel_id, key.remote_ipv4, md.gbp);
 130
 131        return TC_ACT_OK;
 132}
 133
 134SEC("geneve_set_tunnel")
 135int _geneve_set_tunnel(struct __sk_buff *skb)
 136{
 137        int ret, ret2;
 138        struct bpf_tunnel_key key;
 139        struct geneve_opt gopt;
 140
 141        __builtin_memset(&key, 0x0, sizeof(key));
 142        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 143        key.tunnel_id = 2;
 144        key.tunnel_tos = 0;
 145        key.tunnel_ttl = 64;
 146
 147        __builtin_memset(&gopt, 0x0, sizeof(gopt));
 148        gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
 149        gopt.type = 0x08;
 150        gopt.r1 = 1;
 151        gopt.r2 = 0;
 152        gopt.r3 = 1;
 153        gopt.length = 2; /* 4-byte multiple */
 154        *(int *) &gopt.opt_data = 0xdeadbeef;
 155
 156        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
 157        if (ret < 0) {
 158                ERROR(ret);
 159                return TC_ACT_SHOT;
 160        }
 161
 162        ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
 163        if (ret < 0) {
 164                ERROR(ret);
 165                return TC_ACT_SHOT;
 166        }
 167
 168        return TC_ACT_OK;
 169}
 170
 171SEC("geneve_get_tunnel")
 172int _geneve_get_tunnel(struct __sk_buff *skb)
 173{
 174        int ret;
 175        struct bpf_tunnel_key key;
 176        struct geneve_opt gopt;
 177        char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
 178
 179        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 180        if (ret < 0) {
 181                ERROR(ret);
 182                return TC_ACT_SHOT;
 183        }
 184
 185        ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
 186        if (ret < 0) {
 187                ERROR(ret);
 188                return TC_ACT_SHOT;
 189        }
 190
 191        bpf_trace_printk(fmt, sizeof(fmt),
 192                        key.tunnel_id, key.remote_ipv4, gopt.opt_class);
 193        return TC_ACT_OK;
 194}
 195
 196SEC("ipip_set_tunnel")
 197int _ipip_set_tunnel(struct __sk_buff *skb)
 198{
 199        struct bpf_tunnel_key key = {};
 200        void *data = (void *)(long)skb->data;
 201        struct iphdr *iph = data;
 202        struct tcphdr *tcp = data + sizeof(*iph);
 203        void *data_end = (void *)(long)skb->data_end;
 204        int ret;
 205
 206        /* single length check */
 207        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 208                ERROR(1);
 209                return TC_ACT_SHOT;
 210        }
 211
 212        key.tunnel_ttl = 64;
 213        if (iph->protocol == IPPROTO_ICMP) {
 214                key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 215        } else {
 216                if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
 217                        return TC_ACT_SHOT;
 218
 219                if (tcp->dest == htons(5200))
 220                        key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
 221                else if (tcp->dest == htons(5201))
 222                        key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
 223                else
 224                        return TC_ACT_SHOT;
 225        }
 226
 227        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
 228        if (ret < 0) {
 229                ERROR(ret);
 230                return TC_ACT_SHOT;
 231        }
 232
 233        return TC_ACT_OK;
 234}
 235
 236SEC("ipip_get_tunnel")
 237int _ipip_get_tunnel(struct __sk_buff *skb)
 238{
 239        int ret;
 240        struct bpf_tunnel_key key;
 241        char fmt[] = "remote ip 0x%x\n";
 242
 243        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 244        if (ret < 0) {
 245                ERROR(ret);
 246                return TC_ACT_SHOT;
 247        }
 248
 249        bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
 250        return TC_ACT_OK;
 251}
 252
 253SEC("ipip6_set_tunnel")
 254int _ipip6_set_tunnel(struct __sk_buff *skb)
 255{
 256        struct bpf_tunnel_key key = {};
 257        void *data = (void *)(long)skb->data;
 258        struct iphdr *iph = data;
 259        struct tcphdr *tcp = data + sizeof(*iph);
 260        void *data_end = (void *)(long)skb->data_end;
 261        int ret;
 262
 263        /* single length check */
 264        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 265                ERROR(1);
 266                return TC_ACT_SHOT;
 267        }
 268
 269        key.remote_ipv6[0] = _htonl(0x2401db00);
 270        key.tunnel_ttl = 64;
 271
 272        if (iph->protocol == IPPROTO_ICMP) {
 273                key.remote_ipv6[3] = _htonl(1);
 274        } else {
 275                if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
 276                        ERROR(iph->protocol);
 277                        return TC_ACT_SHOT;
 278                }
 279
 280                if (tcp->dest == htons(5200)) {
 281                        key.remote_ipv6[3] = _htonl(1);
 282                } else if (tcp->dest == htons(5201)) {
 283                        key.remote_ipv6[3] = _htonl(2);
 284                } else {
 285                        ERROR(tcp->dest);
 286                        return TC_ACT_SHOT;
 287                }
 288        }
 289
 290        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
 291        if (ret < 0) {
 292                ERROR(ret);
 293                return TC_ACT_SHOT;
 294        }
 295
 296        return TC_ACT_OK;
 297}
 298
 299SEC("ipip6_get_tunnel")
 300int _ipip6_get_tunnel(struct __sk_buff *skb)
 301{
 302        int ret;
 303        struct bpf_tunnel_key key;
 304        char fmt[] = "remote ip6 %x::%x\n";
 305
 306        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
 307        if (ret < 0) {
 308                ERROR(ret);
 309                return TC_ACT_SHOT;
 310        }
 311
 312        bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
 313                         _htonl(key.remote_ipv6[3]));
 314        return TC_ACT_OK;
 315}
 316
 317SEC("ip6ip6_set_tunnel")
 318int _ip6ip6_set_tunnel(struct __sk_buff *skb)
 319{
 320        struct bpf_tunnel_key key = {};
 321        void *data = (void *)(long)skb->data;
 322        struct ipv6hdr *iph = data;
 323        struct tcphdr *tcp = data + sizeof(*iph);
 324        void *data_end = (void *)(long)skb->data_end;
 325        int ret;
 326
 327        /* single length check */
 328        if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
 329                ERROR(1);
 330                return TC_ACT_SHOT;
 331        }
 332
 333        key.remote_ipv6[0] = _htonl(0x2401db00);
 334        key.tunnel_ttl = 64;
 335
 336        if (iph->nexthdr == NEXTHDR_ICMP) {
 337                key.remote_ipv6[3] = _htonl(1);
 338        } else {
 339                if (iph->nexthdr != NEXTHDR_TCP) {
 340                        ERROR(iph->nexthdr);
 341                        return TC_ACT_SHOT;
 342                }
 343
 344                if (tcp->dest == htons(5200)) {
 345                        key.remote_ipv6[3] = _htonl(1);
 346                } else if (tcp->dest == htons(5201)) {
 347                        key.remote_ipv6[3] = _htonl(2);
 348                } else {
 349                        ERROR(tcp->dest);
 350                        return TC_ACT_SHOT;
 351                }
 352        }
 353
 354        ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
 355        if (ret < 0) {
 356                ERROR(ret);
 357                return TC_ACT_SHOT;
 358        }
 359
 360        return TC_ACT_OK;
 361}
 362
 363SEC("ip6ip6_get_tunnel")
 364int _ip6ip6_get_tunnel(struct __sk_buff *skb)
 365{
 366        int ret;
 367        struct bpf_tunnel_key key;
 368        char fmt[] = "remote ip6 %x::%x\n";
 369
 370        ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
 371        if (ret < 0) {
 372                ERROR(ret);
 373                return TC_ACT_SHOT;
 374        }
 375
 376        bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
 377                         _htonl(key.remote_ipv6[3]));
 378        return TC_ACT_OK;
 379}
 380
 381
 382char _license[] SEC("license") = "GPL";
 383