back to topotato report
topotato coverage report
Current view: top level - lib - qobj.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 41 47 87.2 %
Date: 2023-11-16 17:19:14 Functions: 9 17 52.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (c) 2015-16  David Lamparter, for NetDEF, Inc.
       4             :  *
       5             :  * This file is part of Quagga
       6             :  */
       7             : 
       8             : #include <zebra.h>
       9             : 
      10             : #include "frrevent.h"
      11             : #include "memory.h"
      12             : #include "hash.h"
      13             : #include "log.h"
      14             : #include "qobj.h"
      15             : #include "jhash.h"
      16             : #include "network.h"
      17             : 
      18          80 : static uint32_t qobj_hash(const struct qobj_node *node)
      19             : {
      20          80 :         return (uint32_t)node->nid;
      21             : }
      22             : 
      23          20 : static int qobj_cmp(const struct qobj_node *na, const struct qobj_node *nb)
      24             : {
      25          20 :         if (na->nid < nb->nid)
      26             :                 return -1;
      27          20 :         if (na->nid > nb->nid)
      28             :                 return 1;
      29             :         return 0;
      30             : }
      31             : 
      32         364 : DECLARE_HASH(qobj_nodes, struct qobj_node, nodehash,
      33             :                         qobj_cmp, qobj_hash);
      34             : 
      35             : static pthread_rwlock_t nodes_lock;
      36             : static struct qobj_nodes_head nodes = { };
      37             : 
      38             : 
      39          32 : void qobj_reg(struct qobj_node *node, const struct qobj_nodetype *type)
      40             : {
      41          32 :         node->type = type;
      42          32 :         pthread_rwlock_wrlock(&nodes_lock);
      43          32 :         do {
      44          32 :                 node->nid = (uint64_t)frr_weak_random();
      45          32 :                 node->nid ^= (uint64_t)frr_weak_random() << 32;
      46          64 :         } while (!node->nid || qobj_nodes_find(&nodes, node));
      47          32 :         qobj_nodes_add(&nodes, node);
      48          32 :         pthread_rwlock_unlock(&nodes_lock);
      49          32 : }
      50             : 
      51          26 : void qobj_unreg(struct qobj_node *node)
      52             : {
      53          26 :         pthread_rwlock_wrlock(&nodes_lock);
      54          26 :         qobj_nodes_del(&nodes, node);
      55          26 :         pthread_rwlock_unlock(&nodes_lock);
      56          26 : }
      57             : 
      58           0 : struct qobj_node *qobj_get(uint64_t id)
      59             : {
      60           0 :         struct qobj_node dummy = {.nid = id}, *rv;
      61           0 :         pthread_rwlock_rdlock(&nodes_lock);
      62           0 :         rv = qobj_nodes_find(&nodes, &dummy);
      63           0 :         pthread_rwlock_unlock(&nodes_lock);
      64           0 :         return rv;
      65             : }
      66             : 
      67          20 : void *qobj_get_typed(uint64_t id, const struct qobj_nodetype *type)
      68             : {
      69          20 :         struct qobj_node dummy = {.nid = id};
      70          20 :         struct qobj_node *node;
      71          20 :         void *rv;
      72             : 
      73          20 :         pthread_rwlock_rdlock(&nodes_lock);
      74          20 :         node = qobj_nodes_find(&nodes, &dummy);
      75             : 
      76             :         /* note: we explicitly hold the lock until after we have checked the
      77             :          * type.
      78             :          * if the caller holds a lock that for example prevents the deletion of
      79             :          * route-maps, we can still race against a delete of something that
      80             :          * isn't
      81             :          * a route-map. */
      82          20 :         if (!node || node->type != type)
      83             :                 rv = NULL;
      84             :         else
      85          20 :                 rv = (char *)node - node->type->node_member_offset;
      86             : 
      87          20 :         pthread_rwlock_unlock(&nodes_lock);
      88          20 :         return rv;
      89             : }
      90             : 
      91           6 : void qobj_init(void)
      92             : {
      93           6 :         pthread_rwlock_init(&nodes_lock, NULL);
      94           6 :         qobj_nodes_init(&nodes);
      95           6 : }
      96             : 
      97           4 : void qobj_finish(void)
      98             : {
      99           4 :         struct qobj_node *node;
     100          10 :         while ((node = qobj_nodes_pop(&nodes)))
     101           6 :                 qobj_nodes_del(&nodes, node);
     102           4 :         pthread_rwlock_destroy(&nodes_lock);
     103           4 : }

Generated by: LCOV version v1.16-topotato