Commit 5e9ff937 authored by Richard Gobert's avatar Richard Gobert Committed by Paolo Abeni
Browse files

selftests/net: test ipip packets in gro.sh



Add IPIP test-cases to the GRO selftest.

This selftest already contains IP ID test-cases. They are now
also tested for encapsulated packets.

This commit also fixes ipip packet generation in the test.

Signed-off-by: default avatarRichard Gobert <richardbgobert@gmail.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20250923085908.4687-6-richardbgobert@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent f095a358
Loading
Loading
Loading
Loading
+39 −10
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ static bool tx_socket = true;
static int tcp_offset = -1;
static int total_hdr_len = -1;
static int ethhdr_proto = -1;
static bool ipip;
static const int num_flush_id_cases = 6;

static void vlog(const char *fmt, ...)
@@ -114,7 +115,9 @@ static void setup_sock_filter(int fd)
	int ipproto_off, opt_ipproto_off;
	int next_off;

	if (proto == PF_INET)
	if (ipip)
		next_off = sizeof(struct iphdr) + offsetof(struct iphdr, protocol);
	else if (proto == PF_INET)
		next_off = offsetof(struct iphdr, protocol);
	else
		next_off = offsetof(struct ipv6hdr, nexthdr);
@@ -244,7 +247,7 @@ static void fill_datalinklayer(void *buf)
	eth->h_proto = ethhdr_proto;
}

static void fill_networklayer(void *buf, int payload_len)
static void fill_networklayer(void *buf, int payload_len, int protocol)
{
	struct ipv6hdr *ip6h = buf;
	struct iphdr *iph = buf;
@@ -254,7 +257,7 @@ static void fill_networklayer(void *buf, int payload_len)

		ip6h->version = 6;
		ip6h->payload_len = htons(sizeof(struct tcphdr) + payload_len);
		ip6h->nexthdr = IPPROTO_TCP;
		ip6h->nexthdr = protocol;
		ip6h->hop_limit = 8;
		if (inet_pton(AF_INET6, addr6_src, &ip6h->saddr) != 1)
			error(1, errno, "inet_pton source ip6");
@@ -266,7 +269,7 @@ static void fill_networklayer(void *buf, int payload_len)
		iph->version = 4;
		iph->ihl = 5;
		iph->ttl = 8;
		iph->protocol	= IPPROTO_TCP;
		iph->protocol	= protocol;
		iph->tot_len = htons(sizeof(struct tcphdr) +
				payload_len + sizeof(struct iphdr));
		iph->frag_off = htons(0x4000); /* DF = 1, MF = 0 */
@@ -313,9 +316,19 @@ static void create_packet(void *buf, int seq_offset, int ack_offset,
{
	memset(buf, 0, total_hdr_len);
	memset(buf + total_hdr_len, 'a', payload_len);

	fill_transportlayer(buf + tcp_offset, seq_offset, ack_offset,
			    payload_len, fin);
	fill_networklayer(buf + ETH_HLEN, payload_len);

	if (ipip) {
		fill_networklayer(buf + ETH_HLEN, payload_len + sizeof(struct iphdr),
				  IPPROTO_IPIP);
		fill_networklayer(buf + ETH_HLEN + sizeof(struct iphdr),
				  payload_len, IPPROTO_TCP);
	} else {
		fill_networklayer(buf + ETH_HLEN, payload_len, IPPROTO_TCP);
	}

	fill_datalinklayer(buf);
}

@@ -416,6 +429,13 @@ static void recompute_packet(char *buf, char *no_ext, int extlen)
		iph->tot_len = htons(ntohs(iph->tot_len) + extlen);
		iph->check = 0;
		iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);

		if (ipip) {
			iph += 1;
			iph->tot_len = htons(ntohs(iph->tot_len) + extlen);
			iph->check = 0;
			iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
		}
	} else {
		ip6h->payload_len = htons(ntohs(ip6h->payload_len) + extlen);
	}
@@ -777,7 +797,7 @@ static void send_fragment4(int fd, struct sockaddr_ll *daddr)
	 */
	memset(buf + total_hdr_len, 'a', PAYLOAD_LEN * 2);
	fill_transportlayer(buf + tcp_offset, PAYLOAD_LEN, 0, PAYLOAD_LEN * 2, 0);
	fill_networklayer(buf + ETH_HLEN, PAYLOAD_LEN);
	fill_networklayer(buf + ETH_HLEN, PAYLOAD_LEN, IPPROTO_TCP);
	fill_datalinklayer(buf);

	iph->frag_off = htons(0x6000); // DF = 1, MF = 1
@@ -1071,7 +1091,7 @@ static void gro_sender(void)
		 * and min ipv6hdr size. Like MAX_HDR_SIZE,
		 * MAX_PAYLOAD is defined with the larger header of the two.
		 */
		int offset = proto == PF_INET ? 20 : 0;
		int offset = (proto == PF_INET && !ipip) ? 20 : 0;
		int remainder = (MAX_PAYLOAD + offset) % MSS;

		send_large(txfd, &daddr, remainder);
@@ -1221,7 +1241,7 @@ static void gro_receiver(void)
			check_recv_pkts(rxfd, correct_payload, 2);
		}
	} else if (strcmp(testname, "large") == 0) {
		int offset = proto == PF_INET ? 20 : 0;
		int offset = (proto == PF_INET && !ipip) ? 20 : 0;
		int remainder = (MAX_PAYLOAD + offset) % MSS;

		correct_payload[0] = (MAX_PAYLOAD + offset);
@@ -1250,6 +1270,7 @@ static void parse_args(int argc, char **argv)
		{ "iface", required_argument, NULL, 'i' },
		{ "ipv4", no_argument, NULL, '4' },
		{ "ipv6", no_argument, NULL, '6' },
		{ "ipip", no_argument, NULL, 'e' },
		{ "rx", no_argument, NULL, 'r' },
		{ "saddr", required_argument, NULL, 's' },
		{ "smac", required_argument, NULL, 'S' },
@@ -1259,7 +1280,7 @@ static void parse_args(int argc, char **argv)
	};
	int c;

	while ((c = getopt_long(argc, argv, "46d:D:i:rs:S:t:v", opts, NULL)) != -1) {
	while ((c = getopt_long(argc, argv, "46d:D:ei:rs:S:t:v", opts, NULL)) != -1) {
		switch (c) {
		case '4':
			proto = PF_INET;
@@ -1269,6 +1290,11 @@ static void parse_args(int argc, char **argv)
			proto = PF_INET6;
			ethhdr_proto = htons(ETH_P_IPV6);
			break;
		case 'e':
			ipip = true;
			proto = PF_INET;
			ethhdr_proto = htons(ETH_P_IP);
			break;
		case 'd':
			addr4_dst = addr6_dst = optarg;
			break;
@@ -1304,7 +1330,10 @@ int main(int argc, char **argv)
{
	parse_args(argc, argv);

	if (proto == PF_INET) {
	if (ipip) {
		tcp_offset = ETH_HLEN + sizeof(struct iphdr) * 2;
		total_hdr_len = tcp_offset + sizeof(struct tcphdr);
	} else if (proto == PF_INET) {
		tcp_offset = ETH_HLEN + sizeof(struct iphdr);
		total_hdr_len = tcp_offset + sizeof(struct tcphdr);
	} else if (proto == PF_INET6) {
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
readonly SERVER_MAC="aa:00:00:00:00:02"
readonly CLIENT_MAC="aa:00:00:00:00:01"
readonly TESTS=("data" "ack" "flags" "tcp" "ip" "large")
readonly PROTOS=("ipv4" "ipv6")
readonly PROTOS=("ipv4" "ipv6" "ipip")
dev=""
test="all"
proto="ipv4"