1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker * This testsuite provides conformance testing for GRO coalescing.
4*053f45beSAndroid Build Coastguard Worker *
5*053f45beSAndroid Build Coastguard Worker * Test cases:
6*053f45beSAndroid Build Coastguard Worker * 1.data
7*053f45beSAndroid Build Coastguard Worker * Data packets of the same size and same header setup with correct
8*053f45beSAndroid Build Coastguard Worker * sequence numbers coalesce. The one exception being the last data
9*053f45beSAndroid Build Coastguard Worker * packet coalesced: it can be smaller than the rest and coalesced
10*053f45beSAndroid Build Coastguard Worker * as long as it is in the same flow.
11*053f45beSAndroid Build Coastguard Worker * 2.ack
12*053f45beSAndroid Build Coastguard Worker * Pure ACK does not coalesce.
13*053f45beSAndroid Build Coastguard Worker * 3.flags
14*053f45beSAndroid Build Coastguard Worker * Specific test cases: no packets with PSH, SYN, URG, RST set will
15*053f45beSAndroid Build Coastguard Worker * be coalesced.
16*053f45beSAndroid Build Coastguard Worker * 4.tcp
17*053f45beSAndroid Build Coastguard Worker * Packets with incorrect checksum, non-consecutive seqno and
18*053f45beSAndroid Build Coastguard Worker * different TCP header options shouldn't coalesce. Nit: given that
19*053f45beSAndroid Build Coastguard Worker * some extension headers have paddings, such as timestamp, headers
20*053f45beSAndroid Build Coastguard Worker * that are padding differently would not be coalesced.
21*053f45beSAndroid Build Coastguard Worker * 5.ip:
22*053f45beSAndroid Build Coastguard Worker * Packets with different (ECN, TTL, TOS) header, ip options or
23*053f45beSAndroid Build Coastguard Worker * ip fragments (ipv6) shouldn't coalesce.
24*053f45beSAndroid Build Coastguard Worker * 6.large:
25*053f45beSAndroid Build Coastguard Worker * Packets larger than GRO_MAX_SIZE packets shouldn't coalesce.
26*053f45beSAndroid Build Coastguard Worker *
27*053f45beSAndroid Build Coastguard Worker * MSS is defined as 4096 - header because if it is too small
28*053f45beSAndroid Build Coastguard Worker * (i.e. 1500 MTU - header), it will result in many packets,
29*053f45beSAndroid Build Coastguard Worker * increasing the "large" test case's flakiness. This is because
30*053f45beSAndroid Build Coastguard Worker * due to time sensitivity in the coalescing window, the receiver
31*053f45beSAndroid Build Coastguard Worker * may not coalesce all of the packets.
32*053f45beSAndroid Build Coastguard Worker *
33*053f45beSAndroid Build Coastguard Worker * Note the timing issue applies to all of the test cases, so some
34*053f45beSAndroid Build Coastguard Worker * flakiness is to be expected.
35*053f45beSAndroid Build Coastguard Worker *
36*053f45beSAndroid Build Coastguard Worker */
37*053f45beSAndroid Build Coastguard Worker
38*053f45beSAndroid Build Coastguard Worker #define _GNU_SOURCE
39*053f45beSAndroid Build Coastguard Worker
40*053f45beSAndroid Build Coastguard Worker #include <arpa/inet.h>
41*053f45beSAndroid Build Coastguard Worker #include <errno.h>
42*053f45beSAndroid Build Coastguard Worker #include <error.h>
43*053f45beSAndroid Build Coastguard Worker #include <getopt.h>
44*053f45beSAndroid Build Coastguard Worker #include <linux/filter.h>
45*053f45beSAndroid Build Coastguard Worker #include <linux/if_packet.h>
46*053f45beSAndroid Build Coastguard Worker #include <linux/ipv6.h>
47*053f45beSAndroid Build Coastguard Worker #include <net/ethernet.h>
48*053f45beSAndroid Build Coastguard Worker #include <net/if.h>
49*053f45beSAndroid Build Coastguard Worker #include <netinet/in.h>
50*053f45beSAndroid Build Coastguard Worker #include <netinet/ip.h>
51*053f45beSAndroid Build Coastguard Worker #include <netinet/ip6.h>
52*053f45beSAndroid Build Coastguard Worker #include <netinet/tcp.h>
53*053f45beSAndroid Build Coastguard Worker #include <stdbool.h>
54*053f45beSAndroid Build Coastguard Worker #include <stddef.h>
55*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
56*053f45beSAndroid Build Coastguard Worker #include <stdarg.h>
57*053f45beSAndroid Build Coastguard Worker #include <string.h>
58*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
59*053f45beSAndroid Build Coastguard Worker
60*053f45beSAndroid Build Coastguard Worker #include "../kselftest.h"
61*053f45beSAndroid Build Coastguard Worker
62*053f45beSAndroid Build Coastguard Worker #define DPORT 8000
63*053f45beSAndroid Build Coastguard Worker #define SPORT 1500
64*053f45beSAndroid Build Coastguard Worker #define PAYLOAD_LEN 100
65*053f45beSAndroid Build Coastguard Worker #define NUM_PACKETS 4
66*053f45beSAndroid Build Coastguard Worker #define START_SEQ 100
67*053f45beSAndroid Build Coastguard Worker #define START_ACK 100
68*053f45beSAndroid Build Coastguard Worker #define ETH_P_NONE 0
69*053f45beSAndroid Build Coastguard Worker #define TOTAL_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
70*053f45beSAndroid Build Coastguard Worker #define MSS (4096 - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
71*053f45beSAndroid Build Coastguard Worker #define MAX_PAYLOAD (IP_MAXPACKET - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
72*053f45beSAndroid Build Coastguard Worker #define NUM_LARGE_PKT (MAX_PAYLOAD / MSS)
73*053f45beSAndroid Build Coastguard Worker #define MAX_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
74*053f45beSAndroid Build Coastguard Worker
75*053f45beSAndroid Build Coastguard Worker static const char *addr6_src = "fdaa::2";
76*053f45beSAndroid Build Coastguard Worker static const char *addr6_dst = "fdaa::1";
77*053f45beSAndroid Build Coastguard Worker static const char *addr4_src = "192.168.1.200";
78*053f45beSAndroid Build Coastguard Worker static const char *addr4_dst = "192.168.1.100";
79*053f45beSAndroid Build Coastguard Worker static int proto = -1;
80*053f45beSAndroid Build Coastguard Worker static uint8_t src_mac[ETH_ALEN], dst_mac[ETH_ALEN];
81*053f45beSAndroid Build Coastguard Worker static char *testname = "data";
82*053f45beSAndroid Build Coastguard Worker static char *ifname = "eth0";
83*053f45beSAndroid Build Coastguard Worker static char *smac = "aa:00:00:00:00:02";
84*053f45beSAndroid Build Coastguard Worker static char *dmac = "aa:00:00:00:00:01";
85*053f45beSAndroid Build Coastguard Worker static bool verbose;
86*053f45beSAndroid Build Coastguard Worker static bool tx_socket = true;
87*053f45beSAndroid Build Coastguard Worker static int tcp_offset = -1;
88*053f45beSAndroid Build Coastguard Worker static int total_hdr_len = -1;
89*053f45beSAndroid Build Coastguard Worker static int ethhdr_proto = -1;
90*053f45beSAndroid Build Coastguard Worker
vlog(const char * fmt,...)91*053f45beSAndroid Build Coastguard Worker static void vlog(const char *fmt, ...)
92*053f45beSAndroid Build Coastguard Worker {
93*053f45beSAndroid Build Coastguard Worker va_list args;
94*053f45beSAndroid Build Coastguard Worker
95*053f45beSAndroid Build Coastguard Worker if (verbose) {
96*053f45beSAndroid Build Coastguard Worker va_start(args, fmt);
97*053f45beSAndroid Build Coastguard Worker vfprintf(stderr, fmt, args);
98*053f45beSAndroid Build Coastguard Worker va_end(args);
99*053f45beSAndroid Build Coastguard Worker }
100*053f45beSAndroid Build Coastguard Worker }
101*053f45beSAndroid Build Coastguard Worker
setup_sock_filter(int fd)102*053f45beSAndroid Build Coastguard Worker static void setup_sock_filter(int fd)
103*053f45beSAndroid Build Coastguard Worker {
104*053f45beSAndroid Build Coastguard Worker const int dport_off = tcp_offset + offsetof(struct tcphdr, dest);
105*053f45beSAndroid Build Coastguard Worker const int ethproto_off = offsetof(struct ethhdr, h_proto);
106*053f45beSAndroid Build Coastguard Worker int optlen = 0;
107*053f45beSAndroid Build Coastguard Worker int ipproto_off;
108*053f45beSAndroid Build Coastguard Worker int next_off;
109*053f45beSAndroid Build Coastguard Worker
110*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET)
111*053f45beSAndroid Build Coastguard Worker next_off = offsetof(struct iphdr, protocol);
112*053f45beSAndroid Build Coastguard Worker else
113*053f45beSAndroid Build Coastguard Worker next_off = offsetof(struct ipv6hdr, nexthdr);
114*053f45beSAndroid Build Coastguard Worker ipproto_off = ETH_HLEN + next_off;
115*053f45beSAndroid Build Coastguard Worker
116*053f45beSAndroid Build Coastguard Worker if (strcmp(testname, "ip") == 0) {
117*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET)
118*053f45beSAndroid Build Coastguard Worker optlen = sizeof(struct ip_timestamp);
119*053f45beSAndroid Build Coastguard Worker else
120*053f45beSAndroid Build Coastguard Worker optlen = sizeof(struct ip6_frag);
121*053f45beSAndroid Build Coastguard Worker }
122*053f45beSAndroid Build Coastguard Worker
123*053f45beSAndroid Build Coastguard Worker struct sock_filter filter[] = {
124*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_LD + BPF_H + BPF_ABS, ethproto_off),
125*053f45beSAndroid Build Coastguard Worker BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ntohs(ethhdr_proto), 0, 7),
126*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ipproto_off),
127*053f45beSAndroid Build Coastguard Worker BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_TCP, 0, 5),
128*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_LD + BPF_H + BPF_ABS, dport_off),
129*053f45beSAndroid Build Coastguard Worker BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DPORT, 2, 0),
130*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_LD + BPF_H + BPF_ABS, dport_off + optlen),
131*053f45beSAndroid Build Coastguard Worker BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DPORT, 0, 1),
132*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_RET + BPF_K, 0xFFFFFFFF),
133*053f45beSAndroid Build Coastguard Worker BPF_STMT(BPF_RET + BPF_K, 0),
134*053f45beSAndroid Build Coastguard Worker };
135*053f45beSAndroid Build Coastguard Worker
136*053f45beSAndroid Build Coastguard Worker struct sock_fprog bpf = {
137*053f45beSAndroid Build Coastguard Worker .len = ARRAY_SIZE(filter),
138*053f45beSAndroid Build Coastguard Worker .filter = filter,
139*053f45beSAndroid Build Coastguard Worker };
140*053f45beSAndroid Build Coastguard Worker
141*053f45beSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0)
142*053f45beSAndroid Build Coastguard Worker error(1, errno, "error setting filter");
143*053f45beSAndroid Build Coastguard Worker }
144*053f45beSAndroid Build Coastguard Worker
checksum_nofold(void * data,size_t len,uint32_t sum)145*053f45beSAndroid Build Coastguard Worker static uint32_t checksum_nofold(void *data, size_t len, uint32_t sum)
146*053f45beSAndroid Build Coastguard Worker {
147*053f45beSAndroid Build Coastguard Worker uint16_t *words = data;
148*053f45beSAndroid Build Coastguard Worker int i;
149*053f45beSAndroid Build Coastguard Worker
150*053f45beSAndroid Build Coastguard Worker for (i = 0; i < len / 2; i++)
151*053f45beSAndroid Build Coastguard Worker sum += words[i];
152*053f45beSAndroid Build Coastguard Worker if (len & 1)
153*053f45beSAndroid Build Coastguard Worker sum += ((char *)data)[len - 1];
154*053f45beSAndroid Build Coastguard Worker return sum;
155*053f45beSAndroid Build Coastguard Worker }
156*053f45beSAndroid Build Coastguard Worker
checksum_fold(void * data,size_t len,uint32_t sum)157*053f45beSAndroid Build Coastguard Worker static uint16_t checksum_fold(void *data, size_t len, uint32_t sum)
158*053f45beSAndroid Build Coastguard Worker {
159*053f45beSAndroid Build Coastguard Worker sum = checksum_nofold(data, len, sum);
160*053f45beSAndroid Build Coastguard Worker while (sum > 0xFFFF)
161*053f45beSAndroid Build Coastguard Worker sum = (sum & 0xFFFF) + (sum >> 16);
162*053f45beSAndroid Build Coastguard Worker return ~sum;
163*053f45beSAndroid Build Coastguard Worker }
164*053f45beSAndroid Build Coastguard Worker
tcp_checksum(void * buf,int payload_len)165*053f45beSAndroid Build Coastguard Worker static uint16_t tcp_checksum(void *buf, int payload_len)
166*053f45beSAndroid Build Coastguard Worker {
167*053f45beSAndroid Build Coastguard Worker struct pseudo_header6 {
168*053f45beSAndroid Build Coastguard Worker struct in6_addr saddr;
169*053f45beSAndroid Build Coastguard Worker struct in6_addr daddr;
170*053f45beSAndroid Build Coastguard Worker uint16_t protocol;
171*053f45beSAndroid Build Coastguard Worker uint16_t payload_len;
172*053f45beSAndroid Build Coastguard Worker } ph6;
173*053f45beSAndroid Build Coastguard Worker struct pseudo_header4 {
174*053f45beSAndroid Build Coastguard Worker struct in_addr saddr;
175*053f45beSAndroid Build Coastguard Worker struct in_addr daddr;
176*053f45beSAndroid Build Coastguard Worker uint16_t protocol;
177*053f45beSAndroid Build Coastguard Worker uint16_t payload_len;
178*053f45beSAndroid Build Coastguard Worker } ph4;
179*053f45beSAndroid Build Coastguard Worker uint32_t sum = 0;
180*053f45beSAndroid Build Coastguard Worker
181*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET6) {
182*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, addr6_src, &ph6.saddr) != 1)
183*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton6 source ip pseudo");
184*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, addr6_dst, &ph6.daddr) != 1)
185*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton6 dest ip pseudo");
186*053f45beSAndroid Build Coastguard Worker ph6.protocol = htons(IPPROTO_TCP);
187*053f45beSAndroid Build Coastguard Worker ph6.payload_len = htons(sizeof(struct tcphdr) + payload_len);
188*053f45beSAndroid Build Coastguard Worker
189*053f45beSAndroid Build Coastguard Worker sum = checksum_nofold(&ph6, sizeof(ph6), 0);
190*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET) {
191*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET, addr4_src, &ph4.saddr) != 1)
192*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton source ip pseudo");
193*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET, addr4_dst, &ph4.daddr) != 1)
194*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton dest ip pseudo");
195*053f45beSAndroid Build Coastguard Worker ph4.protocol = htons(IPPROTO_TCP);
196*053f45beSAndroid Build Coastguard Worker ph4.payload_len = htons(sizeof(struct tcphdr) + payload_len);
197*053f45beSAndroid Build Coastguard Worker
198*053f45beSAndroid Build Coastguard Worker sum = checksum_nofold(&ph4, sizeof(ph4), 0);
199*053f45beSAndroid Build Coastguard Worker }
200*053f45beSAndroid Build Coastguard Worker
201*053f45beSAndroid Build Coastguard Worker return checksum_fold(buf, sizeof(struct tcphdr) + payload_len, sum);
202*053f45beSAndroid Build Coastguard Worker }
203*053f45beSAndroid Build Coastguard Worker
read_MAC(uint8_t * mac_addr,char * mac)204*053f45beSAndroid Build Coastguard Worker static void read_MAC(uint8_t *mac_addr, char *mac)
205*053f45beSAndroid Build Coastguard Worker {
206*053f45beSAndroid Build Coastguard Worker if (sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
207*053f45beSAndroid Build Coastguard Worker &mac_addr[0], &mac_addr[1], &mac_addr[2],
208*053f45beSAndroid Build Coastguard Worker &mac_addr[3], &mac_addr[4], &mac_addr[5]) != 6)
209*053f45beSAndroid Build Coastguard Worker error(1, 0, "sscanf");
210*053f45beSAndroid Build Coastguard Worker }
211*053f45beSAndroid Build Coastguard Worker
fill_datalinklayer(void * buf)212*053f45beSAndroid Build Coastguard Worker static void fill_datalinklayer(void *buf)
213*053f45beSAndroid Build Coastguard Worker {
214*053f45beSAndroid Build Coastguard Worker struct ethhdr *eth = buf;
215*053f45beSAndroid Build Coastguard Worker
216*053f45beSAndroid Build Coastguard Worker memcpy(eth->h_dest, dst_mac, ETH_ALEN);
217*053f45beSAndroid Build Coastguard Worker memcpy(eth->h_source, src_mac, ETH_ALEN);
218*053f45beSAndroid Build Coastguard Worker eth->h_proto = ethhdr_proto;
219*053f45beSAndroid Build Coastguard Worker }
220*053f45beSAndroid Build Coastguard Worker
fill_networklayer(void * buf,int payload_len)221*053f45beSAndroid Build Coastguard Worker static void fill_networklayer(void *buf, int payload_len)
222*053f45beSAndroid Build Coastguard Worker {
223*053f45beSAndroid Build Coastguard Worker struct ipv6hdr *ip6h = buf;
224*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = buf;
225*053f45beSAndroid Build Coastguard Worker
226*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET6) {
227*053f45beSAndroid Build Coastguard Worker memset(ip6h, 0, sizeof(*ip6h));
228*053f45beSAndroid Build Coastguard Worker
229*053f45beSAndroid Build Coastguard Worker ip6h->version = 6;
230*053f45beSAndroid Build Coastguard Worker ip6h->payload_len = htons(sizeof(struct tcphdr) + payload_len);
231*053f45beSAndroid Build Coastguard Worker ip6h->nexthdr = IPPROTO_TCP;
232*053f45beSAndroid Build Coastguard Worker ip6h->hop_limit = 8;
233*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, addr6_src, &ip6h->saddr) != 1)
234*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton source ip6");
235*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, addr6_dst, &ip6h->daddr) != 1)
236*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton dest ip6");
237*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET) {
238*053f45beSAndroid Build Coastguard Worker memset(iph, 0, sizeof(*iph));
239*053f45beSAndroid Build Coastguard Worker
240*053f45beSAndroid Build Coastguard Worker iph->version = 4;
241*053f45beSAndroid Build Coastguard Worker iph->ihl = 5;
242*053f45beSAndroid Build Coastguard Worker iph->ttl = 8;
243*053f45beSAndroid Build Coastguard Worker iph->protocol = IPPROTO_TCP;
244*053f45beSAndroid Build Coastguard Worker iph->tot_len = htons(sizeof(struct tcphdr) +
245*053f45beSAndroid Build Coastguard Worker payload_len + sizeof(struct iphdr));
246*053f45beSAndroid Build Coastguard Worker iph->frag_off = htons(0x4000); /* DF = 1, MF = 0 */
247*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET, addr4_src, &iph->saddr) != 1)
248*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton source ip");
249*053f45beSAndroid Build Coastguard Worker if (inet_pton(AF_INET, addr4_dst, &iph->daddr) != 1)
250*053f45beSAndroid Build Coastguard Worker error(1, errno, "inet_pton dest ip");
251*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(buf, sizeof(struct iphdr), 0);
252*053f45beSAndroid Build Coastguard Worker }
253*053f45beSAndroid Build Coastguard Worker }
254*053f45beSAndroid Build Coastguard Worker
fill_transportlayer(void * buf,int seq_offset,int ack_offset,int payload_len,int fin)255*053f45beSAndroid Build Coastguard Worker static void fill_transportlayer(void *buf, int seq_offset, int ack_offset,
256*053f45beSAndroid Build Coastguard Worker int payload_len, int fin)
257*053f45beSAndroid Build Coastguard Worker {
258*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcph = buf;
259*053f45beSAndroid Build Coastguard Worker
260*053f45beSAndroid Build Coastguard Worker memset(tcph, 0, sizeof(*tcph));
261*053f45beSAndroid Build Coastguard Worker
262*053f45beSAndroid Build Coastguard Worker tcph->source = htons(SPORT);
263*053f45beSAndroid Build Coastguard Worker tcph->dest = htons(DPORT);
264*053f45beSAndroid Build Coastguard Worker tcph->seq = ntohl(START_SEQ + seq_offset);
265*053f45beSAndroid Build Coastguard Worker tcph->ack_seq = ntohl(START_ACK + ack_offset);
266*053f45beSAndroid Build Coastguard Worker tcph->ack = 1;
267*053f45beSAndroid Build Coastguard Worker tcph->fin = fin;
268*053f45beSAndroid Build Coastguard Worker tcph->doff = 5;
269*053f45beSAndroid Build Coastguard Worker tcph->window = htons(TCP_MAXWIN);
270*053f45beSAndroid Build Coastguard Worker tcph->urg_ptr = 0;
271*053f45beSAndroid Build Coastguard Worker tcph->check = tcp_checksum(tcph, payload_len);
272*053f45beSAndroid Build Coastguard Worker }
273*053f45beSAndroid Build Coastguard Worker
write_packet(int fd,char * buf,int len,struct sockaddr_ll * daddr)274*053f45beSAndroid Build Coastguard Worker static void write_packet(int fd, char *buf, int len, struct sockaddr_ll *daddr)
275*053f45beSAndroid Build Coastguard Worker {
276*053f45beSAndroid Build Coastguard Worker int ret = -1;
277*053f45beSAndroid Build Coastguard Worker
278*053f45beSAndroid Build Coastguard Worker ret = sendto(fd, buf, len, 0, (struct sockaddr *)daddr, sizeof(*daddr));
279*053f45beSAndroid Build Coastguard Worker if (ret == -1)
280*053f45beSAndroid Build Coastguard Worker error(1, errno, "sendto failure");
281*053f45beSAndroid Build Coastguard Worker if (ret != len)
282*053f45beSAndroid Build Coastguard Worker error(1, errno, "sendto wrong length");
283*053f45beSAndroid Build Coastguard Worker }
284*053f45beSAndroid Build Coastguard Worker
create_packet(void * buf,int seq_offset,int ack_offset,int payload_len,int fin)285*053f45beSAndroid Build Coastguard Worker static void create_packet(void *buf, int seq_offset, int ack_offset,
286*053f45beSAndroid Build Coastguard Worker int payload_len, int fin)
287*053f45beSAndroid Build Coastguard Worker {
288*053f45beSAndroid Build Coastguard Worker memset(buf, 0, total_hdr_len);
289*053f45beSAndroid Build Coastguard Worker memset(buf + total_hdr_len, 'a', payload_len);
290*053f45beSAndroid Build Coastguard Worker fill_transportlayer(buf + tcp_offset, seq_offset, ack_offset,
291*053f45beSAndroid Build Coastguard Worker payload_len, fin);
292*053f45beSAndroid Build Coastguard Worker fill_networklayer(buf + ETH_HLEN, payload_len);
293*053f45beSAndroid Build Coastguard Worker fill_datalinklayer(buf);
294*053f45beSAndroid Build Coastguard Worker }
295*053f45beSAndroid Build Coastguard Worker
296*053f45beSAndroid Build Coastguard Worker /* send one extra flag, not first and not last pkt */
send_flags(int fd,struct sockaddr_ll * daddr,int psh,int syn,int rst,int urg)297*053f45beSAndroid Build Coastguard Worker static void send_flags(int fd, struct sockaddr_ll *daddr, int psh, int syn,
298*053f45beSAndroid Build Coastguard Worker int rst, int urg)
299*053f45beSAndroid Build Coastguard Worker {
300*053f45beSAndroid Build Coastguard Worker static char flag_buf[MAX_HDR_LEN + PAYLOAD_LEN];
301*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
302*053f45beSAndroid Build Coastguard Worker int payload_len, pkt_size, flag, i;
303*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcph;
304*053f45beSAndroid Build Coastguard Worker
305*053f45beSAndroid Build Coastguard Worker payload_len = PAYLOAD_LEN * psh;
306*053f45beSAndroid Build Coastguard Worker pkt_size = total_hdr_len + payload_len;
307*053f45beSAndroid Build Coastguard Worker flag = NUM_PACKETS / 2;
308*053f45beSAndroid Build Coastguard Worker
309*053f45beSAndroid Build Coastguard Worker create_packet(flag_buf, flag * payload_len, 0, payload_len, 0);
310*053f45beSAndroid Build Coastguard Worker
311*053f45beSAndroid Build Coastguard Worker tcph = (struct tcphdr *)(flag_buf + tcp_offset);
312*053f45beSAndroid Build Coastguard Worker tcph->psh = psh;
313*053f45beSAndroid Build Coastguard Worker tcph->syn = syn;
314*053f45beSAndroid Build Coastguard Worker tcph->rst = rst;
315*053f45beSAndroid Build Coastguard Worker tcph->urg = urg;
316*053f45beSAndroid Build Coastguard Worker tcph->check = 0;
317*053f45beSAndroid Build Coastguard Worker tcph->check = tcp_checksum(tcph, payload_len);
318*053f45beSAndroid Build Coastguard Worker
319*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NUM_PACKETS + 1; i++) {
320*053f45beSAndroid Build Coastguard Worker if (i == flag) {
321*053f45beSAndroid Build Coastguard Worker write_packet(fd, flag_buf, pkt_size, daddr);
322*053f45beSAndroid Build Coastguard Worker continue;
323*053f45beSAndroid Build Coastguard Worker }
324*053f45beSAndroid Build Coastguard Worker create_packet(buf, i * PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
325*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len + PAYLOAD_LEN, daddr);
326*053f45beSAndroid Build Coastguard Worker }
327*053f45beSAndroid Build Coastguard Worker }
328*053f45beSAndroid Build Coastguard Worker
329*053f45beSAndroid Build Coastguard Worker /* Test for data of same length, smaller than previous
330*053f45beSAndroid Build Coastguard Worker * and of different lengths
331*053f45beSAndroid Build Coastguard Worker */
send_data_pkts(int fd,struct sockaddr_ll * daddr,int payload_len1,int payload_len2)332*053f45beSAndroid Build Coastguard Worker static void send_data_pkts(int fd, struct sockaddr_ll *daddr,
333*053f45beSAndroid Build Coastguard Worker int payload_len1, int payload_len2)
334*053f45beSAndroid Build Coastguard Worker {
335*053f45beSAndroid Build Coastguard Worker static char buf[ETH_HLEN + IP_MAXPACKET];
336*053f45beSAndroid Build Coastguard Worker
337*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, payload_len1, 0);
338*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len + payload_len1, daddr);
339*053f45beSAndroid Build Coastguard Worker create_packet(buf, payload_len1, 0, payload_len2, 0);
340*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len + payload_len2, daddr);
341*053f45beSAndroid Build Coastguard Worker }
342*053f45beSAndroid Build Coastguard Worker
343*053f45beSAndroid Build Coastguard Worker /* If incoming segments make tracked segment length exceed
344*053f45beSAndroid Build Coastguard Worker * legal IP datagram length, do not coalesce
345*053f45beSAndroid Build Coastguard Worker */
send_large(int fd,struct sockaddr_ll * daddr,int remainder)346*053f45beSAndroid Build Coastguard Worker static void send_large(int fd, struct sockaddr_ll *daddr, int remainder)
347*053f45beSAndroid Build Coastguard Worker {
348*053f45beSAndroid Build Coastguard Worker static char pkts[NUM_LARGE_PKT][TOTAL_HDR_LEN + MSS];
349*053f45beSAndroid Build Coastguard Worker static char last[TOTAL_HDR_LEN + MSS];
350*053f45beSAndroid Build Coastguard Worker static char new_seg[TOTAL_HDR_LEN + MSS];
351*053f45beSAndroid Build Coastguard Worker int i;
352*053f45beSAndroid Build Coastguard Worker
353*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NUM_LARGE_PKT; i++)
354*053f45beSAndroid Build Coastguard Worker create_packet(pkts[i], i * MSS, 0, MSS, 0);
355*053f45beSAndroid Build Coastguard Worker create_packet(last, NUM_LARGE_PKT * MSS, 0, remainder, 0);
356*053f45beSAndroid Build Coastguard Worker create_packet(new_seg, (NUM_LARGE_PKT + 1) * MSS, 0, remainder, 0);
357*053f45beSAndroid Build Coastguard Worker
358*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NUM_LARGE_PKT; i++)
359*053f45beSAndroid Build Coastguard Worker write_packet(fd, pkts[i], total_hdr_len + MSS, daddr);
360*053f45beSAndroid Build Coastguard Worker write_packet(fd, last, total_hdr_len + remainder, daddr);
361*053f45beSAndroid Build Coastguard Worker write_packet(fd, new_seg, total_hdr_len + remainder, daddr);
362*053f45beSAndroid Build Coastguard Worker }
363*053f45beSAndroid Build Coastguard Worker
364*053f45beSAndroid Build Coastguard Worker /* Pure acks and dup acks don't coalesce */
send_ack(int fd,struct sockaddr_ll * daddr)365*053f45beSAndroid Build Coastguard Worker static void send_ack(int fd, struct sockaddr_ll *daddr)
366*053f45beSAndroid Build Coastguard Worker {
367*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN];
368*053f45beSAndroid Build Coastguard Worker
369*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, 0, 0);
370*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len, daddr);
371*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len, daddr);
372*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 1, 0, 0);
373*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len, daddr);
374*053f45beSAndroid Build Coastguard Worker }
375*053f45beSAndroid Build Coastguard Worker
recompute_packet(char * buf,char * no_ext,int extlen)376*053f45beSAndroid Build Coastguard Worker static void recompute_packet(char *buf, char *no_ext, int extlen)
377*053f45beSAndroid Build Coastguard Worker {
378*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcphdr = (struct tcphdr *)(buf + tcp_offset);
379*053f45beSAndroid Build Coastguard Worker struct ipv6hdr *ip6h = (struct ipv6hdr *)(buf + ETH_HLEN);
380*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
381*053f45beSAndroid Build Coastguard Worker
382*053f45beSAndroid Build Coastguard Worker memmove(buf, no_ext, total_hdr_len);
383*053f45beSAndroid Build Coastguard Worker memmove(buf + total_hdr_len + extlen,
384*053f45beSAndroid Build Coastguard Worker no_ext + total_hdr_len, PAYLOAD_LEN);
385*053f45beSAndroid Build Coastguard Worker
386*053f45beSAndroid Build Coastguard Worker tcphdr->doff = tcphdr->doff + (extlen / 4);
387*053f45beSAndroid Build Coastguard Worker tcphdr->check = 0;
388*053f45beSAndroid Build Coastguard Worker tcphdr->check = tcp_checksum(tcphdr, PAYLOAD_LEN + extlen);
389*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
390*053f45beSAndroid Build Coastguard Worker iph->tot_len = htons(ntohs(iph->tot_len) + extlen);
391*053f45beSAndroid Build Coastguard Worker iph->check = 0;
392*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
393*053f45beSAndroid Build Coastguard Worker } else {
394*053f45beSAndroid Build Coastguard Worker ip6h->payload_len = htons(ntohs(ip6h->payload_len) + extlen);
395*053f45beSAndroid Build Coastguard Worker }
396*053f45beSAndroid Build Coastguard Worker }
397*053f45beSAndroid Build Coastguard Worker
tcp_write_options(char * buf,int kind,int ts)398*053f45beSAndroid Build Coastguard Worker static void tcp_write_options(char *buf, int kind, int ts)
399*053f45beSAndroid Build Coastguard Worker {
400*053f45beSAndroid Build Coastguard Worker struct tcp_option_ts {
401*053f45beSAndroid Build Coastguard Worker uint8_t kind;
402*053f45beSAndroid Build Coastguard Worker uint8_t len;
403*053f45beSAndroid Build Coastguard Worker uint32_t tsval;
404*053f45beSAndroid Build Coastguard Worker uint32_t tsecr;
405*053f45beSAndroid Build Coastguard Worker } *opt_ts = (void *)buf;
406*053f45beSAndroid Build Coastguard Worker struct tcp_option_window {
407*053f45beSAndroid Build Coastguard Worker uint8_t kind;
408*053f45beSAndroid Build Coastguard Worker uint8_t len;
409*053f45beSAndroid Build Coastguard Worker uint8_t shift;
410*053f45beSAndroid Build Coastguard Worker } *opt_window = (void *)buf;
411*053f45beSAndroid Build Coastguard Worker
412*053f45beSAndroid Build Coastguard Worker switch (kind) {
413*053f45beSAndroid Build Coastguard Worker case TCPOPT_NOP:
414*053f45beSAndroid Build Coastguard Worker buf[0] = TCPOPT_NOP;
415*053f45beSAndroid Build Coastguard Worker break;
416*053f45beSAndroid Build Coastguard Worker case TCPOPT_WINDOW:
417*053f45beSAndroid Build Coastguard Worker memset(opt_window, 0, sizeof(struct tcp_option_window));
418*053f45beSAndroid Build Coastguard Worker opt_window->kind = TCPOPT_WINDOW;
419*053f45beSAndroid Build Coastguard Worker opt_window->len = TCPOLEN_WINDOW;
420*053f45beSAndroid Build Coastguard Worker opt_window->shift = 0;
421*053f45beSAndroid Build Coastguard Worker break;
422*053f45beSAndroid Build Coastguard Worker case TCPOPT_TIMESTAMP:
423*053f45beSAndroid Build Coastguard Worker memset(opt_ts, 0, sizeof(struct tcp_option_ts));
424*053f45beSAndroid Build Coastguard Worker opt_ts->kind = TCPOPT_TIMESTAMP;
425*053f45beSAndroid Build Coastguard Worker opt_ts->len = TCPOLEN_TIMESTAMP;
426*053f45beSAndroid Build Coastguard Worker opt_ts->tsval = ts;
427*053f45beSAndroid Build Coastguard Worker opt_ts->tsecr = 0;
428*053f45beSAndroid Build Coastguard Worker break;
429*053f45beSAndroid Build Coastguard Worker default:
430*053f45beSAndroid Build Coastguard Worker error(1, 0, "unimplemented TCP option");
431*053f45beSAndroid Build Coastguard Worker break;
432*053f45beSAndroid Build Coastguard Worker }
433*053f45beSAndroid Build Coastguard Worker }
434*053f45beSAndroid Build Coastguard Worker
435*053f45beSAndroid Build Coastguard Worker /* TCP with options is always a permutation of {TS, NOP, NOP}.
436*053f45beSAndroid Build Coastguard Worker * Implement different orders to verify coalescing stops.
437*053f45beSAndroid Build Coastguard Worker */
add_standard_tcp_options(char * buf,char * no_ext,int ts,int order)438*053f45beSAndroid Build Coastguard Worker static void add_standard_tcp_options(char *buf, char *no_ext, int ts, int order)
439*053f45beSAndroid Build Coastguard Worker {
440*053f45beSAndroid Build Coastguard Worker switch (order) {
441*053f45beSAndroid Build Coastguard Worker case 0:
442*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len, TCPOPT_NOP, 0);
443*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + 1, TCPOPT_NOP, 0);
444*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + 2 /* two NOP opts */,
445*053f45beSAndroid Build Coastguard Worker TCPOPT_TIMESTAMP, ts);
446*053f45beSAndroid Build Coastguard Worker break;
447*053f45beSAndroid Build Coastguard Worker case 1:
448*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len, TCPOPT_NOP, 0);
449*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + 1,
450*053f45beSAndroid Build Coastguard Worker TCPOPT_TIMESTAMP, ts);
451*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + 1 + TCPOLEN_TIMESTAMP,
452*053f45beSAndroid Build Coastguard Worker TCPOPT_NOP, 0);
453*053f45beSAndroid Build Coastguard Worker break;
454*053f45beSAndroid Build Coastguard Worker case 2:
455*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len, TCPOPT_TIMESTAMP, ts);
456*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + TCPOLEN_TIMESTAMP + 1,
457*053f45beSAndroid Build Coastguard Worker TCPOPT_NOP, 0);
458*053f45beSAndroid Build Coastguard Worker tcp_write_options(buf + total_hdr_len + TCPOLEN_TIMESTAMP + 2,
459*053f45beSAndroid Build Coastguard Worker TCPOPT_NOP, 0);
460*053f45beSAndroid Build Coastguard Worker break;
461*053f45beSAndroid Build Coastguard Worker default:
462*053f45beSAndroid Build Coastguard Worker error(1, 0, "unknown order");
463*053f45beSAndroid Build Coastguard Worker break;
464*053f45beSAndroid Build Coastguard Worker }
465*053f45beSAndroid Build Coastguard Worker recompute_packet(buf, no_ext, TCPOLEN_TSTAMP_APPA);
466*053f45beSAndroid Build Coastguard Worker }
467*053f45beSAndroid Build Coastguard Worker
468*053f45beSAndroid Build Coastguard Worker /* Packets with invalid checksum don't coalesce. */
send_changed_checksum(int fd,struct sockaddr_ll * daddr)469*053f45beSAndroid Build Coastguard Worker static void send_changed_checksum(int fd, struct sockaddr_ll *daddr)
470*053f45beSAndroid Build Coastguard Worker {
471*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
472*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcph = (struct tcphdr *)(buf + tcp_offset);
473*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
474*053f45beSAndroid Build Coastguard Worker
475*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
476*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
477*053f45beSAndroid Build Coastguard Worker
478*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
479*053f45beSAndroid Build Coastguard Worker tcph->check = tcph->check - 1;
480*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
481*053f45beSAndroid Build Coastguard Worker }
482*053f45beSAndroid Build Coastguard Worker
483*053f45beSAndroid Build Coastguard Worker /* Packets with non-consecutive sequence number don't coalesce.*/
send_changed_seq(int fd,struct sockaddr_ll * daddr)484*053f45beSAndroid Build Coastguard Worker static void send_changed_seq(int fd, struct sockaddr_ll *daddr)
485*053f45beSAndroid Build Coastguard Worker {
486*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
487*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcph = (struct tcphdr *)(buf + tcp_offset);
488*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
489*053f45beSAndroid Build Coastguard Worker
490*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
491*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
492*053f45beSAndroid Build Coastguard Worker
493*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
494*053f45beSAndroid Build Coastguard Worker tcph->seq = ntohl(htonl(tcph->seq) + 1);
495*053f45beSAndroid Build Coastguard Worker tcph->check = 0;
496*053f45beSAndroid Build Coastguard Worker tcph->check = tcp_checksum(tcph, PAYLOAD_LEN);
497*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
498*053f45beSAndroid Build Coastguard Worker }
499*053f45beSAndroid Build Coastguard Worker
500*053f45beSAndroid Build Coastguard Worker /* Packet with different timestamp option or different timestamps
501*053f45beSAndroid Build Coastguard Worker * don't coalesce.
502*053f45beSAndroid Build Coastguard Worker */
send_changed_ts(int fd,struct sockaddr_ll * daddr)503*053f45beSAndroid Build Coastguard Worker static void send_changed_ts(int fd, struct sockaddr_ll *daddr)
504*053f45beSAndroid Build Coastguard Worker {
505*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
506*053f45beSAndroid Build Coastguard Worker static char extpkt[sizeof(buf) + TCPOLEN_TSTAMP_APPA];
507*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN + TCPOLEN_TSTAMP_APPA;
508*053f45beSAndroid Build Coastguard Worker
509*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
510*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt, buf, 0, 0);
511*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, pkt_size, daddr);
512*053f45beSAndroid Build Coastguard Worker
513*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
514*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt, buf, 0, 0);
515*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, pkt_size, daddr);
516*053f45beSAndroid Build Coastguard Worker
517*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0);
518*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt, buf, 100, 0);
519*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, pkt_size, daddr);
520*053f45beSAndroid Build Coastguard Worker
521*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 3, 0, PAYLOAD_LEN, 0);
522*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt, buf, 100, 1);
523*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, pkt_size, daddr);
524*053f45beSAndroid Build Coastguard Worker
525*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 4, 0, PAYLOAD_LEN, 0);
526*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt, buf, 100, 2);
527*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, pkt_size, daddr);
528*053f45beSAndroid Build Coastguard Worker }
529*053f45beSAndroid Build Coastguard Worker
530*053f45beSAndroid Build Coastguard Worker /* Packet with different tcp options don't coalesce. */
send_diff_opt(int fd,struct sockaddr_ll * daddr)531*053f45beSAndroid Build Coastguard Worker static void send_diff_opt(int fd, struct sockaddr_ll *daddr)
532*053f45beSAndroid Build Coastguard Worker {
533*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
534*053f45beSAndroid Build Coastguard Worker static char extpkt1[sizeof(buf) + TCPOLEN_TSTAMP_APPA];
535*053f45beSAndroid Build Coastguard Worker static char extpkt2[sizeof(buf) + TCPOLEN_MAXSEG];
536*053f45beSAndroid Build Coastguard Worker int extpkt1_size = total_hdr_len + PAYLOAD_LEN + TCPOLEN_TSTAMP_APPA;
537*053f45beSAndroid Build Coastguard Worker int extpkt2_size = total_hdr_len + PAYLOAD_LEN + TCPOLEN_MAXSEG;
538*053f45beSAndroid Build Coastguard Worker
539*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
540*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt1, buf, 0, 0);
541*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt1, extpkt1_size, daddr);
542*053f45beSAndroid Build Coastguard Worker
543*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
544*053f45beSAndroid Build Coastguard Worker add_standard_tcp_options(extpkt1, buf, 0, 0);
545*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt1, extpkt1_size, daddr);
546*053f45beSAndroid Build Coastguard Worker
547*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0);
548*053f45beSAndroid Build Coastguard Worker tcp_write_options(extpkt2 + MAX_HDR_LEN, TCPOPT_NOP, 0);
549*053f45beSAndroid Build Coastguard Worker tcp_write_options(extpkt2 + MAX_HDR_LEN + 1, TCPOPT_WINDOW, 0);
550*053f45beSAndroid Build Coastguard Worker recompute_packet(extpkt2, buf, TCPOLEN_WINDOW + 1);
551*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt2, extpkt2_size, daddr);
552*053f45beSAndroid Build Coastguard Worker }
553*053f45beSAndroid Build Coastguard Worker
add_ipv4_ts_option(void * buf,void * optpkt)554*053f45beSAndroid Build Coastguard Worker static void add_ipv4_ts_option(void *buf, void *optpkt)
555*053f45beSAndroid Build Coastguard Worker {
556*053f45beSAndroid Build Coastguard Worker struct ip_timestamp *ts = (struct ip_timestamp *)(optpkt + tcp_offset);
557*053f45beSAndroid Build Coastguard Worker int optlen = sizeof(struct ip_timestamp);
558*053f45beSAndroid Build Coastguard Worker struct iphdr *iph;
559*053f45beSAndroid Build Coastguard Worker
560*053f45beSAndroid Build Coastguard Worker if (optlen % 4)
561*053f45beSAndroid Build Coastguard Worker error(1, 0, "ipv4 timestamp length is not a multiple of 4B");
562*053f45beSAndroid Build Coastguard Worker
563*053f45beSAndroid Build Coastguard Worker ts->ipt_code = IPOPT_TS;
564*053f45beSAndroid Build Coastguard Worker ts->ipt_len = optlen;
565*053f45beSAndroid Build Coastguard Worker ts->ipt_ptr = 5;
566*053f45beSAndroid Build Coastguard Worker ts->ipt_flg = IPOPT_TS_TSONLY;
567*053f45beSAndroid Build Coastguard Worker
568*053f45beSAndroid Build Coastguard Worker memcpy(optpkt, buf, tcp_offset);
569*053f45beSAndroid Build Coastguard Worker memcpy(optpkt + tcp_offset + optlen, buf + tcp_offset,
570*053f45beSAndroid Build Coastguard Worker sizeof(struct tcphdr) + PAYLOAD_LEN);
571*053f45beSAndroid Build Coastguard Worker
572*053f45beSAndroid Build Coastguard Worker iph = (struct iphdr *)(optpkt + ETH_HLEN);
573*053f45beSAndroid Build Coastguard Worker iph->ihl = 5 + (optlen / 4);
574*053f45beSAndroid Build Coastguard Worker iph->tot_len = htons(ntohs(iph->tot_len) + optlen);
575*053f45beSAndroid Build Coastguard Worker iph->check = 0;
576*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr) + optlen, 0);
577*053f45beSAndroid Build Coastguard Worker }
578*053f45beSAndroid Build Coastguard Worker
579*053f45beSAndroid Build Coastguard Worker /* IPv4 options shouldn't coalesce */
send_ip_options(int fd,struct sockaddr_ll * daddr)580*053f45beSAndroid Build Coastguard Worker static void send_ip_options(int fd, struct sockaddr_ll *daddr)
581*053f45beSAndroid Build Coastguard Worker {
582*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
583*053f45beSAndroid Build Coastguard Worker static char optpkt[sizeof(buf) + sizeof(struct ip_timestamp)];
584*053f45beSAndroid Build Coastguard Worker int optlen = sizeof(struct ip_timestamp);
585*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN + optlen;
586*053f45beSAndroid Build Coastguard Worker
587*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
588*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len + PAYLOAD_LEN, daddr);
589*053f45beSAndroid Build Coastguard Worker
590*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 1, 0, PAYLOAD_LEN, 0);
591*053f45beSAndroid Build Coastguard Worker add_ipv4_ts_option(buf, optpkt);
592*053f45beSAndroid Build Coastguard Worker write_packet(fd, optpkt, pkt_size, daddr);
593*053f45beSAndroid Build Coastguard Worker
594*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0);
595*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, total_hdr_len + PAYLOAD_LEN, daddr);
596*053f45beSAndroid Build Coastguard Worker }
597*053f45beSAndroid Build Coastguard Worker
598*053f45beSAndroid Build Coastguard Worker /* IPv4 fragments shouldn't coalesce */
send_fragment4(int fd,struct sockaddr_ll * daddr)599*053f45beSAndroid Build Coastguard Worker static void send_fragment4(int fd, struct sockaddr_ll *daddr)
600*053f45beSAndroid Build Coastguard Worker {
601*053f45beSAndroid Build Coastguard Worker static char buf[IP_MAXPACKET];
602*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
603*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
604*053f45beSAndroid Build Coastguard Worker
605*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
606*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
607*053f45beSAndroid Build Coastguard Worker
608*053f45beSAndroid Build Coastguard Worker /* Once fragmented, packet would retain the total_len.
609*053f45beSAndroid Build Coastguard Worker * Tcp header is prepared as if rest of data is in follow-up frags,
610*053f45beSAndroid Build Coastguard Worker * but follow up frags aren't actually sent.
611*053f45beSAndroid Build Coastguard Worker */
612*053f45beSAndroid Build Coastguard Worker memset(buf + total_hdr_len, 'a', PAYLOAD_LEN * 2);
613*053f45beSAndroid Build Coastguard Worker fill_transportlayer(buf + tcp_offset, PAYLOAD_LEN, 0, PAYLOAD_LEN * 2, 0);
614*053f45beSAndroid Build Coastguard Worker fill_networklayer(buf + ETH_HLEN, PAYLOAD_LEN);
615*053f45beSAndroid Build Coastguard Worker fill_datalinklayer(buf);
616*053f45beSAndroid Build Coastguard Worker
617*053f45beSAndroid Build Coastguard Worker iph->frag_off = htons(0x6000); // DF = 1, MF = 1
618*053f45beSAndroid Build Coastguard Worker iph->check = 0;
619*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
620*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
621*053f45beSAndroid Build Coastguard Worker }
622*053f45beSAndroid Build Coastguard Worker
623*053f45beSAndroid Build Coastguard Worker /* IPv4 packets with different ttl don't coalesce.*/
send_changed_ttl(int fd,struct sockaddr_ll * daddr)624*053f45beSAndroid Build Coastguard Worker static void send_changed_ttl(int fd, struct sockaddr_ll *daddr)
625*053f45beSAndroid Build Coastguard Worker {
626*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
627*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
628*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
629*053f45beSAndroid Build Coastguard Worker
630*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
631*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
632*053f45beSAndroid Build Coastguard Worker
633*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
634*053f45beSAndroid Build Coastguard Worker iph->ttl = 7;
635*053f45beSAndroid Build Coastguard Worker iph->check = 0;
636*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
637*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
638*053f45beSAndroid Build Coastguard Worker }
639*053f45beSAndroid Build Coastguard Worker
640*053f45beSAndroid Build Coastguard Worker /* Packets with different tos don't coalesce.*/
send_changed_tos(int fd,struct sockaddr_ll * daddr)641*053f45beSAndroid Build Coastguard Worker static void send_changed_tos(int fd, struct sockaddr_ll *daddr)
642*053f45beSAndroid Build Coastguard Worker {
643*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
644*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
645*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
646*053f45beSAndroid Build Coastguard Worker struct ipv6hdr *ip6h = (struct ipv6hdr *)(buf + ETH_HLEN);
647*053f45beSAndroid Build Coastguard Worker
648*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
649*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
650*053f45beSAndroid Build Coastguard Worker
651*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
652*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
653*053f45beSAndroid Build Coastguard Worker iph->tos = 1;
654*053f45beSAndroid Build Coastguard Worker iph->check = 0;
655*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
656*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET6) {
657*053f45beSAndroid Build Coastguard Worker ip6h->priority = 0xf;
658*053f45beSAndroid Build Coastguard Worker }
659*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
660*053f45beSAndroid Build Coastguard Worker }
661*053f45beSAndroid Build Coastguard Worker
662*053f45beSAndroid Build Coastguard Worker /* Packets with different ECN don't coalesce.*/
send_changed_ECN(int fd,struct sockaddr_ll * daddr)663*053f45beSAndroid Build Coastguard Worker static void send_changed_ECN(int fd, struct sockaddr_ll *daddr)
664*053f45beSAndroid Build Coastguard Worker {
665*053f45beSAndroid Build Coastguard Worker int pkt_size = total_hdr_len + PAYLOAD_LEN;
666*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
667*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
668*053f45beSAndroid Build Coastguard Worker
669*053f45beSAndroid Build Coastguard Worker create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
670*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
671*053f45beSAndroid Build Coastguard Worker
672*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
673*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
674*053f45beSAndroid Build Coastguard Worker buf[ETH_HLEN + 1] ^= 0x2; // ECN set to 10
675*053f45beSAndroid Build Coastguard Worker iph->check = 0;
676*053f45beSAndroid Build Coastguard Worker iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
677*053f45beSAndroid Build Coastguard Worker } else {
678*053f45beSAndroid Build Coastguard Worker buf[ETH_HLEN + 1] ^= 0x20; // ECN set to 10
679*053f45beSAndroid Build Coastguard Worker }
680*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, pkt_size, daddr);
681*053f45beSAndroid Build Coastguard Worker }
682*053f45beSAndroid Build Coastguard Worker
683*053f45beSAndroid Build Coastguard Worker /* IPv6 fragments and packets with extensions don't coalesce.*/
send_fragment6(int fd,struct sockaddr_ll * daddr)684*053f45beSAndroid Build Coastguard Worker static void send_fragment6(int fd, struct sockaddr_ll *daddr)
685*053f45beSAndroid Build Coastguard Worker {
686*053f45beSAndroid Build Coastguard Worker static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
687*053f45beSAndroid Build Coastguard Worker static char extpkt[MAX_HDR_LEN + PAYLOAD_LEN +
688*053f45beSAndroid Build Coastguard Worker sizeof(struct ip6_frag)];
689*053f45beSAndroid Build Coastguard Worker struct ipv6hdr *ip6h = (struct ipv6hdr *)(buf + ETH_HLEN);
690*053f45beSAndroid Build Coastguard Worker struct ip6_frag *frag = (void *)(extpkt + tcp_offset);
691*053f45beSAndroid Build Coastguard Worker int extlen = sizeof(struct ip6_frag);
692*053f45beSAndroid Build Coastguard Worker int bufpkt_len = total_hdr_len + PAYLOAD_LEN;
693*053f45beSAndroid Build Coastguard Worker int extpkt_len = bufpkt_len + extlen;
694*053f45beSAndroid Build Coastguard Worker int i;
695*053f45beSAndroid Build Coastguard Worker
696*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
697*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * i, 0, PAYLOAD_LEN, 0);
698*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, bufpkt_len, daddr);
699*053f45beSAndroid Build Coastguard Worker }
700*053f45beSAndroid Build Coastguard Worker
701*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0);
702*053f45beSAndroid Build Coastguard Worker memset(extpkt, 0, extpkt_len);
703*053f45beSAndroid Build Coastguard Worker
704*053f45beSAndroid Build Coastguard Worker ip6h->nexthdr = IPPROTO_FRAGMENT;
705*053f45beSAndroid Build Coastguard Worker ip6h->payload_len = htons(ntohs(ip6h->payload_len) + extlen);
706*053f45beSAndroid Build Coastguard Worker frag->ip6f_nxt = IPPROTO_TCP;
707*053f45beSAndroid Build Coastguard Worker
708*053f45beSAndroid Build Coastguard Worker memcpy(extpkt, buf, tcp_offset);
709*053f45beSAndroid Build Coastguard Worker memcpy(extpkt + tcp_offset + extlen, buf + tcp_offset,
710*053f45beSAndroid Build Coastguard Worker sizeof(struct tcphdr) + PAYLOAD_LEN);
711*053f45beSAndroid Build Coastguard Worker write_packet(fd, extpkt, extpkt_len, daddr);
712*053f45beSAndroid Build Coastguard Worker
713*053f45beSAndroid Build Coastguard Worker create_packet(buf, PAYLOAD_LEN * 3, 0, PAYLOAD_LEN, 0);
714*053f45beSAndroid Build Coastguard Worker write_packet(fd, buf, bufpkt_len, daddr);
715*053f45beSAndroid Build Coastguard Worker }
716*053f45beSAndroid Build Coastguard Worker
bind_packetsocket(int fd)717*053f45beSAndroid Build Coastguard Worker static void bind_packetsocket(int fd)
718*053f45beSAndroid Build Coastguard Worker {
719*053f45beSAndroid Build Coastguard Worker struct sockaddr_ll daddr = {};
720*053f45beSAndroid Build Coastguard Worker
721*053f45beSAndroid Build Coastguard Worker daddr.sll_family = AF_PACKET;
722*053f45beSAndroid Build Coastguard Worker daddr.sll_protocol = ethhdr_proto;
723*053f45beSAndroid Build Coastguard Worker daddr.sll_ifindex = if_nametoindex(ifname);
724*053f45beSAndroid Build Coastguard Worker if (daddr.sll_ifindex == 0)
725*053f45beSAndroid Build Coastguard Worker error(1, errno, "if_nametoindex");
726*053f45beSAndroid Build Coastguard Worker
727*053f45beSAndroid Build Coastguard Worker if (bind(fd, (void *)&daddr, sizeof(daddr)) < 0)
728*053f45beSAndroid Build Coastguard Worker error(1, errno, "could not bind socket");
729*053f45beSAndroid Build Coastguard Worker }
730*053f45beSAndroid Build Coastguard Worker
set_timeout(int fd)731*053f45beSAndroid Build Coastguard Worker static void set_timeout(int fd)
732*053f45beSAndroid Build Coastguard Worker {
733*053f45beSAndroid Build Coastguard Worker struct timeval timeout;
734*053f45beSAndroid Build Coastguard Worker
735*053f45beSAndroid Build Coastguard Worker timeout.tv_sec = 3;
736*053f45beSAndroid Build Coastguard Worker timeout.tv_usec = 0;
737*053f45beSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
738*053f45beSAndroid Build Coastguard Worker sizeof(timeout)) < 0)
739*053f45beSAndroid Build Coastguard Worker error(1, errno, "cannot set timeout, setsockopt failed");
740*053f45beSAndroid Build Coastguard Worker }
741*053f45beSAndroid Build Coastguard Worker
check_recv_pkts(int fd,int * correct_payload,int correct_num_pkts)742*053f45beSAndroid Build Coastguard Worker static void check_recv_pkts(int fd, int *correct_payload,
743*053f45beSAndroid Build Coastguard Worker int correct_num_pkts)
744*053f45beSAndroid Build Coastguard Worker {
745*053f45beSAndroid Build Coastguard Worker static char buffer[IP_MAXPACKET + ETH_HLEN + 1];
746*053f45beSAndroid Build Coastguard Worker struct iphdr *iph = (struct iphdr *)(buffer + ETH_HLEN);
747*053f45beSAndroid Build Coastguard Worker struct ipv6hdr *ip6h = (struct ipv6hdr *)(buffer + ETH_HLEN);
748*053f45beSAndroid Build Coastguard Worker struct tcphdr *tcph;
749*053f45beSAndroid Build Coastguard Worker bool bad_packet = false;
750*053f45beSAndroid Build Coastguard Worker int tcp_ext_len = 0;
751*053f45beSAndroid Build Coastguard Worker int ip_ext_len = 0;
752*053f45beSAndroid Build Coastguard Worker int pkt_size = -1;
753*053f45beSAndroid Build Coastguard Worker int data_len = 0;
754*053f45beSAndroid Build Coastguard Worker int num_pkt = 0;
755*053f45beSAndroid Build Coastguard Worker int i;
756*053f45beSAndroid Build Coastguard Worker
757*053f45beSAndroid Build Coastguard Worker vlog("Expected {");
758*053f45beSAndroid Build Coastguard Worker for (i = 0; i < correct_num_pkts; i++)
759*053f45beSAndroid Build Coastguard Worker vlog("%d ", correct_payload[i]);
760*053f45beSAndroid Build Coastguard Worker vlog("}, Total %d packets\nReceived {", correct_num_pkts);
761*053f45beSAndroid Build Coastguard Worker
762*053f45beSAndroid Build Coastguard Worker while (1) {
763*053f45beSAndroid Build Coastguard Worker pkt_size = recv(fd, buffer, IP_MAXPACKET + ETH_HLEN + 1, 0);
764*053f45beSAndroid Build Coastguard Worker if (pkt_size < 0)
765*053f45beSAndroid Build Coastguard Worker error(1, errno, "could not receive");
766*053f45beSAndroid Build Coastguard Worker
767*053f45beSAndroid Build Coastguard Worker if (iph->version == 4)
768*053f45beSAndroid Build Coastguard Worker ip_ext_len = (iph->ihl - 5) * 4;
769*053f45beSAndroid Build Coastguard Worker else if (ip6h->version == 6 && ip6h->nexthdr != IPPROTO_TCP)
770*053f45beSAndroid Build Coastguard Worker ip_ext_len = sizeof(struct ip6_frag);
771*053f45beSAndroid Build Coastguard Worker
772*053f45beSAndroid Build Coastguard Worker tcph = (struct tcphdr *)(buffer + tcp_offset + ip_ext_len);
773*053f45beSAndroid Build Coastguard Worker
774*053f45beSAndroid Build Coastguard Worker if (tcph->fin)
775*053f45beSAndroid Build Coastguard Worker break;
776*053f45beSAndroid Build Coastguard Worker
777*053f45beSAndroid Build Coastguard Worker tcp_ext_len = (tcph->doff - 5) * 4;
778*053f45beSAndroid Build Coastguard Worker data_len = pkt_size - total_hdr_len - tcp_ext_len - ip_ext_len;
779*053f45beSAndroid Build Coastguard Worker /* Min ethernet frame payload is 46(ETH_ZLEN - ETH_HLEN) by RFC 802.3.
780*053f45beSAndroid Build Coastguard Worker * Ipv4/tcp packets without at least 6 bytes of data will be padded.
781*053f45beSAndroid Build Coastguard Worker * Packet sockets are protocol agnostic, and will not trim the padding.
782*053f45beSAndroid Build Coastguard Worker */
783*053f45beSAndroid Build Coastguard Worker if (pkt_size == ETH_ZLEN && iph->version == 4) {
784*053f45beSAndroid Build Coastguard Worker data_len = ntohs(iph->tot_len)
785*053f45beSAndroid Build Coastguard Worker - sizeof(struct tcphdr) - sizeof(struct iphdr);
786*053f45beSAndroid Build Coastguard Worker }
787*053f45beSAndroid Build Coastguard Worker vlog("%d ", data_len);
788*053f45beSAndroid Build Coastguard Worker if (data_len != correct_payload[num_pkt]) {
789*053f45beSAndroid Build Coastguard Worker vlog("[!=%d]", correct_payload[num_pkt]);
790*053f45beSAndroid Build Coastguard Worker bad_packet = true;
791*053f45beSAndroid Build Coastguard Worker }
792*053f45beSAndroid Build Coastguard Worker num_pkt++;
793*053f45beSAndroid Build Coastguard Worker }
794*053f45beSAndroid Build Coastguard Worker vlog("}, Total %d packets.\n", num_pkt);
795*053f45beSAndroid Build Coastguard Worker if (num_pkt != correct_num_pkts)
796*053f45beSAndroid Build Coastguard Worker error(1, 0, "incorrect number of packets");
797*053f45beSAndroid Build Coastguard Worker if (bad_packet)
798*053f45beSAndroid Build Coastguard Worker error(1, 0, "incorrect packet geometry");
799*053f45beSAndroid Build Coastguard Worker
800*053f45beSAndroid Build Coastguard Worker printf("Test succeeded\n\n");
801*053f45beSAndroid Build Coastguard Worker }
802*053f45beSAndroid Build Coastguard Worker
gro_sender(void)803*053f45beSAndroid Build Coastguard Worker static void gro_sender(void)
804*053f45beSAndroid Build Coastguard Worker {
805*053f45beSAndroid Build Coastguard Worker static char fin_pkt[MAX_HDR_LEN];
806*053f45beSAndroid Build Coastguard Worker struct sockaddr_ll daddr = {};
807*053f45beSAndroid Build Coastguard Worker int txfd = -1;
808*053f45beSAndroid Build Coastguard Worker
809*053f45beSAndroid Build Coastguard Worker txfd = socket(PF_PACKET, SOCK_RAW, IPPROTO_RAW);
810*053f45beSAndroid Build Coastguard Worker if (txfd < 0)
811*053f45beSAndroid Build Coastguard Worker error(1, errno, "socket creation");
812*053f45beSAndroid Build Coastguard Worker
813*053f45beSAndroid Build Coastguard Worker memset(&daddr, 0, sizeof(daddr));
814*053f45beSAndroid Build Coastguard Worker daddr.sll_ifindex = if_nametoindex(ifname);
815*053f45beSAndroid Build Coastguard Worker if (daddr.sll_ifindex == 0)
816*053f45beSAndroid Build Coastguard Worker error(1, errno, "if_nametoindex");
817*053f45beSAndroid Build Coastguard Worker daddr.sll_family = AF_PACKET;
818*053f45beSAndroid Build Coastguard Worker memcpy(daddr.sll_addr, dst_mac, ETH_ALEN);
819*053f45beSAndroid Build Coastguard Worker daddr.sll_halen = ETH_ALEN;
820*053f45beSAndroid Build Coastguard Worker create_packet(fin_pkt, PAYLOAD_LEN * 2, 0, 0, 1);
821*053f45beSAndroid Build Coastguard Worker
822*053f45beSAndroid Build Coastguard Worker if (strcmp(testname, "data") == 0) {
823*053f45beSAndroid Build Coastguard Worker send_data_pkts(txfd, &daddr, PAYLOAD_LEN, PAYLOAD_LEN);
824*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
825*053f45beSAndroid Build Coastguard Worker
826*053f45beSAndroid Build Coastguard Worker send_data_pkts(txfd, &daddr, PAYLOAD_LEN, PAYLOAD_LEN / 2);
827*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
828*053f45beSAndroid Build Coastguard Worker
829*053f45beSAndroid Build Coastguard Worker send_data_pkts(txfd, &daddr, PAYLOAD_LEN / 2, PAYLOAD_LEN);
830*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
831*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "ack") == 0) {
832*053f45beSAndroid Build Coastguard Worker send_ack(txfd, &daddr);
833*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
834*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "flags") == 0) {
835*053f45beSAndroid Build Coastguard Worker send_flags(txfd, &daddr, 1, 0, 0, 0);
836*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
837*053f45beSAndroid Build Coastguard Worker
838*053f45beSAndroid Build Coastguard Worker send_flags(txfd, &daddr, 0, 1, 0, 0);
839*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
840*053f45beSAndroid Build Coastguard Worker
841*053f45beSAndroid Build Coastguard Worker send_flags(txfd, &daddr, 0, 0, 1, 0);
842*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
843*053f45beSAndroid Build Coastguard Worker
844*053f45beSAndroid Build Coastguard Worker send_flags(txfd, &daddr, 0, 0, 0, 1);
845*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
846*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "tcp") == 0) {
847*053f45beSAndroid Build Coastguard Worker send_changed_checksum(txfd, &daddr);
848*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
849*053f45beSAndroid Build Coastguard Worker
850*053f45beSAndroid Build Coastguard Worker send_changed_seq(txfd, &daddr);
851*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
852*053f45beSAndroid Build Coastguard Worker
853*053f45beSAndroid Build Coastguard Worker send_changed_ts(txfd, &daddr);
854*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
855*053f45beSAndroid Build Coastguard Worker
856*053f45beSAndroid Build Coastguard Worker send_diff_opt(txfd, &daddr);
857*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
858*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "ip") == 0) {
859*053f45beSAndroid Build Coastguard Worker send_changed_ECN(txfd, &daddr);
860*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
861*053f45beSAndroid Build Coastguard Worker
862*053f45beSAndroid Build Coastguard Worker send_changed_tos(txfd, &daddr);
863*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
864*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
865*053f45beSAndroid Build Coastguard Worker /* Modified packets may be received out of order.
866*053f45beSAndroid Build Coastguard Worker * Sleep function added to enforce test boundaries
867*053f45beSAndroid Build Coastguard Worker * so that fin pkts are not received prior to other pkts.
868*053f45beSAndroid Build Coastguard Worker */
869*053f45beSAndroid Build Coastguard Worker sleep(1);
870*053f45beSAndroid Build Coastguard Worker send_changed_ttl(txfd, &daddr);
871*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
872*053f45beSAndroid Build Coastguard Worker
873*053f45beSAndroid Build Coastguard Worker sleep(1);
874*053f45beSAndroid Build Coastguard Worker send_ip_options(txfd, &daddr);
875*053f45beSAndroid Build Coastguard Worker sleep(1);
876*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
877*053f45beSAndroid Build Coastguard Worker
878*053f45beSAndroid Build Coastguard Worker sleep(1);
879*053f45beSAndroid Build Coastguard Worker send_fragment4(txfd, &daddr);
880*053f45beSAndroid Build Coastguard Worker sleep(1);
881*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
882*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET6) {
883*053f45beSAndroid Build Coastguard Worker send_fragment6(txfd, &daddr);
884*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
885*053f45beSAndroid Build Coastguard Worker }
886*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "large") == 0) {
887*053f45beSAndroid Build Coastguard Worker /* 20 is the difference between min iphdr size
888*053f45beSAndroid Build Coastguard Worker * and min ipv6hdr size. Like MAX_HDR_SIZE,
889*053f45beSAndroid Build Coastguard Worker * MAX_PAYLOAD is defined with the larger header of the two.
890*053f45beSAndroid Build Coastguard Worker */
891*053f45beSAndroid Build Coastguard Worker int offset = proto == PF_INET ? 20 : 0;
892*053f45beSAndroid Build Coastguard Worker int remainder = (MAX_PAYLOAD + offset) % MSS;
893*053f45beSAndroid Build Coastguard Worker
894*053f45beSAndroid Build Coastguard Worker send_large(txfd, &daddr, remainder);
895*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
896*053f45beSAndroid Build Coastguard Worker
897*053f45beSAndroid Build Coastguard Worker send_large(txfd, &daddr, remainder + 1);
898*053f45beSAndroid Build Coastguard Worker write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
899*053f45beSAndroid Build Coastguard Worker } else {
900*053f45beSAndroid Build Coastguard Worker error(1, 0, "Unknown testcase");
901*053f45beSAndroid Build Coastguard Worker }
902*053f45beSAndroid Build Coastguard Worker
903*053f45beSAndroid Build Coastguard Worker if (close(txfd))
904*053f45beSAndroid Build Coastguard Worker error(1, errno, "socket close");
905*053f45beSAndroid Build Coastguard Worker }
906*053f45beSAndroid Build Coastguard Worker
gro_receiver(void)907*053f45beSAndroid Build Coastguard Worker static void gro_receiver(void)
908*053f45beSAndroid Build Coastguard Worker {
909*053f45beSAndroid Build Coastguard Worker static int correct_payload[NUM_PACKETS];
910*053f45beSAndroid Build Coastguard Worker int rxfd = -1;
911*053f45beSAndroid Build Coastguard Worker
912*053f45beSAndroid Build Coastguard Worker rxfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_NONE));
913*053f45beSAndroid Build Coastguard Worker if (rxfd < 0)
914*053f45beSAndroid Build Coastguard Worker error(1, 0, "socket creation");
915*053f45beSAndroid Build Coastguard Worker setup_sock_filter(rxfd);
916*053f45beSAndroid Build Coastguard Worker set_timeout(rxfd);
917*053f45beSAndroid Build Coastguard Worker bind_packetsocket(rxfd);
918*053f45beSAndroid Build Coastguard Worker
919*053f45beSAndroid Build Coastguard Worker memset(correct_payload, 0, sizeof(correct_payload));
920*053f45beSAndroid Build Coastguard Worker
921*053f45beSAndroid Build Coastguard Worker if (strcmp(testname, "data") == 0) {
922*053f45beSAndroid Build Coastguard Worker printf("pure data packet of same size: ");
923*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 2;
924*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 1);
925*053f45beSAndroid Build Coastguard Worker
926*053f45beSAndroid Build Coastguard Worker printf("large data packets followed by a smaller one: ");
927*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 1.5;
928*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 1);
929*053f45beSAndroid Build Coastguard Worker
930*053f45beSAndroid Build Coastguard Worker printf("small data packets followed by a larger one: ");
931*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN / 2;
932*053f45beSAndroid Build Coastguard Worker correct_payload[1] = PAYLOAD_LEN;
933*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
934*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "ack") == 0) {
935*053f45beSAndroid Build Coastguard Worker printf("duplicate ack and pure ack: ");
936*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
937*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "flags") == 0) {
938*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 3;
939*053f45beSAndroid Build Coastguard Worker correct_payload[1] = PAYLOAD_LEN * 2;
940*053f45beSAndroid Build Coastguard Worker
941*053f45beSAndroid Build Coastguard Worker printf("psh flag ends coalescing: ");
942*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
943*053f45beSAndroid Build Coastguard Worker
944*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 2;
945*053f45beSAndroid Build Coastguard Worker correct_payload[1] = 0;
946*053f45beSAndroid Build Coastguard Worker correct_payload[2] = PAYLOAD_LEN * 2;
947*053f45beSAndroid Build Coastguard Worker printf("syn flag ends coalescing: ");
948*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
949*053f45beSAndroid Build Coastguard Worker
950*053f45beSAndroid Build Coastguard Worker printf("rst flag ends coalescing: ");
951*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
952*053f45beSAndroid Build Coastguard Worker
953*053f45beSAndroid Build Coastguard Worker printf("urg flag ends coalescing: ");
954*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
955*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "tcp") == 0) {
956*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN;
957*053f45beSAndroid Build Coastguard Worker correct_payload[1] = PAYLOAD_LEN;
958*053f45beSAndroid Build Coastguard Worker correct_payload[2] = PAYLOAD_LEN;
959*053f45beSAndroid Build Coastguard Worker correct_payload[3] = PAYLOAD_LEN;
960*053f45beSAndroid Build Coastguard Worker
961*053f45beSAndroid Build Coastguard Worker printf("changed checksum does not coalesce: ");
962*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
963*053f45beSAndroid Build Coastguard Worker
964*053f45beSAndroid Build Coastguard Worker printf("Wrong Seq number doesn't coalesce: ");
965*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
966*053f45beSAndroid Build Coastguard Worker
967*053f45beSAndroid Build Coastguard Worker printf("Different timestamp doesn't coalesce: ");
968*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 2;
969*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 4);
970*053f45beSAndroid Build Coastguard Worker
971*053f45beSAndroid Build Coastguard Worker printf("Different options doesn't coalesce: ");
972*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 2;
973*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
974*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "ip") == 0) {
975*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN;
976*053f45beSAndroid Build Coastguard Worker correct_payload[1] = PAYLOAD_LEN;
977*053f45beSAndroid Build Coastguard Worker
978*053f45beSAndroid Build Coastguard Worker printf("different ECN doesn't coalesce: ");
979*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
980*053f45beSAndroid Build Coastguard Worker
981*053f45beSAndroid Build Coastguard Worker printf("different tos doesn't coalesce: ");
982*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
983*053f45beSAndroid Build Coastguard Worker
984*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
985*053f45beSAndroid Build Coastguard Worker printf("different ttl doesn't coalesce: ");
986*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
987*053f45beSAndroid Build Coastguard Worker
988*053f45beSAndroid Build Coastguard Worker printf("ip options doesn't coalesce: ");
989*053f45beSAndroid Build Coastguard Worker correct_payload[2] = PAYLOAD_LEN;
990*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
991*053f45beSAndroid Build Coastguard Worker
992*053f45beSAndroid Build Coastguard Worker printf("fragmented ip4 doesn't coalesce: ");
993*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
994*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET6) {
995*053f45beSAndroid Build Coastguard Worker /* GRO doesn't check for ipv6 hop limit when flushing.
996*053f45beSAndroid Build Coastguard Worker * Hence no corresponding test to the ipv4 case.
997*053f45beSAndroid Build Coastguard Worker */
998*053f45beSAndroid Build Coastguard Worker printf("fragmented ip6 doesn't coalesce: ");
999*053f45beSAndroid Build Coastguard Worker correct_payload[0] = PAYLOAD_LEN * 2;
1000*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
1001*053f45beSAndroid Build Coastguard Worker }
1002*053f45beSAndroid Build Coastguard Worker } else if (strcmp(testname, "large") == 0) {
1003*053f45beSAndroid Build Coastguard Worker int offset = proto == PF_INET ? 20 : 0;
1004*053f45beSAndroid Build Coastguard Worker int remainder = (MAX_PAYLOAD + offset) % MSS;
1005*053f45beSAndroid Build Coastguard Worker
1006*053f45beSAndroid Build Coastguard Worker correct_payload[0] = (MAX_PAYLOAD + offset);
1007*053f45beSAndroid Build Coastguard Worker correct_payload[1] = remainder;
1008*053f45beSAndroid Build Coastguard Worker printf("Shouldn't coalesce if exceed IP max pkt size: ");
1009*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 2);
1010*053f45beSAndroid Build Coastguard Worker
1011*053f45beSAndroid Build Coastguard Worker /* last segment sent individually, doesn't start new segment */
1012*053f45beSAndroid Build Coastguard Worker correct_payload[0] = correct_payload[0] - remainder;
1013*053f45beSAndroid Build Coastguard Worker correct_payload[1] = remainder + 1;
1014*053f45beSAndroid Build Coastguard Worker correct_payload[2] = remainder + 1;
1015*053f45beSAndroid Build Coastguard Worker check_recv_pkts(rxfd, correct_payload, 3);
1016*053f45beSAndroid Build Coastguard Worker } else {
1017*053f45beSAndroid Build Coastguard Worker error(1, 0, "Test case error, should never trigger");
1018*053f45beSAndroid Build Coastguard Worker }
1019*053f45beSAndroid Build Coastguard Worker
1020*053f45beSAndroid Build Coastguard Worker if (close(rxfd))
1021*053f45beSAndroid Build Coastguard Worker error(1, 0, "socket close");
1022*053f45beSAndroid Build Coastguard Worker }
1023*053f45beSAndroid Build Coastguard Worker
parse_args(int argc,char ** argv)1024*053f45beSAndroid Build Coastguard Worker static void parse_args(int argc, char **argv)
1025*053f45beSAndroid Build Coastguard Worker {
1026*053f45beSAndroid Build Coastguard Worker static const struct option opts[] = {
1027*053f45beSAndroid Build Coastguard Worker { "daddr", required_argument, NULL, 'd' },
1028*053f45beSAndroid Build Coastguard Worker { "dmac", required_argument, NULL, 'D' },
1029*053f45beSAndroid Build Coastguard Worker { "iface", required_argument, NULL, 'i' },
1030*053f45beSAndroid Build Coastguard Worker { "ipv4", no_argument, NULL, '4' },
1031*053f45beSAndroid Build Coastguard Worker { "ipv6", no_argument, NULL, '6' },
1032*053f45beSAndroid Build Coastguard Worker { "rx", no_argument, NULL, 'r' },
1033*053f45beSAndroid Build Coastguard Worker { "saddr", required_argument, NULL, 's' },
1034*053f45beSAndroid Build Coastguard Worker { "smac", required_argument, NULL, 'S' },
1035*053f45beSAndroid Build Coastguard Worker { "test", required_argument, NULL, 't' },
1036*053f45beSAndroid Build Coastguard Worker { "verbose", no_argument, NULL, 'v' },
1037*053f45beSAndroid Build Coastguard Worker { 0, 0, 0, 0 }
1038*053f45beSAndroid Build Coastguard Worker };
1039*053f45beSAndroid Build Coastguard Worker int c;
1040*053f45beSAndroid Build Coastguard Worker
1041*053f45beSAndroid Build Coastguard Worker while ((c = getopt_long(argc, argv, "46d:D:i:rs:S:t:v", opts, NULL)) != -1) {
1042*053f45beSAndroid Build Coastguard Worker switch (c) {
1043*053f45beSAndroid Build Coastguard Worker case '4':
1044*053f45beSAndroid Build Coastguard Worker proto = PF_INET;
1045*053f45beSAndroid Build Coastguard Worker ethhdr_proto = htons(ETH_P_IP);
1046*053f45beSAndroid Build Coastguard Worker break;
1047*053f45beSAndroid Build Coastguard Worker case '6':
1048*053f45beSAndroid Build Coastguard Worker proto = PF_INET6;
1049*053f45beSAndroid Build Coastguard Worker ethhdr_proto = htons(ETH_P_IPV6);
1050*053f45beSAndroid Build Coastguard Worker break;
1051*053f45beSAndroid Build Coastguard Worker case 'd':
1052*053f45beSAndroid Build Coastguard Worker addr4_dst = addr6_dst = optarg;
1053*053f45beSAndroid Build Coastguard Worker break;
1054*053f45beSAndroid Build Coastguard Worker case 'D':
1055*053f45beSAndroid Build Coastguard Worker dmac = optarg;
1056*053f45beSAndroid Build Coastguard Worker break;
1057*053f45beSAndroid Build Coastguard Worker case 'i':
1058*053f45beSAndroid Build Coastguard Worker ifname = optarg;
1059*053f45beSAndroid Build Coastguard Worker break;
1060*053f45beSAndroid Build Coastguard Worker case 'r':
1061*053f45beSAndroid Build Coastguard Worker tx_socket = false;
1062*053f45beSAndroid Build Coastguard Worker break;
1063*053f45beSAndroid Build Coastguard Worker case 's':
1064*053f45beSAndroid Build Coastguard Worker addr4_src = addr6_src = optarg;
1065*053f45beSAndroid Build Coastguard Worker break;
1066*053f45beSAndroid Build Coastguard Worker case 'S':
1067*053f45beSAndroid Build Coastguard Worker smac = optarg;
1068*053f45beSAndroid Build Coastguard Worker break;
1069*053f45beSAndroid Build Coastguard Worker case 't':
1070*053f45beSAndroid Build Coastguard Worker testname = optarg;
1071*053f45beSAndroid Build Coastguard Worker break;
1072*053f45beSAndroid Build Coastguard Worker case 'v':
1073*053f45beSAndroid Build Coastguard Worker verbose = true;
1074*053f45beSAndroid Build Coastguard Worker break;
1075*053f45beSAndroid Build Coastguard Worker default:
1076*053f45beSAndroid Build Coastguard Worker error(1, 0, "%s invalid option %c\n", __func__, c);
1077*053f45beSAndroid Build Coastguard Worker break;
1078*053f45beSAndroid Build Coastguard Worker }
1079*053f45beSAndroid Build Coastguard Worker }
1080*053f45beSAndroid Build Coastguard Worker }
1081*053f45beSAndroid Build Coastguard Worker
main(int argc,char ** argv)1082*053f45beSAndroid Build Coastguard Worker int main(int argc, char **argv)
1083*053f45beSAndroid Build Coastguard Worker {
1084*053f45beSAndroid Build Coastguard Worker parse_args(argc, argv);
1085*053f45beSAndroid Build Coastguard Worker
1086*053f45beSAndroid Build Coastguard Worker if (proto == PF_INET) {
1087*053f45beSAndroid Build Coastguard Worker tcp_offset = ETH_HLEN + sizeof(struct iphdr);
1088*053f45beSAndroid Build Coastguard Worker total_hdr_len = tcp_offset + sizeof(struct tcphdr);
1089*053f45beSAndroid Build Coastguard Worker } else if (proto == PF_INET6) {
1090*053f45beSAndroid Build Coastguard Worker tcp_offset = ETH_HLEN + sizeof(struct ipv6hdr);
1091*053f45beSAndroid Build Coastguard Worker total_hdr_len = MAX_HDR_LEN;
1092*053f45beSAndroid Build Coastguard Worker } else {
1093*053f45beSAndroid Build Coastguard Worker error(1, 0, "Protocol family is not ipv4 or ipv6");
1094*053f45beSAndroid Build Coastguard Worker }
1095*053f45beSAndroid Build Coastguard Worker
1096*053f45beSAndroid Build Coastguard Worker read_MAC(src_mac, smac);
1097*053f45beSAndroid Build Coastguard Worker read_MAC(dst_mac, dmac);
1098*053f45beSAndroid Build Coastguard Worker
1099*053f45beSAndroid Build Coastguard Worker if (tx_socket)
1100*053f45beSAndroid Build Coastguard Worker gro_sender();
1101*053f45beSAndroid Build Coastguard Worker else
1102*053f45beSAndroid Build Coastguard Worker gro_receiver();
1103*053f45beSAndroid Build Coastguard Worker
1104*053f45beSAndroid Build Coastguard Worker fprintf(stderr, "Gro::%s test passed.\n", testname);
1105*053f45beSAndroid Build Coastguard Worker return 0;
1106*053f45beSAndroid Build Coastguard Worker }
1107