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