1bd4aed0eSJiong Wang // SPDX-License-Identifier: GPL-2.0 2bd4aed0eSJiong Wang /* Copyright (c) 2016 VMware 3bd4aed0eSJiong Wang * Copyright (c) 2016 Facebook 4bd4aed0eSJiong Wang * 5bd4aed0eSJiong Wang * This program is free software; you can redistribute it and/or 6bd4aed0eSJiong Wang * modify it under the terms of version 2 of the GNU General Public 7bd4aed0eSJiong Wang * License as published by the Free Software Foundation. 8bd4aed0eSJiong Wang */ 902b4e126SDaniel Xu #include "vmlinux.h" 1002b4e126SDaniel Xu #include <bpf/bpf_core_read.h> 113e689141SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h> 123e689141SToke Høiland-Jørgensen #include <bpf/bpf_endian.h> 1302b4e126SDaniel Xu #include "bpf_kfuncs.h" 1402b4e126SDaniel Xu #include "bpf_tracing_net.h" 15bd4aed0eSJiong Wang 1671b2ec21SKaixi Fan #define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret) 17bd4aed0eSJiong Wang 181115169fSPaul Chaignon #define VXLAN_UDP_PORT 4789 1902b4e126SDaniel Xu #define ETH_P_IP 0x0800 2002b4e126SDaniel Xu #define PACKET_HOST 0 2102b4e126SDaniel Xu #define TUNNEL_CSUM bpf_htons(0x01) 2202b4e126SDaniel Xu #define TUNNEL_KEY bpf_htons(0x04) 231115169fSPaul Chaignon 241115169fSPaul Chaignon /* Only IPv4 address assigned to veth1. 251115169fSPaul Chaignon * 172.16.1.200 261115169fSPaul Chaignon */ 271115169fSPaul Chaignon #define ASSIGNED_ADDR_VETH1 0xac1001c8 281115169fSPaul Chaignon 29d9688f89SChristian Ehrig int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx, 30d9688f89SChristian Ehrig struct bpf_fou_encap *encap, int type) __ksym; 31d9688f89SChristian Ehrig int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx, 32d9688f89SChristian Ehrig struct bpf_fou_encap *encap) __ksym; 332cd07b0eSDaniel Xu struct xfrm_state * 342cd07b0eSDaniel Xu bpf_xdp_get_xfrm_state(struct xdp_md *ctx, struct bpf_xfrm_state_opts *opts, 352cd07b0eSDaniel Xu u32 opts__sz) __ksym; 362cd07b0eSDaniel Xu void bpf_xdp_xfrm_state_release(struct xfrm_state *x) __ksym; 37d9688f89SChristian Ehrig 381ee7efd4SKaixi Fan struct { 391ee7efd4SKaixi Fan __uint(type, BPF_MAP_TYPE_ARRAY); 401ee7efd4SKaixi Fan __uint(max_entries, 1); 411ee7efd4SKaixi Fan __type(key, __u32); 421ee7efd4SKaixi Fan __type(value, __u32); 431ee7efd4SKaixi Fan } local_ip_map SEC(".maps"); 441ee7efd4SKaixi Fan 451ee7efd4SKaixi Fan SEC("tc") 461ee7efd4SKaixi Fan int gre_set_tunnel(struct __sk_buff *skb) 47bd4aed0eSJiong Wang { 48bd4aed0eSJiong Wang int ret; 49bd4aed0eSJiong Wang struct bpf_tunnel_key key; 50bd4aed0eSJiong Wang 51bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 52bd4aed0eSJiong Wang key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 53bd4aed0eSJiong Wang key.tunnel_id = 2; 54bd4aed0eSJiong Wang key.tunnel_tos = 0; 55bd4aed0eSJiong Wang key.tunnel_ttl = 64; 56bd4aed0eSJiong Wang 57bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 58bd4aed0eSJiong Wang BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER); 59bd4aed0eSJiong Wang if (ret < 0) { 6071b2ec21SKaixi Fan log_err(ret); 61bd4aed0eSJiong Wang return TC_ACT_SHOT; 62bd4aed0eSJiong Wang } 63bd4aed0eSJiong Wang 64bd4aed0eSJiong Wang return TC_ACT_OK; 65bd4aed0eSJiong Wang } 66bd4aed0eSJiong Wang 671ee7efd4SKaixi Fan SEC("tc") 68ac6e45e0SChristian Ehrig int gre_set_tunnel_no_key(struct __sk_buff *skb) 69ac6e45e0SChristian Ehrig { 70ac6e45e0SChristian Ehrig int ret; 71ac6e45e0SChristian Ehrig struct bpf_tunnel_key key; 72ac6e45e0SChristian Ehrig 73ac6e45e0SChristian Ehrig __builtin_memset(&key, 0x0, sizeof(key)); 74ac6e45e0SChristian Ehrig key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 75ac6e45e0SChristian Ehrig key.tunnel_ttl = 64; 76ac6e45e0SChristian Ehrig 77ac6e45e0SChristian Ehrig ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 78ac6e45e0SChristian Ehrig BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER | 79ac6e45e0SChristian Ehrig BPF_F_NO_TUNNEL_KEY); 80ac6e45e0SChristian Ehrig if (ret < 0) { 81ac6e45e0SChristian Ehrig log_err(ret); 82ac6e45e0SChristian Ehrig return TC_ACT_SHOT; 83ac6e45e0SChristian Ehrig } 84ac6e45e0SChristian Ehrig 85ac6e45e0SChristian Ehrig return TC_ACT_OK; 86ac6e45e0SChristian Ehrig } 87ac6e45e0SChristian Ehrig 88ac6e45e0SChristian Ehrig SEC("tc") 891ee7efd4SKaixi Fan int gre_get_tunnel(struct __sk_buff *skb) 90bd4aed0eSJiong Wang { 91bd4aed0eSJiong Wang int ret; 92bd4aed0eSJiong Wang struct bpf_tunnel_key key; 93bd4aed0eSJiong Wang 94bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 95bd4aed0eSJiong Wang if (ret < 0) { 9671b2ec21SKaixi Fan log_err(ret); 97bd4aed0eSJiong Wang return TC_ACT_SHOT; 98bd4aed0eSJiong Wang } 99bd4aed0eSJiong Wang 10071b2ec21SKaixi Fan bpf_printk("key %d remote ip 0x%x\n", key.tunnel_id, key.remote_ipv4); 101bd4aed0eSJiong Wang return TC_ACT_OK; 102bd4aed0eSJiong Wang } 103bd4aed0eSJiong Wang 1041ee7efd4SKaixi Fan SEC("tc") 1051ee7efd4SKaixi Fan int ip6gretap_set_tunnel(struct __sk_buff *skb) 106bd4aed0eSJiong Wang { 107bd4aed0eSJiong Wang struct bpf_tunnel_key key; 108bd4aed0eSJiong Wang int ret; 109bd4aed0eSJiong Wang 110bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 111bd4aed0eSJiong Wang key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 112bd4aed0eSJiong Wang key.tunnel_id = 2; 113bd4aed0eSJiong Wang key.tunnel_tos = 0; 114bd4aed0eSJiong Wang key.tunnel_ttl = 64; 115bd4aed0eSJiong Wang key.tunnel_label = 0xabcde; 116bd4aed0eSJiong Wang 117bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 118bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX | 119bd4aed0eSJiong Wang BPF_F_SEQ_NUMBER); 120bd4aed0eSJiong Wang if (ret < 0) { 12171b2ec21SKaixi Fan log_err(ret); 122bd4aed0eSJiong Wang return TC_ACT_SHOT; 123bd4aed0eSJiong Wang } 124bd4aed0eSJiong Wang 125bd4aed0eSJiong Wang return TC_ACT_OK; 126bd4aed0eSJiong Wang } 127bd4aed0eSJiong Wang 1281ee7efd4SKaixi Fan SEC("tc") 1291ee7efd4SKaixi Fan int ip6gretap_get_tunnel(struct __sk_buff *skb) 130bd4aed0eSJiong Wang { 131bd4aed0eSJiong Wang struct bpf_tunnel_key key; 132bd4aed0eSJiong Wang int ret; 133bd4aed0eSJiong Wang 134bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 135bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 136bd4aed0eSJiong Wang if (ret < 0) { 13771b2ec21SKaixi Fan log_err(ret); 138bd4aed0eSJiong Wang return TC_ACT_SHOT; 139bd4aed0eSJiong Wang } 140bd4aed0eSJiong Wang 14171b2ec21SKaixi Fan bpf_printk("key %d remote ip6 ::%x label %x\n", 142bd4aed0eSJiong Wang key.tunnel_id, key.remote_ipv6[3], key.tunnel_label); 143bd4aed0eSJiong Wang 144bd4aed0eSJiong Wang return TC_ACT_OK; 145bd4aed0eSJiong Wang } 146bd4aed0eSJiong Wang 1471ee7efd4SKaixi Fan SEC("tc") 1481ee7efd4SKaixi Fan int erspan_set_tunnel(struct __sk_buff *skb) 149bd4aed0eSJiong Wang { 150bd4aed0eSJiong Wang struct bpf_tunnel_key key; 151bd4aed0eSJiong Wang struct erspan_metadata md; 152bd4aed0eSJiong Wang int ret; 153bd4aed0eSJiong Wang 154bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 155bd4aed0eSJiong Wang key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 156bd4aed0eSJiong Wang key.tunnel_id = 2; 157bd4aed0eSJiong Wang key.tunnel_tos = 0; 158bd4aed0eSJiong Wang key.tunnel_ttl = 64; 159bd4aed0eSJiong Wang 160bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 161bd4aed0eSJiong Wang BPF_F_ZERO_CSUM_TX); 162bd4aed0eSJiong Wang if (ret < 0) { 16371b2ec21SKaixi Fan log_err(ret); 164bd4aed0eSJiong Wang return TC_ACT_SHOT; 165bd4aed0eSJiong Wang } 166bd4aed0eSJiong Wang 167bd4aed0eSJiong Wang __builtin_memset(&md, 0, sizeof(md)); 168bd4aed0eSJiong Wang #ifdef ERSPAN_V1 169bd4aed0eSJiong Wang md.version = 1; 170bd4aed0eSJiong Wang md.u.index = bpf_htonl(123); 171bd4aed0eSJiong Wang #else 172bd4aed0eSJiong Wang __u8 direction = 1; 173bd4aed0eSJiong Wang __u8 hwid = 7; 174bd4aed0eSJiong Wang 175bd4aed0eSJiong Wang md.version = 2; 17602b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction); 17702b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf)); 17802b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3); 179bd4aed0eSJiong Wang #endif 180bd4aed0eSJiong Wang 181bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); 182bd4aed0eSJiong Wang if (ret < 0) { 18371b2ec21SKaixi Fan log_err(ret); 184bd4aed0eSJiong Wang return TC_ACT_SHOT; 185bd4aed0eSJiong Wang } 186bd4aed0eSJiong Wang 187bd4aed0eSJiong Wang return TC_ACT_OK; 188bd4aed0eSJiong Wang } 189bd4aed0eSJiong Wang 1901ee7efd4SKaixi Fan SEC("tc") 1911ee7efd4SKaixi Fan int erspan_get_tunnel(struct __sk_buff *skb) 192bd4aed0eSJiong Wang { 193bd4aed0eSJiong Wang struct bpf_tunnel_key key; 194bd4aed0eSJiong Wang struct erspan_metadata md; 195bd4aed0eSJiong Wang int ret; 196bd4aed0eSJiong Wang 197bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 198bd4aed0eSJiong Wang if (ret < 0) { 19971b2ec21SKaixi Fan log_err(ret); 200bd4aed0eSJiong Wang return TC_ACT_SHOT; 201bd4aed0eSJiong Wang } 202bd4aed0eSJiong Wang 203bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); 204bd4aed0eSJiong Wang if (ret < 0) { 20571b2ec21SKaixi Fan log_err(ret); 206bd4aed0eSJiong Wang return TC_ACT_SHOT; 207bd4aed0eSJiong Wang } 208bd4aed0eSJiong Wang 20971b2ec21SKaixi Fan bpf_printk("key %d remote ip 0x%x erspan version %d\n", 210bd4aed0eSJiong Wang key.tunnel_id, key.remote_ipv4, md.version); 211bd4aed0eSJiong Wang 212bd4aed0eSJiong Wang #ifdef ERSPAN_V1 213bd4aed0eSJiong Wang index = bpf_ntohl(md.u.index); 21471b2ec21SKaixi Fan bpf_printk("\tindex %x\n", index); 215bd4aed0eSJiong Wang #else 21671b2ec21SKaixi Fan bpf_printk("\tdirection %d hwid %x timestamp %u\n", 21702b4e126SDaniel Xu BPF_CORE_READ_BITFIELD(&md.u.md2, dir), 21802b4e126SDaniel Xu (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) + 21902b4e126SDaniel Xu BPF_CORE_READ_BITFIELD(&md.u.md2, hwid), 220bd4aed0eSJiong Wang bpf_ntohl(md.u.md2.timestamp)); 221bd4aed0eSJiong Wang #endif 222bd4aed0eSJiong Wang 223bd4aed0eSJiong Wang return TC_ACT_OK; 224bd4aed0eSJiong Wang } 225bd4aed0eSJiong Wang 2261ee7efd4SKaixi Fan SEC("tc") 2271ee7efd4SKaixi Fan int ip4ip6erspan_set_tunnel(struct __sk_buff *skb) 228bd4aed0eSJiong Wang { 229bd4aed0eSJiong Wang struct bpf_tunnel_key key; 230bd4aed0eSJiong Wang struct erspan_metadata md; 231bd4aed0eSJiong Wang int ret; 232bd4aed0eSJiong Wang 233bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 234bd4aed0eSJiong Wang key.remote_ipv6[3] = bpf_htonl(0x11); 235bd4aed0eSJiong Wang key.tunnel_id = 2; 236bd4aed0eSJiong Wang key.tunnel_tos = 0; 237bd4aed0eSJiong Wang key.tunnel_ttl = 64; 238bd4aed0eSJiong Wang 239bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 240bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 241bd4aed0eSJiong Wang if (ret < 0) { 24271b2ec21SKaixi Fan log_err(ret); 243bd4aed0eSJiong Wang return TC_ACT_SHOT; 244bd4aed0eSJiong Wang } 245bd4aed0eSJiong Wang 246bd4aed0eSJiong Wang __builtin_memset(&md, 0, sizeof(md)); 247bd4aed0eSJiong Wang 248bd4aed0eSJiong Wang #ifdef ERSPAN_V1 249bd4aed0eSJiong Wang md.u.index = bpf_htonl(123); 250bd4aed0eSJiong Wang md.version = 1; 251bd4aed0eSJiong Wang #else 252bd4aed0eSJiong Wang __u8 direction = 0; 253bd4aed0eSJiong Wang __u8 hwid = 17; 254bd4aed0eSJiong Wang 255bd4aed0eSJiong Wang md.version = 2; 25602b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction); 25702b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf)); 25802b4e126SDaniel Xu BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3); 259bd4aed0eSJiong Wang #endif 260bd4aed0eSJiong Wang 261bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); 262bd4aed0eSJiong Wang if (ret < 0) { 26371b2ec21SKaixi Fan log_err(ret); 264bd4aed0eSJiong Wang return TC_ACT_SHOT; 265bd4aed0eSJiong Wang } 266bd4aed0eSJiong Wang 267bd4aed0eSJiong Wang return TC_ACT_OK; 268bd4aed0eSJiong Wang } 269bd4aed0eSJiong Wang 2701ee7efd4SKaixi Fan SEC("tc") 2711ee7efd4SKaixi Fan int ip4ip6erspan_get_tunnel(struct __sk_buff *skb) 272bd4aed0eSJiong Wang { 273bd4aed0eSJiong Wang struct bpf_tunnel_key key; 274bd4aed0eSJiong Wang struct erspan_metadata md; 275bd4aed0eSJiong Wang int ret; 276bd4aed0eSJiong Wang 277bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 278bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 279bd4aed0eSJiong Wang if (ret < 0) { 28071b2ec21SKaixi Fan log_err(ret); 281bd4aed0eSJiong Wang return TC_ACT_SHOT; 282bd4aed0eSJiong Wang } 283bd4aed0eSJiong Wang 284bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); 285bd4aed0eSJiong Wang if (ret < 0) { 28671b2ec21SKaixi Fan log_err(ret); 287bd4aed0eSJiong Wang return TC_ACT_SHOT; 288bd4aed0eSJiong Wang } 289bd4aed0eSJiong Wang 29071b2ec21SKaixi Fan bpf_printk("ip6erspan get key %d remote ip6 ::%x erspan version %d\n", 291bd4aed0eSJiong Wang key.tunnel_id, key.remote_ipv4, md.version); 292bd4aed0eSJiong Wang 293bd4aed0eSJiong Wang #ifdef ERSPAN_V1 294bd4aed0eSJiong Wang index = bpf_ntohl(md.u.index); 29571b2ec21SKaixi Fan bpf_printk("\tindex %x\n", index); 296bd4aed0eSJiong Wang #else 29771b2ec21SKaixi Fan bpf_printk("\tdirection %d hwid %x timestamp %u\n", 29802b4e126SDaniel Xu BPF_CORE_READ_BITFIELD(&md.u.md2, dir), 29902b4e126SDaniel Xu (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) + 30002b4e126SDaniel Xu BPF_CORE_READ_BITFIELD(&md.u.md2, hwid), 301bd4aed0eSJiong Wang bpf_ntohl(md.u.md2.timestamp)); 302bd4aed0eSJiong Wang #endif 303bd4aed0eSJiong Wang 304bd4aed0eSJiong Wang return TC_ACT_OK; 305bd4aed0eSJiong Wang } 306bd4aed0eSJiong Wang 3071ee7efd4SKaixi Fan SEC("tc") 3081ee7efd4SKaixi Fan int vxlan_set_tunnel_dst(struct __sk_buff *skb) 309bd4aed0eSJiong Wang { 310bd4aed0eSJiong Wang struct bpf_tunnel_key key; 311bd4aed0eSJiong Wang struct vxlan_metadata md; 3121ee7efd4SKaixi Fan __u32 index = 0; 3131ee7efd4SKaixi Fan __u32 *local_ip = NULL; 314ec97a76fSDave Marchevsky int ret = 0; 3151ee7efd4SKaixi Fan 3161ee7efd4SKaixi Fan local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 3171ee7efd4SKaixi Fan if (!local_ip) { 3181ee7efd4SKaixi Fan log_err(ret); 3191ee7efd4SKaixi Fan return TC_ACT_SHOT; 3201ee7efd4SKaixi Fan } 321bd4aed0eSJiong Wang 322bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 3231ee7efd4SKaixi Fan key.local_ipv4 = 0xac100164; /* 172.16.1.100 */ 3241ee7efd4SKaixi Fan key.remote_ipv4 = *local_ip; 3251ee7efd4SKaixi Fan key.tunnel_id = 2; 3261ee7efd4SKaixi Fan key.tunnel_tos = 0; 3271ee7efd4SKaixi Fan key.tunnel_ttl = 64; 3281ee7efd4SKaixi Fan 3291ee7efd4SKaixi Fan ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 3301ee7efd4SKaixi Fan BPF_F_ZERO_CSUM_TX); 3311ee7efd4SKaixi Fan if (ret < 0) { 3321ee7efd4SKaixi Fan log_err(ret); 3331ee7efd4SKaixi Fan return TC_ACT_SHOT; 3341ee7efd4SKaixi Fan } 3351ee7efd4SKaixi Fan 3361ee7efd4SKaixi Fan md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */ 3371ee7efd4SKaixi Fan ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); 3381ee7efd4SKaixi Fan if (ret < 0) { 3391ee7efd4SKaixi Fan log_err(ret); 3401ee7efd4SKaixi Fan return TC_ACT_SHOT; 3411ee7efd4SKaixi Fan } 3421ee7efd4SKaixi Fan 3431ee7efd4SKaixi Fan return TC_ACT_OK; 3441ee7efd4SKaixi Fan } 3451ee7efd4SKaixi Fan 3461ee7efd4SKaixi Fan SEC("tc") 3471ee7efd4SKaixi Fan int vxlan_set_tunnel_src(struct __sk_buff *skb) 3481ee7efd4SKaixi Fan { 3491ee7efd4SKaixi Fan struct bpf_tunnel_key key; 3501ee7efd4SKaixi Fan struct vxlan_metadata md; 3511ee7efd4SKaixi Fan __u32 index = 0; 3521ee7efd4SKaixi Fan __u32 *local_ip = NULL; 353ec97a76fSDave Marchevsky int ret = 0; 3541ee7efd4SKaixi Fan 3551ee7efd4SKaixi Fan local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 3561ee7efd4SKaixi Fan if (!local_ip) { 35771b2ec21SKaixi Fan log_err(ret); 3581ee7efd4SKaixi Fan return TC_ACT_SHOT; 3591ee7efd4SKaixi Fan } 3601ee7efd4SKaixi Fan 3611ee7efd4SKaixi Fan __builtin_memset(&key, 0x0, sizeof(key)); 3621ee7efd4SKaixi Fan key.local_ipv4 = *local_ip; 363bd4aed0eSJiong Wang key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 364bd4aed0eSJiong Wang key.tunnel_id = 2; 365bd4aed0eSJiong Wang key.tunnel_tos = 0; 366bd4aed0eSJiong Wang key.tunnel_ttl = 64; 367bd4aed0eSJiong Wang 368bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 369bd4aed0eSJiong Wang BPF_F_ZERO_CSUM_TX); 370bd4aed0eSJiong Wang if (ret < 0) { 37171b2ec21SKaixi Fan log_err(ret); 372bd4aed0eSJiong Wang return TC_ACT_SHOT; 373bd4aed0eSJiong Wang } 374bd4aed0eSJiong Wang 375bd4aed0eSJiong Wang md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */ 376bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); 377bd4aed0eSJiong Wang if (ret < 0) { 37871b2ec21SKaixi Fan log_err(ret); 379bd4aed0eSJiong Wang return TC_ACT_SHOT; 380bd4aed0eSJiong Wang } 381bd4aed0eSJiong Wang 382bd4aed0eSJiong Wang return TC_ACT_OK; 383bd4aed0eSJiong Wang } 384bd4aed0eSJiong Wang 3851ee7efd4SKaixi Fan SEC("tc") 3861ee7efd4SKaixi Fan int vxlan_get_tunnel_src(struct __sk_buff *skb) 387bd4aed0eSJiong Wang { 388bd4aed0eSJiong Wang int ret; 389bd4aed0eSJiong Wang struct bpf_tunnel_key key; 390bd4aed0eSJiong Wang struct vxlan_metadata md; 391bd4aed0eSJiong Wang 3928cc61b7aSShmulik Ladkani ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 3938cc61b7aSShmulik Ladkani BPF_F_TUNINFO_FLAGS); 394bd4aed0eSJiong Wang if (ret < 0) { 39571b2ec21SKaixi Fan log_err(ret); 396bd4aed0eSJiong Wang return TC_ACT_SHOT; 397bd4aed0eSJiong Wang } 398bd4aed0eSJiong Wang 399bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); 400bd4aed0eSJiong Wang if (ret < 0) { 40171b2ec21SKaixi Fan log_err(ret); 402bd4aed0eSJiong Wang return TC_ACT_SHOT; 403bd4aed0eSJiong Wang } 404bd4aed0eSJiong Wang 4058cc61b7aSShmulik Ladkani if (key.local_ipv4 != ASSIGNED_ADDR_VETH1 || md.gbp != 0x800FF || 4068cc61b7aSShmulik Ladkani !(key.tunnel_flags & TUNNEL_KEY) || 4078cc61b7aSShmulik Ladkani (key.tunnel_flags & TUNNEL_CSUM)) { 4088cc61b7aSShmulik Ladkani bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x flags 0x%x\n", 4091ee7efd4SKaixi Fan key.tunnel_id, key.local_ipv4, 4108cc61b7aSShmulik Ladkani key.remote_ipv4, md.gbp, 4118cc61b7aSShmulik Ladkani bpf_ntohs(key.tunnel_flags)); 4121ee7efd4SKaixi Fan log_err(ret); 4131ee7efd4SKaixi Fan return TC_ACT_SHOT; 4141ee7efd4SKaixi Fan } 415bd4aed0eSJiong Wang 416bd4aed0eSJiong Wang return TC_ACT_OK; 417bd4aed0eSJiong Wang } 418bd4aed0eSJiong Wang 4191ee7efd4SKaixi Fan SEC("tc") 4201115169fSPaul Chaignon int veth_set_outer_dst(struct __sk_buff *skb) 4211115169fSPaul Chaignon { 4221115169fSPaul Chaignon struct ethhdr *eth = (struct ethhdr *)(long)skb->data; 4231115169fSPaul Chaignon __u32 assigned_ip = bpf_htonl(ASSIGNED_ADDR_VETH1); 4241115169fSPaul Chaignon void *data_end = (void *)(long)skb->data_end; 4251115169fSPaul Chaignon struct udphdr *udph; 4261115169fSPaul Chaignon struct iphdr *iph; 4271115169fSPaul Chaignon int ret = 0; 4281115169fSPaul Chaignon __s64 csum; 4291115169fSPaul Chaignon 4301115169fSPaul Chaignon if ((void *)eth + sizeof(*eth) > data_end) { 4311115169fSPaul Chaignon log_err(ret); 4321115169fSPaul Chaignon return TC_ACT_SHOT; 4331115169fSPaul Chaignon } 4341115169fSPaul Chaignon 4351115169fSPaul Chaignon if (eth->h_proto != bpf_htons(ETH_P_IP)) 4361115169fSPaul Chaignon return TC_ACT_OK; 4371115169fSPaul Chaignon 4381115169fSPaul Chaignon iph = (struct iphdr *)(eth + 1); 4391115169fSPaul Chaignon if ((void *)iph + sizeof(*iph) > data_end) { 4401115169fSPaul Chaignon log_err(ret); 4411115169fSPaul Chaignon return TC_ACT_SHOT; 4421115169fSPaul Chaignon } 4431115169fSPaul Chaignon if (iph->protocol != IPPROTO_UDP) 4441115169fSPaul Chaignon return TC_ACT_OK; 4451115169fSPaul Chaignon 4461115169fSPaul Chaignon udph = (struct udphdr *)(iph + 1); 4471115169fSPaul Chaignon if ((void *)udph + sizeof(*udph) > data_end) { 4481115169fSPaul Chaignon log_err(ret); 4491115169fSPaul Chaignon return TC_ACT_SHOT; 4501115169fSPaul Chaignon } 4511115169fSPaul Chaignon if (udph->dest != bpf_htons(VXLAN_UDP_PORT)) 4521115169fSPaul Chaignon return TC_ACT_OK; 4531115169fSPaul Chaignon 4541115169fSPaul Chaignon if (iph->daddr != assigned_ip) { 4551115169fSPaul Chaignon csum = bpf_csum_diff(&iph->daddr, sizeof(__u32), &assigned_ip, 4561115169fSPaul Chaignon sizeof(__u32), 0); 4571115169fSPaul Chaignon if (bpf_skb_store_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr), 4581115169fSPaul Chaignon &assigned_ip, sizeof(__u32), 0) < 0) { 4591115169fSPaul Chaignon log_err(ret); 4601115169fSPaul Chaignon return TC_ACT_SHOT; 4611115169fSPaul Chaignon } 4621115169fSPaul Chaignon if (bpf_l3_csum_replace(skb, ETH_HLEN + offsetof(struct iphdr, check), 4631115169fSPaul Chaignon 0, csum, 0) < 0) { 4641115169fSPaul Chaignon log_err(ret); 4651115169fSPaul Chaignon return TC_ACT_SHOT; 4661115169fSPaul Chaignon } 4671115169fSPaul Chaignon bpf_skb_change_type(skb, PACKET_HOST); 4681115169fSPaul Chaignon } 4691115169fSPaul Chaignon return TC_ACT_OK; 4701115169fSPaul Chaignon } 4711115169fSPaul Chaignon 4721115169fSPaul Chaignon SEC("tc") 4731ee7efd4SKaixi Fan int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb) 474bd4aed0eSJiong Wang { 475bd4aed0eSJiong Wang struct bpf_tunnel_key key; 4761ee7efd4SKaixi Fan __u32 index = 0; 4771ee7efd4SKaixi Fan __u32 *local_ip; 478ec97a76fSDave Marchevsky int ret = 0; 4791ee7efd4SKaixi Fan 4801ee7efd4SKaixi Fan local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 4811ee7efd4SKaixi Fan if (!local_ip) { 4821ee7efd4SKaixi Fan log_err(ret); 4831ee7efd4SKaixi Fan return TC_ACT_SHOT; 4841ee7efd4SKaixi Fan } 485bd4aed0eSJiong Wang 486bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 4871ee7efd4SKaixi Fan key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 4881ee7efd4SKaixi Fan key.remote_ipv6[3] = bpf_htonl(*local_ip); 4891ee7efd4SKaixi Fan key.tunnel_id = 22; 4901ee7efd4SKaixi Fan key.tunnel_tos = 0; 4911ee7efd4SKaixi Fan key.tunnel_ttl = 64; 4921ee7efd4SKaixi Fan 4931ee7efd4SKaixi Fan ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 4941ee7efd4SKaixi Fan BPF_F_TUNINFO_IPV6); 4951ee7efd4SKaixi Fan if (ret < 0) { 4961ee7efd4SKaixi Fan log_err(ret); 4971ee7efd4SKaixi Fan return TC_ACT_SHOT; 4981ee7efd4SKaixi Fan } 4991ee7efd4SKaixi Fan 5001ee7efd4SKaixi Fan return TC_ACT_OK; 5011ee7efd4SKaixi Fan } 5021ee7efd4SKaixi Fan 5031ee7efd4SKaixi Fan SEC("tc") 5041ee7efd4SKaixi Fan int ip6vxlan_set_tunnel_src(struct __sk_buff *skb) 5051ee7efd4SKaixi Fan { 5061ee7efd4SKaixi Fan struct bpf_tunnel_key key; 5071ee7efd4SKaixi Fan __u32 index = 0; 5081ee7efd4SKaixi Fan __u32 *local_ip; 509ec97a76fSDave Marchevsky int ret = 0; 5101ee7efd4SKaixi Fan 5111ee7efd4SKaixi Fan local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 5121ee7efd4SKaixi Fan if (!local_ip) { 51371b2ec21SKaixi Fan log_err(ret); 5141ee7efd4SKaixi Fan return TC_ACT_SHOT; 5151ee7efd4SKaixi Fan } 5161ee7efd4SKaixi Fan 5171ee7efd4SKaixi Fan __builtin_memset(&key, 0x0, sizeof(key)); 5181ee7efd4SKaixi Fan key.local_ipv6[3] = bpf_htonl(*local_ip); 519bd4aed0eSJiong Wang key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 520bd4aed0eSJiong Wang key.tunnel_id = 22; 521bd4aed0eSJiong Wang key.tunnel_tos = 0; 522bd4aed0eSJiong Wang key.tunnel_ttl = 64; 523bd4aed0eSJiong Wang 524bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 525bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 526bd4aed0eSJiong Wang if (ret < 0) { 52771b2ec21SKaixi Fan log_err(ret); 528bd4aed0eSJiong Wang return TC_ACT_SHOT; 529bd4aed0eSJiong Wang } 530bd4aed0eSJiong Wang 531bd4aed0eSJiong Wang return TC_ACT_OK; 532bd4aed0eSJiong Wang } 533bd4aed0eSJiong Wang 5341ee7efd4SKaixi Fan SEC("tc") 5351ee7efd4SKaixi Fan int ip6vxlan_get_tunnel_src(struct __sk_buff *skb) 536bd4aed0eSJiong Wang { 537bd4aed0eSJiong Wang struct bpf_tunnel_key key; 5381ee7efd4SKaixi Fan __u32 index = 0; 5391ee7efd4SKaixi Fan __u32 *local_ip; 540ec97a76fSDave Marchevsky int ret = 0; 5411ee7efd4SKaixi Fan 5421ee7efd4SKaixi Fan local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 5431ee7efd4SKaixi Fan if (!local_ip) { 54471b2ec21SKaixi Fan log_err(ret); 5451ee7efd4SKaixi Fan return TC_ACT_SHOT; 5461ee7efd4SKaixi Fan } 547bd4aed0eSJiong Wang 548bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 5498cc61b7aSShmulik Ladkani BPF_F_TUNINFO_IPV6 | BPF_F_TUNINFO_FLAGS); 550bd4aed0eSJiong Wang if (ret < 0) { 55171b2ec21SKaixi Fan log_err(ret); 552bd4aed0eSJiong Wang return TC_ACT_SHOT; 553bd4aed0eSJiong Wang } 554bd4aed0eSJiong Wang 5558cc61b7aSShmulik Ladkani if (bpf_ntohl(key.local_ipv6[3]) != *local_ip || 5568cc61b7aSShmulik Ladkani !(key.tunnel_flags & TUNNEL_KEY) || 5578cc61b7aSShmulik Ladkani !(key.tunnel_flags & TUNNEL_CSUM)) { 5588cc61b7aSShmulik Ladkani bpf_printk("ip6vxlan key %d local ip6 ::%x remote ip6 ::%x label 0x%x flags 0x%x\n", 55971b2ec21SKaixi Fan key.tunnel_id, bpf_ntohl(key.local_ipv6[3]), 5608cc61b7aSShmulik Ladkani bpf_ntohl(key.remote_ipv6[3]), key.tunnel_label, 5618cc61b7aSShmulik Ladkani bpf_ntohs(key.tunnel_flags)); 56271b2ec21SKaixi Fan bpf_printk("local_ip 0x%x\n", *local_ip); 56371b2ec21SKaixi Fan log_err(ret); 5641ee7efd4SKaixi Fan return TC_ACT_SHOT; 5651ee7efd4SKaixi Fan } 566bd4aed0eSJiong Wang 567bd4aed0eSJiong Wang return TC_ACT_OK; 568bd4aed0eSJiong Wang } 569bd4aed0eSJiong Wang 570*5ddafcc3SCupertino Miranda struct local_geneve_opt { 571*5ddafcc3SCupertino Miranda struct geneve_opt gopt; 572*5ddafcc3SCupertino Miranda int data; 573*5ddafcc3SCupertino Miranda }; 574*5ddafcc3SCupertino Miranda 5751ee7efd4SKaixi Fan SEC("tc") 5761ee7efd4SKaixi Fan int geneve_set_tunnel(struct __sk_buff *skb) 577bd4aed0eSJiong Wang { 578069904ceSzuoqilin int ret; 579bd4aed0eSJiong Wang struct bpf_tunnel_key key; 580*5ddafcc3SCupertino Miranda struct local_geneve_opt local_gopt; 581*5ddafcc3SCupertino Miranda struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt; 582bd4aed0eSJiong Wang 583bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 584bd4aed0eSJiong Wang key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 585bd4aed0eSJiong Wang key.tunnel_id = 2; 586bd4aed0eSJiong Wang key.tunnel_tos = 0; 587bd4aed0eSJiong Wang key.tunnel_ttl = 64; 588bd4aed0eSJiong Wang 589*5ddafcc3SCupertino Miranda __builtin_memset(gopt, 0x0, sizeof(local_gopt)); 590*5ddafcc3SCupertino Miranda gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */ 591*5ddafcc3SCupertino Miranda gopt->type = 0x08; 592*5ddafcc3SCupertino Miranda gopt->r1 = 0; 593*5ddafcc3SCupertino Miranda gopt->r2 = 0; 594*5ddafcc3SCupertino Miranda gopt->r3 = 0; 595*5ddafcc3SCupertino Miranda gopt->length = 2; /* 4-byte multiple */ 596*5ddafcc3SCupertino Miranda *(int *) &gopt->opt_data = bpf_htonl(0xdeadbeef); 597bd4aed0eSJiong Wang 598bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 599bd4aed0eSJiong Wang BPF_F_ZERO_CSUM_TX); 600bd4aed0eSJiong Wang if (ret < 0) { 60171b2ec21SKaixi Fan log_err(ret); 602bd4aed0eSJiong Wang return TC_ACT_SHOT; 603bd4aed0eSJiong Wang } 604bd4aed0eSJiong Wang 605*5ddafcc3SCupertino Miranda ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(local_gopt)); 606bd4aed0eSJiong Wang if (ret < 0) { 60771b2ec21SKaixi Fan log_err(ret); 608bd4aed0eSJiong Wang return TC_ACT_SHOT; 609bd4aed0eSJiong Wang } 610bd4aed0eSJiong Wang 611bd4aed0eSJiong Wang return TC_ACT_OK; 612bd4aed0eSJiong Wang } 613bd4aed0eSJiong Wang 6141ee7efd4SKaixi Fan SEC("tc") 6151ee7efd4SKaixi Fan int geneve_get_tunnel(struct __sk_buff *skb) 616bd4aed0eSJiong Wang { 617bd4aed0eSJiong Wang int ret; 618bd4aed0eSJiong Wang struct bpf_tunnel_key key; 619bd4aed0eSJiong Wang struct geneve_opt gopt; 620bd4aed0eSJiong Wang 621bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 622bd4aed0eSJiong Wang if (ret < 0) { 62371b2ec21SKaixi Fan log_err(ret); 624bd4aed0eSJiong Wang return TC_ACT_SHOT; 625bd4aed0eSJiong Wang } 626bd4aed0eSJiong Wang 627bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt)); 628557c223bSHangbin Liu if (ret < 0) 629557c223bSHangbin Liu gopt.opt_class = 0; 630bd4aed0eSJiong Wang 63171b2ec21SKaixi Fan bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n", 632bd4aed0eSJiong Wang key.tunnel_id, key.remote_ipv4, gopt.opt_class); 633bd4aed0eSJiong Wang return TC_ACT_OK; 634bd4aed0eSJiong Wang } 635bd4aed0eSJiong Wang 6361ee7efd4SKaixi Fan SEC("tc") 6371ee7efd4SKaixi Fan int ip6geneve_set_tunnel(struct __sk_buff *skb) 638bd4aed0eSJiong Wang { 639bd4aed0eSJiong Wang struct bpf_tunnel_key key; 640*5ddafcc3SCupertino Miranda struct local_geneve_opt local_gopt; 641*5ddafcc3SCupertino Miranda struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt; 642bd4aed0eSJiong Wang int ret; 643bd4aed0eSJiong Wang 644bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 645bd4aed0eSJiong Wang key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 646bd4aed0eSJiong Wang key.tunnel_id = 22; 647bd4aed0eSJiong Wang key.tunnel_tos = 0; 648bd4aed0eSJiong Wang key.tunnel_ttl = 64; 649bd4aed0eSJiong Wang 650bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 651bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 652bd4aed0eSJiong Wang if (ret < 0) { 65371b2ec21SKaixi Fan log_err(ret); 654bd4aed0eSJiong Wang return TC_ACT_SHOT; 655bd4aed0eSJiong Wang } 656bd4aed0eSJiong Wang 657*5ddafcc3SCupertino Miranda __builtin_memset(gopt, 0x0, sizeof(local_gopt)); 658*5ddafcc3SCupertino Miranda gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */ 659*5ddafcc3SCupertino Miranda gopt->type = 0x08; 660*5ddafcc3SCupertino Miranda gopt->r1 = 0; 661*5ddafcc3SCupertino Miranda gopt->r2 = 0; 662*5ddafcc3SCupertino Miranda gopt->r3 = 0; 663*5ddafcc3SCupertino Miranda gopt->length = 2; /* 4-byte multiple */ 664*5ddafcc3SCupertino Miranda *(int *) &gopt->opt_data = bpf_htonl(0xfeedbeef); 665bd4aed0eSJiong Wang 666*5ddafcc3SCupertino Miranda ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(gopt)); 667bd4aed0eSJiong Wang if (ret < 0) { 66871b2ec21SKaixi Fan log_err(ret); 669bd4aed0eSJiong Wang return TC_ACT_SHOT; 670bd4aed0eSJiong Wang } 671bd4aed0eSJiong Wang 672bd4aed0eSJiong Wang return TC_ACT_OK; 673bd4aed0eSJiong Wang } 674bd4aed0eSJiong Wang 6751ee7efd4SKaixi Fan SEC("tc") 6761ee7efd4SKaixi Fan int ip6geneve_get_tunnel(struct __sk_buff *skb) 677bd4aed0eSJiong Wang { 678bd4aed0eSJiong Wang struct bpf_tunnel_key key; 679bd4aed0eSJiong Wang struct geneve_opt gopt; 680bd4aed0eSJiong Wang int ret; 681bd4aed0eSJiong Wang 682bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 683bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 684bd4aed0eSJiong Wang if (ret < 0) { 68571b2ec21SKaixi Fan log_err(ret); 686bd4aed0eSJiong Wang return TC_ACT_SHOT; 687bd4aed0eSJiong Wang } 688bd4aed0eSJiong Wang 689bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt)); 69031254dc9SHangbin Liu if (ret < 0) 69131254dc9SHangbin Liu gopt.opt_class = 0; 692bd4aed0eSJiong Wang 69371b2ec21SKaixi Fan bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n", 694bd4aed0eSJiong Wang key.tunnel_id, key.remote_ipv4, gopt.opt_class); 695bd4aed0eSJiong Wang 696bd4aed0eSJiong Wang return TC_ACT_OK; 697bd4aed0eSJiong Wang } 698bd4aed0eSJiong Wang 6991ee7efd4SKaixi Fan SEC("tc") 7001ee7efd4SKaixi Fan int ipip_set_tunnel(struct __sk_buff *skb) 701bd4aed0eSJiong Wang { 702bd4aed0eSJiong Wang struct bpf_tunnel_key key = {}; 703bd4aed0eSJiong Wang void *data = (void *)(long)skb->data; 704bd4aed0eSJiong Wang struct iphdr *iph = data; 705bd4aed0eSJiong Wang void *data_end = (void *)(long)skb->data_end; 706bd4aed0eSJiong Wang int ret; 707bd4aed0eSJiong Wang 708bd4aed0eSJiong Wang /* single length check */ 70958cfa49cSHangbin Liu if (data + sizeof(*iph) > data_end) { 71071b2ec21SKaixi Fan log_err(1); 711bd4aed0eSJiong Wang return TC_ACT_SHOT; 712bd4aed0eSJiong Wang } 713bd4aed0eSJiong Wang 714bd4aed0eSJiong Wang key.tunnel_ttl = 64; 715bd4aed0eSJiong Wang if (iph->protocol == IPPROTO_ICMP) { 716bd4aed0eSJiong Wang key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 717bd4aed0eSJiong Wang } 718bd4aed0eSJiong Wang 719bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); 720bd4aed0eSJiong Wang if (ret < 0) { 72171b2ec21SKaixi Fan log_err(ret); 722bd4aed0eSJiong Wang return TC_ACT_SHOT; 723bd4aed0eSJiong Wang } 724bd4aed0eSJiong Wang 725bd4aed0eSJiong Wang return TC_ACT_OK; 726bd4aed0eSJiong Wang } 727bd4aed0eSJiong Wang 7281ee7efd4SKaixi Fan SEC("tc") 7291ee7efd4SKaixi Fan int ipip_get_tunnel(struct __sk_buff *skb) 730bd4aed0eSJiong Wang { 731bd4aed0eSJiong Wang int ret; 732bd4aed0eSJiong Wang struct bpf_tunnel_key key; 733bd4aed0eSJiong Wang 734bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 735bd4aed0eSJiong Wang if (ret < 0) { 73671b2ec21SKaixi Fan log_err(ret); 737bd4aed0eSJiong Wang return TC_ACT_SHOT; 738bd4aed0eSJiong Wang } 739bd4aed0eSJiong Wang 74071b2ec21SKaixi Fan bpf_printk("remote ip 0x%x\n", key.remote_ipv4); 741bd4aed0eSJiong Wang return TC_ACT_OK; 742bd4aed0eSJiong Wang } 743bd4aed0eSJiong Wang 7441ee7efd4SKaixi Fan SEC("tc") 745d9688f89SChristian Ehrig int ipip_gue_set_tunnel(struct __sk_buff *skb) 746d9688f89SChristian Ehrig { 747d9688f89SChristian Ehrig struct bpf_tunnel_key key = {}; 748d9688f89SChristian Ehrig struct bpf_fou_encap encap = {}; 749d9688f89SChristian Ehrig void *data = (void *)(long)skb->data; 750d9688f89SChristian Ehrig struct iphdr *iph = data; 751d9688f89SChristian Ehrig void *data_end = (void *)(long)skb->data_end; 752d9688f89SChristian Ehrig int ret; 753d9688f89SChristian Ehrig 754d9688f89SChristian Ehrig if (data + sizeof(*iph) > data_end) { 755d9688f89SChristian Ehrig log_err(1); 756d9688f89SChristian Ehrig return TC_ACT_SHOT; 757d9688f89SChristian Ehrig } 758d9688f89SChristian Ehrig 759d9688f89SChristian Ehrig key.tunnel_ttl = 64; 760d9688f89SChristian Ehrig if (iph->protocol == IPPROTO_ICMP) 761d9688f89SChristian Ehrig key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 762d9688f89SChristian Ehrig 763d9688f89SChristian Ehrig ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); 764d9688f89SChristian Ehrig if (ret < 0) { 765d9688f89SChristian Ehrig log_err(ret); 766d9688f89SChristian Ehrig return TC_ACT_SHOT; 767d9688f89SChristian Ehrig } 768d9688f89SChristian Ehrig 769d9688f89SChristian Ehrig encap.sport = 0; 770d9688f89SChristian Ehrig encap.dport = bpf_htons(5555); 771d9688f89SChristian Ehrig 772d9688f89SChristian Ehrig ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_GUE); 773d9688f89SChristian Ehrig if (ret < 0) { 774d9688f89SChristian Ehrig log_err(ret); 775d9688f89SChristian Ehrig return TC_ACT_SHOT; 776d9688f89SChristian Ehrig } 777d9688f89SChristian Ehrig 778d9688f89SChristian Ehrig return TC_ACT_OK; 779d9688f89SChristian Ehrig } 780d9688f89SChristian Ehrig 781d9688f89SChristian Ehrig SEC("tc") 782d9688f89SChristian Ehrig int ipip_fou_set_tunnel(struct __sk_buff *skb) 783d9688f89SChristian Ehrig { 784d9688f89SChristian Ehrig struct bpf_tunnel_key key = {}; 785d9688f89SChristian Ehrig struct bpf_fou_encap encap = {}; 786d9688f89SChristian Ehrig void *data = (void *)(long)skb->data; 787d9688f89SChristian Ehrig struct iphdr *iph = data; 788d9688f89SChristian Ehrig void *data_end = (void *)(long)skb->data_end; 789d9688f89SChristian Ehrig int ret; 790d9688f89SChristian Ehrig 791d9688f89SChristian Ehrig if (data + sizeof(*iph) > data_end) { 792d9688f89SChristian Ehrig log_err(1); 793d9688f89SChristian Ehrig return TC_ACT_SHOT; 794d9688f89SChristian Ehrig } 795d9688f89SChristian Ehrig 796d9688f89SChristian Ehrig key.tunnel_ttl = 64; 797d9688f89SChristian Ehrig if (iph->protocol == IPPROTO_ICMP) 798d9688f89SChristian Ehrig key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 799d9688f89SChristian Ehrig 800d9688f89SChristian Ehrig ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); 801d9688f89SChristian Ehrig if (ret < 0) { 802d9688f89SChristian Ehrig log_err(ret); 803d9688f89SChristian Ehrig return TC_ACT_SHOT; 804d9688f89SChristian Ehrig } 805d9688f89SChristian Ehrig 806d9688f89SChristian Ehrig encap.sport = 0; 807d9688f89SChristian Ehrig encap.dport = bpf_htons(5555); 808d9688f89SChristian Ehrig 809d9688f89SChristian Ehrig ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_FOU); 810d9688f89SChristian Ehrig if (ret < 0) { 811d9688f89SChristian Ehrig log_err(ret); 812d9688f89SChristian Ehrig return TC_ACT_SHOT; 813d9688f89SChristian Ehrig } 814d9688f89SChristian Ehrig 815d9688f89SChristian Ehrig return TC_ACT_OK; 816d9688f89SChristian Ehrig } 817d9688f89SChristian Ehrig 818d9688f89SChristian Ehrig SEC("tc") 819d9688f89SChristian Ehrig int ipip_encap_get_tunnel(struct __sk_buff *skb) 820d9688f89SChristian Ehrig { 821d9688f89SChristian Ehrig int ret; 822d9688f89SChristian Ehrig struct bpf_tunnel_key key = {}; 823d9688f89SChristian Ehrig struct bpf_fou_encap encap = {}; 824d9688f89SChristian Ehrig 825d9688f89SChristian Ehrig ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 826d9688f89SChristian Ehrig if (ret < 0) { 827d9688f89SChristian Ehrig log_err(ret); 828d9688f89SChristian Ehrig return TC_ACT_SHOT; 829d9688f89SChristian Ehrig } 830d9688f89SChristian Ehrig 831d9688f89SChristian Ehrig ret = bpf_skb_get_fou_encap(skb, &encap); 832d9688f89SChristian Ehrig if (ret < 0) { 833d9688f89SChristian Ehrig log_err(ret); 834d9688f89SChristian Ehrig return TC_ACT_SHOT; 835d9688f89SChristian Ehrig } 836d9688f89SChristian Ehrig 837d9688f89SChristian Ehrig if (bpf_ntohs(encap.dport) != 5555) 838d9688f89SChristian Ehrig return TC_ACT_SHOT; 839d9688f89SChristian Ehrig 840d9688f89SChristian Ehrig bpf_printk("%d remote ip 0x%x, sport %d, dport %d\n", ret, 841d9688f89SChristian Ehrig key.remote_ipv4, bpf_ntohs(encap.sport), 842d9688f89SChristian Ehrig bpf_ntohs(encap.dport)); 843d9688f89SChristian Ehrig return TC_ACT_OK; 844d9688f89SChristian Ehrig } 845d9688f89SChristian Ehrig 846d9688f89SChristian Ehrig SEC("tc") 8471ee7efd4SKaixi Fan int ipip6_set_tunnel(struct __sk_buff *skb) 848bd4aed0eSJiong Wang { 849bd4aed0eSJiong Wang struct bpf_tunnel_key key = {}; 850bd4aed0eSJiong Wang void *data = (void *)(long)skb->data; 851bd4aed0eSJiong Wang struct iphdr *iph = data; 852bd4aed0eSJiong Wang void *data_end = (void *)(long)skb->data_end; 853bd4aed0eSJiong Wang int ret; 854bd4aed0eSJiong Wang 855bd4aed0eSJiong Wang /* single length check */ 85658cfa49cSHangbin Liu if (data + sizeof(*iph) > data_end) { 85771b2ec21SKaixi Fan log_err(1); 858bd4aed0eSJiong Wang return TC_ACT_SHOT; 859bd4aed0eSJiong Wang } 860bd4aed0eSJiong Wang 861bd4aed0eSJiong Wang __builtin_memset(&key, 0x0, sizeof(key)); 862bd4aed0eSJiong Wang key.tunnel_ttl = 64; 86358cfa49cSHangbin Liu if (iph->protocol == IPPROTO_ICMP) { 86458cfa49cSHangbin Liu key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 86558cfa49cSHangbin Liu } 866bd4aed0eSJiong Wang 867bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 868bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 869bd4aed0eSJiong Wang if (ret < 0) { 87071b2ec21SKaixi Fan log_err(ret); 871bd4aed0eSJiong Wang return TC_ACT_SHOT; 872bd4aed0eSJiong Wang } 873bd4aed0eSJiong Wang 874bd4aed0eSJiong Wang return TC_ACT_OK; 875bd4aed0eSJiong Wang } 876bd4aed0eSJiong Wang 8771ee7efd4SKaixi Fan SEC("tc") 8781ee7efd4SKaixi Fan int ipip6_get_tunnel(struct __sk_buff *skb) 879bd4aed0eSJiong Wang { 880bd4aed0eSJiong Wang int ret; 881bd4aed0eSJiong Wang struct bpf_tunnel_key key; 882bd4aed0eSJiong Wang 883bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 884bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 885bd4aed0eSJiong Wang if (ret < 0) { 88671b2ec21SKaixi Fan log_err(ret); 887bd4aed0eSJiong Wang return TC_ACT_SHOT; 888bd4aed0eSJiong Wang } 889bd4aed0eSJiong Wang 89071b2ec21SKaixi Fan bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]), 891bd4aed0eSJiong Wang bpf_htonl(key.remote_ipv6[3])); 892bd4aed0eSJiong Wang return TC_ACT_OK; 893bd4aed0eSJiong Wang } 894bd4aed0eSJiong Wang 8951ee7efd4SKaixi Fan SEC("tc") 8961ee7efd4SKaixi Fan int ip6ip6_set_tunnel(struct __sk_buff *skb) 897bd4aed0eSJiong Wang { 898bd4aed0eSJiong Wang struct bpf_tunnel_key key = {}; 899bd4aed0eSJiong Wang void *data = (void *)(long)skb->data; 900bd4aed0eSJiong Wang struct ipv6hdr *iph = data; 901bd4aed0eSJiong Wang void *data_end = (void *)(long)skb->data_end; 902bd4aed0eSJiong Wang int ret; 903bd4aed0eSJiong Wang 904bd4aed0eSJiong Wang /* single length check */ 90558cfa49cSHangbin Liu if (data + sizeof(*iph) > data_end) { 90671b2ec21SKaixi Fan log_err(1); 907bd4aed0eSJiong Wang return TC_ACT_SHOT; 908bd4aed0eSJiong Wang } 909bd4aed0eSJiong Wang 910bd4aed0eSJiong Wang key.tunnel_ttl = 64; 911bd4aed0eSJiong Wang if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) { 91258cfa49cSHangbin Liu key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 913bd4aed0eSJiong Wang } 914bd4aed0eSJiong Wang 915bd4aed0eSJiong Wang ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 916bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 917bd4aed0eSJiong Wang if (ret < 0) { 91871b2ec21SKaixi Fan log_err(ret); 919bd4aed0eSJiong Wang return TC_ACT_SHOT; 920bd4aed0eSJiong Wang } 921bd4aed0eSJiong Wang 922bd4aed0eSJiong Wang return TC_ACT_OK; 923bd4aed0eSJiong Wang } 924bd4aed0eSJiong Wang 9251ee7efd4SKaixi Fan SEC("tc") 9261ee7efd4SKaixi Fan int ip6ip6_get_tunnel(struct __sk_buff *skb) 927bd4aed0eSJiong Wang { 928bd4aed0eSJiong Wang int ret; 929bd4aed0eSJiong Wang struct bpf_tunnel_key key; 930bd4aed0eSJiong Wang 931bd4aed0eSJiong Wang ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 932bd4aed0eSJiong Wang BPF_F_TUNINFO_IPV6); 933bd4aed0eSJiong Wang if (ret < 0) { 93471b2ec21SKaixi Fan log_err(ret); 935bd4aed0eSJiong Wang return TC_ACT_SHOT; 936bd4aed0eSJiong Wang } 937bd4aed0eSJiong Wang 93871b2ec21SKaixi Fan bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]), 939bd4aed0eSJiong Wang bpf_htonl(key.remote_ipv6[3])); 940bd4aed0eSJiong Wang return TC_ACT_OK; 941bd4aed0eSJiong Wang } 942bd4aed0eSJiong Wang 943e7adc829SDaniel Xu volatile int xfrm_reqid = 0; 944e7adc829SDaniel Xu volatile int xfrm_spi = 0; 945e7adc829SDaniel Xu volatile int xfrm_remote_ip = 0; 946e7adc829SDaniel Xu 9471ee7efd4SKaixi Fan SEC("tc") 9481ee7efd4SKaixi Fan int xfrm_get_state(struct __sk_buff *skb) 949bd4aed0eSJiong Wang { 950bd4aed0eSJiong Wang struct bpf_xfrm_state x; 951bd4aed0eSJiong Wang int ret; 952bd4aed0eSJiong Wang 953bd4aed0eSJiong Wang ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0); 954bd4aed0eSJiong Wang if (ret < 0) 955bd4aed0eSJiong Wang return TC_ACT_OK; 956bd4aed0eSJiong Wang 957e7adc829SDaniel Xu xfrm_reqid = x.reqid; 958e7adc829SDaniel Xu xfrm_spi = bpf_ntohl(x.spi); 959e7adc829SDaniel Xu xfrm_remote_ip = bpf_ntohl(x.remote_ipv4); 960e7adc829SDaniel Xu 961bd4aed0eSJiong Wang return TC_ACT_OK; 962bd4aed0eSJiong Wang } 963bd4aed0eSJiong Wang 9642cd07b0eSDaniel Xu volatile int xfrm_replay_window = 0; 9652cd07b0eSDaniel Xu 9662cd07b0eSDaniel Xu SEC("xdp") 9672cd07b0eSDaniel Xu int xfrm_get_state_xdp(struct xdp_md *xdp) 9682cd07b0eSDaniel Xu { 9692cd07b0eSDaniel Xu struct bpf_xfrm_state_opts opts = {}; 9702cd07b0eSDaniel Xu struct xfrm_state *x = NULL; 9712cd07b0eSDaniel Xu struct ip_esp_hdr *esph; 9722cd07b0eSDaniel Xu struct bpf_dynptr ptr; 9732cd07b0eSDaniel Xu u8 esph_buf[8] = {}; 9742cd07b0eSDaniel Xu u8 iph_buf[20] = {}; 9752cd07b0eSDaniel Xu struct iphdr *iph; 9762cd07b0eSDaniel Xu u32 off; 9772cd07b0eSDaniel Xu 9782cd07b0eSDaniel Xu if (bpf_dynptr_from_xdp(xdp, 0, &ptr)) 9792cd07b0eSDaniel Xu goto out; 9802cd07b0eSDaniel Xu 9812cd07b0eSDaniel Xu off = sizeof(struct ethhdr); 9822cd07b0eSDaniel Xu iph = bpf_dynptr_slice(&ptr, off, iph_buf, sizeof(iph_buf)); 9832cd07b0eSDaniel Xu if (!iph || iph->protocol != IPPROTO_ESP) 9842cd07b0eSDaniel Xu goto out; 9852cd07b0eSDaniel Xu 9862cd07b0eSDaniel Xu off += sizeof(struct iphdr); 9872cd07b0eSDaniel Xu esph = bpf_dynptr_slice(&ptr, off, esph_buf, sizeof(esph_buf)); 9882cd07b0eSDaniel Xu if (!esph) 9892cd07b0eSDaniel Xu goto out; 9902cd07b0eSDaniel Xu 9912cd07b0eSDaniel Xu opts.netns_id = BPF_F_CURRENT_NETNS; 9922cd07b0eSDaniel Xu opts.daddr.a4 = iph->daddr; 9932cd07b0eSDaniel Xu opts.spi = esph->spi; 9942cd07b0eSDaniel Xu opts.proto = IPPROTO_ESP; 9952cd07b0eSDaniel Xu opts.family = AF_INET; 9962cd07b0eSDaniel Xu 9972cd07b0eSDaniel Xu x = bpf_xdp_get_xfrm_state(xdp, &opts, sizeof(opts)); 9982cd07b0eSDaniel Xu if (!x) 9992cd07b0eSDaniel Xu goto out; 10002cd07b0eSDaniel Xu 10012cd07b0eSDaniel Xu if (!x->replay_esn) 10022cd07b0eSDaniel Xu goto out; 10032cd07b0eSDaniel Xu 10042cd07b0eSDaniel Xu xfrm_replay_window = x->replay_esn->replay_window; 10052cd07b0eSDaniel Xu out: 10062cd07b0eSDaniel Xu if (x) 10072cd07b0eSDaniel Xu bpf_xdp_xfrm_state_release(x); 10082cd07b0eSDaniel Xu return XDP_PASS; 10092cd07b0eSDaniel Xu } 10102cd07b0eSDaniel Xu 1011bd4aed0eSJiong Wang char _license[] SEC("license") = "GPL"; 1012