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