GBP plugin
[vpp.git] / test / test_gbp.py
1 #!/usr/bin/env python
2
3 import unittest
4 import socket
5 import struct
6
7 from framework import VppTestCase, VppTestRunner
8 from vpp_object import VppObject
9
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether
12 from scapy.layers.inet import IP, UDP
13 from scapy.layers.inet6 import IPv6
14
15 from socket import AF_INET, AF_INET6
16 from scapy.utils import inet_pton
17
18
19 class VppGbpEndpoint(VppObject):
20     """
21     GDB Endpoint
22     """
23
24     def __init__(self, test, sw_if_index, addr, epg, is_ip6=0):
25         self._test = test
26         self.sw_if_index = sw_if_index
27         self.epg = epg
28         self.addr_p = addr
29         self.is_ip6 = is_ip6
30         if is_ip6:
31             self.addr = inet_pton(AF_INET6, addr)
32         else:
33             self.addr = inet_pton(AF_INET, addr)
34
35     def add_vpp_config(self):
36         self._test.vapi.gbp_endpoint_add_del(
37             1,
38             self.sw_if_index,
39             self.addr,
40             self.is_ip6,
41             self.epg)
42         self._test.registry.register(self, self._test.logger)
43
44     def remove_vpp_config(self):
45         self._test.vapi.gbp_endpoint_add_del(
46             0,
47             self.sw_if_index,
48             self.addr,
49             self.is_ip6,
50             self.epg)
51
52     def __str__(self):
53         return self.object_id()
54
55     def object_id(self):
56         return "gbp-endpoint;[%d:%s:%d]" % (self.sw_if_index,
57                                             self.addr_p,
58                                             self.epg)
59
60     def query_vpp_config(self):
61         eps = self._test.vapi.gbp_endpoint_dump()
62         for ep in eps:
63             if ep.endpoint.address == self.addr \
64                and ep.endpoint.sw_if_index == self.sw_if_index:
65                 return True
66         return False
67
68
69 class VppGbpContract(VppObject):
70     """
71     GDB Contract
72     """
73
74     def __init__(self, test, src_epg, dst_epg, acl_index):
75         self._test = test
76         self.acl_index = acl_index
77         self.src_epg = src_epg
78         self.dst_epg = dst_epg
79
80     def add_vpp_config(self):
81         self._test.vapi.gbp_contract_add_del(
82             1,
83             self.src_epg,
84             self.dst_epg,
85             self.acl_index)
86         self._test.registry.register(self, self._test.logger)
87
88     def remove_vpp_config(self):
89         self._test.vapi.gbp_contract_add_del(
90             0,
91             self.src_epg,
92             self.dst_epg,
93             self.acl_index)
94
95     def __str__(self):
96         return self.object_id()
97
98     def object_id(self):
99         return "gbp-contract;[%d:%s:%d]" % (self.src_epg,
100                                             self.dst_epg,
101                                             self.acl_index)
102
103     def query_vpp_config(self):
104         eps = self._test.vapi.gbp_contract_dump()
105         for ep in eps:
106             if ep.contract.src_epg == self.src_epg \
107                and ep.contract.dst_epg == self.dst_epg:
108                 return True
109         return False
110
111
112 class TestGBP(VppTestCase):
113     """ GBP Test Case """
114
115     def setUp(self):
116         super(TestGBP, self).setUp()
117
118         # create 6 pg interfaces for pg0 to pg5
119         self.create_pg_interfaces(range(6))
120
121         for i in self.pg_interfaces:
122             i.admin_up()
123             i.config_ip4()
124             i.resolve_arp()
125             i.config_ip6()
126             i.resolve_ndp()
127
128     def tearDown(self):
129         for i in self.pg_interfaces:
130             i.unconfig_ip4()
131             i.unconfig_ip6()
132
133         super(TestGBP, self).tearDown()
134
135     def test_gbp4(self):
136         """ Group Based Policy v4 """
137
138         ep1 = VppGbpEndpoint(self,
139                              self.pg0.sw_if_index,
140                              self.pg0.remote_ip4,
141                              220)
142         ep1.add_vpp_config()
143         ep2 = VppGbpEndpoint(self,
144                              self.pg1.sw_if_index,
145                              self.pg1.remote_ip4,
146                              220)
147         ep2.add_vpp_config()
148
149         ep3 = VppGbpEndpoint(self,
150                              self.pg2.sw_if_index,
151                              self.pg2.remote_ip4,
152                              221)
153         ep3.add_vpp_config()
154         ep4 = VppGbpEndpoint(self,
155                              self.pg3.sw_if_index,
156                              self.pg3.remote_ip4,
157                              222)
158         ep4.add_vpp_config()
159
160         self.logger.info(self.vapi.cli("sh gbp endpoint"))
161
162         #
163         # in the abscense of policy, endpoints in the same EPG
164         # can communicate
165         #
166         pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
167                                dst=self.pg0.local_mac) /
168                          IP(src=self.pg0.remote_ip4,
169                             dst=self.pg1.remote_ip4) /
170                          UDP(sport=1234, dport=1234) /
171                          Raw('\xa5' * 100))
172
173         self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1)
174
175         #
176         # in the abscense of policy, endpoints in the different EPG
177         # cannot communicate
178         #
179         pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
180                                           dst=self.pg0.local_mac) /
181                                     IP(src=self.pg0.remote_ip4,
182                                        dst=self.pg2.remote_ip4) /
183                                     UDP(sport=1234, dport=1234) /
184                                     Raw('\xa5' * 100))
185         pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
186                                           dst=self.pg0.local_mac) /
187                                     IP(src=self.pg0.remote_ip4,
188                                        dst=self.pg3.remote_ip4) /
189                                     UDP(sport=1234, dport=1234) /
190                                     Raw('\xa5' * 100))
191         pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
192                                           dst=self.pg2.local_mac) /
193                                     IP(src=self.pg2.remote_ip4,
194                                        dst=self.pg0.remote_ip4) /
195                                     UDP(sport=1234, dport=1234) /
196                                     Raw('\xa5' * 100))
197
198         self.send_and_assert_no_replies(self.pg0,
199                                         pkt_inter_epg_220_to_221 * 65)
200         self.send_and_assert_no_replies(self.pg0,
201                                         pkt_inter_epg_221_to_220 * 65)
202
203         #
204         # A uni-directional contract from EPG 220 -> 221
205         #
206         c1 = VppGbpContract(self, 220, 221, 0xffffffff)
207         c1.add_vpp_config()
208
209         self.send_and_expect(self.pg0,
210                              pkt_inter_epg_220_to_221 * 65,
211                              self.pg2)
212         self.send_and_assert_no_replies(self.pg2,
213                                         pkt_inter_epg_221_to_220 * 65)
214
215         #
216         # contract for the return direction
217         #
218         c2 = VppGbpContract(self, 221, 220, 0xffffffff)
219         c2.add_vpp_config()
220
221         self.send_and_expect(self.pg0,
222                              pkt_inter_epg_220_to_221 * 65,
223                              self.pg2)
224         self.send_and_expect(self.pg2,
225                              pkt_inter_epg_221_to_220 * 65,
226                              self.pg0)
227
228         #
229         # check that inter group is still disabled for the groups
230         # not in the contract.
231         #
232         self.send_and_assert_no_replies(self.pg0,
233                                         pkt_inter_epg_220_to_222 * 65)
234
235         self.logger.info(self.vapi.cli("sh gbp contract"))
236
237         #
238         # remove both contracts, traffic stops in both directions
239         #
240         c2.remove_vpp_config()
241         c1.remove_vpp_config()
242
243         self.send_and_assert_no_replies(self.pg2,
244                                         pkt_inter_epg_221_to_220 * 65)
245         self.send_and_assert_no_replies(self.pg0,
246                                         pkt_inter_epg_220_to_221 * 65)
247         self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1)
248
249     def test_gbp6(self):
250         """ Group Based Policy v6 """
251
252         ep1 = VppGbpEndpoint(self,
253                              self.pg0.sw_if_index,
254                              self.pg0.remote_ip6,
255                              220,
256                              is_ip6=1)
257         ep1.add_vpp_config()
258         ep2 = VppGbpEndpoint(self,
259                              self.pg1.sw_if_index,
260                              self.pg1.remote_ip6,
261                              220,
262                              is_ip6=1)
263         ep2.add_vpp_config()
264
265         ep3 = VppGbpEndpoint(self,
266                              self.pg2.sw_if_index,
267                              self.pg2.remote_ip6,
268                              221,
269                              is_ip6=1)
270         ep3.add_vpp_config()
271         ep4 = VppGbpEndpoint(self,
272                              self.pg3.sw_if_index,
273                              self.pg3.remote_ip6,
274                              222,
275                              is_ip6=1)
276         ep4.add_vpp_config()
277
278         self.logger.info(self.vapi.cli("sh gbp endpoint"))
279
280         #
281         # in the abscense of policy, endpoints in the same EPG
282         # can communicate
283         #
284         pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
285                                dst=self.pg0.local_mac) /
286                          IPv6(src=self.pg0.remote_ip6,
287                               dst=self.pg1.remote_ip6) /
288                          UDP(sport=1234, dport=1234) /
289                          Raw('\xa5' * 100))
290
291         self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1)
292
293         #
294         # in the abscense of policy, endpoints in the different EPG
295         # cannot communicate
296         #
297         pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
298                                           dst=self.pg0.local_mac) /
299                                     IPv6(src=self.pg0.remote_ip6,
300                                          dst=self.pg2.remote_ip6) /
301                                     UDP(sport=1234, dport=1234) /
302                                     Raw('\xa5' * 100))
303         pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
304                                           dst=self.pg0.local_mac) /
305                                     IPv6(src=self.pg0.remote_ip6,
306                                          dst=self.pg3.remote_ip6) /
307                                     UDP(sport=1234, dport=1234) /
308                                     Raw('\xa5' * 100))
309         pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
310                                           dst=self.pg2.local_mac) /
311                                     IPv6(src=self.pg2.remote_ip6,
312                                          dst=self.pg0.remote_ip6) /
313                                     UDP(sport=1234, dport=1234) /
314                                     Raw('\xa5' * 100))
315
316         self.send_and_assert_no_replies(self.pg0,
317                                         pkt_inter_epg_220_to_221 * 65)
318         self.send_and_assert_no_replies(self.pg0,
319                                         pkt_inter_epg_221_to_220 * 65)
320
321         #
322         # A uni-directional contract from EPG 220 -> 221
323         #
324         c1 = VppGbpContract(self, 220, 221, 0xffffffff)
325         c1.add_vpp_config()
326
327         self.send_and_expect(self.pg0,
328                              pkt_inter_epg_220_to_221 * 65,
329                              self.pg2)
330         self.send_and_assert_no_replies(self.pg2,
331                                         pkt_inter_epg_221_to_220 * 65)
332
333         #
334         # contract for the return direction
335         #
336         c2 = VppGbpContract(self, 221, 220, 0xffffffff)
337         c2.add_vpp_config()
338
339         self.send_and_expect(self.pg0,
340                              pkt_inter_epg_220_to_221 * 65,
341                              self.pg2)
342         self.send_and_expect(self.pg2,
343                              pkt_inter_epg_221_to_220 * 65,
344                              self.pg0)
345
346         #
347         # check that inter group is still disabled for the groups
348         # not in the contract.
349         #
350         self.send_and_assert_no_replies(self.pg0,
351                                         pkt_inter_epg_220_to_222 * 65)
352
353         self.logger.info(self.vapi.cli("sh gbp contract"))
354
355         #
356         # remove both contracts, traffic stops in both directions
357         #
358         c2.remove_vpp_config()
359         c1.remove_vpp_config()
360
361         self.send_and_assert_no_replies(self.pg2,
362                                         pkt_inter_epg_221_to_220 * 65)
363         self.send_and_assert_no_replies(self.pg0,
364                                         pkt_inter_epg_220_to_221 * 65)
365         self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1)
366
367
368 if __name__ == '__main__':
369     unittest.main(testRunner=VppTestRunner)