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         #
87         # Add routes to bridge the traffic via a tagged an nontagged interface
88         #
89         route_no_tag = VppIpRoute(
90             self, ip_non_tag_bridged, 32,
91             [VppRoutePath("0.0.0.0",
92                           self.pg1.sw_if_index,
93                           proto=DpoProto.DPO_PROTO_ETHERNET)])
94         route_no_tag.add_vpp_config()
95
96         #
97         # Inject the packet that arrives and leaves on a non-tagged interface
98         # Since it's 'bridged' expect that the MAC headed is unchanged.
99         #
100         self.pg0.add_stream(pkt_no_tag)
101
102         self.pg_enable_capture(self.pg_interfaces)
103         self.pg_start()
104
105         rx = self.pg1.get_capture(1)
106
107         self.assertEqual(rx[0][Ether].dst, pkt_no_tag[Ether].dst)
108         self.assertEqual(rx[0][Ether].src, pkt_no_tag[Ether].src)
109
110         #
111         # Add routes to bridge the traffic via a tagged interface
112         #
113         route_no_tag = VppIpRoute(
114             self, ip_tag_bridged, 32,
115             [VppRoutePath("0.0.0.0",
116                           sub_if_on_pg3.sw_if_index,
117                           proto=DpoProto.DPO_PROTO_ETHERNET)])
118         route_no_tag.add_vpp_config()
119
120         #
121         # Inject the packet that arrives and leaves on a non-tagged interface
122         # Since it's 'bridged' expect that the MAC headed is unchanged.
123         #
124         self.pg0.add_stream(pkt_tag)
125
126         self.pg_enable_capture(self.pg_interfaces)
127         self.pg_start()
128
129         rx = self.pg3.get_capture(1)
130
131         self.assertEqual(rx[0][Ether].dst, pkt_tag[Ether].dst)
132         self.assertEqual(rx[0][Ether].src, pkt_tag[Ether].src)
133         self.assertEqual(rx[0][Dot1Q].vlan, 93)
134
135         #
136         # Tag to tag
137         #
138         pkt_tag_to_tag = (Ether(src=self.pg2.remote_mac,
139                                 dst=self.loop0.local_mac) /
140                           Dot1Q(vlan=92) /
141                           IP(src=any_src_addr,
142                              dst=ip_tag_bridged) /
143                           UDP(sport=1234, dport=1234) /
144                           Raw('\xa5' * 100))
145
146         self.pg2.add_stream(pkt_tag_to_tag)
147         self.pg_enable_capture(self.pg_interfaces)
148         self.pg_start()
149         rx = self.pg3.get_capture(1)
150
151         self.assertEqual(rx[0][Ether].dst, pkt_tag_to_tag[Ether].dst)
152         self.assertEqual(rx[0][Ether].src, pkt_tag_to_tag[Ether].src)
153         self.assertEqual(rx[0][Dot1Q].vlan, 93)
154
155         #
156         # Tag to non-Tag
157         #
158         pkt_tag_to_non_tag = (Ether(src=self.pg2.remote_mac,
159                                     dst=self.loop0.local_mac) /
160                               Dot1Q(vlan=92) /
161                               IP(src=any_src_addr,
162                                  dst=ip_non_tag_bridged) /
163                               UDP(sport=1234, dport=1234) /
164                               Raw('\xa5' * 100))
165
166         self.pg2.add_stream(pkt_tag_to_non_tag)
167         self.pg_enable_capture(self.pg_interfaces)
168         self.pg_start()
169         rx = self.pg1.get_capture(1)
170
171         self.assertEqual(rx[0][Ether].dst, pkt_tag_to_tag[Ether].dst)
172         self.assertEqual(rx[0][Ether].src, pkt_tag_to_tag[Ether].src)
173         self.assertFalse(rx[0].haslayer(Dot1Q))
174
175 if __name__ == '__main__':
176     unittest.main(testRunner=VppTestRunner)