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

Generated by: LCOV version 1.14