1 # copyright (c) 2021 Intel 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 """Flow Utilities Library."""
16 from ipaddress import ip_address
18 from resources.libraries.python.topology import Topology
19 from resources.libraries.python.ssh import exec_cmd_no_error
20 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
22 from vpp_papi import VppEnum
25 """Utilities for flow configuration."""
28 def vpp_create_ip4_n_tuple_flow(
29 node, src_ip, dst_ip, src_port, dst_port,
30 proto, action, value=0):
31 """Create IP4_N_TUPLE flow.
33 :param node: DUT node.
34 :param src_ip: Source IP4 address.
35 :param dst_ip: Destination IP4 address.
36 :param src_port: Source port.
37 :param dst_port: Destination port.
38 :param proto: TCP or UDP.
39 :param action: Mark, drop or redirect-to-queue.
40 :param value: Action value.
54 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_N_TUPLE
57 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_TCP
59 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
61 raise ValueError(f"proto error: {proto}")
64 u'src_addr': {u'addr': src_ip, u'mask': u"255.255.255.255"},
65 u'dst_addr': {u'addr': dst_ip, u'mask': u"255.255.255.255"},
66 u'src_port': {u'port': src_port, u'mask': 0xFFFF},
67 u'dst_port': {u'port': dst_port, u'mask': 0xFFFF},
68 u'protocol': {u'prot': flow_proto}
71 flow_index = FlowUtil.vpp_flow_add(
72 node, flow, flow_type, pattern, action, value)
77 def vpp_create_ip6_n_tuple_flow(
78 node, src_ip, dst_ip, src_port, dst_port,
79 proto, action, value=0):
80 """Create IP6_N_TUPLE flow.
82 :param node: DUT node.
83 :param src_ip: Source IP6 address.
84 :param dst_ip: Destination IP6 address.
85 :param src_port: Source port.
86 :param dst_port: Destination port.
87 :param proto: TCP or UDP.
88 :param action: Mark, drop or redirect-to-queue.
89 :param value: Action value.
102 flow = u"ip6_n_tuple"
103 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP6_N_TUPLE
106 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_TCP
107 elif proto == u"UDP":
108 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
110 raise ValueError(f"proto error: {proto}")
113 u'src_addr': {u'addr': src_ip, \
114 u'mask': u"FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"},
115 u'dst_addr': {u'addr': dst_ip, \
116 u'mask': u"FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"},
117 u'src_port': {u'port': src_port, u'mask': 0xFFFF},
118 u'dst_port': {u'port': dst_port, u'mask': 0xFFFF},
119 u'protocol': {u'prot': flow_proto}
122 flow_index = FlowUtil.vpp_flow_add(
123 node, flow, flow_type, pattern, action, value)
128 def vpp_create_ip4_flow(
129 node, src_ip, dst_ip, proto, action, value=0):
132 :param node: DUT node.
133 :param src_ip: Source IP4 address.
134 :param dst_ip: Destination IP4 address.
135 :param proto: TCP or UDP.
136 :param action: Mark, drop or redirect-to-queue.
137 :param value: Action value.
145 :returns: flow_index.
149 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4
152 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_TCP
153 elif proto == u"UDP":
154 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
156 raise ValueError(f"proto error: {proto}")
159 u'src_addr': {u'addr': src_ip, u'mask': u"255.255.255.255"},
160 u'dst_addr': {u'addr': dst_ip, u'mask': u"255.255.255.255"},
161 u'protocol': {u'prot': flow_proto}
164 flow_index = FlowUtil.vpp_flow_add(
165 node, flow, flow_type, pattern, action, value)
170 def vpp_create_ip6_flow(
171 node, src_ip, dst_ip, proto, action, value=0):
174 :param node: DUT node.
175 :param src_ip: Source IP6 address.
176 :param dst_ip: Destination IP6 address.
177 :param proto: TCP or UDP.
178 :param action: Mark, drop or redirect-to-queue.
179 :param value: Action value.
187 :returns: flow_index.
191 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP6
194 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_TCP
195 elif proto == u"UDP":
196 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
198 raise ValueError(f"proto error: {proto}")
201 u'src_addr': {u'addr': src_ip, \
202 u'mask': u"FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"},
203 u'dst_addr': {'addr': dst_ip, \
204 u'mask': u"FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"},
205 u'protocol': {u'prot': flow_proto}
208 flow_index = FlowUtil.vpp_flow_add(
209 node, flow, flow_type, pattern, action, value)
214 def vpp_create_ip4_gtpu_flow(
215 node, src_ip, dst_ip, teid, action, value=0):
216 """Create IP4_GTPU flow.
218 :param node: DUT node.
219 :param src_ip: Source IP4 address.
220 :param dst_ip: Destination IP4 address.
221 :param teid: Tunnel endpoint identifier.
222 :param action: Mark, drop or redirect-to-queue.
223 :param value: Action value.
231 :returns: flow_index.
235 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_GTPU
236 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
239 u'src_addr': {u'addr': src_ip, u'mask': u"255.255.255.255"},
240 u'dst_addr': {u'addr': dst_ip, u'mask': u"255.255.255.255"},
241 u'protocol': {u'prot': flow_proto},
245 flow_index = FlowUtil.vpp_flow_add(
246 node, flow, flow_type, pattern, action, value)
251 def vpp_create_ip4_ipsec_flow(node, proto, spi, action, value=0):
252 """Create IP4_IPSEC flow.
254 :param node: DUT node.
255 :param proto: TCP or UDP.
256 :param spi: Security Parameters Index.
257 :param action: Mark, drop or redirect-to-queue.
258 :param value: Action value.
265 :returns: flow_index.
269 flow = u"ip4_ipsec_esp"
270 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_ESP
271 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_IPSEC_ESP
273 flow = u"ip4_ipsec_ah"
274 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_AH
275 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_IPSEC_AH
277 raise ValueError(f"proto error: {proto}")
280 u'protocol': {u'prot': flow_proto},
284 flow_index = FlowUtil.vpp_flow_add(
285 node, flow, flow_type, pattern, action, value)
290 def vpp_create_ip4_l2tp_flow(node, session_id, action, value=0):
291 """Create IP4_L2TPV3OIP flow.
293 :param node: DUT node.
294 :param session_id: PPPoE session ID
295 :param action: Mark, drop or redirect-to-queue.
296 :param value: Action value.
299 :type session_id: int
302 :returns: flow_index.
305 flow = u"ip4_l2tpv3oip"
306 flow_proto = 115 # IP_API_PROTO_L2TP
307 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_L2TPV3OIP
310 u'protocol': {u'prot': flow_proto},
311 u'session_id': session_id
314 flow_index = FlowUtil.vpp_flow_add(
315 node, flow, flow_type, pattern, action, value)
320 def vpp_create_ip4_vxlan_flow(node, src_ip, dst_ip, vni, action, value=0):
321 """Create IP4_VXLAN flow.
323 :param node: DUT node.
324 :param src_ip: Source IP4 address.
325 :param dst_ip: Destination IP4 address.
326 :param vni: Virtual network instance.
327 :param action: Mark, drop or redirect-to-queue.
328 :param value: Action value.
336 :returns: flow_index.
339 flow_type = VppEnum.vl_api_flow_type_t.FLOW_TYPE_IP4_VXLAN
340 flow_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
343 u'src_addr': {u'addr': src_ip, u'mask': u"255.255.255.255"},
344 u'dst_addr': {u'addr': dst_ip, u'mask': u"255.255.255.255"},
345 u'dst_port': {u'port': 4789, 'mask': 0xFFFF},
346 u'protocol': {u'prot': flow_proto},
350 flow_index = FlowUtil.vpp_flow_add(
351 node, flow, flow_type, pattern, action, value)
356 def vpp_flow_add(node, flow, flow_type, pattern, action, value=0):
359 :param node: DUT node.
360 :param flow: Name of flow.
361 :param flow_type: Type of flow.
362 :param pattern: Pattern of flow.
363 :param action: Mark, drop or redirect-to-queue.
364 :param value: Action value.
372 :returns: flow_index.
374 :raises ValueError: If action type is not supported.
378 if action == u"redirect-to-queue":
381 u'actions': VppEnum.vl_api_flow_action_t.\
382 FLOW_ACTION_REDIRECT_TO_QUEUE,
383 u'redirect_queue': value,
384 u'flow': {flow : pattern}
386 elif action == u"mark":
389 u'actions': VppEnum.vl_api_flow_action_t.FLOW_ACTION_MARK,
390 u'mark_flow_id': value,
391 u'flow': {flow : pattern}
393 elif action == u"drop":
396 u'actions': VppEnum.vl_api_flow_action_t.FLOW_ACTION_DROP,
397 u'flow': {flow : pattern}
400 raise ValueError(f"Unsupported action type: {action}")
402 err_msg = f"Failed to create {flow} flow on host {node[u'host']}."
403 args = dict(flow=flow_rule)
405 with PapiSocketExecutor(node) as papi_exec:
406 reply = papi_exec.add(cmd, **args).get_reply(err_msg)
407 flow_index = reply[u"flow_index"]
412 def vpp_flow_enable(node, interface, flow_index=0):
415 :param node: DUT node.
416 :param interface: Interface sw_if_index.
417 :param flow_index: Flow index.
421 :type flow_index: int
425 sw_if_index = Topology.get_interface_sw_index(node, interface)
427 flow_index=int(flow_index),
428 hw_if_index=int(sw_if_index)
431 err_msg = u"Failed to enable flow on host {node[u'host']}"
432 with PapiSocketExecutor(node) as papi_exec:
433 papi_exec.add(cmd, **args).get_reply(err_msg)
436 def vpp_flow_disable(node, interface, flow_index=0):
439 :param node: DUT node.
440 :param interface: Interface sw_if_index.
441 :param flow_index: Flow index.
445 :type flow_index: int
448 cmd = u"flow_disable"
449 sw_if_index = Topology.get_interface_sw_index(node, interface)
451 flow_index=int(flow_index),
452 hw_if_index=int(sw_if_index)
455 err_msg = u"Failed to disable flow on host {node[u'host']}"
456 with PapiSocketExecutor(node) as papi_exec:
457 papi_exec.add(cmd, **args).get_reply(err_msg)
460 def vpp_flow_del(node, flow_index=0):
463 :param node: DUT node.
464 :param flow_index: Flow index.
467 :type flow_index: int
472 flow_index=int(flow_index)
475 err_msg = u"Failed to delete flow on host {node[u'host']}"
476 with PapiSocketExecutor(node) as papi_exec:
477 papi_exec.add(cmd, **args).get_reply(err_msg)
480 def vpp_show_flow_entry(node):
483 :param node: DUT node.
486 :returns: flow entry.
489 cmd = u"vppctl show flow entry"
491 err_msg = u"Failed to show flow on host {node[u'host']}"
492 stdout, _ = exec_cmd_no_error(
493 node, cmd, sudo=False, message=err_msg, retries=120
496 return stdout.strip()
499 def vpp_verify_flow_action(
501 src_mac=u"11:22:33:44:55:66", dst_mac=u"11:22:33:44:55:66",
502 src_ip=None, dst_ip=None):
503 """Verify the correctness of the flow action.
505 :param node: DUT node.
506 :param action: Action.
507 :param value: Action value.
508 :param src_mac: Source mac address.
509 :param dst_mac: Destination mac address.
510 :param src_ip: Source IP address.
511 :param dst_ip: Destination IP address.
521 :raises RuntimeError: If the verification of flow action fails.
522 :raises ValueError: If action type is not supported.
524 err_msg = f"Failed to show trace on host {node[u'host']}"
525 cmd = u"vppctl show trace"
526 stdout, _ = exec_cmd_no_error(
527 node, cmd, sudo=False, message=err_msg, retries=120
530 err_info = f"Verify flow {action} failed"
533 expected_str = f"{src_mac} -> {dst_mac}"
535 src_ip = ip_address(src_ip)
536 dst_ip = ip_address(dst_ip)
537 expected_str = f"{src_ip} -> {dst_ip}"
539 if action == u"drop":
540 if expected_str in stdout:
541 raise RuntimeError(err_info)
542 elif action == u"redirect-to-queue":
543 if f"queue {value}" not in stdout \
544 and f"qid {value}" not in stdout:
545 raise RuntimeError(err_info)
546 if expected_str not in stdout:
547 raise RuntimeError(err_info)
548 elif action == u"mark":
549 if u"PKT_RX_FDIR" not in stdout and u"flow-id 1" not in stdout:
550 raise RuntimeError(err_info)
551 if expected_str not in stdout:
552 raise RuntimeError(err_info)
554 raise ValueError(f"Unsupported action type: {action}")