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