1027 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2016 VMware3 * Copyright (c) 2016 Facebook4 *5 * This program is free software; you can redistribute it and/or6 * modify it under the terms of version 2 of the GNU General Public7 * License as published by the Free Software Foundation.8 */9#include "vmlinux.h"10#include <bpf/bpf_core_read.h>11#include <bpf/bpf_helpers.h>12#include <bpf/bpf_endian.h>13#include "bpf_kfuncs.h"14#include "bpf_tracing_net.h"15 16#define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret)17 18#define VXLAN_UDP_PORT 478919#define ETH_P_IP 0x080020#define PACKET_HOST 021#define TUNNEL_CSUM bpf_htons(0x01)22#define TUNNEL_KEY bpf_htons(0x04)23 24/* Only IPv4 address assigned to veth1.25 * 172.16.1.20026 */27#define ASSIGNED_ADDR_VETH1 0xac1001c828 29struct bpf_fou_encap___local {30 __be16 sport;31 __be16 dport;32} __attribute__((preserve_access_index));33 34enum bpf_fou_encap_type___local {35 FOU_BPF_ENCAP_FOU___local,36 FOU_BPF_ENCAP_GUE___local,37};38 39struct bpf_fou_encap;40 41int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx,42 struct bpf_fou_encap *encap, int type) __ksym;43int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,44 struct bpf_fou_encap *encap) __ksym;45struct xfrm_state *46bpf_xdp_get_xfrm_state(struct xdp_md *ctx, struct bpf_xfrm_state_opts *opts,47 u32 opts__sz) __ksym;48void bpf_xdp_xfrm_state_release(struct xfrm_state *x) __ksym;49 50struct {51 __uint(type, BPF_MAP_TYPE_ARRAY);52 __uint(max_entries, 1);53 __type(key, __u32);54 __type(value, __u32);55} local_ip_map SEC(".maps");56 57SEC("tc")58int gre_set_tunnel(struct __sk_buff *skb)59{60 int ret;61 struct bpf_tunnel_key key;62 63 __builtin_memset(&key, 0x0, sizeof(key));64 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */65 key.tunnel_id = 2;66 key.tunnel_tos = 0;67 key.tunnel_ttl = 64;68 69 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),70 BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);71 if (ret < 0) {72 log_err(ret);73 return TC_ACT_SHOT;74 }75 76 return TC_ACT_OK;77}78 79SEC("tc")80int gre_set_tunnel_no_key(struct __sk_buff *skb)81{82 int ret;83 struct bpf_tunnel_key key;84 85 __builtin_memset(&key, 0x0, sizeof(key));86 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */87 key.tunnel_ttl = 64;88 89 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),90 BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER |91 BPF_F_NO_TUNNEL_KEY);92 if (ret < 0) {93 log_err(ret);94 return TC_ACT_SHOT;95 }96 97 return TC_ACT_OK;98}99 100SEC("tc")101int gre_get_tunnel(struct __sk_buff *skb)102{103 int ret;104 struct bpf_tunnel_key key;105 106 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);107 if (ret < 0) {108 log_err(ret);109 return TC_ACT_SHOT;110 }111 112 bpf_printk("key %d remote ip 0x%x\n", key.tunnel_id, key.remote_ipv4);113 return TC_ACT_OK;114}115 116SEC("tc")117int ip6gretap_set_tunnel(struct __sk_buff *skb)118{119 struct bpf_tunnel_key key;120 int ret;121 122 __builtin_memset(&key, 0x0, sizeof(key));123 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */124 key.tunnel_id = 2;125 key.tunnel_tos = 0;126 key.tunnel_ttl = 64;127 key.tunnel_label = 0xabcde;128 129 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),130 BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |131 BPF_F_SEQ_NUMBER);132 if (ret < 0) {133 log_err(ret);134 return TC_ACT_SHOT;135 }136 137 return TC_ACT_OK;138}139 140SEC("tc")141int ip6gretap_get_tunnel(struct __sk_buff *skb)142{143 struct bpf_tunnel_key key;144 int ret;145 146 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),147 BPF_F_TUNINFO_IPV6);148 if (ret < 0) {149 log_err(ret);150 return TC_ACT_SHOT;151 }152 153 bpf_printk("key %d remote ip6 ::%x label %x\n",154 key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);155 156 return TC_ACT_OK;157}158 159SEC("tc")160int erspan_set_tunnel(struct __sk_buff *skb)161{162 struct bpf_tunnel_key key;163 struct erspan_metadata md;164 int ret;165 166 __builtin_memset(&key, 0x0, sizeof(key));167 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */168 key.tunnel_id = 2;169 key.tunnel_tos = 0;170 key.tunnel_ttl = 64;171 172 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),173 BPF_F_ZERO_CSUM_TX);174 if (ret < 0) {175 log_err(ret);176 return TC_ACT_SHOT;177 }178 179 __builtin_memset(&md, 0, sizeof(md));180#ifdef ERSPAN_V1181 md.version = 1;182 md.u.index = bpf_htonl(123);183#else184 __u8 direction = 1;185 __u8 hwid = 7;186 187 md.version = 2;188 BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction);189 BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf));190 BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3);191#endif192 193 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));194 if (ret < 0) {195 log_err(ret);196 return TC_ACT_SHOT;197 }198 199 return TC_ACT_OK;200}201 202SEC("tc")203int erspan_get_tunnel(struct __sk_buff *skb)204{205 struct bpf_tunnel_key key;206 struct erspan_metadata md;207 int ret;208 209 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);210 if (ret < 0) {211 log_err(ret);212 return TC_ACT_SHOT;213 }214 215 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));216 if (ret < 0) {217 log_err(ret);218 return TC_ACT_SHOT;219 }220 221 bpf_printk("key %d remote ip 0x%x erspan version %d\n",222 key.tunnel_id, key.remote_ipv4, md.version);223 224#ifdef ERSPAN_V1225 index = bpf_ntohl(md.u.index);226 bpf_printk("\tindex %x\n", index);227#else228 bpf_printk("\tdirection %d hwid %x timestamp %u\n",229 BPF_CORE_READ_BITFIELD(&md.u.md2, dir),230 (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) +231 BPF_CORE_READ_BITFIELD(&md.u.md2, hwid),232 bpf_ntohl(md.u.md2.timestamp));233#endif234 235 return TC_ACT_OK;236}237 238SEC("tc")239int ip4ip6erspan_set_tunnel(struct __sk_buff *skb)240{241 struct bpf_tunnel_key key;242 struct erspan_metadata md;243 int ret;244 245 __builtin_memset(&key, 0x0, sizeof(key));246 key.remote_ipv6[3] = bpf_htonl(0x11);247 key.tunnel_id = 2;248 key.tunnel_tos = 0;249 key.tunnel_ttl = 64;250 251 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),252 BPF_F_TUNINFO_IPV6);253 if (ret < 0) {254 log_err(ret);255 return TC_ACT_SHOT;256 }257 258 __builtin_memset(&md, 0, sizeof(md));259 260#ifdef ERSPAN_V1261 md.u.index = bpf_htonl(123);262 md.version = 1;263#else264 __u8 direction = 0;265 __u8 hwid = 17;266 267 md.version = 2;268 BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction);269 BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf));270 BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3);271#endif272 273 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));274 if (ret < 0) {275 log_err(ret);276 return TC_ACT_SHOT;277 }278 279 return TC_ACT_OK;280}281 282SEC("tc")283int ip4ip6erspan_get_tunnel(struct __sk_buff *skb)284{285 struct bpf_tunnel_key key;286 struct erspan_metadata md;287 int ret;288 289 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),290 BPF_F_TUNINFO_IPV6);291 if (ret < 0) {292 log_err(ret);293 return TC_ACT_SHOT;294 }295 296 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));297 if (ret < 0) {298 log_err(ret);299 return TC_ACT_SHOT;300 }301 302 bpf_printk("ip6erspan get key %d remote ip6 ::%x erspan version %d\n",303 key.tunnel_id, key.remote_ipv4, md.version);304 305#ifdef ERSPAN_V1306 index = bpf_ntohl(md.u.index);307 bpf_printk("\tindex %x\n", index);308#else309 bpf_printk("\tdirection %d hwid %x timestamp %u\n",310 BPF_CORE_READ_BITFIELD(&md.u.md2, dir),311 (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) +312 BPF_CORE_READ_BITFIELD(&md.u.md2, hwid),313 bpf_ntohl(md.u.md2.timestamp));314#endif315 316 return TC_ACT_OK;317}318 319SEC("tc")320int vxlan_set_tunnel_dst(struct __sk_buff *skb)321{322 struct bpf_tunnel_key key;323 struct vxlan_metadata md;324 __u32 index = 0;325 __u32 *local_ip = NULL;326 int ret = 0;327 328 local_ip = bpf_map_lookup_elem(&local_ip_map, &index);329 if (!local_ip) {330 log_err(ret);331 return TC_ACT_SHOT;332 }333 334 __builtin_memset(&key, 0x0, sizeof(key));335 key.local_ipv4 = 0xac100164; /* 172.16.1.100 */336 key.remote_ipv4 = *local_ip;337 key.tunnel_id = 2;338 key.tunnel_tos = 0;339 key.tunnel_ttl = 64;340 341 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),342 BPF_F_ZERO_CSUM_TX);343 if (ret < 0) {344 log_err(ret);345 return TC_ACT_SHOT;346 }347 348 md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */349 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));350 if (ret < 0) {351 log_err(ret);352 return TC_ACT_SHOT;353 }354 355 return TC_ACT_OK;356}357 358SEC("tc")359int vxlan_set_tunnel_src(struct __sk_buff *skb)360{361 struct bpf_tunnel_key key;362 struct vxlan_metadata md;363 __u32 index = 0;364 __u32 *local_ip = NULL;365 int ret = 0;366 367 local_ip = bpf_map_lookup_elem(&local_ip_map, &index);368 if (!local_ip) {369 log_err(ret);370 return TC_ACT_SHOT;371 }372 373 __builtin_memset(&key, 0x0, sizeof(key));374 key.local_ipv4 = *local_ip;375 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */376 key.tunnel_id = 2;377 key.tunnel_tos = 0;378 key.tunnel_ttl = 64;379 380 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),381 BPF_F_ZERO_CSUM_TX);382 if (ret < 0) {383 log_err(ret);384 return TC_ACT_SHOT;385 }386 387 md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */388 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));389 if (ret < 0) {390 log_err(ret);391 return TC_ACT_SHOT;392 }393 394 return TC_ACT_OK;395}396 397SEC("tc")398int vxlan_get_tunnel_src(struct __sk_buff *skb)399{400 int ret;401 struct bpf_tunnel_key key;402 struct vxlan_metadata md;403 404 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),405 BPF_F_TUNINFO_FLAGS);406 if (ret < 0) {407 log_err(ret);408 return TC_ACT_SHOT;409 }410 411 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));412 if (ret < 0) {413 log_err(ret);414 return TC_ACT_SHOT;415 }416 417 if (key.local_ipv4 != ASSIGNED_ADDR_VETH1 || md.gbp != 0x800FF ||418 !(key.tunnel_flags & TUNNEL_KEY) ||419 (key.tunnel_flags & TUNNEL_CSUM)) {420 bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x flags 0x%x\n",421 key.tunnel_id, key.local_ipv4,422 key.remote_ipv4, md.gbp,423 bpf_ntohs(key.tunnel_flags));424 log_err(ret);425 return TC_ACT_SHOT;426 }427 428 return TC_ACT_OK;429}430 431SEC("tc")432int veth_set_outer_dst(struct __sk_buff *skb)433{434 struct ethhdr *eth = (struct ethhdr *)(long)skb->data;435 __u32 assigned_ip = bpf_htonl(ASSIGNED_ADDR_VETH1);436 void *data_end = (void *)(long)skb->data_end;437 struct udphdr *udph;438 struct iphdr *iph;439 int ret = 0;440 __s64 csum;441 442 if ((void *)eth + sizeof(*eth) > data_end) {443 log_err(ret);444 return TC_ACT_SHOT;445 }446 447 if (eth->h_proto != bpf_htons(ETH_P_IP))448 return TC_ACT_OK;449 450 iph = (struct iphdr *)(eth + 1);451 if ((void *)iph + sizeof(*iph) > data_end) {452 log_err(ret);453 return TC_ACT_SHOT;454 }455 if (iph->protocol != IPPROTO_UDP)456 return TC_ACT_OK;457 458 udph = (struct udphdr *)(iph + 1);459 if ((void *)udph + sizeof(*udph) > data_end) {460 log_err(ret);461 return TC_ACT_SHOT;462 }463 if (udph->dest != bpf_htons(VXLAN_UDP_PORT))464 return TC_ACT_OK;465 466 if (iph->daddr != assigned_ip) {467 csum = bpf_csum_diff(&iph->daddr, sizeof(__u32), &assigned_ip,468 sizeof(__u32), 0);469 if (bpf_skb_store_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr),470 &assigned_ip, sizeof(__u32), 0) < 0) {471 log_err(ret);472 return TC_ACT_SHOT;473 }474 if (bpf_l3_csum_replace(skb, ETH_HLEN + offsetof(struct iphdr, check),475 0, csum, 0) < 0) {476 log_err(ret);477 return TC_ACT_SHOT;478 }479 bpf_skb_change_type(skb, PACKET_HOST);480 }481 return TC_ACT_OK;482}483 484SEC("tc")485int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb)486{487 struct bpf_tunnel_key key;488 __u32 index = 0;489 __u32 *local_ip;490 int ret = 0;491 492 local_ip = bpf_map_lookup_elem(&local_ip_map, &index);493 if (!local_ip) {494 log_err(ret);495 return TC_ACT_SHOT;496 }497 498 __builtin_memset(&key, 0x0, sizeof(key));499 key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */500 key.remote_ipv6[3] = bpf_htonl(*local_ip);501 key.tunnel_id = 22;502 key.tunnel_tos = 0;503 key.tunnel_ttl = 64;504 505 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),506 BPF_F_TUNINFO_IPV6);507 if (ret < 0) {508 log_err(ret);509 return TC_ACT_SHOT;510 }511 512 return TC_ACT_OK;513}514 515SEC("tc")516int ip6vxlan_set_tunnel_src(struct __sk_buff *skb)517{518 struct bpf_tunnel_key key;519 __u32 index = 0;520 __u32 *local_ip;521 int ret = 0;522 523 local_ip = bpf_map_lookup_elem(&local_ip_map, &index);524 if (!local_ip) {525 log_err(ret);526 return TC_ACT_SHOT;527 }528 529 __builtin_memset(&key, 0x0, sizeof(key));530 key.local_ipv6[3] = bpf_htonl(*local_ip);531 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */532 key.tunnel_id = 22;533 key.tunnel_tos = 0;534 key.tunnel_ttl = 64;535 536 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),537 BPF_F_TUNINFO_IPV6);538 if (ret < 0) {539 log_err(ret);540 return TC_ACT_SHOT;541 }542 543 return TC_ACT_OK;544}545 546SEC("tc")547int ip6vxlan_get_tunnel_src(struct __sk_buff *skb)548{549 struct bpf_tunnel_key key;550 __u32 index = 0;551 __u32 *local_ip;552 int ret = 0;553 554 local_ip = bpf_map_lookup_elem(&local_ip_map, &index);555 if (!local_ip) {556 log_err(ret);557 return TC_ACT_SHOT;558 }559 560 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),561 BPF_F_TUNINFO_IPV6 | BPF_F_TUNINFO_FLAGS);562 if (ret < 0) {563 log_err(ret);564 return TC_ACT_SHOT;565 }566 567 if (bpf_ntohl(key.local_ipv6[3]) != *local_ip ||568 !(key.tunnel_flags & TUNNEL_KEY) ||569 !(key.tunnel_flags & TUNNEL_CSUM)) {570 bpf_printk("ip6vxlan key %d local ip6 ::%x remote ip6 ::%x label 0x%x flags 0x%x\n",571 key.tunnel_id, bpf_ntohl(key.local_ipv6[3]),572 bpf_ntohl(key.remote_ipv6[3]), key.tunnel_label,573 bpf_ntohs(key.tunnel_flags));574 bpf_printk("local_ip 0x%x\n", *local_ip);575 log_err(ret);576 return TC_ACT_SHOT;577 }578 579 return TC_ACT_OK;580}581 582struct local_geneve_opt {583 struct geneve_opt gopt;584 int data;585};586 587SEC("tc")588int geneve_set_tunnel(struct __sk_buff *skb)589{590 int ret;591 struct bpf_tunnel_key key;592 struct local_geneve_opt local_gopt;593 struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt;594 595 __builtin_memset(&key, 0x0, sizeof(key));596 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */597 key.tunnel_id = 2;598 key.tunnel_tos = 0;599 key.tunnel_ttl = 64;600 601 __builtin_memset(gopt, 0x0, sizeof(local_gopt));602 gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */603 gopt->type = 0x08;604 gopt->r1 = 0;605 gopt->r2 = 0;606 gopt->r3 = 0;607 gopt->length = 2; /* 4-byte multiple */608 *(int *) &gopt->opt_data = bpf_htonl(0xdeadbeef);609 610 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),611 BPF_F_ZERO_CSUM_TX);612 if (ret < 0) {613 log_err(ret);614 return TC_ACT_SHOT;615 }616 617 ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(local_gopt));618 if (ret < 0) {619 log_err(ret);620 return TC_ACT_SHOT;621 }622 623 return TC_ACT_OK;624}625 626SEC("tc")627int geneve_get_tunnel(struct __sk_buff *skb)628{629 int ret;630 struct bpf_tunnel_key key;631 struct geneve_opt gopt;632 633 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);634 if (ret < 0) {635 log_err(ret);636 return TC_ACT_SHOT;637 }638 639 ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));640 if (ret < 0)641 gopt.opt_class = 0;642 643 bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",644 key.tunnel_id, key.remote_ipv4, gopt.opt_class);645 return TC_ACT_OK;646}647 648SEC("tc")649int ip6geneve_set_tunnel(struct __sk_buff *skb)650{651 struct bpf_tunnel_key key;652 struct local_geneve_opt local_gopt;653 struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt;654 int ret;655 656 __builtin_memset(&key, 0x0, sizeof(key));657 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */658 key.tunnel_id = 22;659 key.tunnel_tos = 0;660 key.tunnel_ttl = 64;661 662 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),663 BPF_F_TUNINFO_IPV6);664 if (ret < 0) {665 log_err(ret);666 return TC_ACT_SHOT;667 }668 669 __builtin_memset(gopt, 0x0, sizeof(local_gopt));670 gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */671 gopt->type = 0x08;672 gopt->r1 = 0;673 gopt->r2 = 0;674 gopt->r3 = 0;675 gopt->length = 2; /* 4-byte multiple */676 *(int *) &gopt->opt_data = bpf_htonl(0xfeedbeef);677 678 ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(gopt));679 if (ret < 0) {680 log_err(ret);681 return TC_ACT_SHOT;682 }683 684 return TC_ACT_OK;685}686 687SEC("tc")688int ip6geneve_get_tunnel(struct __sk_buff *skb)689{690 struct bpf_tunnel_key key;691 struct geneve_opt gopt;692 int ret;693 694 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),695 BPF_F_TUNINFO_IPV6);696 if (ret < 0) {697 log_err(ret);698 return TC_ACT_SHOT;699 }700 701 ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));702 if (ret < 0)703 gopt.opt_class = 0;704 705 bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",706 key.tunnel_id, key.remote_ipv4, gopt.opt_class);707 708 return TC_ACT_OK;709}710 711SEC("tc")712int ipip_set_tunnel(struct __sk_buff *skb)713{714 struct bpf_tunnel_key key = {};715 void *data = (void *)(long)skb->data;716 struct iphdr *iph = data;717 void *data_end = (void *)(long)skb->data_end;718 int ret;719 720 /* single length check */721 if (data + sizeof(*iph) > data_end) {722 log_err(1);723 return TC_ACT_SHOT;724 }725 726 key.tunnel_ttl = 64;727 if (iph->protocol == IPPROTO_ICMP) {728 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */729 }730 731 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);732 if (ret < 0) {733 log_err(ret);734 return TC_ACT_SHOT;735 }736 737 return TC_ACT_OK;738}739 740SEC("tc")741int ipip_get_tunnel(struct __sk_buff *skb)742{743 int ret;744 struct bpf_tunnel_key key;745 746 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);747 if (ret < 0) {748 log_err(ret);749 return TC_ACT_SHOT;750 }751 752 bpf_printk("remote ip 0x%x\n", key.remote_ipv4);753 return TC_ACT_OK;754}755 756SEC("tc")757int ipip_gue_set_tunnel(struct __sk_buff *skb)758{759 struct bpf_tunnel_key key = {};760 struct bpf_fou_encap___local encap = {};761 void *data = (void *)(long)skb->data;762 struct iphdr *iph = data;763 void *data_end = (void *)(long)skb->data_end;764 int ret;765 766 if (data + sizeof(*iph) > data_end) {767 log_err(1);768 return TC_ACT_SHOT;769 }770 771 key.tunnel_ttl = 64;772 if (iph->protocol == IPPROTO_ICMP)773 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */774 775 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);776 if (ret < 0) {777 log_err(ret);778 return TC_ACT_SHOT;779 }780 781 encap.sport = 0;782 encap.dport = bpf_htons(5555);783 784 ret = bpf_skb_set_fou_encap(skb, (struct bpf_fou_encap *)&encap,785 bpf_core_enum_value(enum bpf_fou_encap_type___local,786 FOU_BPF_ENCAP_GUE___local));787 if (ret < 0) {788 log_err(ret);789 return TC_ACT_SHOT;790 }791 792 return TC_ACT_OK;793}794 795SEC("tc")796int ipip_fou_set_tunnel(struct __sk_buff *skb)797{798 struct bpf_tunnel_key key = {};799 struct bpf_fou_encap___local encap = {};800 void *data = (void *)(long)skb->data;801 struct iphdr *iph = data;802 void *data_end = (void *)(long)skb->data_end;803 int ret;804 805 if (data + sizeof(*iph) > data_end) {806 log_err(1);807 return TC_ACT_SHOT;808 }809 810 key.tunnel_ttl = 64;811 if (iph->protocol == IPPROTO_ICMP)812 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */813 814 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);815 if (ret < 0) {816 log_err(ret);817 return TC_ACT_SHOT;818 }819 820 encap.sport = 0;821 encap.dport = bpf_htons(5555);822 823 ret = bpf_skb_set_fou_encap(skb, (struct bpf_fou_encap *)&encap,824 FOU_BPF_ENCAP_FOU___local);825 if (ret < 0) {826 log_err(ret);827 return TC_ACT_SHOT;828 }829 830 return TC_ACT_OK;831}832 833SEC("tc")834int ipip_encap_get_tunnel(struct __sk_buff *skb)835{836 int ret;837 struct bpf_tunnel_key key = {};838 struct bpf_fou_encap___local encap = {};839 840 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);841 if (ret < 0) {842 log_err(ret);843 return TC_ACT_SHOT;844 }845 846 ret = bpf_skb_get_fou_encap(skb, (struct bpf_fou_encap *)&encap);847 if (ret < 0) {848 log_err(ret);849 return TC_ACT_SHOT;850 }851 852 if (bpf_ntohs(encap.dport) != 5555)853 return TC_ACT_SHOT;854 855 bpf_printk("%d remote ip 0x%x, sport %d, dport %d\n", ret,856 key.remote_ipv4, bpf_ntohs(encap.sport),857 bpf_ntohs(encap.dport));858 return TC_ACT_OK;859}860 861SEC("tc")862int ipip6_set_tunnel(struct __sk_buff *skb)863{864 struct bpf_tunnel_key key = {};865 void *data = (void *)(long)skb->data;866 struct iphdr *iph = data;867 void *data_end = (void *)(long)skb->data_end;868 int ret;869 870 /* single length check */871 if (data + sizeof(*iph) > data_end) {872 log_err(1);873 return TC_ACT_SHOT;874 }875 876 __builtin_memset(&key, 0x0, sizeof(key));877 key.tunnel_ttl = 64;878 if (iph->protocol == IPPROTO_ICMP) {879 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */880 }881 882 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),883 BPF_F_TUNINFO_IPV6);884 if (ret < 0) {885 log_err(ret);886 return TC_ACT_SHOT;887 }888 889 return TC_ACT_OK;890}891 892SEC("tc")893int ipip6_get_tunnel(struct __sk_buff *skb)894{895 int ret;896 struct bpf_tunnel_key key;897 898 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),899 BPF_F_TUNINFO_IPV6);900 if (ret < 0) {901 log_err(ret);902 return TC_ACT_SHOT;903 }904 905 bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),906 bpf_htonl(key.remote_ipv6[3]));907 return TC_ACT_OK;908}909 910SEC("tc")911int ip6ip6_set_tunnel(struct __sk_buff *skb)912{913 struct bpf_tunnel_key key = {};914 void *data = (void *)(long)skb->data;915 struct ipv6hdr *iph = data;916 void *data_end = (void *)(long)skb->data_end;917 int ret;918 919 /* single length check */920 if (data + sizeof(*iph) > data_end) {921 log_err(1);922 return TC_ACT_SHOT;923 }924 925 key.tunnel_ttl = 64;926 if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {927 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */928 }929 930 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),931 BPF_F_TUNINFO_IPV6);932 if (ret < 0) {933 log_err(ret);934 return TC_ACT_SHOT;935 }936 937 return TC_ACT_OK;938}939 940SEC("tc")941int ip6ip6_get_tunnel(struct __sk_buff *skb)942{943 int ret;944 struct bpf_tunnel_key key;945 946 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),947 BPF_F_TUNINFO_IPV6);948 if (ret < 0) {949 log_err(ret);950 return TC_ACT_SHOT;951 }952 953 bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),954 bpf_htonl(key.remote_ipv6[3]));955 return TC_ACT_OK;956}957 958volatile int xfrm_reqid = 0;959volatile int xfrm_spi = 0;960volatile int xfrm_remote_ip = 0;961 962SEC("tc")963int xfrm_get_state(struct __sk_buff *skb)964{965 struct bpf_xfrm_state x;966 int ret;967 968 ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);969 if (ret < 0)970 return TC_ACT_OK;971 972 xfrm_reqid = x.reqid;973 xfrm_spi = bpf_ntohl(x.spi);974 xfrm_remote_ip = bpf_ntohl(x.remote_ipv4);975 976 return TC_ACT_OK;977}978 979volatile int xfrm_replay_window = 0;980 981SEC("xdp")982int xfrm_get_state_xdp(struct xdp_md *xdp)983{984 struct bpf_xfrm_state_opts opts = {};985 struct xfrm_state *x = NULL;986 struct ip_esp_hdr *esph;987 struct bpf_dynptr ptr;988 u8 esph_buf[8] = {};989 u8 iph_buf[20] = {};990 struct iphdr *iph;991 u32 off;992 993 if (bpf_dynptr_from_xdp(xdp, 0, &ptr))994 goto out;995 996 off = sizeof(struct ethhdr);997 iph = bpf_dynptr_slice(&ptr, off, iph_buf, sizeof(iph_buf));998 if (!iph || iph->protocol != IPPROTO_ESP)999 goto out;1000 1001 off += sizeof(struct iphdr);1002 esph = bpf_dynptr_slice(&ptr, off, esph_buf, sizeof(esph_buf));1003 if (!esph)1004 goto out;1005 1006 opts.netns_id = BPF_F_CURRENT_NETNS;1007 opts.daddr.a4 = iph->daddr;1008 opts.spi = esph->spi;1009 opts.proto = IPPROTO_ESP;1010 opts.family = AF_INET;1011 1012 x = bpf_xdp_get_xfrm_state(xdp, &opts, sizeof(opts));1013 if (!x)1014 goto out;1015 1016 if (!x->replay_esn)1017 goto out;1018 1019 xfrm_replay_window = x->replay_esn->replay_window;1020out:1021 if (x)1022 bpf_xdp_xfrm_state_release(x);1023 return XDP_PASS;1024}1025 1026char _license[] SEC("license") = "GPL";1027