.. | .. |
---|
19 | 19 | #include <linux/ip.h> |
---|
20 | 20 | #include <linux/ipv6.h> |
---|
21 | 21 | |
---|
22 | | -#include "bpf_helpers.h" |
---|
| 22 | +#include <bpf/bpf_helpers.h> |
---|
23 | 23 | |
---|
24 | 24 | #define IPV6_FLOWINFO_MASK cpu_to_be32(0x0FFFFFFF) |
---|
25 | 25 | |
---|
26 | | -struct bpf_map_def SEC("maps") tx_port = { |
---|
27 | | - .type = BPF_MAP_TYPE_DEVMAP, |
---|
28 | | - .key_size = sizeof(int), |
---|
29 | | - .value_size = sizeof(int), |
---|
30 | | - .max_entries = 64, |
---|
31 | | -}; |
---|
| 26 | +struct { |
---|
| 27 | + __uint(type, BPF_MAP_TYPE_DEVMAP); |
---|
| 28 | + __uint(key_size, sizeof(int)); |
---|
| 29 | + __uint(value_size, sizeof(int)); |
---|
| 30 | + __uint(max_entries, 64); |
---|
| 31 | +} xdp_tx_ports SEC(".maps"); |
---|
32 | 32 | |
---|
33 | 33 | /* from include/net/ip.h */ |
---|
34 | 34 | static __always_inline int ip_decrease_ttl(struct iphdr *iph) |
---|
.. | .. |
---|
102 | 102 | fib_params.ifindex = ctx->ingress_ifindex; |
---|
103 | 103 | |
---|
104 | 104 | rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags); |
---|
105 | | - |
---|
106 | | - /* verify egress index has xdp support |
---|
107 | | - * TO-DO bpf_map_lookup_elem(&tx_port, &key) fails with |
---|
108 | | - * cannot pass map_type 14 into func bpf_map_lookup_elem#1: |
---|
109 | | - * NOTE: without verification that egress index supports XDP |
---|
110 | | - * forwarding packets are dropped. |
---|
| 105 | + /* |
---|
| 106 | + * Some rc (return codes) from bpf_fib_lookup() are important, |
---|
| 107 | + * to understand how this XDP-prog interacts with network stack. |
---|
| 108 | + * |
---|
| 109 | + * BPF_FIB_LKUP_RET_NO_NEIGH: |
---|
| 110 | + * Even if route lookup was a success, then the MAC-addresses are also |
---|
| 111 | + * needed. This is obtained from arp/neighbour table, but if table is |
---|
| 112 | + * (still) empty then BPF_FIB_LKUP_RET_NO_NEIGH is returned. To avoid |
---|
| 113 | + * doing ARP lookup directly from XDP, then send packet to normal |
---|
| 114 | + * network stack via XDP_PASS and expect it will do ARP resolution. |
---|
| 115 | + * |
---|
| 116 | + * BPF_FIB_LKUP_RET_FWD_DISABLED: |
---|
| 117 | + * The bpf_fib_lookup respect sysctl net.ipv{4,6}.conf.all.forwarding |
---|
| 118 | + * setting, and will return BPF_FIB_LKUP_RET_FWD_DISABLED if not |
---|
| 119 | + * enabled this on ingress device. |
---|
111 | 120 | */ |
---|
112 | | - if (rc == 0) { |
---|
| 121 | + if (rc == BPF_FIB_LKUP_RET_SUCCESS) { |
---|
| 122 | + /* Verify egress index has been configured as TX-port. |
---|
| 123 | + * (Note: User can still have inserted an egress ifindex that |
---|
| 124 | + * doesn't support XDP xmit, which will result in packet drops). |
---|
| 125 | + * |
---|
| 126 | + * Note: lookup in devmap supported since 0cdbb4b09a0. |
---|
| 127 | + * If not supported will fail with: |
---|
| 128 | + * cannot pass map_type 14 into func bpf_map_lookup_elem#1: |
---|
| 129 | + */ |
---|
| 130 | + if (!bpf_map_lookup_elem(&xdp_tx_ports, &fib_params.ifindex)) |
---|
| 131 | + return XDP_PASS; |
---|
| 132 | + |
---|
113 | 133 | if (h_proto == htons(ETH_P_IP)) |
---|
114 | 134 | ip_decrease_ttl(iph); |
---|
115 | 135 | else if (h_proto == htons(ETH_P_IPV6)) |
---|
.. | .. |
---|
117 | 137 | |
---|
118 | 138 | memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN); |
---|
119 | 139 | memcpy(eth->h_source, fib_params.smac, ETH_ALEN); |
---|
120 | | - return bpf_redirect_map(&tx_port, fib_params.ifindex, 0); |
---|
| 140 | + return bpf_redirect_map(&xdp_tx_ports, fib_params.ifindex, 0); |
---|
121 | 141 | } |
---|
122 | 142 | |
---|
123 | 143 | return XDP_PASS; |
---|