Optimize GRE Tunnel and add support for ERSPAN encap
[vpp.git] / test / test_gre.py
1 #!/usr/bin/env python
2
3 import unittest
4 from logging import *
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppDot1QSubint
8 from vpp_gre_interface import VppGreInterface, VppGre6Interface
9 from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable
10 from vpp_papi_provider import L2_VTR_OP
11
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether, Dot1Q, GRE
14 from scapy.layers.inet import IP, UDP
15 from scapy.layers.inet6 import IPv6
16 from scapy.volatile import RandMAC, RandIP
17
18 from util import ppp, ppc
19
20
21 class GreTunnelTypes:
22     TT_L3 = 0
23     TT_TEB = 1
24     TT_ERSPAN = 2
25
26
27 class TestGRE(VppTestCase):
28     """ GRE Test Case """
29
30     @classmethod
31     def setUpClass(cls):
32         super(TestGRE, cls).setUpClass()
33
34     def setUp(self):
35         super(TestGRE, self).setUp()
36
37         # create 3 pg interfaces - set one in a non-default table.
38         self.create_pg_interfaces(range(3))
39
40         self.tbl = VppIpTable(self, 1)
41         self.tbl.add_vpp_config()
42         self.pg1.set_table_ip4(1)
43
44         for i in self.pg_interfaces:
45             i.admin_up()
46
47         self.pg0.config_ip4()
48         self.pg0.resolve_arp()
49         self.pg1.config_ip4()
50         self.pg1.resolve_arp()
51         self.pg2.config_ip6()
52         self.pg2.resolve_ndp()
53
54     def tearDown(self):
55         for i in self.pg_interfaces:
56             i.unconfig_ip4()
57             i.unconfig_ip6()
58             i.admin_down()
59         self.pg1.set_table_ip4(0)
60         super(TestGRE, self).tearDown()
61
62     def create_stream_ip4(self, src_if, src_ip, dst_ip):
63         pkts = []
64         for i in range(0, 257):
65             info = self.create_packet_info(src_if, src_if)
66             payload = self.info_to_payload(info)
67             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
68                  IP(src=src_ip, dst=dst_ip) /
69                  UDP(sport=1234, dport=1234) /
70                  Raw(payload))
71             info.data = p.copy()
72             pkts.append(p)
73         return pkts
74
75     def create_stream_ip6(self, src_if, src_ip, dst_ip):
76         pkts = []
77         for i in range(0, 257):
78             info = self.create_packet_info(src_if, src_if)
79             payload = self.info_to_payload(info)
80             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
81                  IPv6(src=src_ip, dst=dst_ip) /
82                  UDP(sport=1234, dport=1234) /
83                  Raw(payload))
84             info.data = p.copy()
85             pkts.append(p)
86         return pkts
87
88     def create_tunnel_stream_4o4(self, src_if,
89                                  tunnel_src, tunnel_dst,
90                                  src_ip, dst_ip):
91         pkts = []
92         for i in range(0, 257):
93             info = self.create_packet_info(src_if, src_if)
94             payload = self.info_to_payload(info)
95             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
96                  IP(src=tunnel_src, dst=tunnel_dst) /
97                  GRE() /
98                  IP(src=src_ip, dst=dst_ip) /
99                  UDP(sport=1234, dport=1234) /
100                  Raw(payload))
101             info.data = p.copy()
102             pkts.append(p)
103         return pkts
104
105     def create_tunnel_stream_6o4(self, src_if,
106                                  tunnel_src, tunnel_dst,
107                                  src_ip, dst_ip):
108         pkts = []
109         for i in range(0, 257):
110             info = self.create_packet_info(src_if, src_if)
111             payload = self.info_to_payload(info)
112             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
113                  IP(src=tunnel_src, dst=tunnel_dst) /
114                  GRE() /
115                  IPv6(src=src_ip, dst=dst_ip) /
116                  UDP(sport=1234, dport=1234) /
117                  Raw(payload))
118             info.data = p.copy()
119             pkts.append(p)
120         return pkts
121
122     def create_tunnel_stream_6o6(self, src_if,
123                                  tunnel_src, tunnel_dst,
124                                  src_ip, dst_ip):
125         pkts = []
126         for i in range(0, 257):
127             info = self.create_packet_info(src_if, src_if)
128             payload = self.info_to_payload(info)
129             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
130                  IPv6(src=tunnel_src, dst=tunnel_dst) /
131                  GRE() /
132                  IPv6(src=src_ip, dst=dst_ip) /
133                  UDP(sport=1234, dport=1234) /
134                  Raw(payload))
135             info.data = p.copy()
136             pkts.append(p)
137         return pkts
138
139     def create_tunnel_stream_l2o4(self, src_if,
140                                   tunnel_src, tunnel_dst):
141         pkts = []
142         for i in range(0, 257):
143             info = self.create_packet_info(src_if, src_if)
144             payload = self.info_to_payload(info)
145             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
146                  IP(src=tunnel_src, dst=tunnel_dst) /
147                  GRE() /
148                  Ether(dst=RandMAC('*:*:*:*:*:*'),
149                        src=RandMAC('*:*:*:*:*:*')) /
150                  IP(src=str(RandIP()), dst=str(RandIP())) /
151                  UDP(sport=1234, dport=1234) /
152                  Raw(payload))
153             info.data = p.copy()
154             pkts.append(p)
155         return pkts
156
157     def create_tunnel_stream_vlano4(self, src_if,
158                                     tunnel_src, tunnel_dst, vlan):
159         pkts = []
160         for i in range(0, 257):
161             info = self.create_packet_info(src_if, src_if)
162             payload = self.info_to_payload(info)
163             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
164                  IP(src=tunnel_src, dst=tunnel_dst) /
165                  GRE() /
166                  Ether(dst=RandMAC('*:*:*:*:*:*'),
167                        src=RandMAC('*:*:*:*:*:*')) /
168                  Dot1Q(vlan=vlan) /
169                  IP(src=str(RandIP()), dst=str(RandIP())) /
170                  UDP(sport=1234, dport=1234) /
171                  Raw(payload))
172             info.data = p.copy()
173             pkts.append(p)
174         return pkts
175
176     def verify_tunneled_4o4(self, src_if, capture, sent,
177                             tunnel_src, tunnel_dst):
178
179         self.assertEqual(len(capture), len(sent))
180
181         for i in range(len(capture)):
182             try:
183                 tx = sent[i]
184                 rx = capture[i]
185
186                 tx_ip = tx[IP]
187                 rx_ip = rx[IP]
188
189                 self.assertEqual(rx_ip.src, tunnel_src)
190                 self.assertEqual(rx_ip.dst, tunnel_dst)
191
192                 rx_gre = rx[GRE]
193                 rx_ip = rx_gre[IP]
194
195                 self.assertEqual(rx_ip.src, tx_ip.src)
196                 self.assertEqual(rx_ip.dst, tx_ip.dst)
197                 # IP processing post pop has decremented the TTL
198                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
199
200             except:
201                 self.logger.error(ppp("Rx:", rx))
202                 self.logger.error(ppp("Tx:", tx))
203                 raise
204
205     def verify_tunneled_6o6(self, src_if, capture, sent,
206                             tunnel_src, tunnel_dst):
207
208         self.assertEqual(len(capture), len(sent))
209
210         for i in range(len(capture)):
211             try:
212                 tx = sent[i]
213                 rx = capture[i]
214
215                 tx_ip = tx[IPv6]
216                 rx_ip = rx[IPv6]
217
218                 self.assertEqual(rx_ip.src, tunnel_src)
219                 self.assertEqual(rx_ip.dst, tunnel_dst)
220
221                 rx_gre = GRE(str(rx_ip[IPv6].payload))
222                 rx_ip = rx_gre[IPv6]
223
224                 self.assertEqual(rx_ip.src, tx_ip.src)
225                 self.assertEqual(rx_ip.dst, tx_ip.dst)
226
227             except:
228                 self.logger.error(ppp("Rx:", rx))
229                 self.logger.error(ppp("Tx:", tx))
230                 raise
231
232     def verify_tunneled_l2o4(self, src_if, capture, sent,
233                              tunnel_src, tunnel_dst):
234         self.assertEqual(len(capture), len(sent))
235
236         for i in range(len(capture)):
237             try:
238                 tx = sent[i]
239                 rx = capture[i]
240
241                 tx_ip = tx[IP]
242                 rx_ip = rx[IP]
243
244                 self.assertEqual(rx_ip.src, tunnel_src)
245                 self.assertEqual(rx_ip.dst, tunnel_dst)
246
247                 rx_gre = rx[GRE]
248                 rx_l2 = rx_gre[Ether]
249                 rx_ip = rx_l2[IP]
250                 tx_gre = tx[GRE]
251                 tx_l2 = tx_gre[Ether]
252                 tx_ip = tx_l2[IP]
253
254                 self.assertEqual(rx_ip.src, tx_ip.src)
255                 self.assertEqual(rx_ip.dst, tx_ip.dst)
256                 # bridged, not L3 forwarded, so no TTL decrement
257                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
258
259             except:
260                 self.logger.error(ppp("Rx:", rx))
261                 self.logger.error(ppp("Tx:", tx))
262                 raise
263
264     def verify_tunneled_vlano4(self, src_if, capture, sent,
265                                tunnel_src, tunnel_dst, vlan):
266         try:
267             self.assertEqual(len(capture), len(sent))
268         except:
269             ppc("Unexpected packets captured:", capture)
270             raise
271
272         for i in range(len(capture)):
273             try:
274                 tx = sent[i]
275                 rx = capture[i]
276
277                 tx_ip = tx[IP]
278                 rx_ip = rx[IP]
279
280                 self.assertEqual(rx_ip.src, tunnel_src)
281                 self.assertEqual(rx_ip.dst, tunnel_dst)
282
283                 rx_gre = rx[GRE]
284                 rx_l2 = rx_gre[Ether]
285                 rx_vlan = rx_l2[Dot1Q]
286                 rx_ip = rx_l2[IP]
287
288                 self.assertEqual(rx_vlan.vlan, vlan)
289
290                 tx_gre = tx[GRE]
291                 tx_l2 = tx_gre[Ether]
292                 tx_ip = tx_l2[IP]
293
294                 self.assertEqual(rx_ip.src, tx_ip.src)
295                 self.assertEqual(rx_ip.dst, tx_ip.dst)
296                 # bridged, not L3 forwarded, so no TTL decrement
297                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
298
299             except:
300                 self.logger.error(ppp("Rx:", rx))
301                 self.logger.error(ppp("Tx:", tx))
302                 raise
303
304     def verify_decapped_4o4(self, src_if, capture, sent):
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                 tx_ip = tx[IP]
313                 rx_ip = rx[IP]
314                 tx_gre = tx[GRE]
315                 tx_ip = tx_gre[IP]
316
317                 self.assertEqual(rx_ip.src, tx_ip.src)
318                 self.assertEqual(rx_ip.dst, tx_ip.dst)
319                 # IP processing post pop has decremented the TTL
320                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
321
322             except:
323                 self.logger.error(ppp("Rx:", rx))
324                 self.logger.error(ppp("Tx:", tx))
325                 raise
326
327     def verify_decapped_6o4(self, src_if, capture, sent):
328         self.assertEqual(len(capture), len(sent))
329
330         for i in range(len(capture)):
331             try:
332                 tx = sent[i]
333                 rx = capture[i]
334
335                 tx_ip = tx[IP]
336                 rx_ip = rx[IPv6]
337                 tx_gre = tx[GRE]
338                 tx_ip = tx_gre[IPv6]
339
340                 self.assertEqual(rx_ip.src, tx_ip.src)
341                 self.assertEqual(rx_ip.dst, tx_ip.dst)
342                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
343
344             except:
345                 self.logger.error(ppp("Rx:", rx))
346                 self.logger.error(ppp("Tx:", tx))
347                 raise
348
349     def test_gre(self):
350         """ GRE IPv4 tunnel Tests """
351
352         #
353         # Create an L3 GRE tunnel.
354         #  - set it admin up
355         #  - assign an IP Addres
356         #  - Add a route via the tunnel
357         #
358         gre_if = VppGreInterface(self,
359                                  self.pg0.local_ip4,
360                                  "1.1.1.2")
361         gre_if.add_vpp_config()
362
363         #
364         # The double create (create the same tunnel twice) should fail,
365         # and we should still be able to use the original
366         #
367         try:
368             gre_if.add_vpp_config()
369         except Exception:
370             pass
371         else:
372             self.fail("Double GRE tunnel add does not fail")
373
374         gre_if.admin_up()
375         gre_if.config_ip4()
376
377         route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
378                                    [VppRoutePath("0.0.0.0",
379                                                  gre_if.sw_if_index)])
380
381         route_via_tun.add_vpp_config()
382
383         #
384         # Send a packet stream that is routed into the tunnel
385         #  - they are all dropped since the tunnel's desintation IP
386         #    is unresolved - or resolves via the default route - which
387         #    which is a drop.
388         #
389         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
390         self.pg0.add_stream(tx)
391
392         self.pg_enable_capture(self.pg_interfaces)
393         self.pg_start()
394
395         self.pg0.assert_nothing_captured(
396             remark="GRE packets forwarded without DIP resolved")
397
398         #
399         # Add a route that resolves the tunnel's destination
400         #
401         route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
402                                    [VppRoutePath(self.pg0.remote_ip4,
403                                                  self.pg0.sw_if_index)])
404         route_tun_dst.add_vpp_config()
405
406         #
407         # Send a packet stream that is routed into the tunnel
408         #  - packets are GRE encapped
409         #
410         self.vapi.cli("clear trace")
411         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
412         self.pg0.add_stream(tx)
413
414         self.pg_enable_capture(self.pg_interfaces)
415         self.pg_start()
416
417         rx = self.pg0.get_capture(len(tx))
418         self.verify_tunneled_4o4(self.pg0, rx, tx,
419                                  self.pg0.local_ip4, "1.1.1.2")
420
421         #
422         # Send tunneled packets that match the created tunnel and
423         # are decapped and forwarded
424         #
425         self.vapi.cli("clear trace")
426         tx = self.create_tunnel_stream_4o4(self.pg0,
427                                            "1.1.1.2",
428                                            self.pg0.local_ip4,
429                                            self.pg0.local_ip4,
430                                            self.pg0.remote_ip4)
431         self.pg0.add_stream(tx)
432
433         self.pg_enable_capture(self.pg_interfaces)
434         self.pg_start()
435
436         rx = self.pg0.get_capture(len(tx))
437         self.verify_decapped_4o4(self.pg0, rx, tx)
438
439         #
440         # Send tunneled packets that do not match the tunnel's src
441         #
442         self.vapi.cli("clear trace")
443         tx = self.create_tunnel_stream_4o4(self.pg0,
444                                            "1.1.1.3",
445                                            self.pg0.local_ip4,
446                                            self.pg0.local_ip4,
447                                            self.pg0.remote_ip4)
448         self.pg0.add_stream(tx)
449
450         self.pg_enable_capture(self.pg_interfaces)
451         self.pg_start()
452
453         self.pg0.assert_nothing_captured(
454             remark="GRE packets forwarded despite no SRC address match")
455
456         #
457         # Configure IPv6 on the PG interface so we can route IPv6
458         # packets
459         #
460         self.pg0.config_ip6()
461         self.pg0.resolve_ndp()
462
463         #
464         # Send IPv6 tunnel encapslated packets
465         #  - dropped since IPv6 is not enabled on the tunnel
466         #
467         self.vapi.cli("clear trace")
468         tx = self.create_tunnel_stream_6o4(self.pg0,
469                                            "1.1.1.2",
470                                            self.pg0.local_ip4,
471                                            self.pg0.local_ip6,
472                                            self.pg0.remote_ip6)
473         self.pg0.add_stream(tx)
474
475         self.pg_enable_capture(self.pg_interfaces)
476         self.pg_start()
477
478         self.pg0.assert_nothing_captured(remark="IPv6 GRE packets forwarded "
479                                          "despite IPv6 not enabled on tunnel")
480
481         #
482         # Enable IPv6 on the tunnel
483         #
484         gre_if.config_ip6()
485
486         #
487         # Send IPv6 tunnel encapslated packets
488         #  - forwarded since IPv6 is enabled on the tunnel
489         #
490         self.vapi.cli("clear trace")
491         tx = self.create_tunnel_stream_6o4(self.pg0,
492                                            "1.1.1.2",
493                                            self.pg0.local_ip4,
494                                            self.pg0.local_ip6,
495                                            self.pg0.remote_ip6)
496         self.pg0.add_stream(tx)
497
498         self.pg_enable_capture(self.pg_interfaces)
499         self.pg_start()
500
501         rx = self.pg0.get_capture(len(tx))
502         self.verify_decapped_6o4(self.pg0, rx, tx)
503
504         #
505         # test case cleanup
506         #
507         route_tun_dst.remove_vpp_config()
508         route_via_tun.remove_vpp_config()
509         gre_if.remove_vpp_config()
510
511         self.pg0.unconfig_ip6()
512
513     def test_gre6(self):
514         """ GRE IPv6 tunnel Tests """
515
516         self.pg1.config_ip6()
517         self.pg1.resolve_ndp()
518
519         #
520         # Create an L3 GRE tunnel.
521         #  - set it admin up
522         #  - assign an IP Address
523         #  - Add a route via the tunnel
524         #
525         gre_if = VppGre6Interface(self,
526                                   self.pg2.local_ip6,
527                                   "1002::1")
528         gre_if.add_vpp_config()
529         gre_if.admin_up()
530         gre_if.config_ip6()
531
532         route_via_tun = VppIpRoute(
533             self, "4004::1", 128,
534             [VppRoutePath("0::0",
535                           gre_if.sw_if_index,
536                           proto=DpoProto.DPO_PROTO_IP6)],
537             is_ip6=1)
538
539         route_via_tun.add_vpp_config()
540
541         #
542         # Send a packet stream that is routed into the tunnel
543         #  - they are all dropped since the tunnel's desintation IP
544         #    is unresolved - or resolves via the default route - which
545         #    which is a drop.
546         #
547         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
548         self.pg2.add_stream(tx)
549
550         self.pg_enable_capture(self.pg_interfaces)
551         self.pg_start()
552
553         self.pg2.assert_nothing_captured(
554             remark="GRE packets forwarded without DIP resolved")
555
556         #
557         # Add a route that resolves the tunnel's destination
558         #
559         route_tun_dst = VppIpRoute(
560             self, "1002::1", 128,
561             [VppRoutePath(self.pg2.remote_ip6,
562                           self.pg2.sw_if_index,
563                           proto=DpoProto.DPO_PROTO_IP6)],
564             is_ip6=1)
565         route_tun_dst.add_vpp_config()
566
567         #
568         # Send a packet stream that is routed into the tunnel
569         #  - packets are GRE encapped
570         #
571         self.vapi.cli("clear trace")
572         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
573         self.pg2.add_stream(tx)
574
575         self.pg_enable_capture(self.pg_interfaces)
576         self.pg_start()
577
578         rx = self.pg2.get_capture(len(tx))
579         self.verify_tunneled_6o6(self.pg2, rx, tx,
580                                  self.pg2.local_ip6, "1002::1")
581
582         #
583         # Test decap. decapped packets go out pg1
584         #
585         tx = self.create_tunnel_stream_6o6(self.pg2,
586                                            "1002::1",
587                                            self.pg2.local_ip6,
588                                            "2001::1",
589                                            self.pg1.remote_ip6)
590         self.vapi.cli("clear trace")
591         self.pg2.add_stream(tx)
592
593         self.pg_enable_capture(self.pg_interfaces)
594         self.pg_start()
595         rx = self.pg1.get_capture(len(tx))
596
597         #
598         # RX'd packet is UDP over IPv6, test the GRE header is gone.
599         #
600         self.assertFalse(rx[0].haslayer(GRE))
601         self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
602
603         #
604         # test case cleanup
605         #
606         route_tun_dst.remove_vpp_config()
607         route_via_tun.remove_vpp_config()
608         gre_if.remove_vpp_config()
609
610         self.pg2.unconfig_ip6()
611         self.pg1.unconfig_ip6()
612
613     def test_gre_vrf(self):
614         """ GRE tunnel VRF Tests """
615
616         #
617         # Create an L3 GRE tunnel whose destination is in the non-default
618         # table. The underlay is thus non-default - the overlay is still
619         # the default.
620         #  - set it admin up
621         #  - assign an IP Addres
622         #
623         gre_if = VppGreInterface(self, self.pg1.local_ip4,
624                                  "2.2.2.2",
625                                  outer_fib_id=1)
626         gre_if.add_vpp_config()
627         gre_if.admin_up()
628         gre_if.config_ip4()
629
630         #
631         # Add a route via the tunnel - in the overlay
632         #
633         route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
634                                    [VppRoutePath("0.0.0.0",
635                                                  gre_if.sw_if_index)])
636         route_via_tun.add_vpp_config()
637
638         #
639         # Add a route that resolves the tunnel's destination - in the
640         # underlay table
641         #
642         route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
643                                    paths=[VppRoutePath(self.pg1.remote_ip4,
644                                                        self.pg1.sw_if_index)])
645         route_tun_dst.add_vpp_config()
646
647         #
648         # Send a packet stream that is routed into the tunnel
649         # packets are sent in on pg0 which is in the default table
650         #  - packets are GRE encapped
651         #
652         self.vapi.cli("clear trace")
653         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
654         self.pg0.add_stream(tx)
655
656         self.pg_enable_capture(self.pg_interfaces)
657         self.pg_start()
658
659         rx = self.pg1.get_capture(len(tx))
660         self.verify_tunneled_4o4(self.pg1, rx, tx,
661                                  self.pg1.local_ip4, "2.2.2.2")
662
663         #
664         # Send tunneled packets that match the created tunnel and
665         # are decapped and forwarded. This tests the decap lookup
666         # does not happen in the encap table
667         #
668         self.vapi.cli("clear trace")
669         tx = self.create_tunnel_stream_4o4(self.pg1,
670                                            "2.2.2.2",
671                                            self.pg1.local_ip4,
672                                            self.pg0.local_ip4,
673                                            self.pg0.remote_ip4)
674         self.pg1.add_stream(tx)
675
676         self.pg_enable_capture(self.pg_interfaces)
677         self.pg_start()
678
679         rx = self.pg0.get_capture(len(tx))
680         self.verify_decapped_4o4(self.pg0, rx, tx)
681
682         #
683         # Send tunneled packets that match the created tunnel and
684         # but arrive on an interface that is not in the tunnel's
685         # encap VRF, these are dropped
686         #
687         self.vapi.cli("clear trace")
688         tx = self.create_tunnel_stream_4o4(self.pg2,
689                                            "2.2.2.2",
690                                            self.pg1.local_ip4,
691                                            self.pg0.local_ip4,
692                                            self.pg0.remote_ip4)
693         self.pg1.add_stream(tx)
694
695         self.pg_enable_capture(self.pg_interfaces)
696         self.pg_start()
697
698         self.pg0.assert_nothing_captured(
699             remark="GRE decap packets in wrong VRF")
700
701         #
702         # test case cleanup
703         #
704         route_tun_dst.remove_vpp_config()
705         route_via_tun.remove_vpp_config()
706         gre_if.remove_vpp_config()
707
708     def test_gre_l2(self):
709         """ GRE tunnel L2 Tests """
710
711         #
712         # Add routes to resolve the tunnel destinations
713         #
714         route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
715                                     [VppRoutePath(self.pg0.remote_ip4,
716                                                   self.pg0.sw_if_index)])
717         route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
718                                     [VppRoutePath(self.pg0.remote_ip4,
719                                                   self.pg0.sw_if_index)])
720
721         route_tun1_dst.add_vpp_config()
722         route_tun2_dst.add_vpp_config()
723
724         #
725         # Create 2 L2 GRE tunnels and x-connect them
726         #
727         gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
728                                   "2.2.2.2",
729                                   type=GreTunnelTypes.TT_TEB)
730         gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
731                                   "2.2.2.3",
732                                   type=GreTunnelTypes.TT_TEB)
733         gre_if1.add_vpp_config()
734         gre_if2.add_vpp_config()
735
736         gre_if1.admin_up()
737         gre_if2.admin_up()
738
739         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
740                                                gre_if2.sw_if_index,
741                                                enable=1)
742         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
743                                                gre_if1.sw_if_index,
744                                                enable=1)
745
746         #
747         # Send in tunnel encapped L2. expect out tunnel encapped L2
748         # in both directions
749         #
750         self.vapi.cli("clear trace")
751         tx = self.create_tunnel_stream_l2o4(self.pg0,
752                                             "2.2.2.2",
753                                             self.pg0.local_ip4)
754         self.pg0.add_stream(tx)
755
756         self.pg_enable_capture(self.pg_interfaces)
757         self.pg_start()
758
759         rx = self.pg0.get_capture(len(tx))
760         self.verify_tunneled_l2o4(self.pg0, rx, tx,
761                                   self.pg0.local_ip4,
762                                   "2.2.2.3")
763
764         self.vapi.cli("clear trace")
765         tx = self.create_tunnel_stream_l2o4(self.pg0,
766                                             "2.2.2.3",
767                                             self.pg0.local_ip4)
768         self.pg0.add_stream(tx)
769
770         self.pg_enable_capture(self.pg_interfaces)
771         self.pg_start()
772
773         rx = self.pg0.get_capture(len(tx))
774         self.verify_tunneled_l2o4(self.pg0, rx, tx,
775                                   self.pg0.local_ip4,
776                                   "2.2.2.2")
777
778         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
779                                                gre_if2.sw_if_index,
780                                                enable=0)
781         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
782                                                gre_if1.sw_if_index,
783                                                enable=0)
784
785         #
786         # Create a VLAN sub-interfaces on the GRE TEB interfaces
787         # then x-connect them
788         #
789         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
790         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
791
792         # gre_if_11.add_vpp_config()
793         # gre_if_12.add_vpp_config()
794
795         gre_if_11.admin_up()
796         gre_if_12.admin_up()
797
798         self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
799                                                gre_if_12.sw_if_index,
800                                                enable=1)
801         self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
802                                                gre_if_11.sw_if_index,
803                                                enable=1)
804
805         #
806         # Configure both to pop thier respective VLAN tags,
807         # so that during the x-coonect they will subsequently push
808         #
809         self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
810                                                   L2_VTR_OP.L2_POP_1,
811                                                   12)
812         self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
813                                                   L2_VTR_OP.L2_POP_1,
814                                                   11)
815
816         #
817         # Send traffic in both directiond - expect the VLAN tags to
818         # be swapped.
819         #
820         self.vapi.cli("clear trace")
821         tx = self.create_tunnel_stream_vlano4(self.pg0,
822                                               "2.2.2.2",
823                                               self.pg0.local_ip4,
824                                               11)
825         self.pg0.add_stream(tx)
826
827         self.pg_enable_capture(self.pg_interfaces)
828         self.pg_start()
829
830         rx = self.pg0.get_capture(len(tx))
831         self.verify_tunneled_vlano4(self.pg0, rx, tx,
832                                     self.pg0.local_ip4,
833                                     "2.2.2.3",
834                                     12)
835
836         self.vapi.cli("clear trace")
837         tx = self.create_tunnel_stream_vlano4(self.pg0,
838                                               "2.2.2.3",
839                                               self.pg0.local_ip4,
840                                               12)
841         self.pg0.add_stream(tx)
842
843         self.pg_enable_capture(self.pg_interfaces)
844         self.pg_start()
845
846         rx = self.pg0.get_capture(len(tx))
847         self.verify_tunneled_vlano4(self.pg0, rx, tx,
848                                     self.pg0.local_ip4,
849                                     "2.2.2.2",
850                                     11)
851
852         #
853         # Cleanup Test resources
854         #
855         gre_if_11.remove_vpp_config()
856         gre_if_12.remove_vpp_config()
857         gre_if1.remove_vpp_config()
858         gre_if2.remove_vpp_config()
859         route_tun1_dst.add_vpp_config()
860         route_tun2_dst.add_vpp_config()
861
862
863 if __name__ == '__main__':
864     unittest.main(testRunner=VppTestRunner)