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

Generated by: LCOV version 1.14