aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--resources/libraries/python/Memif.py309
-rw-r--r--resources/libraries/robot/shared/memif.robot10
2 files changed, 140 insertions, 179 deletions
diff --git a/resources/libraries/python/Memif.py b/resources/libraries/python/Memif.py
index 40178986d8..71c476fb9e 100644
--- a/resources/libraries/python/Memif.py
+++ b/resources/libraries/python/Memif.py
@@ -13,20 +13,117 @@
"""Memif interface library."""
-from resources.libraries.python.ssh import SSH
-from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
+import logging
+
+from enum import IntEnum
+
from resources.libraries.python.topology import NodeType, Topology
+from resources.libraries.python.PapiExecutor import PapiExecutor
+from resources.libraries.python.L2Util import L2Util
+
+
+class MemifRole(IntEnum):
+ """Memif interface roles"""
+ MASTER = 0
+ SLAVE = 1
class Memif(object):
- """Memif interface class."""
+ """Memif interface class"""
def __init__(self):
pass
@staticmethod
+ def _memif_dump(node):
+ """Get the memif dump on the given node.
+
+ :param node: Given node to get Memif dump from.
+ :type node: dict
+ :returns: List of memif interfaces extracted from Papi response.
+ :rtype: list
+ """
+ with PapiExecutor(node) as papi_exec:
+ dump = papi_exec.add("memif_dump").get_dump()
+
+ data = list()
+ for item in dump.reply[0]["api_reply"]:
+ item["memif_details"]["if_name"] = \
+ item["memif_details"]["if_name"].rstrip('\x00')
+ item["memif_details"]["hw_addr"] = \
+ L2Util.bin_to_mac(item["memif_details"]["hw_addr"])
+ data.append(item)
+
+ logging.debug("MEMIF data:\n{data}".format(data=data))
+
+ return data
+
+ @staticmethod
+ def _memif_socket_filename_add_del(node, is_add, filename, sid):
+ """Create Memif socket on the given node.
+
+ :param node: Given node to create Memif socket on.
+ :param is_add: If True, socket is added, otherwise deleted.
+ :param filename: Memif interface socket filename.
+ :param sid: Socket ID.
+ :type node: dict
+ :type is_add: bool
+ :type filename: str
+ :type sid: str
+ :returns: Verified data from PAPI response. In this case, the response
+ includes only retval.
+ :rtype: dict
+ """
+ cmd = 'memif_socket_filename_add_del'
+ err_msg = 'Failed to create memif socket on host {host}'.format(
+ host=node['host'])
+ args = dict(
+ is_add=int(is_add),
+ socket_id=int(sid),
+ socket_filename=str('/tmp/' + filename)
+ )
+ with PapiExecutor(node) as papi_exec:
+ data = papi_exec.add(cmd, **args).get_replies(err_msg).\
+ verify_reply(err_msg=err_msg)
+ return data
+
+ @staticmethod
+ def _memif_create(node, mid, sid, rxq=1, txq=1, role=1):
+ """Create Memif interface on the given node.
+
+ :param node: Given node to create Memif interface on.
+ :param mid: Memif interface ID.
+ :param sid: Socket ID.
+ :param rxq: Number of RX queues; 0 means do not set.
+ :param txq: Number of TX queues; 0 means do not set.
+ :param role: Memif interface role [master=0|slave=1]. Default is slave.
+ :type node: dict
+ :type mid: str
+ :type sid: str
+ :type rxq: int
+ :type txq: int
+ :type role: int
+ :returns: Verified data from PAPI response.
+ :rtype: dict
+ """
+ cmd = 'memif_create'
+ err_msg = 'Failed to create memif interface on host {host}'.format(
+ host=node['host'])
+ args = dict(
+ role=role,
+ rx_queues=int(rxq),
+ tx_queues=int(txq),
+ socket_id=int(sid),
+ id=int(mid)
+ )
+ with PapiExecutor(node) as papi_exec:
+ data = papi_exec.add(cmd, **args).get_replies(err_msg).\
+ verify_reply(err_msg=err_msg)
+ return data
+
+ @staticmethod
def create_memif_interface(node, filename, mid, sid, rxq=1, txq=1,
- role='slave'):
+ role="SLAVE"):
"""Create Memif interface on the given node.
:param node: Given node to create Memif interface on.
@@ -35,7 +132,7 @@ class Memif(object):
:param sid: Socket ID.
:param rxq: Number of RX queues; 0 means do not set.
:param txq: Number of TX queues; 0 means do not set.
- :param role: Memif interface role [master|slave]. Default is master.
+ :param role: Memif interface role [master=0|slave=1]. Default is master.
:type node: dict
:type filename: str
:type mid: str
@@ -48,48 +145,29 @@ class Memif(object):
:raises ValueError: If command 'create memif' fails.
"""
- rx_q = 'rx-queues {rxq}'.format(rxq=rxq) if rxq else ''
- tx_q = 'tx-queues {txq}'.format(txq=txq) if txq else ''
-
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template(
- 'memif_socket_filename_add_del.vat',
- add_del='add', id=sid, filename='/tmp/'+filename)
- vat.vat_terminal_exec_cmd_from_template(
- 'memif_create.vat', id=mid, socket=sid, rx_q=rx_q, tx_q=tx_q,
- role=role)
- if 'sw_if_index' in vat.vat_stdout:
- try:
- sw_if_idx = int(vat.vat_stdout.split()[4])
- if_key = Topology.add_new_port(node, 'memif')
- Topology.update_interface_sw_if_index(
- node, if_key, sw_if_idx)
- ifc_name = Memif.vpp_get_memif_interface_name(
- node, sw_if_idx)
- Topology.update_interface_name(node, if_key, ifc_name)
- ifc_mac = Memif.vpp_get_memif_interface_mac(node, sw_if_idx)
- Topology.update_interface_mac_address(node, if_key, ifc_mac)
- Topology.update_interface_memif_socket(node, if_key,
- '/tmp/'+filename)
- Topology.update_interface_memif_id(node, if_key, mid)
- Topology.update_interface_memif_role(node, if_key, role)
- return sw_if_idx
- except KeyError:
- raise ValueError('Create Memif interface failed on node '
- '{}'.format(node['host']))
- else:
- raise ValueError('Create Memif interface failed on node '
- '{}'.format(node['host']))
+ role = getattr(MemifRole, role.upper()).value
- @staticmethod
- def dump_memif(node):
- """Dump Memif data for the given node.
+ # Create socket
+ Memif._memif_socket_filename_add_del(node, True, filename, sid)
- :param node: Given node to show Memif data on.
- :type node: dict
- """
- vat = VatExecutor()
- vat.execute_script("memif_dump.vat", node, json_out=False)
+ # Create memif
+ rsp = Memif._memif_create(node, mid, sid, rxq=rxq, txq=txq, role=role)
+
+ # Update Topology
+ if_key = Topology.add_new_port(node, 'memif')
+ Topology.update_interface_sw_if_index(node, if_key, rsp["sw_if_index"])
+
+ ifc_name = Memif.vpp_get_memif_interface_name(node, rsp["sw_if_index"])
+ Topology.update_interface_name(node, if_key, ifc_name)
+
+ ifc_mac = Memif.vpp_get_memif_interface_mac(node, rsp["sw_if_index"])
+ Topology.update_interface_mac_address(node, if_key, ifc_mac)
+
+ Topology.update_interface_memif_socket(node, if_key, '/tmp/' + filename)
+ Topology.update_interface_memif_id(node, if_key, mid)
+ Topology.update_interface_memif_role(node, if_key, str(role))
+
+ return rsp["sw_if_index"]
@staticmethod
def show_memif(node):
@@ -98,8 +176,8 @@ class Memif(object):
:param node: Given node to show Memif data on.
:type node: dict
"""
- vat = VatExecutor()
- vat.execute_script("show_memif.vat", node, json_out=False)
+
+ Memif._memif_dump(node)
@staticmethod
def show_memif_on_all_duts(nodes):
@@ -113,66 +191,6 @@ class Memif(object):
Memif.show_memif(node)
@staticmethod
- def clear_memif_socks(node, *socks):
- """Clear Memif sockets for the given node.
-
- :param node: Given node to clear Memif sockets on.
- :param socks: Memif sockets.
- :type node: dict
- :type socks: list
- """
- ssh = SSH()
- ssh.connect(node)
-
- for sock in socks:
- ssh.exec_command_sudo('rm -f {}'.format(sock))
-
- @staticmethod
- def parse_memif_dump_data(memif_data):
- """Convert Memif data to dictionary.
-
- :param memif_data: Dump of Memif interfaces data.
- :type memif_data: str
- :returns: Memif interfaces data in dictionary.
- :rtype: dict
- :raises RuntimeError: If there is no memif interface name found in
- provided data.
- """
- memif_name = None
- memif_dict = dict()
- memif_data = str(memif_data)
- values = dict()
-
- clutter = ['vat#']
- for garbage in clutter:
- memif_data = memif_data.replace(garbage, '')
-
- for line in memif_data.splitlines():
- if not line or line.startswith('Sending'):
- continue
- elif line.startswith('memif'):
- if memif_name:
- memif_dict[memif_name] = values
- line_split = line.split(':', 1)
- memif_name = str(line_split[0])
- values = dict()
- line = line_split[1]
- line_split = line.split()
- for i in range(0, len(line_split), 2):
- key = str(line_split[i])
- try:
- value = line_split[i+1]
- except IndexError:
- value = None
- values[key] = value
- if memif_name:
- memif_dict[memif_name] = values
- else:
- raise RuntimeError('No memif interface name found')
-
- return memif_dict
-
- @staticmethod
def vpp_get_memif_interface_name(node, sw_if_idx):
"""Get Memif interface name from Memif interfaces dump.
@@ -183,12 +201,12 @@ class Memif(object):
:returns: Memif interface name, or None if not found.
:rtype: str
"""
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template('memif_dump.vat')
- memif_data = Memif.parse_memif_dump_data(vat.vat_stdout)
- for item in memif_data:
- if memif_data[item]['sw_if_index'] == str(sw_if_idx):
- return item
+
+ dump = Memif._memif_dump(node)
+
+ for item in dump:
+ if item["memif_details"]["sw_if_index"] == sw_if_idx:
+ return item["memif_details"]["if_name"]
return None
@staticmethod
@@ -202,67 +220,10 @@ class Memif(object):
:returns: Memif interface MAC address, or None if not found.
:rtype: str
"""
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template('memif_dump.vat')
- memif_data = Memif.parse_memif_dump_data(vat.vat_stdout)
- for item in memif_data:
- if memif_data[item]['sw_if_index'] == str(sw_if_idx):
- return memif_data[item].get('mac', None)
- return None
-
- @staticmethod
- def vpp_get_memif_interface_socket(node, sw_if_idx):
- """Get Memif interface socket path from Memif interfaces dump.
-
- :param node: DUT node.
- :param sw_if_idx: DUT node.
- :type node: dict
- :type sw_if_idx: int
- :returns: Memif interface socket path, or None if not found.
- :rtype: str
- """
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template('memif_dump.vat')
- memif_data = Memif.parse_memif_dump_data(vat.vat_stdout)
- for item in memif_data:
- if memif_data[item]['sw_if_index'] == str(sw_if_idx):
- return memif_data[item].get('socket', None)
- return None
-
- @staticmethod
- def vpp_get_memif_interface_id(node, sw_if_idx):
- """Get Memif interface ID from Memif interfaces dump.
-
- :param node: DUT node.
- :param sw_if_idx: DUT node.
- :type node: dict
- :type sw_if_idx: int
- :returns: Memif interface ID, or None if not found.
- :rtype: int
- """
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template('memif_dump.vat')
- memif_data = Memif.parse_memif_dump_data(vat.vat_stdout)
- for item in memif_data:
- if memif_data[item]['sw_if_index'] == str(sw_if_idx):
- return int(memif_data[item].get('id', None))
- return None
- @staticmethod
- def vpp_get_memif_interface_role(node, sw_if_idx):
- """Get Memif interface role from Memif interfaces dump.
+ dump = Memif._memif_dump(node)
- :param node: DUT node.
- :param sw_if_idx: DUT node.
- :type node: dict
- :type sw_if_idx: int
- :returns: Memif interface role, or None if not found.
- :rtype: int
- """
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template('memif_dump.vat')
- memif_data = Memif.parse_memif_dump_data(vat.vat_stdout)
- for item in memif_data:
- if memif_data[item]['sw_if_index'] == str(sw_if_idx):
- return memif_data[item].get('role', None)
+ for item in dump:
+ if item["memif_details"]["sw_if_index"] == sw_if_idx:
+ return item["memif_details"]["hw_addr"]
return None
diff --git a/resources/libraries/robot/shared/memif.robot b/resources/libraries/robot/shared/memif.robot
index 482a4cf77b..0b092c2f6a 100644
--- a/resources/libraries/robot/shared/memif.robot
+++ b/resources/libraries/robot/shared/memif.robot
@@ -33,7 +33,7 @@
| | ... | default value: ${1}
| | ... | - txq - TX queues; 0 means do not set (Optional). Type: integer,
| | ... | default value: ${1}
-| | ... | - role - Memif role (Optional). Type: string, default value: slave
+| | ... | - role - Memif role (Optional). Type: string, default value: SLAVE
| | ... | - dcr_uuid - UUID string (including prefix - underscore character) of
| | ... | DUT1 /tmp volume created outside of the DUT1 docker in case of
| | ... | vpp-device test. ${EMPTY} value means that /tmp directory is inside
@@ -49,13 +49,13 @@
| | ... | \| ${nodes['DUT1']} \| sock1 \| sock2 \| 1 \|
| | ... | \| Set up memif interfaces on DUT node \
| | ... | \| ${nodes['DUT2']} \| sock1 \| sock2 \| 1 \
-| | ... | \| dut2_memif_if1 \| dut2_memif_if2 \| 1 \| 1 \| slave \|
+| | ... | \| dut2_memif_if1 \| dut2_memif_if2 \| 1 \| 1 \| SLAVE \|
| | ... | \| ${nodes['DUT2']} \| sock1 \| sock2 \| 1 \| rxq=0 \| txq=0 \
| | ... | \| dcr_uuid=_a5730a0a-2ba1-4fe9-91bd-79b9828e968e \|
| | ...
| | [Arguments] | ${dut_node} | ${filename1} | ${filename2} | ${mid}=${1}
| | ... | ${memif_if1}=memif_if1 | ${memif_if2}=memif_if2 | ${rxq}=${1}
-| | ... | ${txq}=${1} | ${role}=slave | ${dcr_uuid}=${EMPTY}
+| | ... | ${txq}=${1} | ${role}=SLAVE | ${dcr_uuid}=${EMPTY}
| | ...
| | ${sid_1}= | Evaluate | (${mid}*2)-1
| | ${sid_2}= | Evaluate | (${mid}*2)
@@ -91,10 +91,10 @@
| | ...
| | ... | \| Set up single memif interface on DUT node \
| | ... | \| ${nodes['DUT1']} \| sock1 \| 1 \| dut1_memif_if1 \| 1 \| 1 \
-| | ... | \| slave \|
+| | ... | \| SLAVE \|
| | ...
| | [Arguments] | ${dut_node} | ${filename} | ${mid}=${1} | ${sid}=${1}
-| | ... | ${memif_if}=memif_if1 | ${rxq}=${1} | ${txq}=${1} | ${role}=slave
+| | ... | ${memif_if}=memif_if1 | ${rxq}=${1} | ${txq}=${1} | ${role}=SLAVE
| | ...
| | ${memif}= | Create memif interface | ${dut_node} | ${filename}${mid}-${sid}
| | ... | ${mid} | ${sid} | rxq=${rxq} | txq=${txq} | role=${role}