Reduce disabled pylint to address them not hide
[csit.git] / resources / libraries / python / Policer.py
1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Policer utilities library."""
15
16 from enum import Enum
17
18 from ipaddress import ip_address
19
20 from resources.libraries.python.VatExecutor import VatExecutor
21 from resources.libraries.python.VatJsonUtil import VatJsonUtil
22 from resources.libraries.python.topology import Topology
23
24
25 class PolicerRateType(Enum):
26     """Policer rate types."""
27     KBPS = 'kbps'
28     PPS = 'pps'
29
30     def __init__(self, string):
31         self.string = string
32
33
34 # pylint: disable=invalid-name
35 class PolicerRoundType(Enum):
36     """Policer round types."""
37     CLOSEST = 'closest'
38     UP = 'up'
39     DOWN = 'down'
40
41     def __init__(self, string):
42         self.string = string
43
44
45 class PolicerType(Enum):
46     """Policer type."""
47     P_1R2C = '1r2c'
48     P_1R3C = '1r3c'
49     P_2R3C_2698 = '2r3c-2698'
50     P_2R3C_4115 = '2r3c-4115'
51     P_2R3C_MEF5CF1 = '2r3c-mef5cf1'
52
53     def __init__(self, string):
54         self.string = string
55
56
57 class PolicerAction(Enum):
58     """Policer action."""
59     DROP = 'drop'
60     TRANSMIT = 'transmit'
61     MARK_AND_TRANSMIT = 'mark-and-transmit'
62
63     def __init__(self, string):
64         self.string = string
65
66
67 class DSCP(Enum):
68     """DSCP for mark-and-transmit action."""
69     CS0 = ('CS0', 0)
70     CS1 = ('CS1', 8)
71     CS2 = ('CS2', 16)
72     CS3 = ('CS3', 24)
73     CS4 = ('CS4', 32)
74     CS5 = ('CS5', 40)
75     CS6 = ('CS6', 48)
76     CS7 = ('CS7', 56)
77     AF11 = ('AF11', 10)
78     AF12 = ('AF12', 12)
79     AF13 = ('AF13', 14)
80     AF21 = ('AF21', 18)
81     AF22 = ('AF22', 20)
82     AF23 = ('AF23', 22)
83     AF31 = ('AF31', 26)
84     AF32 = ('AF32', 28)
85     AF33 = ('AF33', 30)
86     EF = ('EF', 46)
87
88     def __init__(self, string, num):
89         self.string = string
90         self.num = num
91
92
93 class PolicerClassifyPreColor(Enum):
94     """Policer classify precolor."""
95     CONFORM_COLOR = 'conform-color'
96     EXCEED_COLOR = 'exceed-color'
97
98     def __init__(self, string):
99         self.string = string
100
101
102 class PolicerClassifyTableType(Enum):
103     """Policer classify table type."""
104     IP4_TABLE = 'ip4-table'
105     IP6_TABLE = 'ip6-table'
106     L2_TABLE = 'l2-table'
107
108     def __init__(self, string):
109         self.string = string
110
111
112 class Policer(object):
113     """Policer utilities."""
114
115     def __init__(self):
116         self._cir = 0
117         self._eir = 0
118         self._cb = 0
119         self._eb = 0
120         self._rate_type = None
121         self._round_type = None
122         self._policer_type = None
123         self._conform_action = None
124         self._conform_dscp = None
125         self._exceed_action = None
126         self._exceed_dscp = None
127         self._violate_action = None
128         self._violate_dscp = None
129         self._color_aware = False
130         self._classify_match_ip = ''
131         self._classify_match_is_src = True
132         self._classify_precolor = None
133         self._sw_if_index = 0
134         self._node = None
135         self._policer_name = ''
136
137     def policer_set_configuration(self):
138         """Configure policer on VPP node.
139
140         ...note:: First set all required parameters.
141         """
142         node = self._node
143
144         # create policer
145         color_aware = 'color-aware' if self._color_aware else ''
146
147         conform_action = self._conform_action.value
148
149         if PolicerAction.MARK_AND_TRANSMIT == self._conform_action:
150             conform_action += ' {0}'.format(self._conform_dscp.string)
151
152         exceed_action = self._exceed_action.value
153         if PolicerAction.MARK_AND_TRANSMIT == self._exceed_action:
154             exceed_action += ' {0}'.format(self._exceed_dscp.string)
155
156         violate_action = self._violate_action.value
157         if PolicerAction.MARK_AND_TRANSMIT == self._violate_action:
158             violate_action += ' {0}'.format(self._violate_dscp.string)
159
160         out = VatExecutor.cmd_from_template(node,
161                                             "policer/policer_add_3c.vat",
162                                             name=self._policer_name,
163                                             cir=self._cir,
164                                             eir=self._eir,
165                                             cb=self._cb,
166                                             eb=self._eb,
167                                             rate_type=self._rate_type.value,
168                                             round_type=self._round_type.value,
169                                             p_type=self._policer_type.value,
170                                             conform_action=conform_action,
171                                             exceed_action=exceed_action,
172                                             violate_action=violate_action,
173                                             color_aware=color_aware)
174
175         VatJsonUtil.verify_vat_retval(
176             out[0],
177             err_msg='Add policer {0} failed on {1}'.format(self._policer_name,
178                                                            node['host']))
179
180         policer_index = out[0].get('policer_index')
181
182         # create classify table
183         direction = 'src' if self._classify_match_is_src else 'dst'
184
185         if ip_address(unicode(self._classify_match_ip)).version == 6:
186             ip_version = 'ip6'
187             table_type = PolicerClassifyTableType.IP6_TABLE
188         else:
189             ip_version = 'ip4'
190             table_type = PolicerClassifyTableType.IP4_TABLE
191
192         out = VatExecutor.cmd_from_template(node,
193                                             "classify_add_table.vat",
194                                             ip_version=ip_version,
195                                             direction=direction)
196
197         VatJsonUtil.verify_vat_retval(
198             out[0],
199             err_msg='Add classify table failed on {0}'.format(node['host']))
200
201         new_table_index = out[0].get('new_table_index')
202         skip_n_vectors = out[0].get('skip_n_vectors')
203         match_n_vectors = out[0].get('match_n_vectors')
204
205         # create classify session
206         match = 'l3 {0} {1} {2}'.format(ip_version,
207                                         direction,
208                                         self._classify_match_ip)
209
210         out = VatExecutor.cmd_from_template(
211             node,
212             "policer/policer_classify_add_session.vat",
213             policer_index=policer_index,
214             pre_color=self._classify_precolor.value,
215             table_index=new_table_index,
216             skip_n=skip_n_vectors,
217             match_n=match_n_vectors,
218             match=match)
219
220         VatJsonUtil.verify_vat_retval(
221             out[0],
222             err_msg='Add classify session failed on {0}'.format(node['host']))
223
224         # set classify interface
225         out = VatExecutor.cmd_from_template(
226             node,
227             "policer/policer_classify_set_interface.vat",
228             sw_if_index=self._sw_if_index,
229             table_type=table_type.value,
230             table_index=new_table_index)
231
232         VatJsonUtil.verify_vat_retval(
233             out[0],
234             err_msg='Set classify interface failed on {0}'.format(node['host']))
235
236     def policer_clear_settings(self):
237         """Clear policer settings."""
238         self._cir = 0
239         self._eir = 0
240         self._cb = 0
241         self._eb = 0
242         self._rate_type = None
243         self._round_type = None
244         self._policer_type = None
245         self._conform_action = None
246         self._conform_dscp = None
247         self._exceed_action = None
248         self._exceed_dscp = None
249         self._violate_action = None
250         self._violate_dscp = None
251         self._color_aware = False
252         self._classify_match_ip = ''
253         self._classify_match_is_src = True
254         self._classify_precolor = None
255         self._sw_if_index = 0
256         self._node = None
257         self._policer_name = ''
258
259     def policer_set_name(self, name):
260         """Set policer name.
261
262         :param name: Policer name.
263         :type name: str
264         """
265         self._policer_name = name
266
267     def policer_set_node(self, node):
268         """Set node to setup policer on.
269
270         :param node: VPP node.
271         :type node: dict
272         """
273         self._node = node
274
275     def policer_set_cir(self, cir):
276         """Set policer CIR.
277
278         :param cir: Committed Information Rate.
279         :type cir: int
280         """
281         self._cir = cir
282
283     def policer_set_eir(self, eir):
284         """Set polcier EIR.
285
286         :param eir: Excess Information Rate.
287         :type eir: int
288         """
289         self._eir = eir
290
291     def policer_set_cb(self, cb):
292         """Set policer CB.
293
294         :param cb: Committed Burst size.
295         :type cb: int or str
296         """
297         if cb == "IMIX_v4_1":
298             self._cb = 1518
299         else:
300             self._cb = cb
301
302     def policer_set_eb(self, eb):
303         """Set policer EB.
304
305         :param eb: Excess Burst size.
306         :type eb: int or str
307         """
308         if eb == "IMIX_v4_1":
309             self._eb = 1518
310         else:
311             self._eb = eb
312
313     def policer_set_rate_type_kbps(self):
314         """Set policer rate type to kbps."""
315         self._rate_type = PolicerRateType.KBPS
316
317     def policer_set_rate_type_pps(self):
318         """Set policer rate type to pps."""
319         self._rate_type = PolicerRateType.PPS
320
321     def policer_set_round_type_closest(self):
322         """Set policer round type to closest."""
323         self._round_type = PolicerRoundType.CLOSEST
324
325     def policer_set_round_type_up(self):
326         """Set policer round type to up."""
327         self._round_type = PolicerRoundType.UP
328
329     def policer_set_round_type_down(self):
330         """Set policer round type to down."""
331         self._round_type = PolicerRoundType.DOWN
332
333     def policer_set_type_1r2c(self):
334         """Set policer type to 1r2c."""
335         self._policer_type = PolicerType.P_1R2C
336
337     def policer_set_type_1r3c(self):
338         """Set policer type to 1r3c RFC2697."""
339         self._policer_type = PolicerType.P_1R3C
340
341     def policer_set_type_2r3c_2698(self):
342         """Set policer type to 2r3c RFC2698."""
343         self._policer_type = PolicerType.P_2R3C_2698
344
345     def policer_set_type_2r3c_4115(self):
346         """Set policer type to 2r3c RFC4115."""
347         self._policer_type = PolicerType.P_2R3C_4115
348
349     def policer_set_type_2r3c_mef5cf1(self):
350         """Set policer type to 2r3c MEF5CF1."""
351         self._policer_type = PolicerType.P_2R3C_MEF5CF1
352
353     def policer_set_conform_action_drop(self):
354         """Set policer conform-action to drop."""
355         self._conform_action = PolicerAction.DROP
356
357     def policer_set_conform_action_transmit(self):
358         """Set policer conform-action to transmit."""
359         self._conform_action = PolicerAction.TRANSMIT
360
361     def policer_set_conform_action_mark_and_transmit(self, dscp):
362         """Set policer conform-action to mark-and-transmit.
363
364         :param dscp: DSCP value to mark.
365         :type dscp: DSCP
366         """
367         self._conform_action = PolicerAction.MARK_AND_TRANSMIT
368         self._conform_dscp = dscp
369
370     def policer_set_exceed_action_drop(self):
371         """Set policer exceed-action to drop."""
372         self._exceed_action = PolicerAction.DROP
373
374     def policer_set_exceed_action_transmit(self):
375         """Set policer exceed-action to transmit."""
376         self._exceed_action = PolicerAction.TRANSMIT
377
378     def policer_set_exceed_action_mark_and_transmit(self, dscp):
379         """Set policer exceed-action to mark-and-transmit.
380
381         :param dscp: DSCP value to mark.
382         :type dscp: DSCP
383         """
384         self._exceed_action = PolicerAction.MARK_AND_TRANSMIT
385         self._exceed_dscp = dscp
386
387     def policer_set_violate_action_drop(self):
388         """Set policer violate-action to drop."""
389         self._violate_action = PolicerAction.DROP
390
391     def policer_set_violate_action_transmit(self):
392         """Set policer violate-action to transmit."""
393         self._violate_action = PolicerAction.TRANSMIT
394
395     def policer_set_violate_action_mark_and_transmit(self, dscp):
396         """Set policer violate-action to mark-and-transmit.
397
398         :param dscp: DSCP value to mark.
399         :type dscp: DSCP
400         """
401         self._violate_action = PolicerAction.MARK_AND_TRANSMIT
402         self._violate_dscp = dscp
403
404     def policer_enable_color_aware(self):
405         """Enable color-aware mode for policer."""
406         self._color_aware = True
407
408     def policer_classify_set_precolor_conform(self):
409         """Set policer classify pre-color to conform-color."""
410         self._classify_precolor = PolicerClassifyPreColor.CONFORM_COLOR
411
412     def policer_classify_set_precolor_exceed(self):
413         """Set policer classify pre-color to exceeed-color."""
414         self._classify_precolor = PolicerClassifyPreColor.EXCEED_COLOR
415
416     def policer_classify_set_interface(self, interface):
417         """Set policer classify interface.
418
419         .. note:: First set node with policer_set_node.
420
421         :param interface: Interface name or sw_if_index.
422         :type interface: str or int
423         """
424         if isinstance(interface, basestring):
425             self._sw_if_index = Topology.get_interface_sw_index(self._node,
426                                                                 interface)
427         else:
428             self._sw_if_index = interface
429
430     def policer_classify_set_match_ip(self, ip, is_src=True):
431         """Set policer classify match source IP address.
432
433         :param ip: IPv4 or IPv6 address.
434         :param is_src: Match src IP if True otherwise match dst IP.
435         :type ip: str
436         :type is_src: bool
437         """
438         self._classify_match_ip = ip
439         self._classify_match_is_src = is_src
440
441     @staticmethod
442     def dscp_cs0():
443         """Return DSCP CS0.
444
445         :returns: DSCP enum CS0 object.
446         :rtype: DSCP
447         """
448         return DSCP.CS0
449
450     @staticmethod
451     def dscp_cs1():
452         """Return DSCP CS1.
453
454         :returns: DSCP enum CS1 object.
455         :rtype: DSCP
456         """
457         return DSCP.CS1
458
459     @staticmethod
460     def dscp_cs2():
461         """Return DSCP CS2.
462
463         :returns: DSCP enum CS2 object.
464         :rtype: DSCP
465         """
466         return DSCP.CS2
467
468     @staticmethod
469     def dscp_cs3():
470         """Return DSCP CS3.
471
472         :returns: DSCP enum CS3 object.
473         :rtype: DSCP
474         """
475         return DSCP.CS3
476
477     @staticmethod
478     def dscp_cs4():
479         """Return DSCP CS4.
480
481         :returns: DSCP enum CS4 object.
482         :rtype: DSCP
483         """
484         return DSCP.CS4
485
486     @staticmethod
487     def dscp_cs5():
488         """Return DSCP CS5.
489
490         :returns: DSCP enum CS5 object.
491         :rtype: DSCP
492         """
493         return DSCP.CS5
494
495     @staticmethod
496     def dscp_cs6():
497         """Return DSCP CS6.
498
499         :returns: DSCP enum CS6 object.
500         :rtype: DSCP
501         """
502         return DSCP.CS6
503
504     @staticmethod
505     def dscp_cs7():
506         """Return DSCP CS7.
507
508         :returns: DSCP enum CS7 object.
509         :rtype: DSCP
510         """
511         return DSCP.CS7
512
513     @staticmethod
514     def dscp_ef():
515         """Return DSCP EF.
516
517         :returns: DSCP enum EF object.
518         :rtype: DSCP
519         """
520         return DSCP.EF
521
522     @staticmethod
523     def dscp_af11():
524         """Return DSCP AF11.
525
526         :returns: DSCP enum AF11 object.
527         :rtype: DSCP
528         """
529         return DSCP.AF11
530
531     @staticmethod
532     def dscp_af12():
533         """Return DSCP AF12.
534
535         :returns: DSCP enum AF12 object.
536         :rtype: DSCP
537         """
538         return DSCP.AF12
539
540     @staticmethod
541     def dscp_af13():
542         """Return DSCP AF13.
543
544         :returns: DSCP enum AF13 object.
545         :rtype: DSCP
546         """
547         return DSCP.AF13
548
549     @staticmethod
550     def dscp_af21():
551         """Return DSCP AF21.
552
553         :returns: DSCP enum AF21 object.
554         :rtype: DSCP
555         """
556         return DSCP.AF21
557
558     @staticmethod
559     def dscp_af22():
560         """Return DSCP AF22.
561
562         :returns: DSCP enum AF22 object.
563         :rtype: DSCP
564         """
565         return DSCP.AF22
566
567     @staticmethod
568     def dscp_af23():
569         """Return DSCP AF23.
570
571         :returns: DSCP enum AF23 object.
572         :rtype: DSCP
573         """
574         return DSCP.AF23
575
576     @staticmethod
577     def dscp_af31():
578         """Return DSCP AF31.
579
580         :returns: DSCP enum AF31 object.
581         :rtype: DSCP
582         """
583         return DSCP.AF31
584
585     @staticmethod
586     def dscp_af32():
587         """Return DSCP AF32.
588
589         :returns: DSCP enum AF32 object.
590         :rtype: DSCP
591         """
592         return DSCP.AF32
593
594     @staticmethod
595     def dscp_af33():
596         """Return DSCP AF33.
597
598         :returns: DSCP enum AF33 object.
599         :rtype: DSCP
600         """
601         return DSCP.AF33
602
603     @staticmethod
604     def get_dscp_num_value(dscp):
605         """Return DSCP numeric value.
606
607         :param dscp: DSCP enum object.
608         :type dscp: DSCP
609         :returns: DSCP numeric value.
610         :rtype: int
611         """
612         return dscp.num