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