IGMP: proxy device
[vpp.git] / test / lisp.py
1 from random import randint
2 from socket import AF_INET, AF_INET6
3 from scapy.all import *
4 from scapy.packet import *
5 from scapy.fields import *
6 from lisp import *
7 from framework import *
8 from vpp_object import *
9
10
11 class VppLispLocatorSet(VppObject):
12     """ Represents LISP locator set in VPP """
13
14     def __init__(self, test, ls_name):
15         self._test = test
16         self._ls_name = ls_name
17
18     @property
19     def test(self):
20         return self._test
21
22     @property
23     def ls_name(self):
24         return self._ls_name
25
26     def add_vpp_config(self):
27         self.test.vapi.lisp_locator_set(ls_name=self._ls_name)
28         self._test.registry.register(self, self.test.logger)
29
30     def get_lisp_locator_sets_dump_entry(self):
31         result = self.test.vapi.lisp_locator_set_dump()
32         for ls in result:
33             if ls.ls_name.strip('\x00') == self._ls_name:
34                 return ls
35         return None
36
37     def query_vpp_config(self):
38         return self.get_lisp_locator_sets_dump_entry() is not None
39
40     def remove_vpp_config(self):
41         self.test.vapi.lisp_locator_set(ls_name=self._ls_name, is_add=0)
42
43     def object_id(self):
44         return 'lisp-locator-set-%s' % self._ls_name
45
46
47 class VppLispLocator(VppObject):
48     """ Represents LISP locator in VPP """
49
50     def __init__(self, test, sw_if_index, ls_name, priority=1, weight=1):
51         self._test = test
52         self._sw_if_index = sw_if_index
53         self._ls_name = ls_name
54         self._priority = priority
55         self._weight = weight
56
57     @property
58     def test(self):
59         """ Test which created this locator """
60         return self._test
61
62     @property
63     def ls_name(self):
64         """ Locator set name """
65         return self._ls_name
66
67     @property
68     def sw_if_index(self):
69         return self._sw_if_index
70
71     @property
72     def priority(self):
73         return self.priority
74
75     @property
76     def weight(self):
77         return self._weight
78
79     def add_vpp_config(self):
80         self.test.vapi.lisp_locator(ls_name=self._ls_name,
81                                     sw_if_index=self._sw_if_index,
82                                     priority=self._priority,
83                                     weight=self._weight)
84         self._test.registry.register(self, self.test.logger)
85
86     def get_lisp_locator_dump_entry(self):
87         locators = self.test.vapi.lisp_locator_dump(
88                 is_index_set=0, ls_name=self._ls_name)
89         for locator in locators:
90             if locator.sw_if_index == self._sw_if_index:
91                 return locator
92         return None
93
94     def query_vpp_config(self):
95         locator = self.get_lisp_locator_dump_entry()
96         return locator is not None
97
98     def remove_vpp_config(self):
99         self.test.vapi.lisp_locator(
100                 ls_name=self._ls_name, sw_if_index=self._sw_if_index,
101                 priority=self._priority, weight=self._weight, is_add=0)
102         self._test.registry.register(self, self.test.logger)
103
104     def object_id(self):
105         return 'lisp-locator-%s-%d' % (self._ls_name, self._sw_if_index)
106
107
108 class LispEIDType(object):
109     IP4 = 0
110     IP6 = 1
111     MAC = 2
112
113
114 class LispKeyIdType(object):
115     NONE = 0
116     SHA1 = 1
117     SHA256 = 2
118
119
120 class LispEID(object):
121     """ Lisp endpoint identifier """
122     def __init__(self, eid):
123         self.eid = eid
124
125         # find out whether EID is ip4 prefix, ip6 prefix or MAC
126         if self.eid.find("/") != -1:
127             if self.eid.find(":") == -1:
128                 self.eid_type = LispEIDType.IP4
129                 self.data_length = 4
130             else:
131                 self.eid_type = LispEIDType.IP6
132                 self.data_length = 16
133
134             self.eid_address = self.eid.split("/")[0]
135             self.prefix_length = int(self.eid.split("/")[1])
136         elif self.eid.count(":") == 5:  # MAC address
137             self.eid_type = LispEIDType.MAC
138             self.eid_address = self.eid
139             self.prefix_length = 0
140             self.data_length = 6
141         else:
142             raise Exception('Unsupported EID format {}!'.format(eid))
143
144     def __str__(self):
145         if self.eid_type == LispEIDType.IP4:
146             return socket.inet_pton(socket.AF_INET, self.eid_address)
147         elif self.eid_type == LispEIDType.IP6:
148             return socket.inet_pton(socket.AF_INET6, self.eid_address)
149         elif self.eid_type == LispEIDType.MAC:
150             return Exception('Unimplemented')
151         raise Exception('Unknown EID type {}!'.format(self.eid_type))
152
153
154 class VppLispMapping(VppObject):
155     """ Represents common features for remote and local LISP mapping in VPP """
156
157     def __init__(self, test, eid, vni=0, priority=1, weight=1):
158         self._eid = LispEID(eid)
159         self._test = test
160         self._priority = priority
161         self._weight = weight
162         self._vni = vni
163
164     @property
165     def test(self):
166         return self._test
167
168     @property
169     def vni(self):
170         return self._vni
171
172     @property
173     def eid(self):
174         return self._eid
175
176     @property
177     def priority(self):
178         return self._priority
179
180     @property
181     def weight(self):
182         return self._weight
183
184     def get_lisp_mapping_dump_entry(self):
185         return self.test.vapi.lisp_eid_table_dump(
186                 eid_set=1, prefix_length=self._eid.prefix_length,
187                 vni=self._vni, eid_type=self._eid.eid_type, eid=str(self._eid))
188
189     def query_vpp_config(self):
190         mapping = self.get_lisp_mapping_dump_entry()
191         return mapping
192
193
194 class VppLocalMapping(VppLispMapping):
195     """ LISP Local mapping """
196     def __init__(self, test, eid, ls_name, vni=0, priority=1, weight=1,
197                  key_id=LispKeyIdType.NONE, key=''):
198         super(VppLocalMapping, self).__init__(test, eid, vni, priority, weight)
199         self._ls_name = ls_name
200         self._key_id = key_id
201         self._key = key
202
203     @property
204     def ls_name(self):
205         return self._ls_name
206
207     @property
208     def key_id(self):
209         return self._key_id
210
211     @property
212     def key(self):
213         return self._key
214
215     def add_vpp_config(self):
216         self.test.vapi.lisp_local_mapping(
217                 ls_name=self._ls_name, eid_type=self._eid.eid_type,
218                 eid=str(self._eid), prefix_len=self._eid.prefix_length,
219                 vni=self._vni, key_id=self._key_id, key=self._key)
220         self._test.registry.register(self, self.test.logger)
221
222     def remove_vpp_config(self):
223         self.test.vapi.lisp_local_mapping(
224                 ls_name=self._ls_name, eid_type=self._eid.eid_type,
225                 eid=str(self._eid), prefix_len=self._eid.prefix_length,
226                 vni=self._vni, is_add=0)
227
228     def object_id(self):
229         return 'lisp-eid-local-mapping-%s[%d]' % (self._eid, self._vni)
230
231
232 class VppRemoteMapping(VppLispMapping):
233
234     def __init__(self, test, eid, rlocs=None, vni=0, priority=1, weight=1):
235         super(VppRemoteMapping, self).__init__(test, eid, vni, priority,
236                                                weight)
237         self._rlocs = rlocs
238
239     @property
240     def rlocs(self):
241         return self._rlocs
242
243     def add_vpp_config(self):
244         self.test.vapi.lisp_remote_mapping(
245                 rlocs=self._rlocs, eid_type=self._eid.eid_type,
246                 eid=str(self._eid), eid_prefix_len=self._eid.prefix_length,
247                 vni=self._vni, rlocs_num=len(self._rlocs))
248         self._test.registry.register(self, self.test.logger)
249
250     def remove_vpp_config(self):
251         self.test.vapi.lisp_remote_mapping(
252                 eid_type=self._eid.eid_type, eid=str(self._eid),
253                 eid_prefix_len=self._eid.prefix_length, vni=self._vni,
254                 is_add=0, rlocs_num=0)
255
256     def object_id(self):
257         return 'lisp-eid-remote-mapping-%s[%d]' % (self._eid, self._vni)
258
259
260 class VppLispAdjacency(VppObject):
261     """ Represents LISP adjacency in VPP """
262
263     def __init__(self, test, leid, reid, vni=0):
264         self._leid = LispEID(leid)
265         self._reid = LispEID(reid)
266         if self._leid.eid_type != self._reid.eid_type:
267             raise Exception('remote and local EID are different types!')
268         self._vni = vni
269         self._test = test
270
271     @property
272     def test(self):
273         return self._test
274
275     @property
276     def leid(self):
277         return self._leid
278
279     @property
280     def reid(self):
281         return self._reid
282
283     @property
284     def vni(self):
285         return self._vni
286
287     def add_vpp_config(self):
288         self.test.vapi.lisp_adjacency(
289                 leid=str(self._leid),
290                 reid=str(self._reid), eid_type=self._leid.eid_type,
291                 leid_len=self._leid.prefix_length,
292                 reid_len=self._reid.prefix_length, vni=self._vni)
293         self._test.registry.register(self, self.test.logger)
294
295     def eid_equal(self, eid, eid_type, eid_data, prefix_len):
296         if eid.eid_type != eid_type:
297             return False
298
299         if eid_type == LispEIDType.IP4 or eid_type == LispEIDType.IP6:
300             if eid.prefix_length != prefix_len:
301                 return False
302
303         if str(eid) != eid_data[0:eid.data_length]:
304             return False
305
306         return True
307
308     def query_vpp_config(self):
309         res = self.test.vapi.lisp_adjacencies_get(vni=self._vni)
310         for adj in res.adjacencies:
311             if self.eid_equal(self._leid, adj.eid_type, adj.leid,
312                               adj.leid_prefix_len) and \
313                 self.eid_equal(self._reid, adj.eid_type, adj.reid,
314                                adj.reid_prefix_len):
315                 return True
316         return False
317
318     def remove_vpp_config(self):
319         self.test.vapi.lisp_adjacency(
320                 leid=str(self._leid),
321                 reid=str(self._reid), eid_type=self._leid.eid_type,
322                 leid_len=self._leid.prefix_length,
323                 reid_len=self._reid.prefix_length, vni=self._vni, is_add=0)
324
325     def object_id(self):
326         return 'lisp-adjacency-%s-%s[%d]' % (self._leid, self._reid, self._vni)