xref: /openbmc/linux/tools/testing/selftests/net/tap.c (revision 2e64fe46)
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