misc: Fix python scripts shebang line
[vpp.git] / src / plugins / svs / test / test_svs.py
1 #!/usr/bin/env python3
2
3 import unittest
4
5 from framework import VppTestCase, VppTestRunner
6 from vpp_ip_route import VppIpTable
7
8 from scapy.packet import Raw
9 from scapy.layers.l2 import Ether
10 from scapy.layers.inet import IP, UDP, ICMP
11 from scapy.layers.inet6 import IPv6
12
13 from vpp_papi import VppEnum
14
15 NUM_PKTS = 67
16
17
18 class TestSVS(VppTestCase):
19     """ SVS Test Case """
20
21     @classmethod
22     def setUpClass(cls):
23         super(TestSVS, cls).setUpClass()
24
25     @classmethod
26     def tearDownClass(cls):
27         super(TestSVS, cls).tearDownClass()
28
29     def setUp(self):
30         super(TestSVS, self).setUp()
31
32         # create 2 pg interfaces
33         self.create_pg_interfaces(range(4))
34
35         table_id = 0
36
37         for i in self.pg_interfaces:
38             i.admin_up()
39
40             if table_id != 0:
41                 tbl = VppIpTable(self, table_id)
42                 tbl.add_vpp_config()
43                 tbl = VppIpTable(self, table_id, is_ip6=1)
44                 tbl.add_vpp_config()
45
46             i.set_table_ip4(table_id)
47             i.set_table_ip6(table_id)
48             i.config_ip4()
49             i.resolve_arp()
50             i.config_ip6()
51             i.resolve_ndp()
52             table_id += 1
53
54     def tearDown(self):
55         for i in self.pg_interfaces:
56             i.unconfig_ip4()
57             i.unconfig_ip6()
58             i.ip6_disable()
59             i.set_table_ip4(0)
60             i.set_table_ip6(0)
61             i.admin_down()
62         super(TestSVS, self).tearDown()
63
64     def test_svs4(self):
65         """ Source VRF Select IP4 """
66
67         #
68         # packets destined out of the 3 non-default table interfaces
69         #
70         pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
71                    IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
72                    UDP(sport=1234, dport=1234) /
73                    Raw('\xa5' * 100)),
74                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
75                    IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
76                    UDP(sport=1234, dport=1234) /
77                    Raw('\xa5' * 100)),
78                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
79                    IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
80                    UDP(sport=1234, dport=1234) /
81                    Raw('\xa5' * 100))]
82         pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
83                    IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
84                    UDP(sport=1234, dport=1234) /
85                    Raw('\xa5' * 100)),
86                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
87                    IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
88                    UDP(sport=1234, dport=1234) /
89                    Raw('\xa5' * 100)),
90                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
91                    IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
92                    UDP(sport=1234, dport=1234) /
93                    Raw('\xa5' * 100))]
94
95         #
96         # before adding the SVS config all these packets are dropped when
97         # ingressing on pg0 since pg0 is in the default table
98         #
99         for p in pkts_0:
100             self.send_and_assert_no_replies(self.pg0, p * 1)
101
102         #
103         # Add table 1001 & 1002 into which we'll add the routes
104         # determining the source VRF selection
105         #
106         table_ids = [101, 102]
107
108         for table_id in table_ids:
109             self.vapi.svs_table_add_del(
110                 VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_id)
111
112             #
113             # map X.0.0.0/8 to each SVS table for lookup in table X
114             #
115             for i in range(1, 4):
116                 self.vapi.svs_route_add_del(
117                     table_id, "%d.0.0.0/8" % i, i)
118
119         #
120         # Enable SVS on pg0/pg1 using table 1001/1002
121         #
122         self.vapi.svs_enable_disable(
123             VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[0],
124             self.pg0.sw_if_index)
125         self.vapi.svs_enable_disable(
126             VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[1],
127             self.pg1.sw_if_index)
128
129         #
130         # now all the packets should be delivered out the respective interface
131         #
132         self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
133         self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
134         self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
135         self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
136         self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
137         self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
138
139         #
140         # check that if the SVS lookup does not match a route the packet
141         # is forwarded using the interface's routing table
142         #
143         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
144              IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
145              UDP(sport=1234, dport=1234) /
146              Raw('\xa5' * 100))
147         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
148
149         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
150              IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4) /
151              UDP(sport=1234, dport=1234) /
152              Raw('\xa5' * 100))
153         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
154
155         #
156         # dump the SVS configs
157         #
158         ss = self.vapi.svs_dump()
159
160         self.assertEqual(ss[0].table_id, table_ids[0])
161         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
162         self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
163         self.assertEqual(ss[1].table_id, table_ids[1])
164         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
165         self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
166
167         #
168         # cleanup
169         #
170         self.vapi.svs_enable_disable(
171             VppEnum.vl_api_address_family_t.ADDRESS_IP4,
172             table_ids[0],
173             self.pg0.sw_if_index,
174             is_enable=0)
175         self.vapi.svs_enable_disable(
176             VppEnum.vl_api_address_family_t.ADDRESS_IP4,
177             table_ids[1],
178             self.pg1.sw_if_index,
179             is_enable=0)
180
181         for table_id in table_ids:
182             for i in range(1, 4):
183                 self.vapi.svs_route_add_del(
184                     table_id, "%d.0.0.0/8" % i,
185                     0, is_add=0)
186             self.vapi.svs_table_add_del(
187                 VppEnum.vl_api_address_family_t.ADDRESS_IP4,
188                 table_id,
189                 is_add=0)
190
191     def test_svs6(self):
192         """ Source VRF Select IP6 """
193
194         #
195         # packets destined out of the 3 non-default table interfaces
196         #
197         pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
198                    IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
199                    UDP(sport=1234, dport=1234) /
200                    Raw('\xa5' * 100)),
201                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
202                    IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
203                    UDP(sport=1234, dport=1234) /
204                    Raw('\xa5' * 100)),
205                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
206                    IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
207                    UDP(sport=1234, dport=1234) /
208                    Raw('\xa5' * 100))]
209         pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
210                    IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
211                    UDP(sport=1234, dport=1234) /
212                    Raw('\xa5' * 100)),
213                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
214                    IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
215                    UDP(sport=1234, dport=1234) /
216                    Raw('\xa5' * 100)),
217                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
218                    IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
219                    UDP(sport=1234, dport=1234) /
220                    Raw('\xa5' * 100))]
221
222         #
223         # before adding the SVS config all these packets are dropped when
224         # ingressing on pg0 since pg0 is in the default table
225         #
226         for p in pkts_0:
227             self.send_and_assert_no_replies(self.pg0, p * 1)
228
229         #
230         # Add table 1001 & 1002 into which we'll add the routes
231         # determining the source VRF selection
232         #
233         table_ids = [101, 102]
234
235         for table_id in table_ids:
236             self.vapi.svs_table_add_del(
237                 VppEnum.vl_api_address_family_t.ADDRESS_IP6, table_id)
238
239             #
240             # map X.0.0.0/8 to each SVS table for lookup in table X
241             #
242             for i in range(1, 4):
243                 self.vapi.svs_route_add_del(
244                     table_id, "2001:%d::/32" % i,
245                     i)
246
247         #
248         # Enable SVS on pg0/pg1 using table 1001/1002
249         #
250         self.vapi.svs_enable_disable(
251             VppEnum.vl_api_address_family_t.ADDRESS_IP6,
252             table_ids[0],
253             self.pg0.sw_if_index)
254         self.vapi.svs_enable_disable(
255             VppEnum.vl_api_address_family_t.ADDRESS_IP6,
256             table_ids[1],
257             self.pg1.sw_if_index)
258
259         #
260         # now all the packets should be delivered out the respective interface
261         #
262         self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
263         self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
264         self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
265         self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
266         self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
267         self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
268
269         #
270         # check that if the SVS lookup does not match a route the packet
271         # is forwarded using the interface's routing table
272         #
273         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
274              IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
275              UDP(sport=1234, dport=1234) /
276              Raw('\xa5' * 100))
277         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
278
279         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
280              IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
281              UDP(sport=1234, dport=1234) /
282              Raw('\xa5' * 100))
283         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
284
285         #
286         # dump the SVS configs
287         #
288         ss = self.vapi.svs_dump()
289
290         self.assertEqual(ss[0].table_id, table_ids[0])
291         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
292         self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
293         self.assertEqual(ss[1].table_id, table_ids[1])
294         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
295         self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
296
297         #
298         # cleanup
299         #
300         self.vapi.svs_enable_disable(
301             VppEnum.vl_api_address_family_t.ADDRESS_IP6,
302             table_ids[0],
303             self.pg0.sw_if_index,
304             is_enable=0)
305         self.vapi.svs_enable_disable(
306             VppEnum.vl_api_address_family_t.ADDRESS_IP6,
307             table_ids[1],
308             self.pg1.sw_if_index,
309             is_enable=0)
310         for table_id in table_ids:
311             for i in range(1, 4):
312                 self.vapi.svs_route_add_del(
313                     table_id, "2001:%d::/32" % i,
314                     0, is_add=0)
315             self.vapi.svs_table_add_del(
316                 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
317                 table_id,
318                 is_add=0)
319
320
321 if __name__ == '__main__':
322     unittest.main(testRunner=VppTestRunner)