gso: fix the make test for ipip
[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 jumbo frame with gso enabled and DF bit is set
112         # input and output interfaces support GSO
113         #
114         p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
115                IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
116                   flags='DF') /
117                TCP(sport=1234, dport=1234) /
118                Raw(b'\xa5' * 65200))
119
120         rxs = self.send_and_expect(self.pg2, [p41], self.pg3)
121
122         for rx in rxs:
123             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
124             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
125             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
126             self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
127             self.assertEqual(rx[IP].len, 65240)  # 65200 + 20 (IP) + 20 (TCP)
128             self.assertEqual(rx[TCP].sport, 1234)
129             self.assertEqual(rx[TCP].dport, 1234)
130
131         #
132         # ipv6
133         #
134         p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
135                IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
136                TCP(sport=1234, dport=1234) /
137                Raw(b'\xa5' * 65200))
138
139         rxs = self.send_and_expect(self.pg2, [p61], self.pg3)
140
141         for rx in rxs:
142             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
143             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
144             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
145             self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
146             self.assertEqual(rx[IPv6].plen, 65220)  # 65200 + 20 (TCP)
147             self.assertEqual(rx[TCP].sport, 1234)
148             self.assertEqual(rx[TCP].dport, 1234)
149
150         #
151         # Send jumbo frame with gso enabled only on input interface
152         # and DF bit is set. GSO packet will be chunked into gso_size
153         # data payload
154         #
155         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
156         p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
157                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
158                   flags='DF') /
159                TCP(sport=1234, dport=1234) /
160                Raw(b'\xa5' * 65200))
161
162         rxs = self.send_and_expect(self.pg2, [p42], self.pg0, 45)
163         size = 0
164         for rx in rxs:
165             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
166             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
167             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
168             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
169             self.assertEqual(rx[TCP].sport, 1234)
170             self.assertEqual(rx[TCP].dport, 1234)
171
172         size = rxs[44][TCP].seq + rxs[44][IP].len - 20 - 20
173         self.assertEqual(size, 65200)
174
175         #
176         # ipv6
177         #
178         p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
179                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
180                TCP(sport=1234, dport=1234) /
181                Raw(b'\xa5' * 65200))
182
183         rxs = self.send_and_expect(self.pg2, [p62], self.pg0, 45)
184         size = 0
185         for rx in rxs:
186             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
187             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
188             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
189             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
190             self.assertEqual(rx[TCP].sport, 1234)
191             self.assertEqual(rx[TCP].dport, 1234)
192
193         size = rxs[44][TCP].seq + rxs[44][IPv6].plen - 20
194         self.assertEqual(size, 65200)
195
196         #
197         # Send jumbo frame with gso enabled only on input interface
198         # and DF bit is unset. GSO packet will be fragmented.
199         #
200         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
201         self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index)
202
203         p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
204                IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
205                TCP(sport=1234, dport=1234) /
206                Raw(b'\xa5' * 65200))
207
208         rxs = self.send_and_expect(self.pg2, [p43], self.pg1, 119)
209         size = 0
210         for rx in rxs:
211             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
212             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
213             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
214             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
215             size += rx[IP].len - 20
216         size -= 20  # TCP header
217         self.assertEqual(size, 65200)
218
219         #
220         # IPv6
221         # Send jumbo frame with gso enabled only on input interface.
222         # ICMPv6 Packet Too Big will be sent back to sender.
223         #
224         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
225         p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
226                IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
227                TCP(sport=1234, dport=1234) /
228                Raw(b'\xa5' * 65200))
229
230         rxs = self.send_and_expect(self.pg2, [p63], self.pg2, 1)
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[IPv6].src, self.pg2.local_ip6)
235             self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
236             self.assertEqual(rx[IPv6].plen, 1240)  # MTU - IPv6 header
237             self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
238             self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
239             self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
240             self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
241             self.assertEqual(rx[IPerror6].plen - 20, 65200)
242
243         #
244         # Send jumbo frame with gso enabled only on input interface with 9K MTU
245         # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
246         # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
247         #
248         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
249         self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
250         p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
251                IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
252                TCP(sport=1234, dport=1234) /
253                Raw(b'\xa5' * 65200))
254
255         self.pg1.enable_capture()
256         rxs = self.send_and_expect(self.pg4, [p44], self.pg1, 33)
257         size = 0
258         for rx in rxs:
259             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
260             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
261             self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
262             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
263         size = rxs[32][TCP].seq + rxs[32][IP].len - 20 - 20
264         self.assertEqual(size, 65200)
265
266         #
267         # IPv6
268         #
269         p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
270                IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
271                TCP(sport=1234, dport=1234) /
272                Raw(b'\xa5' * 65200))
273
274         self.pg1.enable_capture()
275         rxs = self.send_and_expect(self.pg4, [p64], self.pg1, 34)
276         size = 0
277         for rx in rxs:
278             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
279             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
280             self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
281             self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
282         size = rxs[33][TCP].seq + rxs[33][IPv6].plen - 20
283         self.assertEqual(size, 65200)
284
285         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
286                                              enable_disable=0)
287         self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index,
288                                              enable_disable=0)
289
290     def test_gso_vxlan(self):
291         """ GSO VXLAN test """
292         self.logger.info(self.vapi.cli("sh int addr"))
293         #
294         # Send jumbo frame with gso enabled only on input interface and
295         # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
296         # into BD.
297         #
298
299         #
300         # enable ipv4/vxlan
301         #
302         self.vxlan.add_vpp_config()
303         self.vapi.sw_interface_set_l2_bridge(
304             rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
305         self.vapi.sw_interface_set_l2_bridge(
306             rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
307         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
308
309         #
310         # IPv4/IPv4 - VXLAN
311         #
312         p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
313                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
314                TCP(sport=1234, dport=1234) /
315                Raw(b'\xa5' * 65200))
316
317         rxs = self.send_and_expect(self.pg2, [p45], self.pg0, 45)
318         size = 0
319         for rx in rxs:
320             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
321             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
322             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
323             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
324             self.assertEqual(rx[VXLAN].vni, 10)
325             inner = rx[VXLAN].payload
326             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
327             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
328             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
329             self.assertEqual(inner[IP].dst, "172.16.3.3")
330             size += inner[IP].len - 20 - 20
331         self.assertEqual(size, 65200)
332
333         #
334         # IPv4/IPv6 - VXLAN
335         #
336         p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
337                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
338                TCP(sport=1234, dport=1234) /
339                Raw(b'\xa5' * 65200))
340
341         rxs = self.send_and_expect(self.pg2, [p65], self.pg0, 45)
342         size = 0
343         for rx in rxs:
344             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
345             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
346             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
347             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
348             self.assertEqual(rx[VXLAN].vni, 10)
349             inner = rx[VXLAN].payload
350             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
351             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
352             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
353             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
354             size += inner[IPv6].plen - 20
355         self.assertEqual(size, 65200)
356
357         #
358         # disable ipv4/vxlan
359         #
360         self.vxlan.remove_vpp_config()
361
362         #
363         # enable ipv6/vxlan
364         #
365         self.vxlan2.add_vpp_config()
366         self.vapi.sw_interface_set_l2_bridge(
367             rx_sw_if_index=self.vxlan2.sw_if_index,
368             bd_id=self.single_tunnel_bd)
369
370         #
371         # IPv6/IPv4 - VXLAN
372         #
373         p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
374                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
375                TCP(sport=1234, dport=1234) /
376                Raw(b'\xa5' * 65200))
377
378         rxs = self.send_and_expect(self.pg2, [p46], self.pg0, 45)
379         size = 0
380         for rx in rxs:
381             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
382             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
383             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
384             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
385             self.assertEqual(rx[VXLAN].vni, 10)
386             inner = rx[VXLAN].payload
387             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
388             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
389             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
390             self.assertEqual(inner[IP].dst, "172.16.3.3")
391             size += inner[IP].len - 20 - 20
392         self.assertEqual(size, 65200)
393
394         #
395         # IPv6/IPv6 - VXLAN
396         #
397         p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
398                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
399                TCP(sport=1234, dport=1234) /
400                Raw(b'\xa5' * 65200))
401
402         rxs = self.send_and_expect(self.pg2, [p66], self.pg0, 45)
403         size = 0
404         for rx in rxs:
405             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
406             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
407             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
408             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
409             self.assertEqual(rx[VXLAN].vni, 10)
410             inner = rx[VXLAN].payload
411             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
412             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
413             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
414             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
415             size += inner[IPv6].plen - 20
416         self.assertEqual(size, 65200)
417
418         #
419         # disable ipv4/vxlan
420         #
421         self.vxlan2.remove_vpp_config()
422
423         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
424                                              enable_disable=0)
425
426     def test_gso_ipip(self):
427         """ GSO IPIP test """
428         self.logger.info(self.vapi.cli("sh int addr"))
429         #
430         # Send jumbo frame with gso enabled only on input interface and
431         # create IPIP tunnel on VPP pg0.
432         #
433         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
434
435         #
436         # enable ipip4
437         #
438         self.ipip4.add_vpp_config()
439
440         # Set interface up and enable IP on it
441         self.ipip4.admin_up()
442         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
443
444         # Add IPv4 routes via tunnel interface
445         self.ip4_via_ip4_tunnel = VppIpRoute(
446                 self, "172.16.10.0", 24,
447                 [VppRoutePath("0.0.0.0",
448                               self.ipip4.sw_if_index,
449                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
450         self.ip4_via_ip4_tunnel.add_vpp_config()
451
452         #
453         # IPv4/IPv4 - IPIP
454         #
455         p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
456                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
457                TCP(sport=1234, dport=1234) /
458                Raw(b'\xa5' * 65200))
459
460         rxs = self.send_and_expect(self.pg2, [p47], self.pg0, 45)
461         size = 0
462         for rx in rxs:
463             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
464             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
465             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
466             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
467             self.assertEqual(rx[IP].proto, 4)  # ipencap
468             inner = rx[IP].payload
469             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
470             self.assertEqual(inner[IP].dst, "172.16.10.3")
471             size += inner[IP].len - 20 - 20
472         self.assertEqual(size, 65200)
473
474         self.ip6_via_ip4_tunnel = VppIpRoute(
475                 self, "fd01:10::", 64,
476                 [VppRoutePath("::",
477                               self.ipip4.sw_if_index,
478                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
479         self.ip6_via_ip4_tunnel.add_vpp_config()
480         #
481         # IPv4/IPv6 - IPIP
482         #
483         p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
484                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
485                TCP(sport=1234, dport=1234) /
486                Raw(b'\xa5' * 65200))
487
488         rxs = self.send_and_expect(self.pg2, [p67], self.pg0, 45)
489         size = 0
490         for rx in rxs:
491             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
492             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
493             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
494             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
495             self.assertEqual(rx[IP].proto, 41)  # ipv6
496             inner = rx[IP].payload
497             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
498             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
499             size += inner[IPv6].plen - 20
500         self.assertEqual(size, 65200)
501
502         #
503         # Send jumbo frame with gso enabled only on input interface and
504         # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
505         # tunnel - IPSec use case
506         #
507         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
508                                              enable_disable=0)
509         self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index)
510
511         rxs = self.send_and_expect(self.pg2, [p47], self.pg0, 45)
512         size = 0
513         for rx in rxs:
514             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
515             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
516             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
517             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
518             self.assertEqual(rx[IP].proto, 4)  # ipencap
519             inner = rx[IP].payload
520             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
521             self.assertEqual(inner[IP].dst, "172.16.10.3")
522             size += inner[IP].len - 20 - 20
523         self.assertEqual(size, 65200)
524
525         #
526         # disable ipip4
527         #
528         self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index,
529                                              enable_disable=0)
530         self.ip4_via_ip4_tunnel.remove_vpp_config()
531         self.ip6_via_ip4_tunnel.remove_vpp_config()
532         self.ipip4.remove_vpp_config()
533
534         #
535         # enable ipip6
536         #
537         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
538         self.ipip6.add_vpp_config()
539
540         # Set interface up and enable IP on it
541         self.ipip6.admin_up()
542         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
543
544         # Add IPv4 routes via tunnel interface
545         self.ip4_via_ip6_tunnel = VppIpRoute(
546                 self, "172.16.10.0", 24,
547                 [VppRoutePath("0.0.0.0",
548                               self.ipip6.sw_if_index,
549                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
550         self.ip4_via_ip6_tunnel.add_vpp_config()
551
552         #
553         # IPv6/IPv4 - IPIP
554         #
555         p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
556                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
557                TCP(sport=1234, dport=1234) /
558                Raw(b'\xa5' * 65200))
559
560         rxs = self.send_and_expect(self.pg2, [p48], self.pg0, 45)
561         size = 0
562         for rx in rxs:
563             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
564             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
565             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
566             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
567             self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
568             inner = rx[IPv6].payload
569             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
570             self.assertEqual(inner[IP].dst, "172.16.10.3")
571             size += inner[IP].len - 20 - 20
572         self.assertEqual(size, 65200)
573
574         self.ip6_via_ip6_tunnel = VppIpRoute(
575                 self, "fd01:10::", 64,
576                 [VppRoutePath("::",
577                               self.ipip6.sw_if_index,
578                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
579         self.ip6_via_ip6_tunnel.add_vpp_config()
580
581         #
582         # IPv6/IPv6 - IPIP
583         #
584         p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
585                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
586                TCP(sport=1234, dport=1234) /
587                Raw(b'\xa5' * 65200))
588
589         rxs = self.send_and_expect(self.pg2, [p68], self.pg0, 45)
590         size = 0
591         for rx in rxs:
592             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
593             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
594             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
595             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
596             self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
597             inner = rx[IPv6].payload
598             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
599             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
600             size += inner[IPv6].plen - 20
601         self.assertEqual(size, 65200)
602
603         #
604         # disable ipip6
605         #
606         self.ip4_via_ip6_tunnel.remove_vpp_config()
607         self.ip6_via_ip6_tunnel.remove_vpp_config()
608         self.ipip6.remove_vpp_config()
609
610         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
611                                              enable_disable=0)
612
613 if __name__ == '__main__':
614     unittest.main(testRunner=VppTestRunner)