LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_vxlan.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 85 159 53.5 %
Date: 2026-11-09 02:10:49 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_vxlan.c -- VXLAN encapsulation handling
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  * Copyright Contributors to the OpenSDN project
       6             :  */
       7             : #include <vr_os.h>
       8             : #include <vr_types.h>
       9             : #include <vr_packet.h>
      10             : #include "vr_interface.h"
      11             : #include "vr_message.h"
      12             : #include "vr_sandesh.h"
      13             : #include "vr_vxlan.h"
      14             : #include "vr_bridge.h"
      15             : #include "vr_datapath.h"
      16             : #include "vr_offloads_dp.h"
      17             : 
      18             : int
      19           1 : vr_vxlan_input(struct vrouter *router, struct vr_packet *pkt,
      20             :                                 struct vr_forwarding_md *fmd)
      21             : {
      22             :     struct vr_vxlan *vxlan;
      23             :     unsigned int vnid, drop_reason;
      24             :     unsigned int flags;
      25             :     struct vr_nexthop *nh;
      26             :     struct vr_forwarding_md c_fmd;
      27             :     struct vr_ip *ip;
      28             : 
      29           1 :     if (!fmd) {
      30           0 :         vr_init_forwarding_md(&c_fmd);
      31           0 :         fmd = &c_fmd;
      32             :     }
      33             : 
      34           1 :     ip = (struct vr_ip *)pkt_network_header(pkt);
      35           1 :     fmd->fmd_outer_src_ip = ip->ip_saddr;
      36             : 
      37           1 :     vxlan = (struct vr_vxlan *)pkt_data(pkt);
      38           1 :     flags = ntohl(vxlan->vxlan_flags);
      39           1 :     if (!(flags & VR_VXLAN_IBIT)) {
      40           0 :         drop_reason = VP_DROP_INVALID_VNID;
      41           0 :         PKT_LOG(drop_reason, pkt, 0, VR_VXLAN_C, __LINE__);
      42           0 :         goto fail;
      43             :     }
      44           1 :     if (!fmd->fmd_fe) {
      45           1 :         vnid = ntohl(vxlan->vxlan_vnid) >> VR_VXLAN_VNID_SHIFT;
      46           1 :         if (!pkt_pull(pkt, sizeof(struct vr_vxlan))) {
      47           0 :             drop_reason = VP_DROP_PULL;
      48           0 :             PKT_LOG(drop_reason, pkt, 0, VR_VXLAN_C, __LINE__);
      49           0 :             goto fail;
      50             :         }
      51             : 
      52           1 :         nh = (struct vr_nexthop *)vr_itable_get(router->vr_vxlan_table, vnid);
      53           1 :         if (!nh) {
      54           0 :             drop_reason = VP_DROP_INVALID_VNID;
      55           0 :             PKT_LOG(drop_reason, pkt, 0, VR_VXLAN_C, __LINE__);
      56           0 :             goto fail;
      57             :         }
      58             :     } else {
      59           0 :         vnid = fmd->fmd_label;
      60           0 :         nh = pkt->vp_nh;
      61             :     }
      62             : 
      63           1 :     vr_fmd_set_label(fmd, vnid, VR_LABEL_TYPE_VXLAN_ID);
      64             : 
      65           1 :     fmd->fmd_vlan = VLAN_ID_INVALID;
      66             : 
      67           1 :     if (vr_pkt_type(pkt, 0, fmd) < 0) {
      68           0 :         drop_reason = VP_DROP_INVALID_PACKET;
      69           0 :         PKT_LOG(drop_reason, pkt, 0, VR_VXLAN_C, __LINE__);
      70           0 :         goto fail;
      71             :     }
      72             : 
      73           1 :     if (nh->nh_vrf >= 0) {
      74           1 :         fmd->fmd_dvrf = nh->nh_vrf;
      75           0 :     } else if (nh->nh_dev) {
      76           0 :         fmd->fmd_dvrf = nh->nh_dev->vif_vrf;
      77             :     } else {
      78           0 :         fmd->fmd_dvrf = pkt->vp_if->vif_vrf;
      79             :     }
      80             : 
      81           1 :     if (flags & VR_VXLAN_RABIT) {
      82           0 :         vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ROUTER_ALERT, NULL);
      83           0 :         return 0;
      84             :     }
      85             : 
      86           1 :     if (vr_perfr)
      87           1 :         vr_pkt_set_gro(pkt);
      88             : 
      89           1 :     return nh_output(pkt, nh, fmd);
      90             : 
      91           0 : fail:
      92           0 :     vr_pfree(pkt, drop_reason);
      93           0 :     return 0;
      94             : }
      95             : 
      96             : static void
      97           1 : vr_vxlan_make_req(vr_vxlan_req *req, struct vr_nexthop *nh, unsigned int vnid)
      98             : {
      99           1 :     memset(req, 0, sizeof(*req));
     100           1 :     req->vxlanr_vnid = vnid;
     101           1 :     if (nh)
     102           1 :         req->vxlanr_nhid = nh->nh_id;
     103             :     /* Debug comparison to check if matching entry is programmed on NIC */
     104           1 :     vr_offload_vxlan_get(req);
     105           1 :     return;
     106             : }
     107             : 
     108             : static int
     109           0 : vr_vxlan_trav_cb(unsigned int index, void *data, void *udata)
     110             : {
     111           0 :     struct vr_nexthop *nh = (struct vr_nexthop *)data;
     112           0 :     struct vr_message_dumper *dumper = (struct vr_message_dumper *)udata;
     113             :     vr_vxlan_req resp;
     114             : 
     115           0 :     vr_vxlan_make_req(&resp, nh, index);
     116           0 :     return vr_message_dump_object(dumper, VR_VXLAN_OBJECT_ID, &resp);
     117             : }
     118             : 
     119             : static int
     120           0 : vr_vxlan_dump(vr_vxlan_req *req)
     121             : {
     122             :     int ret;
     123           0 :     struct vr_message_dumper *dumper = NULL;
     124           0 :     struct vrouter *router = vrouter_get(req->vxlanr_rid);
     125             :     unsigned int index;
     126             : 
     127           0 :     if (!router && (ret = -ENODEV))
     128           0 :         goto generate_response;
     129             : 
     130           0 :     dumper = vr_message_dump_init(req);
     131           0 :     if (!dumper && (ret = -ENOMEM))
     132           0 :        goto generate_response;
     133             : 
     134           0 :    index = req->vxlanr_vnid;
     135           0 :    if (index)
     136           0 :        index++;
     137             : 
     138           0 :    ret = vr_itable_trav(router->vr_vxlan_table, vr_vxlan_trav_cb, index, dumper);
     139             : 
     140           0 : generate_response:
     141           0 :     vr_message_dump_exit(dumper, ret);
     142           0 :     return 0;
     143             : }
     144             : 
     145             : static int
     146           1 : vr_vxlan_get(vr_vxlan_req *req)
     147             : {
     148           1 :     int ret = 0;
     149           1 :     struct vr_nexthop *nh = NULL;
     150             :     struct vrouter *router;
     151             : 
     152           1 :     router = vrouter_get(req->vxlanr_rid);
     153           1 :     if (!router) {
     154           0 :         ret = -ENODEV;
     155             :     } else {
     156           1 :         nh = (struct vr_nexthop *)vr_itable_get(router->vr_vxlan_table,
     157           1 :                 req->vxlanr_vnid);
     158           1 :         if (!nh)
     159           0 :             ret = -ENOENT;
     160             :     }
     161             : 
     162           1 :     if (!ret)
     163           1 :         vr_vxlan_make_req(req, nh, req->vxlanr_vnid);
     164             :     else
     165           0 :         req = NULL;
     166             : 
     167           1 :     vr_message_response(VR_VXLAN_OBJECT_ID, req, ret, false);
     168             : 
     169           1 :     return 0;
     170             : }
     171             : 
     172             : static int
     173           2 : vr_vxlan_del(vr_vxlan_req *req)
     174             : {
     175             :     struct vrouter *router;
     176             :     struct vr_nexthop *nh;
     177           2 :     int ret = 0;
     178             : 
     179           2 :     router = vrouter_get(req->vxlanr_rid);
     180           2 :     if (!router) {
     181           0 :         ret = -EINVAL;
     182           0 :         goto generate_resp;
     183             :     }
     184             : 
     185             :     /* notify hw offload of change, if enabled */
     186           2 :     vr_offload_vxlan_del(req->vxlanr_vnid);
     187             : 
     188           2 :     nh = vr_itable_del(router->vr_vxlan_table, req->vxlanr_vnid);
     189           2 :     if (nh)
     190           2 :         vrouter_put_nexthop(nh);
     191             : 
     192           0 : generate_resp:
     193           2 :     vr_send_response(ret);
     194           2 :     return ret;
     195             : }
     196             : 
     197             : static int
     198           2 : vr_vxlan_add(vr_vxlan_req *req)
     199             : {
     200             :     struct vrouter *router;
     201             :     struct vr_nexthop *nh, *nh_old;
     202           2 :     int ret = 0;
     203             : 
     204           2 :     router = vrouter_get(req->vxlanr_rid);
     205           2 :     if (!router) {
     206           0 :         ret = -EINVAL;
     207           0 :         goto generate_resp;
     208             :     }
     209             : 
     210           2 :     nh = vrouter_get_nexthop(req->vxlanr_rid, req->vxlanr_nhid);
     211           2 :     if (!nh) {
     212           0 :         ret = -EINVAL;
     213           0 :         goto generate_resp;
     214             :     }
     215             : 
     216           2 :     nh_old = vr_itable_set(router->vr_vxlan_table, req->vxlanr_vnid, nh);
     217             : 
     218           2 :     ret = vr_offload_vxlan_add(nh, req->vxlanr_vnid);
     219           2 :     if (ret) {
     220             :         /* If offload add fails, restore old nexthop */
     221           0 :         if (nh_old && nh_old != VR_ITABLE_ERR_PTR)
     222           0 :             vr_itable_set(router->vr_vxlan_table, req->vxlanr_vnid, nh_old);
     223             :         else
     224           0 :             vr_itable_del(router->vr_vxlan_table, req->vxlanr_vnid);
     225           0 :         vrouter_put_nexthop(nh);
     226           0 :         goto generate_resp;
     227             :     }
     228             : 
     229           2 :     if (nh_old) {
     230           0 :         if (nh_old == VR_ITABLE_ERR_PTR) {
     231           0 :             ret = -EINVAL;
     232             :         } else {
     233             :             /* If there is any old nexthop, remove the reference */
     234           0 :             vrouter_put_nexthop(nh_old);
     235             :         }
     236             :     }
     237             : 
     238           2 : generate_resp:
     239           2 :     vr_send_response(ret);
     240           2 :     return ret;
     241             : }
     242             : 
     243             : void
     244           5 : vr_vxlan_req_process(void *s_req)
     245             : {
     246           5 :     vr_vxlan_req *req = (vr_vxlan_req *)s_req;
     247             : 
     248           5 :     switch(req->h_op) {
     249           2 :     case SANDESH_OP_ADD:
     250           2 :         vr_vxlan_add(req);
     251           2 :         break;
     252             : 
     253           1 :     case SANDESH_OP_GET:
     254           1 :         vr_vxlan_get(req);
     255           1 :         break;
     256             : 
     257           0 :     case SANDESH_OP_DUMP:
     258           0 :         vr_vxlan_dump(req);
     259           0 :         break;
     260             : 
     261           2 :     case SANDESH_OP_DEL:
     262           2 :         vr_vxlan_del(req);
     263           2 :         break;
     264             : 
     265           0 :     default:
     266           0 :         break;
     267             :     }
     268             : 
     269           5 :     return;
     270             : }
     271             : 
     272             : static void
     273           0 : vr_vxlan_destroy(unsigned int index, void *arg)
     274             : {
     275           0 :     struct vr_nexthop *nh = (struct vr_nexthop *)arg;
     276             : 
     277           0 :     if (nh && nh != VR_ITABLE_ERR_PTR) {
     278           0 :         vrouter_put_nexthop(nh);
     279             :     }
     280             : 
     281           0 :     return;
     282             : }
     283             : 
     284             : void
     285          53 : vr_vxlan_exit(struct vrouter *router, bool soft_reset)
     286             : {
     287             :     /* Delete the complete index table, irrespective of soft_reset */
     288          53 :     vr_itable_delete(router->vr_vxlan_table, vr_vxlan_destroy);
     289          53 :     router->vr_vxlan_table = NULL;
     290          53 : }
     291             : 
     292             : int
     293          53 : vr_vxlan_init(struct vrouter *router)
     294             : {
     295             :     /* Create an index table with two strides of 12 bits each */
     296          53 :     if (!router->vr_vxlan_table) {
     297          53 :         router->vr_vxlan_table = vr_itable_create(24, 2, 12, 12);
     298          53 :         if (!router->vr_vxlan_table) {
     299           0 :             vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0);
     300           0 :             return -ENOMEM;
     301             :         }
     302             :     }
     303          53 :     return 0;
     304             : }

Generated by: LCOV version 1.14