~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/prog_tests/xfrm_info.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2 
  3 /*
  4  * Topology:
  5  * ---------
  6  *   NS0 namespace         |   NS1 namespace        | NS2 namespace
  7  *                         |                        |
  8  *   +---------------+     |   +---------------+    |
  9  *   |    ipsec0     |---------|    ipsec0     |    |
 10  *   | 192.168.1.100 |     |   | 192.168.1.200 |    |
 11  *   | if_id: bpf    |     |   +---------------+    |
 12  *   +---------------+     |                        |
 13  *           |             |                        |   +---------------+
 14  *           |             |                        |   |    ipsec0     |
 15  *           \------------------------------------------| 192.168.1.200 |
 16  *                         |                        |   +---------------+
 17  *                         |                        |
 18  *                         |                        | (overlay network)
 19  *      ------------------------------------------------------
 20  *                         |                        | (underlay network)
 21  *   +--------------+      |   +--------------+     |
 22  *   |    veth01    |----------|    veth10    |     |
 23  *   | 172.16.1.100 |      |   | 172.16.1.200 |     |
 24  *   ---------------+      |   +--------------+     |
 25  *                         |                        |
 26  *   +--------------+      |                        |   +--------------+
 27  *   |    veth02    |-----------------------------------|    veth20    |
 28  *   | 172.16.2.100 |      |                        |   | 172.16.2.200 |
 29  *   +--------------+      |                        |   +--------------+
 30  *
 31  *
 32  * Test Packet flow
 33  * -----------
 34  *  The tests perform 'ping 192.168.1.200' from the NS0 namespace:
 35  *  1) request is routed to NS0 ipsec0
 36  *  2) NS0 ipsec0 tc egress BPF program is triggered and sets the if_id based
 37  *     on the requested value. This makes the ipsec0 device in external mode
 38  *     select the destination tunnel
 39  *  3) ping reaches the other namespace (NS1 or NS2 based on which if_id was
 40  *     used) and response is sent
 41  *  4) response is received on NS0 ipsec0, tc ingress program is triggered and
 42  *     records the response if_id
 43  *  5) requested if_id is compared with received if_id
 44  */
 45 
 46 #include <net/if.h>
 47 #include <linux/rtnetlink.h>
 48 #include <linux/if_link.h>
 49 
 50 #include "test_progs.h"
 51 #include "network_helpers.h"
 52 #include "xfrm_info.skel.h"
 53 
 54 #define NS0 "xfrm_test_ns0"
 55 #define NS1 "xfrm_test_ns1"
 56 #define NS2 "xfrm_test_ns2"
 57 
 58 #define IF_ID_0_TO_1 1
 59 #define IF_ID_0_TO_2 2
 60 #define IF_ID_1 3
 61 #define IF_ID_2 4
 62 
 63 #define IP4_ADDR_VETH01 "172.16.1.100"
 64 #define IP4_ADDR_VETH10 "172.16.1.200"
 65 #define IP4_ADDR_VETH02 "172.16.2.100"
 66 #define IP4_ADDR_VETH20 "172.16.2.200"
 67 
 68 #define ESP_DUMMY_PARAMS \
 69     "proto esp aead 'rfc4106(gcm(aes))' " \
 70     "0xe4d8f4b4da1df18a3510b3781496daa82488b713 128 mode tunnel "
 71 
 72 static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
 73 {
 74         LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1, .priority = 1,
 75                     .prog_fd = igr_fd);
 76         LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1, .priority = 1,
 77                     .prog_fd = egr_fd);
 78         int ret;
 79 
 80         ret = bpf_tc_hook_create(hook);
 81         if (!ASSERT_OK(ret, "create tc hook"))
 82                 return ret;
 83 
 84         if (igr_fd >= 0) {
 85                 hook->attach_point = BPF_TC_INGRESS;
 86                 ret = bpf_tc_attach(hook, &opts1);
 87                 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
 88                         bpf_tc_hook_destroy(hook);
 89                         return ret;
 90                 }
 91         }
 92 
 93         if (egr_fd >= 0) {
 94                 hook->attach_point = BPF_TC_EGRESS;
 95                 ret = bpf_tc_attach(hook, &opts2);
 96                 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
 97                         bpf_tc_hook_destroy(hook);
 98                         return ret;
 99                 }
100         }
101 
102         return 0;
103 }
104 
105 static void cleanup(void)
106 {
107         SYS_NOFAIL("test -f /var/run/netns/" NS0 " && ip netns delete " NS0);
108         SYS_NOFAIL("test -f /var/run/netns/" NS1 " && ip netns delete " NS1);
109         SYS_NOFAIL("test -f /var/run/netns/" NS2 " && ip netns delete " NS2);
110 }
111 
112 static int config_underlay(void)
113 {
114         SYS(fail, "ip netns add " NS0);
115         SYS(fail, "ip netns add " NS1);
116         SYS(fail, "ip netns add " NS2);
117 
118         /* NS0 <-> NS1 [veth01 <-> veth10] */
119         SYS(fail, "ip link add veth01 netns " NS0 " type veth peer name veth10 netns " NS1);
120         SYS(fail, "ip -net " NS0 " addr add " IP4_ADDR_VETH01 "/24 dev veth01");
121         SYS(fail, "ip -net " NS0 " link set dev veth01 up");
122         SYS(fail, "ip -net " NS1 " addr add " IP4_ADDR_VETH10 "/24 dev veth10");
123         SYS(fail, "ip -net " NS1 " link set dev veth10 up");
124 
125         /* NS0 <-> NS2 [veth02 <-> veth20] */
126         SYS(fail, "ip link add veth02 netns " NS0 " type veth peer name veth20 netns " NS2);
127         SYS(fail, "ip -net " NS0 " addr add " IP4_ADDR_VETH02 "/24 dev veth02");
128         SYS(fail, "ip -net " NS0 " link set dev veth02 up");
129         SYS(fail, "ip -net " NS2 " addr add " IP4_ADDR_VETH20 "/24 dev veth20");
130         SYS(fail, "ip -net " NS2 " link set dev veth20 up");
131 
132         return 0;
133 fail:
134         return -1;
135 }
136 
137 static int setup_xfrm_tunnel_ns(const char *ns, const char *ipv4_local,
138                                 const char *ipv4_remote, int if_id)
139 {
140         /* State: local -> remote */
141         SYS(fail, "ip -net %s xfrm state add src %s dst %s spi 1 "
142             ESP_DUMMY_PARAMS "if_id %d", ns, ipv4_local, ipv4_remote, if_id);
143 
144         /* State: local <- remote */
145         SYS(fail, "ip -net %s xfrm state add src %s dst %s spi 1 "
146             ESP_DUMMY_PARAMS "if_id %d", ns, ipv4_remote, ipv4_local, if_id);
147 
148         /* Policy: local -> remote */
149         SYS(fail, "ip -net %s xfrm policy add dir out src 0.0.0.0/0 dst 0.0.0.0/0 "
150             "if_id %d tmpl src %s dst %s proto esp mode tunnel if_id %d", ns,
151             if_id, ipv4_local, ipv4_remote, if_id);
152 
153         /* Policy: local <- remote */
154         SYS(fail, "ip -net %s xfrm policy add dir in src 0.0.0.0/0 dst 0.0.0.0/0 "
155             "if_id %d tmpl src %s dst %s proto esp mode tunnel if_id %d", ns,
156             if_id, ipv4_remote, ipv4_local, if_id);
157 
158         return 0;
159 fail:
160         return -1;
161 }
162 
163 static int setup_xfrm_tunnel(const char *ns_a, const char *ns_b,
164                              const char *ipv4_a, const char *ipv4_b,
165                              int if_id_a, int if_id_b)
166 {
167         return setup_xfrm_tunnel_ns(ns_a, ipv4_a, ipv4_b, if_id_a) ||
168                 setup_xfrm_tunnel_ns(ns_b, ipv4_b, ipv4_a, if_id_b);
169 }
170 
171 static struct rtattr *rtattr_add(struct nlmsghdr *nh, unsigned short type,
172                                  unsigned short len)
173 {
174         struct rtattr *rta =
175                 (struct rtattr *)((uint8_t *)nh + RTA_ALIGN(nh->nlmsg_len));
176         rta->rta_type = type;
177         rta->rta_len = RTA_LENGTH(len);
178         nh->nlmsg_len = RTA_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta->rta_len);
179         return rta;
180 }
181 
182 static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type,
183                                      const char *s)
184 {
185         struct rtattr *rta = rtattr_add(nh, type, strlen(s));
186 
187         memcpy(RTA_DATA(rta), s, strlen(s));
188         return rta;
189 }
190 
191 static struct rtattr *rtattr_begin(struct nlmsghdr *nh, unsigned short type)
192 {
193         return rtattr_add(nh, type, 0);
194 }
195 
196 static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr)
197 {
198         uint8_t *end = (uint8_t *)nh + nh->nlmsg_len;
199 
200         attr->rta_len = end - (uint8_t *)attr;
201 }
202 
203 static int setup_xfrmi_external_dev(const char *ns)
204 {
205         struct {
206                 struct nlmsghdr nh;
207                 struct ifinfomsg info;
208                 unsigned char data[128];
209         } req;
210         struct rtattr *link_info, *info_data;
211         struct nstoken *nstoken;
212         int ret = -1, sock = -1;
213         struct nlmsghdr *nh;
214 
215         memset(&req, 0, sizeof(req));
216         nh = &req.nh;
217         nh->nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
218         nh->nlmsg_type = RTM_NEWLINK;
219         nh->nlmsg_flags |= NLM_F_CREATE | NLM_F_REQUEST;
220 
221         rtattr_add_str(nh, IFLA_IFNAME, "ipsec0");
222         link_info = rtattr_begin(nh, IFLA_LINKINFO);
223         rtattr_add_str(nh, IFLA_INFO_KIND, "xfrm");
224         info_data = rtattr_begin(nh, IFLA_INFO_DATA);
225         rtattr_add(nh, IFLA_XFRM_COLLECT_METADATA, 0);
226         rtattr_end(nh, info_data);
227         rtattr_end(nh, link_info);
228 
229         nstoken = open_netns(ns);
230         if (!ASSERT_OK_PTR(nstoken, "setns"))
231                 goto done;
232 
233         sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
234         if (!ASSERT_GE(sock, 0, "netlink socket"))
235                 goto done;
236         ret = send(sock, nh, nh->nlmsg_len, 0);
237         if (!ASSERT_EQ(ret, nh->nlmsg_len, "netlink send length"))
238                 goto done;
239 
240         ret = 0;
241 done:
242         if (sock != -1)
243                 close(sock);
244         if (nstoken)
245                 close_netns(nstoken);
246         return ret;
247 }
248 
249 static int config_overlay(void)
250 {
251         if (setup_xfrm_tunnel(NS0, NS1, IP4_ADDR_VETH01, IP4_ADDR_VETH10,
252                               IF_ID_0_TO_1, IF_ID_1))
253                 goto fail;
254         if (setup_xfrm_tunnel(NS0, NS2, IP4_ADDR_VETH02, IP4_ADDR_VETH20,
255                               IF_ID_0_TO_2, IF_ID_2))
256                 goto fail;
257 
258         /* Older iproute2 doesn't support this option */
259         if (!ASSERT_OK(setup_xfrmi_external_dev(NS0), "xfrmi"))
260                 goto fail;
261 
262         SYS(fail, "ip -net " NS0 " addr add 192.168.1.100/24 dev ipsec0");
263         SYS(fail, "ip -net " NS0 " link set dev ipsec0 up");
264 
265         SYS(fail, "ip -net " NS1 " link add ipsec0 type xfrm if_id %d", IF_ID_1);
266         SYS(fail, "ip -net " NS1 " addr add 192.168.1.200/24 dev ipsec0");
267         SYS(fail, "ip -net " NS1 " link set dev ipsec0 up");
268 
269         SYS(fail, "ip -net " NS2 " link add ipsec0 type xfrm if_id %d", IF_ID_2);
270         SYS(fail, "ip -net " NS2 " addr add 192.168.1.200/24 dev ipsec0");
271         SYS(fail, "ip -net " NS2 " link set dev ipsec0 up");
272 
273         return 0;
274 fail:
275         return -1;
276 }
277 
278 static int test_xfrm_ping(struct xfrm_info *skel, u32 if_id)
279 {
280         skel->bss->req_if_id = if_id;
281 
282         SYS(fail, "ping -i 0.01 -c 3 -w 10 -q 192.168.1.200 > /dev/null");
283 
284         if (!ASSERT_EQ(skel->bss->resp_if_id, if_id, "if_id"))
285                 goto fail;
286 
287         return 0;
288 fail:
289         return -1;
290 }
291 
292 static void _test_xfrm_info(void)
293 {
294         LIBBPF_OPTS(bpf_tc_hook, tc_hook, .attach_point = BPF_TC_INGRESS);
295         int get_xfrm_info_prog_fd, set_xfrm_info_prog_fd;
296         struct nstoken *nstoken = NULL;
297         struct xfrm_info *skel;
298         int ifindex;
299 
300         /* load and attach bpf progs to ipsec dev tc hook point */
301         skel = xfrm_info__open_and_load();
302         if (!ASSERT_OK_PTR(skel, "xfrm_info__open_and_load"))
303                 goto done;
304         nstoken = open_netns(NS0);
305         if (!ASSERT_OK_PTR(nstoken, "setns " NS0))
306                 goto done;
307         ifindex = if_nametoindex("ipsec0");
308         if (!ASSERT_NEQ(ifindex, 0, "ipsec0 ifindex"))
309                 goto done;
310         tc_hook.ifindex = ifindex;
311         set_xfrm_info_prog_fd = bpf_program__fd(skel->progs.set_xfrm_info);
312         get_xfrm_info_prog_fd = bpf_program__fd(skel->progs.get_xfrm_info);
313         if (!ASSERT_GE(set_xfrm_info_prog_fd, 0, "bpf_program__fd"))
314                 goto done;
315         if (!ASSERT_GE(get_xfrm_info_prog_fd, 0, "bpf_program__fd"))
316                 goto done;
317         if (attach_tc_prog(&tc_hook, get_xfrm_info_prog_fd,
318                            set_xfrm_info_prog_fd))
319                 goto done;
320 
321         /* perform test */
322         if (!ASSERT_EQ(test_xfrm_ping(skel, IF_ID_0_TO_1), 0, "ping " NS1))
323                 goto done;
324         if (!ASSERT_EQ(test_xfrm_ping(skel, IF_ID_0_TO_2), 0, "ping " NS2))
325                 goto done;
326 
327 done:
328         if (nstoken)
329                 close_netns(nstoken);
330         xfrm_info__destroy(skel);
331 }
332 
333 void test_xfrm_info(void)
334 {
335         cleanup();
336 
337         if (!ASSERT_OK(config_underlay(), "config_underlay"))
338                 goto done;
339         if (!ASSERT_OK(config_overlay(), "config_overlay"))
340                 goto done;
341 
342         if (test__start_subtest("xfrm_info"))
343                 _test_xfrm_info();
344 
345 done:
346         cleanup();
347 }
348 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php