Revert "Enforce FIB table creation before use"
[vpp.git] / test / test_dvr.py
1 #!/usr/bin/env python
2 import random
3 import socket
4 import unittest
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppSubInterface, VppDot1QSubint
8 from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
9 from vpp_papi_provider import L2_VTR_OP
10
11 from scapy.packet import Raw
12 from scapy.layers.l2 import Ether, Dot1Q, ARP
13 from scapy.layers.inet import IP, UDP
14 from util import ppp
15
16
17 class TestDVR(VppTestCase):
18     """ IPv4 Load-Balancing """
19
20     def setUp(self):
21         super(TestDVR, self).setUp()
22
23         self.create_pg_interfaces(range(4))
24         self.create_loopback_interfaces(range(1))
25
26         for i in self.pg_interfaces:
27             i.admin_up()
28
29         self.loop0.config_ip4()
30
31     def tearDown(self):
32         for i in self.pg_interfaces:
33             i.admin_down()
34         self.loop0.unconfig_ip4()
35
36         super(TestDVR, self).tearDown()
37
38     def test_dvr(self):
39         """ Distributed Virtual Router """
40
41         #
42         # A packet destined to an IP address that is L2 bridged via
43         # a non-tag interface
44         #
45         ip_non_tag_bridged = "10.10.10.10"
46         ip_tag_bridged = "10.10.10.11"
47         any_src_addr = "1.1.1.1"
48
49         pkt_no_tag = (Ether(src=self.pg0.remote_mac,
50                             dst=self.loop0.local_mac) /
51                       IP(src=any_src_addr,
52                          dst=ip_non_tag_bridged) /
53                       UDP(sport=1234, dport=1234) /
54                       Raw('\xa5' * 100))
55         pkt_tag = (Ether(src=self.pg0.remote_mac,
56                          dst=self.loop0.local_mac) /
57                    IP(src=any_src_addr,
58                       dst=ip_tag_bridged) /
59                    UDP(sport=1234, dport=1234) /
60                    Raw('\xa5' * 100))
61
62         #
63         # Two sub-interfaces so we can test VLAN tag push/pop
64         #
65         sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92)
66         sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93)
67         sub_if_on_pg2.admin_up()
68         sub_if_on_pg3.admin_up()
69
70         #
71         # Put all the interfaces into a new bridge domain
72         #
73         self.vapi.sw_interface_set_l2_bridge(self.pg0.sw_if_index, 1)
74         self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index, 1)
75         self.vapi.sw_interface_set_l2_bridge(sub_if_on_pg2.sw_if_index, 1)
76         self.vapi.sw_interface_set_l2_bridge(sub_if_on_pg3.sw_if_index, 1)
77         self.vapi.sw_interface_set_l2_bridge(self.loop0.sw_if_index, 1, bvi=1)
78
79         self.vapi.sw_interface_set_l2_tag_rewrite(sub_if_on_pg2.sw_if_index,
80                                                   L2_VTR_OP.L2_POP_1,
81                                                   92)
82         self.vapi.sw_interface_set_l2_tag_rewrite(sub_if_on_pg3.sw_if_index,
83                                                   L2_VTR_OP.L2_POP_1,
84                                                   93)
85
86         self.logger.error(self.vapi.ppcli("show bridge-domain 1 detail"))
87
88         #
89         # Add routes to bridge the traffic via a tagged an nontagged interface
90         #
91         route_no_tag = VppIpRoute(
92             self, ip_non_tag_bridged, 32,
93             [VppRoutePath("0.0.0.0",
94                           self.pg1.sw_if_index,
95                           proto=DpoProto.DPO_PROTO_ETHERNET)])
96         route_no_tag.add_vpp_config()
97
98         #
99         # Inject the packet that arrives and leaves on a non-tagged interface
100         # Since it's 'bridged' expect that the MAC headed is unchanged.
101         #
102         self.pg0.add_stream(pkt_no_tag)
103
104         self.pg_enable_capture(self.pg_interfaces)
105         self.pg_start()
106
107         rx = self.pg1.get_capture(1)
108
109         self.assertEqual(rx[0][Ether].dst, pkt_no_tag[Ether].dst)
110         self.assertEqual(rx[0][Ether].src, pkt_no_tag[Ether].src)
111
112         #
113         # Add routes to bridge the traffic via a tagged interface
114         #
115         route_no_tag = VppIpRoute(
116             self, ip_tag_bridged, 32,
117             [VppRoutePath("0.0.0.0",
118                           sub_if_on_pg3.sw_if_index,
119                           proto=DpoProto.DPO_PROTO_ETHERNET)])
120         route_no_tag.add_vpp_config()
121
122         #
123         # Inject the packet that arrives and leaves on a non-tagged interface
124         # Since it's 'bridged' expect that the MAC headed is unchanged.
125         #
126         self.pg0.add_stream(pkt_tag)
127
128         self.pg_enable_capture(self.pg_interfaces)
129         self.pg_start()
130
131         rx = self.pg3.get_capture(1)
132
133         self.assertEqual(rx[0][Ether].dst, pkt_tag[Ether].dst)
134         self.assertEqual(rx[0][Ether].src, pkt_tag[Ether].src)
135         self.assertEqual(rx[0][Dot1Q].vlan, 93)
136
137         #
138         # Tag to tag
139         #
140         pkt_tag_to_tag = (Ether(src=self.pg2.remote_mac,
141                                 dst=self.loop0.local_mac) /
142                           Dot1Q(vlan=92) /
143                           IP(src=any_src_addr,
144                              dst=ip_tag_bridged) /
145                           UDP(sport=1234, dport=1234) /
146                           Raw('\xa5' * 100))
147
148         self.pg2.add_stream(pkt_tag_to_tag)
149         self.pg_enable_capture(self.pg_interfaces)
150         self.pg_start()
151         rx = self.pg3.get_capture(1)
152
153         self.assertEqual(rx[0][Ether].dst, pkt_tag_to_tag[Ether].dst)
154         self.assertEqual(rx[0][Ether].src, pkt_tag_to_tag[Ether].src)
155         self.assertEqual(rx[0][Dot1Q].vlan, 93)
156
157         #
158         # Tag to non-Tag
159         #
160         pkt_tag_to_non_tag = (Ether(src=self.pg2.remote_mac,
161                                     dst=self.loop0.local_mac) /
162                               Dot1Q(vlan=92) /
163                               IP(src=any_src_addr,
164                                  dst=ip_non_tag_bridged) /
165                               UDP(sport=1234, dport=1234) /
166                               Raw('\xa5' * 100))
167
168         self.pg2.add_stream(pkt_tag_to_non_tag)
169         self.pg_enable_capture(self.pg_interfaces)
170         self.pg_start()
171         rx = self.pg1.get_capture(1)
172
173         self.assertEqual(rx[0][Ether].dst, pkt_tag_to_tag[Ether].dst)
174         self.assertEqual(rx[0][Ether].src, pkt_tag_to_tag[Ether].src)
175         self.assertFalse(rx[0].haslayer(Dot1Q))
176
177 if __name__ == '__main__':
178     unittest.main(testRunner=VppTestRunner)