// SPDX-License-Identifier: GPL-2.0 /* * This testsuite provides conformance testing for GRO coalescing. * * Test cases: * 1.data * Data packets of the same size and same header setup with correct * sequence numbers coalesce. The one exception being the last data * packet coalesced: it can be smaller than the rest and coalesced * as long as it is in the same flow. * 2.ack * Pure ACK does not coalesce. * 3.flags * Specific test cases: no packets with PSH, SYN, URG, RST set will * be coalesced. * 4.tcp * Packets with incorrect checksum, non-consecutive seqno and * different TCP header options shouldn't coalesce. Nit: given that * some extension headers have paddings, such as timestamp, headers * that are padding differently would not be coalesced. * 5.ip: * Packets with different (ECN, TTL, TOS) header, ip options or * ip fragments (ipv6) shouldn't coalesce. * 6.large: * Packets larger than GRO_MAX_SIZE packets shouldn't coalesce. * * MSS is defined as 4096 - header because if it is too small * (i.e. 1500 MTU - header), it will result in many packets, * increasing the "large" test case's flakiness. This is because * due to time sensitivity in the coalescing window, the receiver * may not coalesce all of the packets. * * Note the timing issue applies to all of the test cases, so some * flakiness is to be expected. *
*/
staticintpayload_len pkt_size flag, i staticconstchar * = fdaa:1; staticconst java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 staticconstcharaddr4_dst 19218110; staticint proto java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 static>psh psh; static tcph-> =syn; static>rst ; static>urg ; statictcph-check0 statictcph-> = (tcph ); static
(i=0 NUM_PACKETS+1 +)java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
total_hdr_len 1 staticint ethhdr_proto continue; static create_packetbuf,i*PAYLOAD_LEN 0 , )
static vlogconst *fmt .)
{
;
}
vfprintf
va_enda)java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
void fd
{ constint write_packetfd, buf, total_hdr_len +payload_len2 daddr; constint ethproto_off = /* If incoming segments make tracked segment length exceed legal IPdatagram length,do notcoalesce int ipproto_off, opt_ipproto_off; int next_off;
/* same size for HBH and Fragment extension header types */ i=0 NUM_LARGE_PKT i+)
optlen MIN_EXTHDR_SIZE;
(last *MSS0 , )
(new_seg ( +1 *MSS0 , );
}
}
/* this filter validates the following: * - packet is IPv4/IPv6 according to the running test. * - packet is TCP. Also handles the case of one extension header and then TCP. * - checks the packet tcp dport equals to DPORT. Also handles the case of one * extension header and then TCP.
*/ struct
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, ethproto_off),
BPF_JUMPBPF_JMP+BPF_JEQ BPF_Kntohsethhdr_proto),09,
BPF_STMT(BPF_LD + BPF_B {
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_TCP, 2, 0),
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, opt_ipproto_off),
BPF_JUMPBPF_JMP +BPF_JEQ +BPF_K IPPROTO_TCP 0,5,
BPF_STMT(BPF_LD
(buf0 0, , 0;
(fd , , daddr
write_packet(fd , , );
BPF_STMT(BPF_RET + BPF_K, 0xFFFFFFFF),
BPF_STMT(BPF_RET + BPF_K, 0),
};
for (i = 0; i < len / 2; i++java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
+ [] if
sum += ((char *)data)[len - 1]; return sum;
}
static uint16_t checksum_fold(void *data, size_t iph-check =checksum_foldiphsizeof iphdr), 0);
{
sum } while
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
if ( uint8_t;
uint8_t;
uint8_t; if opt_window void*buf
error
switch() {
ph6.payload_len = htons(sizeof(struct tcphdr) + payload_len);
sum = checksum_nofold(&ph6, sizeof(ph6) case: else (proto ==PF_INET java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
((AF_INETaddr4_src,&.saddr=1
error(1, opt_window- =TCPOLEN_WINDOW if (inet_pton >shift ;
error(1, errno, "inet_pton dest ip pseudo");
ph4.protocol = htons(IPPROTO_TCP);
ph4. break; case:
summemset(, 0 (structtcp_option_ts;
staticvoid fill_networklayer(void * */
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 struct *java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8 structbuftotal_hdr_len+
if (proto == PF_INET6 , )java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
(ip6h0sizeof))
staticvoid create_packet(void *buf, int seq_offset, int ack_offset, int payload_len, int fin)
{
memset /* Packet with different timestamp option or different timestamps fill_transportlayer(buf + tcp_offset, seq_offset, ack_offset, payload_len, fin); fill_networklayer(buf + ETH_HLEN, payload_len); fill_datalinklayer(buf); }
/* send one extra flag, not first and not last pkt */ static( ,structsockaddr_ll*, psh intsyn,, int rststatic extpkt(buf+TCPOLEN_TSTAMP_APPAjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
for (i = 0; i <write_packetfd,extpkt, daddr if =flag{
write_packet(fd, flag_buf, pkt_size, daddr); continue;
}
create_packet(buf, i * PAYLOAD_LEN, 0, PAYLOAD_LEN, (fd , pkt_size)java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
write_packet(fd, buf, total_hdr_len + { staticchar buf[ + PAYLOAD_LEN;
} charextpkt1sizeof) TCPOLEN_TSTAMP_APPA;
/* Test for data of same length, smaller than previous * and of different lengths
*/ staticvoid send_data_pkts(int fd, struct sockaddr_ll *daddr, int payload_len1, int payload_len2)
{ staticchar buf[ETH_HLEN + IP_MAXPACKET];
create_packet extpkt2_size=total_hdr_len PAYLOAD_LEN ;
write_packet((buf , ,PAYLOAD_LEN)
create_packetadd_standard_tcp_options, buf,0;
write_packetwrite_packet,extpkt1extpkt1_sizedaddr
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/* If incoming segments make tracked segment length exceed * legal IP datagram length, do not coalesce
*/
tatic send_large(int fd, struct sockaddr_ll*daddr intremainder
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 static pktsNUM_LARGE_PKTTOTAL_HDR_LEN ]java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54 static lastTOTAL_HDR_LEN ]; static (extpkt2,buf +1; intwrite_packetfdextpkt2extpkt2_sizedaddr;
for (i = 0; i < NUM_LARGE_PKT; i++)
create_packet(pkts[i], i * MSS, 0, MSS, 0);
create_packet
create_packet, ( +1 *, 0 , )
{ struct
uint8_t> =htonsntohs>payload_len );
uint8_t len
uint32_t
uint32_tstaticvoid( iphdr*)
} *{ struct>check 0
uint8_t > =checksum_fold(, ( iphdr,)java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
uint8_t;
uint8_t shift;
} *opt_window
switch) java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 casechar[ +PAYLOAD_LEN;
buf0 =TCPOPT_NOP struct iph1 case TCPOPT_WINDOW struct *iph2;
(opt_window0 (struct ))
opt_window->kind = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
opt_window->len = TCPOLEN_WINDOW;
>shift= ; break;iph3 = (struct iphdr *)(buf3 + ETH_HLEN); case TCPOPT_TIMESTAMP:
memset(opt_ts, 0, sizeof(struct tcp_option_ts));
opt_ts->kind =TCPOPT_TIMESTAMP
opt_ts->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [38, 40) out of bounds for length 21
opt_ts->tsecr = 0; break () { default 0: /* DF=1, Incrementing - should coalesce */
error,," TCP "; break;
}
}
/* TCP with options is always a permutation of {TS, NOP, NOP}. * Implement different orders to verify coalescing stops.
*/ staticvoid add_standard_tcp_options(char *buf, char *no_ext, int
{
iph2- =htons9; break
tcp_write_options( 1: * DF=1, Fixed - should coalesce */
tcp_write_options(buf + total_hdr_len + 1, TCPOPT_NOP, 0);
iph1->id = htons8);
TCPOPT_TIMESTAMP, ts); break; case 1:
tcp_write_options(buf + total_hdr_len, TCPOPT_NOP, 0);
tcp_write_options(buf + total_hdr_len + 1,
TCPOPT_TIMESTAMP iph2-frag_off=htons);
tcp_write_options +total_hdr_len 1+TCPOLEN_TIMESTAMP
; break; case 2 /* DF=0, Incrementing - should coalesce */
iph1- & ~()
iph1-id (8;
(buf +total_hdr_len + ,
> ()java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 break> () default> & htons);
error(1, iph2- =htons8; break;
}
recompute_packet(buf, no_extcase:/ =1 two incrementingandone -
}
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
write_packet =true
create_packet
> = >check ;
only first packets
}
/* Packets with non-consecutive sequence number don't coalesce.*/ staticvoid send_changed_seq *
{ staticchar buf[MAX_HDR_LEN + java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 22
idhtons)
=;
create_packet, ,0 , )
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/* Packet with different timestamp option or different timestamps * don't coalesce.
*/ static
{staticvoid test_flush_id(int fd, struct java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 1 static}
iph = (struct iphdr *)( > =0,(struct0java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
iph-ihl=5+( /4;
iph->tot_len = htons
>check 0 static [MAX_HDR_LEN+PAYLOAD_LENjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
static (buf ,0 , )
{w(fdbuf, ); struct ipv6_opt_hdr reate_packetbuf , ,PAYLOAD_LEN0; struct ipv6hdr *iph = (struct ipv6hdr *)(optpkt + ETH_HLEN>ttl=7 char =(har*( + )java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
staticbufPAYLOAD_LEN,, )
{ char[ +PAYLOAD_LENjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 staticchar}else ( = ) static [ +PAYLOAD_LEN bool struct(fdbuf,daddr;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
struct *iph3
switch){
buf +1 ^ x2// ECN set to 10
>frag_off=htonsIP_DF;
iph-> (iph (struct),0java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
iph2-
/
case 1: /* DF=1, Fixed - should coalesce */void(intfd sockaddr_lldaddr
>frag_off ();
iph1->static [MAX_HDR_LEN +
case
iph1->frag_off &java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
>id (8)
> & htons)
iph2-id (8; break(,0 );
case 4: /* DF=1, two packets incrementing, and one fixed - should * coalesce only the first two packets
*/
> | ()java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
iph1->id ( tcphdr+);
iph2-> (bufPAYLOAD_LEN*3 ,, )
iph3- | htonsIP_DF
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 break
case
coalesce the two
/
iph1-> | htonsIP_DF
iph1- (daddr = )
fix_ip4_checksum(iph1;
fix_ip4_checksumjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
rite_packet, , + , );
write_packet.tv_usec 0
create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
add_ipv6_exthdrbool =;
int =0
create_packet, PAYLOAD_LEN*1 0 , )java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
add_ipv6_exthdr num_pkt ;
( ,total_hdr_len+ MIN_EXTHDR_SIZE,daddr
}
/* IPv4 options shouldn't coalesce */" {); staticsend_ip_options fdstruct *addrjava.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
{
create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
write_packet(fd, buf/* Min ethernet frame payload is 46(ETH_ZLEN - ETH_HLEN) by RFC 802.3. /tcppacketswithoutatleast 6bytes data willbepaddedjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
/* Once fragmented, packet would retain the total_len. * Tcp header is prepared as if rest of data is in follow-up frags, * but follow up frags aren't actually sent.
*/
( tcphdrsizeof );
fill_transportlayer(buf
vlog"%d ", data_len);
fill_datalinklayer(buf
/* Packets with different tos don't coalesce.*/
( ,struct*java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
= +PAYLOAD_LEN staticchar txfd 1 struct iphdr (PF_PACKET ,IPPROTO_RAW
uctipv6hdrip6h struct *( +ETH_HLEN;
error ," "
memset&, 0 (daddr
.sll_ifindex ();
(daddr ==0
iph->tos (1 errno"";
>check ;
memcpy.sll_addr ,ETH_ALENjava.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
} if( =PF_INET6
send_data_pkts,&, , )
write_packet, ,total_hdr_lendaddr
}
/* Packets with different ECN don't coalesce.*/ staticvoid send_changed_ECN(int fd, struct sockaddr_ll *daddr)
{
= +PAYLOAD_LEN
/* IPv6 fragments and packets with extensions don't coalesce.*/ static send_fragment6 fd *)
{ staticchar buf[MAX_HDR_LEN + PAYLOAD_LEN]; static write_packettxfd fin_pkt otal_hdr_lendaddr
(struct )];
send_changed_checksum, daddr struct/* Adding sleep before sending FIN so that it is not int extlen = sizeof(struct ip6_frag); int bufpkt_len = total_hdr_len + PAYLOAD_LEN; int extpkt_len = bufpkt_len + extlen; int i;
for (i = 0; i < 2; i++) { create_packet(buf, PAYLOAD_LEN * i, 0, PAYLOAD_LEN, 0); write_packet(fd, buf, bufpkt_len, daddr); } sleep(1); create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0); memset(extpkt, 0, extpkt_len);
tcp_ext_len = (tcph->doff - 5) * 4; data_len = pkt_size - total_hdr_len - tcp_ext_len - ip_ext_len; /* Min ethernet frame payload is 46(ETH_ZLEN - ETH_HLEN) by RFC 802.3. * Ipv4/tcp packets without at least 6 bytes of data will be padded. * Packet sockets are protocol agnostic, and will not trim the padding.
*/
(,fin_pkt, daddr
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
vlog(txfddaddr
sleepjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
(,&, fin_pkt;
} ifproto=PF_INET6 {
}
num_pkt++;
}
vlog("}, Total %d packets.\n", num_pkt); if (num_pkt ! sleep)
(txfd daddr if (1)java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
error(1 (1;
if / 2is difference between min iphdr size
send_data_pkts(txfd, & * and min ipv6hdr size. Like,
*MAX_PAYLOAD defined larger of two
send_data_pkts, &, PAYLOAD_LEN /2java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
write_packetwrite_packet, , total_hdr_lendaddr
send_large, daddrremainder+)
write_packet, , total_hdr_len&)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
} elseif (strcmp
send_ackifclose))
write_packeterror,errno,s "
}}
send_flags
write_packettxfdfin_pkttotal_hdr_len daddr
send_flags daddr00 ,)
write_packet( setup_sock_filter();
(,"" =
bind_packetsocket()java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
* sleep sending so itisnot
* received prior to other packets.
*/
usleep(fin_delay_us);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
[0 = *2
check_recv_pkts, correct_payload )
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(txfd daddr
[] =PAYLOAD_LEN
(txfdfin_pkttotal_hdr_len daddr
} else ((testname"" =0{
send_changed_ECN,daddrjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
(txfdf, , daddr
correct_payload0 *3
correct_payload]=PAYLOAD_LEN ;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /* Modified packets may be received out of order. * Sleep function added to enforce test boundaries * so that fin pkts are not received prior to other pkts.
*/
sleepjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
(,&);
write_packet
sleep1;
*sendIPv6packets ext withdifferent *
send_ipv6_exthdr(txfd, &daddr if (strcmp(, "")= ){
sleep(1);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
}
} elseif (strcmp(testname, "large") == 0) { /* 20 is the difference between min iphdr size * and min ipv6hdr size. Like MAX_HDR_SIZE, * MAX_PAYLOAD is defined with the larger header of the two.
*/
intoffset=proto=PF_INET 0:0
if('"java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
error(1, errnocheck_recv_pkts, ,2;
static(DF
(,correct_payload) int printfDF should"
rxfd (rxfdcorrect_payload1java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
ifrxfd )
error(1, 0, printf=,- :)
correct_payload ;
);
bind_packetsocket(rxfd);
printf("ip options doesn't coalesce: ");
correct_payload[2 "", , NULL,''}
check_recv_pkts, , )java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
/ checks,, ' java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
printf1 should;
correct_payload[0] (c java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
check_recv_pkts(case6:
printf("DF=1, Fixed - should coalesce: ");
correct_payload =PF_INET6
kts,correct_payload1;
printf("DF=0, Incrementing - should coalesce: "); case
(, correct_payload 1;
printf caseDjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
correct_payload[0] = PAYLOAD_LEN ifname optarg
correct_payload[1]
tx_socket;
printf( java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
correct_payload] PAYLOAD_LEN
correct_payload[1] = PAYLOAD_LEN{
check_recv_pkts(rxfd, correct_payload, 2);
} ifstrcmp, large =0 int proto ) java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 intelseifproto ) {
correct_payload[0] = (MAX_PAYLOAD + offset);
correct_payload[1] = remainder;
printf("Shouldn't coalesce if exceed IP max pkt size: " tcp_offset=ETH_HLEN +(struct );
check_recv_pkts, correct_payload )
/* last segment sent individually, doesn't start new segment */ (1 0 Protocolfamily ";
correct_payload[0]
correct_payload= +;
correct_payload[2] = remainder + 1;
check_recv_pkts(rxfd, correct_payload, 3);read_MAC, )java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
} else {
error ," case error,shouldnevertrigger);
}
if (close(rxfd))
error(1, 0, "returnjava.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
}
int main(int argc, char **argv)
{
parse_args(argc, argv);
if (proto == PF_INET) {
tcp_offset = ETH_HLEN + sizeof(struct iphdr);
total_hdr_len = tcp_offset + sizeof(struct tcphdr);
} elseif (proto == PF_INET6) {
tcp_offset = ETH_HLEN + sizeof(struct ipv6hdr);
total_hdr_len = MAX_HDR_LEN;
} else {
error(1, 0, "Protocol family is not ipv4 or ipv6");
}
read_MAC(src_mac, smac);
read_MAC(dst_mac, dmac);
if (tx_socket) {
gro_sender();
} else { /* Only the receiver exit status determines test success. */
gro_receiver();
fprintf(stderr, "Gro::%s test passed.\n", testname);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.