|
22 | 22 | struct {
|
23 | 23 | __uint(type, BPF_MAP_TYPE_DEVMAP);
|
24 | 24 | __uint(key_size, sizeof(int));
|
25 |
| - __uint(value_size, sizeof(int)); |
| 25 | + __uint(value_size, sizeof(struct bpf_devmap_val)); |
26 | 26 | __uint(max_entries, 100);
|
27 | 27 | } tx_port SEC(".maps");
|
28 | 28 |
|
@@ -52,6 +52,48 @@ static void swap_src_dst_mac(void *data)
|
52 | 52 | p[5] = dst[2];
|
53 | 53 | }
|
54 | 54 |
|
| 55 | +static __always_inline __u16 csum_fold_helper(__u32 csum) |
| 56 | +{ |
| 57 | + __u32 sum; |
| 58 | + sum = (csum & 0xffff) + (csum >> 16); |
| 59 | + sum += (sum >> 16); |
| 60 | + return ~sum; |
| 61 | +} |
| 62 | + |
| 63 | +static __always_inline __u16 ipv4_csum(__u16 seed, struct iphdr *iphdr_new, |
| 64 | + struct iphdr *iphdr_old) |
| 65 | +{ |
| 66 | + __u32 csum, size = sizeof(struct iphdr); |
| 67 | + csum = bpf_csum_diff((__be32 *)iphdr_old, size, |
| 68 | + (__be32 *)iphdr_new, size, seed); |
| 69 | + return csum_fold_helper(csum); |
| 70 | +} |
| 71 | + |
| 72 | +static void parse_ipv4(void *data, u64 nh_off, void *data_end, u8 ttl) |
| 73 | +{ |
| 74 | + struct iphdr *iph = data + nh_off; |
| 75 | + struct iphdr iph_old; |
| 76 | + __u16 csum_old; |
| 77 | + |
| 78 | + if (iph + 1 > data_end) |
| 79 | + return; |
| 80 | + |
| 81 | + iph_old = *iph; |
| 82 | + csum_old = iph->check; |
| 83 | + iph->ttl = ttl; |
| 84 | + iph->check = ipv4_csum(~csum_old, iph, &iph_old); |
| 85 | +} |
| 86 | + |
| 87 | +static void parse_ipv6(void *data, u64 nh_off, void *data_end, u8 hop_limit) |
| 88 | +{ |
| 89 | + struct ipv6hdr *ip6h = data + nh_off; |
| 90 | + |
| 91 | + if (ip6h + 1 > data_end) |
| 92 | + return; |
| 93 | + |
| 94 | + ip6h->hop_limit = hop_limit; |
| 95 | +} |
| 96 | + |
55 | 97 | SEC("xdp_redirect_map")
|
56 | 98 | int xdp_redirect_map_prog(struct xdp_md *ctx)
|
57 | 99 | {
|
@@ -82,6 +124,36 @@ int xdp_redirect_map_prog(struct xdp_md *ctx)
|
82 | 124 | return bpf_redirect_map(&tx_port, vport, 0);
|
83 | 125 | }
|
84 | 126 |
|
| 127 | +/* This map prog will set new IP ttl based on egress ifindex */ |
| 128 | +SEC("xdp_devmap/map_prog") |
| 129 | +int xdp_devmap_prog(struct xdp_md *ctx) |
| 130 | +{ |
| 131 | + char fmt[] = "devmap redirect: egress dev %u with new ttl %u\n"; |
| 132 | + void *data_end = (void *)(long)ctx->data_end; |
| 133 | + void *data = (void *)(long)ctx->data; |
| 134 | + struct ethhdr *eth = data; |
| 135 | + u16 h_proto; |
| 136 | + u64 nh_off; |
| 137 | + u8 ttl; |
| 138 | + |
| 139 | + nh_off = sizeof(struct ethhdr); |
| 140 | + if (data + nh_off > data_end) |
| 141 | + return XDP_DROP; |
| 142 | + |
| 143 | + /* set new ttl based on egress ifindex */ |
| 144 | + ttl = ctx->egress_ifindex % 64; |
| 145 | + |
| 146 | + h_proto = eth->h_proto; |
| 147 | + if (h_proto == htons(ETH_P_IP)) |
| 148 | + parse_ipv4(data, nh_off, data_end, ttl); |
| 149 | + else if (h_proto == htons(ETH_P_IPV6)) |
| 150 | + parse_ipv6(data, nh_off, data_end, ttl); |
| 151 | + |
| 152 | + bpf_trace_printk(fmt, sizeof(fmt), ctx->egress_ifindex, ttl); |
| 153 | + |
| 154 | + return XDP_PASS; |
| 155 | +} |
| 156 | + |
85 | 157 | /* Redirect require an XDP bpf_prog loaded on the TX device */
|
86 | 158 | SEC("xdp_redirect_dummy")
|
87 | 159 | int xdp_redirect_dummy_prog(struct xdp_md *ctx)
|
|
0 commit comments