094600eb74cbb6393fa706b9f9841302e4eb8b8b
[vpp.git] / 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(sw_if_index=self.pg3.sw_if_index,
152                                              enable_disable=1)
153         p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
154                IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
155                   flags='DF') /
156                TCP(sport=1234, dport=1234) /
157                Raw(b'\xa5' * 65200))
158
159         rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100)
160
161         for rx in rxs:
162             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
163             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
164             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
165             self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
166             self.assertEqual(rx[IP].len, 65240)  # 65200 + 20 (IP) + 20 (TCP)
167             self.assertEqual(rx[TCP].sport, 1234)
168             self.assertEqual(rx[TCP].dport, 1234)
169
170         #
171         # ipv6
172         #
173         p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
174                IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
175                TCP(sport=1234, dport=1234) /
176                Raw(b'\xa5' * 65200))
177
178         rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100)
179
180         for rx in rxs:
181             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
182             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
183             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
184             self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
185             self.assertEqual(rx[IPv6].plen, 65220)  # 65200 + 20 (TCP)
186             self.assertEqual(rx[TCP].sport, 1234)
187             self.assertEqual(rx[TCP].dport, 1234)
188
189         #
190         # Send jumbo frame with gso enabled only on input interface
191         # and DF bit is set. GSO packet will be chunked into gso_size
192         # data payload
193         #
194         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
195                                              enable_disable=1)
196         p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
197                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
198                   flags='DF') /
199                TCP(sport=1234, dport=1234) /
200                Raw(b'\xa5' * 65200))
201
202         rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225)
203         size = 0
204         for rx in rxs:
205             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
206             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
207             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
208             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
209             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
210             self.assert_ip_checksum_valid(rx)
211             self.assert_tcp_checksum_valid(rx)
212             self.assertEqual(rx[TCP].sport, 1234)
213             self.assertEqual(rx[TCP].dport, 1234)
214             self.assertEqual(payload_len, len(rx[Raw]))
215             size += payload_len
216         self.assertEqual(size, 65200*5)
217
218         #
219         # ipv6
220         #
221         p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
222                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
223                TCP(sport=1234, dport=1234) /
224                Raw(b'\xa5' * 65200))
225
226         rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225)
227         size = 0
228         for rx in rxs:
229             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
230             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
231             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
232             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
233             payload_len = rx[IPv6].plen - 20
234             self.assert_tcp_checksum_valid(rx)
235             self.assertEqual(rx[TCP].sport, 1234)
236             self.assertEqual(rx[TCP].dport, 1234)
237             self.assertEqual(payload_len, len(rx[Raw]))
238             size += payload_len
239         self.assertEqual(size, 65200*5)
240
241         #
242         # Send jumbo frame with gso enabled only on input interface
243         # and DF bit is unset. GSO packet will be fragmented.
244         #
245         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
246         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
247                                              enable_disable=1)
248
249         p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
250                IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
251                TCP(sport=1234, dport=1234) /
252                Raw(b'\xa5' * 65200))
253
254         rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119)
255         size = 0
256         for rx in rxs:
257             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
258             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
259             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
260             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
261             self.assert_ip_checksum_valid(rx)
262             size += rx[IP].len - 20
263         size -= 20*5  # TCP header
264         self.assertEqual(size, 65200*5)
265
266         #
267         # IPv6
268         # Send jumbo frame with gso enabled only on input interface.
269         # ICMPv6 Packet Too Big will be sent back to sender.
270         #
271         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
272         p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
273                IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
274                TCP(sport=1234, dport=1234) /
275                Raw(b'\xa5' * 65200))
276
277         rxs = self.send_and_expect(self.pg2, 5*[p63], self.pg2, 5)
278         for rx in rxs:
279             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
280             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
281             self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
282             self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
283             self.assertEqual(rx[IPv6].plen, 1240)  # MTU - IPv6 header
284             self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
285             self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
286             self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
287             self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
288             self.assertEqual(rx[IPerror6].plen - 20, 65200)
289
290         #
291         # Send jumbo frame with gso enabled only on input interface with 9K MTU
292         # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
293         # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
294         #
295         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
296         self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
297         p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
298                IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
299                TCP(sport=1234, dport=1234) /
300                Raw(b'\xa5' * 65200))
301
302         rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165)
303         size = 0
304         for rx in rxs:
305             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
306             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
307             self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
308             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
309             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
310             self.assert_ip_checksum_valid(rx)
311             self.assert_tcp_checksum_valid(rx)
312             self.assertEqual(payload_len, len(rx[Raw]))
313             size += payload_len
314         self.assertEqual(size, 65200*5)
315
316         #
317         # IPv6
318         #
319         p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
320                IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
321                TCP(sport=1234, dport=1234) /
322                Raw(b'\xa5' * 65200))
323
324         rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170)
325         size = 0
326         for rx in rxs:
327             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
328             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
329             self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
330             self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
331             payload_len = rx[IPv6].plen - 20
332             self.assert_tcp_checksum_valid(rx)
333             self.assertEqual(payload_len, len(rx[Raw]))
334             size += payload_len
335         self.assertEqual(size, 65200*5)
336
337         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
338                                              enable_disable=0)
339         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
340                                              enable_disable=0)
341
342     def test_gso_vxlan(self):
343         """ GSO VXLAN test """
344         self.logger.info(self.vapi.cli("sh int addr"))
345         #
346         # Send jumbo frame with gso enabled only on input interface and
347         # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
348         # into BD.
349         #
350
351         #
352         # enable ipv4/vxlan
353         #
354         self.vxlan.add_vpp_config()
355         self.vapi.sw_interface_set_l2_bridge(
356             rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
357         self.vapi.sw_interface_set_l2_bridge(
358             rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
359         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
360                                              enable_disable=1)
361
362         #
363         # IPv4/IPv4 - VXLAN
364         #
365         p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
366                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
367                TCP(sport=1234, dport=1234) /
368                Raw(b'\xa5' * 65200))
369
370         rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225)
371         size = 0
372         for rx in rxs:
373             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
374             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
375             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
376             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
377             self.assert_ip_checksum_valid(rx)
378             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
379             self.assertEqual(rx[VXLAN].vni, 10)
380             inner = rx[VXLAN].payload
381             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
382             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
383             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
384             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
385             self.assertEqual(inner[IP].dst, "172.16.3.3")
386             self.assert_ip_checksum_valid(inner)
387             self.assert_tcp_checksum_valid(inner)
388             payload_len = inner[IP].len - 20 - 20
389             self.assertEqual(payload_len, len(inner[Raw]))
390             size += payload_len
391         self.assertEqual(size, 65200*5)
392
393         #
394         # IPv4/IPv6 - VXLAN
395         #
396         p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
397                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
398                TCP(sport=1234, dport=1234) /
399                Raw(b'\xa5' * 65200))
400
401         rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225)
402         size = 0
403         for rx in rxs:
404             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
405             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
406             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
407             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
408             self.assert_ip_checksum_valid(rx)
409             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
410             self.assertEqual(rx[VXLAN].vni, 10)
411             inner = rx[VXLAN].payload
412             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
413             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
414             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
415             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
416             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
417             self.assert_tcp_checksum_valid(inner)
418             payload_len = inner[IPv6].plen - 20
419             self.assertEqual(payload_len, len(inner[Raw]))
420             size += payload_len
421         self.assertEqual(size, 65200*5)
422
423         #
424         # disable ipv4/vxlan
425         #
426         self.vxlan.remove_vpp_config()
427
428         #
429         # enable ipv6/vxlan
430         #
431         self.vxlan2.add_vpp_config()
432         self.vapi.sw_interface_set_l2_bridge(
433             rx_sw_if_index=self.vxlan2.sw_if_index,
434             bd_id=self.single_tunnel_bd)
435
436         #
437         # IPv6/IPv4 - VXLAN
438         #
439         p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
440                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
441                TCP(sport=1234, dport=1234) /
442                Raw(b'\xa5' * 65200))
443
444         rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225)
445         size = 0
446         for rx in rxs:
447             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
448             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
449             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
450             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
451             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
452             self.assertEqual(rx[VXLAN].vni, 10)
453             inner = rx[VXLAN].payload
454             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
455             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
456             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
457             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
458             self.assertEqual(inner[IP].dst, "172.16.3.3")
459             self.assert_ip_checksum_valid(inner)
460             self.assert_tcp_checksum_valid(inner)
461             payload_len = inner[IP].len - 20 - 20
462             self.assertEqual(payload_len, len(inner[Raw]))
463             size += payload_len
464         self.assertEqual(size, 65200*5)
465
466         #
467         # IPv6/IPv6 - VXLAN
468         #
469         p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
470                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
471                TCP(sport=1234, dport=1234) /
472                Raw(b'\xa5' * 65200))
473
474         rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225)
475         size = 0
476         for rx in rxs:
477             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
478             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
479             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
480             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
481             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
482             self.assertEqual(rx[VXLAN].vni, 10)
483             inner = rx[VXLAN].payload
484             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
485             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
486             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
487             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
488             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
489             self.assert_tcp_checksum_valid(inner)
490             payload_len = inner[IPv6].plen - 20
491             self.assertEqual(payload_len, len(inner[Raw]))
492             size += payload_len
493         self.assertEqual(size, 65200*5)
494
495         #
496         # disable ipv4/vxlan
497         #
498         self.vxlan2.remove_vpp_config()
499
500         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
501                                              enable_disable=0)
502
503     def test_gso_ipip(self):
504         """ GSO IPIP test """
505         self.logger.info(self.vapi.cli("sh int addr"))
506         #
507         # Send jumbo frame with gso enabled only on input interface and
508         # create IPIP tunnel on VPP pg0.
509         #
510         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
511                                              enable_disable=1)
512
513         #
514         # enable ipip4
515         #
516         self.ipip4.add_vpp_config()
517
518         # Set interface up and enable IP on it
519         self.ipip4.admin_up()
520         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
521
522         # Add IPv4 routes via tunnel interface
523         self.ip4_via_ip4_tunnel = VppIpRoute(
524                 self, "172.16.10.0", 24,
525                 [VppRoutePath("0.0.0.0",
526                               self.ipip4.sw_if_index,
527                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
528         self.ip4_via_ip4_tunnel.add_vpp_config()
529
530         #
531         # IPv4/IPv4 - IPIP
532         #
533         p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
534                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
535                TCP(sport=1234, dport=1234) /
536                Raw(b'\xa5' * 65200))
537
538         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
539         size = 0
540         for rx in rxs:
541             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
542             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
543             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
544             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
545             self.assert_ip_checksum_valid(rx)
546             self.assertEqual(rx[IP].proto, 4)  # ipencap
547             inner = rx[IP].payload
548             self.assertEqual(rx[IP].len - 20, len(inner))
549             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
550             self.assertEqual(inner[IP].dst, "172.16.10.3")
551             self.assert_ip_checksum_valid(inner)
552             self.assert_tcp_checksum_valid(inner)
553             payload_len = inner[IP].len - 20 - 20
554             self.assertEqual(payload_len, len(inner[Raw]))
555             size += payload_len
556         self.assertEqual(size, 65200*5)
557
558         self.ip6_via_ip4_tunnel = VppIpRoute(
559                 self, "fd01:10::", 64,
560                 [VppRoutePath("::",
561                               self.ipip4.sw_if_index,
562                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
563         self.ip6_via_ip4_tunnel.add_vpp_config()
564         #
565         # IPv4/IPv6 - IPIP
566         #
567         p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
568                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
569                TCP(sport=1234, dport=1234) /
570                Raw(b'\xa5' * 65200))
571
572         rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225)
573         size = 0
574         for rx in rxs:
575             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
576             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
577             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
578             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
579             self.assert_ip_checksum_valid(rx)
580             self.assertEqual(rx[IP].proto, 41)  # ipv6
581             inner = rx[IP].payload
582             self.assertEqual(rx[IP].len - 20, len(inner))
583             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
584             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
585             self.assert_tcp_checksum_valid(inner)
586             payload_len = inner[IPv6].plen - 20
587             self.assertEqual(payload_len, len(inner[Raw]))
588             size += payload_len
589         self.assertEqual(size, 65200*5)
590
591         #
592         # Send jumbo frame with gso enabled only on input interface and
593         # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
594         # tunnel - IPSec use case
595         #
596         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
597                                              enable_disable=0)
598         self.vapi.feature_gso_enable_disable(
599             sw_if_index=self.ipip4.sw_if_index,
600             enable_disable=1)
601
602         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
603         size = 0
604         for rx in rxs:
605             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
606             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
607             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
608             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
609             self.assert_ip_checksum_valid(rx)
610             self.assertEqual(rx[IP].proto, 4)  # ipencap
611             inner = rx[IP].payload
612             self.assertEqual(rx[IP].len - 20, len(inner))
613             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
614             self.assertEqual(inner[IP].dst, "172.16.10.3")
615             self.assert_ip_checksum_valid(inner)
616             self.assert_tcp_checksum_valid(inner)
617             payload_len = inner[IP].len - 20 - 20
618             self.assertEqual(payload_len, len(inner[Raw]))
619             size += payload_len
620         self.assertEqual(size, 65200*5)
621
622         #
623         # disable ipip4
624         #
625         self.vapi.feature_gso_enable_disable(
626             sw_if_index=self.ipip4.sw_if_index,
627             enable_disable=0)
628         self.ip4_via_ip4_tunnel.remove_vpp_config()
629         self.ip6_via_ip4_tunnel.remove_vpp_config()
630         self.ipip4.remove_vpp_config()
631
632         #
633         # enable ipip6
634         #
635         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
636                                              enable_disable=1)
637         self.ipip6.add_vpp_config()
638
639         # Set interface up and enable IP on it
640         self.ipip6.admin_up()
641         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
642
643         # Add IPv4 routes via tunnel interface
644         self.ip4_via_ip6_tunnel = VppIpRoute(
645                 self, "172.16.10.0", 24,
646                 [VppRoutePath("0.0.0.0",
647                               self.ipip6.sw_if_index,
648                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
649         self.ip4_via_ip6_tunnel.add_vpp_config()
650
651         #
652         # IPv6/IPv4 - IPIP
653         #
654         p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
655                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
656                TCP(sport=1234, dport=1234) /
657                Raw(b'\xa5' * 65200))
658
659         rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225)
660         size = 0
661         for rx in rxs:
662             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
663             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
664             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
665             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
666             self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
667             inner = rx[IPv6].payload
668             self.assertEqual(rx[IPv6].plen, len(inner))
669             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
670             self.assertEqual(inner[IP].dst, "172.16.10.3")
671             self.assert_ip_checksum_valid(inner)
672             self.assert_tcp_checksum_valid(inner)
673             payload_len = inner[IP].len - 20 - 20
674             self.assertEqual(payload_len, len(inner[Raw]))
675             size += payload_len
676         self.assertEqual(size, 65200*5)
677
678         self.ip6_via_ip6_tunnel = VppIpRoute(
679                 self, "fd01:10::", 64,
680                 [VppRoutePath("::",
681                               self.ipip6.sw_if_index,
682                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
683         self.ip6_via_ip6_tunnel.add_vpp_config()
684
685         #
686         # IPv6/IPv6 - IPIP
687         #
688         p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
689                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
690                TCP(sport=1234, dport=1234) /
691                Raw(b'\xa5' * 65200))
692
693         rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225)
694         size = 0
695         for rx in rxs:
696             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
697             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
698             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
699             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
700             self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
701             inner = rx[IPv6].payload
702             self.assertEqual(rx[IPv6].plen, len(inner))
703             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
704             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
705             self.assert_tcp_checksum_valid(inner)
706             payload_len = inner[IPv6].plen - 20
707             self.assertEqual(payload_len, len(inner[Raw]))
708             size += payload_len
709         self.assertEqual(size, 65200*5)
710
711         #
712         # disable ipip6
713         #
714         self.ip4_via_ip6_tunnel.remove_vpp_config()
715         self.ip6_via_ip6_tunnel.remove_vpp_config()
716         self.ipip6.remove_vpp_config()
717
718         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
719                                              enable_disable=0)
720
721 if __name__ == '__main__':
722     unittest.main(testRunner=VppTestRunner)