tests: move cli tests to src/vlib/test
[vpp.git] / src / vnet / gso / test / test_gso.py
1 #!/usr/bin/env python3
2 """GSO functional tests"""
3
4 #
5 # Add tests for:
6 # - GSO
7 # - Verify that sending Jumbo frame without GSO enabled correctly
8 # - Verify that sending Jumbo frame with GSO enabled correctly
9 # - Verify that sending Jumbo frame with GSO enabled only on ingress interface
10 #
11 import unittest
12
13 from scapy.packet import Raw
14 from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig
15 from scapy.layers.inet6 import ipv6nh, IPerror6
16 from scapy.layers.inet import TCP, ICMP
17 from scapy.layers.vxlan import VXLAN
18 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
19
20 from framework import VppTestCase, VppTestRunner
21 from vpp_object import VppObject
22 from vpp_interface import VppInterface
23 from vpp_ip import DpoProto
24 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
25 from vpp_ipip_tun_interface import VppIpIpTunInterface
26 from vpp_vxlan_tunnel import VppVxlanTunnel
27 from socket import AF_INET, AF_INET6, inet_pton
28 from util import reassemble4
29
30
31 """ Test_gso is a subclass of VPPTestCase classes.
32     GSO tests.
33 """
34
35
36 class TestGSO(VppTestCase):
37     """ GSO Test Case """
38
39     def __init__(self, *args):
40         VppTestCase.__init__(self, *args)
41
42     @classmethod
43     def setUpClass(self):
44         super(TestGSO, self).setUpClass()
45         res = self.create_pg_interfaces(range(2))
46         res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460)
47         self.create_pg_interfaces(range(4, 5), 1, 8940)
48         self.pg_interfaces.append(res[0])
49         self.pg_interfaces.append(res[1])
50         self.pg_interfaces.append(res_gso[0])
51         self.pg_interfaces.append(res_gso[1])
52
53     @classmethod
54     def tearDownClass(self):
55         super(TestGSO, self).tearDownClass()
56
57     def setUp(self):
58         super(TestGSO, self).setUp()
59         for i in self.pg_interfaces:
60             i.admin_up()
61             i.config_ip4()
62             i.config_ip6()
63             i.disable_ipv6_ra()
64             i.resolve_arp()
65             i.resolve_ndp()
66
67         self.single_tunnel_bd = 10
68         self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4,
69                                     dst=self.pg0.remote_ip4,
70                                     vni=self.single_tunnel_bd)
71
72         self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6,
73                                      dst=self.pg0.remote_ip6,
74                                      vni=self.single_tunnel_bd)
75
76         self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4,
77                                          self.pg0.remote_ip4)
78         self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6,
79                                          self.pg0.remote_ip6)
80
81     def tearDown(self):
82         super(TestGSO, self).tearDown()
83         if not self.vpp_dead:
84             for i in self.pg_interfaces:
85                 i.unconfig_ip4()
86                 i.unconfig_ip6()
87                 i.admin_down()
88
89     def test_gso(self):
90         """ GSO test """
91         #
92         # Send jumbo frame with gso disabled and DF bit is set
93         #
94         p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
95               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
96                  flags='DF') /
97               TCP(sport=1234, dport=1234) /
98               Raw(b'\xa5' * 65200))
99
100         rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
101
102         for rx in rxs:
103             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
104             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
105             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
106             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
107             self.assertEqual(rx[ICMP].type, 3)  # "dest-unreach"
108             self.assertEqual(rx[ICMP].code, 4)  # "fragmentation-needed"
109
110         #
111         # Send checksum offload frames
112         #
113         p40 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
114                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
115                   flags='DF') /
116                TCP(sport=1234, dport=1234) /
117                Raw(b'\xa5' * 1460))
118
119         rxs = self.send_and_expect(self.pg2, 100*[p40], self.pg0)
120
121         for rx in rxs:
122             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
123             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
124             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
125             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
126             payload_len = rx[IP].len - 20 - 20
127             self.assert_ip_checksum_valid(rx)
128             self.assert_tcp_checksum_valid(rx)
129             self.assertEqual(payload_len, len(rx[Raw]))
130
131         p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
132                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
133                TCP(sport=1234, dport=1234) /
134                Raw(b'\xa5' * 1440))
135
136         rxs = self.send_and_expect(self.pg2, 100*[p60], self.pg0)
137
138         for rx in rxs:
139             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
140             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
141             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
142             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
143             payload_len = rx[IPv6].plen - 20
144             self.assert_tcp_checksum_valid(rx)
145             self.assertEqual(payload_len, len(rx[Raw]))
146
147         #
148         # Send jumbo frame with gso enabled and DF bit is set
149         # input and output interfaces support GSO
150         #
151         self.vapi.feature_gso_enable_disable(self.pg3.sw_if_index)
152         p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
153                IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
154                   flags='DF') /
155                TCP(sport=1234, dport=1234) /
156                Raw(b'\xa5' * 65200))
157
158         rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100)
159
160         for rx in rxs:
161             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
162             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
163             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
164             self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
165             self.assertEqual(rx[IP].len, 65240)  # 65200 + 20 (IP) + 20 (TCP)
166             self.assertEqual(rx[TCP].sport, 1234)
167             self.assertEqual(rx[TCP].dport, 1234)
168
169         #
170         # ipv6
171         #
172         p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
173                IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
174                TCP(sport=1234, dport=1234) /
175                Raw(b'\xa5' * 65200))
176
177         rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100)
178
179         for rx in rxs:
180             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
181             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
182             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
183             self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
184             self.assertEqual(rx[IPv6].plen, 65220)  # 65200 + 20 (TCP)
185             self.assertEqual(rx[TCP].sport, 1234)
186             self.assertEqual(rx[TCP].dport, 1234)
187
188         #
189         # Send jumbo frame with gso enabled only on input interface
190         # and DF bit is set. GSO packet will be chunked into gso_size
191         # data payload
192         #
193         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
194         p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
195                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
196                   flags='DF') /
197                TCP(sport=1234, dport=1234) /
198                Raw(b'\xa5' * 65200))
199
200         rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225)
201         size = 0
202         for rx in rxs:
203             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
204             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
205             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
206             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
207             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
208             self.assert_ip_checksum_valid(rx)
209             self.assert_tcp_checksum_valid(rx)
210             self.assertEqual(rx[TCP].sport, 1234)
211             self.assertEqual(rx[TCP].dport, 1234)
212             self.assertEqual(payload_len, len(rx[Raw]))
213             size += payload_len
214         self.assertEqual(size, 65200*5)
215
216         #
217         # ipv6
218         #
219         p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
220                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
221                TCP(sport=1234, dport=1234) /
222                Raw(b'\xa5' * 65200))
223
224         rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225)
225         size = 0
226         for rx in rxs:
227             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
228             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
229             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
230             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
231             payload_len = rx[IPv6].plen - 20
232             self.assert_tcp_checksum_valid(rx)
233             self.assertEqual(rx[TCP].sport, 1234)
234             self.assertEqual(rx[TCP].dport, 1234)
235             self.assertEqual(payload_len, len(rx[Raw]))
236             size += payload_len
237         self.assertEqual(size, 65200*5)
238
239         #
240         # Send jumbo frame with gso enabled only on input interface
241         # and DF bit is unset. GSO packet will be fragmented.
242         #
243         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
244         self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index)
245
246         p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
247                IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
248                TCP(sport=1234, dport=1234) /
249                Raw(b'\xa5' * 65200))
250
251         rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119)
252         size = 0
253         for rx in rxs:
254             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
255             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
256             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
257             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
258             self.assert_ip_checksum_valid(rx)
259             size += rx[IP].len - 20
260         size -= 20*5  # TCP header
261         self.assertEqual(size, 65200*5)
262
263         #
264         # IPv6
265         # Send jumbo frame with gso enabled only on input interface.
266         # ICMPv6 Packet Too Big will be sent back to sender.
267         #
268         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
269         p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
270                IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
271                TCP(sport=1234, dport=1234) /
272                Raw(b'\xa5' * 65200))
273
274         rxs = self.send_and_expect(self.pg2, 5*[p63], self.pg2, 5)
275         for rx in rxs:
276             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
277             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
278             self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
279             self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
280             self.assertEqual(rx[IPv6].plen, 1240)  # MTU - IPv6 header
281             self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
282             self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
283             self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
284             self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
285             self.assertEqual(rx[IPerror6].plen - 20, 65200)
286
287         #
288         # Send jumbo frame with gso enabled only on input interface with 9K MTU
289         # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
290         # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
291         #
292         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
293         self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
294         p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
295                IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
296                TCP(sport=1234, dport=1234) /
297                Raw(b'\xa5' * 65200))
298
299         rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165)
300         size = 0
301         for rx in rxs:
302             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
303             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
304             self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
305             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
306             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
307             self.assert_ip_checksum_valid(rx)
308             self.assert_tcp_checksum_valid(rx)
309             self.assertEqual(payload_len, len(rx[Raw]))
310             size += payload_len
311         self.assertEqual(size, 65200*5)
312
313         #
314         # IPv6
315         #
316         p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
317                IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
318                TCP(sport=1234, dport=1234) /
319                Raw(b'\xa5' * 65200))
320
321         rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170)
322         size = 0
323         for rx in rxs:
324             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
325             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
326             self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
327             self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
328             payload_len = rx[IPv6].plen - 20
329             self.assert_tcp_checksum_valid(rx)
330             self.assertEqual(payload_len, len(rx[Raw]))
331             size += payload_len
332         self.assertEqual(size, 65200*5)
333
334         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
335                                              enable_disable=0)
336         self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index,
337                                              enable_disable=0)
338
339     def test_gso_vxlan(self):
340         """ GSO VXLAN test """
341         self.logger.info(self.vapi.cli("sh int addr"))
342         #
343         # Send jumbo frame with gso enabled only on input interface and
344         # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
345         # into BD.
346         #
347
348         #
349         # enable ipv4/vxlan
350         #
351         self.vxlan.add_vpp_config()
352         self.vapi.sw_interface_set_l2_bridge(
353             rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
354         self.vapi.sw_interface_set_l2_bridge(
355             rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
356         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
357
358         #
359         # IPv4/IPv4 - VXLAN
360         #
361         p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
362                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
363                TCP(sport=1234, dport=1234) /
364                Raw(b'\xa5' * 65200))
365
366         rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225)
367         size = 0
368         for rx in rxs:
369             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
370             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
371             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
372             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
373             self.assert_ip_checksum_valid(rx)
374             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
375             self.assertEqual(rx[VXLAN].vni, 10)
376             inner = rx[VXLAN].payload
377             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
378             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
379             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
380             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
381             self.assertEqual(inner[IP].dst, "172.16.3.3")
382             self.assert_ip_checksum_valid(inner)
383             self.assert_tcp_checksum_valid(inner)
384             payload_len = inner[IP].len - 20 - 20
385             self.assertEqual(payload_len, len(inner[Raw]))
386             size += payload_len
387         self.assertEqual(size, 65200*5)
388
389         #
390         # IPv4/IPv6 - VXLAN
391         #
392         p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
393                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
394                TCP(sport=1234, dport=1234) /
395                Raw(b'\xa5' * 65200))
396
397         rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225)
398         size = 0
399         for rx in rxs:
400             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
401             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
402             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
403             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
404             self.assert_ip_checksum_valid(rx)
405             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
406             self.assertEqual(rx[VXLAN].vni, 10)
407             inner = rx[VXLAN].payload
408             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
409             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
410             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
411             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
412             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
413             self.assert_tcp_checksum_valid(inner)
414             payload_len = inner[IPv6].plen - 20
415             self.assertEqual(payload_len, len(inner[Raw]))
416             size += payload_len
417         self.assertEqual(size, 65200*5)
418
419         #
420         # disable ipv4/vxlan
421         #
422         self.vxlan.remove_vpp_config()
423
424         #
425         # enable ipv6/vxlan
426         #
427         self.vxlan2.add_vpp_config()
428         self.vapi.sw_interface_set_l2_bridge(
429             rx_sw_if_index=self.vxlan2.sw_if_index,
430             bd_id=self.single_tunnel_bd)
431
432         #
433         # IPv6/IPv4 - VXLAN
434         #
435         p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
436                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
437                TCP(sport=1234, dport=1234) /
438                Raw(b'\xa5' * 65200))
439
440         rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225)
441         size = 0
442         for rx in rxs:
443             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
444             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
445             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
446             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
447             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
448             self.assertEqual(rx[VXLAN].vni, 10)
449             inner = rx[VXLAN].payload
450             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
451             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
452             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
453             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
454             self.assertEqual(inner[IP].dst, "172.16.3.3")
455             self.assert_ip_checksum_valid(inner)
456             self.assert_tcp_checksum_valid(inner)
457             payload_len = inner[IP].len - 20 - 20
458             self.assertEqual(payload_len, len(inner[Raw]))
459             size += payload_len
460         self.assertEqual(size, 65200*5)
461
462         #
463         # IPv6/IPv6 - VXLAN
464         #
465         p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
466                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
467                TCP(sport=1234, dport=1234) /
468                Raw(b'\xa5' * 65200))
469
470         rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225)
471         size = 0
472         for rx in rxs:
473             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
474             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
475             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
476             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
477             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
478             self.assertEqual(rx[VXLAN].vni, 10)
479             inner = rx[VXLAN].payload
480             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
481             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
482             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
483             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
484             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
485             self.assert_tcp_checksum_valid(inner)
486             payload_len = inner[IPv6].plen - 20
487             self.assertEqual(payload_len, len(inner[Raw]))
488             size += payload_len
489         self.assertEqual(size, 65200*5)
490
491         #
492         # disable ipv4/vxlan
493         #
494         self.vxlan2.remove_vpp_config()
495
496         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
497                                              enable_disable=0)
498
499     def test_gso_ipip(self):
500         """ GSO IPIP test """
501         self.logger.info(self.vapi.cli("sh int addr"))
502         #
503         # Send jumbo frame with gso enabled only on input interface and
504         # create IPIP tunnel on VPP pg0.
505         #
506         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
507
508         #
509         # enable ipip4
510         #
511         self.ipip4.add_vpp_config()
512
513         # Set interface up and enable IP on it
514         self.ipip4.admin_up()
515         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
516
517         # Add IPv4 routes via tunnel interface
518         self.ip4_via_ip4_tunnel = VppIpRoute(
519                 self, "172.16.10.0", 24,
520                 [VppRoutePath("0.0.0.0",
521                               self.ipip4.sw_if_index,
522                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
523         self.ip4_via_ip4_tunnel.add_vpp_config()
524
525         #
526         # IPv4/IPv4 - IPIP
527         #
528         p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
529                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
530                TCP(sport=1234, dport=1234) /
531                Raw(b'\xa5' * 65200))
532
533         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
534         size = 0
535         for rx in rxs:
536             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
537             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
538             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
539             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
540             self.assert_ip_checksum_valid(rx)
541             self.assertEqual(rx[IP].proto, 4)  # ipencap
542             inner = rx[IP].payload
543             self.assertEqual(rx[IP].len - 20, len(inner))
544             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
545             self.assertEqual(inner[IP].dst, "172.16.10.3")
546             self.assert_ip_checksum_valid(inner)
547             self.assert_tcp_checksum_valid(inner)
548             payload_len = inner[IP].len - 20 - 20
549             self.assertEqual(payload_len, len(inner[Raw]))
550             size += payload_len
551         self.assertEqual(size, 65200*5)
552
553         self.ip6_via_ip4_tunnel = VppIpRoute(
554                 self, "fd01:10::", 64,
555                 [VppRoutePath("::",
556                               self.ipip4.sw_if_index,
557                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
558         self.ip6_via_ip4_tunnel.add_vpp_config()
559         #
560         # IPv4/IPv6 - IPIP
561         #
562         p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
563                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
564                TCP(sport=1234, dport=1234) /
565                Raw(b'\xa5' * 65200))
566
567         rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225)
568         size = 0
569         for rx in rxs:
570             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
571             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
572             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
573             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
574             self.assert_ip_checksum_valid(rx)
575             self.assertEqual(rx[IP].proto, 41)  # ipv6
576             inner = rx[IP].payload
577             self.assertEqual(rx[IP].len - 20, len(inner))
578             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
579             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
580             self.assert_tcp_checksum_valid(inner)
581             payload_len = inner[IPv6].plen - 20
582             self.assertEqual(payload_len, len(inner[Raw]))
583             size += payload_len
584         self.assertEqual(size, 65200*5)
585
586         #
587         # Send jumbo frame with gso enabled only on input interface and
588         # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
589         # tunnel - IPSec use case
590         #
591         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
592                                              enable_disable=0)
593         self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index)
594
595         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
596         size = 0
597         for rx in rxs:
598             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
599             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
600             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
601             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
602             self.assert_ip_checksum_valid(rx)
603             self.assertEqual(rx[IP].proto, 4)  # ipencap
604             inner = rx[IP].payload
605             self.assertEqual(rx[IP].len - 20, len(inner))
606             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
607             self.assertEqual(inner[IP].dst, "172.16.10.3")
608             self.assert_ip_checksum_valid(inner)
609             self.assert_tcp_checksum_valid(inner)
610             payload_len = inner[IP].len - 20 - 20
611             self.assertEqual(payload_len, len(inner[Raw]))
612             size += payload_len
613         self.assertEqual(size, 65200*5)
614
615         #
616         # disable ipip4
617         #
618         self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index,
619                                              enable_disable=0)
620         self.ip4_via_ip4_tunnel.remove_vpp_config()
621         self.ip6_via_ip4_tunnel.remove_vpp_config()
622         self.ipip4.remove_vpp_config()
623
624         #
625         # enable ipip6
626         #
627         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
628         self.ipip6.add_vpp_config()
629
630         # Set interface up and enable IP on it
631         self.ipip6.admin_up()
632         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
633
634         # Add IPv4 routes via tunnel interface
635         self.ip4_via_ip6_tunnel = VppIpRoute(
636                 self, "172.16.10.0", 24,
637                 [VppRoutePath("0.0.0.0",
638                               self.ipip6.sw_if_index,
639                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
640         self.ip4_via_ip6_tunnel.add_vpp_config()
641
642         #
643         # IPv6/IPv4 - IPIP
644         #
645         p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
646                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
647                TCP(sport=1234, dport=1234) /
648                Raw(b'\xa5' * 65200))
649
650         rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225)
651         size = 0
652         for rx in rxs:
653             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
654             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
655             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
656             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
657             self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
658             inner = rx[IPv6].payload
659             self.assertEqual(rx[IPv6].plen, len(inner))
660             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
661             self.assertEqual(inner[IP].dst, "172.16.10.3")
662             self.assert_ip_checksum_valid(inner)
663             self.assert_tcp_checksum_valid(inner)
664             payload_len = inner[IP].len - 20 - 20
665             self.assertEqual(payload_len, len(inner[Raw]))
666             size += payload_len
667         self.assertEqual(size, 65200*5)
668
669         self.ip6_via_ip6_tunnel = VppIpRoute(
670                 self, "fd01:10::", 64,
671                 [VppRoutePath("::",
672                               self.ipip6.sw_if_index,
673                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
674         self.ip6_via_ip6_tunnel.add_vpp_config()
675
676         #
677         # IPv6/IPv6 - IPIP
678         #
679         p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
680                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
681                TCP(sport=1234, dport=1234) /
682                Raw(b'\xa5' * 65200))
683
684         rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225)
685         size = 0
686         for rx in rxs:
687             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
688             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
689             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
690             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
691             self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
692             inner = rx[IPv6].payload
693             self.assertEqual(rx[IPv6].plen, len(inner))
694             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
695             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
696             self.assert_tcp_checksum_valid(inner)
697             payload_len = inner[IPv6].plen - 20
698             self.assertEqual(payload_len, len(inner[Raw]))
699             size += payload_len
700         self.assertEqual(size, 65200*5)
701
702         #
703         # disable ipip6
704         #
705         self.ip4_via_ip6_tunnel.remove_vpp_config()
706         self.ip6_via_ip6_tunnel.remove_vpp_config()
707         self.ipip6.remove_vpp_config()
708
709         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
710                                              enable_disable=0)
711
712 if __name__ == '__main__':
713     unittest.main(testRunner=VppTestRunner)