LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk/n3k - vr_dpdk_n3k_interface.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 14 52 26.9 %
Date: 2026-08-03 02:19:58 Functions: 2 6 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* SPDX-License-Identifier: BSD-2-Clause
       2             :  * Copyright(c) HCL TECHNOLOGIES LTD
       3             :  * Submitted on behalf of a third-party: Intel Corporation, a
       4             :  * Delaware corporation, having its principal place of business
       5             :  * at 2200 Mission College Boulevard,
       6             :  * Santa Clara, California 95052, USA
       7             :  */
       8             : 
       9             : #include "vr_dpdk_n3k_offloads.h"
      10             : #include "vr_dpdk_n3k_missing_mirror.h"
      11             : #include "vr_dpdk_n3k_interface.h"
      12             : #include "vr_dpdk_n3k_flow.h"
      13             : 
      14             : #include <rte_log.h>
      15             : #include <rte_malloc.h>
      16             : 
      17             : #include "vr_dpdk.h"
      18             : #include "vr_interface.h"
      19             : 
      20             : struct interface_meta {
      21             :     bool exists;
      22             :     uint8_t mirror_id;
      23             : };
      24             : 
      25             : /* Note: This array does not need to be protected by any lock, as it's accessed
      26             :  * only from add/del callbacks, which vrouter calls only from only one thread
      27             :  * (dpdk_lcore_netlink_loop) */
      28             : static struct interface_meta *interfaces;
      29             : 
      30             : int
      31           0 : vr_dpdk_n3k_offload_interface_init(uint16_t count)
      32             : {
      33           0 :     interfaces = rte_zmalloc("n3k_offload_vif", count * sizeof(*interfaces), 0);
      34           0 :     if (interfaces == NULL)
      35           0 :         return -ENOMEM;
      36             : 
      37           0 :     return 0;
      38             : }
      39             : 
      40             : void
      41           0 : vr_dpdk_n3k_offload_interface_exit(void)
      42             : {
      43           0 :     rte_free(interfaces);
      44           0 :     interfaces = NULL;
      45           0 : }
      46             : 
      47          62 : static bool is_vif_supported(const struct vr_interface *vif) {
      48             :     /* TODO(n3k): Handle multiple routers */
      49          62 :     if (vif->vif_rid != 0)
      50           0 :         return false;
      51             : 
      52          62 :     if (!vif_is_fabric(vif) && !vif_is_virtual(vif))
      53           0 :         return false;
      54             : 
      55          62 :     if (vif->vif_os == NULL) {
      56           0 :         RTE_LOG(ERR, VROUTER,
      57             :             "Failed to translate vr_interface (idx=%hu) into port_id, vif_os is NULL.\n",
      58             :             vif->vif_idx);
      59           0 :         return false;
      60             :     }
      61          62 :     return true;
      62             : }
      63             : 
      64             : const struct vr_interface *
      65          62 : vr_dpdk_n3k_offload_interface_get(uint16_t id,struct vr_interface **used_as_virtual)
      66             : {
      67             :     /* Using intermediate variable to avoid changing used_as_virtual on fail */
      68          62 :     struct vr_interface *virtual_vif = NULL;
      69             : 
      70             :     /* Note: Using `__vrouter_get_interface` instead of
      71             :      * `vrouter_get_interface`, as we don't need nor want to touch the
      72             :      * refcount. See the comment on `vr_dpdk_n3k_offload_nexthop_get */
      73          62 :     struct vr_interface *vif = __vrouter_get_interface(vrouter_get(0), id);
      74             : 
      75          62 :     if (vif == NULL)
      76           0 :         return NULL;
      77             : 
      78             :     /* For virtual VLAN, use parent interface */
      79          62 :     if (vif_is_vlan(vif) && (vif->vif_parent != NULL)) {
      80           0 :         virtual_vif = vif;
      81           0 :         vif = __vrouter_get_interface(vrouter_get(0), vif->vif_parent->vif_idx);
      82             :     }
      83             : 
      84          62 :     if (vif == NULL || !is_vif_supported(vif))
      85           0 :         return NULL;
      86             : 
      87          62 :     if (used_as_virtual != NULL)
      88          56 :         *used_as_virtual = virtual_vif;
      89             : 
      90          62 :     return vif;
      91             : }
      92             : 
      93             : int
      94           0 : vr_dpdk_n3k_offload_interface_add(struct vr_interface *vif)
      95             : {
      96           0 :     int ret = 0;
      97           0 :     unsigned short id = vif->vif_idx;
      98             : 
      99           0 :     bool mirror_changed = interfaces[id].exists && interfaces[id].mirror_id != vif->vif_mirror_id;
     100             : 
     101           0 :     interfaces[id] = (struct interface_meta) {
     102             :         .exists = true,
     103           0 :         .mirror_id = vif->vif_mirror_id,
     104             :     };
     105             : 
     106           0 :     if (!is_vif_supported(vif)) {
     107           0 :         return 0;
     108             :     }
     109             : 
     110           0 :     vr_dpdk_n3k_offload_lock();
     111             : 
     112           0 :     if (mirror_changed) {
     113           0 :         ret = vr_dpdk_n3k_offload_flow_vif_update_unlocked(vif);
     114           0 :         if (ret) {
     115           0 :             RTE_LOG(ERR, VROUTER, "%s(): vif's flows update failed: %d\n",
     116             :                 __func__, ret);
     117           0 :             goto out;
     118             :         }
     119             :     }
     120             : 
     121           0 :     vr_dpdk_n3k_offload_missing_vif_flows_unlocked(vif->vif_idx);
     122             : 
     123           0 : out:
     124           0 :     vr_dpdk_n3k_offload_unlock();
     125             : 
     126           0 :     return ret;
     127             : }
     128             : 
     129             : int
     130           0 : vr_dpdk_n3k_offload_interface_del(struct vr_interface *vif)
     131             : {
     132           0 :     interfaces[vif->vif_idx].exists = false;
     133           0 :     return 0;
     134             : }

Generated by: LCOV version 1.14