1 # Copyright (c) 2021 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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Policer utilities library."""
16 from enum import IntEnum
18 from resources.libraries.python.Constants import Constants
19 from resources.libraries.python.IPUtil import IpDscp
20 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
21 from resources.libraries.python.topology import Topology
24 class PolicerRateType(IntEnum):
25 """Policer rate types."""
31 class PolicerRoundType(IntEnum):
32 """Policer round types."""
39 class PolicerType(IntEnum):
42 TYPE_1R3C_RFC_2697 = 1
43 TYPE_2R3C_RFC_2698 = 2
44 TYPE_2R3C_RFC_4115 = 3
45 TYPE_2R3C_RFC_MEF5CF1 = 4
49 class PolicerAction(IntEnum):
56 class PolicerPreColor(IntEnum):
57 """Policer Pre-color."""
64 """Policer utilities."""
66 # TODO: Pylint says too-many-arguments and too-many-locals.
67 # It is right, we should refactor the code
68 # and group similar arguments together (into documented classes).
69 # Note that even the call from Robot Framework
70 # is not very readable with this many arguments.
72 def policer_set_configuration(
73 node, policer_name, cir, eir, cbs, ebs, rate_type, round_type,
74 policer_type, conform_action_type, exceed_action_type,
75 violate_action_type, color_aware, is_add=True, conform_dscp=None,
76 exceed_dscp=None, violate_dscp=None):
77 """Configure policer on VPP node.
79 :param node: VPP node.
80 :param policer_name: Name of the policer.
81 :param cir: Committed information rate.
82 :param eir: Excess (or Peak) information rate.
83 :param cbs: Committed burst size.
84 :param ebs: Excess (or Peak) burst size.
85 :param rate_type: Rate type.
86 :param round_type: Round type.
87 :param policer_type: Policer algorithm.
88 :param conform_action_type: Conform action type.
89 :param exceed_action_type: Exceed action type.
90 :param violate_action_type: Violate action type.
91 :param color_aware: Color-blind (cb) or color-aware (ca).
92 :param is_add: Add policer if True, else delete.
93 :param conform_dscp: DSCP for conform mark_and_transmit action.
94 :param exceed_dscp: DSCP for exceed mark_and_transmit action.
95 :param violate_dscp: DSCP for vilate mark_and_transmit action.
97 :type policer_name: str
103 :type round_type: str
104 :type policer_type: str
105 :type conform_action_type: str
106 :type exceed_action_type: str
107 :type violate_action_type: str
108 :type color_aware: str
110 :type conform_dscp: str
111 :type exceed_dscp: str
112 :type violate_dscp: str
114 conform_action = dict(
115 type=getattr(PolicerAction, conform_action_type.upper()).value,
116 dscp=Policer.get_dscp_num_value(conform_dscp) if
117 conform_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
120 exceed_action = dict(
121 type=getattr(PolicerAction, exceed_action_type.upper()).value,
122 dscp=Policer.get_dscp_num_value(exceed_dscp) if
123 exceed_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
126 violate_action = dict(
127 type=getattr(PolicerAction, violate_action_type.upper()).value,
128 dscp=Policer.get_dscp_num_value(violate_dscp) if
129 violate_action_type.upper() == PolicerAction.MARK_AND_TRANSMIT.name
133 cmd = u"policer_add_del"
136 name=str(policer_name),
141 rate_type=getattr(PolicerRateType, rate_type.upper()).value,
143 PolicerRoundType, f"ROUND_TO_{round_type.upper()}"
145 type=getattr(PolicerType, f"TYPE_{policer_type.upper()}").value,
146 conform_action=conform_action,
147 exceed_action=exceed_action,
148 violate_action=violate_action,
149 color_aware=bool(color_aware == u"'ca'")
151 err_msg = f"Failed to configure policer {policer_name} " \
152 f"on host {node['host']}"
154 with PapiSocketExecutor(node) as papi_exec:
155 reply = papi_exec.add(cmd, **args).get_reply(err_msg)
157 return reply[u"policer_index"]
160 def policer_classify_set_interface(
161 node, interface, ip4_table_index=Constants.BITWISE_NON_ZERO,
162 ip6_table_index=Constants.BITWISE_NON_ZERO,
163 l2_table_index=Constants.BITWISE_NON_ZERO, is_add=True):
164 """Set/unset policer classify interface.
166 :param node: VPP node.
167 :param interface: Interface name or sw_if_index to set/unset policer
169 :param ip4_table_index: IP4 classify table index (~0 to skip).
171 :param ip6_table_index: IP6 classify table index (~0 to skip).
173 :param l2_table_index: L2 classify table index (~0 to skip).
175 :param is_add: Set if True, else unset.
177 :type interface: str or int
178 :type ip4_table_index: int
179 :type ip6_table_index: int
180 :type l2_table_index: int
183 if isinstance(interface, str):
184 sw_if_index = Topology.get_interface_sw_index(node, interface)
186 sw_if_index = interface
188 cmd = u"policer_classify_set_interface"
191 sw_if_index=int(sw_if_index),
192 ip4_table_index=int(ip4_table_index),
193 ip6_table_index=int(ip6_table_index),
194 l2_table_index=int(l2_table_index)
196 err_msg = f"Failed to set/unset policer classify interface " \
197 f"{interface} on host {node[u'host']}"
199 with PapiSocketExecutor(node) as papi_exec:
200 papi_exec.add(cmd, **args).get_reply(err_msg)
203 def policer_classify_get_precolor(precolor):
204 """Return policer pre-color numeric value.
206 :param precolor: Policer pre-color name.
208 :returns: Policer pre-color numeric value.
211 return getattr(PolicerPreColor, precolor.upper()).value
214 def get_dscp_num_value(dscp):
215 """Return DSCP numeric value.
217 :param dscp: DSCP name.
219 :returns: DSCP numeric value.
222 return getattr(IpDscp, f"IP_API_DSCP_{dscp.upper()}").value