Python3: resources and libraries
[csit.git] / resources / libraries / python / Policer.py
1 # Copyright (c) 2019 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 IntEnum
17
18 from resources.libraries.python.Constants import Constants
19 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
20 from resources.libraries.python.topology import Topology
21
22
23 class PolicerRateType(IntEnum):
24     """Policer rate types."""
25     KBPS = 0
26     PPS = 1
27     INVALID = 2
28
29
30 class PolicerRoundType(IntEnum):
31     """Policer round types."""
32     ROUND_TO_CLOSEST = 0
33     ROUND_TO_UP = 1
34     ROUND_TO_DOWN = 2
35     ROUND_TO_INVALID = 3
36
37
38 class PolicerType(IntEnum):
39     """Policer type."""
40     TYPE_1R2C = 0
41     TYPE_1R3C_RFC_2697 = 1
42     TYPE_2R3C_RFC_2698 = 2
43     TYPE_2R3C_RFC_4115 = 3
44     TYPE_2R3C_RFC_MEF5CF1 = 4
45     TYPE_MAX = 5
46
47
48 class PolicerAction(IntEnum):
49     """Policer action."""
50     DROP = 0
51     TRANSMIT = 1
52     MARK_AND_TRANSMIT = 2
53
54
55 class PolicerPreColor(IntEnum):
56     """Policer Pre-color."""
57     CONFORM_COLOR = 0
58     EXCEED_COLOR = 1
59     VIOLATE_COLOR = 2
60
61
62 class DSCP(IntEnum):
63     """DSCP for mark-and-transmit action."""
64     D_CS0 = 0
65     D_CS1 = 8
66     D_CS2 = 16
67     D_CS3 = 24
68     D_CS4 = 32
69     D_vCS5 = 40
70     D_CS6 = 48
71     D_CS7 = 56
72     D_AF11 = 10
73     D_AF12 = 12
74     D_AF13 = 14
75     D_AF21 = 18
76     D_AF22 = 20
77     D_AF23 = 22
78     D_AF31 = 26
79     D_AF32 = 28
80     D_AF33 = 30
81     D_EF = 46
82
83
84 class Policer:
85     """Policer utilities."""
86
87     # pylint: disable=too-many-arguments, too-many-locals
88     @staticmethod
89     def policer_set_configuration(
90             node, policer_name, cir, eir, cbs, ebs, rate_type, round_type,
91             policer_type, conform_action_type, exceed_action_type,
92             violate_action_type, color_aware, is_add=True, conform_dscp=None,
93             exceed_dscp=None, violate_dscp=None):
94         """Configure policer on VPP node.
95
96         :param node: VPP node.
97         :param policer_name: Name of the policer.
98         :param cir: Committed information rate.
99         :param eir: Excess (or Peak) information rate.
100         :param cbs: Committed burst size.
101         :param ebs: Excess (or Peak) burst size.
102         :param rate_type: Rate type.
103         :param round_type: Round type.
104         :param policer_type: Policer algorithm.
105         :param conform_action_type: Conform action type.
106         :param exceed_action_type: Exceed action type.
107         :param violate_action_type: Violate action type.
108         :param color_aware: Color-blind (cb) or color-aware (ca).
109         :param is_add: Add policer if True, else delete.
110         :param conform_dscp: DSCP for conform mark_and_transmit action.
111         :param exceed_dscp: DSCP for exceed mark_and_transmit action.
112         :param violate_dscp: DSCP for vilate mark_and_transmit action.
113         :type node: dict
114         :type policer_name: str
115         :type cir: int
116         :type eir: int
117         :type cbs: int
118         :type ebs: int
119         :type rate_type: str
120         :type round_type: str
121         :type policer_type: str
122         :type conform_action_type: str
123         :type exceed_action_type: str
124         :type violate_action_type: str
125         :type color_aware: str
126         :type is_add: bool
127         :type conform_dscp: str
128         :type exceed_dscp: str
129         :type violate_dscp: str
130         """
131         cmd = u"policer_add_del"
132         args = dict(
133             is_add=int(is_add),
134             name=str(policer_name).encode(encoding=u"utf-8"),
135             cir=int(cir),
136             eir=int(eir),
137             cb=int(cbs),
138             eb=int(ebs),
139             rate_type=getattr(PolicerRateType, rate_type.upper()).value,
140             round_type=getattr(
141                 PolicerRoundType, f"ROUND_TO_{round_type.upper()}"
142             ).value,
143             type=getattr(PolicerType, f"TYPE_{policer_type.upper()}").value,
144             conform_action_type=getattr(
145                 PolicerAction, conform_action_type.upper()
146             ).value,
147             conform_dscp=getattr(DSCP, f"D_{conform_dscp.upper()}").value
148             if
149             conform_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
150             else 0,
151             exceed_action_type=getattr(
152                 PolicerAction, exceed_action_type.upper()
153             ).value,
154             exceed_dscp=getattr(DSCP, f"D_{exceed_dscp.upper()}").value
155             if
156             exceed_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
157             else 0,
158             violate_action_type=getattr(
159                 PolicerAction, violate_action_type.upper()
160             ).value,
161             violate_dscp=getattr(DSCP, f"D_{violate_dscp.upper()}").value
162             if
163             violate_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
164             else 0,
165             color_aware=1 if color_aware == u"'ca'" else 0
166         )
167         err_msg = f"Failed to configure policer {policer_name} " \
168             f"on host {node['host']}"
169
170         with PapiSocketExecutor(node) as papi_exec:
171             reply = papi_exec.add(cmd, **args).get_reply(err_msg)
172
173         return reply[u"policer_index"]
174
175     @staticmethod
176     def policer_classify_set_interface(
177             node, interface, ip4_table_index=Constants.BITWISE_NON_ZERO,
178             ip6_table_index=Constants.BITWISE_NON_ZERO,
179             l2_table_index=Constants.BITWISE_NON_ZERO, is_add=1):
180         """Set/unset policer classify interface.
181
182         :param node: VPP node.
183         :param interface: Interface name or sw_if_index to set/unset policer
184             classify.
185         :param ip4_table_index: IP4 classify table index (~0 to skip).
186             (Default value = ~0)
187         :param ip6_table_index: IP6 classify table index (~0 to skip).
188             (Default value = ~0)
189         :param l2_table_index: L2 classify table index (~0 to skip).
190             (Default value = ~0)
191         :param is_add: Set if non-zero, else unset.
192         :type node: dict
193         :type interface: str or int
194         :type ip4_table_index: int
195         :type ip6_table_index: int
196         :type l2_table_index: int
197         """
198         if isinstance(interface, str):
199             sw_if_index = Topology.get_interface_sw_index(node, interface)
200         else:
201             sw_if_index = interface
202
203         cmd = u"policer_classify_set_interface"
204         args = dict(
205             is_add=int(is_add),
206             sw_if_index=sw_if_index,
207             ip4_table_index=int(ip4_table_index),
208             ip6_table_index=int(ip6_table_index),
209             l2_table_index=int(l2_table_index)
210         )
211         err_msg = f"Failed to set/unset policer classify interface " \
212             f"{interface} on host {node[u'host']}"
213
214         with PapiSocketExecutor(node) as papi_exec:
215             papi_exec.add(cmd, **args).get_reply(err_msg)
216
217     @staticmethod
218     def policer_classify_get_precolor(precolor):
219         """Return policer pre-color numeric value.
220
221         :param precolor: Policer pre-color name.
222         :type precolor: str
223         :returns: Policer pre-color numeric value.
224         :rtype: int
225         """
226         return getattr(PolicerPreColor, precolor.upper()).value
227
228     @staticmethod
229     def get_dscp_num_value(dscp):
230         """Return DSCP numeric value.
231
232         :param dscp: DSCP name.
233         :type dscp: str
234         :returns: DSCP numeric value.
235         :rtype: int
236         """
237         return getattr(DSCP, f"D_{dscp.upper()}").value