-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2023 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
pass
@staticmethod
- def enable_nat44_plugin(
- node, inside_vrf=0, outside_vrf=0, users=0, user_memory=0,
- sessions=0, session_memory=0, user_sessions=0, mode=u""):
+ def enable_nat44_ed_plugin(
+ node, inside_vrf=0, outside_vrf=0, sessions=0, session_memory=0,
+ mode=u""):
"""Enable NAT44 plugin.
:param node: DUT node.
:param inside_vrf: Inside VRF ID.
:param outside_vrf: Outside VRF ID.
- :param users: Maximum number of users. Used only in endpoint-independent
- mode.
- :param user_memory: User memory size - overwrite auto calculated hash
- allocation parameter if non-zero.
:param sessions: Maximum number of sessions.
:param session_memory: Session memory size - overwrite auto calculated
hash allocation parameter if non-zero.
- :param user_sessions: Maximum number of sessions per user. Used only in
- endpoint-independent mode.
:param mode: NAT44 mode. Valid values:
- endpoint-independent
- endpoint-dependent
:type node: dict
:type inside_vrf: str or int
:type outside_vrf: str or int
- :type users: str or int
- :type user_memory: str or int
:type sessions: str or int
:type session_memory: str or int
- :type user_sessions: str or int
:type mode: str
"""
- cmd = u"nat44_plugin_enable_disable"
+ cmd = u"nat44_ed_plugin_enable_disable"
err_msg = f"Failed to enable NAT44 plugin on the host {node[u'host']}!"
args_in = dict(
enable=True,
inside_vrf=int(inside_vrf),
outside_vrf=int(outside_vrf),
- users=int(users),
- user_memory=int(user_memory),
sessions=int(sessions),
session_memory=int(session_memory),
- user_sessions=int(user_sessions),
flags=getattr(
Nat44ConfigFlags,
f"NAT44_IS_{mode.replace(u'-', u'_').upper()}"
"""Delete and re-add the NAT range setting."""
with PapiSocketExecutor(node) as papi_exec:
args_in[u"is_add"] = False
- papi_exec.add(cmd, **args_in)
+ papi_exec.add(cmd, **args_in).get_reply(err_msg)
args_in[u"is_add"] = True
- papi_exec.add(cmd, **args_in)
- papi_exec.get_replies(err_msg)
+ papi_exec.add(cmd, **args_in).get_reply(err_msg)
return resetter
cmd = u"nat44_show_running_config"
err_msg = f"Failed to get NAT44 configuration on host {node[u'host']}"
- try:
- with PapiSocketExecutor(node) as papi_exec:
- reply = papi_exec.add(cmd).get_reply(err_msg)
- except AssertionError:
- # Perhaps VPP is an older version
- old_cmd = u"nat_show_config"
- with PapiSocketExecutor(node) as papi_exec:
- reply = papi_exec.add(old_cmd).get_reply(err_msg)
+ with PapiSocketExecutor(node) as papi_exec:
+ reply = papi_exec.add(cmd).get_reply(err_msg)
logger.debug(f"NAT44 Configuration:\n{pformat(reply)}")
:rtype: int
"""
# vpp-device tests have not dedicated physical core so
- # ${thr_count_int} == 0 but we need to use one thread
+ # ${dp_count_int} == 0 but we need to use one thread
threads = 1 if not int(threads) else int(threads)
rest, mult = modf(log2(sessions/(10*threads)))
return 2 ** (int(mult) + (1 if rest else 0)) * 10
@staticmethod
def get_nat44_sessions_number(node, proto):
- """Get number of established NAT44 sessions from actual NAT44 mapping
- data.
+ """Get number of expected NAT44 sessions from NAT44 mapping data.
+
+ This keyword uses output from a CLI command,
+ so it can start failing when VPP changes the output format.
+ TODO: Switch to API (or stat segment) when available.
+
+ The current implementation supports both 2202 and post-2202 format.
+ (The Gerrit number changing the output format is 34877.)
+
+ For TCP proto, the expected state after rampup is
+ some number of sessions in transitory state (VPP has seen the FINs),
+ and some number of sessions in established state (meaning
+ some FINs were lost in the last trial).
+ While the two states may need slightly different number of cycles
+ to process next packet, the current implementation considers
+ both of them the "fast path", so they are both counted as expected.
+
+ As the tests should fail if a session is timed-out,
+ the logic substracts timed out sessions for the returned value
+ (only available for post-2202 format).
+
+ TODO: Investigate if it is worth to insert additional rampup trials
+ in TPUT tests to ensure all sessions are transitory before next
+ measurement.
:param node: DUT node.
:param proto: Required protocol - TCP/UDP/ICMP.
:type node: dict
:type proto: str
- :returns: Number of established NAT44 sessions.
+ :returns: Number of active established NAT44 sessions.
:rtype: int
:raises ValueError: If not supported protocol.
+ :raises RuntimeError: If output is not formatted as expected.
"""
- nat44_data = dict()
- if proto in [u"UDP", u"TCP", u"ICMP"]:
- for line in NATUtil.show_nat44_summary(node).splitlines():
- sum_k, sum_v = line.split(u":") if u":" in line \
- else (line, None)
- nat44_data[sum_k] = sum_v.strip() if isinstance(sum_v, str) \
- else sum_v
- else:
+ proto_l = proto.strip().lower()
+ if proto_l not in [u"udp", u"tcp", u"icmp"]:
raise ValueError(f"Unsupported protocol: {proto}!")
- return nat44_data.get(f"total {proto.lower()} sessions", 0)
+ summary_text = NATUtil.show_nat44_summary(node)
+ summary_lines = summary_text.splitlines()
+ # Output from VPP v22.02 and before, delete when no longer needed.
+ pattern_2202 = f"total {proto_l} sessions:"
+ if pattern_2202 in summary_text:
+ for line in summary_lines:
+ if pattern_2202 not in line:
+ continue
+ return int(line.split(u":", 1)[1].strip())
+ # Post-2202, the proto info and session info are not on the same line.
+ found = False
+ for line in summary_lines:
+ if not found:
+ if f"{proto_l} sessions:" in line:
+ found = True
+ continue
+ # Proto is found, find the line we are interested in.
+ if u"total" not in line:
+ raise RuntimeError(f"show nat summary: no {proto} total.")
+ # We have the line with relevant numbers.
+ total_part, timed_out_part = line.split(u"(", 1)
+ timed_out_part = timed_out_part.split(u")", 1)[0]
+ total_count = int(total_part.split(u":", 1)[1].strip())
+ timed_out_count = int(timed_out_part.split(u":", 1)[1].strip())
+ active_count = total_count - timed_out_count
+ return active_count
+ raise RuntimeError(u"Unknown format of show nat44 summary")
# DET44 PAPI calls
# DET44 means deterministic mode of NAT44
"""Delete and re-add the deterministic NAT mapping."""
with PapiSocketExecutor(node) as papi_exec:
args_in[u"is_add"] = False
- papi_exec.add(cmd, **args_in)
+ papi_exec.add(cmd, **args_in).get_reply(err_msg)
args_in[u"is_add"] = True
- papi_exec.add(cmd, **args_in)
- papi_exec.get_replies(err_msg)
+ papi_exec.add(cmd, **args_in).get_reply(err_msg)
return resetter