gso: use the header offsets from buffer metadata
[vpp.git] / test / test_gre.py
1 #!/usr/bin/env python3
2
3 import unittest
4
5 import scapy.compat
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, Dot1Q, GRE
8 from scapy.layers.inet import IP, UDP
9 from scapy.layers.inet6 import IPv6
10 from scapy.volatile import RandMAC, RandIP
11
12 from framework import VppTestCase
13 from asfframework import VppTestRunner, tag_fixme_vpp_workers
14 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
15 from vpp_gre_interface import VppGreInterface
16 from vpp_teib import VppTeib
17 from vpp_ip import DpoProto
18 from vpp_ip_route import (
19     VppIpRoute,
20     VppRoutePath,
21     VppIpTable,
22     VppMplsLabel,
23 )
24 from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
25 from util import ppp, ppc
26 from vpp_papi import VppEnum
27
28
29 @tag_fixme_vpp_workers
30 class TestGREInputNodes(VppTestCase):
31     """GRE Input Nodes Test Case"""
32
33     def setUp(self):
34         super(TestGREInputNodes, self).setUp()
35
36         # create 3 pg interfaces - set one in a non-default table.
37         self.create_pg_interfaces(range(1))
38
39         for i in self.pg_interfaces:
40             i.admin_up()
41             i.config_ip4()
42
43     def tearDown(self):
44         for i in self.pg_interfaces:
45             i.unconfig_ip4()
46             i.admin_down()
47         super(TestGREInputNodes, self).tearDown()
48
49     def test_gre_input_node(self):
50         """GRE gre input nodes not registerd unless configured"""
51         pkt = (
52             Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
53             / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
54             / GRE()
55         )
56
57         self.pg0.add_stream(pkt)
58         self.pg_start()
59         # no tunnel created, gre-input not registered
60         err = self.statistics.get_counter("/err/ip4-local/unknown_protocol")[0]
61         self.assertEqual(err, 1)
62         err_count = err
63
64         # create gre tunnel
65         gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
66         gre_if.add_vpp_config()
67
68         self.pg0.add_stream(pkt)
69         self.pg_start()
70         # tunnel created, gre-input registered
71         err = self.statistics.get_counter("/err/ip4-local/unknown_protocol")[0]
72         # expect no new errors
73         self.assertEqual(err, err_count)
74
75
76 class TestGRE(VppTestCase):
77     """GRE Test Case"""
78
79     @classmethod
80     def setUpClass(cls):
81         super(TestGRE, cls).setUpClass()
82
83     @classmethod
84     def tearDownClass(cls):
85         super(TestGRE, cls).tearDownClass()
86
87     def setUp(self):
88         super(TestGRE, self).setUp()
89
90         # create 3 pg interfaces - set one in a non-default table.
91         self.create_pg_interfaces(range(5))
92
93         self.tbl = VppIpTable(self, 1)
94         self.tbl.add_vpp_config()
95         self.pg1.set_table_ip4(1)
96
97         for i in self.pg_interfaces:
98             i.admin_up()
99
100         self.pg0.config_ip4()
101         self.pg0.resolve_arp()
102         self.pg1.config_ip4()
103         self.pg1.resolve_arp()
104         self.pg2.config_ip6()
105         self.pg2.resolve_ndp()
106         self.pg3.config_ip4()
107         self.pg3.resolve_arp()
108         self.pg4.config_ip4()
109         self.pg4.resolve_arp()
110
111     def tearDown(self):
112         for i in self.pg_interfaces:
113             i.unconfig_ip4()
114             i.unconfig_ip6()
115             i.admin_down()
116         self.pg1.set_table_ip4(0)
117         super(TestGRE, self).tearDown()
118
119     def create_stream_ip4(self, src_if, src_ip, dst_ip, dscp=0, ecn=0):
120         pkts = []
121         tos = (dscp << 2) | ecn
122         for i in range(0, 257):
123             info = self.create_packet_info(src_if, src_if)
124             payload = self.info_to_payload(info)
125             p = (
126                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
127                 / IP(src=src_ip, dst=dst_ip, tos=tos)
128                 / UDP(sport=1234, dport=1234)
129                 / Raw(payload)
130             )
131             info.data = p.copy()
132             pkts.append(p)
133         return pkts
134
135     def create_stream_ip6(self, src_if, src_ip, dst_ip, dscp=0, ecn=0):
136         pkts = []
137         tc = (dscp << 2) | ecn
138         for i in range(0, 257):
139             info = self.create_packet_info(src_if, src_if)
140             payload = self.info_to_payload(info)
141             p = (
142                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
143                 / IPv6(src=src_ip, dst=dst_ip, tc=tc)
144                 / UDP(sport=1234, dport=1234)
145                 / Raw(payload)
146             )
147             info.data = p.copy()
148             pkts.append(p)
149         return pkts
150
151     def create_tunnel_stream_4o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
152         pkts = []
153         for i in range(0, 257):
154             info = self.create_packet_info(src_if, src_if)
155             payload = self.info_to_payload(info)
156             p = (
157                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
158                 / IP(src=tunnel_src, dst=tunnel_dst)
159                 / GRE()
160                 / IP(src=src_ip, dst=dst_ip)
161                 / UDP(sport=1234, dport=1234)
162                 / Raw(payload)
163             )
164             info.data = p.copy()
165             pkts.append(p)
166         return pkts
167
168     def create_tunnel_stream_6o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
169         pkts = []
170         for i in range(0, 257):
171             info = self.create_packet_info(src_if, src_if)
172             payload = self.info_to_payload(info)
173             p = (
174                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
175                 / IP(src=tunnel_src, dst=tunnel_dst)
176                 / GRE()
177                 / IPv6(src=src_ip, dst=dst_ip)
178                 / UDP(sport=1234, dport=1234)
179                 / Raw(payload)
180             )
181             info.data = p.copy()
182             pkts.append(p)
183         return pkts
184
185     def create_tunnel_stream_6o6(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
186         pkts = []
187         for i in range(0, 257):
188             info = self.create_packet_info(src_if, src_if)
189             payload = self.info_to_payload(info)
190             p = (
191                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
192                 / IPv6(src=tunnel_src, dst=tunnel_dst)
193                 / GRE()
194                 / IPv6(src=src_ip, dst=dst_ip)
195                 / UDP(sport=1234, dport=1234)
196                 / Raw(payload)
197             )
198             info.data = p.copy()
199             pkts.append(p)
200         return pkts
201
202     def create_tunnel_stream_l2o4(self, src_if, tunnel_src, tunnel_dst):
203         pkts = []
204         for i in range(0, 257):
205             info = self.create_packet_info(src_if, src_if)
206             payload = self.info_to_payload(info)
207             p = (
208                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
209                 / IP(src=tunnel_src, dst=tunnel_dst)
210                 / GRE()
211                 / Ether(dst=RandMAC("*:*:*:*:*:*"), src=RandMAC("*:*:*:*:*:*"))
212                 / IP(src=scapy.compat.raw(RandIP()), dst=scapy.compat.raw(RandIP()))
213                 / UDP(sport=1234, dport=1234)
214                 / Raw(payload)
215             )
216             info.data = p.copy()
217             pkts.append(p)
218         return pkts
219
220     def create_tunnel_stream_vlano4(self, src_if, tunnel_src, tunnel_dst, vlan):
221         pkts = []
222         for i in range(0, 257):
223             info = self.create_packet_info(src_if, src_if)
224             payload = self.info_to_payload(info)
225             p = (
226                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
227                 / IP(src=tunnel_src, dst=tunnel_dst)
228                 / GRE()
229                 / Ether(dst=RandMAC("*:*:*:*:*:*"), src=RandMAC("*:*:*:*:*:*"))
230                 / Dot1Q(vlan=vlan)
231                 / IP(src=scapy.compat.raw(RandIP()), dst=scapy.compat.raw(RandIP()))
232                 / UDP(sport=1234, dport=1234)
233                 / Raw(payload)
234             )
235             info.data = p.copy()
236             pkts.append(p)
237         return pkts
238
239     def verify_tunneled_4o4(
240         self, src_if, capture, sent, tunnel_src, tunnel_dst, dscp=0, ecn=0
241     ):
242         self.assertEqual(len(capture), len(sent))
243         tos = (dscp << 2) | ecn
244
245         for i in range(len(capture)):
246             try:
247                 tx = sent[i]
248                 rx = capture[i]
249
250                 tx_ip = tx[IP]
251                 rx_ip = rx[IP]
252
253                 self.assertEqual(rx_ip.src, tunnel_src)
254                 self.assertEqual(rx_ip.dst, tunnel_dst)
255                 self.assertEqual(rx_ip.tos, tos)
256                 self.assertEqual(rx_ip.len, len(rx_ip))
257
258                 rx_gre = rx[GRE]
259                 rx_ip = rx_gre[IP]
260
261                 self.assertEqual(rx_ip.src, tx_ip.src)
262                 self.assertEqual(rx_ip.dst, tx_ip.dst)
263                 # IP processing post pop has decremented the TTL
264                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
265
266             except:
267                 self.logger.error(ppp("Rx:", rx))
268                 self.logger.error(ppp("Tx:", tx))
269                 raise
270
271     def verify_tunneled_6o6(
272         self, src_if, capture, sent, tunnel_src, tunnel_dst, dscp=0, ecn=0
273     ):
274         self.assertEqual(len(capture), len(sent))
275         tc = (dscp << 2) | ecn
276
277         for i in range(len(capture)):
278             try:
279                 tx = sent[i]
280                 rx = capture[i]
281
282                 tx_ip = tx[IPv6]
283                 rx_ip = rx[IPv6]
284
285                 self.assertEqual(rx_ip.src, tunnel_src)
286                 self.assertEqual(rx_ip.dst, tunnel_dst)
287                 self.assertEqual(rx_ip.tc, tc)
288
289                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
290
291                 self.assertEqual(rx_ip.plen, len(rx_gre))
292
293                 rx_ip = rx_gre[IPv6]
294
295                 self.assertEqual(rx_ip.src, tx_ip.src)
296                 self.assertEqual(rx_ip.dst, tx_ip.dst)
297
298             except:
299                 self.logger.error(ppp("Rx:", rx))
300                 self.logger.error(ppp("Tx:", tx))
301                 raise
302
303     def verify_tunneled_4o6(self, src_if, capture, sent, tunnel_src, tunnel_dst):
304         self.assertEqual(len(capture), len(sent))
305
306         for i in range(len(capture)):
307             try:
308                 tx = sent[i]
309                 rx = capture[i]
310
311                 rx_ip = rx[IPv6]
312
313                 self.assertEqual(rx_ip.src, tunnel_src)
314                 self.assertEqual(rx_ip.dst, tunnel_dst)
315
316                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
317
318                 self.assertEqual(rx_ip.plen, len(rx_gre))
319
320                 tx_ip = tx[IP]
321                 rx_ip = rx_gre[IP]
322
323                 self.assertEqual(rx_ip.src, tx_ip.src)
324                 self.assertEqual(rx_ip.dst, tx_ip.dst)
325
326             except:
327                 self.logger.error(ppp("Rx:", rx))
328                 self.logger.error(ppp("Tx:", tx))
329                 raise
330
331     def verify_tunneled_6o4(self, src_if, capture, sent, tunnel_src, tunnel_dst):
332         self.assertEqual(len(capture), len(sent))
333
334         for i in range(len(capture)):
335             try:
336                 tx = sent[i]
337                 rx = capture[i]
338
339                 rx_ip = rx[IP]
340
341                 self.assertEqual(rx_ip.src, tunnel_src)
342                 self.assertEqual(rx_ip.dst, tunnel_dst)
343                 self.assertEqual(rx_ip.len, len(rx_ip))
344
345                 rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload))
346                 rx_ip = rx_gre[IPv6]
347                 tx_ip = tx[IPv6]
348
349                 self.assertEqual(rx_ip.src, tx_ip.src)
350                 self.assertEqual(rx_ip.dst, tx_ip.dst)
351
352             except:
353                 self.logger.error(ppp("Rx:", rx))
354                 self.logger.error(ppp("Tx:", tx))
355                 raise
356
357     def verify_tunneled_l2o4(self, src_if, capture, sent, tunnel_src, tunnel_dst):
358         self.assertEqual(len(capture), len(sent))
359
360         for i in range(len(capture)):
361             try:
362                 tx = sent[i]
363                 rx = capture[i]
364
365                 tx_ip = tx[IP]
366                 rx_ip = rx[IP]
367
368                 self.assertEqual(rx_ip.src, tunnel_src)
369                 self.assertEqual(rx_ip.dst, tunnel_dst)
370                 self.assertEqual(rx_ip.len, len(rx_ip))
371
372                 rx_gre = rx[GRE]
373                 rx_l2 = rx_gre[Ether]
374                 rx_ip = rx_l2[IP]
375                 tx_gre = tx[GRE]
376                 tx_l2 = tx_gre[Ether]
377                 tx_ip = tx_l2[IP]
378
379                 self.assertEqual(rx_ip.src, tx_ip.src)
380                 self.assertEqual(rx_ip.dst, tx_ip.dst)
381                 # bridged, not L3 forwarded, so no TTL decrement
382                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
383
384             except:
385                 self.logger.error(ppp("Rx:", rx))
386                 self.logger.error(ppp("Tx:", tx))
387                 raise
388
389     def verify_tunneled_vlano4(
390         self, src_if, capture, sent, tunnel_src, tunnel_dst, vlan
391     ):
392         try:
393             self.assertEqual(len(capture), len(sent))
394         except:
395             ppc("Unexpected packets captured:", capture)
396             raise
397
398         for i in range(len(capture)):
399             try:
400                 tx = sent[i]
401                 rx = capture[i]
402
403                 tx_ip = tx[IP]
404                 rx_ip = rx[IP]
405
406                 self.assertEqual(rx_ip.src, tunnel_src)
407                 self.assertEqual(rx_ip.dst, tunnel_dst)
408
409                 rx_gre = rx[GRE]
410                 rx_l2 = rx_gre[Ether]
411                 rx_vlan = rx_l2[Dot1Q]
412                 rx_ip = rx_l2[IP]
413
414                 self.assertEqual(rx_vlan.vlan, vlan)
415
416                 tx_gre = tx[GRE]
417                 tx_l2 = tx_gre[Ether]
418                 tx_ip = tx_l2[IP]
419
420                 self.assertEqual(rx_ip.src, tx_ip.src)
421                 self.assertEqual(rx_ip.dst, tx_ip.dst)
422                 # bridged, not L3 forwarded, so no TTL decrement
423                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
424
425             except:
426                 self.logger.error(ppp("Rx:", rx))
427                 self.logger.error(ppp("Tx:", tx))
428                 raise
429
430     def verify_decapped_4o4(self, src_if, capture, sent):
431         self.assertEqual(len(capture), len(sent))
432
433         for i in range(len(capture)):
434             try:
435                 tx = sent[i]
436                 rx = capture[i]
437
438                 tx_ip = tx[IP]
439                 rx_ip = rx[IP]
440                 tx_gre = tx[GRE]
441                 tx_ip = tx_gre[IP]
442
443                 self.assertEqual(rx_ip.src, tx_ip.src)
444                 self.assertEqual(rx_ip.dst, tx_ip.dst)
445                 # IP processing post pop has decremented the TTL
446                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
447
448             except:
449                 self.logger.error(ppp("Rx:", rx))
450                 self.logger.error(ppp("Tx:", tx))
451                 raise
452
453     def verify_decapped_6o4(self, src_if, capture, sent):
454         self.assertEqual(len(capture), len(sent))
455
456         for i in range(len(capture)):
457             try:
458                 tx = sent[i]
459                 rx = capture[i]
460
461                 tx_ip = tx[IP]
462                 rx_ip = rx[IPv6]
463                 tx_gre = tx[GRE]
464                 tx_ip = tx_gre[IPv6]
465
466                 self.assertEqual(rx_ip.src, tx_ip.src)
467                 self.assertEqual(rx_ip.dst, tx_ip.dst)
468                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
469
470             except:
471                 self.logger.error(ppp("Rx:", rx))
472                 self.logger.error(ppp("Tx:", tx))
473                 raise
474
475     def verify_decapped_6o6(self, src_if, capture, sent):
476         self.assertEqual(len(capture), len(sent))
477
478         for i in range(len(capture)):
479             try:
480                 tx = sent[i]
481                 rx = capture[i]
482
483                 tx_ip = tx[IPv6]
484                 rx_ip = rx[IPv6]
485                 tx_gre = tx[GRE]
486                 tx_ip = tx_gre[IPv6]
487
488                 self.assertEqual(rx_ip.src, tx_ip.src)
489                 self.assertEqual(rx_ip.dst, tx_ip.dst)
490                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
491
492             except:
493                 self.logger.error(ppp("Rx:", rx))
494                 self.logger.error(ppp("Tx:", tx))
495                 raise
496
497     def test_gre(self):
498         """GRE IPv4 tunnel Tests"""
499
500         #
501         # Create an L3 GRE tunnel.
502         #  - set it admin up
503         #  - assign an IP Addres
504         #  - Add a route via the tunnel
505         #
506         gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
507         gre_if.add_vpp_config()
508
509         #
510         # The double create (create the same tunnel twice) should fail,
511         # and we should still be able to use the original
512         #
513         try:
514             gre_if.add_vpp_config()
515         except Exception:
516             pass
517         else:
518             self.fail("Double GRE tunnel add does not fail")
519
520         gre_if.admin_up()
521         gre_if.config_ip4()
522
523         route_via_tun = VppIpRoute(
524             self, "4.4.4.4", 32, [VppRoutePath("0.0.0.0", gre_if.sw_if_index)]
525         )
526
527         route_via_tun.add_vpp_config()
528
529         #
530         # Send a packet stream that is routed into the tunnel
531         #  - they are all dropped since the tunnel's destintation IP
532         #    is unresolved - or resolves via the default route - which
533         #    which is a drop.
534         #
535         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
536
537         self.send_and_assert_no_replies(self.pg0, tx)
538
539         #
540         # Add a route that resolves the tunnel's destination
541         #
542         route_tun_dst = VppIpRoute(
543             self,
544             "1.1.1.2",
545             32,
546             [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index)],
547         )
548         route_tun_dst.add_vpp_config()
549
550         #
551         # Send a packet stream that is routed into the tunnel
552         #  - packets are GRE encapped
553         #
554         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
555         rx = self.send_and_expect(self.pg0, tx, self.pg0)
556         self.verify_tunneled_4o4(self.pg0, rx, tx, self.pg0.local_ip4, "1.1.1.2")
557
558         #
559         # Send tunneled packets that match the created tunnel and
560         # are decapped and forwarded
561         #
562         tx = self.create_tunnel_stream_4o4(
563             self.pg0,
564             "1.1.1.2",
565             self.pg0.local_ip4,
566             self.pg0.local_ip4,
567             self.pg0.remote_ip4,
568         )
569         rx = self.send_and_expect(self.pg0, tx, self.pg0)
570         self.verify_decapped_4o4(self.pg0, rx, tx)
571
572         #
573         # Send tunneled packets that do not match the tunnel's src
574         #
575         self.vapi.cli("clear trace")
576         tx = self.create_tunnel_stream_4o4(
577             self.pg0,
578             "1.1.1.3",
579             self.pg0.local_ip4,
580             self.pg0.local_ip4,
581             self.pg0.remote_ip4,
582         )
583         self.send_and_assert_no_replies(
584             self.pg0, tx, remark="GRE packets forwarded despite no SRC address match"
585         )
586
587         #
588         # Configure IPv6 on the PG interface so we can route IPv6
589         # packets
590         #
591         self.pg0.config_ip6()
592         self.pg0.resolve_ndp()
593
594         #
595         # Send IPv6 tunnel encapslated packets
596         #  - dropped since IPv6 is not enabled on the tunnel
597         #
598         tx = self.create_tunnel_stream_6o4(
599             self.pg0,
600             "1.1.1.2",
601             self.pg0.local_ip4,
602             self.pg0.local_ip6,
603             self.pg0.remote_ip6,
604         )
605         self.send_and_assert_no_replies(
606             self.pg0,
607             tx,
608             "IPv6 GRE packets forwarded despite IPv6 not enabled on tunnel",
609         )
610
611         #
612         # Enable IPv6 on the tunnel
613         #
614         gre_if.config_ip6()
615
616         #
617         # Send IPv6 tunnel encapslated packets
618         #  - forwarded since IPv6 is enabled on the tunnel
619         #
620         tx = self.create_tunnel_stream_6o4(
621             self.pg0,
622             "1.1.1.2",
623             self.pg0.local_ip4,
624             self.pg0.local_ip6,
625             self.pg0.remote_ip6,
626         )
627         rx = self.send_and_expect(self.pg0, tx, self.pg0)
628         self.verify_decapped_6o4(self.pg0, rx, tx)
629
630         #
631         # Send v6 packets for v4 encap
632         #
633         route6_via_tun = VppIpRoute(
634             self,
635             "2001::1",
636             128,
637             [VppRoutePath("::", gre_if.sw_if_index, proto=DpoProto.DPO_PROTO_IP6)],
638         )
639         route6_via_tun.add_vpp_config()
640
641         tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
642         rx = self.send_and_expect(self.pg0, tx, self.pg0)
643
644         self.verify_tunneled_6o4(self.pg0, rx, tx, self.pg0.local_ip4, "1.1.1.2")
645
646         #
647         # add a labelled route through the tunnel
648         #
649         label_via_tun = VppIpRoute(
650             self,
651             "5.4.3.2",
652             32,
653             [VppRoutePath("0.0.0.0", gre_if.sw_if_index, labels=[VppMplsLabel(33)])],
654         )
655         label_via_tun.add_vpp_config()
656
657         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.2")
658         rx = self.send_and_expect(self.pg0, tx, self.pg0)
659         self.verify_tunneled_4o4(self.pg0, rx, tx, self.pg0.local_ip4, "1.1.1.2")
660
661         #
662         # an MPLS tunnel over the GRE tunnel add a route through
663         # the mpls tunnel
664         #
665         mpls_tun = VppMPLSTunnelInterface(
666             self,
667             [
668                 VppRoutePath(
669                     "0.0.0.0",
670                     gre_if.sw_if_index,
671                     labels=[VppMplsLabel(44), VppMplsLabel(46)],
672                 )
673             ],
674         )
675         mpls_tun.add_vpp_config()
676         mpls_tun.admin_up()
677
678         label_via_mpls = VppIpRoute(
679             self,
680             "5.4.3.1",
681             32,
682             [VppRoutePath("0.0.0.0", mpls_tun.sw_if_index, labels=[VppMplsLabel(33)])],
683         )
684         label_via_mpls.add_vpp_config()
685
686         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.1")
687         rx = self.send_and_expect(self.pg0, tx, self.pg0)
688         self.verify_tunneled_4o4(self.pg0, rx, tx, self.pg0.local_ip4, "1.1.1.2")
689
690         mpls_tun_l2 = VppMPLSTunnelInterface(
691             self,
692             [
693                 VppRoutePath(
694                     "0.0.0.0",
695                     gre_if.sw_if_index,
696                     labels=[VppMplsLabel(44), VppMplsLabel(46)],
697                 )
698             ],
699             is_l2=1,
700         )
701         mpls_tun_l2.add_vpp_config()
702         mpls_tun_l2.admin_up()
703
704         #
705         # test case cleanup
706         #
707         route_tun_dst.remove_vpp_config()
708         route_via_tun.remove_vpp_config()
709         route6_via_tun.remove_vpp_config()
710         label_via_mpls.remove_vpp_config()
711         label_via_tun.remove_vpp_config()
712         mpls_tun.remove_vpp_config()
713         mpls_tun_l2.remove_vpp_config()
714         gre_if.remove_vpp_config()
715
716         self.pg0.unconfig_ip6()
717
718     def test_gre6(self):
719         """GRE IPv6 tunnel Tests"""
720
721         self.pg1.config_ip6()
722         self.pg1.resolve_ndp()
723
724         #
725         # Create an L3 GRE tunnel.
726         #  - set it admin up
727         #  - assign an IP Address
728         #  - Add a route via the tunnel
729         #
730         gre_if = VppGreInterface(self, self.pg2.local_ip6, "1002::1")
731         gre_if.add_vpp_config()
732         gre_if.admin_up()
733         gre_if.config_ip6()
734
735         route_via_tun = VppIpRoute(
736             self, "4004::1", 128, [VppRoutePath("0::0", gre_if.sw_if_index)]
737         )
738
739         route_via_tun.add_vpp_config()
740
741         #
742         # Send a packet stream that is routed into the tunnel
743         #  - they are all dropped since the tunnel's destintation IP
744         #    is unresolved - or resolves via the default route - which
745         #    which is a drop.
746         #
747         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
748         self.send_and_assert_no_replies(
749             self.pg2, tx, "GRE packets forwarded without DIP resolved"
750         )
751
752         #
753         # Add a route that resolves the tunnel's destination
754         #
755         route_tun_dst = VppIpRoute(
756             self,
757             "1002::1",
758             128,
759             [VppRoutePath(self.pg2.remote_ip6, self.pg2.sw_if_index)],
760         )
761         route_tun_dst.add_vpp_config()
762
763         #
764         # Send a packet stream that is routed into the tunnel
765         #  - packets are GRE encapped
766         #
767         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
768         rx = self.send_and_expect(self.pg2, tx, self.pg2)
769         self.verify_tunneled_6o6(self.pg2, rx, tx, self.pg2.local_ip6, "1002::1")
770
771         #
772         # Test decap. decapped packets go out pg1
773         #
774         tx = self.create_tunnel_stream_6o6(
775             self.pg2, "1002::1", self.pg2.local_ip6, "2001::1", self.pg1.remote_ip6
776         )
777         rx = self.send_and_expect(self.pg2, tx, self.pg1)
778
779         #
780         # RX'd packet is UDP over IPv6, test the GRE header is gone.
781         #
782         self.assertFalse(rx[0].haslayer(GRE))
783         self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
784
785         #
786         # Send v4 over v6
787         #
788         route4_via_tun = VppIpRoute(
789             self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", gre_if.sw_if_index)]
790         )
791         route4_via_tun.add_vpp_config()
792
793         tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
794         rx = self.send_and_expect(self.pg0, tx, self.pg2)
795
796         self.verify_tunneled_4o6(self.pg0, rx, tx, self.pg2.local_ip6, "1002::1")
797
798         #
799         # test case cleanup
800         #
801         route_tun_dst.remove_vpp_config()
802         route_via_tun.remove_vpp_config()
803         route4_via_tun.remove_vpp_config()
804         gre_if.remove_vpp_config()
805
806         self.pg2.unconfig_ip6()
807         self.pg1.unconfig_ip6()
808
809     def test_gre_vrf(self):
810         """GRE tunnel VRF Tests"""
811
812         e = VppEnum.vl_api_tunnel_encap_decap_flags_t
813
814         #
815         # Create an L3 GRE tunnel whose destination is in the non-default
816         # table. The underlay is thus non-default - the overlay is still
817         # the default.
818         #  - set it admin up
819         #  - assign an IP Addres
820         #
821         gre_if = VppGreInterface(
822             self,
823             self.pg1.local_ip4,
824             "2.2.2.2",
825             outer_table_id=1,
826             flags=(
827                 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
828                 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
829             ),
830         )
831
832         gre_if.add_vpp_config()
833         gre_if.admin_up()
834         gre_if.config_ip4()
835
836         #
837         # Add a route via the tunnel - in the overlay
838         #
839         route_via_tun = VppIpRoute(
840             self, "9.9.9.9", 32, [VppRoutePath("0.0.0.0", gre_if.sw_if_index)]
841         )
842         route_via_tun.add_vpp_config()
843
844         #
845         # Add a route that resolves the tunnel's destination - in the
846         # underlay table
847         #
848         route_tun_dst = VppIpRoute(
849             self,
850             "2.2.2.2",
851             32,
852             table_id=1,
853             paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
854         )
855         route_tun_dst.add_vpp_config()
856
857         #
858         # Send a packet stream that is routed into the tunnel
859         # packets are sent in on pg0 which is in the default table
860         #  - packets are GRE encapped
861         #
862         self.vapi.cli("clear trace")
863         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9", dscp=5, ecn=3)
864         rx = self.send_and_expect(self.pg0, tx, self.pg1)
865         self.verify_tunneled_4o4(
866             self.pg1, rx, tx, self.pg1.local_ip4, "2.2.2.2", dscp=5, ecn=3
867         )
868
869         #
870         # Send tunneled packets that match the created tunnel and
871         # are decapped and forwarded. This tests the decap lookup
872         # does not happen in the encap table
873         #
874         self.vapi.cli("clear trace")
875         tx = self.create_tunnel_stream_4o4(
876             self.pg1,
877             "2.2.2.2",
878             self.pg1.local_ip4,
879             self.pg0.local_ip4,
880             self.pg0.remote_ip4,
881         )
882         rx = self.send_and_expect(self.pg1, tx, self.pg0)
883         self.verify_decapped_4o4(self.pg0, rx, tx)
884
885         #
886         # Send tunneled packets that match the created tunnel
887         # but arrive on an interface that is not in the tunnel's
888         # encap VRF, these are dropped.
889         # IP enable the interface so they aren't dropped due to
890         # IP not being enabled.
891         #
892         self.pg2.config_ip4()
893         self.vapi.cli("clear trace")
894         tx = self.create_tunnel_stream_4o4(
895             self.pg2,
896             "2.2.2.2",
897             self.pg1.local_ip4,
898             self.pg0.local_ip4,
899             self.pg0.remote_ip4,
900         )
901         rx = self.send_and_assert_no_replies(
902             self.pg2, tx, "GRE decap packets in wrong VRF"
903         )
904
905         self.pg2.unconfig_ip4()
906
907         #
908         # test case cleanup
909         #
910         route_tun_dst.remove_vpp_config()
911         route_via_tun.remove_vpp_config()
912         gre_if.remove_vpp_config()
913
914     def test_gre_l2(self):
915         """GRE tunnel L2 Tests"""
916
917         #
918         # Add routes to resolve the tunnel destinations
919         #
920         route_tun1_dst = VppIpRoute(
921             self,
922             "2.2.2.2",
923             32,
924             [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index)],
925         )
926         route_tun2_dst = VppIpRoute(
927             self,
928             "2.2.2.3",
929             32,
930             [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index)],
931         )
932
933         route_tun1_dst.add_vpp_config()
934         route_tun2_dst.add_vpp_config()
935
936         #
937         # Create 2 L2 GRE tunnels and x-connect them
938         #
939         gre_if1 = VppGreInterface(
940             self,
941             self.pg0.local_ip4,
942             "2.2.2.2",
943             type=(VppEnum.vl_api_gre_tunnel_type_t.GRE_API_TUNNEL_TYPE_TEB),
944         )
945         gre_if2 = VppGreInterface(
946             self,
947             self.pg0.local_ip4,
948             "2.2.2.3",
949             type=(VppEnum.vl_api_gre_tunnel_type_t.GRE_API_TUNNEL_TYPE_TEB),
950         )
951         gre_if1.add_vpp_config()
952         gre_if2.add_vpp_config()
953
954         gre_if1.admin_up()
955         gre_if2.admin_up()
956
957         self.vapi.sw_interface_set_l2_xconnect(
958             gre_if1.sw_if_index, gre_if2.sw_if_index, enable=1
959         )
960         self.vapi.sw_interface_set_l2_xconnect(
961             gre_if2.sw_if_index, gre_if1.sw_if_index, enable=1
962         )
963
964         #
965         # Send in tunnel encapped L2. expect out tunnel encapped L2
966         # in both directions
967         #
968         tx = self.create_tunnel_stream_l2o4(self.pg0, "2.2.2.2", self.pg0.local_ip4)
969         rx = self.send_and_expect(self.pg0, tx, self.pg0)
970         self.verify_tunneled_l2o4(self.pg0, rx, tx, self.pg0.local_ip4, "2.2.2.3")
971
972         tx = self.create_tunnel_stream_l2o4(self.pg0, "2.2.2.3", self.pg0.local_ip4)
973         rx = self.send_and_expect(self.pg0, tx, self.pg0)
974         self.verify_tunneled_l2o4(self.pg0, rx, tx, self.pg0.local_ip4, "2.2.2.2")
975
976         self.vapi.sw_interface_set_l2_xconnect(
977             gre_if1.sw_if_index, gre_if2.sw_if_index, enable=0
978         )
979         self.vapi.sw_interface_set_l2_xconnect(
980             gre_if2.sw_if_index, gre_if1.sw_if_index, enable=0
981         )
982
983         #
984         # Create a VLAN sub-interfaces on the GRE TEB interfaces
985         # then x-connect them
986         #
987         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
988         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
989
990         # gre_if_11.add_vpp_config()
991         # gre_if_12.add_vpp_config()
992
993         gre_if_11.admin_up()
994         gre_if_12.admin_up()
995
996         self.vapi.sw_interface_set_l2_xconnect(
997             gre_if_11.sw_if_index, gre_if_12.sw_if_index, enable=1
998         )
999         self.vapi.sw_interface_set_l2_xconnect(
1000             gre_if_12.sw_if_index, gre_if_11.sw_if_index, enable=1
1001         )
1002
1003         #
1004         # Configure both to pop thier respective VLAN tags,
1005         # so that during the x-coonect they will subsequently push
1006         #
1007         self.vapi.l2_interface_vlan_tag_rewrite(
1008             sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=12
1009         )
1010         self.vapi.l2_interface_vlan_tag_rewrite(
1011             sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=11
1012         )
1013
1014         #
1015         # Send traffic in both directiond - expect the VLAN tags to
1016         # be swapped.
1017         #
1018         tx = self.create_tunnel_stream_vlano4(
1019             self.pg0, "2.2.2.2", self.pg0.local_ip4, 11
1020         )
1021         rx = self.send_and_expect(self.pg0, tx, self.pg0)
1022         self.verify_tunneled_vlano4(self.pg0, rx, tx, self.pg0.local_ip4, "2.2.2.3", 12)
1023
1024         tx = self.create_tunnel_stream_vlano4(
1025             self.pg0, "2.2.2.3", self.pg0.local_ip4, 12
1026         )
1027         rx = self.send_and_expect(self.pg0, tx, self.pg0)
1028         self.verify_tunneled_vlano4(self.pg0, rx, tx, self.pg0.local_ip4, "2.2.2.2", 11)
1029
1030         #
1031         # Cleanup Test resources
1032         #
1033         gre_if_11.remove_vpp_config()
1034         gre_if_12.remove_vpp_config()
1035         gre_if1.remove_vpp_config()
1036         gre_if2.remove_vpp_config()
1037         route_tun1_dst.add_vpp_config()
1038         route_tun2_dst.add_vpp_config()
1039
1040     def test_gre_loop(self):
1041         """GRE tunnel loop Tests"""
1042
1043         #
1044         # Create an L3 GRE tunnel.
1045         #  - set it admin up
1046         #  - assign an IP Addres
1047         #
1048         gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
1049         gre_if.add_vpp_config()
1050         gre_if.admin_up()
1051         gre_if.config_ip4()
1052
1053         #
1054         # add a route to the tunnel's destination that points
1055         # through the tunnel, hence forming a loop in the forwarding
1056         # graph
1057         #
1058         route_dst = VppIpRoute(
1059             self, "1.1.1.2", 32, [VppRoutePath("0.0.0.0", gre_if.sw_if_index)]
1060         )
1061         route_dst.add_vpp_config()
1062
1063         #
1064         # packets to the tunnels destination should be dropped
1065         #
1066         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
1067         self.send_and_assert_no_replies(self.pg2, tx)
1068
1069         self.logger.info(self.vapi.ppcli("sh adj 7"))
1070
1071         #
1072         # break the loop
1073         #
1074         route_dst.modify([VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)])
1075         route_dst.add_vpp_config()
1076
1077         rx = self.send_and_expect(self.pg0, tx, self.pg1)
1078
1079         #
1080         # a good route throught the tunnel to check it restacked
1081         #
1082         route_via_tun_2 = VppIpRoute(
1083             self, "2.2.2.2", 32, [VppRoutePath("0.0.0.0", gre_if.sw_if_index)]
1084         )
1085         route_via_tun_2.add_vpp_config()
1086
1087         tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
1088         rx = self.send_and_expect(self.pg0, tx, self.pg1)
1089         self.verify_tunneled_4o4(self.pg1, rx, tx, self.pg0.local_ip4, "1.1.1.2")
1090
1091         #
1092         # cleanup
1093         #
1094         route_via_tun_2.remove_vpp_config()
1095         gre_if.remove_vpp_config()
1096
1097     def test_mgre(self):
1098         """mGRE IPv4 tunnel Tests"""
1099
1100         for itf in self.pg_interfaces[3:]:
1101             #
1102             # one underlay nh for each overlay/tunnel peer
1103             #
1104             itf.generate_remote_hosts(4)
1105             itf.configure_ipv4_neighbors()
1106
1107             #
1108             # Create an L3 GRE tunnel.
1109             #  - set it admin up
1110             #  - assign an IP Addres
1111             #  - Add a route via the tunnel
1112             #
1113             gre_if = VppGreInterface(
1114                 self,
1115                 itf.local_ip4,
1116                 "0.0.0.0",
1117                 mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
1118             )
1119             gre_if.add_vpp_config()
1120             gre_if.admin_up()
1121             gre_if.config_ip4()
1122             gre_if.generate_remote_hosts(4)
1123
1124             self.logger.info(self.vapi.cli("sh adj"))
1125             self.logger.info(self.vapi.cli("sh ip fib"))
1126
1127             #
1128             # ensure we don't match to the tunnel if the source address
1129             # is all zeros
1130             #
1131             tx = self.create_tunnel_stream_4o4(
1132                 self.pg0,
1133                 "0.0.0.0",
1134                 itf.local_ip4,
1135                 self.pg0.local_ip4,
1136                 self.pg0.remote_ip4,
1137             )
1138             self.send_and_assert_no_replies(self.pg0, tx)
1139
1140             #
1141             # for-each peer
1142             #
1143             for ii in range(1, 4):
1144                 route_addr = "4.4.4.%d" % ii
1145                 tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr)
1146
1147                 #
1148                 # route traffic via the peer
1149                 #
1150                 route_via_tun = VppIpRoute(
1151                     self,
1152                     route_addr,
1153                     32,
1154                     [VppRoutePath(gre_if._remote_hosts[ii].ip4, gre_if.sw_if_index)],
1155                 )
1156                 route_via_tun.add_vpp_config()
1157
1158                 # all packets dropped at this point
1159                 rx = self.send_and_assert_no_replies(self.pg0, tx_e)
1160
1161                 gre_if.admin_down()
1162                 gre_if.admin_up()
1163                 rx = self.send_and_assert_no_replies(self.pg0, tx_e)
1164
1165                 #
1166                 # Add a TEIB entry resolves the peer
1167                 #
1168                 teib = VppTeib(
1169                     self,
1170                     gre_if,
1171                     gre_if._remote_hosts[ii].ip4,
1172                     itf._remote_hosts[ii].ip4,
1173                 )
1174                 teib.add_vpp_config()
1175
1176                 #
1177                 # Send a packet stream that is routed into the tunnel
1178                 #  - packets are GRE encapped
1179                 #
1180                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1181                 self.verify_tunneled_4o4(
1182                     self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
1183                 )
1184
1185                 tx_i = self.create_tunnel_stream_4o4(
1186                     self.pg0,
1187                     itf._remote_hosts[ii].ip4,
1188                     itf.local_ip4,
1189                     self.pg0.local_ip4,
1190                     self.pg0.remote_ip4,
1191                 )
1192                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1193                 self.verify_decapped_4o4(self.pg0, rx, tx_i)
1194
1195                 #
1196                 # delete and re-add the TEIB
1197                 #
1198                 teib.remove_vpp_config()
1199                 self.send_and_assert_no_replies(self.pg0, tx_e)
1200                 self.send_and_assert_no_replies(self.pg0, tx_i)
1201
1202                 teib.add_vpp_config()
1203                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1204                 self.verify_tunneled_4o4(
1205                     self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
1206                 )
1207                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1208                 self.verify_decapped_4o4(self.pg0, rx, tx_i)
1209
1210                 #
1211                 # bounce the interface state and try packets again
1212                 #
1213                 gre_if.admin_down()
1214                 gre_if.admin_up()
1215                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1216                 self.verify_tunneled_4o4(
1217                     self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
1218                 )
1219                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1220                 self.verify_decapped_4o4(self.pg0, rx, tx_i)
1221
1222             gre_if.admin_down()
1223             gre_if.unconfig_ip4()
1224
1225     def test_mgre6(self):
1226         """mGRE IPv6 tunnel Tests"""
1227
1228         self.pg0.config_ip6()
1229         self.pg0.resolve_ndp()
1230
1231         e = VppEnum.vl_api_tunnel_encap_decap_flags_t
1232
1233         for itf in self.pg_interfaces[3:]:
1234             #
1235             # one underlay nh for each overlay/tunnel peer
1236             #
1237             itf.config_ip6()
1238             itf.generate_remote_hosts(4)
1239             itf.configure_ipv6_neighbors()
1240
1241             #
1242             # Create an L3 GRE tunnel.
1243             #  - set it admin up
1244             #  - assign an IP Addres
1245             #  - Add a route via the tunnel
1246             #
1247             gre_if = VppGreInterface(
1248                 self,
1249                 itf.local_ip6,
1250                 "::",
1251                 mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
1252                 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
1253             )
1254
1255             gre_if.add_vpp_config()
1256             gre_if.admin_up()
1257             gre_if.config_ip6()
1258             gre_if.generate_remote_hosts(4)
1259
1260             #
1261             # for-each peer
1262             #
1263             for ii in range(1, 4):
1264                 route_addr = "4::%d" % ii
1265
1266                 #
1267                 # Add a TEIB entry resolves the peer
1268                 #
1269                 teib = VppTeib(
1270                     self,
1271                     gre_if,
1272                     gre_if._remote_hosts[ii].ip6,
1273                     itf._remote_hosts[ii].ip6,
1274                 )
1275                 teib.add_vpp_config()
1276
1277                 #
1278                 # route traffic via the peer
1279                 #
1280                 route_via_tun = VppIpRoute(
1281                     self,
1282                     route_addr,
1283                     128,
1284                     [VppRoutePath(gre_if._remote_hosts[ii].ip6, gre_if.sw_if_index)],
1285                 )
1286                 route_via_tun.add_vpp_config()
1287
1288                 #
1289                 # Send a packet stream that is routed into the tunnel
1290                 #  - packets are GRE encapped
1291                 #
1292                 tx_e = self.create_stream_ip6(
1293                     self.pg0, "5::5", route_addr, dscp=2, ecn=1
1294                 )
1295                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1296                 self.verify_tunneled_6o6(
1297                     self.pg0, rx, tx_e, itf.local_ip6, itf._remote_hosts[ii].ip6, dscp=2
1298                 )
1299                 tx_i = self.create_tunnel_stream_6o6(
1300                     self.pg0,
1301                     itf._remote_hosts[ii].ip6,
1302                     itf.local_ip6,
1303                     self.pg0.local_ip6,
1304                     self.pg0.remote_ip6,
1305                 )
1306                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1307                 self.verify_decapped_6o6(self.pg0, rx, tx_i)
1308
1309                 #
1310                 # delete and re-add the TEIB
1311                 #
1312                 teib.remove_vpp_config()
1313                 self.send_and_assert_no_replies(self.pg0, tx_e)
1314
1315                 teib.add_vpp_config()
1316                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1317                 self.verify_tunneled_6o6(
1318                     self.pg0, rx, tx_e, itf.local_ip6, itf._remote_hosts[ii].ip6, dscp=2
1319                 )
1320                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1321                 self.verify_decapped_6o6(self.pg0, rx, tx_i)
1322
1323             gre_if.admin_down()
1324             gre_if.unconfig_ip4()
1325             itf.unconfig_ip6()
1326         self.pg0.unconfig_ip6()
1327
1328
1329 if __name__ == "__main__":
1330     unittest.main(testRunner=VppTestRunner)