X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FNATUtil.py;h=841bd2e6836ab771f63d9944610c6dab55cd51f0;hp=0f8e74666380f3c4c415238df162e53603fd9eda;hb=1daa6fdc0bae284dee1b61f34534e59b60b7526a;hpb=d6af9d72acaca4dff70dce1b55dcc03f73061c7b diff --git a/resources/libraries/python/NATUtil.py b/resources/libraries/python/NATUtil.py index 0f8e746663..841bd2e683 100644 --- a/resources/libraries/python/NATUtil.py +++ b/resources/libraries/python/NATUtil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Cisco and/or its affiliates. +# Copyright (c) 2022 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: @@ -62,23 +62,18 @@ class NATUtil: 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 @@ -88,24 +83,18 @@ class NATUtil: :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()}" @@ -211,14 +200,8 @@ class NATUtil: 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)}") @@ -288,34 +271,77 @@ class NATUtil: :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