/* lpm_init: * Constructs a fresh tree ready for use by the other functions. */ struct lpm_tree* lpm_init() { /* Build empty internal node, and attach it to new tree. */ struct internal_node* node = create_internal_node(); struct lpm_tree* tree = (struct lpm_tree*)malloc(sizeof(struct lpm_tree)); DEBUG("## Created tree %p\n", (void*)tree); tree->head = node; return tree; }
/* * This function used internally; see lpm_insert(). */ void insert(struct sockaddr_storage *prefix, uint32_t nm, struct internal_node* n) { uint8_t b = 0; uint8_t depth = 0; struct internal_node* parent; struct internal_node* next = n; if (prefix->ss_family == AF_INET6) { b = MAX_BITS6; } else if (prefix->ss_family == AF_INET) { b = MAX_BITS4; } /* First, find the correct location for the prefix. Burrow down to the correct depth, potentially creating internal nodes as I go. */ do { n = next; b--; depth++; parent = (struct internal_node*)n; bool v_bit = test_v_bit(prefix, b); /* Determine which direction to descend. */ if (v_bit) { if (n->r == NULL) { n->r = create_internal_node(); } next = n->r; } else { if (n->l == NULL) { n->l = create_internal_node(); } next = n->l; } } while (depth < nm); if (next == NULL) { /* The easy case. */ struct data_node* node = create_data_node(prefix, nm); bool v_bit = test_v_bit(prefix, b); if (v_bit) { parent->r = (struct internal_node*)node; } else { parent->l = (struct internal_node*)node; } } else if (next->type == INT_NODE) { /* In this case, we've descended as far as we can. Attach the prefix here. */ bool v_bit = test_v_bit(prefix, b); struct data_node* newnode = create_data_node(prefix, nm); newnode->l = next->l; newnode->r = next->r; if (v_bit) { n->r = (struct internal_node*)newnode; } else { n->l = (struct internal_node*)newnode; } DEBUG("## Freeing %p\n", (void*)next); free(next); } }
/* * This function used internally; see lpm_insert(). */ void insert(uint32_t prefix, uint32_t nm, struct internal_node* n, uint32_t network_owner) { uint8_t b = MAX_BITS; uint8_t depth = 0; struct internal_node* parent; struct internal_node* next = n; /* First, find the correct location for the prefix. Burrow down to the correct depth, potentially creating internal nodes as I go. */ do { n = next; b--; depth++; parent = (struct internal_node*)n; uint32_t v_bit = prefix & ((uint32_t)pow(2, b)); /* Determine which direction to descend. */ if (v_bit) { if (n->r == NULL) { n->r = create_internal_node(); } next = n->r; } else { if (n->l == NULL) { n->l = create_internal_node(); } next = n->l; } } while (depth < nm); if (next == NULL) { /* The easy case. */ struct data_node* node = create_data_node(prefix, nm, network_owner); uint32_t v_bit = prefix & ((uint32_t)pow(2, b)); if (v_bit) { parent->r = (struct internal_node*)node; } else { parent->l = (struct internal_node*)node; } } else if (next->type == INT_NODE) { /* In this case, we've descended as far as we can. Attach the prefix here. */ uint32_t v_bit = prefix & ((uint32_t)pow(2, b)); struct data_node* newnode = create_data_node(prefix, nm, network_owner); newnode->l = next->l; newnode->r = next->r; if (v_bit) { n->r = (struct internal_node*)newnode; } else { n->l = (struct internal_node*)newnode; } DEBUG("## Freeing %p\n", (void*)n); free(next); } }