IGMP: proxy device
[vpp.git] / test / test_svs.py
1 #!/usr/bin/env python
2
3 from framework import VppTestCase, VppTestRunner
4 from vpp_ip import IpAddressFamily, 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
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(IpAddressFamily.ADDRESS_IP4, table_id)
98
99             #
100             # map X.0.0.0/8 to each SVS table for lookup in table X
101             #
102             for i in range(1, 4):
103                 self.vapi.svs_route_add_del(
104                     table_id,
105                     VppIpPrefix("%d.0.0.0" % i, 8).encode(),
106                     i)
107
108         #
109         # Enable SVS on pg0/pg1 using table 1001/1002
110         #
111         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP4,
112                                      table_ids[0],
113                                      self.pg0.sw_if_index)
114         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP4,
115                                      table_ids[1],
116                                      self.pg1.sw_if_index)
117
118         #
119         # now all the packets should be delivered out the respective interface
120         #
121         self.send_and_expect(self.pg0, pkts_0[0] * 65, self.pg1)
122         self.send_and_expect(self.pg0, pkts_0[1] * 65, self.pg2)
123         self.send_and_expect(self.pg0, pkts_0[2] * 65, self.pg3)
124         self.send_and_expect(self.pg1, pkts_1[0] * 65, self.pg1)
125         self.send_and_expect(self.pg1, pkts_1[1] * 65, self.pg2)
126         self.send_and_expect(self.pg1, pkts_1[2] * 65, self.pg3)
127
128         #
129         # check that if the SVS lookup does not match a route the packet
130         # is forwarded using the interface's routing table
131         #
132         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
133              IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
134              UDP(sport=1234, dport=1234) /
135              Raw('\xa5' * 100))
136         self.send_and_expect(self.pg0, p * 65, self.pg0)
137
138         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
139              IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4) /
140              UDP(sport=1234, dport=1234) /
141              Raw('\xa5' * 100))
142         self.send_and_expect(self.pg1, p * 65, self.pg1)
143
144         #
145         # dump the SVS configs
146         #
147         ss = self.vapi.svs_dump()
148
149         self.assertEqual(ss[0].table_id, table_ids[0])
150         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
151         self.assertEqual(ss[0].af, IpAddressFamily.ADDRESS_IP4)
152         self.assertEqual(ss[1].table_id, table_ids[1])
153         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
154         self.assertEqual(ss[1].af, IpAddressFamily.ADDRESS_IP4)
155
156         #
157         # cleanup
158         #
159         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP4,
160                                      table_ids[0],
161                                      self.pg0.sw_if_index,
162                                      is_enable=0)
163         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP4,
164                                      table_ids[1],
165                                      self.pg1.sw_if_index,
166                                      is_enable=0)
167
168         for table_id in table_ids:
169             for i in range(1, 4):
170                 self.vapi.svs_route_add_del(
171                     table_id,
172                     VppIpPrefix("%d.0.0.0" % i, 8).encode(),
173                     0, is_add=0)
174             self.vapi.svs_table_add_del(IpAddressFamily.ADDRESS_IP4,
175                                         table_id,
176                                         is_add=0)
177
178     def test_svs6(self):
179         """ Source VRF Select IP6 """
180
181         #
182         # packets destinet out of the 3 non-default table interfaces
183         #
184         pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
185                    IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
186                    UDP(sport=1234, dport=1234) /
187                    Raw('\xa5' * 100)),
188                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
189                    IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
190                    UDP(sport=1234, dport=1234) /
191                    Raw('\xa5' * 100)),
192                   (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
193                    IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
194                    UDP(sport=1234, dport=1234) /
195                    Raw('\xa5' * 100))]
196         pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
197                    IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
198                    UDP(sport=1234, dport=1234) /
199                    Raw('\xa5' * 100)),
200                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
201                    IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
202                    UDP(sport=1234, dport=1234) /
203                    Raw('\xa5' * 100)),
204                   (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
205                    IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
206                    UDP(sport=1234, dport=1234) /
207                    Raw('\xa5' * 100))]
208
209         #
210         # before adding the SVS config all these packets are dropped when
211         # ingressing on pg0 since pg0 is in the default table
212         #
213         for p in pkts_0:
214             self.send_and_assert_no_replies(self.pg0, p * 1)
215
216         #
217         # Add table 1001 & 1002 into which we'll add the routes
218         # determing the source VRF selection
219         #
220         table_ids = [101, 102]
221
222         for table_id in table_ids:
223             self.vapi.svs_table_add_del(IpAddressFamily.ADDRESS_IP6, table_id)
224
225             #
226             # map X.0.0.0/8 to each SVS table for lookup in table X
227             #
228             for i in range(1, 4):
229                 self.vapi.svs_route_add_del(
230                     table_id,
231                     VppIpPrefix("2001:%d::" % i, 32).encode(),
232                     i)
233
234         #
235         # Enable SVS on pg0/pg1 using table 1001/1002
236         #
237         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP6,
238                                      table_ids[0],
239                                      self.pg0.sw_if_index)
240         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP6,
241                                      table_ids[1],
242                                      self.pg1.sw_if_index)
243
244         #
245         # now all the packets should be delivered out the respective interface
246         #
247         self.send_and_expect(self.pg0, pkts_0[0] * 65, self.pg1)
248         self.send_and_expect(self.pg0, pkts_0[1] * 65, self.pg2)
249         self.send_and_expect(self.pg0, pkts_0[2] * 65, self.pg3)
250         self.send_and_expect(self.pg1, pkts_1[0] * 65, self.pg1)
251         self.send_and_expect(self.pg1, pkts_1[1] * 65, self.pg2)
252         self.send_and_expect(self.pg1, pkts_1[2] * 65, self.pg3)
253
254         #
255         # check that if the SVS lookup does not match a route the packet
256         # is forwarded using the interface's routing table
257         #
258         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
259              IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
260              UDP(sport=1234, dport=1234) /
261              Raw('\xa5' * 100))
262         self.send_and_expect(self.pg0, p * 65, self.pg0)
263
264         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
265              IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
266              UDP(sport=1234, dport=1234) /
267              Raw('\xa5' * 100))
268         self.send_and_expect(self.pg1, p * 65, self.pg1)
269
270         #
271         # dump the SVS configs
272         #
273         ss = self.vapi.svs_dump()
274
275         self.assertEqual(ss[0].table_id, table_ids[0])
276         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
277         self.assertEqual(ss[0].af, IpAddressFamily.ADDRESS_IP6)
278         self.assertEqual(ss[1].table_id, table_ids[1])
279         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
280         self.assertEqual(ss[1].af, IpAddressFamily.ADDRESS_IP6)
281
282         #
283         # cleanup
284         #
285         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP6,
286                                      table_ids[0],
287                                      self.pg0.sw_if_index,
288                                      is_enable=0)
289         self.vapi.svs_enable_disable(IpAddressFamily.ADDRESS_IP6,
290                                      table_ids[1],
291                                      self.pg1.sw_if_index,
292                                      is_enable=0)
293         for table_id in table_ids:
294             for i in range(1, 4):
295                 self.vapi.svs_route_add_del(
296                     table_id,
297                     VppIpPrefix("2001:%d::" % i, 32).encode(),
298                     0, is_add=0)
299             self.vapi.svs_table_add_del(IpAddressFamily.ADDRESS_IP6,
300                                         table_id,
301                                         is_add=0)
302
303 if __name__ == '__main__':
304     unittest.main(testRunner=VppTestRunner)