summaryrefslogtreecommitdiffstats
path: root/src/vlib
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2018-03-05 20:08:28 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2018-03-05 20:02:41 +0000
commit88c062119b5e94ef19e02f007e38ee119b02218f (patch)
tree319e63d64e6217db698674e92ed5a18c1728a44e /src/vlib
parent3cf2d6403dd90083fe2c678c03565f6f483de9e3 (diff)
physmem: keep only one physmem_main
We don't need per vlib_main physmem_main, so keep it separatelly instead of trying to keep them in sync. Change-Id: I0fbeecf4d9672d31af7a43c640a7d8f05dd6e46f Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vlib')
-rw-r--r--src/vlib/linux/physmem.c8
-rw-r--r--src/vlib/linux/vfio.c2
-rw-r--r--src/vlib/main.h2
-rw-r--r--src/vlib/physmem.h2
-rw-r--r--src/vlib/physmem_funcs.h4
-rw-r--r--src/vlib/unix/main.c1
6 files changed, 10 insertions, 9 deletions
diff --git a/src/vlib/linux/physmem.c b/src/vlib/linux/physmem.c
index f60a6f75adf..b3703388b84 100644
--- a/src/vlib/linux/physmem.c
+++ b/src/vlib/linux/physmem.c
@@ -114,7 +114,7 @@ unix_physmem_region_alloc (vlib_main_t * vm, char *name, u32 size,
u8 numa_node, u32 flags,
vlib_physmem_region_index_t * idx)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
vlib_physmem_region_t *pr;
clib_error_t *error = 0;
clib_mem_vm_alloc_t alloc = { 0 };
@@ -208,7 +208,7 @@ done:
static void
unix_physmem_region_free (vlib_main_t * vm, vlib_physmem_region_index_t idx)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
vlib_physmem_region_t *pr = vlib_physmem_get_region (vm, idx);
if (pr->fd > 0)
@@ -221,7 +221,7 @@ unix_physmem_region_free (vlib_main_t * vm, vlib_physmem_region_index_t idx)
clib_error_t *
unix_physmem_init (vlib_main_t * vm)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
linux_vfio_main_t *lvm = &vfio_main;
clib_error_t *error = 0;
u64 *pt = 0;
@@ -254,7 +254,7 @@ static clib_error_t *
show_physmem (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
vlib_physmem_region_t *pr;
/* *INDENT-OFF* */
diff --git a/src/vlib/linux/vfio.c b/src/vlib/linux/vfio.c
index dffe49ce7b2..e39bf01fdc0 100644
--- a/src/vlib/linux/vfio.c
+++ b/src/vlib/linux/vfio.c
@@ -57,7 +57,7 @@ linux_vfio_main_t vfio_main;
static int
map_regions (vlib_main_t * vm, int fd)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
vlib_physmem_region_t *pr;
struct vfio_iommu_type1_dma_map dm = { 0 };
int i;
diff --git a/src/vlib/main.h b/src/vlib/main.h
index 28412e823a9..2eec930e9b6 100644
--- a/src/vlib/main.h
+++ b/src/vlib/main.h
@@ -105,8 +105,6 @@ typedef struct vlib_main_t
vlib_buffer_main_t *buffer_main;
- vlib_physmem_main_t physmem_main;
-
/* Allocate/free buffer memory for DMA transfers, descriptor rings, etc.
buffer memory is guaranteed to be cache-aligned. */
diff --git a/src/vlib/physmem.h b/src/vlib/physmem.h
index e99db7de72c..2f54938ff10 100644
--- a/src/vlib/physmem.h
+++ b/src/vlib/physmem.h
@@ -73,6 +73,8 @@ typedef struct
vlib_physmem_region_t *regions;
} vlib_physmem_main_t;
+extern vlib_physmem_main_t physmem_main;
+
#endif /* included_vlib_physmem_h */
/*
diff --git a/src/vlib/physmem_funcs.h b/src/vlib/physmem_funcs.h
index 0013c2f70cd..bff66aa5726 100644
--- a/src/vlib/physmem_funcs.h
+++ b/src/vlib/physmem_funcs.h
@@ -43,7 +43,7 @@
always_inline vlib_physmem_region_t *
vlib_physmem_get_region (vlib_main_t * vm, u8 index)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
return pool_elt_at_index (vpm->regions, index);
}
@@ -129,7 +129,7 @@ always_inline u64
vlib_physmem_virtual_to_physical (vlib_main_t * vm,
vlib_physmem_region_index_t idx, void *mem)
{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
+ vlib_physmem_main_t *vpm = &physmem_main;
vlib_physmem_region_t *pr = pool_elt_at_index (vpm->regions, idx);
uword o = mem - pr->mem;
return vlib_physmem_offset_to_physical (vm, idx, o);
diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c
index 7e868f99cc2..786addf2e0a 100644
--- a/src/vlib/unix/main.c
+++ b/src/vlib/unix/main.c
@@ -61,6 +61,7 @@ char *vlib_default_runtime_dir = "vlib";
unix_main_t unix_main;
clib_file_main_t file_main;
+vlib_physmem_main_t physmem_main;
static clib_error_t *
unix_main_init (vlib_main_t * vm)
ef='#n218'>218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
# Copyright (c) 2020 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:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Path utilities library for nodes in the topology."""

from resources.libraries.python.topology import Topology


class NodePath:
    """Path utilities for nodes in the topology.

    :Example:

    node1--link1-->node2--link2-->node3--link3-->node2--link4-->node1
    RobotFramework:
    | Library | resources/libraries/python/NodePath.py

    | Path test
    | | [Arguments] | ${node1} | ${node2} | ${node3}
    | | Append Node | ${nodes1}
    | | Append Node | ${nodes2}
    | | Append Nodes | ${nodes3} | ${nodes2}
    | | Append Node | ${nodes1}
    | | Compute Path | ${FALSE}
    | | ${first_int} | ${node}= | First Interface
    | | ${last_int} | ${node}= | Last Interface
    | | ${first_ingress} | ${node}= | First Ingress Interface
    | | ${last_egress} | ${node}= | Last Egress Interface
    | | ${next} | ${node}= | Next Interface

    Python:
    >>> from NodePath import NodePath
    >>> path = NodePath()
    >>> path.append_node(node1)
    >>> path.append_node(node2)
    >>> path.append_nodes(node3, node2)
    >>> path.append_node(node1)
    >>> path.compute_path()
    >>> (interface, node) = path.first_interface()
    >>> (interface, node) = path.last_interface()
    >>> (interface, node) = path.first_ingress_interface()
    >>> (interface, node) = path.last_egress_interface()
    >>> (interface, node) = path.next_interface()
    """

    def __init__(self):
        self._nodes = []
        self._nodes_filter = []
        self._links = []
        self._path = []
        self._path_iter = []

    def append_node(self, node, filter_list=None):
        """Append node to the path.

        :param node: Node to append to the path.
        :param filter_list: Filter criteria list.
        :type node: dict
        :type filter_list: list of strings
        """
        self._nodes_filter.append(filter_list)
        self._nodes.append(node)

    def append_nodes(self, *nodes, filter_list=None):
        """Append nodes to the path.

        :param nodes: Nodes to append to the path.
        :param filter_list: Filter criteria list.
        :type nodes: dict
        :type filter_list: list of strings

        .. note:: Node order does matter.
        """
        for node in nodes:
            self.append_node(node, filter_list=filter_list)

    def clear_path(self):
        """Clear path."""
        self._nodes = []
        self._nodes_filter = []
        self._links = []
        self._path = []
        self._path_iter = []

    def compute_path(self, always_same_link=True):
        """Compute path for added nodes.

        .. note:: First add at least two nodes to the topology.

        :param always_same_link: If True use always same link between two nodes
            in path. If False use different link (if available)
            between two nodes if one link was used before.
        :type always_same_link: bool
        :raises RuntimeError: If not enough nodes for path.
        """
        nodes = self._nodes
        if len(nodes) < 2:
            raise RuntimeError(u"Not enough nodes to compute path")

        for idx in range(0, len(nodes) - 1):
            topo = Topology()
            node1 = nodes[idx]
            node2 = nodes[idx + 1]
            n1_list = self._nodes_filter[idx]
            n2_list = self._nodes_filter[idx + 1]
            links = topo.get_active_connecting_links(
                node1, node2, filter_list_node1=n1_list,
                filter_list_node2=n2_list
            )
            if not links:
                raise RuntimeError(
                    f"No link between {node1[u'host']} and {node2[u'host']}"
                )

            # Not using set operations, as we need deterministic order.
            if always_same_link:
                l_set = [link for link in links if link in self._links]
            else:
                l_set = [link for link in links if link not in self._links]
                if not l_set:
                    raise RuntimeError(
                        f"No free link between {node1[u'host']} and "
                        f"{node2[u'host']}, all links already used"
                    )

            if not l_set:
                link = links[0]
            else:
                link = l_set[0]

            self._links.append(link)
            interface1 = topo.get_interface_by_link_name(node1, link)
            interface2 = topo.get_interface_by_link_name(node2, link)
            self._path.append((interface1, node1))
            self._path.append((interface2, node2))

        self._path_iter.extend(self._path)
        self._path_iter.reverse()

    def next_interface(self):
        """Path interface iterator.

        :returns: Interface and node or None if not next interface.
        :rtype: tuple (str, dict)

        .. note:: Call compute_path before.
        """
        if not self._path_iter:
            return None, None
        return self._path_iter.pop()

    def first_interface(self):
        """Return first interface on the path.

        :returns: Interface and node.
        :rtype: tuple (str, dict)

        .. note:: Call compute_path before.
        """
        if not self._path:
            raise RuntimeError(u"No path for topology")
        return self._path[0]

    def last_interface(self):
        """Return last interface on the path.

        :returns: Interface and node.
        :rtype: tuple (str, dict)

        .. note:: Call compute_path before.
        """
        if not self._path:
            raise RuntimeError(u"No path for topology")
        return self._path[-1]

    def first_ingress_interface(self):
        """Return first ingress interface on the path.

        :returns: Interface and node.
        :rtype: tuple (str, dict)

        .. note:: Call compute_path before.
        """
        if not self._path:
            raise RuntimeError(u"No path for topology")
        return self._path[1]

    def last_egress_interface(self):
        """Return last egress interface on the path.

        :returns: Interface and node.
        :rtype: tuple (str, dict)

        .. note:: Call compute_path before.
        """
        if not self._path:
            raise RuntimeError(u"No path for topology")
        return self._path[-2]

    def compute_circular_topology(self, nodes, filter_list=None, nic_pfs=1,
                                  always_same_link=False, topo_has_tg=True):
        """Return computed circular path.

        :param nodes: Nodes to append to the path.
        :param filter_list: Filter criteria list.
        :param nic_pfs: Number of PF of NIC.
        :param always_same_link: If True use always same link between two nodes
            in path. If False use different link (if available)
            between two nodes if one link was used before.
        :param topo_has_tg: If True, the topology has a TG node. If False,
            the topology consists entirely of DUT nodes.
        :type nodes: dict
        :type filter_list: list of strings
        :type nic_pfs: int
        :type always_same_link: bool
        :type topo_has_tg: bool
        :returns: Topology information dictionary.
        :rtype: dict
        :raises RuntimeError: If unsupported combination of parameters.
        """
        t_dict = dict()
        duts = [key for key in nodes if u"DUT" in key]
        t_dict[u"duts"] = duts
        t_dict[u"duts_count"] = len(duts)
        t_dict[u"int"] = u"pf"

        for _ in range(0, nic_pfs // 2):
            if topo_has_tg:
                self.append_node(nodes[u"TG"])
            for dut in duts:
                self.append_node(nodes[dut], filter_list=filter_list)
        if topo_has_tg:
            self.append_node(nodes[u"TG"])
        self.compute_path(always_same_link)

        n_idx = 0 # node index
        t_idx = 1 # TG interface index
        d_idx = 0 # DUT interface index
        prev_host = None
        while True:
            interface, node = self.next_interface()
            if not interface:
                break
            if topo_has_tg and node.get(u"type") == u"TG":
                n_pfx = f"TG" # node prefix
                p_pfx = f"pf{t_idx}" # physical interface prefix
                i_pfx = f"if{t_idx}" # [backwards compatible] interface prefix
                n_idx = 0
                t_idx = t_idx + 1
            elif topo_has_tg:
                # Each node has 2 interfaces, starting with 1
                # Calculate prefixes appropriately for current
                # path topology nomenclature:
                #   tg1_if1 -> dut1_if1 -> dut1_if2 ->
                #        [dut2_if1 -> dut2_if2 ...] -> tg1_if2
                n_pfx = f"DUT{n_idx // 2 + 1}"
                p_pfx = f"pf{d_idx % 2 + t_idx - 1}"
                i_pfx = f"if{d_idx % 2 + t_idx - 1}"
                n_idx = n_idx + 1
                d_idx = d_idx + 1
            elif not topo_has_tg and always_same_link:
                this_host = node.get(u"host")
                if prev_host != this_host:
                    # When moving to a new host in the path,
                    # increment the node index (n_idx) and
                    # reset DUT interface index (d_idx) to 1.
                    n_idx = n_idx + 1
                    d_idx = 1
                n_pfx = f"DUT{n_idx}"
                p_pfx = f"pf{d_idx}"
                i_pfx = f"if{d_idx}"
                d_idx = d_idx + 1
            else:
                raise RuntimeError(u"Unsupported combination of paramters")

            t_dict[f"{n_pfx}"] = node
            t_dict[f"{n_pfx}_{p_pfx}"] = [interface]
            t_dict[f"{n_pfx}_{p_pfx}_mac"] = \
                [Topology.get_interface_mac(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_vlan"] = \
                [Topology.get_interface_vlan(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_pci"] = \
                [Topology.get_interface_pci_addr(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_addr"] = \
                [Topology.get_interface_ip4(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_prefix"] = \
                [Topology.get_interface_ip4_prefix_length(node, interface)]
            if f"{n_pfx}_pf_pci" not in t_dict:
                t_dict[f"{n_pfx}_pf_pci"] = []
            t_dict[f"{n_pfx}_pf_pci"].append(
                Topology.get_interface_pci_addr(node, interface))
            if f"{n_pfx}_pf_keys" not in t_dict:
                t_dict[f"{n_pfx}_pf_keys"] = []
            t_dict[f"{n_pfx}_pf_keys"].append(interface)
            # Backward compatibility below
            t_dict[f"{n_pfx.lower()}_{i_pfx}"] = interface
            t_dict[f"{n_pfx.lower()}_{i_pfx}_mac"] = \
                Topology.get_interface_mac(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_pci"] = \
                Topology.get_interface_pci_addr(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_addr"] = \
                Topology.get_interface_ip4(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_prefix"] = \
                Topology.get_interface_ip4_prefix_length(node, interface)

        self.clear_path()
        return t_dict