diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
commit | 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 (patch) | |
tree | c05dc0f8e6aa3accc84e3e5cffc933ed94941383 /lib/qobj.c | |
parent | Initial commit. (diff) | |
download | frr-upstream.tar.xz frr-upstream.zip |
Adding upstream version 8.4.4.upstream/8.4.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/qobj.c')
-rw-r--r-- | lib/qobj.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/qobj.c b/lib/qobj.c new file mode 100644 index 0000000..c6cb36c --- /dev/null +++ b/lib/qobj.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * This file is part of Quagga + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "thread.h" +#include "memory.h" +#include "hash.h" +#include "log.h" +#include "qobj.h" +#include "jhash.h" +#include "network.h" + +static uint32_t qobj_hash(const struct qobj_node *node) +{ + return (uint32_t)node->nid; +} + +static int qobj_cmp(const struct qobj_node *na, const struct qobj_node *nb) +{ + if (na->nid < nb->nid) + return -1; + if (na->nid > nb->nid) + return 1; + return 0; +} + +DECLARE_HASH(qobj_nodes, struct qobj_node, nodehash, + qobj_cmp, qobj_hash); + +static pthread_rwlock_t nodes_lock; +static struct qobj_nodes_head nodes = { }; + + +void qobj_reg(struct qobj_node *node, const struct qobj_nodetype *type) +{ + node->type = type; + pthread_rwlock_wrlock(&nodes_lock); + do { + node->nid = (uint64_t)frr_weak_random(); + node->nid ^= (uint64_t)frr_weak_random() << 32; + } while (!node->nid || qobj_nodes_find(&nodes, node)); + qobj_nodes_add(&nodes, node); + pthread_rwlock_unlock(&nodes_lock); +} + +void qobj_unreg(struct qobj_node *node) +{ + pthread_rwlock_wrlock(&nodes_lock); + qobj_nodes_del(&nodes, node); + pthread_rwlock_unlock(&nodes_lock); +} + +struct qobj_node *qobj_get(uint64_t id) +{ + struct qobj_node dummy = {.nid = id}, *rv; + pthread_rwlock_rdlock(&nodes_lock); + rv = qobj_nodes_find(&nodes, &dummy); + pthread_rwlock_unlock(&nodes_lock); + return rv; +} + +void *qobj_get_typed(uint64_t id, const struct qobj_nodetype *type) +{ + struct qobj_node dummy = {.nid = id}; + struct qobj_node *node; + void *rv; + + pthread_rwlock_rdlock(&nodes_lock); + node = qobj_nodes_find(&nodes, &dummy); + + /* note: we explicitly hold the lock until after we have checked the + * type. + * if the caller holds a lock that for example prevents the deletion of + * route-maps, we can still race against a delete of something that + * isn't + * a route-map. */ + if (!node || node->type != type) + rv = NULL; + else + rv = (char *)node - node->type->node_member_offset; + + pthread_rwlock_unlock(&nodes_lock); + return rv; +} + +void qobj_init(void) +{ + pthread_rwlock_init(&nodes_lock, NULL); + qobj_nodes_init(&nodes); +} + +void qobj_finish(void) +{ + struct qobj_node *node; + while ((node = qobj_nodes_pop(&nodes))) + qobj_nodes_del(&nodes, node); + pthread_rwlock_destroy(&nodes_lock); +} |