ip: rate-limit the sending of ICMP error messages
[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 from scapy.layers.ipsec import SecurityAssociation, ESP
20
21 from vpp_papi import VppEnum
22 from framework import VppTestCase, VppTestRunner
23 from vpp_object import VppObject
24 from vpp_interface import VppInterface
25 from vpp_ip import DpoProto
26 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
27 from vpp_ipip_tun_interface import VppIpIpTunInterface
28 from vpp_vxlan_tunnel import VppVxlanTunnel
29 from socket import AF_INET, AF_INET6, inet_pton
30 from util import reassemble4
31
32 from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect
33 from template_ipsec import IPsecIPv4Params, IPsecIPv6Params, \
34     mk_scapy_crypt_key, config_tun_params
35
36 """ Test_gso is a subclass of VPPTestCase classes.
37     GSO tests.
38 """
39
40
41 class TestGSO(VppTestCase):
42     """ GSO Test Case """
43
44     def __init__(self, *args):
45         VppTestCase.__init__(self, *args)
46
47     @classmethod
48     def setUpClass(self):
49         super(TestGSO, self).setUpClass()
50         res = self.create_pg_interfaces(range(2))
51         res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460)
52         self.create_pg_interfaces(range(4, 5), 1, 8940)
53         self.pg_interfaces.append(res[0])
54         self.pg_interfaces.append(res[1])
55         self.pg_interfaces.append(res_gso[0])
56         self.pg_interfaces.append(res_gso[1])
57
58     @classmethod
59     def tearDownClass(self):
60         super(TestGSO, self).tearDownClass()
61
62     def setUp(self):
63         super(TestGSO, self).setUp()
64         for i in self.pg_interfaces:
65             i.admin_up()
66             i.config_ip4()
67             i.config_ip6()
68             i.disable_ipv6_ra()
69             i.resolve_arp()
70             i.resolve_ndp()
71
72         self.single_tunnel_bd = 10
73         self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4,
74                                     dst=self.pg0.remote_ip4,
75                                     vni=self.single_tunnel_bd)
76
77         self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6,
78                                      dst=self.pg0.remote_ip6,
79                                      vni=self.single_tunnel_bd)
80
81         self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4,
82                                          self.pg0.remote_ip4)
83         self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6,
84                                          self.pg0.remote_ip6)
85
86     def tearDown(self):
87         super(TestGSO, self).tearDown()
88         if not self.vpp_dead:
89             for i in self.pg_interfaces:
90                 i.unconfig_ip4()
91                 i.unconfig_ip6()
92                 i.admin_down()
93
94     def test_gso(self):
95         """ GSO test """
96         #
97         # Send jumbo frame with gso disabled and DF bit is set
98         #
99         p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
100               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
101                  flags='DF') /
102               TCP(sport=1234, dport=1234) /
103               Raw(b'\xa5' * 65200))
104
105         rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
106
107         for rx in rxs:
108             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
109             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
110             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
111             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
112             self.assertEqual(rx[ICMP].type, 3)  # "dest-unreach"
113             self.assertEqual(rx[ICMP].code, 4)  # "fragmentation-needed"
114
115         #
116         # Send checksum offload frames
117         #
118         p40 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
119                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
120                   flags='DF') /
121                TCP(sport=1234, dport=1234) /
122                Raw(b'\xa5' * 1460))
123
124         rxs = self.send_and_expect(self.pg2, 100*[p40], self.pg0)
125
126         for rx in rxs:
127             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
128             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
129             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
130             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
131             payload_len = rx[IP].len - 20 - 20
132             self.assert_ip_checksum_valid(rx)
133             self.assert_tcp_checksum_valid(rx)
134             self.assertEqual(payload_len, len(rx[Raw]))
135
136         p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
137                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
138                TCP(sport=1234, dport=1234) /
139                Raw(b'\xa5' * 1440))
140
141         rxs = self.send_and_expect(self.pg2, 100*[p60], self.pg0)
142
143         for rx in rxs:
144             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
145             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
146             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
147             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
148             payload_len = rx[IPv6].plen - 20
149             self.assert_tcp_checksum_valid(rx)
150             self.assertEqual(payload_len, len(rx[Raw]))
151
152         #
153         # Send jumbo frame with gso enabled and DF bit is set
154         # input and output interfaces support GSO
155         #
156         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg3.sw_if_index,
157                                              enable_disable=1)
158         p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
159                IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
160                   flags='DF') /
161                TCP(sport=1234, dport=1234) /
162                Raw(b'\xa5' * 65200))
163
164         rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100)
165
166         for rx in rxs:
167             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
168             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
169             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
170             self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
171             self.assertEqual(rx[IP].len, 65240)  # 65200 + 20 (IP) + 20 (TCP)
172             self.assertEqual(rx[TCP].sport, 1234)
173             self.assertEqual(rx[TCP].dport, 1234)
174
175         #
176         # ipv6
177         #
178         p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
179                IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
180                TCP(sport=1234, dport=1234) /
181                Raw(b'\xa5' * 65200))
182
183         rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100)
184
185         for rx in rxs:
186             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
187             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
188             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
189             self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
190             self.assertEqual(rx[IPv6].plen, 65220)  # 65200 + 20 (TCP)
191             self.assertEqual(rx[TCP].sport, 1234)
192             self.assertEqual(rx[TCP].dport, 1234)
193
194         #
195         # Send jumbo frame with gso enabled only on input interface
196         # and DF bit is set. GSO packet will be chunked into gso_size
197         # data payload
198         #
199         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
200                                              enable_disable=1)
201         p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
202                IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
203                   flags='DF') /
204                TCP(sport=1234, dport=1234) /
205                Raw(b'\xa5' * 65200))
206
207         rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225)
208         size = 0
209         for rx in rxs:
210             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
211             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
212             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
213             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
214             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
215             self.assert_ip_checksum_valid(rx)
216             self.assert_tcp_checksum_valid(rx)
217             self.assertEqual(rx[TCP].sport, 1234)
218             self.assertEqual(rx[TCP].dport, 1234)
219             self.assertEqual(payload_len, len(rx[Raw]))
220             size += payload_len
221         self.assertEqual(size, 65200*5)
222
223         #
224         # ipv6
225         #
226         p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
227                IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
228                TCP(sport=1234, dport=1234) /
229                Raw(b'\xa5' * 65200))
230
231         rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225)
232         size = 0
233         for rx in rxs:
234             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
235             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
236             self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
237             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
238             payload_len = rx[IPv6].plen - 20
239             self.assert_tcp_checksum_valid(rx)
240             self.assertEqual(rx[TCP].sport, 1234)
241             self.assertEqual(rx[TCP].dport, 1234)
242             self.assertEqual(payload_len, len(rx[Raw]))
243             size += payload_len
244         self.assertEqual(size, 65200*5)
245
246         #
247         # Send jumbo frame with gso enabled only on input interface
248         # and DF bit is unset. GSO packet will be fragmented.
249         #
250         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
251         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
252                                              enable_disable=1)
253
254         p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
255                IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
256                TCP(sport=1234, dport=1234) /
257                Raw(b'\xa5' * 65200))
258
259         rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119)
260         size = 0
261         for rx in rxs:
262             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
263             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
264             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
265             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
266             self.assert_ip_checksum_valid(rx)
267             size += rx[IP].len - 20
268         size -= 20*5  # TCP header
269         self.assertEqual(size, 65200*5)
270
271         #
272         # IPv6
273         # Send jumbo frame with gso enabled only on input interface.
274         # ICMPv6 Packet Too Big will be sent back to sender.
275         #
276         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
277         p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
278                IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
279                TCP(sport=1234, dport=1234) /
280                Raw(b'\xa5' * 65200))
281
282         rxs = self.send_and_expect_some(self.pg2, 5*[p63], self.pg2, 5)
283         for rx in rxs:
284             self.assertEqual(rx[Ether].src, self.pg2.local_mac)
285             self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
286             self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
287             self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
288             self.assertEqual(rx[IPv6].plen, 1240)  # MTU - IPv6 header
289             self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
290             self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
291             self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
292             self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
293             self.assertEqual(rx[IPerror6].plen - 20, 65200)
294
295         #
296         # Send jumbo frame with gso enabled only on input interface with 9K MTU
297         # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
298         # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
299         #
300         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
301         self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
302         p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
303                IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
304                TCP(sport=1234, dport=1234) /
305                Raw(b'\xa5' * 65200))
306
307         rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165)
308         size = 0
309         for rx in rxs:
310             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
311             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
312             self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
313             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
314             payload_len = rx[IP].len - 20 - 20  # len - 20 (IP4) - 20 (TCP)
315             self.assert_ip_checksum_valid(rx)
316             self.assert_tcp_checksum_valid(rx)
317             self.assertEqual(payload_len, len(rx[Raw]))
318             size += payload_len
319         self.assertEqual(size, 65200*5)
320
321         #
322         # IPv6
323         #
324         p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
325                IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
326                TCP(sport=1234, dport=1234) /
327                Raw(b'\xa5' * 65200))
328
329         rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170)
330         size = 0
331         for rx in rxs:
332             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
333             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
334             self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
335             self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
336             payload_len = rx[IPv6].plen - 20
337             self.assert_tcp_checksum_valid(rx)
338             self.assertEqual(payload_len, len(rx[Raw]))
339             size += payload_len
340         self.assertEqual(size, 65200*5)
341
342         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
343                                              enable_disable=0)
344         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
345                                              enable_disable=0)
346
347     def test_gso_vxlan(self):
348         """ GSO VXLAN test """
349         self.logger.info(self.vapi.cli("sh int addr"))
350         #
351         # Send jumbo frame with gso enabled only on input interface and
352         # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
353         # into BD.
354         #
355
356         #
357         # enable ipv4/vxlan
358         #
359         self.vxlan.add_vpp_config()
360         self.vapi.sw_interface_set_l2_bridge(
361             rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
362         self.vapi.sw_interface_set_l2_bridge(
363             rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
364         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
365                                              enable_disable=1)
366
367         #
368         # IPv4/IPv4 - VXLAN
369         #
370         p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
371                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
372                TCP(sport=1234, dport=1234) /
373                Raw(b'\xa5' * 65200))
374
375         rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225)
376         size = 0
377         for rx in rxs:
378             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
379             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
380             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
381             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
382             self.assert_ip_checksum_valid(rx)
383             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
384             self.assertEqual(rx[VXLAN].vni, 10)
385             inner = rx[VXLAN].payload
386             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
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             self.assert_ip_checksum_valid(inner)
392             self.assert_tcp_checksum_valid(inner)
393             payload_len = inner[IP].len - 20 - 20
394             self.assertEqual(payload_len, len(inner[Raw]))
395             size += payload_len
396         self.assertEqual(size, 65200*5)
397
398         #
399         # IPv4/IPv6 - VXLAN
400         #
401         p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
402                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
403                TCP(sport=1234, dport=1234) /
404                Raw(b'\xa5' * 65200))
405
406         rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225)
407         size = 0
408         for rx in rxs:
409             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
410             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
411             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
412             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
413             self.assert_ip_checksum_valid(rx)
414             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
415             self.assertEqual(rx[VXLAN].vni, 10)
416             inner = rx[VXLAN].payload
417             self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
418             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
419             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
420             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
421             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
422             self.assert_tcp_checksum_valid(inner)
423             payload_len = inner[IPv6].plen - 20
424             self.assertEqual(payload_len, len(inner[Raw]))
425             size += payload_len
426         self.assertEqual(size, 65200*5)
427
428         #
429         # disable ipv4/vxlan
430         #
431         self.vxlan.remove_vpp_config()
432
433         #
434         # enable ipv6/vxlan
435         #
436         self.vxlan2.add_vpp_config()
437         self.vapi.sw_interface_set_l2_bridge(
438             rx_sw_if_index=self.vxlan2.sw_if_index,
439             bd_id=self.single_tunnel_bd)
440
441         #
442         # IPv6/IPv4 - VXLAN
443         #
444         p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
445                IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
446                TCP(sport=1234, dport=1234) /
447                Raw(b'\xa5' * 65200))
448
449         rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225)
450         size = 0
451         for rx in rxs:
452             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
453             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
454             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
455             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
456             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
457             self.assertEqual(rx[VXLAN].vni, 10)
458             inner = rx[VXLAN].payload
459             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
460             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
461             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
462             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
463             self.assertEqual(inner[IP].dst, "172.16.3.3")
464             self.assert_ip_checksum_valid(inner)
465             self.assert_tcp_checksum_valid(inner)
466             payload_len = inner[IP].len - 20 - 20
467             self.assertEqual(payload_len, len(inner[Raw]))
468             size += payload_len
469         self.assertEqual(size, 65200*5)
470
471         #
472         # IPv6/IPv6 - VXLAN
473         #
474         p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
475                IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
476                TCP(sport=1234, dport=1234) /
477                Raw(b'\xa5' * 65200))
478
479         rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225)
480         size = 0
481         for rx in rxs:
482             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
483             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
484             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
485             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
486             self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
487             self.assertEqual(rx[VXLAN].vni, 10)
488             inner = rx[VXLAN].payload
489             self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
490             self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
491             self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
492             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
493             self.assertEqual(inner[IPv6].dst, "fd01:3::3")
494             self.assert_tcp_checksum_valid(inner)
495             payload_len = inner[IPv6].plen - 20
496             self.assertEqual(payload_len, len(inner[Raw]))
497             size += payload_len
498         self.assertEqual(size, 65200*5)
499
500         #
501         # disable ipv4/vxlan
502         #
503         self.vxlan2.remove_vpp_config()
504
505         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
506                                              enable_disable=0)
507
508     def test_gso_ipip(self):
509         """ GSO IPIP test """
510         self.logger.info(self.vapi.cli("sh int addr"))
511         #
512         # Send jumbo frame with gso enabled only on input interface and
513         # create IPIP tunnel on VPP pg0.
514         #
515         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
516                                              enable_disable=1)
517
518         #
519         # enable ipip4
520         #
521         self.ipip4.add_vpp_config()
522
523         # Set interface up and enable IP on it
524         self.ipip4.admin_up()
525         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
526
527         # Add IPv4 routes via tunnel interface
528         self.ip4_via_ip4_tunnel = VppIpRoute(
529                 self, "172.16.10.0", 24,
530                 [VppRoutePath("0.0.0.0",
531                               self.ipip4.sw_if_index,
532                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
533         self.ip4_via_ip4_tunnel.add_vpp_config()
534
535         #
536         # IPv4/IPv4 - IPIP
537         #
538         p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
539                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
540                TCP(sport=1234, dport=1234) /
541                Raw(b'\xa5' * 65200))
542
543         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
544         size = 0
545         for rx in rxs:
546             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
547             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
548             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
549             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
550             self.assert_ip_checksum_valid(rx)
551             self.assertEqual(rx[IP].proto, 4)  # ipencap
552             inner = rx[IP].payload
553             self.assertEqual(rx[IP].len - 20, len(inner))
554             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
555             self.assertEqual(inner[IP].dst, "172.16.10.3")
556             self.assert_ip_checksum_valid(inner)
557             self.assert_tcp_checksum_valid(inner)
558             payload_len = inner[IP].len - 20 - 20
559             self.assertEqual(payload_len, len(inner[Raw]))
560             size += payload_len
561         self.assertEqual(size, 65200*5)
562
563         self.ip6_via_ip4_tunnel = VppIpRoute(
564                 self, "fd01:10::", 64,
565                 [VppRoutePath("::",
566                               self.ipip4.sw_if_index,
567                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
568         self.ip6_via_ip4_tunnel.add_vpp_config()
569         #
570         # IPv4/IPv6 - IPIP
571         #
572         p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
573                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
574                TCP(sport=1234, dport=1234) /
575                Raw(b'\xa5' * 65200))
576
577         rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225)
578         size = 0
579         for rx in rxs:
580             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
581             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
582             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
583             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
584             self.assert_ip_checksum_valid(rx)
585             self.assertEqual(rx[IP].proto, 41)  # ipv6
586             inner = rx[IP].payload
587             self.assertEqual(rx[IP].len - 20, len(inner))
588             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
589             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
590             self.assert_tcp_checksum_valid(inner)
591             payload_len = inner[IPv6].plen - 20
592             self.assertEqual(payload_len, len(inner[Raw]))
593             size += payload_len
594         self.assertEqual(size, 65200*5)
595
596         #
597         # Send jumbo frame with gso enabled only on input interface and
598         # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
599         # tunnel - IPSec use case
600         #
601         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
602                                              enable_disable=0)
603         self.vapi.feature_gso_enable_disable(
604             sw_if_index=self.ipip4.sw_if_index,
605             enable_disable=1)
606
607         rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
608         size = 0
609         for rx in rxs:
610             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
611             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
612             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
613             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
614             self.assert_ip_checksum_valid(rx)
615             self.assertEqual(rx[IP].proto, 4)  # ipencap
616             inner = rx[IP].payload
617             self.assertEqual(rx[IP].len - 20, len(inner))
618             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
619             self.assertEqual(inner[IP].dst, "172.16.10.3")
620             self.assert_ip_checksum_valid(inner)
621             self.assert_tcp_checksum_valid(inner)
622             payload_len = inner[IP].len - 20 - 20
623             self.assertEqual(payload_len, len(inner[Raw]))
624             size += payload_len
625         self.assertEqual(size, 65200*5)
626
627         #
628         # disable ipip4
629         #
630         self.vapi.feature_gso_enable_disable(
631             sw_if_index=self.ipip4.sw_if_index,
632             enable_disable=0)
633         self.ip4_via_ip4_tunnel.remove_vpp_config()
634         self.ip6_via_ip4_tunnel.remove_vpp_config()
635         self.ipip4.remove_vpp_config()
636
637         #
638         # enable ipip6
639         #
640         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
641                                              enable_disable=1)
642         self.ipip6.add_vpp_config()
643
644         # Set interface up and enable IP on it
645         self.ipip6.admin_up()
646         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
647
648         # Add IPv4 routes via tunnel interface
649         self.ip4_via_ip6_tunnel = VppIpRoute(
650                 self, "172.16.10.0", 24,
651                 [VppRoutePath("0.0.0.0",
652                               self.ipip6.sw_if_index,
653                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
654         self.ip4_via_ip6_tunnel.add_vpp_config()
655
656         #
657         # IPv6/IPv4 - IPIP
658         #
659         p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
660                IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
661                TCP(sport=1234, dport=1234) /
662                Raw(b'\xa5' * 65200))
663
664         rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225)
665         size = 0
666         for rx in rxs:
667             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
668             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
669             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
670             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
671             self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
672             inner = rx[IPv6].payload
673             self.assertEqual(rx[IPv6].plen, len(inner))
674             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
675             self.assertEqual(inner[IP].dst, "172.16.10.3")
676             self.assert_ip_checksum_valid(inner)
677             self.assert_tcp_checksum_valid(inner)
678             payload_len = inner[IP].len - 20 - 20
679             self.assertEqual(payload_len, len(inner[Raw]))
680             size += payload_len
681         self.assertEqual(size, 65200*5)
682
683         self.ip6_via_ip6_tunnel = VppIpRoute(
684                 self, "fd01:10::", 64,
685                 [VppRoutePath("::",
686                               self.ipip6.sw_if_index,
687                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
688         self.ip6_via_ip6_tunnel.add_vpp_config()
689
690         #
691         # IPv6/IPv6 - IPIP
692         #
693         p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
694                IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
695                TCP(sport=1234, dport=1234) /
696                Raw(b'\xa5' * 65200))
697
698         rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225)
699         size = 0
700         for rx in rxs:
701             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
702             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
703             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
704             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
705             self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
706             inner = rx[IPv6].payload
707             self.assertEqual(rx[IPv6].plen, len(inner))
708             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
709             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
710             self.assert_tcp_checksum_valid(inner)
711             payload_len = inner[IPv6].plen - 20
712             self.assertEqual(payload_len, len(inner[Raw]))
713             size += payload_len
714         self.assertEqual(size, 65200*5)
715
716         #
717         # disable ipip6
718         #
719         self.ip4_via_ip6_tunnel.remove_vpp_config()
720         self.ip6_via_ip6_tunnel.remove_vpp_config()
721         self.ipip6.remove_vpp_config()
722
723         self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
724                                              enable_disable=0)
725
726     def test_gso_ipsec(self):
727         """ GSO IPSEC test """
728         #
729         # Send jumbo frame with gso enabled only on input interface and
730         # create IPIP tunnel on VPP pg0.
731         #
732
733         #
734         # enable ipip4
735         #
736         self.ipip4.add_vpp_config()
737         self.vapi.feature_gso_enable_disable(
738             sw_if_index=self.ipip4.sw_if_index, enable_disable=1)
739
740         # Add IPv4 routes via tunnel interface
741         self.ip4_via_ip4_tunnel = VppIpRoute(
742                 self, "172.16.10.0", 24,
743                 [VppRoutePath("0.0.0.0",
744                               self.ipip4.sw_if_index,
745                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
746         self.ip4_via_ip4_tunnel.add_vpp_config()
747
748         # IPSec config
749         self.ipv4_params = IPsecIPv4Params()
750         self.encryption_type = ESP
751         config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4)
752
753         self.tun_sa_in_v4 = VppIpsecSA(self, self.ipv4_params.vpp_tun_sa_id,
754                                        self.ipv4_params.vpp_tun_spi,
755                                        self.ipv4_params.auth_algo_vpp_id,
756                                        self.ipv4_params.auth_key,
757                                        self.ipv4_params.crypt_algo_vpp_id,
758                                        self.ipv4_params.crypt_key,
759                                        VppEnum.vl_api_ipsec_proto_t.
760                                        IPSEC_API_PROTO_ESP)
761         self.tun_sa_in_v4.add_vpp_config()
762
763         self.tun_sa_out_v4 = VppIpsecSA(self, self.ipv4_params.scapy_tun_sa_id,
764                                         self.ipv4_params.scapy_tun_spi,
765                                         self.ipv4_params.auth_algo_vpp_id,
766                                         self.ipv4_params.auth_key,
767                                         self.ipv4_params.crypt_algo_vpp_id,
768                                         self.ipv4_params.crypt_key,
769                                         VppEnum.vl_api_ipsec_proto_t.
770                                         IPSEC_API_PROTO_ESP)
771         self.tun_sa_out_v4.add_vpp_config()
772
773         self.tun_protect_v4 = VppIpsecTunProtect(self,
774                                                  self.ipip4,
775                                                  self.tun_sa_out_v4,
776                                                  [self.tun_sa_in_v4])
777
778         self.tun_protect_v4.add_vpp_config()
779
780         # Set interface up and enable IP on it
781         self.ipip4.admin_up()
782         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
783
784         #
785         # IPv4/IPv4 - IPSEC
786         #
787         ipsec44 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
788                    IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
789                    TCP(sport=1234, dport=1234) /
790                    Raw(b'\xa5' * 65200))
791
792         rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45)
793         size = 0
794         for rx in rxs:
795             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
796             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
797             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
798             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
799             self.assertEqual(rx[IP].proto, 50)  # ESP
800             self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
801             inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
802             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
803             self.assertEqual(inner[IP].dst, "172.16.10.3")
804             size += inner[IP].len - 20 - 20
805         self.assertEqual(size, 65200)
806
807         self.ip6_via_ip4_tunnel = VppIpRoute(
808                 self, "fd01:10::", 64,
809                 [VppRoutePath("::",
810                               self.ipip4.sw_if_index,
811                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
812         self.ip6_via_ip4_tunnel.add_vpp_config()
813         #
814         # IPv4/IPv6 - IPSEC
815         #
816         ipsec46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
817                    IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
818                    TCP(sport=1234, dport=1234) /
819                    Raw(b'\xa5' * 65200))
820
821         rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45)
822         size = 0
823         for rx in rxs:
824             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
825             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
826             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
827             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
828             self.assertEqual(rx[IP].proto, 50)  # ESP
829             self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
830             inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
831             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
832             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
833             size += inner[IPv6].plen - 20
834         self.assertEqual(size, 65200)
835
836         # disable IPSec
837         self.tun_protect_v4.remove_vpp_config()
838         self.tun_sa_in_v4.remove_vpp_config()
839         self.tun_sa_out_v4.remove_vpp_config()
840
841         #
842         # disable ipip4
843         #
844         self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index,
845                                              enable_disable=0)
846         self.ip4_via_ip4_tunnel.remove_vpp_config()
847         self.ip6_via_ip4_tunnel.remove_vpp_config()
848         self.ipip4.remove_vpp_config()
849
850         #
851         # enable ipip6
852         #
853         self.ipip6.add_vpp_config()
854         self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index,
855                                              enable_disable=1)
856
857         # Set interface up and enable IP on it
858         self.ipip6.admin_up()
859         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
860
861         # Add IPv4 routes via tunnel interface
862         self.ip4_via_ip6_tunnel = VppIpRoute(
863                 self, "172.16.10.0", 24,
864                 [VppRoutePath("0.0.0.0",
865                               self.ipip6.sw_if_index,
866                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
867         self.ip4_via_ip6_tunnel.add_vpp_config()
868
869         # IPSec config
870         self.ipv6_params = IPsecIPv6Params()
871         self.encryption_type = ESP
872         config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6)
873         self.tun_sa_in_v6 = VppIpsecSA(self, self.ipv6_params.vpp_tun_sa_id,
874                                        self.ipv6_params.vpp_tun_spi,
875                                        self.ipv6_params.auth_algo_vpp_id,
876                                        self.ipv6_params.auth_key,
877                                        self.ipv6_params.crypt_algo_vpp_id,
878                                        self.ipv6_params.crypt_key,
879                                        VppEnum.vl_api_ipsec_proto_t.
880                                        IPSEC_API_PROTO_ESP)
881         self.tun_sa_in_v6.add_vpp_config()
882
883         self.tun_sa_out_v6 = VppIpsecSA(self, self.ipv6_params.scapy_tun_sa_id,
884                                         self.ipv6_params.scapy_tun_spi,
885                                         self.ipv6_params.auth_algo_vpp_id,
886                                         self.ipv6_params.auth_key,
887                                         self.ipv6_params.crypt_algo_vpp_id,
888                                         self.ipv6_params.crypt_key,
889                                         VppEnum.vl_api_ipsec_proto_t.
890                                         IPSEC_API_PROTO_ESP)
891         self.tun_sa_out_v6.add_vpp_config()
892
893         self.tun_protect_v6 = VppIpsecTunProtect(self,
894                                                  self.ipip6,
895                                                  self.tun_sa_out_v6,
896                                                  [self.tun_sa_in_v6])
897
898         self.tun_protect_v6.add_vpp_config()
899
900         #
901         # IPv6/IPv4 - IPSEC
902         #
903         ipsec64 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
904                    IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
905                    TCP(sport=1234, dport=1234) /
906                    Raw(b'\xa5' * 65200))
907
908         rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45)
909         size = 0
910         for rx in rxs:
911             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
912             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
913             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
914             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
915             self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
916             self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
917             inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
918             self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
919             self.assertEqual(inner[IP].dst, "172.16.10.3")
920             size += inner[IP].len - 20 - 20
921         self.assertEqual(size, 65200)
922
923         self.ip6_via_ip6_tunnel = VppIpRoute(
924                 self, "fd01:10::", 64,
925                 [VppRoutePath("::",
926                               self.ipip6.sw_if_index,
927                               proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
928         self.ip6_via_ip6_tunnel.add_vpp_config()
929
930         #
931         # IPv6/IPv6 - IPSEC
932         #
933         ipsec66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
934                    IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
935                    TCP(sport=1234, dport=1234) /
936                    Raw(b'\xa5' * 65200))
937
938         rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45)
939         size = 0
940         for rx in rxs:
941             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
942             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
943             self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
944             self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
945             self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
946             self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
947             inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
948             self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
949             self.assertEqual(inner[IPv6].dst, "fd01:10::3")
950             size += inner[IPv6].plen - 20
951         self.assertEqual(size, 65200)
952
953         # disable IPSec
954         self.tun_protect_v6.remove_vpp_config()
955         self.tun_sa_in_v6.remove_vpp_config()
956         self.tun_sa_out_v6.remove_vpp_config()
957
958         #
959         # disable ipip6
960         #
961         self.ip4_via_ip6_tunnel.remove_vpp_config()
962         self.ip6_via_ip6_tunnel.remove_vpp_config()
963         self.ipip6.remove_vpp_config()
964
965         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
966                                              enable_disable=0)
967
968 if __name__ == '__main__':
969     unittest.main(testRunner=VppTestRunner)