LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_bridge.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 240 534 44.9 %
Date: 2026-11-09 02:10:49 Functions: 20 37 54.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : #include <vr_os.h>
       6             : #include <vr_packet.h>
       7             : #include "vr_interface.h"
       8             : #include "vr_message.h"
       9             : #include "vr_sandesh.h"
      10             : #include "vr_bridge.h"
      11             : #include "vr_htable.h"
      12             : #include "vr_nexthop.h"
      13             : #include "vr_datapath.h"
      14             : #include "vr_defs.h"
      15             : #include "vr_hash.h"
      16             : 
      17             : #if defined(__linux__) && defined(__KERNEL__)
      18             : extern short vr_bridge_table_major;
      19             : #endif
      20             : unsigned char *vr_bridge_table_path;
      21             : 
      22             : unsigned int vr_bridge_entries = VR_DEF_BRIDGE_ENTRIES;
      23             : unsigned int vr_bridge_oentries = 0;
      24             : static vr_htable_t vn_rtable;
      25             : char vr_bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
      26             : 
      27             : int bridge_table_init(struct vr_rtable *, struct rtable_fspec *);
      28             : void bridge_table_deinit(struct vr_rtable *, struct rtable_fspec *, bool);
      29             : struct vr_bridge_entry *vr_find_bridge_entry(struct vr_bridge_entry_key *);
      30             : struct vr_bridge_entry *vr_find_free_bridge_entry(unsigned int, char *);
      31             : extern struct vr_vrf_stats *(*vr_inet_vrf_stats)(unsigned short, unsigned int);
      32             : extern l4_pkt_type_t vr_ip_well_known_packet(struct vr_packet *);
      33             : extern l4_pkt_type_t vr_ip6_well_known_packet(struct vr_packet *);
      34             : extern int vr_bridge_get_mac_type(char *mac);
      35             : 
      36             : void *vr_bridge_table = NULL;
      37             : void *vr_obridge_table = NULL;
      38             : 
      39             : int
      40         110 : vr_bridge_get_mac_type(char *mac)
      41             : {
      42         110 :     int flags = 0;
      43         110 :     if (IS_MAC_BCAST(mac)) {
      44           0 :         flags |= MAC_BC_BIT_SET;
      45         110 :     } else if (IS_MAC_BMCAST(mac)) {
      46           0 :         flags |= MAC_MC_BIT_SET;
      47             :     } else {
      48         110 :         flags |= MAC_UC_BIT_SET;
      49             :     }
      50             : 
      51         110 :     return flags;
      52             : }
      53             : 
      54             : void *
      55           0 : vr_bridge_get_va(struct vrouter *router, uint64_t offset)
      56             : {
      57           0 :     return vr_htable_get_address(vn_rtable, offset);
      58             : }
      59             : 
      60             : /*
      61             :  * This api is called to get bridge table size
      62             :  * NOTE: This api is also called from agent (via sandesh)
      63             :  *       very early during init even before bridge table is
      64             :  *       initialized to calculate huge page table size.
      65             :  *       Hence this api should not use vr_htable structures
      66             :  */
      67             : unsigned int
      68           0 : vr_bridge_table_size(struct vrouter *router)
      69             : {
      70             :     // set the overflow table size
      71           0 :     vr_compute_size_bridge_otable();
      72           0 :     return (VR_BRIDGE_TABLE_SIZE + VR_BRIDGE_OFLOW_TABLE_SIZE);
      73             : }
      74             : 
      75             : static bool
      76           1 : vr_unknown_uc_flood(struct vr_interface *ingress_vif,
      77             :         struct vr_nexthop *ingress_nh)
      78             : {
      79           1 :     if (!ingress_vif)
      80           0 :         return false;
      81             : 
      82           1 :     if (vif_is_virtual(ingress_vif)) {
      83           1 :         return ((ingress_vif->vif_flags & VIF_FLAG_UNKNOWN_UC_FLOOD) != 0);
      84           0 :     } else if (vif_is_fabric(ingress_vif) && ingress_nh) {
      85           0 :         return ((ingress_nh->nh_flags & NH_FLAG_UNKNOWN_UC_FLOOD) != 0);
      86             :     }
      87             : 
      88           0 :     return false;
      89             : }
      90             : 
      91             : struct vr_bridge_entry *
      92         293 : vr_find_bridge_entry(struct vr_bridge_entry_key *key)
      93             : {
      94         293 :     if (!vn_rtable || !key)
      95           0 :         return NULL;
      96             : 
      97         293 :     return (struct vr_bridge_entry *)vr_htable_find_hentry(vn_rtable, key, 0);
      98             : }
      99             : 
     100             : struct vr_bridge_entry *
     101          86 : vr_find_free_bridge_entry(unsigned int vrf_id, char *mac)
     102             : {
     103             :     struct vr_bridge_entry *be;
     104             :     struct vr_bridge_entry_key key;
     105             : 
     106          86 :     if (!vn_rtable || !mac)
     107           0 :         return NULL;
     108             : 
     109          86 :     key.be_vrf_id = vrf_id;
     110          86 :     VR_MAC_COPY(key.be_mac, mac);
     111          86 :     be = (struct vr_bridge_entry *)vr_htable_find_free_hentry(vn_rtable,
     112             :                                                                 &key, 0);
     113          86 :     return be;
     114             : }
     115             : 
     116             : static struct vr_bridge_entry *
     117          91 : bridge_add(unsigned int router_id, unsigned int vrf,
     118             :         uint8_t *mac, int nh_id)
     119             : {
     120             :     struct vr_bridge_entry *be;
     121             :     struct vr_bridge_entry_key key;
     122             :     struct vr_nexthop *old_nh;
     123             : 
     124          91 :     VR_MAC_COPY(key.be_mac, mac);
     125          91 :     key.be_vrf_id = vrf;
     126          91 :     be = vr_find_bridge_entry(&key);
     127          91 :     if (!be) {
     128          86 :         be = vr_find_free_bridge_entry(vrf, mac);
     129          86 :         if (!be)
     130           0 :             return NULL;
     131             : 
     132          86 :         VR_MAC_COPY(be->be_key.be_mac, mac);
     133          86 :         be->be_key.be_vrf_id = vrf;
     134          86 :         be->be_packets = 0;
     135          86 :         be->be_flags = VR_BE_VALID_FLAG;
     136          86 :         be->be_nh_id = -1;
     137             :     }
     138             : 
     139             :     /* Un ref the old nexthop */
     140          91 :     if (be->be_nh_id != nh_id) {
     141          91 :         old_nh = be->be_nh;
     142          91 :         be->be_nh = vrouter_get_nexthop(router_id, nh_id);
     143          91 :         if (be->be_nh) {
     144          91 :             be->be_nh_id = be->be_nh->nh_id;
     145             :         } else {
     146           0 :             be->be_nh_id = -1;
     147             :         }
     148             : 
     149          91 :         if (be->be_flags & VR_BE_MAC_MOVED_FLAG) {
     150           0 :             be->be_flags &= ~VR_BE_MAC_MOVED_FLAG;
     151             :         }
     152             : 
     153          91 :         if (old_nh)
     154           5 :             vrouter_put_nexthop(old_nh);
     155             :     }
     156             : 
     157          91 :     return be;
     158             : }
     159             : 
     160             : static int
     161          91 : __bridge_table_add(struct vr_route_req *rt)
     162             : {
     163             :     int ret;
     164             :     unsigned short flags, i;
     165             : 
     166             :     struct vr_bridge_entry *be;
     167             : 
     168          91 :     be = bridge_add(rt->rtr_req.rtr_rid, rt->rtr_req.rtr_vrf_id,
     169          91 :             rt->rtr_req.rtr_mac, rt->rtr_req.rtr_nh_id);
     170          91 :     if (!be)
     171           0 :         return -ENOMEM;
     172             : 
     173          91 :     rt->rtr_req.rtr_label_flags =
     174          91 :         VR_BRIDGE_FLAG_MASK(rt->rtr_req.rtr_label_flags);
     175             : 
     176          91 :     if (rt->rtr_req.rtr_label_flags & VR_BE_LABEL_VALID_FLAG)
     177          37 :         be->be_label = rt->rtr_req.rtr_label;
     178             : 
     179             :     /*
     180             :      * attempt the change for some number of times, if the set
     181             :      * turns out to be contested
     182             :      */
     183          91 :     ret = -EAGAIN;
     184          91 :     for (i = 0; i < 10; i++) {
     185          91 :         flags = be->be_flags;
     186          91 :         if (vr_sync_bool_compare_and_swap_16u(&be->be_flags, flags,
     187             :                 VR_BE_VALID_FLAG | rt->rtr_req.rtr_label_flags)) {
     188          91 :             ret = 0;
     189          91 :             break;
     190             :         }
     191             :     }
     192             : 
     193          91 :     rt->rtr_req.rtr_index = be->be_hentry.hentry_index;
     194             : 
     195          91 :     return ret;
     196             : }
     197             : 
     198             : static int
     199          92 : bridge_table_add(struct vr_rtable * _unused, struct vr_route_req *rt)
     200             : {
     201             :     int ret;
     202             : 
     203          92 :     if (!vn_rtable)
     204           0 :         return -EINVAL;
     205             : 
     206          92 :     if (rt->rtr_req.rtr_mac_size != VR_ETHER_ALEN)
     207           0 :         return -EINVAL;
     208             : 
     209          92 :     if (IS_MAC_ZERO(rt->rtr_req.rtr_mac))
     210           0 :         return -EINVAL;
     211             : 
     212         184 :     rt->rtr_nh = vrouter_get_nexthop(rt->rtr_req.rtr_rid,
     213          92 :             rt->rtr_req.rtr_nh_id);
     214          92 :     if (!rt->rtr_nh)
     215           1 :         return -ENOENT;
     216             : 
     217          91 :     ret = __bridge_table_add(rt);
     218          91 :     vrouter_put_nexthop(rt->rtr_nh);
     219          91 :     return ret;
     220             : }
     221             : 
     222             : static void
     223    16715861 : bridge_table_entry_free(vr_htable_t table, vr_hentry_t *hentry,
     224             :         unsigned int index, void *data)
     225             : {
     226             :     struct vr_nexthop *nh;
     227    16715861 :     struct vr_bridge_entry *be = (struct vr_bridge_entry *)hentry;
     228             : 
     229    16715861 :     if (!be)
     230           0 :         return;
     231             : 
     232             :     /* Mark this entry as invalid */
     233    16715861 :     be->be_flags &= ~VR_BE_VALID_FLAG;
     234             : 
     235    16715861 :     if (be->be_nh) {
     236          86 :         nh = be->be_nh;
     237          86 :         be->be_nh = NULL;
     238          86 :         be->be_nh_id = -1;
     239          86 :         vrouter_put_nexthop(nh);
     240             :     }
     241             : 
     242    16715861 :     be->be_packets = 0;
     243    16715861 :     vr_htable_release_hentry(table, hentry);
     244             : 
     245    16715861 :     return;
     246             : }
     247             : 
     248             : static int
     249          87 : bridge_table_delete(struct vr_rtable * _unused, struct vr_route_req *rt)
     250             : {
     251             :     struct vr_bridge_entry_key key;
     252             :     struct vr_bridge_entry *be;
     253             : 
     254          87 :     if (!vn_rtable)
     255           0 :         return -EINVAL;
     256             : 
     257          87 :     if (rt->rtr_req.rtr_mac_size != VR_ETHER_ALEN)
     258           0 :         return -EINVAL;
     259             : 
     260          87 :     VR_MAC_COPY(key.be_mac, rt->rtr_req.rtr_mac);
     261          87 :     key.be_vrf_id = rt->rtr_req.rtr_vrf_id;
     262             : 
     263          87 :     be = vr_find_bridge_entry(&key);
     264          87 :     if (!be)
     265           2 :         return -ENOENT;
     266             : 
     267          85 :     bridge_table_entry_free(vn_rtable, (vr_hentry_t *)be, 0, NULL);
     268          85 :     return 0;
     269             : }
     270             : 
     271             : static void
     272           9 : bridge_update_route_req(struct vr_bridge_entry *be, struct vr_route_req *rt)
     273             : {
     274           9 :     rt->rtr_req.rtr_label_flags = be->be_flags;
     275           9 :     rt->rtr_req.rtr_label = be->be_label;
     276           9 :     rt->rtr_nh = be->be_nh;
     277           9 :     if (rt->rtr_nh)
     278           9 :         rt->rtr_req.rtr_nh_id = rt->rtr_nh->nh_id;
     279           9 :     if (rt->rtr_req.rtr_index != VR_BE_INVALID_INDEX) {
     280           4 :         if (rt->rtr_req.rtr_mac) {
     281           4 :             VR_MAC_COPY(rt->rtr_req.rtr_mac, be->be_key.be_mac);
     282             :         }
     283             :     } else {
     284           5 :         rt->rtr_req.rtr_index = be->be_hentry.hentry_index;
     285             :     }
     286             : 
     287           9 :     return;
     288             : }
     289             : 
     290             : static struct vr_bridge_entry *
     291         125 : __bridge_lookup(unsigned int vrf_id, struct vr_route_req *rt)
     292             : {
     293             :     struct vr_bridge_entry *be;
     294             :     struct vr_bridge_entry_key key;
     295             : 
     296         125 :     rt->rtr_req.rtr_label_flags = 0;
     297         125 :     rt->rtr_nh = NULL;
     298             : 
     299         125 :     if (rt->rtr_req.rtr_index != VR_BE_INVALID_INDEX) {
     300             :         be = (struct vr_bridge_entry *)
     301          10 :              vr_htable_get_hentry_by_index(vn_rtable, rt->rtr_req.rtr_index);
     302             :     } else {
     303         115 :         VR_MAC_COPY(key.be_mac, rt->rtr_req.rtr_mac);
     304         115 :         key.be_vrf_id = rt->rtr_req.rtr_vrf_id;
     305         115 :         be = vr_find_bridge_entry(&key);
     306             :     }
     307             : 
     308         125 :     return be;
     309             : }
     310             : 
     311             : 
     312             : static struct vr_nexthop *
     313          16 : bridge_table_lookup(unsigned int vrf_id, struct vr_route_req *rt)
     314             : {
     315             :     struct vr_bridge_entry *be;
     316             : 
     317          16 :     be = __bridge_lookup(vrf_id, rt);
     318          16 :     if (be)
     319           9 :         bridge_update_route_req(be, rt);
     320             : 
     321          16 :     return rt->rtr_nh;
     322             : }
     323             : 
     324             : struct vr_nexthop *
     325          16 : vr_bridge_lookup(unsigned int vrf_id, struct vr_route_req *rt)
     326             : {
     327          16 :     if (!vn_rtable)
     328           0 :         return NULL;
     329             : 
     330          16 :     return bridge_table_lookup(vrf_id, rt);
     331             : }
     332             : 
     333             : static struct vr_bridge_entry *
     334         109 : bridge_lookup(uint8_t *mac, struct vr_forwarding_md *fmd)
     335             : {
     336             :     struct vr_route_req rt;
     337             :     struct vr_bridge_entry *be;
     338             : 
     339         109 :     rt.rtr_req.rtr_label_flags = 0;
     340         109 :     rt.rtr_req.rtr_index = VR_BE_INVALID_INDEX;
     341         109 :     rt.rtr_req.rtr_mac_size = VR_ETHER_ALEN;
     342         109 :     rt.rtr_req.rtr_mac = mac;
     343         109 :     rt.rtr_req.rtr_vrf_id = fmd->fmd_dvrf;
     344         109 :     be = __bridge_lookup(rt.rtr_req.rtr_vrf_id, &rt);
     345             : 
     346         109 :     if (be && fmd) {
     347         108 :         if (be->be_flags & VR_BE_LABEL_VALID_FLAG)
     348          64 :             vr_fmd_set_label(fmd, be->be_label, VR_LABEL_TYPE_UNKNOWN);
     349         108 :         if (be->be_flags & VR_BE_L2_CONTROL_DATA_FLAG)
     350           0 :             vr_fmd_update_l2_control_data(fmd, true);
     351             :     }
     352             : 
     353         109 :     return be;
     354             : }
     355             : 
     356             : struct vr_nexthop *
     357           2 : __vrouter_bridge_lookup(unsigned int vrf_id, unsigned char *mac)
     358             : {
     359             :     struct vr_route_req rt;
     360             : 
     361           2 :     if (!mac)
     362           0 :         return NULL;
     363             : 
     364           2 :     rt.rtr_req.rtr_label_flags = 0;
     365           2 :     rt.rtr_req.rtr_index = VR_BE_INVALID_INDEX;
     366           2 :     rt.rtr_req.rtr_mac_size = VR_ETHER_ALEN;
     367           2 :     rt.rtr_req.rtr_mac = mac;
     368             :     /* If multicast L2 packet, use broadcast composite nexthop */
     369           2 :     if (IS_MAC_BMCAST(rt.rtr_req.rtr_mac))
     370           0 :         rt.rtr_req.rtr_mac = (int8_t *)vr_bcast_mac;
     371           2 :    rt.rtr_req.rtr_vrf_id = vrf_id;
     372             : 
     373           2 :     return vr_bridge_lookup(vrf_id,  &rt);
     374             : }
     375             : 
     376             : 
     377             : unsigned short
     378           0 : vr_bridge_route_flags(unsigned int vrf_id, unsigned char *mac)
     379             : {
     380             :     struct vr_bridge_entry *be;
     381             :     struct vr_bridge_entry_key key;
     382             : 
     383           0 :     VR_MAC_COPY(key.be_mac, mac);
     384           0 :     key.be_vrf_id = vrf_id;
     385             : 
     386           0 :     be = vr_find_bridge_entry(&key);
     387           0 :     if (be && (be->be_flags & VR_BE_VALID_FLAG))
     388           0 :         return be->be_flags;
     389             : 
     390           0 :     return 0;
     391             : }
     392             : 
     393             : static int
     394           0 : vr_bridge_set_route_flags(struct vr_bridge_entry *be, unsigned short flags)
     395             : {
     396             :     unsigned short be_flags, be_flags_old;
     397             : 
     398           0 :     if (be) {
     399           0 :         be_flags = be_flags_old = be->be_flags;
     400           0 :         if (be_flags & VR_BE_VALID_FLAG) {
     401           0 :             if ((be_flags & flags) == flags)
     402           0 :                 return -EEXIST;
     403             : 
     404           0 :             flags = VR_BRIDGE_FLAG_MASK(flags);
     405           0 :             be_flags = vr_sync_val_compare_and_swap_16u(&be->be_flags, be_flags,
     406             :                     flags | be_flags);
     407             : 
     408           0 :             if ((be_flags & flags) == flags)
     409           0 :                 return -EEXIST;
     410             : 
     411           0 :             if (be_flags == be_flags_old)
     412           0 :                 return 0;
     413             :         }
     414             :     }
     415             : 
     416           0 :     return -EINVAL;
     417             : }
     418             : 
     419             : unsigned int
     420           0 : vr_bridge_table_used_total_entries(struct vrouter *router)
     421             : {
     422           0 :     if (vn_rtable)
     423           0 :         return vr_htable_used_total_entries(vn_rtable);
     424             : 
     425           0 :     return 0;
     426             : }
     427             : 
     428             : unsigned int
     429           0 : vr_bridge_table_used_oflow_entries(struct vrouter *router)
     430             : {
     431           0 :     if (vn_rtable)
     432           0 :         return vr_htable_used_oflow_entries(vn_rtable);
     433           0 :     return 0;
     434             : }
     435             : 
     436             : static int
     437           0 : bridge_table_get(unsigned int vrf_id, struct vr_route_req *rt)
     438             : {
     439             :     struct vr_nexthop *nh;
     440             : 
     441           0 :     nh = bridge_table_lookup(vrf_id, rt);
     442           0 :     if (nh)
     443           0 :         return 0;
     444             : 
     445           0 :     return -ENOENT;
     446             : }
     447             : 
     448             : static int
     449           0 : bridge_entry_make_req(struct vr_route_req *resp, struct vr_bridge_entry *ent)
     450             : {
     451           0 :     memset(resp, 0, sizeof(struct vr_route_req));
     452           0 :     resp->rtr_req.rtr_mac_size = VR_ETHER_ALEN;
     453           0 :     resp->rtr_req.rtr_mac = vr_zalloc(VR_ETHER_ALEN, VR_ROUTE_REQ_MAC_OBJECT);
     454           0 :     if (!resp->rtr_req.rtr_mac)
     455           0 :         return -ENOMEM;
     456           0 :     VR_MAC_COPY(resp->rtr_req.rtr_mac, ent->be_key.be_mac);
     457           0 :     resp->rtr_req.rtr_vrf_id = ent->be_key.be_vrf_id;
     458           0 :     if (ent->be_nh)
     459           0 :         resp->rtr_req.rtr_nh_id = ent->be_nh->nh_id;
     460           0 :     resp->rtr_req.rtr_family = AF_BRIDGE;
     461           0 :     resp->rtr_req.rtr_label = ent->be_label;
     462           0 :     resp->rtr_req.rtr_label_flags = ent->be_flags;
     463           0 :     resp->rtr_req.rtr_index = ent->be_hentry.hentry_index;
     464             : 
     465           0 :     return 0;
     466             : }
     467             : 
     468             : static void
     469           0 : bridge_entry_req_destroy(struct vr_route_req *resp)
     470             : {
     471           0 :     if (resp->rtr_req.rtr_mac)
     472           0 :         vr_free(resp->rtr_req.rtr_mac, VR_ROUTE_REQ_MAC_OBJECT);
     473           0 : }
     474             : 
     475             : static int
     476           0 : __bridge_table_dump(struct vr_message_dumper *dumper)
     477             : {
     478           0 :     struct vr_route_req *req = (struct vr_route_req *)(dumper->dump_req);
     479             :     struct vr_route_req resp;
     480             :     int ret;
     481             :     unsigned int i;
     482             :     struct vr_bridge_entry *be;
     483             : 
     484           0 :     for(i = 0; i < (vr_bridge_entries + vr_bridge_oentries); i++) {
     485             :         be = (struct vr_bridge_entry *)
     486           0 :                 vr_htable_get_hentry_by_index(vn_rtable, i);
     487           0 :         if (!be)
     488           0 :             continue;
     489           0 :         if (be->be_flags & VR_BE_VALID_FLAG) {
     490           0 :             if (be->be_key.be_vrf_id != req->rtr_req.rtr_vrf_id)
     491           0 :                 continue;
     492           0 :             if (dumper->dump_been_to_marker == 0) {
     493           0 :                 if (VR_MAC_CMP(be->be_key.be_mac, req->rtr_req.rtr_mac)
     494           0 :                         && (be->be_key.be_vrf_id == req->rtr_req.rtr_vrf_id)) {
     495           0 :                     dumper->dump_been_to_marker = 1;
     496             :                 }
     497             :             } else {
     498           0 :                 if (!bridge_entry_make_req(&resp, be)) {
     499           0 :                     ret = vr_message_dump_object(dumper, VR_ROUTE_OBJECT_ID, &resp);
     500           0 :                     bridge_entry_req_destroy(&resp);
     501           0 :                     if (ret <= 0) {
     502           0 :                         return ret;
     503             :                     }
     504             :                 }
     505             :             }
     506             :         }
     507             :     }
     508             : 
     509           0 :     return 0;
     510             : }
     511             : 
     512             : static int
     513           0 : bridge_table_dump(struct vr_rtable * __unsued, struct vr_route_req *rt)
     514             : {
     515           0 :     int ret = 0;
     516             :     struct vr_message_dumper *dumper;
     517             :     char *mac;
     518             : 
     519           0 :     if (rt->rtr_req.rtr_mac_size != VR_ETHER_ALEN)
     520           0 :         return -EINVAL;
     521             : 
     522           0 :     dumper = vr_message_dump_init(&rt->rtr_req);
     523           0 :     if (!dumper) {
     524           0 :         ret = -ENOMEM;
     525           0 :         goto generate_response;
     526             :     }
     527             : 
     528             : 
     529           0 :     mac = (char *)(((vr_route_req *)(dumper->dump_req))->rtr_mac);
     530           0 :     if (!mac) {
     531           0 :         ret = -EINVAL;
     532           0 :         goto generate_response;
     533             :     }
     534             : 
     535           0 :     if (IS_MAC_ZERO(mac))
     536           0 :         dumper->dump_been_to_marker = 1;
     537             : 
     538           0 :     ret = __bridge_table_dump(dumper);
     539             : 
     540           0 : generate_response:
     541           0 :     vr_message_dump_exit(dumper, ret);
     542             : 
     543           0 :     return 0;
     544             : }
     545             : 
     546             : static vr_hentry_key
     547         203 : bridge_entry_key(vr_htable_t table, vr_hentry_t *entry, unsigned int
     548             :         *key_len)
     549             : {
     550         203 :     struct vr_bridge_entry *be = CONTAINER_OF(be_hentry,
     551             :                         struct vr_bridge_entry, entry);
     552             : 
     553         203 :     if (!entry || (!(be->be_flags & VR_BE_VALID_FLAG)))
     554           0 :         return NULL;
     555             : 
     556         203 :     if (key_len)
     557         203 :         *key_len = sizeof(be->be_key);
     558             : 
     559         203 :     return &be->be_key;
     560             : }
     561             : 
     562             : static void
     563           0 : vr_bridge_table_data_destroy(vr_bridge_table_data *data)
     564             : {
     565           0 :     if (data) {
     566           0 :         if (data->btable_file_path) {
     567           0 :             vr_free(data->btable_file_path, VR_BRIDGE_TABLE_DATA_OBJECT);
     568           0 :             data->btable_file_path = NULL;
     569             :         }
     570           0 :         vr_free(data, VR_BRIDGE_TABLE_DATA_OBJECT);
     571             :     }
     572             : 
     573           0 :     return;
     574             : }
     575             : 
     576             : static vr_bridge_table_data *
     577           0 : vr_bridge_table_data_get(void)
     578             : {
     579           0 :     vr_bridge_table_data *data = vr_zalloc(sizeof(vr_bridge_table_data),
     580             :                 VR_BRIDGE_TABLE_DATA_OBJECT);
     581           0 :     if (!data)
     582           0 :         return NULL;
     583             : 
     584           0 :     if (vr_bridge_table_path) {
     585           0 :         data->btable_file_path = vr_zalloc(VR_UNIX_PATH_MAX,
     586             :                 VR_BRIDGE_TABLE_DATA_OBJECT);
     587           0 :         if (!data->btable_file_path) {
     588           0 :             goto exit_func;
     589             :         }
     590             :     }
     591             : 
     592           0 :     return data;
     593             : 
     594           0 : exit_func:
     595           0 :     vr_bridge_table_data_destroy(data);
     596           0 :     return NULL;
     597             : }
     598             : 
     599             : 
     600             : void
     601           0 : vr_bridge_table_data_process(void *s_req)
     602             : {
     603           0 :     int ret = 0;
     604             :     struct vrouter *router;
     605           0 :     vr_bridge_table_data *resp = NULL, *req = (vr_bridge_table_data *)s_req;
     606             : 
     607           0 :     router = vrouter_get(req->btable_rid);
     608           0 :     if (!router) {
     609           0 :         ret = -EINVAL;
     610           0 :         goto generate_response;
     611             :     }
     612             : 
     613           0 :     resp = vr_bridge_table_data_get();
     614           0 :     if (!resp) {
     615           0 :         ret = -ENOMEM;
     616           0 :         goto generate_response;
     617             :     }
     618             : 
     619           0 :     resp->btable_op = req->btable_op;
     620           0 :     switch (req->btable_op) {
     621           0 :     case SANDESH_OP_GET:
     622           0 :         resp->btable_size = vr_bridge_table_size(router);
     623             : #if defined(__linux__) && defined(__KERNEL__)
     624             :         resp->btable_dev = vr_bridge_table_major;
     625             : #endif
     626           0 :         if (vr_bridge_table_path) {
     627           0 :             strncpy(resp->btable_file_path, vr_bridge_table_path,
     628             :                     VR_UNIX_PATH_MAX - 1);
     629             :         }
     630           0 :         break;
     631             : 
     632           0 :     default:
     633           0 :         ret = -EINVAL;
     634           0 :         break;
     635             :     }
     636             : 
     637           0 : generate_response:
     638           0 :     vr_message_response(VR_BRIDGE_TABLE_DATA_OBJECT_ID, resp, ret, false);
     639           0 :     if (resp) {
     640           0 :         vr_bridge_table_data_destroy(resp);
     641           0 :         resp = NULL;
     642             :     }
     643             : 
     644           0 :     return;
     645             : }
     646             : 
     647             : int
     648          53 : bridge_table_init(struct vr_rtable *rtable, struct rtable_fspec *fs)
     649             : {
     650             : 
     651             :     /* If table already exists, dont create again */
     652          53 :     if (rtable->algo_data)
     653           0 :         return 0;
     654             : 
     655          53 :     vr_compute_size_bridge_otable();
     656             : 
     657          53 :     if (!vr_bridge_table && vr_huge_page_mem_get) {
     658           0 :         vr_bridge_table = vr_huge_page_mem_get((VR_BRIDGE_TABLE_SIZE +
     659             :                            VR_BRIDGE_OFLOW_TABLE_SIZE), &vr_bridge_table_path);
     660           0 :         if (vr_bridge_table)
     661           0 :             vr_obridge_table = (unsigned char *)vr_bridge_table + VR_BRIDGE_TABLE_SIZE;
     662             :     }
     663             : 
     664          53 :     rtable->algo_data = vr_htable_attach(vrouter_get(0), vr_bridge_entries,
     665             :                 vr_bridge_table, vr_bridge_oentries, vr_obridge_table,
     666             :                 sizeof(struct vr_bridge_entry),
     667             :                 sizeof(struct vr_bridge_entry_key), 0, bridge_entry_key);
     668             : 
     669          53 :     if (!rtable->algo_data)
     670           0 :         return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__,
     671             :                 vr_bridge_entries);
     672             : 
     673             :     /* Max VRF's does not matter as Bridge table is not per VRF. But
     674             :      * still this can be maintained in table
     675             :      */
     676          53 :     rtable->algo_max_vrfs = fs->rtb_max_vrfs;
     677          53 :     rtable->algo_add = bridge_table_add;
     678          53 :     rtable->algo_del = bridge_table_delete;
     679          53 :     rtable->algo_lookup = bridge_table_lookup;
     680          53 :     rtable->algo_get = bridge_table_get;
     681          53 :     rtable->algo_dump = bridge_table_dump;
     682             : 
     683          53 :     vn_rtable = rtable->algo_data;
     684             : 
     685          53 :     return 0;
     686             : }
     687             : 
     688             : void
     689          53 : bridge_table_deinit(struct vr_rtable *rtable, struct rtable_fspec *fs,
     690             :         bool soft_reset)
     691             : {
     692          53 :     if (!vn_rtable)
     693           0 :         return;
     694             : 
     695          53 :     vr_htable_reset(vn_rtable, bridge_table_entry_free, NULL);
     696             : 
     697          53 :     if (!soft_reset) {
     698          53 :         vr_htable_delete(vn_rtable);
     699          53 :         rtable->algo_data = NULL;
     700          53 :         vn_rtable = NULL;
     701             :     }
     702             : 
     703             : }
     704             : 
     705             : static void
     706           0 : bridge_table_unlock(struct vr_interface *vif, uint8_t *mac, int cpu)
     707             : {
     708           0 :     uint8_t *bridge_table_lock = vif->vif_bridge_table_lock;
     709             : 
     710           0 :     if (cpu < 0 || !bridge_table_lock)
     711           0 :         return;
     712             : 
     713           0 :     bridge_table_lock[cpu] = 0;
     714             : 
     715           0 :     return;
     716             : }
     717             : 
     718             : static int
     719           0 : bridge_table_lock(struct vr_interface *vif, uint8_t *mac)
     720             : {
     721           0 :     uint8_t lock = 1, *bridge_table_lock = vif->vif_bridge_table_lock;
     722             :     uint32_t hash;
     723             :     uint64_t t1s, t1ns, t2s, t2ns, diff;
     724             : 
     725           0 :     if (!bridge_table_lock)
     726           0 :         return -EINVAL;
     727             : 
     728           0 :     hash = vr_hash(mac, VR_ETHER_ALEN, 0);
     729           0 :     hash %= vr_num_cpus;
     730             : 
     731           0 :     vr_get_mono_time(&t1s, &t1ns);
     732           0 :     while (lock) {
     733           0 :         lock = vr_sync_lock_test_and_set_8u(&bridge_table_lock[hash], lock);
     734           0 :         if (lock) {
     735           0 :             vr_get_mono_time(&t2s, &t2ns);
     736           0 :             if (t2ns >= t1ns) {
     737           0 :                 diff = t2ns - t1ns;
     738             :             } else {
     739           0 :                 diff = 999999999 - t1ns + t2ns;
     740             :             }
     741             : 
     742           0 :             if (diff >= 50000) {
     743           0 :                 return -EINVAL;
     744             :             }
     745             :         }
     746             :     }
     747             : 
     748           0 :     return hash;
     749             : }
     750             : 
     751             : mac_learn_t
     752           0 : vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt,
     753             :         struct vr_eth *eth, struct vr_forwarding_md *fmd)
     754             : {
     755             :     int lock, valid_src;
     756             :     unsigned int trap_reason;
     757           0 :     bool trap = false, root = false;
     758           0 :     mac_learn_t ml_res = MAC_EXISTS;
     759             :     struct vr_packet *pkt_c;
     760           0 :     struct vr_nexthop *nh = NULL;
     761             :     struct vr_bridge_entry *be;
     762             : 
     763           0 :     if (!eth)
     764           0 :         return MAC_LEARN_FAILURE;
     765             : 
     766           0 :     if (IS_MAC_BMCAST(eth->eth_smac))
     767           0 :         return MAC_LEARN_FAILURE;
     768             : 
     769           0 :     vr_fmd_update_etree(fmd, true);
     770           0 :     if (vif_is_virtual(pkt->vp_if)) {
     771           0 :         if (pkt->vp_if->vif_flags & VIF_FLAG_ETREE_ROOT)
     772           0 :             root = true;
     773           0 :         vr_fmd_update_etree_root(fmd, root);
     774             :     }
     775             : 
     776           0 :     be = bridge_lookup(eth->eth_smac, fmd);
     777           0 :     if (be) {
     778           0 :         nh = be->be_nh;
     779             :     }
     780             : 
     781           0 :     if (!nh) {
     782           0 :         be = bridge_lookup((uint8_t *)vr_bcast_mac, fmd);
     783           0 :         if (be) {
     784           0 :             nh = be->be_nh;
     785             :         }
     786             : 
     787           0 :         if (!nh)
     788           0 :             return MAC_LEARN_FAILURE;
     789             : 
     790           0 :         lock = bridge_table_lock(pkt->vp_if, eth->eth_smac);
     791           0 :         if (lock < 0)
     792           0 :             return MAC_LEARN_FAILURE;
     793             : 
     794           0 :         be = bridge_add(0, fmd->fmd_dvrf, eth->eth_smac, nh->nh_id);
     795           0 :         if (be)
     796           0 :             be->be_flags |= VR_BE_MAC_NEW_FLAG;
     797           0 :         bridge_table_unlock(pkt->vp_if, eth->eth_smac, lock);
     798           0 :         if (!be)
     799           0 :             return MAC_LEARN_FAILURE;
     800             : 
     801           0 :         trap_reason = AGENT_TRAP_MAC_LEARN;
     802           0 :         trap = true;
     803           0 :         ml_res = MAC_LEARNT;
     804             :     } else {
     805           0 :         if (!(be->be_flags & VR_BE_MAC_MOVED_FLAG) && (nh->nh_validate_src)) {
     806           0 :             valid_src = nh->nh_validate_src(pkt, nh, fmd, NULL);
     807           0 :             if (valid_src != NH_SOURCE_VALID) {
     808           0 :                 if (!vr_bridge_set_route_flags(be, VR_BE_MAC_MOVED_FLAG)) {
     809             :                     /* trap the packet for mac move */
     810           0 :                     trap_reason = AGENT_TRAP_MAC_MOVE;
     811           0 :                     trap = true;
     812             :                 }
     813             :             }
     814             :         }
     815           0 :         if (be->be_flags & VR_BE_MAC_MOVED_FLAG)
     816           0 :             ml_res = MAC_MOVED;
     817             :     }
     818             : 
     819           0 :     vr_sync_fetch_and_add_64u(&be->be_packets, 1);
     820             : 
     821           0 :     if (trap) {
     822           0 :         pkt_c = pkt_cow(pkt, 0);
     823           0 :         if (!pkt_c) {
     824           0 :             pkt_c = pkt;
     825           0 :             ml_res = MAC_TRAPPED;
     826             :         }
     827             : 
     828           0 :         vr_trap(pkt_c, fmd->fmd_dvrf,
     829           0 :                 trap_reason, (void *)&be->be_hentry.hentry_index);
     830             :     }
     831             : 
     832             : 
     833           0 :     return ml_res;
     834             : }
     835             : 
     836             : unsigned int
     837         110 : vr_bridge_input(struct vrouter *router, struct vr_packet *pkt,
     838             :                 struct vr_forwarding_md *fmd)
     839             : {
     840             :     int reason, handled;
     841         110 :     l4_pkt_type_t l4_type = L4_TYPE_UNKNOWN;
     842         110 :     unsigned short pull_len, overlay_len = VROUTER_OVERLAY_LEN;
     843             :     int8_t *dmac;
     844             :     int8_t *lookup_mac;
     845             :     mac_learn_t ml_res;
     846             :     struct vr_bridge_entry *be;
     847         110 :     struct vr_nexthop *nh = NULL;
     848         110 :     struct vr_vrf_stats *stats = NULL;
     849             :     int mac_flags;
     850             : 
     851         110 :     if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6)) {
     852         106 :         if (fmd->fmd_dscp < 0) {
     853         101 :             if (pkt->vp_type == VP_TYPE_IP) {
     854          93 :                 fmd->fmd_dscp =
     855          93 :                     vr_inet_get_tos((struct vr_ip *)pkt_network_header(pkt));
     856           8 :             } else if (pkt->vp_type == VP_TYPE_IP6) {
     857           8 :                 fmd->fmd_dscp =
     858           8 :                     vr_inet6_get_tos((struct vr_ip6 *)pkt_network_header(pkt));
     859             :             }
     860             :         }
     861             :     } else {
     862           4 :         if (fmd->fmd_dotonep < 0) {
     863           4 :             fmd->fmd_dotonep = vr_vlan_get_tos(pkt_data(pkt));
     864             :         }
     865             :     }
     866             : 
     867         110 :     if (!fmd->fmd_to_me) {
     868         110 :         if ((pkt->vp_if->vif_flags & VIF_FLAG_MAC_LEARN) ||
     869         110 :                 (pkt->vp_nh && (pkt->vp_nh->nh_flags & NH_FLAG_MAC_LEARN))) {
     870           0 :             ml_res = vr_bridge_learn(router, pkt,
     871           0 :                     (struct vr_eth *)pkt_data(pkt), fmd);
     872           0 :             if (ml_res == MAC_TRAPPED)
     873           0 :                 return 0;
     874             :         }
     875             :     }
     876             : 
     877         110 :     dmac = (int8_t *) pkt_data(pkt);
     878         110 :     mac_flags = vr_bridge_get_mac_type((char *)dmac);
     879         110 :     pull_len = 0;
     880         110 :     if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6) ||
     881           4 :             (pkt->vp_type == VP_TYPE_ARP)) {
     882         110 :         pull_len = pkt_get_network_header_off(pkt) - pkt_head_space(pkt);
     883         110 :         if (pull_len && !pkt_pull(pkt, pull_len)) {
     884           0 :             PKT_LOG(VP_DROP_PULL, pkt, 0, VR_BRIDGE_C, __LINE__);
     885           0 :             vr_pfree(pkt, VP_DROP_PULL);
     886           0 :             return 0;
     887             :         }
     888             :     }
     889             : 
     890             :     /* Do the bridge lookup for the packets not meant for "me" */
     891         110 :     if (!fmd->fmd_to_me) {
     892             :         /*
     893             :          * If DHCP packet coming from VM, Trap it to Agent before doing the bridge
     894             :          * lookup itself
     895             :          */
     896         110 :         if (vif_is_virtual(pkt->vp_if)) {
     897             : 
     898         108 :             if (pkt->vp_type == VP_TYPE_IP)
     899          97 :                 l4_type = vr_ip_well_known_packet(pkt);
     900          11 :             else if (pkt->vp_type == VP_TYPE_IP6)
     901           7 :                 l4_type = vr_ip6_well_known_packet(pkt);
     902             : 
     903         108 :             if (l4_type == L4_TYPE_DHCP_REQUEST) {
     904           0 :                 if (pkt->vp_if->vif_flags & VIF_FLAG_DHCP_ENABLED) {
     905           0 :                     vr_trap(pkt, fmd->fmd_dvrf,  AGENT_TRAP_L3_PROTOCOLS, NULL);
     906           0 :                     return 0;
     907             :                 }
     908             :             }
     909             : 
     910         108 :             if (l4_type == L4_TYPE_IGMP) {
     911           0 :                 if (pkt->vp_if->vif_flags & VIF_FLAG_IGMP_ENABLED) {
     912           0 :                     vr_trap(pkt, fmd->fmd_dvrf,  AGENT_TRAP_L3_PROTOCOLS, NULL);
     913           0 :                     return 0;
     914             :                 }
     915             :             }
     916             : 
     917             :             /*
     918             :              * Handle the unicast ARP, coming from VM, not
     919             :              * destined to us. Broadcast ARP requests would be handled
     920             :              * in L2 multicast nexthop. Multicast ARP on fabric
     921             :              * interface also would be handled in L2 multicast nexthop.
     922             :              * Unicast ARP packets on fabric interface would be handled
     923             :              * in plug routines of interface.
     924             :              */
     925         108 :             if (!(mac_flags & MAC_BMC_BIT_SET) ||
     926           0 :                     (pkt->vp_if->vif_flags & VIF_FLAG_MAC_PROXY)) {
     927         108 :                 handled = 0;
     928         108 :                 if (pkt->vp_type == VP_TYPE_ARP) {
     929           4 :                     handled = vr_arp_input(pkt, fmd, dmac);
     930           4 :                     if (VR_RX_HANDLER_PASS == handled)
     931           0 :                         return handled;
     932         104 :                 } else if (l4_type == L4_TYPE_NEIGHBOUR_SOLICITATION) {
     933           0 :                     handled = vr_neighbor_input(pkt, fmd, dmac);
     934             :                 }
     935             : 
     936         108 :                 if (handled)
     937           1 :                     return 0;
     938             :             }
     939             :         }
     940             : 
     941         109 :         if ((mac_flags & MAC_BMC_BIT_SET) &&
     942           0 :             (pkt->vp_if->vif_mcast_vrf != 65535)) {
     943             : 
     944           0 :             fmd->fmd_dvrf = pkt->vp_if->vif_mcast_vrf;
     945             :         }
     946             : 
     947         109 :         be = NULL;
     948         109 :         lookup_mac = dmac;
     949         109 :         if (mac_flags & MAC_UC_BIT_SET) {
     950         109 :             be = bridge_lookup(lookup_mac, fmd);
     951             :         } else {
     952           0 :             if (pkt->vp_type == VP_TYPE_IP) {
     953           0 :                 if (!(pkt->vp_if->vif_flags & VIF_FLAG_IGMP_ENABLED)) {
     954           0 :                     if (!vif_is_fabric(pkt->vp_if) && vif_is_tap(pkt->vp_if)) {
     955             :                         /*
     956             :                          * - Comes here for VxLAN tunnel based multicast data.
     957             :                          * For this, IGMP is always disabled on fabric vif.
     958             :                          *
     959             :                          * - Packets originating from VM with IGMP disabled.
     960             :                          * Locally generated multicast packets are not handled
     961             :                          * by EVPN multicast in P1. We should do lookup for
     962             :                          * broadcast mac to be able to use IMET route.
     963             :                          */
     964           0 :                         lookup_mac = (int8_t *)vr_bcast_mac;
     965             :                     }
     966             :                 }
     967             :             } else {
     968           0 :                 lookup_mac = (int8_t *)vr_bcast_mac;
     969             :             }
     970           0 :             be = bridge_lookup(lookup_mac, fmd);
     971           0 :             if (!be) {
     972             :                 /* Fallback MAC lookup */
     973           0 :                 lookup_mac = (int8_t *)vr_bcast_mac;
     974           0 :                 be = bridge_lookup(lookup_mac, fmd);
     975             :             }
     976             :         }
     977         109 :         if (be)
     978         108 :             nh = be->be_nh;
     979             : 
     980         109 :         if (!nh || nh->nh_type == NH_DISCARD) {
     981             : 
     982             :             /* If Flooding of unknown unicast not allowed, drop the packet */
     983           1 :             if (!vr_unknown_uc_flood(pkt->vp_if, pkt->vp_nh) ||
     984           0 :                                  (mac_flags & MAC_BMC_BIT_SET)) {
     985           1 :                 PKT_LOG(VP_DROP_L2_NO_ROUTE, pkt, 0, VR_BRIDGE_C, __LINE__);
     986           1 :                 vr_pfree(pkt, VP_DROP_L2_NO_ROUTE);
     987           1 :                 return 0;
     988             :             }
     989             : 
     990           0 :             be = bridge_lookup(vr_bcast_mac, fmd);
     991           0 :             if (!be || !(nh = be->be_nh)) {
     992           0 :                 PKT_LOG(VP_DROP_L2_NO_ROUTE, pkt, 0, VR_BRIDGE_C, __LINE__);
     993           0 :                 vr_pfree(pkt, VP_DROP_L2_NO_ROUTE);
     994           0 :                 return 0;
     995             :             }
     996           0 :             if (vr_inet_vrf_stats) {
     997           0 :                 stats = vr_inet_vrf_stats(fmd->fmd_dvrf, pkt->vp_cpu);
     998           0 :                 if (stats)
     999           0 :                     stats->vrf_uuc_floods++;
    1000             :             }
    1001             : 
    1002             :             /* Treat this unknown unicast packet as multicast */
    1003           0 :             pkt->vp_flags |= VP_FLAG_MULTICAST;
    1004             :         }
    1005             : 
    1006         108 :         if (be)
    1007         108 :             vr_sync_fetch_and_add_64u(&be->be_packets, 1);
    1008             : 
    1009         108 :         if (nh->nh_type != NH_L2_RCV)
    1010          79 :             overlay_len = VROUTER_L2_OVERLAY_LEN;
    1011             : 
    1012             :         /*
    1013             :          * If the tunnel is a PBB tunnel, we need to accomodate for Itag
    1014             :          * and an extra ethernet (for Bmac) + Vlan header
    1015             :          */
    1016         108 :         if (nh->nh_flags & NH_FLAG_TUNNEL_PBB) {
    1017           0 :             overlay_len += VR_ETHER_HLEN + sizeof(struct vr_vlan_hdr) +
    1018             :                             sizeof(struct vr_pbb_itag);
    1019             :         }
    1020             :     }
    1021             : 
    1022             :     /* Adjust MSS for V4 and V6 packets */
    1023         108 :     if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6)) {
    1024             : 
    1025         105 :         if (vif_is_virtual(pkt->vp_if) &&
    1026         103 :                 vr_from_vm_mss_adj && vr_pkt_from_vm_tcp_mss_adj) {
    1027             : 
    1028         103 :             if ((reason = vr_pkt_from_vm_tcp_mss_adj(pkt, overlay_len))) {
    1029           0 :                 PKT_LOG(reason, pkt, 0, VR_BRIDGE_C, __LINE__);
    1030           0 :                 vr_pfree(pkt, reason);
    1031           0 :                 return 0;
    1032             :             }
    1033             :         }
    1034             : 
    1035         105 :         if (fmd->fmd_to_me) {
    1036           0 :             handled = vr_l3_input(pkt, fmd);
    1037           0 :             if (!handled) {
    1038           0 :                 PKT_LOG(VP_DROP_NOWHERE_TO_GO, pkt, 0, VR_BRIDGE_C, __LINE__);
    1039           0 :                 vr_pfree(pkt, VP_DROP_NOWHERE_TO_GO);
    1040             :             }
    1041           0 :             return 0;
    1042             :         }
    1043             : 
    1044             :         /* If a ucast packet is coming from fabric and going to fabric, drop it */
    1045         105 :         if (be && (mac_flags & MAC_UC_BIT_SET) && vif_is_fabric(pkt->vp_if) &&
    1046           1 :                 (nh->nh_type == NH_TUNNEL) &&
    1047           1 :                 (!(pkt->vp_if->vif_flags & VIF_FLAG_FAB_GW_MODE))) {
    1048           1 :             PKT_LOG(VP_DROP_INVALID_SOURCE, pkt, 0, VR_BRIDGE_C, __LINE__);
    1049           1 :             vr_pfree(pkt, VP_DROP_INVALID_SOURCE);
    1050           1 :             return 0;
    1051             :         }
    1052             :     }
    1053             : 
    1054             : 
    1055         107 :     if (pull_len && !pkt_push(pkt, pull_len)) {
    1056           0 :         PKT_LOG(VP_DROP_PUSH, pkt, 0, VR_BRIDGE_C, __LINE__);
    1057           0 :         vr_pfree(pkt, VP_DROP_PUSH);
    1058           0 :         return 0;
    1059             :     }
    1060             : 
    1061         107 :     nh_output(pkt, nh, fmd);
    1062         107 :     return 0;
    1063             : }
    1064             : 
    1065          53 : void vr_compute_size_bridge_otable(void)
    1066             : {
    1067          53 :     if (!vr_bridge_oentries)
    1068           0 :         vr_bridge_oentries = ((vr_bridge_entries / 5) + 1023) & ~1023;
    1069          53 : }

Generated by: LCOV version 1.14