6c68299d7f4b8bb7f1082a25d97c359f04cc3502
[vpp.git] / test / test_gro.py
1 #!/usr/bin/env python3
2 """GRO functional tests"""
3
4 #
5 # Add tests for:
6 # - GRO
7 # - Verify that sending 1500 Bytes frame without GRO enabled correctly
8 # - Verify that sending 1500 Bytes frame with GRO enabled correctly
9 #
10 import unittest
11
12 from scapy.packet import Raw
13 from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig
14 from scapy.layers.inet6 import ipv6nh, IPerror6
15 from scapy.layers.inet import TCP, ICMP
16 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
17
18 from framework import VppTestCase, VppTestRunner
19 from vpp_object import VppObject
20 from vpp_interface import VppInterface
21
22
23 """ Test_gro is a subclass of VPPTestCase classes.
24     GRO tests.
25 """
26
27
28 class TestGRO(VppTestCase):
29     """ GRO Test Case """
30
31     @classmethod
32     def setUpClass(self):
33         super(TestGRO, self).setUpClass()
34         res = self.create_pg_interfaces(range(2))
35         res_gro = self.create_pg_interfaces(range(2, 3), 1, 1460)
36         self.create_pg_interfaces(range(3, 4), 1, 8940)
37         self.pg_interfaces.append(res[0])
38         self.pg_interfaces.append(res[1])
39         self.pg_interfaces.append(res_gro[0])
40         self.pg2.coalesce_enable()
41         self.pg3.coalesce_enable()
42
43     @classmethod
44     def tearDownClass(self):
45         super(TestGRO, self).tearDownClass()
46
47     def setUp(self):
48         super(TestGRO, self).setUp()
49         for i in self.pg_interfaces:
50             i.admin_up()
51             i.config_ip4()
52             i.config_ip6()
53             i.disable_ipv6_ra()
54             i.resolve_arp()
55             i.resolve_ndp()
56
57     def tearDown(self):
58         super(TestGRO, self).tearDown()
59         if not self.vpp_dead:
60             for i in self.pg_interfaces:
61                 i.unconfig_ip4()
62                 i.unconfig_ip6()
63                 i.admin_down()
64
65     def test_gro(self):
66         """ GRO test """
67
68         n_packets = 124
69         #
70         # Send 1500 bytes frame with gro disabled
71         #
72         p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
73               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
74                  flags='DF') /
75               TCP(sport=1234, dport=4321) /
76               Raw(b'\xa5' * 1460))
77
78         rxs = self.send_and_expect(self.pg0, n_packets * p4, self.pg1)
79         for rx in rxs:
80             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
81             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
82             self.assertEqual(rx[IP].src, self.pg0.remote_ip4)
83             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
84             self.assertEqual(rx[TCP].sport, 1234)
85             self.assertEqual(rx[TCP].dport, 4321)
86
87         #
88         # Send 1500 bytes frame with gro enabled on
89         # output interfaces support GRO
90         #
91         p = []
92         s = 0
93         for n in range(0, n_packets):
94             p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
95                       IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4,
96                          flags='DF') /
97                       TCP(sport=1234, dport=4321, seq=s, ack=n, flags='A') /
98                       Raw(b'\xa5' * 1460)))
99             s += 1460
100
101         rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2)
102
103         i = 0
104         for rx in rxs:
105             i += 1
106             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
107             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
108             self.assertEqual(rx[IP].src, self.pg0.remote_ip4)
109             self.assertEqual(rx[IP].dst, self.pg2.remote_ip4)
110             self.assertEqual(rx[IP].len, 64280)  # 1460 * 44 + 40 < 65536
111             self.assertEqual(rx[TCP].sport, 1234)
112             self.assertEqual(rx[TCP].dport, 4321)
113             self.assertEqual(rx[TCP].ack, (44*i - 1))
114
115         p4_temp = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
116                    IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
117                       flags='DF') /
118                    TCP(sport=1234, dport=4321, flags='F'))
119
120         rxs = self.send_and_expect(self.pg2, 100*[p4_temp], self.pg0, n_rx=100)
121         rx_coalesce = self.pg2.get_capture(1, timeout=1)
122
123         rx0 = rx_coalesce[0]
124         self.assertEqual(rx0[Ether].src, self.pg2.local_mac)
125         self.assertEqual(rx0[Ether].dst, self.pg2.remote_mac)
126         self.assertEqual(rx0[IP].src, self.pg0.remote_ip4)
127         self.assertEqual(rx0[IP].dst, self.pg2.remote_ip4)
128         self.assertEqual(rx0[IP].len, 52600)  # 1460 * 36 + 40
129         self.assertEqual(rx0[TCP].sport, 1234)
130         self.assertEqual(rx0[TCP].dport, 4321)
131
132         for rx in rxs:
133             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
134             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
135             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
136             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
137             self.assertEqual(rx[IP].len, 40)
138             self.assertEqual(rx[TCP].sport, 1234)
139             self.assertEqual(rx[TCP].dport, 4321)
140
141         #
142         # Same test with IPv6
143         #
144         p = []
145         s = 0
146         for n in range(0, 88):
147             p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
148                       IPv6(src=self.pg0.remote_ip6, dst=self.pg2.remote_ip6) /
149                       TCP(sport=1234, dport=4321, seq=s, ack=n, flags='A') /
150                       Raw(b'\xa5' * 1460)))
151             s += 1460
152         p[-1][TCP].flags = 'AP'  # push to flush second packet
153
154         rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2)
155
156         i = 0
157         for rx in rxs:
158             i += 1
159             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
160             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
161             self.assertEqual(rx[IPv6].src, self.pg0.remote_ip6)
162             self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
163             self.assertEqual(rx[IPv6].plen, 64260)  # 1460 * 44 + 20 < 65536
164             self.assertEqual(rx[TCP].sport, 1234)
165             self.assertEqual(rx[TCP].dport, 4321)
166             self.assertEqual(rx[TCP].ack, (44*i - 1))
167
168         #
169         # Send a series of 1500 bytes packets each followed by a packet with a
170         # PSH flag. Verify that GRO stops everytime a PSH flag is encountered
171         #
172         p = []
173         s = 0
174         for n in range(0, n_packets):
175             p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
176                       IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4,
177                          flags='DF') /
178                       TCP(sport=1234, dport=4321, seq=s, ack=2*n, flags='A') /
179                       Raw(b'\xa5' * 1460)))
180             s += 1460
181             p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
182                       IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4,
183                          flags='DF') /
184                       TCP(sport=1234, dport=4321, seq=s, ack=2*n+1,
185                           flags='AP') /
186                       Raw(b'\xa5' * 1340)))
187             s += 1340
188
189         rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=n_packets)
190
191         i = 0
192         for rx in rxs:
193             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
194             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
195             self.assertEqual(rx[IP].src, self.pg0.remote_ip4)
196             self.assertEqual(rx[IP].dst, self.pg2.remote_ip4)
197             self.assertEqual(rx[IP].len, 40 + 1460 + 1340)
198             self.assertEqual(rx[TCP].sport, 1234)
199             self.assertEqual(rx[TCP].dport, 4321)
200             self.assertEqual(rx[TCP].ack, (2*i + 1))
201             i += 1
202
203         #
204         # Send a series of 1500 bytes packets each followed by a short packet
205         # with padding. Verify that GRO removes the padding and stops on short
206         # packets
207         #
208         p = []
209         s = 0
210         for n in range(0, n_packets):
211             i = self.pg0
212             p.append((Ether(src=i.remote_mac, dst=i.local_mac) /
213                       IP(src=i.remote_ip4, dst=self.pg2.remote_ip4,
214                          flags='DF') /
215                       TCP(sport=1234, dport=4321, seq=s, ack=2*n, flags='A') /
216                       Raw(b'\xa5' * 1459)))
217             s += 1459
218             p2 = (Ether(src=i.remote_mac, dst=i.local_mac) /
219                   IP(src=i.remote_ip4, dst=self.pg2.remote_ip4,
220                      flags='DF', len=41) /
221                   TCP(sport=1234, dport=4321, seq=s, ack=2*n+1, flags='A') /
222                   Raw(b'\xa5'))
223             # first compute csum of pkt w/o padding to work around scapy bug
224             p2 = Ether(bytes(p2))
225             p.append(p2 / Raw(b'\xa5' * 5))  # 1 byte data + 5 bytes padding
226             s += 1
227
228         rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=n_packets)
229
230         i = 0
231         for rx in rxs:
232             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
233             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
234             self.assertEqual(rx[IP].src, self.pg0.remote_ip4)
235             self.assertEqual(rx[IP].dst, self.pg2.remote_ip4)
236             self.assertEqual(rx[IP].len, 40 + 1459 + 1)
237             self.assertEqual(rx[TCP].sport, 1234)
238             self.assertEqual(rx[TCP].dport, 4321)
239             self.assertEqual(rx[TCP].ack, (2*i + 1))
240             i += 1
241
242
243 if __name__ == '__main__':
244     unittest.main(testRunner=VppTestRunner)