1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <linux/if_tun.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14
15 #include "kselftest_harness.h"
16 #include "tuntap_helpers.h"
17
18 static const char param_dev_geneve_name[] = "geneve1";
19 static unsigned char param_hwaddr_outer_dst[] = { 0x00, 0xfe, 0x98,
20 0x14, 0x22, 0x42 };
21 static unsigned char param_hwaddr_outer_src[] = { 0x00, 0xfe, 0x98,
22 0x94, 0xd2, 0x43 };
23 static unsigned char param_hwaddr_inner_dst[] = { 0x00, 0xfe, 0x98,
24 0x94, 0x22, 0xcc };
25 static unsigned char param_hwaddr_inner_src[] = { 0x00, 0xfe, 0x98,
26 0x94, 0xd2, 0xdd };
27
28 static struct in_addr param_ipaddr4_outer_dst = {
29 __constant_htonl(0xac100001),
30 };
31
32 static struct in_addr param_ipaddr4_outer_src = {
33 __constant_htonl(0xac100002),
34 };
35
36 static struct in_addr param_ipaddr4_inner_dst = {
37 __constant_htonl(0xac100101),
38 };
39
40 static struct in_addr param_ipaddr4_inner_src = {
41 __constant_htonl(0xac100102),
42 };
43
44 static struct in6_addr param_ipaddr6_outer_dst = {
45 { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
46 };
47
48 static struct in6_addr param_ipaddr6_outer_src = {
49 { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } },
50 };
51
52 static struct in6_addr param_ipaddr6_inner_dst = {
53 { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
54 };
55
56 static struct in6_addr param_ipaddr6_inner_src = {
57 { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } },
58 };
59
60 #ifndef BIT
61 #define BIT(nr) (1UL << (nr))
62 #endif
63
64 #define VN_ID 1
65 #define VN_PORT 4789
66 #define UDP_SRC_PORT 22
67 #define UDP_DST_PORT 48878
68 #define IPPREFIX_LEN 24
69 #define IP6PREFIX_LEN 64
70 #define TIMEOUT_SEC 10
71 #define TIMEOUT_USEC 100000
72 #define MAX_RETRIES 20
73
74 #define UDP_TUNNEL_GENEVE_4IN4 0x01
75 #define UDP_TUNNEL_GENEVE_6IN4 0x02
76 #define UDP_TUNNEL_GENEVE_4IN6 0x04
77 #define UDP_TUNNEL_GENEVE_6IN6 0x08
78
79 #define UDP_TUNNEL_MAX_SEGMENTS BIT(7)
80
81 #define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_6IN4)
82 #define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_4IN6)
83
84 #define UDP_TUNNEL_GENEVE_4IN4_HDRLEN \
85 (ETH_HLEN + 2 * sizeof(struct iphdr) + GENEVE_HLEN + \
86 2 * sizeof(struct udphdr))
87 #define UDP_TUNNEL_GENEVE_6IN6_HDRLEN \
88 (ETH_HLEN + 2 * sizeof(struct ipv6hdr) + GENEVE_HLEN + \
89 2 * sizeof(struct udphdr))
90 #define UDP_TUNNEL_GENEVE_4IN6_HDRLEN \
91 (ETH_HLEN + sizeof(struct iphdr) + sizeof(struct ipv6hdr) + \
92 GENEVE_HLEN + 2 * sizeof(struct udphdr))
93 #define UDP_TUNNEL_GENEVE_6IN4_HDRLEN \
94 (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct iphdr) + \
95 GENEVE_HLEN + 2 * sizeof(struct udphdr))
96
97 #define UDP_TUNNEL_HDRLEN(type) \
98 ((type) == UDP_TUNNEL_GENEVE_4IN4 ? UDP_TUNNEL_GENEVE_4IN4_HDRLEN : \
99 (type) == UDP_TUNNEL_GENEVE_6IN6 ? UDP_TUNNEL_GENEVE_6IN6_HDRLEN : \
100 (type) == UDP_TUNNEL_GENEVE_4IN6 ? UDP_TUNNEL_GENEVE_4IN6_HDRLEN : \
101 (type) == UDP_TUNNEL_GENEVE_6IN4 ? UDP_TUNNEL_GENEVE_6IN4_HDRLEN : \
102 0)
103
104 #define UDP_TUNNEL_MSS(type) (ETH_DATA_LEN - UDP_TUNNEL_HDRLEN(type))
105 #define UDP_TUNNEL_MAX(type, is_tap) \
106 (ETH_MAX_MTU - UDP_TUNNEL_HDRLEN(type) - ((is_tap) ? ETH_HLEN : 0))
107
108 #define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel)
109 #define MAX_VNET_TUNNEL_PACKET_SZ \
110 (TUN_VNET_TNL_SIZE + ETH_HLEN + UDP_TUNNEL_GENEVE_6IN6_HDRLEN + \
111 ETH_MAX_MTU)
112
113 struct geneve_setup_config {
114 int family;
115 union {
116 struct in_addr r4;
117 struct in6_addr r6;
118 } remote;
119 __be32 vnid;
120 __be16 vnport;
121 unsigned char hwaddr[6];
122 uint8_t csum;
123 };
124
tun_attach(int fd,char * dev)125 static int tun_attach(int fd, char *dev)
126 {
127 struct ifreq ifr;
128
129 memset(&ifr, 0, sizeof(ifr));
130 strcpy(ifr.ifr_name, dev);
131 ifr.ifr_flags = IFF_ATTACH_QUEUE;
132
133 return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
134 }
135
tun_detach(int fd,char * dev)136 static int tun_detach(int fd, char *dev)
137 {
138 struct ifreq ifr;
139
140 memset(&ifr, 0, sizeof(ifr));
141 strcpy(ifr.ifr_name, dev);
142 ifr.ifr_flags = IFF_DETACH_QUEUE;
143
144 return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
145 }
146
tun_alloc(char * dev)147 static int tun_alloc(char *dev)
148 {
149 struct ifreq ifr;
150 int fd, err;
151
152 fd = open("/dev/net/tun", O_RDWR);
153 if (fd < 0) {
154 fprintf(stderr, "can't open tun: %s\n", strerror(errno));
155 return fd;
156 }
157
158 memset(&ifr, 0, sizeof(ifr));
159 strcpy(ifr.ifr_name, dev);
160 ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
161
162 err = ioctl(fd, TUNSETIFF, (void *)&ifr);
163 if (err < 0) {
164 fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno));
165 close(fd);
166 return err;
167 }
168 strcpy(dev, ifr.ifr_name);
169 return fd;
170 }
171
tun_delete(char * dev)172 static int tun_delete(char *dev)
173 {
174 return ip_link_del(dev);
175 }
176
tun_open(char * dev,const int flags,const int hdrlen,const int features,const unsigned char * mac_addr)177 static int tun_open(char *dev, const int flags, const int hdrlen,
178 const int features, const unsigned char *mac_addr)
179 {
180 struct ifreq ifr = { 0 };
181 int fd, sk = -1;
182
183 fd = open("/dev/net/tun", O_RDWR);
184 if (fd < 0) {
185 perror("open");
186 return -1;
187 }
188
189 ifr.ifr_flags = flags;
190 if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
191 perror("ioctl(TUNSETIFF)");
192 goto err;
193 }
194 strcpy(dev, ifr.ifr_name);
195
196 if (hdrlen > 0) {
197 if (ioctl(fd, TUNSETVNETHDRSZ, &hdrlen) < 0) {
198 perror("ioctl(TUNSETVNETHDRSZ)");
199 goto err;
200 }
201 }
202
203 if (features) {
204 if (ioctl(fd, TUNSETOFFLOAD, features) < 0) {
205 perror("ioctl(TUNSETOFFLOAD)");
206 goto err;
207 }
208 }
209
210 sk = socket(PF_INET, SOCK_DGRAM, 0);
211 if (sk < 0) {
212 perror("socket");
213 goto err;
214 }
215
216 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
217 perror("ioctl(SIOCGIFFLAGS)");
218 goto err;
219 }
220
221 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
222 if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
223 perror("ioctl(SIOCSIFFLAGS)");
224 goto err;
225 }
226
227 if (mac_addr && flags & IFF_TAP) {
228 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
229 memcpy(ifr.ifr_hwaddr.sa_data, mac_addr, ETH_ALEN);
230
231 if (ioctl(sk, SIOCSIFHWADDR, &ifr) < 0) {
232 perror("ioctl(SIOCSIFHWADDR)");
233 goto err;
234 }
235 }
236
237 out:
238 if (sk >= 0)
239 close(sk);
240 return fd;
241
242 err:
243 close(fd);
244 fd = -1;
245 goto out;
246 }
247
sockaddr_len(int family)248 static size_t sockaddr_len(int family)
249 {
250 return (family == AF_INET) ? sizeof(struct sockaddr_in) :
251 sizeof(struct sockaddr_in6);
252 }
253
geneve_fill_newlink(struct rt_link_newlink_req * req,void * data)254 static int geneve_fill_newlink(struct rt_link_newlink_req *req, void *data)
255 {
256 struct geneve_setup_config *cfg = data;
257
258 #define SET_GENEVE_REMOTE rt_link_newlink_req_set_linkinfo_data_geneve_remote
259 #define SET_GENEVE_REMOTE6 rt_link_newlink_req_set_linkinfo_data_geneve_remote6
260
261 rt_link_newlink_req_set_address(req, cfg->hwaddr, ETH_ALEN);
262 rt_link_newlink_req_set_linkinfo_data_geneve_id(req, cfg->vnid);
263 rt_link_newlink_req_set_linkinfo_data_geneve_port(req, cfg->vnport);
264 rt_link_newlink_req_set_linkinfo_data_geneve_udp_csum(req, cfg->csum);
265
266 if (cfg->family == AF_INET)
267 SET_GENEVE_REMOTE(req, cfg->remote.r4.s_addr);
268 else
269 SET_GENEVE_REMOTE6(req, &cfg->remote.r6,
270 sizeof(cfg->remote.r6));
271
272 return 0;
273 }
274
geneve_create(const char * dev,int family,void * remote,void * hwaddr)275 static int geneve_create(const char *dev, int family, void *remote,
276 void *hwaddr)
277 {
278 struct geneve_setup_config geneve;
279
280 memset(&geneve, 0, sizeof(geneve));
281 geneve.vnid = VN_ID;
282 geneve.vnport = htons(VN_PORT);
283 geneve.csum = 1;
284 geneve.family = family;
285 if (family == AF_INET)
286 memcpy(&geneve.remote.r4, remote, sizeof(struct in_addr));
287 else
288 memcpy(&geneve.remote.r6, remote, sizeof(struct in6_addr));
289 memcpy(geneve.hwaddr, hwaddr, ETH_ALEN);
290
291 return ip_link_add(dev, "geneve", geneve_fill_newlink, (void *)&geneve);
292 }
293
set_pmtu_discover(int fd,bool is_ipv4)294 static int set_pmtu_discover(int fd, bool is_ipv4)
295 {
296 int level, name, val;
297
298 if (is_ipv4) {
299 level = SOL_IP;
300 name = IP_MTU_DISCOVER;
301 val = IP_PMTUDISC_DO;
302 } else {
303 level = SOL_IPV6;
304 name = IPV6_MTU_DISCOVER;
305 val = IPV6_PMTUDISC_DO;
306 }
307
308 return setsockopt(fd, level, name, &val, sizeof(val));
309 }
310
udp_socket_open(struct sockaddr_storage * ssa,bool do_frag,bool do_connect,struct sockaddr_storage * dsa)311 static int udp_socket_open(struct sockaddr_storage *ssa, bool do_frag,
312 bool do_connect, struct sockaddr_storage *dsa)
313 {
314 struct timeval to = { .tv_sec = TIMEOUT_SEC };
315 int fd, family = ssa->ss_family;
316 int salen = sockaddr_len(family);
317
318 fd = socket(family, SOCK_DGRAM, 0);
319 if (fd < 0)
320 return -1;
321
322 if (bind(fd, (struct sockaddr *)ssa, salen) < 0) {
323 perror("bind");
324 goto err;
325 }
326
327 if (do_connect && connect(fd, (struct sockaddr *)dsa, salen) < 0) {
328 perror("connect");
329 goto err;
330 }
331
332 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)) < 0) {
333 perror("setsockopt(SO_RCVTIMEO)");
334 goto err;
335 }
336
337 if (!do_frag && set_pmtu_discover(fd, family == AF_INET) < 0) {
338 perror("set_pmtu_discover");
339 goto err;
340 }
341 return fd;
342
343 err:
344 close(fd);
345 return -1;
346 }
347
parse_route_rsp(struct rt_route_getroute_rsp * rsp,void * rtm_type)348 static void parse_route_rsp(struct rt_route_getroute_rsp *rsp, void *rtm_type)
349 {
350 *(uint8_t *)rtm_type = rsp->_hdr.rtm_type;
351 }
352
ip_route_check(const char * intf,int family,void * addr)353 static int ip_route_check(const char *intf, int family, void *addr)
354 {
355 uint8_t rtm_type, table = RT_TABLE_LOCAL;
356 int retries = MAX_RETRIES;
357
358 while (retries-- > 0) {
359 if (ip_route_get(intf, family, table, addr, parse_route_rsp,
360 &rtm_type) == 0 &&
361 rtm_type == RTN_LOCAL)
362 break;
363
364 usleep(TIMEOUT_USEC);
365 }
366
367 if (retries < 0)
368 return -1;
369
370 return 0;
371 }
372
send_gso_udp_msg(int socket,struct sockaddr_storage * addr,uint8_t * send_buf,int send_len,int gso_size)373 static int send_gso_udp_msg(int socket, struct sockaddr_storage *addr,
374 uint8_t *send_buf, int send_len, int gso_size)
375 {
376 char control[CMSG_SPACE(sizeof(uint16_t))] = { 0 };
377 int alen = sockaddr_len(addr->ss_family);
378 struct msghdr msg = { 0 };
379 struct iovec iov = { 0 };
380 int ret;
381
382 iov.iov_base = send_buf;
383 iov.iov_len = send_len;
384
385 msg.msg_iov = &iov;
386 msg.msg_iovlen = 1;
387 msg.msg_name = addr;
388 msg.msg_namelen = alen;
389
390 if (gso_size > 0) {
391 struct cmsghdr *cmsg;
392
393 msg.msg_control = control;
394 msg.msg_controllen = sizeof(control);
395
396 cmsg = CMSG_FIRSTHDR(&msg);
397 cmsg->cmsg_level = SOL_UDP;
398 cmsg->cmsg_type = UDP_SEGMENT;
399 cmsg->cmsg_len = CMSG_LEN(sizeof(uint16_t));
400 *(uint16_t *)CMSG_DATA(cmsg) = gso_size;
401 }
402
403 ret = sendmsg(socket, &msg, 0);
404 if (ret < 0)
405 perror("sendmsg");
406
407 return ret;
408 }
409
validate_hdrlen(uint8_t ** cur,int * len,int x)410 static int validate_hdrlen(uint8_t **cur, int *len, int x)
411 {
412 if (*len < x)
413 return -1;
414 *cur += x;
415 *len -= x;
416 return 0;
417 }
418
parse_udp_tunnel_vnet_packet(uint8_t * buf,int len,int tunnel_type,bool is_tap)419 static int parse_udp_tunnel_vnet_packet(uint8_t *buf, int len, int tunnel_type,
420 bool is_tap)
421 {
422 struct ipv6hdr *iph6;
423 struct udphdr *udph;
424 struct iphdr *iph4;
425 uint8_t *cur = buf;
426
427 if (validate_hdrlen(&cur, &len, TUN_VNET_TNL_SIZE))
428 return -1;
429
430 if (is_tap) {
431 if (validate_hdrlen(&cur, &len, ETH_HLEN))
432 return -1;
433 }
434
435 if (tunnel_type & UDP_TUNNEL_OUTER_IPV4) {
436 iph4 = (struct iphdr *)cur;
437 if (validate_hdrlen(&cur, &len, sizeof(struct iphdr)))
438 return -1;
439 if (iph4->version != 4 || iph4->protocol != IPPROTO_UDP)
440 return -1;
441 } else {
442 iph6 = (struct ipv6hdr *)cur;
443 if (validate_hdrlen(&cur, &len, sizeof(struct ipv6hdr)))
444 return -1;
445 if (iph6->version != 6 || iph6->nexthdr != IPPROTO_UDP)
446 return -1;
447 }
448
449 udph = (struct udphdr *)cur;
450 if (validate_hdrlen(&cur, &len, sizeof(struct udphdr)))
451 return -1;
452 if (ntohs(udph->dest) != VN_PORT)
453 return -1;
454
455 if (validate_hdrlen(&cur, &len, GENEVE_HLEN))
456 return -1;
457 if (validate_hdrlen(&cur, &len, ETH_HLEN))
458 return -1;
459
460 if (tunnel_type & UDP_TUNNEL_INNER_IPV4) {
461 iph4 = (struct iphdr *)cur;
462 if (validate_hdrlen(&cur, &len, sizeof(struct iphdr)))
463 return -1;
464 if (iph4->version != 4 || iph4->protocol != IPPROTO_UDP)
465 return -1;
466 } else {
467 iph6 = (struct ipv6hdr *)cur;
468 if (validate_hdrlen(&cur, &len, sizeof(struct ipv6hdr)))
469 return -1;
470 if (iph6->version != 6 || iph6->nexthdr != IPPROTO_UDP)
471 return -1;
472 }
473
474 udph = (struct udphdr *)cur;
475 if (validate_hdrlen(&cur, &len, sizeof(struct udphdr)))
476 return -1;
477 if (ntohs(udph->dest) != UDP_DST_PORT)
478 return -1;
479
480 return len;
481 }
482
FIXTURE(tun)483 FIXTURE(tun)
484 {
485 char ifname[IFNAMSIZ];
486 int fd, fd2;
487 };
488
FIXTURE_SETUP(tun)489 FIXTURE_SETUP(tun)
490 {
491 memset(self->ifname, 0, sizeof(self->ifname));
492
493 self->fd = tun_alloc(self->ifname);
494 ASSERT_GE(self->fd, 0);
495
496 self->fd2 = tun_alloc(self->ifname);
497 ASSERT_GE(self->fd2, 0);
498 }
499
FIXTURE_TEARDOWN(tun)500 FIXTURE_TEARDOWN(tun)
501 {
502 if (self->fd >= 0)
503 close(self->fd);
504 if (self->fd2 >= 0)
505 close(self->fd2);
506 }
507
TEST_F(tun,delete_detach_close)508 TEST_F(tun, delete_detach_close)
509 {
510 EXPECT_EQ(tun_delete(self->ifname), 0);
511 EXPECT_EQ(tun_detach(self->fd, self->ifname), -1);
512 EXPECT_EQ(errno, 22);
513 }
514
TEST_F(tun,detach_delete_close)515 TEST_F(tun, detach_delete_close)
516 {
517 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
518 EXPECT_EQ(tun_delete(self->ifname), 0);
519 }
520
TEST_F(tun,detach_close_delete)521 TEST_F(tun, detach_close_delete)
522 {
523 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
524 close(self->fd);
525 self->fd = -1;
526 EXPECT_EQ(tun_delete(self->ifname), 0);
527 }
528
TEST_F(tun,reattach_delete_close)529 TEST_F(tun, reattach_delete_close)
530 {
531 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
532 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
533 EXPECT_EQ(tun_delete(self->ifname), 0);
534 }
535
TEST_F(tun,reattach_close_delete)536 TEST_F(tun, reattach_close_delete)
537 {
538 EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
539 EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
540 close(self->fd);
541 self->fd = -1;
542 EXPECT_EQ(tun_delete(self->ifname), 0);
543 }
544
FIXTURE(tun_vnet_udptnl)545 FIXTURE(tun_vnet_udptnl)
546 {
547 char ifname[IFNAMSIZ];
548 int fd, sock;
549 };
550
FIXTURE_VARIANT(tun_vnet_udptnl)551 FIXTURE_VARIANT(tun_vnet_udptnl)
552 {
553 int tunnel_type;
554 int gso_size;
555 int data_size;
556 int r_num_mss;
557 bool is_tap, no_gso;
558 };
559
560 /* clang-format off */
561 #define TUN_VNET_UDPTNL_VARIANT_ADD(type, desc) \
562 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_1byte) { \
563 /* no GSO: send a single byte */ \
564 .tunnel_type = type, \
565 .data_size = 1, \
566 .r_num_mss = 1, \
567 .is_tap = true, \
568 .no_gso = true, \
569 }; \
570 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_1mss) { \
571 /* no GSO: send a single MSS, fall back to no GSO */ \
572 .tunnel_type = type, \
573 .data_size = UDP_TUNNEL_MSS(type), \
574 .r_num_mss = 1, \
575 .is_tap = true, \
576 .no_gso = true, \
577 }; \
578 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_gtmss) { \
579 /* no GSO: send a single MSS + 1B: fail */ \
580 .tunnel_type = type, \
581 .data_size = UDP_TUNNEL_MSS(type) + 1, \
582 .r_num_mss = 1, \
583 .is_tap = true, \
584 .no_gso = true, \
585 }; \
586 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_1byte) { \
587 /* GSO: send 1 byte, gso 1 byte, fall back to no GSO */ \
588 .tunnel_type = type, \
589 .gso_size = 1, \
590 .data_size = 1, \
591 .r_num_mss = 1, \
592 .is_tap = true, \
593 .no_gso = true, \
594 }; \
595 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_1mss) { \
596 /* send a single MSS: fall back to no GSO */ \
597 .tunnel_type = type, \
598 .gso_size = UDP_TUNNEL_MSS(type), \
599 .data_size = UDP_TUNNEL_MSS(type), \
600 .r_num_mss = 1, \
601 .is_tap = true, \
602 .no_gso = true, \
603 }; \
604 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_ltgso) { \
605 /* data <= MSS < gso: will fall back to no GSO */ \
606 .tunnel_type = type, \
607 .gso_size = UDP_TUNNEL_MSS(type) + 1, \
608 .data_size = UDP_TUNNEL_MSS(type), \
609 .r_num_mss = 1, \
610 .is_tap = true, \
611 .no_gso = true, \
612 }; \
613 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_gtgso) { \
614 /* GSO: a single MSS + 1B */ \
615 .tunnel_type = type, \
616 .gso_size = UDP_TUNNEL_MSS(type), \
617 .data_size = UDP_TUNNEL_MSS(type) + 1, \
618 .r_num_mss = 2, \
619 .is_tap = true, \
620 }; \
621 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_2mss) { \
622 /* no GSO: send exactly 2 MSS */ \
623 .tunnel_type = type, \
624 .gso_size = UDP_TUNNEL_MSS(type), \
625 .data_size = UDP_TUNNEL_MSS(type) * 2, \
626 .r_num_mss = 2, \
627 .is_tap = true, \
628 }; \
629 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_maxbytes) { \
630 /* GSO: send max bytes */ \
631 .tunnel_type = type, \
632 .gso_size = UDP_TUNNEL_MSS(type), \
633 .data_size = UDP_TUNNEL_MAX(type, true), \
634 .r_num_mss = UDP_TUNNEL_MAX(type, true) / \
635 UDP_TUNNEL_MSS(type) + 1, \
636 .is_tap = true, \
637 }; \
638 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_over_maxbytes) { \
639 /* GSO: send oversize max bytes: fail */ \
640 .tunnel_type = type, \
641 .gso_size = UDP_TUNNEL_MSS(type), \
642 .data_size = ETH_MAX_MTU, \
643 .r_num_mss = ETH_MAX_MTU / UDP_TUNNEL_MSS(type) + 1, \
644 .is_tap = true, \
645 }; \
646 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_maxsegs) { \
647 /* GSO: send max number of min sized segments */ \
648 .tunnel_type = type, \
649 .gso_size = 1, \
650 .data_size = UDP_TUNNEL_MAX_SEGMENTS, \
651 .r_num_mss = UDP_TUNNEL_MAX_SEGMENTS, \
652 .is_tap = true, \
653 }; \
654 FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_5byte) { \
655 /* GSO: send 5 bytes, gso 2 bytes */ \
656 .tunnel_type = type, \
657 .gso_size = 2, \
658 .data_size = 5, \
659 .r_num_mss = 3, \
660 .is_tap = true, \
661 } /* clang-format on */
662
663 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN4, 4in4);
664 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_6IN4, 6in4);
665 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN6, 4in6);
666 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_6IN6, 6in6);
667
assign_ifaddr_vars(int family,int is_outer,void ** srcip,void ** dstip,void ** srcmac,void ** dstmac)668 static void assign_ifaddr_vars(int family, int is_outer, void **srcip,
669 void **dstip, void **srcmac, void **dstmac)
670 {
671 if (is_outer) {
672 if (family == AF_INET) {
673 *srcip = (void *)¶m_ipaddr4_outer_src;
674 *dstip = (void *)¶m_ipaddr4_outer_dst;
675 } else {
676 *srcip = (void *)¶m_ipaddr6_outer_src;
677 *dstip = (void *)¶m_ipaddr6_outer_dst;
678 }
679 *srcmac = param_hwaddr_outer_src;
680 *dstmac = param_hwaddr_outer_dst;
681 } else {
682 if (family == AF_INET) {
683 *srcip = (void *)¶m_ipaddr4_inner_src;
684 *dstip = (void *)¶m_ipaddr4_inner_dst;
685 } else {
686 *srcip = (void *)¶m_ipaddr6_inner_src;
687 *dstip = (void *)¶m_ipaddr6_inner_dst;
688 }
689 *srcmac = param_hwaddr_inner_src;
690 *dstmac = param_hwaddr_inner_dst;
691 }
692 }
693
assign_sockaddr_vars(int family,int is_outer,struct sockaddr_storage * src,struct sockaddr_storage * dst)694 static void assign_sockaddr_vars(int family, int is_outer,
695 struct sockaddr_storage *src,
696 struct sockaddr_storage *dst)
697 {
698 src->ss_family = family;
699 dst->ss_family = family;
700
701 if (family == AF_INET) {
702 struct sockaddr_in *s4 = (struct sockaddr_in *)src;
703 struct sockaddr_in *d4 = (struct sockaddr_in *)dst;
704
705 s4->sin_addr = is_outer ? param_ipaddr4_outer_src :
706 param_ipaddr4_inner_src;
707 d4->sin_addr = is_outer ? param_ipaddr4_outer_dst :
708 param_ipaddr4_inner_dst;
709 if (!is_outer) {
710 s4->sin_port = htons(UDP_SRC_PORT);
711 d4->sin_port = htons(UDP_DST_PORT);
712 }
713 } else {
714 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)src;
715 struct sockaddr_in6 *d6 = (struct sockaddr_in6 *)dst;
716
717 s6->sin6_addr = is_outer ? param_ipaddr6_outer_src :
718 param_ipaddr6_inner_src;
719 d6->sin6_addr = is_outer ? param_ipaddr6_outer_dst :
720 param_ipaddr6_inner_dst;
721 if (!is_outer) {
722 s6->sin6_port = htons(UDP_SRC_PORT);
723 d6->sin6_port = htons(UDP_DST_PORT);
724 }
725 }
726 }
727
FIXTURE_SETUP(tun_vnet_udptnl)728 FIXTURE_SETUP(tun_vnet_udptnl)
729 {
730 int ret, family, prefix, flags, features;
731 int tunnel_type = variant->tunnel_type;
732 struct sockaddr_storage ssa, dsa;
733 void *sip, *dip, *smac, *dmac;
734
735 flags = (variant->is_tap ? IFF_TAP : IFF_TUN) | IFF_VNET_HDR |
736 IFF_MULTI_QUEUE | IFF_NO_PI;
737 features = TUN_F_CSUM | TUN_F_UDP_TUNNEL_GSO |
738 TUN_F_UDP_TUNNEL_GSO_CSUM | TUN_F_USO4 | TUN_F_USO6;
739 self->fd = tun_open(self->ifname, flags, TUN_VNET_TNL_SIZE, features,
740 param_hwaddr_outer_src);
741 ASSERT_GE(self->fd, 0);
742
743 family = (tunnel_type & UDP_TUNNEL_OUTER_IPV4) ? AF_INET : AF_INET6;
744 prefix = (family == AF_INET) ? IPPREFIX_LEN : IP6PREFIX_LEN;
745 assign_ifaddr_vars(family, 1, &sip, &dip, &smac, &dmac);
746
747 ret = ip_addr_add(self->ifname, family, sip, prefix);
748 ASSERT_EQ(ret, 0);
749 ret = ip_neigh_add(self->ifname, family, dip, dmac);
750 ASSERT_EQ(ret, 0);
751 ret = ip_route_check(self->ifname, family, sip);
752 ASSERT_EQ(ret, 0);
753
754 ret = geneve_create(param_dev_geneve_name, family, dip,
755 param_hwaddr_inner_src);
756 ASSERT_EQ(ret, 0);
757
758 family = (tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET : AF_INET6;
759 prefix = (family == AF_INET) ? IPPREFIX_LEN : IP6PREFIX_LEN;
760 assign_ifaddr_vars(family, 0, &sip, &dip, &smac, &dmac);
761
762 ret = ip_addr_add(param_dev_geneve_name, family, sip, prefix);
763 ASSERT_EQ(ret, 0);
764 ret = ip_neigh_add(param_dev_geneve_name, family, dip, dmac);
765 ASSERT_EQ(ret, 0);
766 ret = ip_route_check(param_dev_geneve_name, family, sip);
767 ASSERT_EQ(ret, 0);
768
769 assign_sockaddr_vars(family, 0, &ssa, &dsa);
770 self->sock = udp_socket_open(&ssa, false, true, &dsa);
771 ASSERT_GE(self->sock, 0);
772 }
773
FIXTURE_TEARDOWN(tun_vnet_udptnl)774 FIXTURE_TEARDOWN(tun_vnet_udptnl)
775 {
776 int ret;
777
778 if (self->sock != -1)
779 close(self->sock);
780
781 ret = ip_link_del(param_dev_geneve_name);
782 EXPECT_EQ(ret, 0);
783
784 ret = tun_delete(self->ifname);
785 EXPECT_EQ(ret, 0);
786 }
787
build_gso_packet_into_tun(const FIXTURE_VARIANT (tun_vnet_udptnl)* variant,uint8_t * buf)788 static int build_gso_packet_into_tun(const FIXTURE_VARIANT(tun_vnet_udptnl) *
789 variant,
790 uint8_t *buf)
791 {
792 int pktlen, hlen, proto, inner_family, outer_family;
793 int tunnel_type = variant->tunnel_type;
794 int payload_len = variant->data_size;
795 int gso_size = variant->gso_size;
796 uint8_t *outer_udph, *cur = buf;
797 void *sip, *dip, *smac, *dmac;
798 bool is_tap = variant->is_tap;
799
800 hlen = (is_tap ? ETH_HLEN : 0) + UDP_TUNNEL_HDRLEN(tunnel_type);
801 inner_family = (tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET :
802 AF_INET6;
803 outer_family = (tunnel_type & UDP_TUNNEL_OUTER_IPV4) ? AF_INET :
804 AF_INET6;
805
806 cur += build_virtio_net_hdr_v1_hash_tunnel(cur, is_tap, hlen, gso_size,
807 outer_family, inner_family);
808
809 pktlen = hlen + payload_len;
810 assign_ifaddr_vars(outer_family, 1, &sip, &dip, &smac, &dmac);
811
812 if (is_tap) {
813 proto = outer_family == AF_INET ? ETH_P_IP : ETH_P_IPV6;
814 pktlen -= ETH_HLEN;
815 cur += build_eth(cur, proto, dmac, smac);
816 }
817
818 if (outer_family == AF_INET) {
819 pktlen = pktlen - sizeof(struct iphdr);
820 cur += build_ipv4_header(cur, IPPROTO_UDP, pktlen, dip, sip);
821 } else {
822 pktlen = pktlen - sizeof(struct ipv6hdr);
823 cur += build_ipv6_header(cur, IPPROTO_UDP, 0, pktlen, dip, sip);
824 }
825
826 outer_udph = cur;
827 assign_ifaddr_vars(inner_family, 0, &sip, &dip, &smac, &dmac);
828
829 pktlen -= sizeof(struct udphdr);
830 proto = inner_family == AF_INET ? ETH_P_IP : ETH_P_IPV6;
831 cur += build_udp_header(cur, UDP_SRC_PORT, VN_PORT, pktlen);
832 cur += build_geneve_header(cur, VN_ID);
833 cur += build_eth(cur, proto, dmac, smac);
834
835 pktlen = sizeof(struct udphdr) + payload_len;
836 if (inner_family == AF_INET)
837 cur += build_ipv4_header(cur, IPPROTO_UDP, pktlen, dip, sip);
838 else
839 cur += build_ipv6_header(cur, IPPROTO_UDP, 0, pktlen, dip, sip);
840
841 cur += build_udp_packet(cur, UDP_DST_PORT, UDP_SRC_PORT, payload_len,
842 inner_family, false);
843
844 build_udp_packet_csum(outer_udph, outer_family, false);
845
846 return cur - buf;
847 }
848
849 static int
receive_gso_packet_from_tunnel(FIXTURE_DATA (tun_vnet_udptnl)* self,const FIXTURE_VARIANT (tun_vnet_udptnl)* variant,int * r_num_mss)850 receive_gso_packet_from_tunnel(FIXTURE_DATA(tun_vnet_udptnl) * self,
851 const FIXTURE_VARIANT(tun_vnet_udptnl) * variant,
852 int *r_num_mss)
853 {
854 uint8_t packet_buf[MAX_VNET_TUNNEL_PACKET_SZ];
855 int len, total_len = 0, socket = self->sock;
856 int payload_len = variant->data_size;
857
858 while (total_len < payload_len) {
859 len = recv(socket, packet_buf, sizeof(packet_buf), 0);
860 if (len <= 0) {
861 if (len < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
862 perror("recv");
863 break;
864 }
865
866 (*r_num_mss)++;
867 total_len += len;
868 }
869
870 return total_len;
871 }
872
send_gso_packet_into_tunnel(FIXTURE_DATA (tun_vnet_udptnl)* self,const FIXTURE_VARIANT (tun_vnet_udptnl)* variant)873 static int send_gso_packet_into_tunnel(FIXTURE_DATA(tun_vnet_udptnl) * self,
874 const FIXTURE_VARIANT(tun_vnet_udptnl) *
875 variant)
876 {
877 int family = (variant->tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET :
878 AF_INET6;
879 uint8_t buf[MAX_VNET_TUNNEL_PACKET_SZ] = { 0 };
880 int payload_len = variant->data_size;
881 int gso_size = variant->gso_size;
882 struct sockaddr_storage ssa, dsa;
883
884 assign_sockaddr_vars(family, 0, &ssa, &dsa);
885 return send_gso_udp_msg(self->sock, &dsa, buf, payload_len, gso_size);
886 }
887
888 static int
receive_gso_packet_from_tun(FIXTURE_DATA (tun_vnet_udptnl)* self,const FIXTURE_VARIANT (tun_vnet_udptnl)* variant,struct virtio_net_hdr_v1_hash_tunnel * vnet_hdr)889 receive_gso_packet_from_tun(FIXTURE_DATA(tun_vnet_udptnl) * self,
890 const FIXTURE_VARIANT(tun_vnet_udptnl) * variant,
891 struct virtio_net_hdr_v1_hash_tunnel *vnet_hdr)
892 {
893 struct timeval timeout = { .tv_sec = TIMEOUT_SEC };
894 uint8_t buf[MAX_VNET_TUNNEL_PACKET_SZ];
895 int tunnel_type = variant->tunnel_type;
896 int payload_len = variant->data_size;
897 bool is_tap = variant->is_tap;
898 int ret, len, total_len = 0;
899 int tun_fd = self->fd;
900 fd_set fdset;
901
902 while (total_len < payload_len) {
903 FD_ZERO(&fdset);
904 FD_SET(tun_fd, &fdset);
905
906 ret = select(tun_fd + 1, &fdset, NULL, NULL, &timeout);
907 if (ret <= 0) {
908 perror("select");
909 break;
910 }
911 if (!FD_ISSET(tun_fd, &fdset))
912 continue;
913
914 len = read(tun_fd, buf, sizeof(buf));
915 if (len <= 0) {
916 if (len < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
917 perror("read");
918 break;
919 }
920
921 len = parse_udp_tunnel_vnet_packet(buf, len, tunnel_type,
922 is_tap);
923 if (len < 0)
924 continue;
925
926 if (total_len == 0)
927 memcpy(vnet_hdr, buf, TUN_VNET_TNL_SIZE);
928
929 total_len += len;
930 }
931
932 return total_len;
933 }
934
TEST_F(tun_vnet_udptnl,send_gso_packet)935 TEST_F(tun_vnet_udptnl, send_gso_packet)
936 {
937 uint8_t pkt[MAX_VNET_TUNNEL_PACKET_SZ];
938 int r_num_mss = 0;
939 int ret, off;
940
941 memset(pkt, 0, sizeof(pkt));
942 off = build_gso_packet_into_tun(variant, pkt);
943 ret = write(self->fd, pkt, off);
944 ASSERT_EQ(ret, off);
945
946 ret = receive_gso_packet_from_tunnel(self, variant, &r_num_mss);
947 EXPECT_EQ(ret, variant->data_size);
948 EXPECT_EQ(r_num_mss, variant->r_num_mss);
949 }
950
TEST_F(tun_vnet_udptnl,recv_gso_packet)951 TEST_F(tun_vnet_udptnl, recv_gso_packet)
952 {
953 struct virtio_net_hdr_v1_hash_tunnel vnet_hdr = { 0 };
954 struct virtio_net_hdr_v1 *vh = &vnet_hdr.hash_hdr.hdr;
955 int ret, gso_type = VIRTIO_NET_HDR_GSO_UDP_L4;
956
957 ret = send_gso_packet_into_tunnel(self, variant);
958 EXPECT_EQ(ret, variant->data_size);
959
960 memset(&vnet_hdr, 0, sizeof(vnet_hdr));
961 ret = receive_gso_packet_from_tun(self, variant, &vnet_hdr);
962 EXPECT_EQ(ret, variant->data_size);
963
964 if (!variant->no_gso) {
965 EXPECT_EQ(vh->gso_size, variant->gso_size);
966 gso_type |= (variant->tunnel_type & UDP_TUNNEL_OUTER_IPV4) ?
967 (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4) :
968 (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6);
969 EXPECT_EQ(vh->gso_type, gso_type);
970 }
971 }
972
973 XFAIL_ADD(tun_vnet_udptnl, 4in4_nogsosz_gtmss, recv_gso_packet);
974 XFAIL_ADD(tun_vnet_udptnl, 6in4_nogsosz_gtmss, recv_gso_packet);
975 XFAIL_ADD(tun_vnet_udptnl, 4in6_nogsosz_gtmss, recv_gso_packet);
976 XFAIL_ADD(tun_vnet_udptnl, 6in6_nogsosz_gtmss, recv_gso_packet);
977
978 XFAIL_ADD(tun_vnet_udptnl, 4in4_over_maxbytes, send_gso_packet);
979 XFAIL_ADD(tun_vnet_udptnl, 6in4_over_maxbytes, send_gso_packet);
980 XFAIL_ADD(tun_vnet_udptnl, 4in6_over_maxbytes, send_gso_packet);
981 XFAIL_ADD(tun_vnet_udptnl, 6in6_over_maxbytes, send_gso_packet);
982
983 XFAIL_ADD(tun_vnet_udptnl, 4in4_over_maxbytes, recv_gso_packet);
984 XFAIL_ADD(tun_vnet_udptnl, 6in4_over_maxbytes, recv_gso_packet);
985 XFAIL_ADD(tun_vnet_udptnl, 4in6_over_maxbytes, recv_gso_packet);
986 XFAIL_ADD(tun_vnet_udptnl, 6in6_over_maxbytes, recv_gso_packet);
987
988 TEST_HARNESS_MAIN
989