1*2e64fe46SCezar Bulinaru // SPDX-License-Identifier: GPL-2.0
2*2e64fe46SCezar Bulinaru
3*2e64fe46SCezar Bulinaru #define _GNU_SOURCE
4*2e64fe46SCezar Bulinaru
5*2e64fe46SCezar Bulinaru #include <errno.h>
6*2e64fe46SCezar Bulinaru #include <fcntl.h>
7*2e64fe46SCezar Bulinaru #include <stdio.h>
8*2e64fe46SCezar Bulinaru #include <stdlib.h>
9*2e64fe46SCezar Bulinaru #include <string.h>
10*2e64fe46SCezar Bulinaru #include <unistd.h>
11*2e64fe46SCezar Bulinaru #include <net/if.h>
12*2e64fe46SCezar Bulinaru #include <linux/if_tun.h>
13*2e64fe46SCezar Bulinaru #include <linux/netlink.h>
14*2e64fe46SCezar Bulinaru #include <linux/rtnetlink.h>
15*2e64fe46SCezar Bulinaru #include <sys/ioctl.h>
16*2e64fe46SCezar Bulinaru #include <sys/socket.h>
17*2e64fe46SCezar Bulinaru #include <linux/virtio_net.h>
18*2e64fe46SCezar Bulinaru #include <netinet/ip.h>
19*2e64fe46SCezar Bulinaru #include <netinet/udp.h>
20*2e64fe46SCezar Bulinaru #include "../kselftest_harness.h"
21*2e64fe46SCezar Bulinaru
22*2e64fe46SCezar Bulinaru static const char param_dev_tap_name[] = "xmacvtap0";
23*2e64fe46SCezar Bulinaru static const char param_dev_dummy_name[] = "xdummy0";
24*2e64fe46SCezar Bulinaru static unsigned char param_hwaddr_src[] = { 0x00, 0xfe, 0x98, 0x14, 0x22, 0x42 };
25*2e64fe46SCezar Bulinaru static unsigned char param_hwaddr_dest[] = {
26*2e64fe46SCezar Bulinaru 0x00, 0xfe, 0x98, 0x94, 0xd2, 0x43
27*2e64fe46SCezar Bulinaru };
28*2e64fe46SCezar Bulinaru
29*2e64fe46SCezar Bulinaru #define MAX_RTNL_PAYLOAD (2048)
30*2e64fe46SCezar Bulinaru #define PKT_DATA 0xCB
31*2e64fe46SCezar Bulinaru #define TEST_PACKET_SZ (sizeof(struct virtio_net_hdr) + ETH_HLEN + ETH_MAX_MTU)
32*2e64fe46SCezar Bulinaru
rtattr_add(struct nlmsghdr * nh,unsigned short type,unsigned short len)33*2e64fe46SCezar Bulinaru static struct rtattr *rtattr_add(struct nlmsghdr *nh, unsigned short type,
34*2e64fe46SCezar Bulinaru unsigned short len)
35*2e64fe46SCezar Bulinaru {
36*2e64fe46SCezar Bulinaru struct rtattr *rta =
37*2e64fe46SCezar Bulinaru (struct rtattr *)((uint8_t *)nh + RTA_ALIGN(nh->nlmsg_len));
38*2e64fe46SCezar Bulinaru rta->rta_type = type;
39*2e64fe46SCezar Bulinaru rta->rta_len = RTA_LENGTH(len);
40*2e64fe46SCezar Bulinaru nh->nlmsg_len = RTA_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta->rta_len);
41*2e64fe46SCezar Bulinaru return rta;
42*2e64fe46SCezar Bulinaru }
43*2e64fe46SCezar Bulinaru
rtattr_begin(struct nlmsghdr * nh,unsigned short type)44*2e64fe46SCezar Bulinaru static struct rtattr *rtattr_begin(struct nlmsghdr *nh, unsigned short type)
45*2e64fe46SCezar Bulinaru {
46*2e64fe46SCezar Bulinaru return rtattr_add(nh, type, 0);
47*2e64fe46SCezar Bulinaru }
48*2e64fe46SCezar Bulinaru
rtattr_end(struct nlmsghdr * nh,struct rtattr * attr)49*2e64fe46SCezar Bulinaru static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr)
50*2e64fe46SCezar Bulinaru {
51*2e64fe46SCezar Bulinaru uint8_t *end = (uint8_t *)nh + nh->nlmsg_len;
52*2e64fe46SCezar Bulinaru
53*2e64fe46SCezar Bulinaru attr->rta_len = end - (uint8_t *)attr;
54*2e64fe46SCezar Bulinaru }
55*2e64fe46SCezar Bulinaru
rtattr_add_str(struct nlmsghdr * nh,unsigned short type,const char * s)56*2e64fe46SCezar Bulinaru static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type,
57*2e64fe46SCezar Bulinaru const char *s)
58*2e64fe46SCezar Bulinaru {
59*2e64fe46SCezar Bulinaru struct rtattr *rta = rtattr_add(nh, type, strlen(s));
60*2e64fe46SCezar Bulinaru
61*2e64fe46SCezar Bulinaru memcpy(RTA_DATA(rta), s, strlen(s));
62*2e64fe46SCezar Bulinaru return rta;
63*2e64fe46SCezar Bulinaru }
64*2e64fe46SCezar Bulinaru
rtattr_add_strsz(struct nlmsghdr * nh,unsigned short type,const char * s)65*2e64fe46SCezar Bulinaru static struct rtattr *rtattr_add_strsz(struct nlmsghdr *nh, unsigned short type,
66*2e64fe46SCezar Bulinaru const char *s)
67*2e64fe46SCezar Bulinaru {
68*2e64fe46SCezar Bulinaru struct rtattr *rta = rtattr_add(nh, type, strlen(s) + 1);
69*2e64fe46SCezar Bulinaru
70*2e64fe46SCezar Bulinaru strcpy(RTA_DATA(rta), s);
71*2e64fe46SCezar Bulinaru return rta;
72*2e64fe46SCezar Bulinaru }
73*2e64fe46SCezar Bulinaru
rtattr_add_any(struct nlmsghdr * nh,unsigned short type,const void * arr,size_t len)74*2e64fe46SCezar Bulinaru static struct rtattr *rtattr_add_any(struct nlmsghdr *nh, unsigned short type,
75*2e64fe46SCezar Bulinaru const void *arr, size_t len)
76*2e64fe46SCezar Bulinaru {
77*2e64fe46SCezar Bulinaru struct rtattr *rta = rtattr_add(nh, type, len);
78*2e64fe46SCezar Bulinaru
79*2e64fe46SCezar Bulinaru memcpy(RTA_DATA(rta), arr, len);
80*2e64fe46SCezar Bulinaru return rta;
81*2e64fe46SCezar Bulinaru }
82*2e64fe46SCezar Bulinaru
dev_create(const char * dev,const char * link_type,int (* fill_rtattr)(struct nlmsghdr * nh),int (* fill_info_data)(struct nlmsghdr * nh))83*2e64fe46SCezar Bulinaru static int dev_create(const char *dev, const char *link_type,
84*2e64fe46SCezar Bulinaru int (*fill_rtattr)(struct nlmsghdr *nh),
85*2e64fe46SCezar Bulinaru int (*fill_info_data)(struct nlmsghdr *nh))
86*2e64fe46SCezar Bulinaru {
87*2e64fe46SCezar Bulinaru struct {
88*2e64fe46SCezar Bulinaru struct nlmsghdr nh;
89*2e64fe46SCezar Bulinaru struct ifinfomsg info;
90*2e64fe46SCezar Bulinaru unsigned char data[MAX_RTNL_PAYLOAD];
91*2e64fe46SCezar Bulinaru } req;
92*2e64fe46SCezar Bulinaru struct rtattr *link_info, *info_data;
93*2e64fe46SCezar Bulinaru int ret, rtnl;
94*2e64fe46SCezar Bulinaru
95*2e64fe46SCezar Bulinaru rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
96*2e64fe46SCezar Bulinaru if (rtnl < 0) {
97*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno));
98*2e64fe46SCezar Bulinaru return 1;
99*2e64fe46SCezar Bulinaru }
100*2e64fe46SCezar Bulinaru
101*2e64fe46SCezar Bulinaru memset(&req, 0, sizeof(req));
102*2e64fe46SCezar Bulinaru req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
103*2e64fe46SCezar Bulinaru req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
104*2e64fe46SCezar Bulinaru req.nh.nlmsg_type = RTM_NEWLINK;
105*2e64fe46SCezar Bulinaru
106*2e64fe46SCezar Bulinaru req.info.ifi_family = AF_UNSPEC;
107*2e64fe46SCezar Bulinaru req.info.ifi_type = 1;
108*2e64fe46SCezar Bulinaru req.info.ifi_index = 0;
109*2e64fe46SCezar Bulinaru req.info.ifi_flags = IFF_BROADCAST | IFF_UP;
110*2e64fe46SCezar Bulinaru req.info.ifi_change = 0xffffffff;
111*2e64fe46SCezar Bulinaru
112*2e64fe46SCezar Bulinaru rtattr_add_str(&req.nh, IFLA_IFNAME, dev);
113*2e64fe46SCezar Bulinaru
114*2e64fe46SCezar Bulinaru if (fill_rtattr) {
115*2e64fe46SCezar Bulinaru ret = fill_rtattr(&req.nh);
116*2e64fe46SCezar Bulinaru if (ret)
117*2e64fe46SCezar Bulinaru return ret;
118*2e64fe46SCezar Bulinaru }
119*2e64fe46SCezar Bulinaru
120*2e64fe46SCezar Bulinaru link_info = rtattr_begin(&req.nh, IFLA_LINKINFO);
121*2e64fe46SCezar Bulinaru
122*2e64fe46SCezar Bulinaru rtattr_add_strsz(&req.nh, IFLA_INFO_KIND, link_type);
123*2e64fe46SCezar Bulinaru
124*2e64fe46SCezar Bulinaru if (fill_info_data) {
125*2e64fe46SCezar Bulinaru info_data = rtattr_begin(&req.nh, IFLA_INFO_DATA);
126*2e64fe46SCezar Bulinaru ret = fill_info_data(&req.nh);
127*2e64fe46SCezar Bulinaru if (ret)
128*2e64fe46SCezar Bulinaru return ret;
129*2e64fe46SCezar Bulinaru rtattr_end(&req.nh, info_data);
130*2e64fe46SCezar Bulinaru }
131*2e64fe46SCezar Bulinaru
132*2e64fe46SCezar Bulinaru rtattr_end(&req.nh, link_info);
133*2e64fe46SCezar Bulinaru
134*2e64fe46SCezar Bulinaru ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
135*2e64fe46SCezar Bulinaru if (ret < 0)
136*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: send %s\n", __func__, strerror(errno));
137*2e64fe46SCezar Bulinaru ret = (unsigned int)ret != req.nh.nlmsg_len;
138*2e64fe46SCezar Bulinaru
139*2e64fe46SCezar Bulinaru close(rtnl);
140*2e64fe46SCezar Bulinaru return ret;
141*2e64fe46SCezar Bulinaru }
142*2e64fe46SCezar Bulinaru
dev_delete(const char * dev)143*2e64fe46SCezar Bulinaru static int dev_delete(const char *dev)
144*2e64fe46SCezar Bulinaru {
145*2e64fe46SCezar Bulinaru struct {
146*2e64fe46SCezar Bulinaru struct nlmsghdr nh;
147*2e64fe46SCezar Bulinaru struct ifinfomsg info;
148*2e64fe46SCezar Bulinaru unsigned char data[MAX_RTNL_PAYLOAD];
149*2e64fe46SCezar Bulinaru } req;
150*2e64fe46SCezar Bulinaru int ret, rtnl;
151*2e64fe46SCezar Bulinaru
152*2e64fe46SCezar Bulinaru rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
153*2e64fe46SCezar Bulinaru if (rtnl < 0) {
154*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno));
155*2e64fe46SCezar Bulinaru return 1;
156*2e64fe46SCezar Bulinaru }
157*2e64fe46SCezar Bulinaru
158*2e64fe46SCezar Bulinaru memset(&req, 0, sizeof(req));
159*2e64fe46SCezar Bulinaru req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
160*2e64fe46SCezar Bulinaru req.nh.nlmsg_flags = NLM_F_REQUEST;
161*2e64fe46SCezar Bulinaru req.nh.nlmsg_type = RTM_DELLINK;
162*2e64fe46SCezar Bulinaru
163*2e64fe46SCezar Bulinaru req.info.ifi_family = AF_UNSPEC;
164*2e64fe46SCezar Bulinaru
165*2e64fe46SCezar Bulinaru rtattr_add_str(&req.nh, IFLA_IFNAME, dev);
166*2e64fe46SCezar Bulinaru
167*2e64fe46SCezar Bulinaru ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
168*2e64fe46SCezar Bulinaru if (ret < 0)
169*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: send %s\n", __func__, strerror(errno));
170*2e64fe46SCezar Bulinaru
171*2e64fe46SCezar Bulinaru ret = (unsigned int)ret != req.nh.nlmsg_len;
172*2e64fe46SCezar Bulinaru
173*2e64fe46SCezar Bulinaru close(rtnl);
174*2e64fe46SCezar Bulinaru return ret;
175*2e64fe46SCezar Bulinaru }
176*2e64fe46SCezar Bulinaru
macvtap_fill_rtattr(struct nlmsghdr * nh)177*2e64fe46SCezar Bulinaru static int macvtap_fill_rtattr(struct nlmsghdr *nh)
178*2e64fe46SCezar Bulinaru {
179*2e64fe46SCezar Bulinaru int ifindex;
180*2e64fe46SCezar Bulinaru
181*2e64fe46SCezar Bulinaru ifindex = if_nametoindex(param_dev_dummy_name);
182*2e64fe46SCezar Bulinaru if (ifindex == 0) {
183*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: ifindex %s\n", __func__, strerror(errno));
184*2e64fe46SCezar Bulinaru return -errno;
185*2e64fe46SCezar Bulinaru }
186*2e64fe46SCezar Bulinaru
187*2e64fe46SCezar Bulinaru rtattr_add_any(nh, IFLA_LINK, &ifindex, sizeof(ifindex));
188*2e64fe46SCezar Bulinaru rtattr_add_any(nh, IFLA_ADDRESS, param_hwaddr_src, ETH_ALEN);
189*2e64fe46SCezar Bulinaru
190*2e64fe46SCezar Bulinaru return 0;
191*2e64fe46SCezar Bulinaru }
192*2e64fe46SCezar Bulinaru
opentap(const char * devname)193*2e64fe46SCezar Bulinaru static int opentap(const char *devname)
194*2e64fe46SCezar Bulinaru {
195*2e64fe46SCezar Bulinaru int ifindex;
196*2e64fe46SCezar Bulinaru char buf[256];
197*2e64fe46SCezar Bulinaru int fd;
198*2e64fe46SCezar Bulinaru struct ifreq ifr;
199*2e64fe46SCezar Bulinaru
200*2e64fe46SCezar Bulinaru ifindex = if_nametoindex(devname);
201*2e64fe46SCezar Bulinaru if (ifindex == 0) {
202*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: ifindex %s\n", __func__, strerror(errno));
203*2e64fe46SCezar Bulinaru return -errno;
204*2e64fe46SCezar Bulinaru }
205*2e64fe46SCezar Bulinaru
206*2e64fe46SCezar Bulinaru sprintf(buf, "/dev/tap%d", ifindex);
207*2e64fe46SCezar Bulinaru fd = open(buf, O_RDWR | O_NONBLOCK);
208*2e64fe46SCezar Bulinaru if (fd < 0) {
209*2e64fe46SCezar Bulinaru fprintf(stderr, "%s: open %s\n", __func__, strerror(errno));
210*2e64fe46SCezar Bulinaru return -errno;
211*2e64fe46SCezar Bulinaru }
212*2e64fe46SCezar Bulinaru
213*2e64fe46SCezar Bulinaru memset(&ifr, 0, sizeof(ifr));
214*2e64fe46SCezar Bulinaru strcpy(ifr.ifr_name, devname);
215*2e64fe46SCezar Bulinaru ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR | IFF_MULTI_QUEUE;
216*2e64fe46SCezar Bulinaru if (ioctl(fd, TUNSETIFF, &ifr, sizeof(ifr)) < 0)
217*2e64fe46SCezar Bulinaru return -errno;
218*2e64fe46SCezar Bulinaru return fd;
219*2e64fe46SCezar Bulinaru }
220*2e64fe46SCezar Bulinaru
build_eth(uint8_t * buf,uint16_t proto)221*2e64fe46SCezar Bulinaru size_t build_eth(uint8_t *buf, uint16_t proto)
222*2e64fe46SCezar Bulinaru {
223*2e64fe46SCezar Bulinaru struct ethhdr *eth = (struct ethhdr *)buf;
224*2e64fe46SCezar Bulinaru
225*2e64fe46SCezar Bulinaru eth->h_proto = htons(proto);
226*2e64fe46SCezar Bulinaru memcpy(eth->h_source, param_hwaddr_src, ETH_ALEN);
227*2e64fe46SCezar Bulinaru memcpy(eth->h_dest, param_hwaddr_dest, ETH_ALEN);
228*2e64fe46SCezar Bulinaru
229*2e64fe46SCezar Bulinaru return ETH_HLEN;
230*2e64fe46SCezar Bulinaru }
231*2e64fe46SCezar Bulinaru
add_csum(const uint8_t * buf,int len)232*2e64fe46SCezar Bulinaru static uint32_t add_csum(const uint8_t *buf, int len)
233*2e64fe46SCezar Bulinaru {
234*2e64fe46SCezar Bulinaru uint32_t sum = 0;
235*2e64fe46SCezar Bulinaru uint16_t *sbuf = (uint16_t *)buf;
236*2e64fe46SCezar Bulinaru
237*2e64fe46SCezar Bulinaru while (len > 1) {
238*2e64fe46SCezar Bulinaru sum += *sbuf++;
239*2e64fe46SCezar Bulinaru len -= 2;
240*2e64fe46SCezar Bulinaru }
241*2e64fe46SCezar Bulinaru
242*2e64fe46SCezar Bulinaru if (len)
243*2e64fe46SCezar Bulinaru sum += *(uint8_t *)sbuf;
244*2e64fe46SCezar Bulinaru
245*2e64fe46SCezar Bulinaru return sum;
246*2e64fe46SCezar Bulinaru }
247*2e64fe46SCezar Bulinaru
finish_ip_csum(uint32_t sum)248*2e64fe46SCezar Bulinaru static uint16_t finish_ip_csum(uint32_t sum)
249*2e64fe46SCezar Bulinaru {
250*2e64fe46SCezar Bulinaru uint16_t lo = sum & 0xffff;
251*2e64fe46SCezar Bulinaru uint16_t hi = sum >> 16;
252*2e64fe46SCezar Bulinaru
253*2e64fe46SCezar Bulinaru return ~(lo + hi);
254*2e64fe46SCezar Bulinaru
255*2e64fe46SCezar Bulinaru }
256*2e64fe46SCezar Bulinaru
build_ip_csum(const uint8_t * buf,int len,uint32_t sum)257*2e64fe46SCezar Bulinaru static uint16_t build_ip_csum(const uint8_t *buf, int len,
258*2e64fe46SCezar Bulinaru uint32_t sum)
259*2e64fe46SCezar Bulinaru {
260*2e64fe46SCezar Bulinaru sum += add_csum(buf, len);
261*2e64fe46SCezar Bulinaru return finish_ip_csum(sum);
262*2e64fe46SCezar Bulinaru }
263*2e64fe46SCezar Bulinaru
build_ipv4_header(uint8_t * buf,int payload_len)264*2e64fe46SCezar Bulinaru static int build_ipv4_header(uint8_t *buf, int payload_len)
265*2e64fe46SCezar Bulinaru {
266*2e64fe46SCezar Bulinaru struct iphdr *iph = (struct iphdr *)buf;
267*2e64fe46SCezar Bulinaru
268*2e64fe46SCezar Bulinaru iph->ihl = 5;
269*2e64fe46SCezar Bulinaru iph->version = 4;
270*2e64fe46SCezar Bulinaru iph->ttl = 8;
271*2e64fe46SCezar Bulinaru iph->tot_len =
272*2e64fe46SCezar Bulinaru htons(sizeof(*iph) + sizeof(struct udphdr) + payload_len);
273*2e64fe46SCezar Bulinaru iph->id = htons(1337);
274*2e64fe46SCezar Bulinaru iph->protocol = IPPROTO_UDP;
275*2e64fe46SCezar Bulinaru iph->saddr = htonl((172 << 24) | (17 << 16) | 2);
276*2e64fe46SCezar Bulinaru iph->daddr = htonl((172 << 24) | (17 << 16) | 1);
277*2e64fe46SCezar Bulinaru iph->check = build_ip_csum(buf, iph->ihl << 2, 0);
278*2e64fe46SCezar Bulinaru
279*2e64fe46SCezar Bulinaru return iph->ihl << 2;
280*2e64fe46SCezar Bulinaru }
281*2e64fe46SCezar Bulinaru
build_udp_packet(uint8_t * buf,int payload_len,bool csum_off)282*2e64fe46SCezar Bulinaru static int build_udp_packet(uint8_t *buf, int payload_len, bool csum_off)
283*2e64fe46SCezar Bulinaru {
284*2e64fe46SCezar Bulinaru const int ip4alen = sizeof(uint32_t);
285*2e64fe46SCezar Bulinaru struct udphdr *udph = (struct udphdr *)buf;
286*2e64fe46SCezar Bulinaru int len = sizeof(*udph) + payload_len;
287*2e64fe46SCezar Bulinaru uint32_t sum = 0;
288*2e64fe46SCezar Bulinaru
289*2e64fe46SCezar Bulinaru udph->source = htons(22);
290*2e64fe46SCezar Bulinaru udph->dest = htons(58822);
291*2e64fe46SCezar Bulinaru udph->len = htons(len);
292*2e64fe46SCezar Bulinaru
293*2e64fe46SCezar Bulinaru memset(buf + sizeof(struct udphdr), PKT_DATA, payload_len);
294*2e64fe46SCezar Bulinaru
295*2e64fe46SCezar Bulinaru sum = add_csum(buf - 2 * ip4alen, 2 * ip4alen);
296*2e64fe46SCezar Bulinaru sum += htons(IPPROTO_UDP) + udph->len;
297*2e64fe46SCezar Bulinaru
298*2e64fe46SCezar Bulinaru if (!csum_off)
299*2e64fe46SCezar Bulinaru sum += add_csum(buf, len);
300*2e64fe46SCezar Bulinaru
301*2e64fe46SCezar Bulinaru udph->check = finish_ip_csum(sum);
302*2e64fe46SCezar Bulinaru
303*2e64fe46SCezar Bulinaru return sizeof(*udph) + payload_len;
304*2e64fe46SCezar Bulinaru }
305*2e64fe46SCezar Bulinaru
build_test_packet_valid_udp_gso(uint8_t * buf,size_t payload_len)306*2e64fe46SCezar Bulinaru size_t build_test_packet_valid_udp_gso(uint8_t *buf, size_t payload_len)
307*2e64fe46SCezar Bulinaru {
308*2e64fe46SCezar Bulinaru uint8_t *cur = buf;
309*2e64fe46SCezar Bulinaru struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf;
310*2e64fe46SCezar Bulinaru
311*2e64fe46SCezar Bulinaru vh->hdr_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr);
312*2e64fe46SCezar Bulinaru vh->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
313*2e64fe46SCezar Bulinaru vh->csum_start = ETH_HLEN + sizeof(struct iphdr);
314*2e64fe46SCezar Bulinaru vh->csum_offset = __builtin_offsetof(struct udphdr, check);
315*2e64fe46SCezar Bulinaru vh->gso_type = VIRTIO_NET_HDR_GSO_UDP;
316*2e64fe46SCezar Bulinaru vh->gso_size = ETH_DATA_LEN - sizeof(struct iphdr);
317*2e64fe46SCezar Bulinaru cur += sizeof(*vh);
318*2e64fe46SCezar Bulinaru
319*2e64fe46SCezar Bulinaru cur += build_eth(cur, ETH_P_IP);
320*2e64fe46SCezar Bulinaru cur += build_ipv4_header(cur, payload_len);
321*2e64fe46SCezar Bulinaru cur += build_udp_packet(cur, payload_len, true);
322*2e64fe46SCezar Bulinaru
323*2e64fe46SCezar Bulinaru return cur - buf;
324*2e64fe46SCezar Bulinaru }
325*2e64fe46SCezar Bulinaru
build_test_packet_valid_udp_csum(uint8_t * buf,size_t payload_len)326*2e64fe46SCezar Bulinaru size_t build_test_packet_valid_udp_csum(uint8_t *buf, size_t payload_len)
327*2e64fe46SCezar Bulinaru {
328*2e64fe46SCezar Bulinaru uint8_t *cur = buf;
329*2e64fe46SCezar Bulinaru struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf;
330*2e64fe46SCezar Bulinaru
331*2e64fe46SCezar Bulinaru vh->flags = VIRTIO_NET_HDR_F_DATA_VALID;
332*2e64fe46SCezar Bulinaru vh->gso_type = VIRTIO_NET_HDR_GSO_NONE;
333*2e64fe46SCezar Bulinaru cur += sizeof(*vh);
334*2e64fe46SCezar Bulinaru
335*2e64fe46SCezar Bulinaru cur += build_eth(cur, ETH_P_IP);
336*2e64fe46SCezar Bulinaru cur += build_ipv4_header(cur, payload_len);
337*2e64fe46SCezar Bulinaru cur += build_udp_packet(cur, payload_len, false);
338*2e64fe46SCezar Bulinaru
339*2e64fe46SCezar Bulinaru return cur - buf;
340*2e64fe46SCezar Bulinaru }
341*2e64fe46SCezar Bulinaru
build_test_packet_crash_tap_invalid_eth_proto(uint8_t * buf,size_t payload_len)342*2e64fe46SCezar Bulinaru size_t build_test_packet_crash_tap_invalid_eth_proto(uint8_t *buf,
343*2e64fe46SCezar Bulinaru size_t payload_len)
344*2e64fe46SCezar Bulinaru {
345*2e64fe46SCezar Bulinaru uint8_t *cur = buf;
346*2e64fe46SCezar Bulinaru struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf;
347*2e64fe46SCezar Bulinaru
348*2e64fe46SCezar Bulinaru vh->hdr_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr);
349*2e64fe46SCezar Bulinaru vh->flags = 0;
350*2e64fe46SCezar Bulinaru vh->gso_type = VIRTIO_NET_HDR_GSO_UDP;
351*2e64fe46SCezar Bulinaru vh->gso_size = ETH_DATA_LEN - sizeof(struct iphdr);
352*2e64fe46SCezar Bulinaru cur += sizeof(*vh);
353*2e64fe46SCezar Bulinaru
354*2e64fe46SCezar Bulinaru cur += build_eth(cur, 0);
355*2e64fe46SCezar Bulinaru cur += sizeof(struct iphdr) + sizeof(struct udphdr);
356*2e64fe46SCezar Bulinaru cur += build_ipv4_header(cur, payload_len);
357*2e64fe46SCezar Bulinaru cur += build_udp_packet(cur, payload_len, true);
358*2e64fe46SCezar Bulinaru cur += payload_len;
359*2e64fe46SCezar Bulinaru
360*2e64fe46SCezar Bulinaru return cur - buf;
361*2e64fe46SCezar Bulinaru }
362*2e64fe46SCezar Bulinaru
FIXTURE(tap)363*2e64fe46SCezar Bulinaru FIXTURE(tap)
364*2e64fe46SCezar Bulinaru {
365*2e64fe46SCezar Bulinaru int fd;
366*2e64fe46SCezar Bulinaru };
367*2e64fe46SCezar Bulinaru
FIXTURE_SETUP(tap)368*2e64fe46SCezar Bulinaru FIXTURE_SETUP(tap)
369*2e64fe46SCezar Bulinaru {
370*2e64fe46SCezar Bulinaru int ret;
371*2e64fe46SCezar Bulinaru
372*2e64fe46SCezar Bulinaru ret = dev_create(param_dev_dummy_name, "dummy", NULL, NULL);
373*2e64fe46SCezar Bulinaru EXPECT_EQ(ret, 0);
374*2e64fe46SCezar Bulinaru
375*2e64fe46SCezar Bulinaru ret = dev_create(param_dev_tap_name, "macvtap", macvtap_fill_rtattr,
376*2e64fe46SCezar Bulinaru NULL);
377*2e64fe46SCezar Bulinaru EXPECT_EQ(ret, 0);
378*2e64fe46SCezar Bulinaru
379*2e64fe46SCezar Bulinaru self->fd = opentap(param_dev_tap_name);
380*2e64fe46SCezar Bulinaru ASSERT_GE(self->fd, 0);
381*2e64fe46SCezar Bulinaru }
382*2e64fe46SCezar Bulinaru
FIXTURE_TEARDOWN(tap)383*2e64fe46SCezar Bulinaru FIXTURE_TEARDOWN(tap)
384*2e64fe46SCezar Bulinaru {
385*2e64fe46SCezar Bulinaru int ret;
386*2e64fe46SCezar Bulinaru
387*2e64fe46SCezar Bulinaru if (self->fd != -1)
388*2e64fe46SCezar Bulinaru close(self->fd);
389*2e64fe46SCezar Bulinaru
390*2e64fe46SCezar Bulinaru ret = dev_delete(param_dev_tap_name);
391*2e64fe46SCezar Bulinaru EXPECT_EQ(ret, 0);
392*2e64fe46SCezar Bulinaru
393*2e64fe46SCezar Bulinaru ret = dev_delete(param_dev_dummy_name);
394*2e64fe46SCezar Bulinaru EXPECT_EQ(ret, 0);
395*2e64fe46SCezar Bulinaru }
396*2e64fe46SCezar Bulinaru
TEST_F(tap,test_packet_valid_udp_gso)397*2e64fe46SCezar Bulinaru TEST_F(tap, test_packet_valid_udp_gso)
398*2e64fe46SCezar Bulinaru {
399*2e64fe46SCezar Bulinaru uint8_t pkt[TEST_PACKET_SZ];
400*2e64fe46SCezar Bulinaru size_t off;
401*2e64fe46SCezar Bulinaru int ret;
402*2e64fe46SCezar Bulinaru
403*2e64fe46SCezar Bulinaru memset(pkt, 0, sizeof(pkt));
404*2e64fe46SCezar Bulinaru off = build_test_packet_valid_udp_gso(pkt, 1021);
405*2e64fe46SCezar Bulinaru ret = write(self->fd, pkt, off);
406*2e64fe46SCezar Bulinaru ASSERT_EQ(ret, off);
407*2e64fe46SCezar Bulinaru }
408*2e64fe46SCezar Bulinaru
TEST_F(tap,test_packet_valid_udp_csum)409*2e64fe46SCezar Bulinaru TEST_F(tap, test_packet_valid_udp_csum)
410*2e64fe46SCezar Bulinaru {
411*2e64fe46SCezar Bulinaru uint8_t pkt[TEST_PACKET_SZ];
412*2e64fe46SCezar Bulinaru size_t off;
413*2e64fe46SCezar Bulinaru int ret;
414*2e64fe46SCezar Bulinaru
415*2e64fe46SCezar Bulinaru memset(pkt, 0, sizeof(pkt));
416*2e64fe46SCezar Bulinaru off = build_test_packet_valid_udp_csum(pkt, 1024);
417*2e64fe46SCezar Bulinaru ret = write(self->fd, pkt, off);
418*2e64fe46SCezar Bulinaru ASSERT_EQ(ret, off);
419*2e64fe46SCezar Bulinaru }
420*2e64fe46SCezar Bulinaru
TEST_F(tap,test_packet_crash_tap_invalid_eth_proto)421*2e64fe46SCezar Bulinaru TEST_F(tap, test_packet_crash_tap_invalid_eth_proto)
422*2e64fe46SCezar Bulinaru {
423*2e64fe46SCezar Bulinaru uint8_t pkt[TEST_PACKET_SZ];
424*2e64fe46SCezar Bulinaru size_t off;
425*2e64fe46SCezar Bulinaru int ret;
426*2e64fe46SCezar Bulinaru
427*2e64fe46SCezar Bulinaru memset(pkt, 0, sizeof(pkt));
428*2e64fe46SCezar Bulinaru off = build_test_packet_crash_tap_invalid_eth_proto(pkt, 1024);
429*2e64fe46SCezar Bulinaru ret = write(self->fd, pkt, off);
430*2e64fe46SCezar Bulinaru ASSERT_EQ(ret, -1);
431*2e64fe46SCezar Bulinaru ASSERT_EQ(errno, EINVAL);
432*2e64fe46SCezar Bulinaru }
433*2e64fe46SCezar Bulinaru
434*2e64fe46SCezar Bulinaru TEST_HARNESS_MAIN
435