blob: b4e6722baa8f3cb17c25346e88f5fc4d1f23807a [file] [log] [blame]
Neale Rannsccc70f62018-10-02 07:28:16 -07001#!/usr/bin/env python
2
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07003import unittest
4
Neale Rannsccc70f62018-10-02 07:28:16 -07005from framework import VppTestCase, VppTestRunner
Neale Rannsccc70f62018-10-02 07:28:16 -07006from vpp_ip_route import VppIpTable
7
8from scapy.packet import Raw
9from scapy.layers.l2 import Ether
10from scapy.layers.inet import IP, UDP, ICMP
11from scapy.layers.inet6 import IPv6
12
Ole Troan0685da42018-10-16 14:42:50 +020013from vpp_papi import VppEnum
14
Neale Rannsccc70f62018-10-02 07:28:16 -070015
16class TestSVS(VppTestCase):
17 """ SVS Test Case """
18
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070019 @classmethod
20 def setUpClass(cls):
21 super(TestSVS, cls).setUpClass()
22
23 @classmethod
24 def tearDownClass(cls):
25 super(TestSVS, cls).tearDownClass()
26
Neale Rannsccc70f62018-10-02 07:28:16 -070027 def setUp(self):
28 super(TestSVS, self).setUp()
29
30 # create 2 pg interfaces
31 self.create_pg_interfaces(range(4))
32
33 table_id = 0
34
35 for i in self.pg_interfaces:
36 i.admin_up()
37
38 if table_id != 0:
39 tbl = VppIpTable(self, table_id)
40 tbl.add_vpp_config()
41 tbl = VppIpTable(self, table_id, is_ip6=1)
42 tbl.add_vpp_config()
43
44 i.set_table_ip4(table_id)
45 i.set_table_ip6(table_id)
46 i.config_ip4()
47 i.resolve_arp()
48 i.config_ip6()
49 i.resolve_ndp()
50 table_id += 1
51
52 def tearDown(self):
53 for i in self.pg_interfaces:
54 i.unconfig_ip4()
55 i.unconfig_ip6()
56 i.ip6_disable()
57 i.set_table_ip4(0)
58 i.set_table_ip6(0)
59 i.admin_down()
60 super(TestSVS, self).tearDown()
61
62 def test_svs4(self):
63 """ Source VRF Select IP4 """
64
65 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -070066 # packets destined out of the 3 non-default table interfaces
Neale Rannsccc70f62018-10-02 07:28:16 -070067 #
68 pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
69 IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
70 UDP(sport=1234, dport=1234) /
71 Raw('\xa5' * 100)),
72 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
73 IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
74 UDP(sport=1234, dport=1234) /
75 Raw('\xa5' * 100)),
76 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
77 IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
78 UDP(sport=1234, dport=1234) /
79 Raw('\xa5' * 100))]
80 pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
81 IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
82 UDP(sport=1234, dport=1234) /
83 Raw('\xa5' * 100)),
84 (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
85 IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
86 UDP(sport=1234, dport=1234) /
87 Raw('\xa5' * 100)),
88 (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
89 IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
90 UDP(sport=1234, dport=1234) /
91 Raw('\xa5' * 100))]
92
93 #
94 # before adding the SVS config all these packets are dropped when
95 # ingressing on pg0 since pg0 is in the default table
96 #
97 for p in pkts_0:
98 self.send_and_assert_no_replies(self.pg0, p * 1)
99
100 #
101 # Add table 1001 & 1002 into which we'll add the routes
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700102 # determining the source VRF selection
Neale Rannsccc70f62018-10-02 07:28:16 -0700103 #
104 table_ids = [101, 102]
105
106 for table_id in table_ids:
Ole Troan0685da42018-10-16 14:42:50 +0200107 self.vapi.svs_table_add_del(
108 VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_id)
Neale Rannsccc70f62018-10-02 07:28:16 -0700109
110 #
111 # map X.0.0.0/8 to each SVS table for lookup in table X
112 #
113 for i in range(1, 4):
114 self.vapi.svs_route_add_del(
Ole Troan31555a32018-10-22 09:30:26 +0200115 table_id, "%d.0.0.0/8" % i, i)
Neale Rannsccc70f62018-10-02 07:28:16 -0700116
117 #
118 # Enable SVS on pg0/pg1 using table 1001/1002
119 #
Ole Troan0685da42018-10-16 14:42:50 +0200120 self.vapi.svs_enable_disable(
121 VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[0],
122 self.pg0.sw_if_index)
123 self.vapi.svs_enable_disable(
124 VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[1],
125 self.pg1.sw_if_index)
Neale Rannsccc70f62018-10-02 07:28:16 -0700126
127 #
128 # now all the packets should be delivered out the respective interface
129 #
130 self.send_and_expect(self.pg0, pkts_0[0] * 65, self.pg1)
131 self.send_and_expect(self.pg0, pkts_0[1] * 65, self.pg2)
132 self.send_and_expect(self.pg0, pkts_0[2] * 65, self.pg3)
133 self.send_and_expect(self.pg1, pkts_1[0] * 65, self.pg1)
134 self.send_and_expect(self.pg1, pkts_1[1] * 65, self.pg2)
135 self.send_and_expect(self.pg1, pkts_1[2] * 65, self.pg3)
136
137 #
138 # check that if the SVS lookup does not match a route the packet
139 # is forwarded using the interface's routing table
140 #
141 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
142 IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
143 UDP(sport=1234, dport=1234) /
144 Raw('\xa5' * 100))
145 self.send_and_expect(self.pg0, p * 65, self.pg0)
146
147 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
148 IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4) /
149 UDP(sport=1234, dport=1234) /
150 Raw('\xa5' * 100))
151 self.send_and_expect(self.pg1, p * 65, self.pg1)
152
153 #
154 # dump the SVS configs
155 #
156 ss = self.vapi.svs_dump()
157
158 self.assertEqual(ss[0].table_id, table_ids[0])
159 self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
Ole Troan0685da42018-10-16 14:42:50 +0200160 self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
Neale Rannsccc70f62018-10-02 07:28:16 -0700161 self.assertEqual(ss[1].table_id, table_ids[1])
162 self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
Ole Troan0685da42018-10-16 14:42:50 +0200163 self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
Neale Rannsccc70f62018-10-02 07:28:16 -0700164
165 #
166 # cleanup
167 #
Ole Troan0685da42018-10-16 14:42:50 +0200168 self.vapi.svs_enable_disable(
169 VppEnum.vl_api_address_family_t.ADDRESS_IP4,
170 table_ids[0],
171 self.pg0.sw_if_index,
172 is_enable=0)
173 self.vapi.svs_enable_disable(
174 VppEnum.vl_api_address_family_t.ADDRESS_IP4,
175 table_ids[1],
176 self.pg1.sw_if_index,
177 is_enable=0)
Neale Rannsccc70f62018-10-02 07:28:16 -0700178
179 for table_id in table_ids:
180 for i in range(1, 4):
181 self.vapi.svs_route_add_del(
Ole Troan31555a32018-10-22 09:30:26 +0200182 table_id, "%d.0.0.0/8" % i,
Neale Rannsccc70f62018-10-02 07:28:16 -0700183 0, is_add=0)
Ole Troan0685da42018-10-16 14:42:50 +0200184 self.vapi.svs_table_add_del(
185 VppEnum.vl_api_address_family_t.ADDRESS_IP4,
186 table_id,
187 is_add=0)
Neale Rannsccc70f62018-10-02 07:28:16 -0700188
189 def test_svs6(self):
190 """ Source VRF Select IP6 """
191
192 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700193 # packets destined out of the 3 non-default table interfaces
Neale Rannsccc70f62018-10-02 07:28:16 -0700194 #
195 pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
196 IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
197 UDP(sport=1234, dport=1234) /
198 Raw('\xa5' * 100)),
199 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
200 IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
201 UDP(sport=1234, dport=1234) /
202 Raw('\xa5' * 100)),
203 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
204 IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
205 UDP(sport=1234, dport=1234) /
206 Raw('\xa5' * 100))]
207 pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
208 IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
209 UDP(sport=1234, dport=1234) /
210 Raw('\xa5' * 100)),
211 (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
212 IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
213 UDP(sport=1234, dport=1234) /
214 Raw('\xa5' * 100)),
215 (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
216 IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
217 UDP(sport=1234, dport=1234) /
218 Raw('\xa5' * 100))]
219
220 #
221 # before adding the SVS config all these packets are dropped when
222 # ingressing on pg0 since pg0 is in the default table
223 #
224 for p in pkts_0:
225 self.send_and_assert_no_replies(self.pg0, p * 1)
226
227 #
228 # Add table 1001 & 1002 into which we'll add the routes
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700229 # determining the source VRF selection
Neale Rannsccc70f62018-10-02 07:28:16 -0700230 #
231 table_ids = [101, 102]
232
233 for table_id in table_ids:
Ole Troan0685da42018-10-16 14:42:50 +0200234 self.vapi.svs_table_add_del(
235 VppEnum.vl_api_address_family_t.ADDRESS_IP6, table_id)
Neale Rannsccc70f62018-10-02 07:28:16 -0700236
237 #
238 # map X.0.0.0/8 to each SVS table for lookup in table X
239 #
240 for i in range(1, 4):
241 self.vapi.svs_route_add_del(
Ole Troan31555a32018-10-22 09:30:26 +0200242 table_id, "2001:%d::/32" % i,
Neale Rannsccc70f62018-10-02 07:28:16 -0700243 i)
244
245 #
246 # Enable SVS on pg0/pg1 using table 1001/1002
247 #
Ole Troan0685da42018-10-16 14:42:50 +0200248 self.vapi.svs_enable_disable(
249 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
250 table_ids[0],
251 self.pg0.sw_if_index)
252 self.vapi.svs_enable_disable(
253 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
254 table_ids[1],
255 self.pg1.sw_if_index)
Neale Rannsccc70f62018-10-02 07:28:16 -0700256
257 #
258 # now all the packets should be delivered out the respective interface
259 #
260 self.send_and_expect(self.pg0, pkts_0[0] * 65, self.pg1)
261 self.send_and_expect(self.pg0, pkts_0[1] * 65, self.pg2)
262 self.send_and_expect(self.pg0, pkts_0[2] * 65, self.pg3)
263 self.send_and_expect(self.pg1, pkts_1[0] * 65, self.pg1)
264 self.send_and_expect(self.pg1, pkts_1[1] * 65, self.pg2)
265 self.send_and_expect(self.pg1, pkts_1[2] * 65, self.pg3)
266
267 #
268 # check that if the SVS lookup does not match a route the packet
269 # is forwarded using the interface's routing table
270 #
271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
272 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
273 UDP(sport=1234, dport=1234) /
274 Raw('\xa5' * 100))
275 self.send_and_expect(self.pg0, p * 65, self.pg0)
276
277 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
278 IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
279 UDP(sport=1234, dport=1234) /
280 Raw('\xa5' * 100))
281 self.send_and_expect(self.pg1, p * 65, self.pg1)
282
283 #
284 # dump the SVS configs
285 #
286 ss = self.vapi.svs_dump()
287
288 self.assertEqual(ss[0].table_id, table_ids[0])
289 self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
Ole Troan0685da42018-10-16 14:42:50 +0200290 self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
Neale Rannsccc70f62018-10-02 07:28:16 -0700291 self.assertEqual(ss[1].table_id, table_ids[1])
292 self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
Ole Troan0685da42018-10-16 14:42:50 +0200293 self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
Neale Rannsccc70f62018-10-02 07:28:16 -0700294
295 #
296 # cleanup
297 #
Ole Troan0685da42018-10-16 14:42:50 +0200298 self.vapi.svs_enable_disable(
299 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
300 table_ids[0],
301 self.pg0.sw_if_index,
302 is_enable=0)
303 self.vapi.svs_enable_disable(
304 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
305 table_ids[1],
306 self.pg1.sw_if_index,
307 is_enable=0)
Neale Rannsccc70f62018-10-02 07:28:16 -0700308 for table_id in table_ids:
309 for i in range(1, 4):
310 self.vapi.svs_route_add_del(
Ole Troan31555a32018-10-22 09:30:26 +0200311 table_id, "2001:%d::/32" % i,
Neale Rannsccc70f62018-10-02 07:28:16 -0700312 0, is_add=0)
Ole Troan0685da42018-10-16 14:42:50 +0200313 self.vapi.svs_table_add_del(
314 VppEnum.vl_api_address_family_t.ADDRESS_IP6,
315 table_id,
316 is_add=0)
317
Neale Rannsccc70f62018-10-02 07:28:16 -0700318
319if __name__ == '__main__':
320 unittest.main(testRunner=VppTestRunner)