Skip to content

Commit 70434ec

Browse files
ebirgerKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
selftests/bpf: test setting tunnel key from lwt xmit
This commit adds test_egress_md() tests which perform a similar flow as test_egress() only that they use gre devices in collect_md mode and set the tunnel key from lwt bpf xmit. VRF scenarios are not checked since it is currently not possible to set the underlying device or vrf from bpf_set_tunnel_key(). This introduces minor changes to the existing setup for consistency with the new tests: - GRE key must exist as bpf_set_tunnel_key() explicitly sets the TUNNEL_KEY flag - Source address for GRE traffic is set to IPv*_5 instead of IPv*_1 since GRE traffic is sent via veth5 so its address is selected when using bpf_set_tunnel_key() Signed-off-by: Eyal Birger <[email protected]>
1 parent d02111b commit 70434ec

File tree

2 files changed

+128
-8
lines changed

2 files changed

+128
-8
lines changed

tools/testing/selftests/bpf/progs/test_lwt_ip_encap.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
struct grehdr {
1111
__be16 flags;
1212
__be16 protocol;
13+
__be32 key;
1314
};
1415

16+
#define GRE_KEY 0x2000
17+
1518
SEC("encap_gre")
1619
int bpf_lwt_encap_gre(struct __sk_buff *skb)
1720
{
@@ -28,17 +31,18 @@ int bpf_lwt_encap_gre(struct __sk_buff *skb)
2831
hdr.iph.ttl = 0x40;
2932
hdr.iph.protocol = 47; /* IPPROTO_GRE */
3033
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
31-
hdr.iph.saddr = 0x640110ac; /* 172.16.1.100 */
34+
hdr.iph.saddr = 0x640510ac; /* 172.16.5.100 */
3235
hdr.iph.daddr = 0x641010ac; /* 172.16.16.100 */
3336
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
34-
hdr.iph.saddr = 0xac100164; /* 172.16.1.100 */
37+
hdr.iph.saddr = 0xac100564; /* 172.16.5.100 */
3538
hdr.iph.daddr = 0xac101064; /* 172.16.16.100 */
3639
#else
3740
#error "Fix your compiler's __BYTE_ORDER__?!"
3841
#endif
3942
hdr.iph.tot_len = bpf_htons(skb->len + sizeof(struct encap_hdr));
4043

4144
hdr.greh.protocol = skb->protocol;
45+
hdr.greh.flags = bpf_htons(GRE_KEY);
4246

4347
err = bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, &hdr,
4448
sizeof(struct encap_hdr));
@@ -63,16 +67,17 @@ int bpf_lwt_encap_gre6(struct __sk_buff *skb)
6367
hdr.ip6hdr.payload_len = bpf_htons(skb->len + sizeof(struct grehdr));
6468
hdr.ip6hdr.nexthdr = 47; /* IPPROTO_GRE */
6569
hdr.ip6hdr.hop_limit = 0x40;
66-
/* fb01::1 */
70+
/* fb05::1 */
6771
hdr.ip6hdr.saddr.s6_addr[0] = 0xfb;
68-
hdr.ip6hdr.saddr.s6_addr[1] = 1;
72+
hdr.ip6hdr.saddr.s6_addr[1] = 5;
6973
hdr.ip6hdr.saddr.s6_addr[15] = 1;
7074
/* fb10::1 */
7175
hdr.ip6hdr.daddr.s6_addr[0] = 0xfb;
7276
hdr.ip6hdr.daddr.s6_addr[1] = 0x10;
7377
hdr.ip6hdr.daddr.s6_addr[15] = 1;
7478

7579
hdr.greh.protocol = skb->protocol;
80+
hdr.greh.flags = bpf_htons(GRE_KEY);
7681

7782
err = bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, &hdr,
7883
sizeof(struct encap_hdr));
@@ -82,4 +87,42 @@ int bpf_lwt_encap_gre6(struct __sk_buff *skb)
8287
return BPF_LWT_REROUTE;
8388
}
8489

90+
SEC("encap_gre_md")
91+
int bpf_lwt_encap_gre_md(struct __sk_buff *skb)
92+
{
93+
struct bpf_tunnel_key key;
94+
int err;
95+
96+
__builtin_memset(&key, 0x0, sizeof(key));
97+
key.remote_ipv4 = 0xac101064; /* 172.16.16.100 - always in host order */
98+
key.tunnel_ttl = 0x40;
99+
err = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
100+
BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);
101+
if (err)
102+
return BPF_DROP;
103+
104+
return BPF_OK;
105+
}
106+
107+
SEC("encap_gre6_md")
108+
int bpf_lwt_encap_gre6_md(struct __sk_buff *skb)
109+
{
110+
struct bpf_tunnel_key key;
111+
int err;
112+
113+
__builtin_memset(&key, 0x0, sizeof(key));
114+
115+
/* fb10::1 */
116+
key.remote_ipv6[0] = bpf_htonl(0xfb100000);
117+
key.remote_ipv6[3] = bpf_htonl(0x01);
118+
key.tunnel_ttl = 0x40;
119+
err = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
120+
BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER |
121+
BPF_F_TUNINFO_IPV6);
122+
if (err)
123+
return BPF_DROP;
124+
125+
return BPF_OK;
126+
}
127+
85128
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/test_lwt_ip_encap.sh

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@
3737
#
3838
# ping: SRC->[encap at veth2:ingress]->GRE:decap->DST
3939
# ping replies go DST->SRC directly
40+
#
41+
# 2c. in an egress_md test, a bpf LWT_XMIT program is installed on a
42+
# route towards a collect_md gre{,6} device and sets the tunnel key
43+
# such that packets are encapsulated with an IP/GRE header to route
44+
# to IPv*_GRE
45+
#
46+
# ping: SRC->[encap at gre{,6}_md:xmit]->GRE:decap->DST
47+
# ping replies go DST->SRC directly
4048

4149
if [[ $EUID -ne 0 ]]; then
4250
echo "This script must be run as root"
@@ -238,15 +246,15 @@ setup()
238246
ip -netns ${NS3} -6 route add ${IPv6_6}/128 dev veth8 via ${IPv6_7}
239247

240248
# configure IPv4 GRE device in NS3, and a route to it via the "bottom" route
241-
ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_1} local ${IPv4_GRE} ttl 255
249+
ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_5} local ${IPv4_GRE} ttl 255 key 0
242250
ip -netns ${NS3} link set gre_dev up
243251
ip -netns ${NS3} addr add ${IPv4_GRE} dev gre_dev
244252
ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6} ${VRF}
245253
ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8} ${VRF}
246254

247255

248256
# configure IPv6 GRE device in NS3, and a route to it via the "bottom" route
249-
ip -netns ${NS3} -6 tunnel add name gre6_dev mode ip6gre remote ${IPv6_1} local ${IPv6_GRE} ttl 255
257+
ip -netns ${NS3} -6 tunnel add name gre6_dev mode ip6gre remote ${IPv6_5} local ${IPv6_GRE} ttl 255 key 0
250258
ip -netns ${NS3} link set gre6_dev up
251259
ip -netns ${NS3} -6 addr add ${IPv6_GRE} nodad dev gre6_dev
252260
ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF}
@@ -291,13 +299,16 @@ test_ping()
291299
{
292300
local readonly PROTO=$1
293301
local readonly EXPECTED=$2
302+
local readonly NOBIND=$3
294303
local RET=0
295304

305+
BINDTODEV=$([ -z ${NOBIND} ] && echo -I veth1)
306+
296307
if [ "${PROTO}" == "IPv4" ] ; then
297-
ip netns exec ${NS1} ping -c 1 -W 1 -I veth1 ${IPv4_DST} 2>&1 > /dev/null
308+
ip netns exec ${NS1} ping -c 1 -W 1 ${BINDTODEV} ${IPv4_DST} 2>&1 > /dev/null
298309
RET=$?
299310
elif [ "${PROTO}" == "IPv6" ] ; then
300-
ip netns exec ${NS1} ping6 -c 1 -W 1 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
311+
ip netns exec ${NS1} ping6 -c 1 -W 1 ${BINDTODEV} ${IPv6_DST} 2>&1 > /dev/null
301312
RET=$?
302313
else
303314
echo " test_ping: unknown PROTO: ${PROTO}"
@@ -409,6 +420,70 @@ test_egress()
409420
process_test_results
410421
}
411422

423+
test_egress_md()
424+
{
425+
local readonly ENCAP=$1
426+
echo "starting egress_md ${ENCAP} encap test"
427+
setup
428+
429+
# by default, pings work
430+
test_ping IPv4 0
431+
test_ping IPv6 0
432+
433+
# remove NS2->DST routes, ping fails
434+
ip -netns ${NS2} route del ${IPv4_DST}/32 dev veth3
435+
ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3
436+
test_ping IPv4 1
437+
test_ping IPv6 1
438+
439+
# install replacement routes (LWT/eBPF), pings succeed
440+
if [ "${ENCAP}" == "IPv4" ] ; then
441+
ip -net ${NS1} link add gre_md type gre external
442+
ip -netns ${NS1} addr add ${IPv4_1}/24 dev gre_md
443+
ip -netns ${NS1} -6 addr add ${IPv6_1}/128 nodad dev gre_md
444+
ip -netns ${NS1} link set gre_md up
445+
446+
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
447+
test_lwt_ip_encap.o sec encap_gre_md dev gre_md
448+
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
449+
test_lwt_ip_encap.o sec encap_gre_md dev gre_md
450+
elif [ "${ENCAP}" == "IPv6" ] ; then
451+
ip -net ${NS1} link add gre6_md type ip6gre external
452+
ip -netns ${NS1} addr add ${IPv4_1}/24 dev gre6_md
453+
ip -netns ${NS1} -6 addr add ${IPv6_1}/128 nodad dev gre6_md
454+
ip -netns ${NS1} link set gre6_md up
455+
456+
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
457+
test_lwt_ip_encap.o sec encap_gre6_md dev gre6_md
458+
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
459+
test_lwt_ip_encap.o sec encap_gre6_md dev gre6_md
460+
else
461+
echo " unknown encap ${ENCAP}"
462+
TEST_STATUS=1
463+
fi
464+
465+
# Due to the asymmetry of the traffic flow we do not bind to device
466+
467+
test_ping IPv4 0 nobind
468+
test_ping IPv6 0 nobind
469+
470+
test_gso IPv4
471+
test_gso IPv6
472+
473+
# a negative test: remove routes to GRE devices: ping fails
474+
remove_routes_to_gredev
475+
test_ping IPv4 1 nobind
476+
test_ping IPv6 1 nobind
477+
478+
# another negative test
479+
add_unreachable_routes_to_gredev
480+
test_ping IPv4 1 nobind
481+
test_ping IPv6 1 nobind
482+
483+
cleanup
484+
process_test_results
485+
}
486+
412487
test_ingress()
413488
{
414489
local readonly ENCAP=$1
@@ -465,6 +540,8 @@ test_egress IPv4
465540
test_egress IPv6
466541
test_ingress IPv4
467542
test_ingress IPv6
543+
test_egress_md IPv4
544+
test_egress_md IPv6
468545

469546
VRF="vrf red"
470547
test_egress IPv4

0 commit comments

Comments
 (0)