diff options
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/dict.c | 1510 | ||||
-rw-r--r-- | isisd/dict.h | 121 | ||||
-rw-r--r-- | isisd/isis_adjacency.c | 1 | ||||
-rw-r--r-- | isisd/isis_bpf.c | 1 | ||||
-rw-r--r-- | isisd/isis_circuit.c | 10 | ||||
-rw-r--r-- | isisd/isis_csm.c | 1 | ||||
-rw-r--r-- | isisd/isis_dlpi.c | 1 | ||||
-rw-r--r-- | isisd/isis_dr.c | 1 | ||||
-rw-r--r-- | isisd/isis_dynhn.c | 1 | ||||
-rw-r--r-- | isisd/isis_events.c | 1 | ||||
-rw-r--r-- | isisd/isis_lsp.c | 297 | ||||
-rw-r--r-- | isisd/isis_lsp.h | 31 | ||||
-rw-r--r-- | isisd/isis_main.c | 1 | ||||
-rw-r--r-- | isisd/isis_misc.c | 1 | ||||
-rw-r--r-- | isisd/isis_northbound.c | 1 | ||||
-rw-r--r-- | isisd/isis_pdu.c | 40 | ||||
-rw-r--r-- | isisd/isis_pfpacket.c | 1 | ||||
-rw-r--r-- | isisd/isis_redist.c | 1 | ||||
-rw-r--r-- | isisd/isis_route.c | 1 | ||||
-rw-r--r-- | isisd/isis_routemap.c | 1 | ||||
-rw-r--r-- | isisd/isis_spf.c | 13 | ||||
-rw-r--r-- | isisd/isis_spf_private.h | 4 | ||||
-rw-r--r-- | isisd/isis_te.c | 1 | ||||
-rw-r--r-- | isisd/isis_tlvs.c | 28 | ||||
-rw-r--r-- | isisd/isis_tlvs.h | 5 | ||||
-rw-r--r-- | isisd/isis_tx_queue.c | 1 | ||||
-rw-r--r-- | isisd/isis_vty_fabricd.c | 10 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 1 | ||||
-rw-r--r-- | isisd/isisd.c | 47 | ||||
-rw-r--r-- | isisd/isisd.h | 6 | ||||
-rw-r--r-- | isisd/subdir.am | 2 |
31 files changed, 213 insertions, 1928 deletions
diff --git a/isisd/dict.c b/isisd/dict.c deleted file mode 100644 index d91f05d25..000000000 --- a/isisd/dict.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* - * Dictionary Abstract Data Type - * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net> - * - * Free Software License: - * - * All rights are reserved by the author, with the following exceptions: - * Permission is granted to freely reproduce and distribute this software, - * possibly in exchange for a fee, provided that this copyright notice appears - * intact. Permission is also granted to adapt this software to produce - * derivative works, as long as the modified versions carry this copyright - * notice and additional notices stating that the work has been modified. - * This source code may be translated into executable form and incorporated - * into proprietary software; there is no requirement for such software to - * contain a copyright notice related to this source. - */ - -#include "zebra.h" -#include "zassert.h" -#include "memory.h" -#include "isis_memory.h" -#include "dict.h" - -/* - * These macros provide short convenient names for structure members, - * which are embellished with dict_ prefixes so that they are - * properly confined to the documented namespace. It's legal for a - * program which uses dict to define, for instance, a macro called ``parent''. - * Such a macro would interfere with the dnode_t struct definition. - * In general, highly portable and reusable C modules which expose their - * structures need to confine structure member names to well-defined spaces. - * The resulting identifiers aren't necessarily convenient to use, nor - * readable, in the implementation, however! - */ - -#define left dict_left -#define right dict_right -#define parent dict_parent -#define color dict_color -#define key dict_key -#define data dict_data - -#define nilnode dict_nilnode -#define nodecount dict_nodecount -#define maxcount dict_maxcount -#define compare dict_compare -#define allocnode dict_allocnode -#define freenode dict_freenode -#define context dict_context -#define dupes dict_dupes - -#define dictptr dict_dictptr - -#define dict_root(D) ((D)->nilnode.left) -#define dict_nil(D) (&(D)->nilnode) -#define DICT_DEPTH_MAX 64 - -static dnode_t *dnode_alloc(void *context); -static void dnode_free(dnode_t *node, void *context); - -/* - * Perform a ``left rotation'' adjustment on the tree. The given node P and - * its right child C are rearranged so that the P instead becomes the left - * child of C. The left subtree of C is inherited as the new right subtree - * for P. The ordering of the keys within the tree is thus preserved. - */ - -static void rotate_left(dnode_t *upper) -{ - dnode_t *lower, *lowleft, *upparent; - - lower = upper->right; - upper->right = lowleft = lower->left; - lowleft->parent = upper; - - lower->parent = upparent = upper->parent; - - /* don't need to check for root node here because root->parent is - the sentinel nil node, and root->parent->left points back to root */ - - if (upper == upparent->left) { - upparent->left = lower; - } else { - assert(upper == upparent->right); - upparent->right = lower; - } - - lower->left = upper; - upper->parent = lower; -} - -/* - * This operation is the ``mirror'' image of rotate_left. It is - * the same procedure, but with left and right interchanged. - */ - -static void rotate_right(dnode_t *upper) -{ - dnode_t *lower, *lowright, *upparent; - - lower = upper->left; - upper->left = lowright = lower->right; - lowright->parent = upper; - - lower->parent = upparent = upper->parent; - - if (upper == upparent->right) { - upparent->right = lower; - } else { - assert(upper == upparent->left); - upparent->left = lower; - } - - lower->right = upper; - upper->parent = lower; -} - -/* - * Do a postorder traversal of the tree rooted at the specified - * node and free everything under it. Used by dict_free(). - */ - -static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) -{ - if (node == nil) - return; - free_nodes(dict, node->left, nil); - free_nodes(dict, node->right, nil); - dict->freenode(node, dict->context); -} - -/* - * This procedure performs a verification that the given subtree is a binary - * search tree. It performs an inorder traversal of the tree using the - * dict_next() successor function, verifying that the key of each node is - * strictly lower than that of its successor, if duplicates are not allowed, - * or lower or equal if duplicates are allowed. This function is used for - * debugging purposes. - */ - -static int verify_bintree(dict_t *dict) -{ - dnode_t *first, *next; - - first = dict_first(dict); - - if (dict->dupes) { - while (first && (next = dict_next(dict, first))) { - if (dict->compare(first->key, next->key) > 0) - return 0; - first = next; - } - } else { - while (first && (next = dict_next(dict, first))) { - if (dict->compare(first->key, next->key) >= 0) - return 0; - first = next; - } - } - return 1; -} - - -/* - * This function recursively verifies that the given binary subtree satisfies - * three of the red black properties. It checks that every red node has only - * black children. It makes sure that each node is either red or black. And it - * checks that every path has the same count of black nodes from root to leaf. - * It returns the blackheight of the given subtree; this allows blackheights to - * be computed recursively and compared for left and right siblings for - * mismatches. It does not check for every nil node being black, because there - * is only one sentinel nil node. The return value of this function is the - * black height of the subtree rooted at the node ``root'', or zero if the - * subtree is not red-black. - */ - -#ifdef EXTREME_DICT_DEBUG -static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) -{ - unsigned height_left, height_right; - - if (root != nil) { - height_left = verify_redblack(nil, root->left); - height_right = verify_redblack(nil, root->right); - if (height_left == 0 || height_right == 0) - return 0; - if (height_left != height_right) - return 0; - if (root->color == dnode_red) { - if (root->left->color != dnode_black) - return 0; - if (root->right->color != dnode_black) - return 0; - return height_left; - } - if (root->color != dnode_black) - return 0; - return height_left + 1; - } - return 1; -} -#endif - -/* - * Compute the actual count of nodes by traversing the tree and - * return it. This could be compared against the stored count to - * detect a mismatch. - */ - -#ifdef EXTREME_DICT_DEBUG -static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) -{ - if (root == nil) - return 0; - else - return 1 + verify_node_count(nil, root->left) - + verify_node_count(nil, root->right); -} -#endif - -/* - * Verify that the tree contains the given node. This is done by - * traversing all of the nodes and comparing their pointers to the - * given pointer. Returns 1 if the node is found, otherwise - * returns zero. It is intended for debugging purposes. - */ - -static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) -{ - if (root != nil) { - return root == node - || verify_dict_has_node(nil, root->left, node) - || verify_dict_has_node(nil, root->right, node); - } - return 0; -} - - -/* - * Dynamically allocate and initialize a dictionary object. - */ - -dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp) -{ - dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t)); - - new->compare = comp; - new->allocnode = dnode_alloc; - new->freenode = dnode_free; - new->context = NULL; - new->nodecount = 0; - new->maxcount = maxcount; - new->nilnode.left = &new->nilnode; - new->nilnode.right = &new->nilnode; - new->nilnode.parent = &new->nilnode; - new->nilnode.color = dnode_black; - new->dupes = 0; - - return new; -} - -/* - * Select a different set of node allocator routines. - */ - -void dict_set_allocator(dict_t *dict, dnode_alloc_t al, dnode_free_t fr, - void *context) -{ - assert(dict_count(dict) == 0); - assert((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); - - dict->allocnode = al ? al : dnode_alloc; - dict->freenode = fr ? fr : dnode_free; - dict->context = context; -} - -/* - * Free a dynamically allocated dictionary object. Removing the nodes - * from the tree before deleting it is required. - */ - -void dict_destroy(dict_t *dict) -{ - assert(dict_isempty(dict)); - XFREE(MTYPE_ISIS_DICT, dict); -} - -/* - * Free all the nodes in the dictionary by using the dictionary's - * installed free routine. The dictionary is emptied. - */ - -void dict_free_nodes(dict_t *dict) -{ - dnode_t *nil = dict_nil(dict), *root = dict_root(dict); - free_nodes(dict, root, nil); - dict->nodecount = 0; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; -} - -/* - * Obsolescent function, equivalent to dict_free_nodes - */ - -void dict_free(dict_t *dict) -{ - dict_free_nodes(dict); -} - -/* - * Initialize a user-supplied dictionary object. - */ - -dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) -{ - dict->compare = comp; - dict->allocnode = dnode_alloc; - dict->freenode = dnode_free; - dict->context = NULL; - dict->nodecount = 0; - dict->maxcount = maxcount; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - dict->nilnode.color = dnode_black; - dict->dupes = 0; - return dict; -} - -/* - * Initialize a dictionary in the likeness of another dictionary - */ - -void dict_init_like(dict_t *dict, const dict_t *template) -{ - dict->compare = template->compare; - dict->allocnode = template->allocnode; - dict->freenode = template->freenode; - dict->context = template->context; - dict->nodecount = 0; - dict->maxcount = template->maxcount; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - dict->nilnode.color = dnode_black; - dict->dupes = template->dupes; - - assert(dict_similar(dict, template)); -} - -/* - * Remove all nodes from the dictionary (without freeing them in any way). - */ - -static void dict_clear(dict_t *dict) -{ - dict->nodecount = 0; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - assert(dict->nilnode.color == dnode_black); -} - - -/* - * Verify the integrity of the dictionary structure. This is provided for - * debugging purposes, and should be placed in assert statements. Just because - * this function succeeds doesn't mean that the tree is not corrupt. Certain - * corruptions in the tree may simply cause undefined behavior. - */ - -int dict_verify(dict_t *dict) -{ -#ifdef EXTREME_DICT_DEBUG - dnode_t *nil = dict_nil(dict), *root = dict_root(dict); - - /* check that the sentinel node and root node are black */ - if (root->color != dnode_black) - return 0; - if (nil->color != dnode_black) - return 0; - if (nil->right != nil) - return 0; - /* nil->left is the root node; check that its parent pointer is nil */ - if (nil->left->parent != nil) - return 0; - /* perform a weak test that the tree is a binary search tree */ - if (!verify_bintree(dict)) - return 0; - /* verify that the tree is a red-black tree */ - if (!verify_redblack(nil, root)) - return 0; - if (verify_node_count(nil, root) != dict_count(dict)) - return 0; -#endif - return 1; -} - -/* - * Determine whether two dictionaries are similar: have the same comparison and - * allocator functions, and same status as to whether duplicates are allowed. - */ - -int dict_similar(const dict_t *left, const dict_t *right) -{ - if (left->compare != right->compare) - return 0; - - if (left->allocnode != right->allocnode) - return 0; - - if (left->freenode != right->freenode) - return 0; - - if (left->context != right->context) - return 0; - - if (left->dupes != right->dupes) - return 0; - - return 1; -} - -/* - * Locate a node in the dictionary having the given key. - * If the node is not found, a null a pointer is returned (rather than - * a pointer that dictionary's nil sentinel node), otherwise a pointer to the - * located node is returned. - */ - -dnode_t *dict_lookup(dict_t *dict, const void *key) -{ - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *saved; - int result; - - /* simple binary search adapted for trees that contain duplicate keys */ - - while (root != nil) { - result = dict->compare(key, root->key); - if (result < 0) - root = root->left; - else if (result > 0) - root = root->right; - else { - if (!dict->dupes) { /* no duplicates, return match - */ - return root; - } else { /* could be dupes, find leftmost one */ - do { - saved = root; - root = root->left; - while (root != nil - && dict->compare(key, root->key)) - root = root->right; - } while (root != nil); - return saved; - } - } - } - - return NULL; -} - -/* - * Look for the node corresponding to the lowest key that is equal to or - * greater than the given key. If there is no such node, return null. - */ - -dnode_t *dict_lower_bound(dict_t *dict, const void *key) -{ - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *tentative = 0; - - while (root != nil) { - int result = dict->compare(key, root->key); - - if (result > 0) { - root = root->right; - } else if (result < 0) { - tentative = root; - root = root->left; - } else { - if (!dict->dupes) { - return root; - } else { - tentative = root; - root = root->left; - } - } - } - - return tentative; -} - -/* - * Look for the node corresponding to the greatest key that is equal to or - * lower than the given key. If there is no such node, return null. - */ - -dnode_t *dict_upper_bound(dict_t *dict, const void *key) -{ - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *tentative = 0; - - while (root != nil) { - int result = dict->compare(key, root->key); - - if (result < 0) { - root = root->left; - } else if (result > 0) { - tentative = root; - root = root->right; - } else { - if (!dict->dupes) { - return root; - } else { - tentative = root; - root = root->right; - } - } - } - - return tentative; -} - -/* - * Insert a node into the dictionary. The node should have been - * initialized with a data field. All other fields are ignored. - * The behavior is undefined if the user attempts to insert into - * a dictionary that is already full (for which the dict_isfull() - * function returns true). - */ - -void dict_insert(dict_t *dict, dnode_t *node, const void *key) -{ - dnode_t *where = dict_root(dict), *nil = dict_nil(dict); - dnode_t *parent = nil, *uncle, *grandpa; - int result = -1; - - node->key = key; - - assert(!dict_isfull(dict)); - assert(!dict_contains(dict, node)); - assert(!dnode_is_in_a_dict(node)); - - /* basic binary tree insert */ - - while (where != nil) { - parent = where; - result = dict->compare(key, where->key); - /* trap attempts at duplicate key insertion unless it's - * explicitly allowed */ - assert(dict->dupes || result != 0); - if (result < 0) - where = where->left; - else - where = where->right; - } - - assert(where == nil); - - if (result < 0) - parent->left = node; - else - parent->right = node; - - node->parent = parent; - node->left = nil; - node->right = nil; - - dict->nodecount++; - - /* red black adjustments */ - - node->color = dnode_red; - - while (parent->color == dnode_red) { - grandpa = parent->parent; - if (parent == grandpa->left) { - uncle = grandpa->right; - if (uncle->color - == dnode_red) { /* red parent, red uncle */ - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { /* red parent, black uncle */ - if (node == parent->right) { - rotate_left(parent); - parent = node; - assert(grandpa == parent->parent); - /* rotation between parent and child - * preserves grandpa */ - } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_right(grandpa); - break; - } - } else { /* symmetric cases: parent == parent->parent->right */ - uncle = grandpa->left; - if (uncle->color == dnode_red) { - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { - if (node == parent->left) { - rotate_right(parent); - parent = node; - assert(grandpa == parent->parent); - } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_left(grandpa); - break; - } - } - } - - dict_root(dict)->color = dnode_black; - - assert(dict_verify(dict)); -} - -/* - * Delete the given node from the dictionary. If the given node does not belong - * to the given dictionary, undefined behavior results. A pointer to the - * deleted node is returned. - */ - -dnode_t *dict_delete(dict_t *dict, dnode_t *delete) -{ - dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; - - /* basic deletion */ - - assert(!dict_isempty(dict)); - assert(dict_contains(dict, delete)); - - /* - * If the node being deleted has two children, then we replace it with - * its - * successor (i.e. the leftmost node in the right subtree.) By doing - * this, - * we avoid the traditional algorithm under which the successor's key - * and - * value *only* move to the deleted node and the successor is spliced - * out - * from the tree. We cannot use this approach because the user may hold - * pointers to the successor, or nodes may be inextricably tied to some - * other structures by way of embedding, etc. So we must splice out the - * node we are given, not some other node, and must not move contents - * from - * one node to another behind the user's back. - */ - - if (delete->left != nil && delete->right != nil) { - dnode_t *next = dict_next(dict, delete); - assert(next); - dnode_t *nextparent = next->parent; - dnode_color_t nextcolor = next->color; - - assert(next != nil); - assert(next->parent != nil); - assert(next->left == nil); - - /* - * First, splice out the successor from the tree completely, by - * moving up its right child into its place. - */ - - child = next->right; - child->parent = nextparent; - - if (nextparent->left == next) { - nextparent->left = child; - } else { - assert(nextparent->right == next); - nextparent->right = child; - } - - /* - * Now that the successor has been extricated from the tree, - * install it - * in place of the node that we want deleted. - */ - - next->parent = delparent; - next->left = delete->left; - next->right = delete->right; - next->left->parent = next; - next->right->parent = next; - next->color = delete->color; - delete->color = nextcolor; - - if (delparent->left == delete) { - delparent->left = next; - } else { - assert(delparent->right == delete); - delparent->right = next; - } - - } else { - assert(delete != nil); - assert(delete->left == nil || delete->right == nil); - - child = (delete->left != nil) ? delete->left : delete->right; - - child->parent = delparent = delete->parent; - - if (delete == delparent->left) { - delparent->left = child; - } else { - assert(delete == delparent->right); - delparent->right = child; - } - } - - delete->parent = NULL; - delete->right = NULL; - delete->left = NULL; - - dict->nodecount--; - - assert(verify_bintree(dict)); - - /* red-black adjustments */ - - if (delete->color == dnode_black) { - dnode_t *parent, *sister; - - dict_root(dict)->color = dnode_red; - - while (child->color == dnode_black) { - parent = child->parent; - if (child == parent->left) { - sister = parent->right; - assert(sister != nil); - if (sister->color == dnode_red) { - sister->color = dnode_black; - parent->color = dnode_red; - rotate_left(parent); - sister = parent->right; - assert(sister != nil); - } - if (sister->left->color == dnode_black - && sister->right->color == dnode_black) { - sister->color = dnode_red; - child = parent; - } else { - if (sister->right->color - == dnode_black) { - assert(sister->left->color - == dnode_red); - sister->left->color = - dnode_black; - sister->color = dnode_red; - rotate_right(sister); - sister = parent->right; - assert(sister != nil); - } - sister->color = parent->color; - sister->right->color = dnode_black; - parent->color = dnode_black; - rotate_left(parent); - break; - } - } else { /* symmetric case: child == - child->parent->right */ - assert(child == parent->right); - sister = parent->left; - assert(sister != nil); - if (sister->color == dnode_red) { - sister->color = dnode_black; - parent->color = dnode_red; - rotate_right(parent); - sister = parent->left; - assert(sister != nil); - } - if (sister->right->color == dnode_black - && sister->left->color == dnode_black) { - sister->color = dnode_red; - child = parent; - } else { - if (sister->left->color - == dnode_black) { - assert(sister->right->color - == dnode_red); - sister->right->color = - dnode_black; - sister->color = dnode_red; - rotate_left(sister); - sister = parent->left; - assert(sister != nil); - } - sister->color = parent->color; - sister->left->color = dnode_black; - parent->color = dnode_black; - rotate_right(parent); - break; - } - } - } - - child->color = dnode_black; - dict_root(dict)->color = dnode_black; - } - - assert(dict_verify(dict)); - - return delete; -} - -/* - * Allocate a node using the dictionary's allocator routine, give it - * the data item. - */ - -int dict_alloc_insert(dict_t *dict, const void *key, void *data) -{ - dnode_t *node = dict->allocnode(dict->context); - - if (node) { - dnode_init(node, data); - dict_insert(dict, node, key); - return 1; - } - return 0; -} - -void dict_delete_free(dict_t *dict, dnode_t *node) -{ - dict_delete(dict, node); - dict->freenode(node, dict->context); -} - -/* - * Return the node with the lowest (leftmost) key. If the dictionary is empty - * (that is, dict_isempty(dict) returns 1) a null pointer is returned. - */ - -dnode_t *dict_first(dict_t *dict) -{ - dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; - - if (root != nil) - while ((left = root->left) != nil) - root = left; - - return (root == nil) ? NULL : root; -} - -/* - * Return the node with the highest (rightmost) key. If the dictionary is empty - * (that is, dict_isempty(dict) returns 1) a null pointer is returned. - */ - -dnode_t *dict_last(dict_t *dict) -{ - dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; - - if (root != nil) - while ((right = root->right) != nil) - root = right; - - return (root == nil) ? NULL : root; -} - -/* - * Return the given node's successor node---the node which has the - * next key in the the left to right ordering. If the node has - * no successor, a null pointer is returned rather than a pointer to - * the nil node. - */ - -dnode_t *dict_next(dict_t *dict, dnode_t *curr) -{ - dnode_t *nil = dict_nil(dict), *parent, *left; - - if (curr->right != nil) { - curr = curr->right; - while ((left = curr->left) != nil) - curr = left; - return curr; - } - - parent = curr->parent; - - while (parent != nil && curr == parent->right) { - curr = parent; - parent = curr->parent; - } - - return (parent == nil) ? NULL : parent; -} - -/* - * Return the given node's predecessor, in the key order. - * The nil sentinel node is returned if there is no predecessor. - */ - -dnode_t *dict_prev(dict_t *dict, dnode_t *curr) -{ - dnode_t *nil = dict_nil(dict), *parent, *right; - - if (curr->left != nil) { - curr = curr->left; - while ((right = curr->right) != nil) - curr = right; - return curr; - } - - parent = curr->parent; - - while (parent != nil && curr == parent->left) { - curr = parent; - parent = curr->parent; - } - - return (parent == nil) ? NULL : parent; -} - -void dict_allow_dupes(dict_t *dict) -{ - dict->dupes = 1; -} - -#undef dict_count -#undef dict_isempty -#undef dict_isfull -#undef dnode_get -#undef dnode_put -#undef dnode_getkey - -dictcount_t dict_count(dict_t *dict) -{ - return dict->nodecount; -} - -int dict_isempty(dict_t *dict) -{ - return dict->nodecount == 0; -} - -int dict_isfull(dict_t *dict) -{ - return dict->nodecount == dict->maxcount; -} - -int dict_contains(dict_t *dict, dnode_t *node) -{ - return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); -} - -static dnode_t *dnode_alloc(void *context) -{ - return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); -} - -static void dnode_free(dnode_t *node, void *context) -{ - XFREE(MTYPE_ISIS_DICT_NODE, node); -} - -dnode_t *dnode_create(void *data) -{ - dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); - - new->data = data; - new->parent = NULL; - new->left = NULL; - new->right = NULL; - - return new; -} - -dnode_t *dnode_init(dnode_t *dnode, void *data) -{ - dnode->data = data; - dnode->parent = NULL; - dnode->left = NULL; - dnode->right = NULL; - return dnode; -} - -void dnode_destroy(dnode_t *dnode) -{ - assert(!dnode_is_in_a_dict(dnode)); - XFREE(MTYPE_ISIS_DICT_NODE, dnode); -} - -void *dnode_get(dnode_t *dnode) -{ - return dnode->data; -} - -const void *dnode_getkey(dnode_t *dnode) -{ - return dnode->key; -} - -void dnode_put(dnode_t *dnode, void *data) -{ - dnode->data = data; -} - -int dnode_is_in_a_dict(dnode_t *dnode) -{ - return (dnode->parent && dnode->left && dnode->right); -} - -void dict_process(dict_t *dict, void *context, dnode_process_t function) -{ - dnode_t *node = dict_first(dict), *next; - - while (node != NULL) { - /* check for callback function deleting */ - /* the next node from under us */ - assert(dict_contains(dict, node)); - next = dict_next(dict, node); - function(dict, node, context); - node = next; - } -} - -static void load_begin_internal(dict_load_t *load, dict_t *dict) -{ - load->dictptr = dict; - load->nilnode.left = &load->nilnode; - load->nilnode.right = &load->nilnode; -} - -void dict_load_begin(dict_load_t *load, dict_t *dict) -{ - assert(dict_isempty(dict)); - load_begin_internal(load, dict); -} - -void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key) -{ - dict_t *dict = load->dictptr; - dnode_t *nil = &load->nilnode; - - assert(!dnode_is_in_a_dict(newnode)); - assert(dict->nodecount < dict->maxcount); - -#ifndef NDEBUG - if (dict->nodecount > 0) { - if (dict->dupes) - assert(dict->compare(nil->left->key, key) <= 0); - else - assert(dict->compare(nil->left->key, key) < 0); - } -#endif - - newnode->key = key; - nil->right->left = newnode; - nil->right = newnode; - newnode->left = nil; - dict->nodecount++; -} - -void dict_load_end(dict_load_t *load) -{ - dict_t *dict = load->dictptr; - dnode_t *tree[DICT_DEPTH_MAX] = {0}; - dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, - *next; - dnode_t *complete = 0; - dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; - dictcount_t botrowcount; - unsigned baselevel = 0, level = 0, i; - - assert(dnode_red == 0 && dnode_black == 1); - - while (fullcount >= nodecount && fullcount) - fullcount >>= 1; - - botrowcount = nodecount - fullcount; - - for (curr = loadnil->left; curr != loadnil; curr = next) { - next = curr->left; - - if (complete == NULL && botrowcount-- == 0) { - assert(baselevel == 0); - assert(level == 0); - baselevel = level = 1; - complete = tree[0]; - - if (complete != NULL) { - tree[0] = 0; - complete->right = dictnil; - while (tree[level] != NULL) { - tree[level]->right = complete; - complete->parent = tree[level]; - complete = tree[level]; - tree[level++] = 0; - } - } - } - - if (complete == NULL) { - curr->left = dictnil; - curr->right = dictnil; - curr->color = level % 2; - complete = curr; - - assert(level == baselevel); - while (tree[level] != NULL) { - tree[level]->right = complete; - complete->parent = tree[level]; - complete = tree[level]; - tree[level++] = 0; - } - } else { - curr->left = complete; - curr->color = (level + 1) % 2; - complete->parent = curr; - tree[level] = curr; - complete = 0; - level = baselevel; - } - } - - if (complete == NULL) - complete = dictnil; - - for (i = 0; i < DICT_DEPTH_MAX; i++) { - if (tree[i] != NULL) { - tree[i]->right = complete; - complete->parent = tree[i]; - complete = tree[i]; - } - } - - dictnil->color = dnode_black; - dictnil->right = dictnil; - complete->parent = dictnil; - complete->color = dnode_black; - dict_root(dict) = complete; - - assert(dict_verify(dict)); -} - -void dict_merge(dict_t *dest, dict_t *source) -{ - dict_load_t load; - dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); - - assert(dict_similar(dest, source)); - - if (source == dest) - return; - - dest->nodecount = 0; - load_begin_internal(&load, dest); - - for (;;) { - if (leftnode != NULL && rightnode != NULL) { - if (dest->compare(leftnode->key, rightnode->key) < 0) - goto copyleft; - else - goto copyright; - } else if (leftnode != NULL) { - goto copyleft; - } else if (rightnode != NULL) { - goto copyright; - } else { - assert(leftnode == NULL && rightnode == NULL); - break; - } - - copyleft : { - dnode_t *next = dict_next(dest, leftnode); -#ifndef NDEBUG - leftnode->left = - NULL; /* suppress assertion in dict_load_next */ -#endif - dict_load_next(&load, leftnode, leftnode->key); - leftnode = next; - continue; - } - - copyright : { - dnode_t *next = dict_next(source, rightnode); -#ifndef NDEBUG - rightnode->left = NULL; -#endif - dict_load_next(&load, rightnode, rightnode->key); - rightnode = next; - continue; - } - } - - dict_clear(source); - dict_load_end(&load); -} - -#ifdef KAZLIB_TEST_MAIN - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdarg.h> - -typedef char input_t[256]; - -static int tokenize(char *string, ...) -{ - char **tokptr; - va_list arglist; - int tokcount = 0; - - va_start(arglist, string); - tokptr = va_arg(arglist, char **); - while (tokptr) { - while (*string && isspace((unsigned char)*string)) - string++; - if (!*string) - break; - *tokptr = string; - while (*string && !isspace((unsigned char)*string)) - string++; - tokptr = va_arg(arglist, char **); - tokcount++; - if (!*string) - break; - *string++ = 0; - } - va_end(arglist); - - return tokcount; -} - -static int comparef(const void *key1, const void *key2) -{ - return strcmp(key1, key2); -} - -static char *dupstring(char *str) -{ - int sz = strlen(str) + 1; - char *new = XCALLOC(MTYPE_ISIS_TMP, sz); - - memcpy(new, str, sz); - return new; -} - -static dnode_t *new_node(void *c) -{ - static dnode_t few[5]; - static int count; - - if (count < 5) - return few + count++; - - return NULL; -} - -static void del_node(dnode_t *n, void *c) -{ -} - -static int prompt = 0; - -static void construct(dict_t *d) -{ - input_t in; - int done = 0; - dict_load_t dl; - dnode_t *dn; - char *tok1, *tok2, *val; - const char *key; - char *help = - "p turn prompt on\n" - "q finish construction\n" - "a <key> <val> add new entry\n"; - - if (!dict_isempty(d)) - puts("warning: dictionary not empty!"); - - dict_load_begin(&dl, d); - - while (!done) { - if (prompt) - putchar('>'); - fflush(stdout); - - if (!fgets(in, sizeof(input_t), stdin)) - break; - - switch (in[0]) { - case '?': - puts(help); - break; - case 'p': - prompt = 1; - break; - case 'q': - done = 1; - break; - case 'a': - if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { - puts("what?"); - break; - } - key = dupstring(tok1); - val = dupstring(tok2); - dn = dnode_create(val); - - if (!key || !val || !dn) { - puts("out of memory"); - free((void *)key); - free(val); - if (dn) - dnode_destroy(dn); - } else - dict_load_next(&dl, dn, key); - break; - default: - putchar('?'); - putchar('\n'); - break; - } - } - - dict_load_end(&dl); -} - -int main(void) -{ - input_t in; - dict_t darray[10]; - dict_t *d = &darray[0]; - dnode_t *dn; - int i; - char *tok1, *tok2, *val; - const char *key; - - char *help = - "a <key> <val> add value to dictionary\n" - "d <key> delete value from dictionary\n" - "l <key> lookup value in dictionary\n" - "( <key> lookup lower bound\n" - ") <key> lookup upper bound\n" - "# <num> switch to alternate dictionary (0-9)\n" - "j <num> <num> merge two dictionaries\n" - "f free the whole dictionary\n" - "k allow duplicate keys\n" - "c show number of entries\n" - "t dump whole dictionary in sort order\n" - "m make dictionary out of sorted items\n" - "p turn prompt on\n" - "s switch to non-functioning allocator\n" - "q quit"; - - for (i = 0; i < 10; i++) - dict_init(&darray[i], DICTCOUNT_T_MAX, comparef); - - for (;;) { - if (prompt) - putchar('>'); - fflush(stdout); - - if (!fgets(in, sizeof(input_t), stdin)) - break; - - switch (in[0]) { - case '?': - puts(help); - break; - case 'a': - if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { - puts("what?"); - break; - } - key = dupstring(tok1); - val = dupstring(tok2); - - if (!key || !val) { - puts("out of memory"); - free((void *)key); - free(val); - } - - if (!dict_alloc_insert(d, key, val)) { - puts("dict_alloc_insert failed"); - free((void *)key); - free(val); - break; - } - break; - case 'd': - if (tokenize(in + 1, &tok1, (char **)0) != 1) { - puts("what?"); - break; - } - dn = dict_lookup(d, tok1); - if (!dn) { - puts("dict_lookup failed"); - break; - } - val = dnode_get(dn); - key = dnode_getkey(dn); - dict_delete_free(d, dn); - - free(val); - free((void *)key); - break; - case 'f': - dict_free(d); - break; - case 'l': - case '(': - case ')': - if (tokenize(in + 1, &tok1, (char **)0) != 1) { - puts("what?"); - break; - } - dn = 0; - switch (in[0]) { - case 'l': - dn = dict_lookup(d, tok1); - break; - case '(': - dn = dict_lower_bound(d, tok1); - break; - case ')': - dn = dict_upper_bound(d, tok1); - break; - } - if (!dn) { - puts("lookup failed"); - break; - } - val = dnode_get(dn); - puts(val); - break; - case 'm': - construct(d); - break; - case 'k': - dict_allow_dupes(d); - break; - case 'c': - printf("%lu\n", (unsigned long)dict_count(d)); - break; - case 't': - for (dn = dict_first(d); dn; dn = dict_next(d, dn)) { - printf("%s\t%s\n", (char *)dnode_getkey(dn), - (char *)dnode_get(dn)); - } - break; - case 'q': - exit(0); - break; - case '\0': - break; - case 'p': - prompt = 1; - break; - case 's': - dict_set_allocator(d, new_node, del_node, NULL); - break; - case '#': - if (tokenize(in + 1, &tok1, (char **)0) != 1) { - puts("what?"); - break; - } else { - int dictnum = atoi(tok1); - if (dictnum < 0 || dictnum > 9) { - puts("invalid number"); - break; - } - d = &darray[dictnum]; - } - break; - case 'j': - if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { - puts("what?"); - break; - } else { - int dict1 = atoi(tok1), dict2 = atoi(tok2); - if (dict1 < 0 || dict1 > 9 || dict2 < 0 - || dict2 > 9) { - puts("invalid number"); - break; - } - dict_merge(&darray[dict1], &darray[dict2]); - } - break; - default: - putchar('?'); - putchar('\n'); - break; - } - } - - return 0; -} - -#endif diff --git a/isisd/dict.h b/isisd/dict.h deleted file mode 100644 index 32683c57d..000000000 --- a/isisd/dict.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Dictionary Abstract Data Type - * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net> - * - * Free Software License: - * - * All rights are reserved by the author, with the following exceptions: - * Permission is granted to freely reproduce and distribute this software, - * possibly in exchange for a fee, provided that this copyright notice appears - * intact. Permission is also granted to adapt this software to produce - * derivative works, as long as the modified versions carry this copyright - * notice and additional notices stating that the work has been modified. - * This source code may be translated into executable form and incorporated - * into proprietary software; there is no requirement for such software to - * contain a copyright notice related to this source. - * - */ - -#ifndef DICT_H -#define DICT_H - -#include <limits.h> - -/* - * Blurb for inclusion into C++ translation units - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned long dictcount_t; -#define DICTCOUNT_T_MAX ULONG_MAX - -/* - * The dictionary is implemented as a red-black tree - */ - -typedef enum { dnode_red, dnode_black } dnode_color_t; - -typedef struct dnode_t { - struct dnode_t *dict_left; - struct dnode_t *dict_right; - struct dnode_t *dict_parent; - dnode_color_t dict_color; - const void *dict_key; - void *dict_data; -} dnode_t; - -typedef int (*dict_comp_t)(const void *, const void *); -typedef dnode_t *(*dnode_alloc_t)(void *); -typedef void (*dnode_free_t)(dnode_t *, void *); - -typedef struct dict_t { - dnode_t dict_nilnode; - dictcount_t dict_nodecount; - dictcount_t dict_maxcount; - dict_comp_t dict_compare; - dnode_alloc_t dict_allocnode; - dnode_free_t dict_freenode; - void *dict_context; - int dict_dupes; -} dict_t; - -typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); - -typedef struct dict_load_t { - dict_t *dict_dictptr; - dnode_t dict_nilnode; -} dict_load_t; - -extern dict_t *dict_create(dictcount_t, dict_comp_t); -extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *); -extern void dict_destroy(dict_t *); -extern void dict_free_nodes(dict_t *); -extern void dict_free(dict_t *); -extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t); -extern void dict_init_like(dict_t *, const dict_t *); -extern int dict_verify(dict_t *); -extern int dict_similar(const dict_t *, const dict_t *); -extern dnode_t *dict_lookup(dict_t *, const void *); -extern dnode_t *dict_lower_bound(dict_t *, const void *); -extern dnode_t *dict_upper_bound(dict_t *, const void *); -extern void dict_insert(dict_t *, dnode_t *, const void *); -extern dnode_t *dict_delete(dict_t *, dnode_t *); -extern int dict_alloc_insert(dict_t *, const void *, void *); -extern void dict_delete_free(dict_t *, dnode_t *); -extern dnode_t *dict_first(dict_t *); -extern dnode_t *dict_last(dict_t *); -extern dnode_t *dict_next(dict_t *, dnode_t *); -extern dnode_t *dict_prev(dict_t *, dnode_t *); -extern dictcount_t dict_count(dict_t *); -extern int dict_isempty(dict_t *); -extern int dict_isfull(dict_t *); -extern int dict_contains(dict_t *, dnode_t *); -extern void dict_allow_dupes(dict_t *); -extern int dnode_is_in_a_dict(dnode_t *); -extern dnode_t *dnode_create(void *); -extern dnode_t *dnode_init(dnode_t *, void *); -extern void dnode_destroy(dnode_t *); -extern void *dnode_get(dnode_t *); -extern const void *dnode_getkey(dnode_t *); -extern void dnode_put(dnode_t *, void *); -extern void dict_process(dict_t *, void *, dnode_process_t); -extern void dict_load_begin(dict_load_t *, dict_t *); -extern void dict_load_next(dict_load_t *, dnode_t *, const void *); -extern void dict_load_end(dict_load_t *); -extern void dict_merge(dict_t *, dict_t *); - -#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount) -#define dict_count(D) ((D)->dict_nodecount) -#define dict_isempty(D) ((D)->dict_nodecount == 0) -#define dnode_get(N) ((N)->dict_data) -#define dnode_getkey(N) ((N)->dict_key) -#define dnode_put(N, X) ((N)->dict_data = (X)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 62814329e..9b368cc40 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -32,7 +32,6 @@ #include "if.h" #include "stream.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 28750278b..4e9aef47a 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -34,7 +34,6 @@ #include "if.h" #include "lib_errors.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_circuit.h" diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 8377638b9..f9a028587 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -40,7 +40,6 @@ #include "qobj.h" #include "lib/northbound_cli.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" @@ -540,7 +539,6 @@ static void isis_circuit_update_all_srmflags(struct isis_circuit *circuit, { struct isis_area *area; struct isis_lsp *lsp; - dnode_t *dnode; int level; assert(circuit); @@ -550,14 +548,10 @@ static void isis_circuit_update_all_srmflags(struct isis_circuit *circuit, if (!(level & circuit->is_type)) continue; - if (!area->lspdb[level - 1] - || !dict_count(area->lspdb[level - 1])) + if (!lspdb_count(&area->lspdb[level - 1])) continue; - for (dnode = dict_first(area->lspdb[level - 1]); - dnode != NULL; - dnode = dict_next(area->lspdb[level - 1], dnode)) { - lsp = dnode_get(dnode); + for_each (lspdb, &area->lspdb[level - 1], lsp) { if (is_set) { isis_tx_queue_add(circuit->tx_queue, lsp, TX_LSP_NORMAL); diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index e50f57ae1..88676dd99 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -32,7 +32,6 @@ #include "prefix.h" #include "stream.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index 148b43866..a96dd9380 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -38,7 +38,6 @@ #include "if.h" #include "lib_errors.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_circuit.h" diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c index 449648656..7be530750 100644 --- a/isisd/isis_dr.c +++ b/isisd/isis_dr.c @@ -32,7 +32,6 @@ #include "stream.h" #include "if.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_misc.h" diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index 1d29d1086..921e23d33 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -31,7 +31,6 @@ #include "if.h" #include "thread.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 4da23c591..6a5dcfb07 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -32,7 +32,6 @@ #include "stream.h" #include "table.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 0a9f13e6d..199166695 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -40,7 +40,6 @@ #include "srcdest_table.h" #include "lib_errors.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" @@ -63,41 +62,38 @@ static int lsp_refresh(struct thread *thread); static int lsp_l1_refresh_pseudo(struct thread *thread); static int lsp_l2_refresh_pseudo(struct thread *thread); +static void lsp_destroy(struct isis_lsp *lsp); + int lsp_id_cmp(uint8_t *id1, uint8_t *id2) { return memcmp(id1, id2, ISIS_SYS_ID_LEN + 2); } -dict_t *lsp_db_init(void) +int lspdb_compare(const struct isis_lsp *a, const struct isis_lsp *b) { - dict_t *dict; - - dict = dict_create(DICTCOUNT_T_MAX, (dict_comp_t)lsp_id_cmp); - - return dict; + return memcmp(a->hdr.lsp_id, b->hdr.lsp_id, sizeof(a->hdr.lsp_id)); } -struct isis_lsp *lsp_search(uint8_t *id, dict_t *lspdb) +void lsp_db_init(struct lspdb_head *head) { - dnode_t *node; - -#ifdef EXTREME_DEBUG - dnode_t *dn; + lspdb_init(head); +} - zlog_debug("searching db"); - for (dn = dict_first(lspdb); dn; dn = dict_next(lspdb, dn)) { - zlog_debug("%s\t%pX", - rawlspid_print((uint8_t *)dnode_getkey(dn)), - dnode_get(dn)); - } -#endif /* EXTREME DEBUG */ +void lsp_db_fini(struct lspdb_head *head) +{ + struct isis_lsp *lsp; - node = dict_lookup(lspdb, id); + while ((lsp = lspdb_pop(head))) + lsp_destroy(lsp); + lspdb_fini(head); +} - if (node) - return (struct isis_lsp *)dnode_get(node); +struct isis_lsp *lsp_search(struct lspdb_head *head, const uint8_t *id) +{ + struct isis_lsp searchfor; + memcpy(searchfor.hdr.lsp_id, id, sizeof(searchfor.hdr.lsp_id)); - return NULL; + return lspdb_find(head, &searchfor); } static void lsp_clear_data(struct isis_lsp *lsp) @@ -109,7 +105,7 @@ static void lsp_clear_data(struct isis_lsp *lsp) lsp->tlvs = NULL; } -static void lsp_remove_frags(struct list *frags, dict_t *lspdb); +static void lsp_remove_frags(struct lspdb_head *head, struct list *frags); static void lsp_destroy(struct isis_lsp *lsp) { @@ -128,8 +124,8 @@ static void lsp_destroy(struct isis_lsp *lsp) if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) { if (lsp->lspu.frags) { - lsp_remove_frags(lsp->lspu.frags, - lsp->area->lspdb[lsp->level - 1]); + lsp_remove_frags(&lsp->area->lspdb[lsp->level - 1], + lsp->lspu.frags); list_delete(&lsp->lspu.frags); } } else { @@ -148,56 +144,34 @@ static void lsp_destroy(struct isis_lsp *lsp) XFREE(MTYPE_ISIS_LSP, lsp); } -void lsp_db_destroy(dict_t *lspdb) -{ - dnode_t *dnode, *next; - struct isis_lsp *lsp; - - dnode = dict_first(lspdb); - while (dnode) { - next = dict_next(lspdb, dnode); - lsp = dnode_get(dnode); - lsp_destroy(lsp); - dict_delete_free(lspdb, dnode); - dnode = next; - } - - dict_free(lspdb); - - return; -} - /* * Remove all the frags belonging to the given lsp */ -static void lsp_remove_frags(struct list *frags, dict_t *lspdb) +static void lsp_remove_frags(struct lspdb_head *head, struct list *frags) { - dnode_t *dnode; struct listnode *lnode, *lnnode; struct isis_lsp *lsp; for (ALL_LIST_ELEMENTS(frags, lnode, lnnode, lsp)) { - dnode = dict_lookup(lspdb, lsp->hdr.lsp_id); + lsp = lsp_search(head, lsp->hdr.lsp_id); + lspdb_del(head, lsp); lsp_destroy(lsp); - dnode_destroy(dict_delete(lspdb, dnode)); } } -void lsp_search_and_destroy(uint8_t *id, dict_t *lspdb) +void lsp_search_and_destroy(struct lspdb_head *head, const uint8_t *id) { - dnode_t *node; struct isis_lsp *lsp; - node = dict_lookup(lspdb, id); - if (node) { - node = dict_delete(lspdb, node); - lsp = dnode_get(node); + lsp = lsp_search(head, id); + if (lsp) { + lspdb_del(head, lsp); /* * If this is a zero lsp, remove all the frags now */ if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0) { if (lsp->lspu.frags) - lsp_remove_frags(lsp->lspu.frags, lspdb); + lsp_remove_frags(head, lsp->lspu.frags); } else { /* * else just remove this frag, from the zero lsps' frag @@ -209,7 +183,6 @@ void lsp_search_and_destroy(uint8_t *id, dict_t *lspdb) lsp); } lsp_destroy(lsp); - dnode_destroy(node); } } @@ -514,7 +487,7 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, memcpy(lspid, lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lspid) = 0; - lsp0 = lsp_search(lspid, area->lspdb[level - 1]); + lsp0 = lsp_search(&area->lspdb[level - 1], lspid); if (lsp0) lsp_link_fragment(lsp, lsp0); } @@ -582,9 +555,9 @@ struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, return lsp; } -void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb) +void lsp_insert(struct lspdb_head *head, struct isis_lsp *lsp) { - dict_alloc_insert(lspdb, lsp->hdr.lsp_id, lsp); + lspdb_add(head, lsp); if (lsp->hdr.seqno) isis_spf_schedule(lsp->area, lsp->level); } @@ -592,13 +565,16 @@ void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb) /* * Build a list of LSPs with non-zero ht bounded by start and stop ids */ -void lsp_build_list_nonzero_ht(uint8_t *start_id, uint8_t *stop_id, - struct list *list, dict_t *lspdb) +void lsp_build_list_nonzero_ht(struct lspdb_head *head, const uint8_t *start_id, + const uint8_t *stop_id, struct list *list) { - for (dnode_t *curr = dict_lower_bound(lspdb, start_id); - curr; curr = dict_next(lspdb, curr)) { - struct isis_lsp *lsp = curr->dict_data; + struct isis_lsp searchfor; + struct isis_lsp *lsp, *start; + + memcpy(&searchfor.hdr.lsp_id, start_id, sizeof(searchfor.hdr.lsp_id)); + start = lspdb_find_gteq(head, &searchfor); + for_each_from (lspdb, head, lsp, start) { if (memcmp(lsp->hdr.lsp_id, stop_id, ISIS_SYS_ID_LEN + 2) > 0) break; @@ -699,26 +675,20 @@ void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost) } /* print all the lsps info in the local lspdb */ -int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost) +int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail, + char dynhost) { - - dnode_t *node = dict_first(lspdb), *next; + struct isis_lsp *lsp; int lsp_count = 0; if (detail == ISIS_UI_LEVEL_BRIEF) { - while (node != NULL) { - /* I think it is unnecessary, so I comment it out */ - /* dict_contains (lspdb, node); */ - next = dict_next(lspdb, node); - lsp_print(dnode_get(node), vty, dynhost); - node = next; + for_each (lspdb, head, lsp) { + lsp_print(lsp, vty, dynhost); lsp_count++; } } else if (detail == ISIS_UI_LEVEL_DETAIL) { - while (node != NULL) { - next = dict_next(lspdb, node); - lsp_print_detail(dnode_get(node), vty, dynhost); - node = next; + for_each (lspdb, head, lsp) { + lsp_print_detail(lsp, vty, dynhost); lsp_count++; } } @@ -847,7 +817,7 @@ static struct isis_lsp *lsp_next_frag(uint8_t frag_num, struct isis_lsp *lsp0, memcpy(frag_id, lsp0->hdr.lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(frag_id) = frag_num; - lsp = lsp_search(frag_id, area->lspdb[level - 1]); + lsp = lsp_search(&area->lspdb[level - 1], frag_id); if (lsp) { lsp_clear_data(lsp); if (!lsp->lspu.zero_lsp) @@ -860,7 +830,7 @@ static struct isis_lsp *lsp_next_frag(uint8_t frag_num, struct isis_lsp *lsp0, area->attached_bit), 0, lsp0, level); lsp->own_lsp = 1; - lsp_insert(lsp, area->lspdb[level - 1]); + lsp_insert(&area->lspdb[level - 1], lsp); return lsp; } @@ -1228,12 +1198,12 @@ int lsp_generate(struct isis_area *area, int level) memcpy(&lspid, isis->sysid, ISIS_SYS_ID_LEN); /* only builds the lsp if the area shares the level */ - oldlsp = lsp_search(lspid, area->lspdb[level - 1]); + oldlsp = lsp_search(&area->lspdb[level - 1], lspid); if (oldlsp) { /* FIXME: we should actually initiate a purge */ seq_num = oldlsp->hdr.seqno; - lsp_search_and_destroy(oldlsp->hdr.lsp_id, - area->lspdb[level - 1]); + lsp_search_and_destroy(&area->lspdb[level - 1], + oldlsp->hdr.lsp_id); } rem_lifetime = lsp_rem_lifetime(area, level); newlsp = @@ -1243,7 +1213,7 @@ int lsp_generate(struct isis_area *area, int level) newlsp->area = area; newlsp->own_lsp = 1; - lsp_insert(newlsp, area->lspdb[level - 1]); + lsp_insert(&area->lspdb[level - 1], newlsp); /* build_lsp_data (newlsp, area); */ lsp_build(newlsp, area); /* time to calculate our checksum */ @@ -1288,7 +1258,7 @@ int lsp_generate(struct isis_area *area, int level) */ static int lsp_regenerate(struct isis_area *area, int level) { - dict_t *lspdb; + struct lspdb_head *head; struct isis_lsp *lsp, *frag; struct listnode *node; uint8_t lspid[ISIS_SYS_ID_LEN + 2]; @@ -1297,12 +1267,12 @@ static int lsp_regenerate(struct isis_area *area, int level) if ((area == NULL) || (area->is_type & level) != level) return ISIS_ERROR; - lspdb = area->lspdb[level - 1]; + head = &area->lspdb[level - 1]; memset(lspid, 0, ISIS_SYS_ID_LEN + 2); memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN); - lsp = lsp_search(lspid, lspdb); + lsp = lsp_search(head, lspid); if (!lsp) { flog_err(EC_LIB_DEVELOPMENT, @@ -1445,7 +1415,7 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level, continue; } - lsp = lsp_search(id, area->lspdb[lvl - 1]); + lsp = lsp_search(&area->lspdb[lvl - 1], id); if (!lsp) { sched_debug( "ISIS (%s): We do not have any LSPs to regenerate, nothing todo.", @@ -1597,7 +1567,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, int lsp_generate_pseudo(struct isis_circuit *circuit, int level) { - dict_t *lspdb = circuit->area->lspdb[level - 1]; + struct lspdb_head *head = &circuit->area->lspdb[level - 1]; struct isis_lsp *lsp; uint8_t lsp_id[ISIS_SYS_ID_LEN + 2]; uint16_t rem_lifetime, refresh_time; @@ -1615,7 +1585,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) /* * If for some reason have a pseudo LSP in the db already -> regenerate */ - if (lsp_search(lsp_id, lspdb)) + if (lsp_search(head, lsp_id)) return lsp_regenerate_schedule_pseudo(circuit, level); rem_lifetime = lsp_rem_lifetime(circuit->area, level); @@ -1628,7 +1598,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) lsp_build_pseudo(lsp, circuit, level); lsp_pack_pdu(lsp); lsp->own_lsp = 1; - lsp_insert(lsp, lspdb); + lsp_insert(head, lsp); lsp_flood(lsp, NULL); refresh_time = lsp_refresh_time(lsp, rem_lifetime); @@ -1659,7 +1629,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) { - dict_t *lspdb = circuit->area->lspdb[level - 1]; + struct lspdb_head *head = &circuit->area->lspdb[level - 1]; struct isis_lsp *lsp; uint8_t lsp_id[ISIS_SYS_ID_LEN + 2]; uint16_t rem_lifetime, refresh_time; @@ -1674,7 +1644,7 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; LSP_FRAGMENT(lsp_id) = 0; - lsp = lsp_search(lsp_id, lspdb); + lsp = lsp_search(head, lsp_id); if (!lsp) { flog_err(EC_LIB_DEVELOPMENT, @@ -1813,7 +1783,7 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) continue; } - lsp = lsp_search(lsp_id, circuit->area->lspdb[lvl - 1]); + lsp = lsp_search(&circuit->area->lspdb[lvl - 1], lsp_id); if (!lsp) { sched_debug( "ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.", @@ -1869,7 +1839,6 @@ int lsp_tick(struct thread *thread) { struct isis_area *area; struct isis_lsp *lsp; - dnode_t *dnode, *dnode_next; int level; uint16_t rem_lifetime; bool fabricd_sync_incomplete = false; @@ -1885,83 +1854,69 @@ int lsp_tick(struct thread *thread) * Remove LSPs which have aged out */ for (level = 0; level < ISIS_LEVELS; level++) { - if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) { - for (dnode = dict_first(area->lspdb[level]); - dnode != NULL; dnode = dnode_next) { - dnode_next = - dict_next(area->lspdb[level], dnode); - lsp = dnode_get(dnode); - - /* - * The lsp rem_lifetime is kept at 0 for MaxAge - * or - * ZeroAgeLifetime depending on explicit purge - * or - * natural age out. So schedule spf only once - * when - * the first time rem_lifetime becomes 0. - */ - rem_lifetime = lsp->hdr.rem_lifetime; - lsp_set_time(lsp); - - /* - * Schedule may run spf which should be done - * only after - * the lsp rem_lifetime becomes 0 for the first - * time. - * ISO 10589 - 7.3.16.4 first paragraph. - */ - if (rem_lifetime == 1 && lsp->hdr.seqno != 0) { - /* 7.3.16.4 a) set SRM flags on all */ - /* 7.3.16.4 b) retain only the header */ - if (lsp->area->purge_originator) - lsp_purge(lsp, lsp->level, NULL); - else - lsp_flood(lsp, NULL); - /* 7.3.16.4 c) record the time to purge - * FIXME */ - isis_spf_schedule(lsp->area, lsp->level); - } + struct isis_lsp *next = lspdb_first(&area->lspdb[level]); + for_each_from (lspdb, &area->lspdb[level], lsp, next) { + /* + * The lsp rem_lifetime is kept at 0 for MaxAge + * or + * ZeroAgeLifetime depending on explicit purge + * or + * natural age out. So schedule spf only once + * when + * the first time rem_lifetime becomes 0. + */ + rem_lifetime = lsp->hdr.rem_lifetime; + lsp_set_time(lsp); - if (lsp->age_out == 0) { - zlog_debug( - "ISIS-Upd (%s): L%u LSP %s seq " - "0x%08" PRIx32 " aged out", - area->area_tag, lsp->level, - rawlspid_print(lsp->hdr.lsp_id), - lsp->hdr.seqno); - - /* if we're aging out fragment 0, - * lsp_destroy() below will delete all - * other fragments too, so we need to - * skip over those - */ - while (!LSP_FRAGMENT(lsp->hdr.lsp_id) - && dnode_next) { - struct isis_lsp *nextlsp; - - nextlsp = dnode_get(dnode_next); - if (memcmp(nextlsp->hdr.lsp_id, - lsp->hdr.lsp_id, - ISIS_SYS_ID_LEN + 1)) - break; - - dnode_next = dict_next( - area->lspdb[level], - dnode_next); - } + /* + * Schedule may run spf which should be done + * only after + * the lsp rem_lifetime becomes 0 for the first + * time. + * ISO 10589 - 7.3.16.4 first paragraph. + */ + if (rem_lifetime == 1 && lsp->hdr.seqno != 0) { + /* 7.3.16.4 a) set SRM flags on all */ + /* 7.3.16.4 b) retain only the header */ + if (lsp->area->purge_originator) + lsp_purge(lsp, lsp->level, NULL); + else + lsp_flood(lsp, NULL); + /* 7.3.16.4 c) record the time to purge + * FIXME */ + isis_spf_schedule(lsp->area, lsp->level); + } - lsp_destroy(lsp); - lsp = NULL; - dict_delete_free(area->lspdb[level], - dnode); - } + if (lsp->age_out == 0) { + zlog_debug( + "ISIS-Upd (%s): L%u LSP %s seq " + "0x%08" PRIx32 " aged out", + area->area_tag, lsp->level, + rawlspid_print(lsp->hdr.lsp_id), + lsp->hdr.seqno); + + /* if we're aging out fragment 0, lsp_destroy() + * below will delete all other fragments too, + * so we need to skip over those + */ + if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) + while (next && + !memcmp(next->hdr.lsp_id, + lsp->hdr.lsp_id, + ISIS_SYS_ID_LEN + 1)) + next = lspdb_next( + &area->lspdb[level], + next); + + lspdb_del(&area->lspdb[level], lsp); + lsp_destroy(lsp); + lsp = NULL; + } - if (fabricd_init_c && lsp) { - fabricd_sync_incomplete |= - ISIS_CHECK_FLAG(lsp->SSNflags, - fabricd_init_c); - } + if (fabricd_init_c && lsp) { + fabricd_sync_incomplete |= + ISIS_CHECK_FLAG(lsp->SSNflags, + fabricd_init_c); } } } @@ -1979,7 +1934,7 @@ void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level) { struct isis_lsp *lsp; - lsp = lsp_search(id, circuit->area->lspdb[level - 1]); + lsp = lsp_search(&circuit->area->lspdb[level - 1], id); if (!lsp) return; @@ -2012,7 +1967,7 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, lsp_pack_pdu(lsp); - lsp_insert(lsp, area->lspdb[lsp->level - 1]); + lsp_insert(&area->lspdb[lsp->level - 1], lsp); lsp_flood(lsp, NULL); return; diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index e6ea0b4ed..4cbca5d51 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -24,13 +24,18 @@ #ifndef _ZEBRA_ISIS_LSP_H #define _ZEBRA_ISIS_LSP_H +#include "lib/typesafe.h" #include "isisd/isis_pdu.h" +PREDECL_RBTREE_UNIQ(lspdb) + /* Structure for isis_lsp, this structure will only support the fixed * System ID (Currently 6) (atleast for now). In order to support more * We will have to split the header into two parts, and for readability * sake it should better be avoided */ struct isis_lsp { + struct lspdb_item dbe; + struct isis_lsp_hdr hdr; struct stream *pdu; /* full pdu lsp */ union { @@ -54,8 +59,11 @@ struct isis_lsp { bool flooding_circuit_scoped; }; -dict_t *lsp_db_init(void); -void lsp_db_destroy(dict_t *lspdb); +extern int lspdb_compare(const struct isis_lsp *a, const struct isis_lsp *b); +DECLARE_RBTREE_UNIQ(lspdb, struct isis_lsp, dbe, lspdb_compare) + +void lsp_db_init(struct lspdb_head *head); +void lsp_db_fini(struct lspdb_head *head); int lsp_tick(struct thread *thread); int lsp_generate(struct isis_area *area, int level); @@ -76,14 +84,16 @@ struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr, struct isis_tlvs *tlvs, struct stream *stream, struct isis_lsp *lsp0, struct isis_area *area, int level); -void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb); -struct isis_lsp *lsp_search(uint8_t *id, dict_t *lspdb); +void lsp_insert(struct lspdb_head *head, struct isis_lsp *lsp); +struct isis_lsp *lsp_search(struct lspdb_head *head, const uint8_t *id); -void lsp_build_list(uint8_t *start_id, uint8_t *stop_id, uint8_t num_lsps, - struct list *list, dict_t *lspdb); -void lsp_build_list_nonzero_ht(uint8_t *start_id, uint8_t *stop_id, - struct list *list, dict_t *lspdb); -void lsp_search_and_destroy(uint8_t *id, dict_t *lspdb); +void lsp_build_list(struct lspdb_head *head, const uint8_t *start_id, + const uint8_t *stop_id, uint8_t num_lsps, + struct list *list); +void lsp_build_list_nonzero_ht(struct lspdb_head *head, + const uint8_t *start_id, + const uint8_t *stop_id, struct list *list); +void lsp_search_and_destroy(struct lspdb_head *head, const uint8_t *id); void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level); void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, struct isis_area *area); @@ -108,7 +118,8 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno); void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag); void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost); void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost); -int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost); +int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail, + char dynhost); /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index e74a9baad..48ae76017 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -41,7 +41,6 @@ #include "qobj.h" #include "libfrr.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 2ce68262e..0a42adea3 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -29,7 +29,6 @@ #include "if.h" #include "command.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index 7838ca6d3..d5cdec154 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -25,7 +25,6 @@ #include "libfrr.h" #include "linklist.h" #include "log.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 418b59da4..9c633117b 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -36,7 +36,6 @@ #include "md5.h" #include "lib_errors.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" @@ -960,7 +959,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, /* Find the LSP in our database and compare it to this Link State header */ struct isis_lsp *lsp = - lsp_search(hdr.lsp_id, circuit->area->lspdb[level - 1]); + lsp_search(&circuit->area->lspdb[level - 1], hdr.lsp_id); int comp = 0; if (lsp) comp = lsp_compare(circuit->area->area_tag, lsp, hdr.seqno, @@ -1187,7 +1186,7 @@ dontcheckadj: memcpy(lspid, hdr.lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lspid) = 0; lsp0 = lsp_search( - lspid, circuit->area->lspdb[level - 1]); + &circuit->area->lspdb[level - 1], lspid); if (!lsp0) { zlog_debug( "Got lsp frag, while zero lsp not in database"); @@ -1200,8 +1199,8 @@ dontcheckadj: &hdr, tlvs, circuit->rcv_stream, lsp0, circuit->area, level); tlvs = NULL; - lsp_insert(lsp, - circuit->area->lspdb[level - 1]); + lsp_insert(&circuit->area->lspdb[level - 1], + lsp); } else /* exists, so we overwrite */ { lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream, @@ -1417,7 +1416,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, for (struct isis_lsp_entry *entry = entry_head; entry; entry = entry->next) { struct isis_lsp *lsp = - lsp_search(entry->id, circuit->area->lspdb[level - 1]); + lsp_search(&circuit->area->lspdb[level - 1], entry->id); bool own_lsp = !memcmp(entry->id, isis->sysid, ISIS_SYS_ID_LEN); if (lsp) { /* 7.3.15.2 b) 1) is this LSP newer */ @@ -1468,8 +1467,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lspid) = 0; lsp0 = lsp_search( - lspid, - circuit->area->lspdb[level - 1]); + &circuit->area->lspdb[level - 1], + lspid); if (!lsp0) { zlog_debug("Got lsp frag in snp, while zero not in database"); continue; @@ -1478,8 +1477,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, lsp = lsp_new(circuit->area, entry->id, entry->rem_lifetime, 0, 0, entry->checksum, lsp0, level); - lsp_insert(lsp, - circuit->area->lspdb[level - 1]); + lsp_insert(&circuit->area->lspdb[level - 1], + lsp); lsp_set_all_srmflags(lsp, false); ISIS_SET_FLAG(lsp->SSNflags, circuit); @@ -1496,8 +1495,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, * start_lsp_id and stop_lsp_id */ struct list *lsp_list = list_new(); - lsp_build_list_nonzero_ht(start_lsp_id, stop_lsp_id, lsp_list, - circuit->area->lspdb[level - 1]); + lsp_build_list_nonzero_ht(&circuit->area->lspdb[level - 1], + start_lsp_id, stop_lsp_id, lsp_list); /* Fixme: Find a better solution */ struct listnode *node, *nnode; @@ -2041,8 +2040,7 @@ static uint16_t get_max_lsp_count(uint16_t size) int send_csnp(struct isis_circuit *circuit, int level) { - if (circuit->area->lspdb[level - 1] == NULL - || dict_count(circuit->area->lspdb[level - 1]) == 0) + if (lspdb_count(&circuit->area->lspdb[level - 1]) == 0) return ISIS_OK; uint8_t pdu_type = (level == ISIS_LEVEL1) ? L1_COMPLETE_SEQ_NUM @@ -2095,7 +2093,7 @@ int send_csnp(struct isis_circuit *circuit, int level) struct isis_lsp *last_lsp; isis_tlvs_add_csnp_entries(tlvs, start, stop, num_lsps, - circuit->area->lspdb[level - 1], + &circuit->area->lspdb[level - 1], &last_lsp); /* * Update the stop lsp_id before encoding this CSNP. @@ -2216,8 +2214,7 @@ static int send_psnp(int level, struct isis_circuit *circuit) && circuit->u.bc.is_dr[level - 1]) return ISIS_OK; - if (circuit->area->lspdb[level - 1] == NULL - || dict_count(circuit->area->lspdb[level - 1]) == 0) + if (lspdb_count(&circuit->area->lspdb[level - 1]) == 0) return ISIS_OK; if (!circuit->snd_stream) @@ -2255,16 +2252,13 @@ static int send_psnp(int level, struct isis_circuit *circuit) get_max_lsp_count(STREAM_WRITEABLE(circuit->snd_stream)); while (1) { + struct isis_lsp *lsp; + tlvs = isis_alloc_tlvs(); if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) isis_tlvs_add_auth(tlvs, passwd); - for (dnode_t *dnode = - dict_first(circuit->area->lspdb[level - 1]); - dnode; dnode = dict_next(circuit->area->lspdb[level - 1], - dnode)) { - struct isis_lsp *lsp = dnode_get(dnode); - + for_each (lspdb, &circuit->area->lspdb[level - 1], lsp) { if (ISIS_CHECK_FLAG(lsp->SSNflags, circuit)) isis_tlvs_add_lsp_entry(tlvs, lsp); diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 2f6526bc5..824acd0ff 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -33,7 +33,6 @@ #include "if.h" #include "lib_errors.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_circuit.h" diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 9047707bf..dc23e8ea4 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -32,7 +32,6 @@ #include "vty.h" #include "srcdest_table.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 1439a4229..82005c911 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -38,7 +38,6 @@ #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" -#include "dict.h" #include "isisd.h" #include "isis_misc.h" #include "isis_adjacency.h" diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index 3c2cf7b3f..d63676256 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -37,7 +37,6 @@ #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" -#include "dict.h" #include "isisd.h" #include "isis_misc.h" #include "isis_adjacency.h" diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 18eb857ec..a28220eb2 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -39,7 +39,6 @@ #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" -#include "dict.h" #include "isisd.h" #include "isis_misc.h" #include "isis_adjacency.h" @@ -313,7 +312,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, memcpy(lspid, sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(lspid) = 0; LSP_FRAGMENT(lspid) = 0; - lsp = lsp_search(lspid, area->lspdb[level - 1]); + lsp = lsp_search(&area->lspdb[level - 1], lspid); if (lsp && lsp->hdr.rem_lifetime != 0) return lsp; return NULL; @@ -870,10 +869,8 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, [spftree->level - 1], parent); lsp = lsp_search( - lsp_id, - spftree->area - ->lspdb[spftree->level - - 1]); + &spftree->area->lspdb[spftree->level- 1], + lsp_id); if (lsp == NULL || lsp->hdr.rem_lifetime == 0) zlog_warn( @@ -923,8 +920,8 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, continue; } lsp = lsp_search( - lsp_id, - spftree->area->lspdb[spftree->level - 1]); + &spftree->area->lspdb[spftree->level - 1], + lsp_id); if (lsp == NULL || lsp->hdr.rem_lifetime == 0) { zlog_warn( "ISIS-Spf: No lsp (%p) found from root " diff --git a/isisd/isis_spf_private.h b/isisd/isis_spf_private.h index 3a05df3f1..3a2a52afa 100644 --- a/isisd/isis_spf_private.h +++ b/isisd/isis_spf_private.h @@ -347,8 +347,8 @@ static struct isis_lsp *lsp_for_vertex(struct isis_spftree *spftree, memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lsp_id) = 0; - dict_t *lspdb = spftree->area->lspdb[spftree->level - 1]; - struct isis_lsp *lsp = lsp_search(lsp_id, lspdb); + struct lspdb_head *lspdb = &spftree->area->lspdb[spftree->level - 1]; + struct isis_lsp *lsp = lsp_search(lspdb, lsp_id); if (lsp && lsp->hdr.rem_lifetime != 0) return lsp; diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 2f18e0356..4ea6c2c60 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -43,7 +43,6 @@ #include "network.h" #include "sbuf.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index fbb1e5714..bc9b51473 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -3522,26 +3522,24 @@ void isis_tlvs_add_lsp_entry(struct isis_tlvs *tlvs, struct isis_lsp *lsp) void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id, uint8_t *stop_id, uint16_t num_lsps, - dict_t *lspdb, struct isis_lsp **last_lsp) + struct lspdb_head *head, + struct isis_lsp **last_lsp) { - dnode_t *first = dict_lower_bound(lspdb, start_id); + struct isis_lsp searchfor; + struct isis_lsp *first, *lsp; + + memcpy(&searchfor.hdr.lsp_id, start_id, sizeof(searchfor.hdr.lsp_id)); + first = lspdb_find_gteq(head, &searchfor); if (!first) return; - dnode_t *last = dict_upper_bound(lspdb, stop_id); - dnode_t *curr = first; - - isis_tlvs_add_lsp_entry(tlvs, first->dict_data); - *last_lsp = first->dict_data; - - while (curr) { - curr = dict_next(lspdb, curr); - if (curr) { - isis_tlvs_add_lsp_entry(tlvs, curr->dict_data); - *last_lsp = curr->dict_data; - } - if (curr == last || tlvs->lsp_entries.count == num_lsps) + for_each_from (lspdb, head, lsp, first) { + if (memcmp(lsp->hdr.lsp_id, stop_id, sizeof(lsp->hdr.lsp_id)) + > 0 || tlvs->lsp_entries.count == num_lsps) break; + + isis_tlvs_add_lsp_entry(tlvs, lsp); + *last_lsp = lsp; } } diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index fce30d4ee..4954d791d 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -25,8 +25,8 @@ #include "openbsd-tree.h" #include "prefix.h" -#include "isisd/dict.h" +struct lspdb_head; struct isis_subtlvs; struct isis_area_address; @@ -355,7 +355,8 @@ bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa); void isis_tlvs_add_lsp_entry(struct isis_tlvs *tlvs, struct isis_lsp *lsp); void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id, uint8_t *stop_id, uint16_t num_lsps, - dict_t *lspdb, struct isis_lsp **last_lsp); + struct lspdb_head *lspdb, + struct isis_lsp **last_lsp); void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs, const char *hostname); void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs, diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index 270dcae7d..6f46e6bec 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -27,7 +27,6 @@ #include "isisd/isisd.h" #include "isisd/isis_memory.h" #include "isisd/isis_flags.h" -#include "dict.h" #include "isisd/isis_circuit.h" #include "isisd/isis_lsp.h" #include "isisd/isis_misc.h" diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index b2c0440de..7f2061692 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -161,13 +161,14 @@ DEFUN (show_lsp_flooding, struct isis_area *area; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - dict_t *lspdb = area->lspdb[ISIS_LEVEL2 - 1]; + struct lspdb_head *head = &area->lspdb[ISIS_LEVEL2 - 1]; + struct isis_lsp *lsp; vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); if (lspid) { - struct isis_lsp *lsp = lsp_for_arg(lspid, lspdb); + struct isis_lsp *lsp = lsp_for_arg(head, lspid); if (lsp) lsp_print_flooding(vty, lsp); @@ -175,9 +176,8 @@ DEFUN (show_lsp_flooding, continue; } - for (dnode_t *dnode = dict_first(lspdb); dnode; - dnode = dict_next(lspdb, dnode)) { - lsp_print_flooding(vty, dnode_get(dnode)); + for_each (lspdb, head, lsp) { + lsp_print_flooding(vty, lsp); vty_out(vty, "\n"); } } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 451caed78..904ab99c7 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -37,7 +37,6 @@ #include "vrf.h" #include "libfrr.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" diff --git a/isisd/isisd.c b/isisd/isisd.c index e649b2bac..07be68d9a 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -38,7 +38,6 @@ #include "spf_backoff.h" #include "lib/northbound_cli.h" -#include "isisd/dict.h" #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_flags.h" @@ -121,12 +120,10 @@ struct isis_area *isis_area_create(const char *area_tag) /* * intialize the databases */ - if (area->is_type & IS_LEVEL_1) { - area->lspdb[0] = lsp_db_init(); - } - if (area->is_type & IS_LEVEL_2) { - area->lspdb[1] = lsp_db_init(); - } + if (area->is_type & IS_LEVEL_1) + lsp_db_init(&area->lspdb[0]); + if (area->is_type & IS_LEVEL_2) + lsp_db_init(&area->lspdb[1]); spftree_area_init(area); @@ -271,14 +268,8 @@ int isis_area_destroy(const char *area_tag) list_delete(&area->circuit_list); } - if (area->lspdb[0] != NULL) { - lsp_db_destroy(area->lspdb[0]); - area->lspdb[0] = NULL; - } - if (area->lspdb[1] != NULL) { - lsp_db_destroy(area->lspdb[1]); - area->lspdb[1] = NULL; - } + lsp_db_fini(&area->lspdb[0]); + lsp_db_fini(&area->lspdb[1]); /* invalidate and verify to delete all routes from zebra */ isis_area_invalidate_routes(area, ISIS_LEVEL1 & ISIS_LEVEL2); @@ -1344,7 +1335,7 @@ DEFUN (show_isis_summary, return CMD_SUCCESS; } -struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb) +struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv) { char sysid[255] = {0}; uint8_t number[3]; @@ -1392,13 +1383,13 @@ struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb) * hostname.<pseudo-id>-<fragment> */ if (sysid2buff(lspid, sysid)) { - lsp = lsp_search(lspid, lspdb); + lsp = lsp_search(head, lspid); } else if ((dynhn = dynhn_find_by_name(sysid))) { memcpy(lspid, dynhn->id, ISIS_SYS_ID_LEN); - lsp = lsp_search(lspid, lspdb); + lsp = lsp_search(head, lspid); } else if (strncmp(cmd_hostname_get(), sysid, 15) == 0) { memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN); - lsp = lsp_search(lspid, lspdb); + lsp = lsp_search(head, lspid); } return lsp; @@ -1435,9 +1426,8 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) area->area_tag ? area->area_tag : "null"); for (level = 0; level < ISIS_LEVELS; level++) { - if (area->lspdb[level] - && dict_count(area->lspdb[level]) > 0) { - lsp = lsp_for_arg(argv, area->lspdb[level]); + if (lspdb_count(&area->lspdb[level]) > 0) { + lsp = lsp_for_arg(&area->lspdb[level], argv); if (lsp != NULL || argv == NULL) { vty_out(vty, @@ -1459,7 +1449,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) area->dynhostname); } else if (argv == NULL) { lsp_count = lsp_print_all( - vty, area->lspdb[level], + vty, &area->lspdb[level], ui_level, area->dynhostname); vty_out(vty, " %u LSPs\n\n", @@ -1699,10 +1689,7 @@ static void area_resign_level(struct isis_area *area, int level) isis_area_invalidate_routes(area, level); isis_area_verify_routes(area); - if (area->lspdb[level - 1]) { - lsp_db_destroy(area->lspdb[level - 1]); - area->lspdb[level - 1] = NULL; - } + lsp_db_fini(&area->lspdb[level - 1]); for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) { if (area->spftree[tree][level - 1]) { @@ -1738,8 +1725,7 @@ void isis_area_is_type_set(struct isis_area *area, int is_type) if (is_type == IS_LEVEL_2) area_resign_level(area, IS_LEVEL_1); - if (area->lspdb[1] == NULL) - area->lspdb[1] = lsp_db_init(); + lsp_db_init(&area->lspdb[1]); break; case IS_LEVEL_1_AND_2: @@ -1753,8 +1739,7 @@ void isis_area_is_type_set(struct isis_area *area, int is_type) if (is_type == IS_LEVEL_1) area_resign_level(area, IS_LEVEL_2); - if (area->lspdb[0] == NULL) - area->lspdb[0] = lsp_db_init(); + lsp_db_init(&area->lspdb[0]); break; default: diff --git a/isisd/isisd.h b/isisd/isisd.h index 758bcb9ad..f8486ae0d 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -31,7 +31,7 @@ #include "isisd/isis_pdu_counter.h" #include "isisd/isis_circuit.h" #include "isis_flags.h" -#include "dict.h" +#include "isis_lsp.h" #include "isis_memory.h" #include "qobj.h" @@ -107,7 +107,7 @@ enum isis_metric_style { struct isis_area { struct isis *isis; /* back pointer */ - dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ + struct lspdb_head lspdb[ISIS_LEVELS]; /* link-state dbs */ struct isis_spftree *spftree[SPFTREE_COUNT][ISIS_LEVELS]; #define DEFAULT_LSP_MTU 1497 unsigned int lsp_mtu; /* Size of LSPs to generate */ @@ -197,7 +197,7 @@ struct isis_area *isis_area_lookup(const char *); int isis_area_get(struct vty *vty, const char *area_tag); int isis_area_destroy(const char *area_tag); void print_debug(struct vty *, int, int); -struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb); +struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv); void isis_area_invalidate_routes(struct isis_area *area, int levels); void isis_area_verify_routes(struct isis_area *area); diff --git a/isisd/subdir.am b/isisd/subdir.am index 4371d5993..bae56309c 100644 --- a/isisd/subdir.am +++ b/isisd/subdir.am @@ -25,7 +25,6 @@ dist_examples_DATA += isisd/fabricd.conf.sample endif noinst_HEADERS += \ - isisd/dict.h \ isisd/isis_adjacency.h \ isisd/isis_bfd.h \ isisd/isis_circuit.h \ @@ -61,7 +60,6 @@ noinst_HEADERS += \ # end LIBISIS_SOURCES = \ - isisd/dict.c \ isisd/isis_adjacency.c \ isisd/isis_bfd.c \ isisd/isis_circuit.c \ |