diff --git a/radix/radix.c b/radix/radix.c index 1c93fbc..950c50b 100644 --- a/radix/radix.c +++ b/radix/radix.c @@ -1,7 +1,7 @@ #include "radix.h" #define GET_BIT(key, mask) ( ((key[0] & mask[0]) | (key[1] & mask[1])) != 0 ) -#define SHIFT_MASK(mask) mask[0] >>= 1, mask[1] = (mask[1] >> 1) || !(mask[0]) +#define SHIFT_MASK(mask) mask[0] >>= 1, mask[1] = (mask[1] >> 1) | (!mask[0] * (1ul << 63)) int radix_insert(radix_holder_t, record_t); int radix_search(radix_holder_t, record_t); @@ -11,7 +11,7 @@ radix_holder_t create_holder() { return ret; } -radix_node_t create_node(record_t record) { +static radix_node_t create_node(record_t record) { radix_node_t ret = malloc(sizeof(struct radix_node)); record->_valid = VALID_RULE; memcpy(&ret->_data, record, sizeof(struct routing_record)); @@ -38,7 +38,7 @@ int destory_holder(struct radix_holder* t) { return 1; } -int destory_node(struct radix_node* n) { +static int destory_node(struct radix_node* n) { int ret = 0; if (!n) return ret; ret = destory_node(n->_l) + destory_node(n->_r); @@ -50,8 +50,14 @@ int radix_insert(radix_holder_t t, record_t /*restrict*/ r) { unsigned char b; unsigned char ibit = 0; unsigned long mask[2] = {0x01ul << 63, 0x00}; - radix_node_t node = t->_root; - radix_node_t* next = &t->_root; + radix_node_t node; + radix_node_t* next; + + if (!r || !t) + return 0; + + node = t->_root; + next = &t->_root; r->_valid = INVALID_RULE; @@ -116,29 +122,33 @@ int radix_insert(radix_holder_t t, record_t /*restrict*/ r) { } int radix_search(radix_holder_t t, record_t r) { - - int ret = INVALID_RULE; - /* - radix_node_t iter = t->_root; - int ibit = 0; - if (!iter) - return INVALID_RULE; - + radix_node_t iter; + int ibit, ret; + unsigned char b; + unsigned long mask[2] = {0x01ul << 63, 0x00}; - for (;ibit < 128; ++ibit) { - b = GET_BIT(key, ibit); - if (ibit < iter->_ip_end_bit && - b == GET_BIT(iter->_ip, ibit)) + if (!r) + return INVALID_RULE; + + if (!t || !t->_root) + return r->_rule = INVALID_RULE; + + iter = t->_root; + ret = r->_rule = iter->_data._valid ? iter->_data._rule : INVALID_RULE; + + for (ibit = 0;ibit < 128; ++ibit, SHIFT_MASK(mask)) { + b = GET_BIT(r->_ip, mask); + if (ibit < iter->_data._mask && + b == GET_BIT(iter->_data._ip, mask)) continue; - if (ibit == iter->_ip_end_bit) // set result if full match - ret = iter->_rule_valid ? iter->_rule : ret; + if (ibit >= iter->_data._mask) /* match upto node mask */ + ret = r->_rule = iter->_data._valid ? iter->_data._rule : ret; iter = b ? iter->_l : iter->_r; if (!iter) return ret; } - */ return ret; } @@ -152,11 +162,11 @@ int radix_search(radix_holder_t t, record_t r) { #define RULES_FILE "../data/routing-data" #define TEST_FILE "../data/test-data" -#define TEST_ROWS 0 /*66319*/ +#define TEST_ROWS 20 /*66319*/ #define READ_MODE "r" int parse_line(FILE* f, record_t r) { - int ikey, jkey; + int ikey, jkey, mask, rule; unsigned long key[2] = {0,0}; struct in6_addr addr; char ipv6_cidr[50]; @@ -172,24 +182,26 @@ int parse_line(FILE* f, record_t r) { separator = strchr(ipv6_cidr, '/'); if (!separator) { printf("invalid CIDR notation\n"); - return 1; + return 0; } *separator++ = '\0'; - r->_mask = atoi(separator); + mask = atoi(separator); separator = strchr(separator, ' '); - r->_rule = atoi(++separator); + rule = atoi(++separator); - if (r->_mask < 0 || r->_mask > 128) { + if (mask < 0 || mask > 128) { printf("invalid prefix length\n"); - return 1; + return 0; } + r->_mask = mask; - if (r->_rule < 0 || r->_rule > 65536) { + if (rule < 0 || rule > 65536) { printf("invalid pop\n"); - return 1; + return 0; } + r->_rule = rule; if (inet_pton(AF_INET6, ipv6_cidr, &addr) != 1) { printf("%s invalid address\n", ipv6_cidr); @@ -205,7 +217,7 @@ int parse_line(FILE* f, record_t r) { r->_ip[0] = key[0]; r->_ip[1] = key[1]; r->_valid = VALID_RULE; - return !feof(f); + return 1; } int load_input(radix_holder_t t) { @@ -215,7 +227,7 @@ int load_input(radix_holder_t t) { if (!(f = fopen(RULES_FILE, READ_MODE))) { puts("cant open input file"); - exit(1); + return 0; } while (parse_line(f, &r)) { @@ -228,67 +240,55 @@ int load_input(radix_holder_t t) { return cnt; } -int load_tests(unsigned long** subnets, int** rref) { - /* - unsigned long* ips; - int* ref; - int row; +int load_tests(struct routing_record** ref) { FILE* f; - struct routing_record r; - - if (!(f = fopen( TEST_FILE, READ_MODE ))) { + int cnt = 0; + struct routing_record* r = malloc(sizeof(struct routing_record) * TEST_ROWS); + + if (!(f = fopen(TEST_FILE, READ_MODE))) { puts("cant open test file"); - exit(1); + return 0; } - - ips = calloc( TEST_ROWS, sizeof(unsigned long) ); - ref = calloc( TEST_ROWS, sizeof(int) ); - - for (row = 0; row < TEST_ROWS; ++ row) { - parse_line(f, &r); - ips[row] = r._ip; - ref[row] = r._rule; - } - fclose(f); - *subnets = ips; - *rref = ref; - */ - return TEST_ROWS; + for (cnt = 0; cnt < TEST_ROWS; ++cnt) + if (!parse_line(f, &r[cnt])) + printf("test parse failed %d\n", cnt); + + fclose(f); + *ref = r; + return cnt; } -int fire_tests(radix_holder_t t, unsigned long* subnets, int* ref, int num_tests ) { - /* +int fire_tests(radix_holder_t t, struct routing_record* r) { int row; int wrong = 0; - struct routing_record r; + unsigned short ref_pop; - for (row = 0; row < TEST_ROWS; ++ row) { - r._ip = subnets[row]; - r._ip = subnets[row+1]; - radix_search(t, &r); - if ( !r._valid || r._rule != ref[row]) { - printf("ref: %d got: %d @ %d\n", ref[row], r._rule, row ); + for (row = 0; row < TEST_ROWS; ++row, ++r) { + ref_pop = r->_rule; + radix_search(t, r); + if ( !r->_valid || ref_pop != r->_rule) { + printf("ref: %d got: %d @ %d\n", ref_pop, r->_rule, row ); ++wrong; } } - free(subnets); - free(ref); - return wrong; + /* + free(r); */ + return wrong; + return 0; } int main() { - unsigned long* subnets; - int* ref; + struct routing_record* ref; radix_holder_t t = create_holder(); printf("Loaded %d rules\n", load_input(t) ); - printf("Loaded %d tests\n", load_tests(&subnets, &ref) ); - printf("%d tests wrong\n", fire_tests(t, subnets, ref, TEST_ROWS) ); + printf("Loaded %d tests\n", load_tests(&ref) ); + printf("%d tests wrong\n", fire_tests(t, ref) ); destory_holder(t); return 0;