| .. | .. |
|---|
| 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; |
|---|