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