xref: /linux/tools/testing/selftests/bpf/prog_tests/fib_lookup.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3 
4 #include <linux/rtnetlink.h>
5 #include <linux/if_ether.h>
6 #include <sys/types.h>
7 #include <net/if.h>
8 
9 #include "test_progs.h"
10 #include "network_helpers.h"
11 #include "fib_lookup.skel.h"
12 
13 #define NS_TEST			"fib_lookup_ns"
14 #define IPV6_IFACE_ADDR		"face::face"
15 #define IPV6_IFACE_ADDR_SEC	"cafe::cafe"
16 #define IPV6_ADDR_DST		"face::3"
17 #define IPV6_NUD_FAILED_ADDR	"face::1"
18 #define IPV6_NUD_STALE_ADDR	"face::2"
19 #define IPV4_IFACE_ADDR		"10.0.0.254"
20 #define IPV4_IFACE_ADDR_SEC	"10.1.0.254"
21 #define IPV4_ADDR_DST		"10.2.0.254"
22 #define IPV4_NUD_FAILED_ADDR	"10.0.0.1"
23 #define IPV4_NUD_STALE_ADDR	"10.0.0.2"
24 #define IPV4_TBID_ADDR		"172.0.0.254"
25 #define IPV4_TBID_NET		"172.0.0.0"
26 #define IPV4_TBID_DST		"172.0.0.2"
27 #define IPV4_TBID_NONEIGH_DST	"172.0.0.5"
28 #define IPV6_TBID_ADDR		"fd00::FFFF"
29 #define IPV6_TBID_NET		"fd00::"
30 #define IPV6_TBID_DST		"fd00::2"
31 #define MARK_NO_POLICY		33
32 #define MARK			42
33 #define MARK_TABLE		"200"
34 #define IPV4_REMOTE_DST		"1.2.3.4"
35 #define IPV4_LOCAL		"10.4.0.3"
36 #define IPV4_GW1		"10.4.0.1"
37 #define IPV4_GW2		"10.4.0.2"
38 #define IPV6_REMOTE_DST		"be:ef::b0:10"
39 #define IPV6_LOCAL		"fd01::3"
40 #define IPV6_GW1		"fd01::1"
41 #define IPV6_GW2		"fd01::2"
42 #define VLAN_ID			100
43 #define VLAN_IFACE		"veth1.100"
44 #define VLAN_ID_DOWN		102
45 #define VLAN_IFACE_DOWN		"veth1.102"
46 #define QINQ_OUTER_IFACE	"veth1.200"
47 #define QINQ_INNER_IFACE	"veth1.200.300"
48 #define VLAN_TABLE		"300"
49 #define IPV4_VLAN_IFACE_ADDR	"10.5.0.254"
50 #define IPV4_VLAN_EGRESS_DST	"10.5.0.2"
51 #define IPV4_QINQ_DST		"10.7.0.2"
52 #define IPV4_VLAN_DST		"10.6.0.2"
53 #define IPV4_VLAN_GW		"10.5.0.1"
54 #define IPV6_VLAN_IFACE_ADDR	"fd02::254"
55 #define IPV6_VLAN_EGRESS_DST	"fd02::2"
56 #define IPV6_VLAN_DST		"fd03::2"
57 #define IPV6_VLAN_GW		"fd02::1"
58 #define VLAN_VID_UNUSED		999
59 #define VRF_IFACE		"vrf-blue"
60 #define VRF_TABLE		"1000"
61 #define VRF_VLAN_ID		101
62 #define VRF_VLAN_IFACE		"veth1.101"
63 #define IPV4_VRF_IFACE_ADDR	"10.8.0.254"
64 #define IPV4_VRF_GW		"10.8.0.1"
65 #define IPV4_VRF_DST		"10.9.0.2"
66 #define TBID_VLAN_ID		50
67 #define TBID_VLAN_IFACE		"veth2.50"
68 #define IPV4_TBID_VLAN_DST	"172.2.0.2"
69 #define IPV4_BOND_VLAN_DST	"10.11.0.2"
70 #define IPV4_VLAN_MTU_DST	"10.5.9.2"
71 #define QINQ_AD_VLAN_ID		200
72 #define QINQ_INNER_VLAN_ID	300
73 #define BOND_IFACE		"bond99"
74 #define BOND_PORT		"veth3"
75 #define BOND_PORT_PEER		"veth4"
76 #define BOND_VLAN_ID		500
77 #define DMAC			"11:11:11:11:11:11"
78 #define DMAC_INIT { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, }
79 #define DMAC2			"01:01:01:01:01:01"
80 #define DMAC_INIT2 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }
81 
82 struct fib_lookup_test {
83 	const char *desc;
84 	const char *daddr;
85 	int expected_ret;
86 	const char *expected_src;
87 	const char *expected_dst;
88 	int lookup_flags;
89 	__u32 tbid;
90 	__u8 dmac[6];
91 	__u32 mark;
92 	/*
93 	 * input tag with BPF_FIB_LOOKUP_VLAN_INPUT; expected output tag
94 	 * with BPF_FIB_LOOKUP_VLAN (checked when check_vlan is set)
95 	 */
96 	__u16 vlan_proto;
97 	__u16 vlan_id;
98 	bool check_vlan;
99 	const char *expected_dev; /* expected params->ifindex after lookup */
100 	const char *iif;	  /* override the default veth1 input device */
101 	__u16 tot_len;		  /* triggers the in-lookup mtu check when set */
102 	__u16 expected_mtu;	  /* expected mtu_result (union with tot_len) */
103 };
104 
105 static const struct fib_lookup_test tests[] = {
106 	{ .desc = "IPv6 failed neigh",
107 	  .daddr = IPV6_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_NO_NEIGH, },
108 	{ .desc = "IPv6 stale neigh",
109 	  .daddr = IPV6_NUD_STALE_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
110 	  .dmac = DMAC_INIT, },
111 	{ .desc = "IPv6 skip neigh",
112 	  .daddr = IPV6_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
113 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH, },
114 	{ .desc = "IPv4 failed neigh",
115 	  .daddr = IPV4_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_NO_NEIGH, },
116 	{ .desc = "IPv4 stale neigh",
117 	  .daddr = IPV4_NUD_STALE_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
118 	  .dmac = DMAC_INIT, },
119 	{ .desc = "IPv4 skip neigh",
120 	  .daddr = IPV4_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
121 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH, },
122 	{ .desc = "IPv4 TBID lookup failure",
123 	  .daddr = IPV4_TBID_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
124 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID,
125 	  .tbid = RT_TABLE_MAIN, },
126 	{ .desc = "IPv4 TBID lookup success",
127 	  .daddr = IPV4_TBID_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
128 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID, .tbid = 100,
129 	  .dmac = DMAC_INIT2, },
130 	/*
131 	 * An error that returns after the egress device is resolved must
132 	 * report the egress ifindex, not the input. This routes from input
133 	 * veth1 via veth2 (table 100) to a dst with no neighbour, so
134 	 * input != egress, pinning NO_NEIGH to the egress device.
135 	 */
136 	{ .desc = "IPv4 NO_NEIGH reports the egress ifindex, not the input",
137 	  .daddr = IPV4_TBID_NONEIGH_DST,
138 	  .expected_ret = BPF_FIB_LKUP_RET_NO_NEIGH,
139 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID, .tbid = 100,
140 	  .expected_dev = "veth2", },
141 	{ .desc = "IPv6 TBID lookup failure",
142 	  .daddr = IPV6_TBID_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
143 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID,
144 	  .tbid = RT_TABLE_MAIN, },
145 	{ .desc = "IPv6 TBID lookup success",
146 	  .daddr = IPV6_TBID_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
147 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID, .tbid = 100,
148 	  .dmac = DMAC_INIT2, },
149 	{ .desc = "IPv4 set src addr from netdev",
150 	  .daddr = IPV4_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
151 	  .expected_src = IPV4_IFACE_ADDR,
152 	  .lookup_flags = BPF_FIB_LOOKUP_SRC | BPF_FIB_LOOKUP_SKIP_NEIGH, },
153 	{ .desc = "IPv6 set src addr from netdev",
154 	  .daddr = IPV6_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
155 	  .expected_src = IPV6_IFACE_ADDR,
156 	  .lookup_flags = BPF_FIB_LOOKUP_SRC | BPF_FIB_LOOKUP_SKIP_NEIGH, },
157 	{ .desc = "IPv4 set prefsrc addr from route",
158 	  .daddr = IPV4_ADDR_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
159 	  .expected_src = IPV4_IFACE_ADDR_SEC,
160 	  .lookup_flags = BPF_FIB_LOOKUP_SRC | BPF_FIB_LOOKUP_SKIP_NEIGH, },
161 	{ .desc = "IPv6 set prefsrc addr route",
162 	  .daddr = IPV6_ADDR_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
163 	  .expected_src = IPV6_IFACE_ADDR_SEC,
164 	  .lookup_flags = BPF_FIB_LOOKUP_SRC | BPF_FIB_LOOKUP_SKIP_NEIGH, },
165 	/* policy routing */
166 	{ .desc = "IPv4 policy routing, default",
167 	  .daddr = IPV4_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
168 	  .expected_dst = IPV4_GW1,
169 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH, },
170 	{ .desc = "IPv4 policy routing, mark doesn't point to a policy",
171 	  .daddr = IPV4_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
172 	  .expected_dst = IPV4_GW1,
173 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH,
174 	  .mark = MARK_NO_POLICY, },
175 	{ .desc = "IPv4 policy routing, mark points to a policy",
176 	  .daddr = IPV4_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
177 	  .expected_dst = IPV4_GW2,
178 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH,
179 	  .mark = MARK, },
180 	{ .desc = "IPv4 policy routing, mark points to a policy, but no flag",
181 	  .daddr = IPV4_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
182 	  .expected_dst = IPV4_GW1,
183 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH,
184 	  .mark = MARK, },
185 	{ .desc = "IPv6 policy routing, default",
186 	  .daddr = IPV6_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
187 	  .expected_dst = IPV6_GW1,
188 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH, },
189 	{ .desc = "IPv6 policy routing, mark doesn't point to a policy",
190 	  .daddr = IPV6_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
191 	  .expected_dst = IPV6_GW1,
192 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH,
193 	  .mark = MARK_NO_POLICY, },
194 	{ .desc = "IPv6 policy routing, mark points to a policy",
195 	  .daddr = IPV6_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
196 	  .expected_dst = IPV6_GW2,
197 	  .lookup_flags = BPF_FIB_LOOKUP_MARK | BPF_FIB_LOOKUP_SKIP_NEIGH,
198 	  .mark = MARK, },
199 	{ .desc = "IPv6 policy routing, mark points to a policy, but no flag",
200 	  .daddr = IPV6_REMOTE_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
201 	  .expected_dst = IPV6_GW1,
202 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH,
203 	  .mark = MARK, },
204 	/* vlan egress resolution */
205 	/*
206 	 * Invariant the VLAN-egress arms jointly enforce: a
207 	 * BPF_FIB_LOOKUP_VLAN SUCCESS always carries a physical,
208 	 * xmit-capable ifindex; no SUCCESS ever returns a VLAN-device
209 	 * ifindex. Reducible arms pin ifindex == the physical parent; the
210 	 * QinQ and foreign-netns arms pin VLAN_FAILURE with params->ifindex
211 	 * left at the input, so a regression to best-effort (SUCCESS + the
212 	 * VLAN ifindex) fails one.
213 	 */
214 	{ .desc = "IPv4 VLAN egress, no flag",
215 	  .daddr = IPV4_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
216 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH,
217 	  .expected_dev = VLAN_IFACE, .check_vlan = true, },
218 	{ .desc = "IPv4 VLAN egress, single VLAN",
219 	  .daddr = IPV4_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
220 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
221 	  .expected_dev = "veth1", .check_vlan = true,
222 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
223 	/*
224 	 * skb path without tot_len: mtu_result is the VLAN device's mtu
225 	 * (1400), not the parent's (1500)
226 	 */
227 	{ .desc = "IPv4 VLAN egress, skb-path mtu is the VLAN device's without the flag",
228 	  .daddr = IPV4_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
229 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH,
230 	  .expected_dev = VLAN_IFACE, .check_vlan = true, .expected_mtu = 1400, },
231 	{ .desc = "IPv4 VLAN egress, flag set but egress is not a VLAN",
232 	  .daddr = IPV4_NUD_FAILED_ADDR, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
233 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
234 	  .expected_dev = "veth1", .check_vlan = true, },
235 	{ .desc = "IPv4 VLAN egress, QinQ not reducible (VLAN_FAILURE)",
236 	  .daddr = IPV4_QINQ_DST,
237 	  .expected_ret = BPF_FIB_LKUP_RET_VLAN_FAILURE,
238 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
239 	  .expected_dev = "veth1", .check_vlan = true, },
240 	{ .desc = "IPv4 QinQ egress without the flag (escape hatch)",
241 	  .daddr = IPV4_QINQ_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
242 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH,
243 	  .expected_dev = QINQ_INNER_IFACE, },
244 	{ .desc = "IPv6 VLAN egress, single VLAN",
245 	  .daddr = IPV6_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
246 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
247 	  .expected_dev = "veth1", .check_vlan = true,
248 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
249 	{ .desc = "IPv4 VLAN egress, neighbour on the VLAN device",
250 	  .daddr = IPV4_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
251 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN,
252 	  .expected_dev = "veth1", .check_vlan = true,
253 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, .dmac = DMAC_INIT, },
254 	{ .desc = "IPv4 VLAN egress in OUTPUT mode",
255 	  .daddr = IPV4_VLAN_EGRESS_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
256 	  .iif = VLAN_IFACE,
257 	  .lookup_flags = BPF_FIB_LOOKUP_OUTPUT | BPF_FIB_LOOKUP_VLAN |
258 			  BPF_FIB_LOOKUP_SKIP_NEIGH,
259 	  .expected_dev = "veth1", .check_vlan = true,
260 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
261 	{ .desc = "IPv4 VLAN egress over a bond",
262 	  .daddr = IPV4_BOND_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
263 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
264 	  .expected_dev = BOND_IFACE, .check_vlan = true,
265 	  .vlan_proto = ETH_P_8021Q, .vlan_id = BOND_VLAN_ID, },
266 	{ .desc = "IPv4 VLAN egress via TBID table",
267 	  .daddr = IPV4_TBID_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
268 	  .lookup_flags = BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_TBID |
269 			  BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
270 	  .tbid = 100,
271 	  .expected_dev = "veth2", .check_vlan = true,
272 	  .vlan_proto = ETH_P_8021Q, .vlan_id = TBID_VLAN_ID, },
273 	{ .desc = "IPv4 VLAN egress, success writes mtu_result with the swap",
274 	  .daddr = IPV4_VLAN_MTU_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
275 	  .tot_len = 500, .expected_mtu = 1000,
276 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
277 	  .expected_dev = "veth1", .check_vlan = true,
278 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
279 	{ .desc = "IPv4 VLAN egress, FRAG_NEEDED reports mtu, swap unwritten",
280 	  .daddr = IPV4_VLAN_MTU_DST, .expected_ret = BPF_FIB_LKUP_RET_FRAG_NEEDED,
281 	  .tot_len = 1400, .expected_mtu = 1000,
282 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH,
283 	  .expected_dev = "veth1", .check_vlan = true, },
284 	/* vlan tag as lookup input */
285 	{ .desc = "IPv4 VLAN input, no flag",
286 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
287 	  .expected_dst = IPV4_GW1,
288 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH, },
289 	{ .desc = "IPv4 VLAN input, tag selects subinterface route",
290 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
291 	  .expected_dst = IPV4_VLAN_GW, .expected_dev = VLAN_IFACE,
292 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
293 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
294 	{ .desc = "IPv6 VLAN input, tag selects subinterface route",
295 	  .daddr = IPV6_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
296 	  .expected_dst = IPV6_VLAN_GW, .expected_dev = VLAN_IFACE,
297 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
298 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
299 	{ .desc = "IPv4 VLAN input and egress combined",
300 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
301 	  .expected_dst = IPV4_VLAN_GW, .expected_dev = "veth1",
302 	  .check_vlan = true,
303 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_VLAN |
304 			  BPF_FIB_LOOKUP_SKIP_NEIGH,
305 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
306 	{ .desc = "IPv4 VLAN input, neighbour resolved on the route",
307 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
308 	  .expected_dst = IPV4_VLAN_GW, .expected_dev = VLAN_IFACE,
309 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT,
310 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, .dmac = DMAC_INIT2, },
311 	{ .desc = "IPv4 VLAN input, source address from the subinterface",
312 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
313 	  .expected_src = IPV4_VLAN_IFACE_ADDR,
314 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SRC |
315 			  BPF_FIB_LOOKUP_SKIP_NEIGH,
316 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
317 	/*
318 	 * VRF: the resolved subinterface is enslaved, so the l3mdev rule
319 	 * (full lookup) and l3mdev_fib_table_rcu() (DIRECT) must select
320 	 * the VRF table from the resolved ingress
321 	 */
322 	{ .desc = "IPv4 VLAN input, VRF subinterface, no flag",
323 	  .daddr = IPV4_VRF_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
324 	  .expected_dst = IPV4_GW1,
325 	  .lookup_flags = BPF_FIB_LOOKUP_SKIP_NEIGH, },
326 	{ .desc = "IPv4 VLAN input, tag selects VRF table",
327 	  .daddr = IPV4_VRF_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
328 	  .expected_dst = IPV4_VRF_GW, .expected_dev = VRF_VLAN_IFACE,
329 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
330 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VRF_VLAN_ID, },
331 	{ .desc = "IPv4 VLAN input, DIRECT uses VRF table from resolved ingress",
332 	  .daddr = IPV4_VRF_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
333 	  .expected_dst = IPV4_VRF_GW, .expected_dev = VRF_VLAN_IFACE,
334 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_DIRECT |
335 			  BPF_FIB_LOOKUP_SKIP_NEIGH,
336 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VRF_VLAN_ID, },
337 	/*
338 	 * failure arms also assert params is left untouched: ifindex still
339 	 * names the physical device and the input tag bytes survive
340 	 */
341 	{ .desc = "IPv4 VLAN input, invalid proto",
342 	  .daddr = IPV4_VLAN_DST, .expected_ret = -EINVAL,
343 	  .expected_dev = "veth1", .check_vlan = true,
344 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
345 	  .vlan_proto = 0x1234, .vlan_id = VLAN_ID, },
346 	{ .desc = "IPv4 VLAN input, unmatched VID",
347 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
348 	  .expected_dev = "veth1", .check_vlan = true,
349 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
350 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_VID_UNUSED, },
351 	{ .desc = "IPv4 VLAN input, subinterface down",
352 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
353 	  .expected_dev = "veth1", .check_vlan = true,
354 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
355 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID_DOWN, },
356 	/*
357 	 * the resolver runs before the forwarding check, so on devices
358 	 * with forwarding off FWD_DISABLED (not NOT_FWDED) proves the tag
359 	 * resolved to that device and the lookup used it as ingress
360 	 */
361 	{ .desc = "IPv4 VLAN input, 802.1ad tag",
362 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_FWD_DISABLED,
363 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
364 	  .vlan_proto = ETH_P_8021AD, .vlan_id = QINQ_AD_VLAN_ID, },
365 	{ .desc = "IPv4 VLAN input, PCP and DEI bits ignored in TCI",
366 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_SUCCESS,
367 	  .expected_dst = IPV4_VLAN_GW,
368 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
369 	  .vlan_proto = ETH_P_8021Q, .vlan_id = 0xe000 | VLAN_ID, },
370 	{ .desc = "IPv4 VLAN input, inner QinQ device from VLAN ifindex",
371 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_FWD_DISABLED,
372 	  .iif = QINQ_OUTER_IFACE,
373 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
374 	  .vlan_proto = ETH_P_8021Q, .vlan_id = QINQ_INNER_VLAN_ID, },
375 	/*
376 	 * bonding: the VLANs live on the master, as on receive, where the
377 	 * frame is steered to the master before VLAN processing; a port
378 	 * ifindex does not match (ports carry vid state but no VLAN devs)
379 	 */
380 	{ .desc = "IPv4 VLAN input, tag on bond master resolves",
381 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_FWD_DISABLED,
382 	  .iif = BOND_IFACE,
383 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
384 	  .vlan_proto = ETH_P_8021Q, .vlan_id = BOND_VLAN_ID, },
385 	{ .desc = "IPv4 VLAN input, tag on bond port does not match",
386 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
387 	  .iif = BOND_PORT, .expected_dev = BOND_PORT, .check_vlan = true,
388 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
389 	  .vlan_proto = ETH_P_8021Q, .vlan_id = BOND_VLAN_ID, },
390 	{ .desc = "IPv6 VLAN input, invalid proto",
391 	  .daddr = IPV6_VLAN_DST, .expected_ret = -EINVAL,
392 	  .expected_dev = "veth1", .check_vlan = true,
393 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
394 	  .vlan_proto = 0x1234, .vlan_id = VLAN_ID, },
395 	{ .desc = "IPv4 VLAN input, VID 0 priority tag fails closed",
396 	  .daddr = IPV4_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
397 	  .expected_dev = "veth1", .check_vlan = true,
398 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
399 	  .vlan_proto = ETH_P_8021Q, .vlan_id = 0, },
400 	{ .desc = "IPv6 VLAN input, unmatched VID",
401 	  .daddr = IPV6_VLAN_DST, .expected_ret = BPF_FIB_LKUP_RET_NOT_FWDED,
402 	  .expected_dev = "veth1", .check_vlan = true,
403 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_SKIP_NEIGH,
404 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_VID_UNUSED, },
405 	{ .desc = "unknown flag bit rejected",
406 	  .daddr = IPV4_VLAN_DST, .expected_ret = -EINVAL,
407 	  .lookup_flags = (1 << 14) | BPF_FIB_LOOKUP_SKIP_NEIGH, },
408 	{ .desc = "IPv4 VLAN input rejected with TBID",
409 	  .daddr = IPV4_VLAN_DST, .expected_ret = -EINVAL,
410 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_TBID,
411 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
412 	{ .desc = "IPv4 VLAN input rejected with OUTPUT",
413 	  .daddr = IPV4_VLAN_DST, .expected_ret = -EINVAL,
414 	  .lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT | BPF_FIB_LOOKUP_OUTPUT,
415 	  .vlan_proto = ETH_P_8021Q, .vlan_id = VLAN_ID, },
416 };
417 
setup_netns(void)418 static int setup_netns(void)
419 {
420 	int err;
421 
422 	/*
423 	 * a new netns copies the IPv4 conf from init_net, so on a host with
424 	 * forwarding enabled the arms that expect FWD_DISABLED would see the
425 	 * lookup succeed instead; pin it off here and enable it per device
426 	 */
427 	err = write_sysctl("/proc/sys/net/ipv4/conf/all/forwarding", "0");
428 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.conf.all.forwarding)"))
429 		goto fail;
430 
431 	err = write_sysctl("/proc/sys/net/ipv4/conf/default/forwarding", "0");
432 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.conf.default.forwarding)"))
433 		goto fail;
434 
435 	SYS(fail, "ip link add veth1 type veth peer name veth2");
436 	SYS(fail, "ip link set dev veth1 up");
437 	SYS(fail, "ip link set dev veth2 up");
438 
439 	err = write_sysctl("/proc/sys/net/ipv4/neigh/veth1/gc_stale_time", "900");
440 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.neigh.veth1.gc_stale_time)"))
441 		goto fail;
442 
443 	err = write_sysctl("/proc/sys/net/ipv6/neigh/veth1/gc_stale_time", "900");
444 	if (!ASSERT_OK(err, "write_sysctl(net.ipv6.neigh.veth1.gc_stale_time)"))
445 		goto fail;
446 
447 	SYS(fail, "ip addr add %s/64 dev veth1 nodad", IPV6_IFACE_ADDR);
448 	SYS(fail, "ip neigh add %s dev veth1 nud failed", IPV6_NUD_FAILED_ADDR);
449 	SYS(fail, "ip neigh add %s dev veth1 lladdr %s nud stale", IPV6_NUD_STALE_ADDR, DMAC);
450 
451 	SYS(fail, "ip addr add %s/24 dev veth1", IPV4_IFACE_ADDR);
452 	SYS(fail, "ip neigh add %s dev veth1 nud failed", IPV4_NUD_FAILED_ADDR);
453 	SYS(fail, "ip neigh add %s dev veth1 lladdr %s nud stale", IPV4_NUD_STALE_ADDR, DMAC);
454 
455 	/* Setup for prefsrc IP addr selection */
456 	SYS(fail, "ip addr add %s/24 dev veth1", IPV4_IFACE_ADDR_SEC);
457 	SYS(fail, "ip route add %s/32 dev veth1 src %s", IPV4_ADDR_DST, IPV4_IFACE_ADDR_SEC);
458 
459 	SYS(fail, "ip addr add %s/64 dev veth1 nodad", IPV6_IFACE_ADDR_SEC);
460 	SYS(fail, "ip route add %s/128 dev veth1 src %s", IPV6_ADDR_DST, IPV6_IFACE_ADDR_SEC);
461 
462 	/* Setup for tbid lookup tests */
463 	SYS(fail, "ip addr add %s/24 dev veth2", IPV4_TBID_ADDR);
464 	SYS(fail, "ip route del %s/24 dev veth2", IPV4_TBID_NET);
465 	SYS(fail, "ip route add table 100 %s/24 dev veth2", IPV4_TBID_NET);
466 	SYS(fail, "ip neigh add %s dev veth2 lladdr %s nud stale", IPV4_TBID_DST, DMAC2);
467 
468 	SYS(fail, "ip addr add %s/64 dev veth2", IPV6_TBID_ADDR);
469 	SYS(fail, "ip -6 route del %s/64 dev veth2", IPV6_TBID_NET);
470 	SYS(fail, "ip -6 route add table 100 %s/64 dev veth2", IPV6_TBID_NET);
471 	SYS(fail, "ip neigh add %s dev veth2 lladdr %s nud stale", IPV6_TBID_DST, DMAC2);
472 
473 	err = write_sysctl("/proc/sys/net/ipv4/conf/veth1/forwarding", "1");
474 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.conf.veth1.forwarding)"))
475 		goto fail;
476 
477 	err = write_sysctl("/proc/sys/net/ipv6/conf/veth1/forwarding", "1");
478 	if (!ASSERT_OK(err, "write_sysctl(net.ipv6.conf.veth1.forwarding)"))
479 		goto fail;
480 
481 	/* Setup for policy routing tests */
482 	SYS(fail, "ip addr add %s/24 dev veth1", IPV4_LOCAL);
483 	SYS(fail, "ip addr add %s/64 dev veth1 nodad", IPV6_LOCAL);
484 	SYS(fail, "ip route add %s/32 via %s", IPV4_REMOTE_DST, IPV4_GW1);
485 	SYS(fail, "ip route add %s/32 via %s table %s", IPV4_REMOTE_DST, IPV4_GW2, MARK_TABLE);
486 	SYS(fail, "ip -6 route add %s/128 via %s", IPV6_REMOTE_DST, IPV6_GW1);
487 	SYS(fail, "ip -6 route add %s/128 via %s table %s", IPV6_REMOTE_DST, IPV6_GW2, MARK_TABLE);
488 	SYS(fail, "ip rule add prio 2 fwmark %d lookup %s", MARK, MARK_TABLE);
489 	SYS(fail, "ip -6 rule add prio 2 fwmark %d lookup %s", MARK, MARK_TABLE);
490 
491 	/*
492 	 * Setup for vlan tests: a subinterface for egress resolution and
493 	 * tag-as-input, a QinQ stack, and an iif rule so the input tests
494 	 * observe which device the lookup used as ingress.
495 	 */
496 	SYS(fail, "ip link add link veth1 name %s type vlan id %d",
497 	    VLAN_IFACE, VLAN_ID);
498 	SYS(fail, "ip link set dev %s up", VLAN_IFACE);
499 	/*
500 	 * lower than the veth1 parent (1500): the skb-path mtu check uses the
501 	 * FIB result (VLAN) device, so mtu_result is this value, which the
502 	 * no-flag arm below pins
503 	 */
504 	SYS(fail, "ip link set dev %s mtu 1400", VLAN_IFACE);
505 	SYS(fail, "ip addr add %s/24 dev %s", IPV4_VLAN_IFACE_ADDR, VLAN_IFACE);
506 	SYS(fail, "ip addr add %s/64 dev %s nodad", IPV6_VLAN_IFACE_ADDR, VLAN_IFACE);
507 
508 	/*
509 	 * stays down: the input flag must treat its tag the way real
510 	 * ingress treats a frame arriving on a down VLAN device (drop)
511 	 */
512 	SYS(fail, "ip link add link veth1 name %s type vlan id %d",
513 	    VLAN_IFACE_DOWN, VLAN_ID_DOWN);
514 
515 	err = write_sysctl("/proc/sys/net/ipv4/conf/" VLAN_IFACE "/forwarding", "1");
516 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.conf." VLAN_IFACE ".forwarding)"))
517 		goto fail;
518 
519 	err = write_sysctl("/proc/sys/net/ipv6/conf/" VLAN_IFACE "/forwarding", "1");
520 	if (!ASSERT_OK(err, "write_sysctl(net.ipv6.conf." VLAN_IFACE ".forwarding)"))
521 		goto fail;
522 
523 	SYS(fail, "ip link add link veth1 name %s type vlan proto 802.1ad id 200",
524 	    QINQ_OUTER_IFACE);
525 	SYS(fail, "ip link add link %s name %s type vlan id 300",
526 	    QINQ_OUTER_IFACE, QINQ_INNER_IFACE);
527 	SYS(fail, "ip link set dev %s up", QINQ_OUTER_IFACE);
528 	SYS(fail, "ip link set dev %s up", QINQ_INNER_IFACE);
529 	SYS(fail, "ip route add %s/32 dev %s", IPV4_QINQ_DST, QINQ_INNER_IFACE);
530 
531 	SYS(fail, "ip route add %s/32 via %s", IPV4_VLAN_DST, IPV4_GW1);
532 	SYS(fail, "ip route add table %s %s/32 via %s",
533 	    VLAN_TABLE, IPV4_VLAN_DST, IPV4_VLAN_GW);
534 	SYS(fail, "ip rule add prio 3 iif %s lookup %s", VLAN_IFACE, VLAN_TABLE);
535 	SYS(fail, "ip -6 route add %s/128 via %s", IPV6_VLAN_DST, IPV6_GW1);
536 	SYS(fail, "ip -6 route add table %s %s/128 via %s",
537 	    VLAN_TABLE, IPV6_VLAN_DST, IPV6_VLAN_GW);
538 	SYS(fail, "ip -6 rule add prio 3 iif %s lookup %s", VLAN_IFACE, VLAN_TABLE);
539 
540 	/* a bond with one port and a VLAN on the bond */
541 	SYS(fail, "ip link add %s type bond", BOND_IFACE);
542 	SYS(fail, "ip link add %s type veth peer name %s", BOND_PORT, BOND_PORT_PEER);
543 	SYS(fail, "ip link set %s master %s", BOND_PORT, BOND_IFACE);
544 	SYS(fail, "ip link set dev %s up", BOND_IFACE);
545 	SYS(fail, "ip link set dev %s up", BOND_PORT);
546 	SYS(fail, "ip link add link %s name %s.%d type vlan id %d",
547 	    BOND_IFACE, BOND_IFACE, BOND_VLAN_ID, BOND_VLAN_ID);
548 	SYS(fail, "ip link set dev %s.%d up", BOND_IFACE, BOND_VLAN_ID);
549 	SYS(fail, "ip route add %s/32 dev %s.%d",
550 	    IPV4_BOND_VLAN_DST, BOND_IFACE, BOND_VLAN_ID);
551 
552 	/*
553 	 * a VRF with its own dedicated subinterface (the iif rules above
554 	 * must not see it), for the table-selection-by-ingress cases
555 	 */
556 	SYS(fail, "ip link add %s type vrf table %s", VRF_IFACE, VRF_TABLE);
557 	SYS(fail, "ip link set dev %s up", VRF_IFACE);
558 	SYS(fail, "ip link add link veth1 name %s type vlan id %d",
559 	    VRF_VLAN_IFACE, VRF_VLAN_ID);
560 	SYS(fail, "ip link set %s master %s", VRF_VLAN_IFACE, VRF_IFACE);
561 	SYS(fail, "ip link set dev %s up", VRF_VLAN_IFACE);
562 	SYS(fail, "ip addr add %s/24 dev %s", IPV4_VRF_IFACE_ADDR, VRF_VLAN_IFACE);
563 	err = write_sysctl("/proc/sys/net/ipv4/conf/" VRF_VLAN_IFACE "/forwarding", "1");
564 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.conf." VRF_VLAN_IFACE ".forwarding)"))
565 		goto fail;
566 	SYS(fail, "ip route add %s/32 via %s", IPV4_VRF_DST, IPV4_GW1);
567 	SYS(fail, "ip route add table %s %s/32 via %s",
568 	    VRF_TABLE, IPV4_VRF_DST, IPV4_VRF_GW);
569 
570 	/* neighbours on the VLAN subinterface for the non-SKIP_NEIGH cases */
571 	err = write_sysctl("/proc/sys/net/ipv4/neigh/" VLAN_IFACE "/gc_stale_time", "900");
572 	if (!ASSERT_OK(err, "write_sysctl(net.ipv4.neigh." VLAN_IFACE ".gc_stale_time)"))
573 		goto fail;
574 	SYS(fail, "ip neigh add %s dev %s lladdr %s nud stale",
575 	    IPV4_VLAN_EGRESS_DST, VLAN_IFACE, DMAC);
576 	SYS(fail, "ip neigh add %s dev %s lladdr %s nud stale",
577 	    IPV4_VLAN_GW, VLAN_IFACE, DMAC2);
578 
579 	/* a VLAN on veth2 with a route in the tbid test table */
580 	SYS(fail, "ip link add link veth2 name %s type vlan id %d",
581 	    TBID_VLAN_IFACE, TBID_VLAN_ID);
582 	SYS(fail, "ip link set dev %s up", TBID_VLAN_IFACE);
583 	SYS(fail, "ip route add table 100 %s/32 dev %s",
584 	    IPV4_TBID_VLAN_DST, TBID_VLAN_IFACE);
585 
586 	/* a locked-mtu route via the subinterface for the FRAG_NEEDED case */
587 	SYS(fail, "ip route add %s/32 dev %s mtu lock 1000",
588 	    IPV4_VLAN_MTU_DST, VLAN_IFACE);
589 
590 	return 0;
591 fail:
592 	return -1;
593 }
594 
set_lookup_params(struct bpf_fib_lookup * params,const struct fib_lookup_test * test,int ifindex)595 static int set_lookup_params(struct bpf_fib_lookup *params,
596 			     const struct fib_lookup_test *test,
597 			     int ifindex)
598 {
599 	int ret;
600 
601 	memset(params, 0, sizeof(*params));
602 
603 	params->l4_protocol = IPPROTO_TCP;
604 	params->ifindex = test->iif ? if_nametoindex(test->iif) : ifindex;
605 	params->tbid = test->tbid;
606 	params->mark = test->mark;
607 	params->tot_len = test->tot_len;
608 
609 	/* h_vlan_proto/h_vlan_TCI union with tbid */
610 	if (test->lookup_flags & BPF_FIB_LOOKUP_VLAN_INPUT) {
611 		params->h_vlan_proto = htons(test->vlan_proto);
612 		params->h_vlan_TCI = htons(test->vlan_id);
613 	}
614 
615 	if (inet_pton(AF_INET6, test->daddr, params->ipv6_dst) == 1) {
616 		params->family = AF_INET6;
617 		if (!(test->lookup_flags & BPF_FIB_LOOKUP_SRC)) {
618 			ret = inet_pton(AF_INET6, IPV6_IFACE_ADDR, params->ipv6_src);
619 			if (!ASSERT_EQ(ret, 1, "inet_pton(IPV6_IFACE_ADDR)"))
620 				return -1;
621 		}
622 
623 		return 0;
624 	}
625 
626 	ret = inet_pton(AF_INET, test->daddr, &params->ipv4_dst);
627 	if (!ASSERT_EQ(ret, 1, "convert IP[46] address"))
628 		return -1;
629 	params->family = AF_INET;
630 
631 	if (!(test->lookup_flags & BPF_FIB_LOOKUP_SRC)) {
632 		ret = inet_pton(AF_INET, IPV4_IFACE_ADDR, &params->ipv4_src);
633 		if (!ASSERT_EQ(ret, 1, "inet_pton(IPV4_IFACE_ADDR)"))
634 			return -1;
635 	}
636 
637 	return 0;
638 }
639 
mac_str(char * b,const __u8 * mac)640 static void mac_str(char *b, const __u8 *mac)
641 {
642 	sprintf(b, "%02X:%02X:%02X:%02X:%02X:%02X",
643 		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
644 }
645 
assert_ip_address(int family,void * addr,const char * expected_str)646 static void assert_ip_address(int family, void *addr, const char *expected_str)
647 {
648 	char str[INET6_ADDRSTRLEN];
649 	u8 expected_addr[16];
650 	int addr_len = 0;
651 	int ret;
652 
653 	switch (family) {
654 	case AF_INET6:
655 		ret = inet_pton(AF_INET6, expected_str, expected_addr);
656 		ASSERT_EQ(ret, 1, "inet_pton(AF_INET6, expected_str)");
657 		addr_len = 16;
658 		break;
659 	case AF_INET:
660 		ret = inet_pton(AF_INET, expected_str, expected_addr);
661 		ASSERT_EQ(ret, 1, "inet_pton(AF_INET, expected_str)");
662 		addr_len = 4;
663 		break;
664 	default:
665 		PRINT_FAIL("invalid address family: %d", family);
666 		break;
667 	}
668 
669 	if (memcmp(addr, expected_addr, addr_len)) {
670 		inet_ntop(family, addr, str, sizeof(str));
671 		PRINT_FAIL("expected %s actual %s ", expected_str, str);
672 	}
673 }
674 
assert_src_ip(struct bpf_fib_lookup * params,const char * expected)675 static void assert_src_ip(struct bpf_fib_lookup *params, const char *expected)
676 {
677 	assert_ip_address(params->family, params->ipv6_src, expected);
678 }
679 
assert_dst_ip(struct bpf_fib_lookup * params,const char * expected)680 static void assert_dst_ip(struct bpf_fib_lookup *params, const char *expected)
681 {
682 	assert_ip_address(params->family, params->ipv6_dst, expected);
683 }
684 
test_fib_lookup(void)685 void test_fib_lookup(void)
686 {
687 	struct bpf_fib_lookup *fib_params;
688 	struct nstoken *nstoken = NULL;
689 	struct __sk_buff skb = { };
690 	struct fib_lookup *skel;
691 	int prog_fd, xdp_fd, err, ret, i;
692 
693 	/* The test does not use the skb->data, so
694 	 * use pkt_v6 for both v6 and v4 test.
695 	 */
696 	LIBBPF_OPTS(bpf_test_run_opts, run_opts,
697 		    .data_in = &pkt_v6,
698 		    .data_size_in = sizeof(pkt_v6),
699 		    .ctx_in = &skb,
700 		    .ctx_size_in = sizeof(skb),
701 	);
702 	LIBBPF_OPTS(bpf_test_run_opts, xdp_opts,
703 		    .data_in = &pkt_v6,
704 		    .data_size_in = sizeof(pkt_v6),
705 	);
706 
707 	skel = fib_lookup__open_and_load();
708 	if (!ASSERT_OK_PTR(skel, "skel open_and_load"))
709 		return;
710 	prog_fd = bpf_program__fd(skel->progs.fib_lookup);
711 	xdp_fd = bpf_program__fd(skel->progs.fib_lookup_xdp);
712 
713 	SYS(fail, "ip netns add %s", NS_TEST);
714 
715 	nstoken = open_netns(NS_TEST);
716 	if (!ASSERT_OK_PTR(nstoken, "open_netns"))
717 		goto fail;
718 
719 	if (setup_netns())
720 		goto fail;
721 
722 	skb.ifindex = if_nametoindex("veth1");
723 	if (!ASSERT_NEQ(skb.ifindex, 0, "if_nametoindex(veth1)"))
724 		goto fail;
725 
726 	fib_params = &skel->bss->fib_params;
727 
728 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
729 		printf("Testing %s ", tests[i].desc);
730 
731 		if (set_lookup_params(fib_params, &tests[i], skb.ifindex))
732 			continue;
733 
734 		skel->bss->fib_lookup_ret = -1;
735 		skel->bss->lookup_flags = tests[i].lookup_flags;
736 
737 		err = bpf_prog_test_run_opts(prog_fd, &run_opts);
738 		if (!ASSERT_OK(err, "bpf_prog_test_run_opts"))
739 			continue;
740 
741 		/*
742 		 * BPF_FIB_LOOKUP_VLAN is XDP-only; the tc helper rejects it.
743 		 * These cases are exercised on the XDP path below.
744 		 */
745 		if (tests[i].lookup_flags & BPF_FIB_LOOKUP_VLAN) {
746 			ASSERT_EQ(skel->bss->fib_lookup_ret, -EINVAL,
747 				  "tc rejects BPF_FIB_LOOKUP_VLAN");
748 			continue;
749 		}
750 
751 		ASSERT_EQ(skel->bss->fib_lookup_ret, tests[i].expected_ret,
752 			  "fib_lookup_ret");
753 
754 		if (tests[i].expected_src)
755 			assert_src_ip(fib_params, tests[i].expected_src);
756 
757 		if (tests[i].expected_dst)
758 			assert_dst_ip(fib_params, tests[i].expected_dst);
759 
760 		if (tests[i].expected_dev)
761 			ASSERT_EQ(fib_params->ifindex,
762 				  if_nametoindex(tests[i].expected_dev), "ifindex");
763 
764 		if (tests[i].expected_mtu)
765 			ASSERT_EQ(fib_params->mtu_result, tests[i].expected_mtu,
766 				  "mtu_result");
767 
768 		if (tests[i].check_vlan) {
769 			ASSERT_EQ(fib_params->h_vlan_proto,
770 				  htons(tests[i].vlan_proto), "h_vlan_proto");
771 			ASSERT_EQ(fib_params->h_vlan_TCI,
772 				  htons(tests[i].vlan_id), "h_vlan_TCI");
773 		}
774 
775 		ret = memcmp(tests[i].dmac, fib_params->dmac, sizeof(tests[i].dmac));
776 		if (!ASSERT_EQ(ret, 0, "dmac not match")) {
777 			char expected[18], actual[18];
778 
779 			mac_str(expected, tests[i].dmac);
780 			mac_str(actual, fib_params->dmac);
781 			printf("dmac expected %s actual %s ", expected, actual);
782 		}
783 
784 		/*
785 		 * ensure tbid is zero'd out after fib lookup. With
786 		 * BPF_FIB_LOOKUP_VLAN the union holds the packed vlan
787 		 * fields instead, so skip the check for those.
788 		 */
789 		if ((tests[i].lookup_flags & BPF_FIB_LOOKUP_DIRECT) &&
790 		    !(tests[i].lookup_flags & BPF_FIB_LOOKUP_VLAN)) {
791 			if (!ASSERT_EQ(skel->bss->fib_params.tbid, 0,
792 					"expected fib_params.tbid to be zero"))
793 				goto fail;
794 		}
795 	}
796 
797 	/*
798 	 * Re-run the cases through bpf_xdp_fib_lookup(). test_run uses the
799 	 * current netns' loopback for ctx->rxq->dev, so dev_net() is NS_TEST
800 	 * and the lookup runs against its FIB. The path-independent results
801 	 * (return code, swapped ifindex, vlan tag, gateway) must match the skb
802 	 * path; the no-tot_len mtu_result is skb-specific and not rechecked.
803 	 */
804 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
805 		if (set_lookup_params(fib_params, &tests[i], skb.ifindex))
806 			continue;
807 
808 		skel->bss->fib_lookup_ret = -1;
809 		skel->bss->lookup_flags = tests[i].lookup_flags;
810 
811 		err = bpf_prog_test_run_opts(xdp_fd, &xdp_opts);
812 		if (!ASSERT_OK(err, "xdp test_run"))
813 			continue;
814 
815 		if (!ASSERT_EQ(skel->bss->fib_lookup_ret, tests[i].expected_ret,
816 			       "xdp fib_lookup_ret"))
817 			printf("(xdp) %s\n", tests[i].desc);
818 
819 		if (tests[i].expected_dev)
820 			ASSERT_EQ(fib_params->ifindex,
821 				  if_nametoindex(tests[i].expected_dev),
822 				  "xdp ifindex");
823 
824 		if (tests[i].expected_dst)
825 			assert_dst_ip(fib_params, tests[i].expected_dst);
826 
827 		if (tests[i].check_vlan) {
828 			ASSERT_EQ(fib_params->h_vlan_proto,
829 				  htons(tests[i].vlan_proto), "xdp h_vlan_proto");
830 			ASSERT_EQ(fib_params->h_vlan_TCI,
831 				  htons(tests[i].vlan_id), "xdp h_vlan_TCI");
832 		}
833 
834 		ret = memcmp(tests[i].dmac, fib_params->dmac, sizeof(tests[i].dmac));
835 		ASSERT_EQ(ret, 0, "xdp dmac");
836 
837 		/*
838 		 * mtu_result from a tot_len lookup is the route mtu and is
839 		 * path-independent; the no-tot_len arm reads dev->mtu and is
840 		 * skb-only, so gate on tot_len
841 		 */
842 		if (tests[i].expected_mtu && tests[i].tot_len)
843 			ASSERT_EQ(fib_params->mtu_result, tests[i].expected_mtu,
844 				  "xdp mtu_result");
845 	}
846 
847 fail:
848 	if (nstoken)
849 		close_netns(nstoken);
850 	SYS_NOFAIL("ip netns del " NS_TEST);
851 	fib_lookup__destroy(skel);
852 }
853 
854 #define NS_VLAN_A	"fib_lookup_vlan_ns_a"
855 #define NS_VLAN_B	"fib_lookup_vlan_ns_b"
856 #define IPV4_VLAN_NETNS_ADDR	"10.66.0.1"
857 #define IPV4_VLAN_NETNS_DST	"10.66.0.2"
858 
859 /*
860  * A VLAN device can be moved to another netns while staying registered
861  * on its parent. Neither direction may then cross the boundary: the
862  * egress flag must not publish the foreign parent's ifindex, and the
863  * input flag must fail closed rather than use a foreign ingress.
864  */
test_fib_lookup_vlan_netns(void)865 void test_fib_lookup_vlan_netns(void)
866 {
867 	struct bpf_fib_lookup *fib_params;
868 	struct nstoken *nstoken = NULL;
869 	struct __sk_buff skb = { };
870 	struct fib_lookup *skel = NULL;
871 	int prog_fd, xdp_fd, err, parent_idx, vlan_idx;
872 
873 	LIBBPF_OPTS(bpf_test_run_opts, run_opts,
874 		    .data_in = &pkt_v6,
875 		    .data_size_in = sizeof(pkt_v6),
876 		    .ctx_in = &skb,
877 		    .ctx_size_in = sizeof(skb),
878 	);
879 	LIBBPF_OPTS(bpf_test_run_opts, xdp_opts,
880 		    .data_in = &pkt_v6,
881 		    .data_size_in = sizeof(pkt_v6),
882 	);
883 
884 	skel = fib_lookup__open_and_load();
885 	if (!ASSERT_OK_PTR(skel, "skel open_and_load"))
886 		return;
887 	prog_fd = bpf_program__fd(skel->progs.fib_lookup);
888 	xdp_fd = bpf_program__fd(skel->progs.fib_lookup_xdp);
889 	fib_params = &skel->bss->fib_params;
890 
891 	SYS(fail, "ip netns add %s", NS_VLAN_A);
892 	SYS(fail, "ip netns add %s", NS_VLAN_B);
893 
894 	nstoken = open_netns(NS_VLAN_A);
895 	if (!ASSERT_OK_PTR(nstoken, "open_netns(a)"))
896 		goto fail;
897 
898 	SYS(fail, "ip link add veth7 type veth peer name veth8");
899 	SYS(fail, "ip link set dev veth7 up");
900 	SYS(fail, "ip link add link veth7 name veth7.66 type vlan id 66");
901 	SYS(fail, "ip link set veth7.66 netns %s", NS_VLAN_B);
902 	/*
903 	 * up it in B before the input lookup: the move closed it, and a
904 	 * down device fails the resolver on IFF_UP before reaching the
905 	 * netns check this subtest exists to pin
906 	 */
907 	SYS(fail, "ip -n %s link set dev veth7.66 up", NS_VLAN_B);
908 
909 	parent_idx = if_nametoindex("veth7");
910 	if (!ASSERT_NEQ(parent_idx, 0, "if_nametoindex(veth7)"))
911 		goto fail;
912 
913 	/*
914 	 * give this netns a route to the destination: the lookup below runs
915 	 * against this FIB, so without the route a kernel that resolved the
916 	 * moved device anyway would still return NOT_FWDED and the arm would
917 	 * pass for the wrong reason
918 	 */
919 	SYS(fail, "ip route add %s/32 dev veth7", IPV4_VLAN_NETNS_DST);
920 
921 	/*
922 	 * input: the moved device is still in veth7's VLAN group, but it
923 	 * lives in another netns, so the lookup must fail closed
924 	 */
925 	skb.ifindex = parent_idx;
926 	memset(fib_params, 0, sizeof(*fib_params));
927 	fib_params->family = AF_INET;
928 	fib_params->l4_protocol = IPPROTO_TCP;
929 	fib_params->ifindex = parent_idx;
930 	fib_params->h_vlan_proto = htons(ETH_P_8021Q);
931 	fib_params->h_vlan_TCI = htons(66);
932 	if (!ASSERT_EQ(inet_pton(AF_INET, IPV4_VLAN_NETNS_DST, &fib_params->ipv4_dst),
933 		       1, "inet_pton(dst)"))
934 		goto fail;
935 
936 	skel->bss->fib_lookup_ret = -1;
937 	skel->bss->lookup_flags = BPF_FIB_LOOKUP_VLAN_INPUT |
938 				  BPF_FIB_LOOKUP_SKIP_NEIGH;
939 	err = bpf_prog_test_run_opts(prog_fd, &run_opts);
940 	if (!ASSERT_OK(err, "test_run(input)"))
941 		goto fail;
942 	ASSERT_EQ(skel->bss->fib_lookup_ret, BPF_FIB_LKUP_RET_NOT_FWDED,
943 		  "input across netns fails closed");
944 	ASSERT_EQ(fib_params->ifindex, parent_idx, "ifindex untouched");
945 	ASSERT_EQ(fib_params->h_vlan_TCI, htons(66), "tag untouched");
946 
947 	close_netns(nstoken);
948 	nstoken = open_netns(NS_VLAN_B);
949 	if (!ASSERT_OK_PTR(nstoken, "open_netns(b)"))
950 		goto fail;
951 
952 	/*
953 	 * egress: the fib result is the VLAN device here, but its parent
954 	 * is in the other netns, so the swap must not happen
955 	 */
956 	SYS(fail, "ip addr add %s/24 dev veth7.66", IPV4_VLAN_NETNS_ADDR);
957 	err = write_sysctl("/proc/sys/net/ipv4/conf/veth7.66/forwarding", "1");
958 	if (!ASSERT_OK(err, "write_sysctl(forwarding)"))
959 		goto fail;
960 
961 	vlan_idx = if_nametoindex("veth7.66");
962 	if (!ASSERT_NEQ(vlan_idx, 0, "if_nametoindex(veth7.66)"))
963 		goto fail;
964 
965 	memset(fib_params, 0, sizeof(*fib_params));
966 	fib_params->family = AF_INET;
967 	fib_params->l4_protocol = IPPROTO_TCP;
968 	fib_params->ifindex = vlan_idx;
969 	if (!ASSERT_EQ(inet_pton(AF_INET, IPV4_VLAN_NETNS_DST, &fib_params->ipv4_dst),
970 		       1, "inet_pton(dst)") ||
971 	    !ASSERT_EQ(inet_pton(AF_INET, IPV4_VLAN_NETNS_ADDR, &fib_params->ipv4_src),
972 		       1, "inet_pton(src)"))
973 		goto fail;
974 
975 	skel->bss->fib_lookup_ret = -1;
976 	skel->bss->lookup_flags = BPF_FIB_LOOKUP_VLAN |
977 				  BPF_FIB_LOOKUP_SKIP_NEIGH;
978 	err = bpf_prog_test_run_opts(xdp_fd, &xdp_opts);
979 	if (!ASSERT_OK(err, "test_run(egress)"))
980 		goto fail;
981 	ASSERT_EQ(skel->bss->fib_lookup_ret, BPF_FIB_LKUP_RET_VLAN_FAILURE,
982 		  "egress returns VLAN_FAILURE");
983 	ASSERT_EQ(fib_params->ifindex, vlan_idx,
984 		  "foreign parent not published");
985 	ASSERT_EQ(fib_params->h_vlan_TCI, 0, "vlan fields zero");
986 
987 fail:
988 	if (nstoken)
989 		close_netns(nstoken);
990 	SYS_NOFAIL("ip netns del " NS_VLAN_A);
991 	SYS_NOFAIL("ip netns del " NS_VLAN_B);
992 	fib_lookup__destroy(skel);
993 }
994 
995 #define REDIRECT_NPKTS 1000
996 #define NS_REDIRECT "fib_lookup_redirect_ns"
997 
998 /*
999  * The egress flag exists so an XDP program can redirect to the physical
1000  * parent. A redirect that lands on a VLAN device is dropped at
1001  * xdp_do_flush(), because a VLAN device has no ndo_xdp_xmit. Drive real
1002  * frames with BPF_F_TEST_XDP_LIVE_FRAMES, which runs the native
1003  * xdp_do_redirect() + xdp_do_flush() path: a reducible VLAN egress
1004  * resolves to veth1 and is delivered to its peer veth2, while a QinQ
1005  * egress returns VLAN_FAILURE and is passed to the stack instead of
1006  * redirected to a device that would silently drop it.
1007  */
test_fib_lookup_vlan_redirect(void)1008 void test_fib_lookup_vlan_redirect(void)
1009 {
1010 	int redirect_fd, err, veth1_idx, veth2_idx = -1;
1011 	struct bpf_fib_lookup *fib_params;
1012 	struct nstoken *nstoken = NULL;
1013 	struct fib_lookup *skel = NULL;
1014 	bool xdp_attached = false;
1015 
1016 	LIBBPF_OPTS(bpf_test_run_opts, lf_opts,
1017 		    .data_in = &pkt_v4,
1018 		    .data_size_in = sizeof(pkt_v4),
1019 		    .flags = BPF_F_TEST_XDP_LIVE_FRAMES,
1020 		    .repeat = REDIRECT_NPKTS,
1021 	);
1022 
1023 	skel = fib_lookup__open_and_load();
1024 	if (!ASSERT_OK_PTR(skel, "skel open_and_load"))
1025 		return;
1026 	redirect_fd = bpf_program__fd(skel->progs.fib_lookup_redirect);
1027 	fib_params = &skel->bss->fib_params;
1028 
1029 	SYS(fail, "ip netns add %s", NS_REDIRECT);
1030 	nstoken = open_netns(NS_REDIRECT);
1031 	if (!ASSERT_OK_PTR(nstoken, "open_netns"))
1032 		goto fail;
1033 	if (setup_netns())
1034 		goto fail;
1035 
1036 	veth1_idx = if_nametoindex("veth1");
1037 	veth2_idx = if_nametoindex("veth2");
1038 	if (!ASSERT_NEQ(veth1_idx, 0, "if_nametoindex(veth1)") ||
1039 	    !ASSERT_NEQ(veth2_idx, 0, "if_nametoindex(veth2)"))
1040 		goto fail;
1041 
1042 	/*
1043 	 * A redirect to veth1 is delivered to its peer veth2. veth_xdp_xmit()
1044 	 * only accepts the frame if veth2's NAPI is up, which on veth means
1045 	 * veth2 carries an XDP program; xdp_count tallies what arrives.
1046 	 */
1047 	err = bpf_xdp_attach(veth2_idx, bpf_program__fd(skel->progs.xdp_count),
1048 			     XDP_FLAGS_DRV_MODE, NULL);
1049 	if (!ASSERT_OK(err, "attach xdp_count on veth2"))
1050 		goto fail;
1051 	xdp_attached = true;
1052 
1053 	/* reducible VLAN egress: resolves to the physical parent veth1 */
1054 	memset(fib_params, 0, sizeof(*fib_params));
1055 	fib_params->family = AF_INET;
1056 	fib_params->l4_protocol = IPPROTO_TCP;
1057 	fib_params->ifindex = veth1_idx;
1058 	if (!ASSERT_EQ(inet_pton(AF_INET, IPV4_IFACE_ADDR, &fib_params->ipv4_src),
1059 		       1, "inet_pton(src)") ||
1060 	    !ASSERT_EQ(inet_pton(AF_INET, IPV4_VLAN_EGRESS_DST, &fib_params->ipv4_dst),
1061 		       1, "inet_pton(reducible dst)"))
1062 		goto fail;
1063 	skel->bss->lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH;
1064 	skel->bss->redirected = 0;
1065 	skel->bss->passed = 0;
1066 	skel->bss->delivered = 0;
1067 
1068 	err = bpf_prog_test_run_opts(redirect_fd, &lf_opts);
1069 	if (!ASSERT_OK(err, "test_run(reducible egress)"))
1070 		goto fail;
1071 	ASSERT_EQ(skel->bss->redirected, REDIRECT_NPKTS, "reducible egress redirected");
1072 	ASSERT_EQ(skel->bss->passed, 0, "reducible egress not passed");
1073 	ASSERT_GT(skel->bss->delivered, 0, "reducible egress delivered to veth2");
1074 
1075 	/*
1076 	 * QinQ egress: not reducible, so the lookup returns VLAN_FAILURE and
1077 	 * the program passes the frame instead of redirecting to the inner
1078 	 * VLAN device. redirected == 0 is the assertion that matters: the
1079 	 * program did not redirect to a device that would drop the frame at
1080 	 * xdp_do_flush(). veth2's delivered count is not checked here, since
1081 	 * a passed frame can still reach veth2 through the stack's forwarding
1082 	 * path, which is unrelated to the redirect under test.
1083 	 */
1084 	memset(fib_params, 0, sizeof(*fib_params));
1085 	fib_params->family = AF_INET;
1086 	fib_params->l4_protocol = IPPROTO_TCP;
1087 	fib_params->ifindex = veth1_idx;
1088 	if (!ASSERT_EQ(inet_pton(AF_INET, IPV4_IFACE_ADDR, &fib_params->ipv4_src),
1089 		       1, "inet_pton(src)") ||
1090 	    !ASSERT_EQ(inet_pton(AF_INET, IPV4_QINQ_DST, &fib_params->ipv4_dst),
1091 		       1, "inet_pton(qinq dst)"))
1092 		goto fail;
1093 	skel->bss->lookup_flags = BPF_FIB_LOOKUP_VLAN | BPF_FIB_LOOKUP_SKIP_NEIGH;
1094 	skel->bss->redirected = 0;
1095 	skel->bss->passed = 0;
1096 
1097 	err = bpf_prog_test_run_opts(redirect_fd, &lf_opts);
1098 	if (!ASSERT_OK(err, "test_run(qinq egress)"))
1099 		goto fail;
1100 	ASSERT_EQ(skel->bss->passed, REDIRECT_NPKTS, "qinq egress passed");
1101 	ASSERT_EQ(skel->bss->redirected, 0, "qinq egress not redirected");
1102 
1103 fail:
1104 	if (xdp_attached)
1105 		bpf_xdp_detach(veth2_idx, XDP_FLAGS_DRV_MODE, NULL);
1106 	if (nstoken)
1107 		close_netns(nstoken);
1108 	SYS_NOFAIL("ip netns del " NS_REDIRECT);
1109 	fib_lookup__destroy(skel);
1110 }
1111