diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.h | 7 | ||||
| -rw-r--r-- | lib/csv.c | 24 | ||||
| -rw-r--r-- | lib/ferr.c | 1 | ||||
| -rw-r--r-- | lib/if.c | 310 | ||||
| -rw-r--r-- | lib/if.h | 71 | ||||
| -rw-r--r-- | lib/linklist.h | 3 | ||||
| -rw-r--r-- | lib/nexthop.c | 2 | ||||
| -rw-r--r-- | lib/ptm_lib.c | 2 | ||||
| -rw-r--r-- | lib/vrf.c | 19 | ||||
| -rw-r--r-- | lib/vrf.h | 14 | ||||
| -rw-r--r-- | lib/workqueue.c | 38 | ||||
| -rw-r--r-- | lib/zclient.c | 8 |
12 files changed, 246 insertions, 253 deletions
diff --git a/lib/command.h b/lib/command.h index 8cccb62de3..e2d31decd4 100644 --- a/lib/command.h +++ b/lib/command.h @@ -380,6 +380,13 @@ extern void uninstall_element(enum node_type, struct cmd_element *); string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ extern char *argv_concat(struct cmd_token **argv, int argc, int shift); + +/* + * It is preferred that you set the index initial value + * to a 0. This way in the future if you modify the + * cli then there is no need to modify the initial + * value of the index + */ extern int argv_find(struct cmd_token **argv, int argc, const char *text, int *index); @@ -284,6 +284,11 @@ csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...) va_start(list, count); str = csv_field_iter(rec, &fld); + if (!fld) { + va_end(list); + return NULL; + } + for (tempc = 0; tempc < count; tempc++) { col = va_arg(list, char *); for (i = 0; i < fld->field_len; i++) { @@ -652,18 +657,15 @@ int main() { char buf[10000]; csv_t csv; - int p; - int i, j; + int i; csv_record_t *rec; - csv_field_t *fld; - char *str; char hdr1[32], hdr2[32]; - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + log_verbose("Mem: %d\n", get_memory_usage(getpid())); csv_init(&csv, buf, 256); sprintf(hdr1, "%4u", 0); sprintf(hdr2, "%4u", 1); - log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), + log_verbose("(%zu/%zu/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), atoi(hdr2)); rec = csv_encode(&csv, 2, hdr1, hdr2); csv_encode(&csv, 4, "name", "age", "sex", "hei"); @@ -676,19 +678,19 @@ int main() log_verbose("%s\n", buf); sprintf(hdr1, "%4u", csv.csv_len); sprintf(hdr2, "%4u", 1); - log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), + log_verbose("(%zu/%zu/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), atoi(hdr2)); rec = csv_encode_record(&csv, rec, 2, hdr1, hdr2); log_verbose("(%d/%d)\n%s\n", rec->rec_len, csv.csv_len, buf); - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + log_verbose("Mem: %d\n", get_memory_usage(getpid())); csv_clean(&csv); - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + log_verbose("Mem: %d\n", get_memory_usage(getpid())); csv_init(&csv, buf, 256); csv_decode(&csv, NULL); - log_verbose("AFTER DECODE\n"); + log_verbose("%s", "AFTER DECODE\n"); csv_dump(&csv); csv_clean(&csv); - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + log_verbose("Mem: %d\n", get_memory_usage(getpid())); } #endif diff --git a/lib/ferr.c b/lib/ferr.c index 2a039d2089..69aeb3db40 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -74,6 +74,7 @@ static ferr_r ferr_set_va(const char *file, int line, const char *func, /* we're screwed */ zlog_err("out of memory while allocating error info"); raise(SIGSEGV); + abort(); /* raise() can return, but raise(SIGSEGV) shall not */ } pthread_setspecific(errkey, error); @@ -40,6 +40,12 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected") DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label") DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") +static int if_cmp_func(const struct interface *, const struct interface *); +static int if_cmp_index_func(const struct interface *ifp1, + const struct interface *ifp2); +RB_GENERATE(if_name_head, interface, name_entry, if_cmp_func); +RB_GENERATE(if_index_head, interface, index_entry, if_cmp_index_func); + DEFINE_QOBJ_TYPE(interface) DEFINE_HOOK(if_add, (struct interface *ifp), (ifp)) @@ -85,6 +91,8 @@ int if_cmp_name_func(char *p1, char *p2) p1 += l1; p2 += l1; + if (!*p1 && !*p2) + return 0; if (!*p1) return -1; if (!*p2) @@ -109,32 +117,31 @@ int if_cmp_name_func(char *p1, char *p2) return 0; } -static int if_cmp_func(struct interface *ifp1, struct interface *ifp2) +static int if_cmp_func(const struct interface *ifp1, + const struct interface *ifp2) +{ + return if_cmp_name_func((char *)ifp1->name, (char *)ifp2->name); +} + +static int if_cmp_index_func(const struct interface *ifp1, + const struct interface *ifp2) { - return if_cmp_name_func(ifp1->name, ifp2->name); + return ifp1->ifindex - ifp2->ifindex; } /* Create new interface structure. */ -struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id) +struct interface *if_create(const char *name, vrf_id_t vrf_id) { + struct vrf *vrf = vrf_get(vrf_id, NULL); struct interface *ifp; - struct list *intf_list = vrf_iflist_get(vrf_id); ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); ifp->ifindex = IFINDEX_INTERNAL; assert(name); - assert(namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ - strncpy(ifp->name, name, namelen); - ifp->name[namelen] = '\0'; + strlcpy(ifp->name, name, sizeof(ifp->name)); ifp->vrf_id = vrf_id; - if (if_lookup_by_name(ifp->name, vrf_id) == NULL) - listnode_add_sort(intf_list, ifp); - else - zlog_err( - "if_create(%s): corruption detected -- interface with this " - "name exists already in VRF %u!", - ifp->name, vrf_id); + IFNAME_RB_INSERT(vrf, ifp); ifp->connected = list_new(); ifp->connected->del = (void (*)(void *))connected_free; @@ -152,22 +159,22 @@ struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id) /* Create new interface structure. */ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { - struct list *intf_list = vrf_iflist_get(vrf_id); + struct vrf *vrf; /* remove interface from old master vrf list */ - if (vrf_iflist(ifp->vrf_id)) - listnode_delete(vrf_iflist(ifp->vrf_id), ifp); + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (vrf) { + IFNAME_RB_REMOVE(vrf, ifp); + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(vrf, ifp); + } ifp->vrf_id = vrf_id; - if (if_lookup_by_name(ifp->name, vrf_id) == NULL) - listnode_add_sort(intf_list, ifp); - else - zlog_err( - "if_create(%s): corruption detected -- interface with this " - "name exists already in VRF %u!", - ifp->name, vrf_id); - - return; + vrf = vrf_get(ifp->vrf_id, NULL); + + IFNAME_RB_INSERT(vrf, ifp); + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_INSERT(vrf, ifp); } @@ -187,7 +194,11 @@ void if_delete_retain(struct interface *ifp) /* Delete and free interface structure. */ void if_delete(struct interface *ifp) { - listnode_delete(vrf_iflist(ifp->vrf_id), ifp); + struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); + + IFNAME_RB_REMOVE(vrf, ifp); + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(vrf, ifp); if_delete_retain(ifp); @@ -202,14 +213,11 @@ void if_delete(struct interface *ifp) /* Interface existance check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + struct interface if_tmp; - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { - if (ifp->ifindex == ifindex) - return ifp; - } - return NULL; + if_tmp.ifindex = ifindex; + return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id) @@ -233,15 +241,14 @@ ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id) /* Interface existance check by interface name. */ struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + struct interface if_tmp; - if (name) - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { - if (strcmp(name, ifp->name) == 0) - return ifp; - } - return NULL; + if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) + return NULL; + + strlcpy(if_tmp.name, name, sizeof(if_tmp.name)); + return RB_FIND(if_name_head, &vrf->ifaces_by_name, &if_tmp); } struct interface *if_lookup_by_name_all_vrf(const char *name) @@ -249,6 +256,9 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) struct vrf *vrf; struct interface *ifp; + if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) + return NULL; + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { ifp = if_lookup_by_name(name, vrf->vrf_id); if (ifp) @@ -258,34 +268,17 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) return NULL; } -struct interface *if_lookup_by_name_len(const char *name, size_t namelen, - vrf_id_t vrf_id) -{ - struct listnode *node; - struct interface *ifp; - - if (namelen > INTERFACE_NAMSIZ) - return NULL; - - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { - if (!memcmp(name, ifp->name, namelen) - && (ifp->name[namelen] == '\0')) - return ifp; - } - return NULL; -} - /* Lookup interface by IPv4 address. */ struct interface *if_lookup_exact_address(void *src, int family, vrf_id_t vrf_id) { - struct listnode *node; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct listnode *cnode; struct interface *ifp; struct prefix *p; struct connected *c; - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + FOR_ALL_INTERFACES (vrf, ifp) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { p = c->address; @@ -311,7 +304,7 @@ struct interface *if_lookup_exact_address(void *src, int family, struct connected *if_lookup_address(void *matchaddr, int family, vrf_id_t vrf_id) { - struct listnode *node; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct prefix addr; int bestlen = 0; struct listnode *cnode; @@ -331,7 +324,7 @@ struct connected *if_lookup_address(void *matchaddr, int family, match = NULL; - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + FOR_ALL_INTERFACES (vrf, ifp) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { if (c->address && (c->address->family == AF_INET) && prefix_match(CONNECTED_PREFIX(c), &addr) @@ -347,12 +340,12 @@ struct connected *if_lookup_address(void *matchaddr, int family, /* Lookup interface by prefix */ struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id) { - struct listnode *node; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct listnode *cnode; struct interface *ifp; struct connected *c; - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + FOR_ALL_INTERFACES (vrf, ifp) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { if (prefix_cmp(c->address, prefix) == 0) { return ifp; @@ -364,53 +357,49 @@ struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id) /* Get interface by name if given name interface doesn't exist create one. */ -struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty) { struct interface *ifp; - return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL) - ? ifp - : if_create(name, strlen(name), vrf_id); + ifp = if_lookup_by_name_all_vrf(name); + if (ifp) { + if (ifp->vrf_id == vrf_id) + return ifp; + + /* Found a match on a different VRF. If the interface command + * was entered in vty without a VRF (passed as VRF_DEFAULT), + * accept the ifp we found. If a vrf was entered and there is + * a mismatch, reject it if from vty. If it came from the kernel + * or by way of zclient, believe it and update the ifp + * accordingly. + */ + if (vty) { + if (vrf_id == VRF_DEFAULT) + return ifp; + return NULL; + } else { + if_update_to_new_vrf(ifp, vrf_id); + return ifp; + } + } + + return if_create(name, vrf_id); } -struct interface *if_get_by_name_len(const char *name, size_t namelen, - vrf_id_t vrf_id, int vty) +void if_set_index(struct interface *ifp, ifindex_t ifindex) { - struct interface *ifp; - struct vrf *vrf; - struct listnode *node; + struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - ifp = if_lookup_by_name_len(name, namelen, vrf_id); - if (ifp) - return ifp; + if (ifp->ifindex == ifindex) + return; - /* Didn't find the interface on that vrf. Defined on a different one? */ - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf->vrf_id), node, ifp)) { - if (!memcmp(name, ifp->name, namelen) - && (ifp->name[namelen] == '\0')) { - /* Found a match. If the interface command was - * entered in vty without a - * VRF (passed as VRF_DEFAULT), accept the ifp - * we found. If a vrf was - * entered and there is a mismatch, reject it if - * from vty. If it came - * from the kernel by way of zclient, believe - * it and update - * the ifp accordingly. - */ - if (vty) { - if (vrf_id == VRF_DEFAULT) - return ifp; - return NULL; - } else { - if_update_to_new_vrf(ifp, vrf_id); - return ifp; - } - } - } - } - return (if_create(name, namelen, vrf_id)); + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(vrf, ifp) + + ifp->ifindex = ifindex; + + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_INSERT(vrf, ifp) } /* Does interface up ? */ @@ -536,13 +525,11 @@ static void if_dump(const struct interface *ifp) void if_dump_all(void) { struct vrf *vrf; - struct listnode *node; - void *p; + void *ifp; RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if (vrf->iflist != NULL) - for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, p)) - if_dump(p); + FOR_ALL_INTERFACES (vrf, ifp) + if_dump(ifp); } DEFUN (interface_desc, @@ -597,24 +584,20 @@ DEFUN (no_interface_desc, * if not: * - no idea, just get the name in its entirety. */ -static struct interface *if_sunwzebra_get(const char *name, size_t nlen, - vrf_id_t vrf_id) +static struct interface *if_sunwzebra_get(char *name, vrf_id_t vrf_id) { struct interface *ifp; - size_t seppos = 0; + char *cp; - if ((ifp = if_lookup_by_name_len(name, nlen, vrf_id)) != NULL) + if ((ifp = if_lookup_by_name(name, vrf_id)) != NULL) return ifp; /* hunt the primary interface name... */ - while (seppos < nlen && name[seppos] != ':') - seppos++; - - /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ - if (seppos < nlen) - return if_get_by_name_len(name, seppos, vrf_id, 1); - else - return if_get_by_name_len(name, nlen, vrf_id, 1); + cp = strchr(name, ':'); + if (cp) + *cp = '\0'; + + return if_get_by_name(name, vrf_id, 1); } #endif /* SUNOS_5 */ @@ -631,10 +614,9 @@ DEFUN (interface, const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL; struct interface *ifp; - size_t sl; vrf_id_t vrf_id = VRF_DEFAULT; - if ((sl = strlen(ifname)) > INTERFACE_NAMSIZ) { + if (strlen(ifname) > INTERFACE_NAMSIZ) { vty_out(vty, "%% Interface name %s is invalid: length exceeds " "%d characters\n", @@ -648,9 +630,9 @@ DEFUN (interface, VRF_GET_ID(vrf_id, vrfname); #ifdef SUNOS_5 - ifp = if_sunwzebra_get(ifname, sl, vrf_id); + ifp = if_sunwzebra_get(ifname, vrf_id); #else - ifp = if_get_by_name_len(ifname, sl, vrf_id, 1); + ifp = if_get_by_name(ifname, vrf_id, 1); #endif /* SUNOS_5 */ if (!ifp) { @@ -697,8 +679,30 @@ DEFUN_NOSH (no_interface, return CMD_SUCCESS; } +static void if_autocomplete(vector comps, struct cmd_token *token) +{ + struct interface *ifp; + struct vrf *vrf = NULL; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, ifp->name)); + } + } +} + +static const struct cmd_variable_handler if_var_handlers[] = { + {/* "interface NAME" */ + .varname = "interface", + .completions = if_autocomplete}, + {.tokenname = "IFNAME", .completions = if_autocomplete}, + {.tokenname = "INTERFACE", .completions = if_autocomplete}, + {.completions = NULL}}; + void if_cmd_init(void) { + cmd_variable_handler_register(if_var_handlers); + install_element(CONFIG_NODE, &interface_cmd); install_element(CONFIG_NODE, &no_interface_cmd); @@ -718,7 +722,6 @@ DEFUN (show_address, { int idx_vrf = 3; struct listnode *node; - struct listnode *node2; struct interface *ifp; struct connected *ifc; struct prefix *p; @@ -727,9 +730,9 @@ DEFUN (show_address, if (argc > 2) VRF_GET_ID (vrf_id, argv[idx_vrf]->arg); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) + FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) { p = ifc->address; @@ -749,21 +752,20 @@ DEFUN (show_address_vrf_all, { struct vrf *vrf; struct listnode *node; - struct listnode *node2; struct interface *ifp; struct connected *ifc; struct prefix *p; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (!vrf->iflist || !listcount (vrf->iflist)) + if (RB_EMPTY (if_name_head, &vrf->ifaces_by_name)) continue; vty_out (vty, "\nVRF %u\n\n", vrf->vrf_id); - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) + FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) { p = ifc->address; @@ -1045,57 +1047,17 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) } #endif /* ifaddr_ipv4_table */ -static void if_autocomplete(vector comps, struct cmd_token *token) +void if_terminate(struct vrf *vrf) { struct interface *ifp; - struct listnode *ln; - struct vrf *vrf = NULL; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - for (ALL_LIST_ELEMENTS_RO(vrf->iflist, ln, ifp)) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, ifp->name)); - } -} - -static const struct cmd_variable_handler if_var_handlers[] = { - {/* "interface NAME" */ - .varname = "interface", - .completions = if_autocomplete}, - {.tokenname = "IFNAME", .completions = if_autocomplete}, - {.tokenname = "INTERFACE", .completions = if_autocomplete}, - {.completions = NULL}}; - -/* Initialize interface list. */ -void if_init(struct list **intf_list) -{ - *intf_list = list_new(); -#if 0 - ifaddr_ipv4_table = route_table_init (); -#endif /* ifaddr_ipv4_table */ - - (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; - - cmd_variable_handler_register(if_var_handlers); -} - -void if_terminate(struct list **intf_list) -{ - for (;;) { - struct interface *ifp; - - ifp = listnode_head(*intf_list); - if (ifp == NULL) - break; + while ((ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name)) != NULL) { if (ifp->node) { ifp->node->info = NULL; route_unlock_node(ifp->node); } - if_delete(ifp); } - - list_delete_and_null(intf_list); } const char *if_link_type_str(enum zebra_link_type llt) @@ -201,6 +201,8 @@ struct if_link_params { /* Interface structure */ struct interface { + RB_ENTRY(interface) name_entry, index_entry; + /* Interface name. This should probably never be changed after the interface is created, because the configuration info for this interface @@ -209,13 +211,17 @@ struct interface { To delete, just set ifindex to IFINDEX_INTERNAL to indicate that the interface does not exist in the kernel. */ - char name[INTERFACE_NAMSIZ + 1]; + char name[INTERFACE_NAMSIZ]; /* Interface index (should be IFINDEX_INTERNAL for non-kernel or - deleted interfaces). */ + deleted interfaces). + WARNING: the ifindex needs to be changed using the if_set_index() + function. Failure to respect this will cause corruption in the data + structure used to store the interfaces and if_lookup_by_index() will + not work as expected. + */ ifindex_t ifindex; #define IFINDEX_INTERNAL 0 -#define IFINDEX_DELETED INT_MAX /* Zebra internal interface status */ u_char status; @@ -282,8 +288,47 @@ struct interface { QOBJ_FIELDS }; +RB_HEAD(if_name_head, interface); +RB_PROTOTYPE(if_name_head, interface, name_entry, if_cmp_func); +RB_HEAD(if_index_head, interface); +RB_PROTOTYPE(if_index_head, interface, index_entry, if_cmp_func); DECLARE_QOBJ_TYPE(interface) +#define IFNAME_RB_INSERT(vrf, ifp) \ + if (RB_INSERT(if_name_head, &vrf->ifaces_by_name, (ifp))) \ + zlog_err( \ + "%s(%s): corruption detected -- interface with this " \ + "name exists already in VRF %u!", \ + __func__, (ifp)->name, (ifp)->vrf_id); + +#define IFNAME_RB_REMOVE(vrf, ifp) \ + if (RB_REMOVE(if_name_head, &vrf->ifaces_by_name, (ifp)) == NULL) \ + zlog_err( \ + "%s(%s): corruption detected -- interface with this " \ + "name doesn't exist in VRF %u!", \ + __func__, (ifp)->name, (ifp)->vrf_id); + +#define IFINDEX_RB_INSERT(vrf, ifp) \ + if (RB_INSERT(if_index_head, &vrf->ifaces_by_index, (ifp))) \ + zlog_err( \ + "%s(%u): corruption detected -- interface with this " \ + "ifindex exists already in VRF %u!", \ + __func__, (ifp)->ifindex, (ifp)->vrf_id); + +#define IFINDEX_RB_REMOVE(vrf, ifp) \ + if (RB_REMOVE(if_index_head, &vrf->ifaces_by_index, (ifp)) == NULL) \ + zlog_err( \ + "%s(%u): corruption detected -- interface with this " \ + "ifindex doesn't exist in VRF %u!", \ + __func__, (ifp)->ifindex, (ifp)->vrf_id); + +#define FOR_ALL_INTERFACES(vrf, ifp) \ + if (vrf) \ + RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) + +#define FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) \ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) + /* called from the library code whenever interfaces are created/deleted * note: interfaces may not be fully realized at that point; also they * may not exist in the system (ifindex = IFINDEX_INTERNAL) @@ -408,8 +453,7 @@ struct nbr_connected { extern int if_cmp_name_func(char *, char *); extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); -extern struct interface *if_create(const char *name, int namelen, - vrf_id_t vrf_id); +extern struct interface *if_create(const char *name, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address(void *matchaddr, int family, vrf_id_t vrf_id); @@ -422,16 +466,9 @@ extern struct interface *if_lookup_prefix(struct prefix *prefix, by a '\0' character: */ extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); - -/* For these 2 functions, the namelen argument should be the precise length - of the ifname string (not counting any optional trailing '\0' character). - In most cases, strnlen should be used to calculate the namelen value. */ -extern struct interface *if_lookup_by_name_len(const char *ifname, - size_t namelen, vrf_id_t vrf_id); -extern struct interface *if_get_by_name_len(const char *ifname, size_t namelen, - vrf_id_t vrf_id, int vty); - +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id, + int vty); +extern void if_set_index(struct interface *ifp, ifindex_t ifindex); /* Delete the interface, but do not free the structure, and leave it in the interface list. It is often advisable to leave the pseudo interface @@ -450,9 +487,9 @@ extern int if_is_loopback(struct interface *); extern int if_is_broadcast(struct interface *); extern int if_is_pointopoint(struct interface *); extern int if_is_multicast(struct interface *); -extern void if_init(struct list **); extern void if_cmd_init(void); -extern void if_terminate(struct list **); +struct vrf; +extern void if_terminate(struct vrf *vrf); extern void if_dump_all(void); extern const char *if_flag_dump(unsigned long); extern const char *if_link_type_str(enum zebra_link_type); diff --git a/lib/linklist.h b/lib/linklist.h index 4a65fead86..8a43fbe64b 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -56,7 +56,8 @@ struct list { #define listtail(X) ((X) ? ((X)->tail) : NULL) #define listcount(X) ((X)->count) #define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) -#define listgetdata(X) (assert((X)->data != NULL), (X)->data) +/* return X->data only if X and X->data are not NULL */ +#define listgetdata(X) (assert(X), assert((X)->data != NULL), (X)->data) /* Prototypes. */ extern struct list * diff --git a/lib/nexthop.c b/lib/nexthop.c index ea6a310a4a..f6b2c9788d 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -128,7 +128,7 @@ int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2) nhl1 = nh1->nh_label; nhl2 = nh2->nh_label; - if ((nhl1 && !nhl2) || (!nhl1 && nhl2)) + if (!nhl1 || !nhl2) return 0; if (nhl1->num_labels != nhl2->num_labels) diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c index f50d1e2989..e881d49225 100644 --- a/lib/ptm_lib.c +++ b/lib/ptm_lib.c @@ -330,7 +330,7 @@ int ptm_lib_process_msg(ptm_lib_handle_t *hdl, int fd, char *inbuf, int inlen, char client_name[32]; int cmd_id, type, ver, msglen; csv_t *csv; - ptm_lib_msg_ctxt_t *p_ctxt; + ptm_lib_msg_ctxt_t *p_ctxt = NULL; len = _ptm_lib_read_ptm_socket(fd, inbuf, PTMLIB_MSG_HDR_LEN); if (len <= 0) @@ -109,7 +109,8 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) if (vrf == NULL) { vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf)); vrf->vrf_id = VRF_UNKNOWN; - if_init(&vrf->iflist); + RB_INIT(if_name_head, &vrf->ifaces_by_name); + RB_INIT(if_index_head, &vrf->ifaces_by_index); QOBJ_REG(vrf, vrf); new = 1; @@ -153,7 +154,7 @@ void vrf_delete(struct vrf *vrf) (*vrf_master.vrf_delete_hook)(vrf); QOBJ_UNREG(vrf); - if_terminate(&vrf->iflist); + if_terminate(vrf); if (vrf->vrf_id != VRF_UNKNOWN) RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); @@ -251,20 +252,6 @@ void *vrf_info_lookup(vrf_id_t vrf_id) return vrf ? vrf->info : NULL; } -/* Look up the interface list in a VRF. */ -struct list *vrf_iflist(vrf_id_t vrf_id) -{ - struct vrf *vrf = vrf_lookup_by_id(vrf_id); - return vrf ? vrf->iflist : NULL; -} - -/* Get the interface list of the specified VRF. Create one if not find. */ -struct list *vrf_iflist_get(vrf_id_t vrf_id) -{ - struct vrf *vrf = vrf_get(vrf_id, NULL); - return vrf->iflist; -} - /* * VRF bit-map */ @@ -77,8 +77,9 @@ struct vrf { u_char status; #define VRF_ACTIVE (1 << 0) - /* Master list of interfaces belonging to this VRF */ - struct list *iflist; + /* Interfaces belonging to this VRF */ + struct if_name_head ifaces_by_name; + struct if_index_head ifaces_by_index; /* User data */ void *info; @@ -127,15 +128,6 @@ extern void *vrf_info_get(vrf_id_t); extern void *vrf_info_lookup(vrf_id_t); /* - * Utilities to obtain the interface list - */ - -/* Look up the interface list of the specified VRF. */ -extern struct list *vrf_iflist(vrf_id_t); -/* Get the interface list of the specified VRF. Create one if not find. */ -extern struct list *vrf_iflist_get(vrf_id_t); - -/* * VRF bit-map: maintaining flags, one bit per VRF ID */ diff --git a/lib/workqueue.c b/lib/workqueue.c index 643ed2d2b8..952012a006 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -57,6 +57,22 @@ static void work_queue_item_free(struct work_queue_item *item) return; } +static void work_queue_item_remove(struct work_queue *wq, + struct work_queue_item *item) +{ + assert(item && item->data); + + /* call private data deletion callback if needed */ + if (wq->spec.del_item_data) + wq->spec.del_item_data(wq, item->data); + + work_queue_item_dequeue(wq, item); + + work_queue_item_free(item); + + return; +} + /* create new work queue */ struct work_queue *work_queue_new(struct thread_master *m, const char *queue_name) @@ -90,6 +106,12 @@ void work_queue_free(struct work_queue *wq) if (wq->thread != NULL) thread_cancel(wq->thread); + while (!work_queue_empty(wq)) { + struct work_queue_item *item = work_queue_last_item(wq); + + work_queue_item_remove(wq, item); + } + listnode_delete(work_queues, wq); XFREE(MTYPE_WORK_QUEUE_NAME, wq->name); @@ -137,22 +159,6 @@ void work_queue_add(struct work_queue *wq, void *data) return; } -static void work_queue_item_remove(struct work_queue *wq, - struct work_queue_item *item) -{ - assert(item && item->data); - - /* call private data deletion callback if needed */ - if (wq->spec.del_item_data) - wq->spec.del_item_data(wq, item->data); - - work_queue_item_dequeue(wq, item); - - work_queue_item_free(item); - - return; -} - static void work_queue_item_requeue(struct work_queue *wq, struct work_queue_item *item) { work_queue_item_dequeue(wq, item); diff --git a/lib/zclient.c b/lib/zclient.c index 43d46a1801..ad5c30584c 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1230,8 +1230,7 @@ struct interface *zebra_interface_add_read(struct stream *s, vrf_id_t vrf_id) stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - ifp = if_get_by_name_len( - ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id, 0); + ifp = if_get_by_name(ifname_tmp, vrf_id, 0); zebra_interface_if_set_value(s, ifp); @@ -1254,8 +1253,7 @@ struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t vrf_id) stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup this by interface index. */ - ifp = if_lookup_by_name_len( - ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id); + ifp = if_lookup_by_name(ifname_tmp, vrf_id); if (ifp == NULL) { zlog_warn("INTERFACE_STATE: Cannot find IF %s in VRF %d", ifname_tmp, vrf_id); @@ -1333,7 +1331,7 @@ void zebra_interface_if_set_value(struct stream *s, struct interface *ifp) u_char link_params_status = 0; /* Read interface's index. */ - ifp->ifindex = stream_getl(s); + if_set_index(ifp, stream_getl(s)); ifp->status = stream_getc(s); /* Read interface's value. */ |
