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