diff options
author | David Ahern <dsahern@gmail.com> | 2018-05-15 19:20:52 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-05-16 16:04:52 -0400 |
commit | 44edef77bd92730e1520b07f5ae2c9f4628738a8 (patch) | |
tree | c974f9f6e52e873b0444c3f8f634741fbf74c88f | |
parent | 5b26ace65012cbf3b54a68c39041bcd8ae5e31a7 (diff) |
samples/bpf: Decrement ttl in fib forwarding example
Only consider forwarding packets if ttl in received packet is > 1 and
decrement ttl before handing off to bpf_redirect_map.
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | samples/bpf/xdp_fwd_kern.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/samples/bpf/xdp_fwd_kern.c b/samples/bpf/xdp_fwd_kern.c index cdf4fc383cc9..4a6be0f87505 100644 --- a/samples/bpf/xdp_fwd_kern.c +++ b/samples/bpf/xdp_fwd_kern.c | |||
@@ -30,12 +30,24 @@ struct bpf_map_def SEC("maps") tx_port = { | |||
30 | .max_entries = 64, | 30 | .max_entries = 64, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | /* from include/net/ip.h */ | ||
34 | static __always_inline int ip_decrease_ttl(struct iphdr *iph) | ||
35 | { | ||
36 | u32 check = (__force u32)iph->check; | ||
37 | |||
38 | check += (__force u32)htons(0x0100); | ||
39 | iph->check = (__force __sum16)(check + (check >= 0xFFFF)); | ||
40 | return --iph->ttl; | ||
41 | } | ||
42 | |||
33 | static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) | 43 | static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) |
34 | { | 44 | { |
35 | void *data_end = (void *)(long)ctx->data_end; | 45 | void *data_end = (void *)(long)ctx->data_end; |
36 | void *data = (void *)(long)ctx->data; | 46 | void *data = (void *)(long)ctx->data; |
37 | struct bpf_fib_lookup fib_params; | 47 | struct bpf_fib_lookup fib_params; |
38 | struct ethhdr *eth = data; | 48 | struct ethhdr *eth = data; |
49 | struct ipv6hdr *ip6h; | ||
50 | struct iphdr *iph; | ||
39 | int out_index; | 51 | int out_index; |
40 | u16 h_proto; | 52 | u16 h_proto; |
41 | u64 nh_off; | 53 | u64 nh_off; |
@@ -48,11 +60,14 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) | |||
48 | 60 | ||
49 | h_proto = eth->h_proto; | 61 | h_proto = eth->h_proto; |
50 | if (h_proto == htons(ETH_P_IP)) { | 62 | if (h_proto == htons(ETH_P_IP)) { |
51 | struct iphdr *iph = data + nh_off; | 63 | iph = data + nh_off; |
52 | 64 | ||
53 | if (iph + 1 > data_end) | 65 | if (iph + 1 > data_end) |
54 | return XDP_DROP; | 66 | return XDP_DROP; |
55 | 67 | ||
68 | if (iph->ttl <= 1) | ||
69 | return XDP_PASS; | ||
70 | |||
56 | fib_params.family = AF_INET; | 71 | fib_params.family = AF_INET; |
57 | fib_params.tos = iph->tos; | 72 | fib_params.tos = iph->tos; |
58 | fib_params.l4_protocol = iph->protocol; | 73 | fib_params.l4_protocol = iph->protocol; |
@@ -64,19 +79,22 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) | |||
64 | } else if (h_proto == htons(ETH_P_IPV6)) { | 79 | } else if (h_proto == htons(ETH_P_IPV6)) { |
65 | struct in6_addr *src = (struct in6_addr *) fib_params.ipv6_src; | 80 | struct in6_addr *src = (struct in6_addr *) fib_params.ipv6_src; |
66 | struct in6_addr *dst = (struct in6_addr *) fib_params.ipv6_dst; | 81 | struct in6_addr *dst = (struct in6_addr *) fib_params.ipv6_dst; |
67 | struct ipv6hdr *iph = data + nh_off; | ||
68 | 82 | ||
69 | if (iph + 1 > data_end) | 83 | ip6h = data + nh_off; |
84 | if (ip6h + 1 > data_end) | ||
70 | return XDP_DROP; | 85 | return XDP_DROP; |
71 | 86 | ||
87 | if (ip6h->hop_limit <= 1) | ||
88 | return XDP_PASS; | ||
89 | |||
72 | fib_params.family = AF_INET6; | 90 | fib_params.family = AF_INET6; |
73 | fib_params.flowlabel = *(__be32 *)iph & IPV6_FLOWINFO_MASK; | 91 | fib_params.flowlabel = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK; |
74 | fib_params.l4_protocol = iph->nexthdr; | 92 | fib_params.l4_protocol = ip6h->nexthdr; |
75 | fib_params.sport = 0; | 93 | fib_params.sport = 0; |
76 | fib_params.dport = 0; | 94 | fib_params.dport = 0; |
77 | fib_params.tot_len = ntohs(iph->payload_len); | 95 | fib_params.tot_len = ntohs(ip6h->payload_len); |
78 | *src = iph->saddr; | 96 | *src = ip6h->saddr; |
79 | *dst = iph->daddr; | 97 | *dst = ip6h->daddr; |
80 | } else { | 98 | } else { |
81 | return XDP_PASS; | 99 | return XDP_PASS; |
82 | } | 100 | } |
@@ -92,6 +110,11 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) | |||
92 | * forwarding packets are dropped. | 110 | * forwarding packets are dropped. |
93 | */ | 111 | */ |
94 | if (out_index > 0) { | 112 | if (out_index > 0) { |
113 | if (h_proto == htons(ETH_P_IP)) | ||
114 | ip_decrease_ttl(iph); | ||
115 | else if (h_proto == htons(ETH_P_IPV6)) | ||
116 | ip6h->hop_limit--; | ||
117 | |||
95 | memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN); | 118 | memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN); |
96 | memcpy(eth->h_source, fib_params.smac, ETH_ALEN); | 119 | memcpy(eth->h_source, fib_params.smac, ETH_ALEN); |
97 | return bpf_redirect_map(&tx_port, out_index, 0); | 120 | return bpf_redirect_map(&tx_port, out_index, 0); |