summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.h7
-rw-r--r--lib/csv.c24
-rw-r--r--lib/ferr.c1
-rw-r--r--lib/if.c310
-rw-r--r--lib/if.h71
-rw-r--r--lib/linklist.h3
-rw-r--r--lib/nexthop.c2
-rw-r--r--lib/ptm_lib.c2
-rw-r--r--lib/vrf.c19
-rw-r--r--lib/vrf.h14
-rw-r--r--lib/workqueue.c38
-rw-r--r--lib/zclient.c8
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);
diff --git a/lib/csv.c b/lib/csv.c
index 0ad5c74be3..27d0fe4029 100644
--- a/lib/csv.c
+++ b/lib/csv.c
@@ -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);
diff --git a/lib/if.c b/lib/if.c
index 34de2c8d8b..320dfba4b5 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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)
diff --git a/lib/if.h b/lib/if.h
index a592e0ff85..eb8af2041b 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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)
diff --git a/lib/vrf.c b/lib/vrf.c
index 0a4969dfac..056f778a3e 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -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
*/
diff --git a/lib/vrf.h b/lib/vrf.h
index bdc0db9c90..8bfdc87689 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -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. */