summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/distribute.c155
-rw-r--r--lib/distribute.h36
-rw-r--r--lib/hook.c26
-rw-r--r--lib/hook.h28
-rw-r--r--lib/lib_errors.c26
-rw-r--r--lib/lib_errors.h5
-rw-r--r--lib/mlag.c41
-rw-r--r--lib/mlag.h32
-rw-r--r--lib/module.c26
-rw-r--r--lib/module.h26
-rw-r--r--lib/northbound.c39
-rw-r--r--lib/northbound_cli.c15
-rw-r--r--lib/northbound_cli.h2
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/vrf.c2
-rw-r--r--lib/vty.h2
-rw-r--r--lib/workqueue.c29
-rw-r--r--lib/workqueue.h5
-rw-r--r--lib/yang.c4
-rw-r--r--lib/yang_wrappers.c8
-rw-r--r--lib/zclient.c13
-rw-r--r--lib/zclient.h7
-rw-r--r--lib/zebra.h52
23 files changed, 398 insertions, 183 deletions
diff --git a/lib/distribute.c b/lib/distribute.c
index 9697916332..3a6b775bc8 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -27,16 +27,12 @@
#include "distribute.h"
#include "memory.h"
+DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_CTX, "Distribute ctx")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name")
-/* Hash of distribute list. */
-struct hash *disthash;
-
-/* Hook functions. */
-void (*distribute_add_hook)(struct distribute *);
-void (*distribute_delete_hook)(struct distribute *);
+struct list *dist_ctx_list;
static struct distribute *distribute_new(void)
{
@@ -62,7 +58,8 @@ static void distribute_free(struct distribute *dist)
XFREE(MTYPE_DISTRIBUTE, dist);
}
-static void distribute_free_if_empty(struct distribute *dist)
+static void distribute_free_if_empty(struct distribute_ctx *ctx,
+ struct distribute *dist)
{
int i;
@@ -70,12 +67,13 @@ static void distribute_free_if_empty(struct distribute *dist)
if (dist->list[i] != NULL || dist->prefix[i] != NULL)
return;
- hash_release(disthash, dist);
+ hash_release(ctx->disthash, dist);
distribute_free(dist);
}
/* Lookup interface's distribute list. */
-struct distribute *distribute_lookup(const char *ifname)
+struct distribute *distribute_lookup(struct distribute_ctx *ctx,
+ const char *ifname)
{
struct distribute key;
struct distribute *dist;
@@ -83,7 +81,7 @@ struct distribute *distribute_lookup(const char *ifname)
/* temporary reference */
key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL;
- dist = hash_lookup(disthash, &key);
+ dist = hash_lookup(ctx->disthash, &key);
if (key.ifname)
XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
@@ -91,14 +89,18 @@ struct distribute *distribute_lookup(const char *ifname)
return dist;
}
-void distribute_list_add_hook(void (*func)(struct distribute *))
+void distribute_list_add_hook(struct distribute_ctx *ctx,
+ void (*func)(struct distribute_ctx *ctx,
+ struct distribute *))
{
- distribute_add_hook = func;
+ ctx->distribute_add_hook = func;
}
-void distribute_list_delete_hook(void (*func)(struct distribute *))
+void distribute_list_delete_hook(struct distribute_ctx *ctx,
+ void (*func)(struct distribute_ctx *ctx,
+ struct distribute *))
{
- distribute_delete_hook = func;
+ ctx->distribute_delete_hook = func;
}
static void *distribute_hash_alloc(struct distribute *arg)
@@ -114,7 +116,8 @@ static void *distribute_hash_alloc(struct distribute *arg)
}
/* Make new distribute list and push into hash. */
-static struct distribute *distribute_get(const char *ifname)
+static struct distribute *distribute_get(struct distribute_ctx *ctx,
+ const char *ifname)
{
struct distribute key;
struct distribute *ret;
@@ -122,7 +125,7 @@ static struct distribute *distribute_get(const char *ifname)
/* temporary reference */
key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL;
- ret = hash_get(disthash, &key,
+ ret = hash_get(ctx->disthash, &key,
(void *(*)(void *))distribute_hash_alloc);
if (key.ifname)
@@ -152,29 +155,32 @@ static bool distribute_cmp(const struct distribute *dist1,
}
/* Set access-list name to the distribute list. */
-static void distribute_list_set(const char *ifname, enum distribute_type type,
+static void distribute_list_set(struct distribute_ctx *ctx,
+ const char *ifname, enum distribute_type type,
const char *alist_name)
{
struct distribute *dist;
- dist = distribute_get(ifname);
+ dist = distribute_get(ctx, ifname);
if (dist->list[type])
XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name);
/* Apply this distribute-list to the interface. */
- (*distribute_add_hook)(dist);
+ (ctx->distribute_add_hook)(ctx, dist);
}
/* Unset distribute-list. If matched distribute-list exist then
return 1. */
-static int distribute_list_unset(const char *ifname, enum distribute_type type,
+static int distribute_list_unset(struct distribute_ctx *ctx,
+ const char *ifname,
+ enum distribute_type type,
const char *alist_name)
{
struct distribute *dist;
- dist = distribute_lookup(ifname);
+ dist = distribute_lookup(ctx, ifname);
if (!dist)
return 0;
@@ -187,39 +193,41 @@ static int distribute_list_unset(const char *ifname, enum distribute_type type,
dist->list[type] = NULL;
/* Apply this distribute-list to the interface. */
- (*distribute_delete_hook)(dist);
+ (ctx->distribute_delete_hook)(ctx, dist);
/* If all dist are NULL, then free distribute list. */
- distribute_free_if_empty(dist);
+ distribute_free_if_empty(ctx, dist);
return 1;
}
/* Set access-list name to the distribute list. */
-static void distribute_list_prefix_set(const char *ifname,
+static void distribute_list_prefix_set(struct distribute_ctx *ctx,
+ const char *ifname,
enum distribute_type type,
const char *plist_name)
{
struct distribute *dist;
- dist = distribute_get(ifname);
+ dist = distribute_get(ctx, ifname);
if (dist->prefix[type])
XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name);
/* Apply this distribute-list to the interface. */
- (*distribute_add_hook)(dist);
+ (ctx->distribute_add_hook)(ctx, dist);
}
/* Unset distribute-list. If matched distribute-list exist then
return 1. */
-static int distribute_list_prefix_unset(const char *ifname,
+static int distribute_list_prefix_unset(struct distribute_ctx *ctx,
+ const char *ifname,
enum distribute_type type,
const char *plist_name)
{
struct distribute *dist;
- dist = distribute_lookup(ifname);
+ dist = distribute_lookup(ctx, ifname);
if (!dist)
return 0;
@@ -232,10 +240,10 @@ static int distribute_list_prefix_unset(const char *ifname,
dist->prefix[type] = NULL;
/* Apply this distribute-list to the interface. */
- (*distribute_delete_hook)(dist);
+ (ctx->distribute_delete_hook)(ctx, dist);
/* If all dist are NULL, then free distribute list. */
- distribute_free_if_empty(dist);
+ distribute_free_if_empty(ctx, dist);
return 1;
}
@@ -250,15 +258,17 @@ DEFUN (distribute_list,
"Interface name\n")
{
int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
-
/* Check of distribute list type. */
enum distribute_type type = argv[2 + prefix]->arg[0] == 'i'
? DISTRIBUTE_V4_IN
: DISTRIBUTE_V4_OUT;
/* Set appropriate function call */
- void (*distfn)(const char *, enum distribute_type, const char *) =
+ void (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_set : &distribute_list_set;
+ struct distribute_ctx *ctx =
+ (struct distribute_ctx *)listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
@@ -266,7 +276,7 @@ DEFUN (distribute_list,
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- distfn(ifname, type, argv[1 + prefix]->arg);
+ distfn(ctx, ifname, type, argv[1 + prefix]->arg);
return CMD_SUCCESS;
}
@@ -283,15 +293,16 @@ DEFUN (ipv6_distribute_list,
"Interface name\n")
{
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-
/* Check of distribute list type. */
enum distribute_type type = argv[3 + prefix]->arg[0] == 'i'
? DISTRIBUTE_V6_IN
: DISTRIBUTE_V6_OUT;
/* Set appropriate function call */
- void (*distfn)(const char *, enum distribute_type, const char *) =
+ void (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_set : &distribute_list_set;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
@@ -299,7 +310,7 @@ DEFUN (ipv6_distribute_list,
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- distfn(ifname, type, argv[2 + prefix]->arg);
+ distfn(ctx, ifname, type, argv[2 + prefix]->arg);
return CMD_SUCCESS;
}
@@ -316,7 +327,6 @@ DEFUN (no_distribute_list,
"Interface name\n")
{
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-
int idx_alname = 2 + prefix;
int idx_disttype = idx_alname + 1;
enum distribute_type type =
@@ -324,16 +334,17 @@ DEFUN (no_distribute_list,
DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT;
/* Set appropriate function call */
- int (*distfn)(const char *, enum distribute_type,
- const char *) =
+ int (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- int ret = distfn(ifname, type, argv[2 + prefix]->arg);
+ int ret = distfn(ctx, ifname, type, argv[2 + prefix]->arg);
if (!ret) {
vty_out(vty, "distribute list doesn't exist\n");
@@ -355,16 +366,17 @@ DEFUN (no_ipv6_distribute_list,
"Interface name\n")
{
int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
-
int idx_alname = 3 + prefix;
int idx_disttype = idx_alname + 1;
enum distribute_type type =
argv[idx_disttype]->arg[0] == 'i' ?
DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* Set appropriate function call */
- int (*distfn)(const char *, enum distribute_type, const char *) =
+ int (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
/* if interface is present, get name */
@@ -373,7 +385,7 @@ DEFUN (no_ipv6_distribute_list,
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- int ret = distfn(ifname, type, argv[3 + prefix]->arg);
+ int ret = distfn(ctx, ifname, type, argv[3 + prefix]->arg);
if (!ret) {
vty_out(vty, "distribute list doesn't exist\n");
@@ -393,7 +405,7 @@ static int distribute_print(struct vty *vty, char *tab[], int is_prefix,
return has_print;
}
-int config_show_distribute(struct vty *vty)
+int config_show_distribute(struct vty *vty, struct distribute_ctx *dist_ctxt)
{
unsigned int i;
int has_print = 0;
@@ -401,7 +413,7 @@ int config_show_distribute(struct vty *vty)
struct distribute *dist;
/* Output filter configuration. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(dist_ctxt, NULL);
vty_out(vty, " Outgoing update filter list for all interface is");
has_print = 0;
if (dist) {
@@ -419,8 +431,8 @@ int config_show_distribute(struct vty *vty)
else
vty_out(vty, " not set\n");
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
dist = mp->data;
if (dist->ifname) {
vty_out(vty, " %s filtered by",
@@ -447,7 +459,7 @@ int config_show_distribute(struct vty *vty)
/* Input filter configuration. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(dist_ctxt, NULL);
vty_out(vty, " Incoming update filter list for all interface is");
has_print = 0;
if (dist) {
@@ -465,8 +477,8 @@ int config_show_distribute(struct vty *vty)
else
vty_out(vty, " not set\n");
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
dist = mp->data;
if (dist->ifname) {
vty_out(vty, " %s filtered by",
@@ -494,7 +506,8 @@ int config_show_distribute(struct vty *vty)
}
/* Configuration write function. */
-int config_write_distribute(struct vty *vty)
+int config_write_distribute(struct vty *vty,
+ struct distribute_ctx *dist_ctxt)
{
unsigned int i;
int j;
@@ -502,8 +515,8 @@ int config_write_distribute(struct vty *vty)
struct hash_backet *mp;
int write = 0;
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
struct distribute *dist;
dist = mp->data;
@@ -543,19 +556,38 @@ int config_write_distribute(struct vty *vty)
return write;
}
-/* Clear all distribute list. */
-void distribute_list_reset()
+void distribute_list_delete(struct distribute_ctx **ctx)
{
- hash_clean(disthash, (void (*)(void *))distribute_free);
+ if ((*ctx)->disthash) {
+ hash_clean((*ctx)->disthash, (void (*)(void *))distribute_free);
+ }
+ if (!dist_ctx_list)
+ dist_ctx_list = list_new();
+ listnode_delete(dist_ctx_list, *ctx);
+ if (list_isempty(dist_ctx_list))
+ list_delete(&dist_ctx_list);
+ XFREE(MTYPE_DISTRIBUTE_CTX, (*ctx));
}
-/* Initialize distribute list related hash. */
-void distribute_list_init(int node)
+/* Initialize distribute list container */
+struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf)
{
- disthash = hash_create(
+ struct distribute_ctx *ctx;
+
+ ctx = XCALLOC(MTYPE_DISTRIBUTE_CTX, sizeof(struct distribute_ctx));
+ ctx->vrf = vrf;
+ ctx->disthash = hash_create(
distribute_hash_make,
(bool (*)(const void *, const void *))distribute_cmp, NULL);
+ if (!dist_ctx_list)
+ dist_ctx_list = list_new();
+ listnode_add(dist_ctx_list, ctx);
+ return ctx;
+}
+/* Initialize distribute list vty commands */
+void distribute_list_init(int node)
+{
/* vtysh command-extraction doesn't grok install_element(node, ) */
if (node == RIP_NODE) {
install_element(RIP_NODE, &distribute_list_cmd);
@@ -563,10 +595,7 @@ void distribute_list_init(int node)
} else if (node == RIPNG_NODE) {
install_element(RIPNG_NODE, &distribute_list_cmd);
install_element(RIPNG_NODE, &no_distribute_list_cmd);
- }
-
- /* install v6 */
- if (node == RIPNG_NODE) {
+ /* install v6 */
install_element(RIPNG_NODE, &ipv6_distribute_list_cmd);
install_element(RIPNG_NODE, &no_ipv6_distribute_list_cmd);
}
diff --git a/lib/distribute.h b/lib/distribute.h
index 35c5e0d6b6..44c699b38a 100644
--- a/lib/distribute.h
+++ b/lib/distribute.h
@@ -45,14 +45,36 @@ struct distribute {
char *prefix[DISTRIBUTE_MAX];
};
+struct distribute_ctx {
+ /* Hash of distribute list. */
+ struct hash *disthash;
+
+ /* Hook functions. */
+ void (*distribute_add_hook)(struct distribute_ctx *ctx,
+ struct distribute *dist);
+ void (*distribute_delete_hook)(struct distribute_ctx *ctx,
+ struct distribute *dist);
+
+ /* vrf information */
+ struct vrf *vrf;
+};
+
/* Prototypes for distribute-list. */
-extern void distribute_list_init(int);
-extern void distribute_list_reset(void);
-extern void distribute_list_add_hook(void (*)(struct distribute *));
-extern void distribute_list_delete_hook(void (*)(struct distribute *));
-extern struct distribute *distribute_lookup(const char *);
-extern int config_write_distribute(struct vty *);
-extern int config_show_distribute(struct vty *);
+extern void distribute_list_init(int node);
+extern struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf);
+extern void distribute_list_delete(struct distribute_ctx **ctx);
+extern void distribute_list_add_hook(struct distribute_ctx *ctx,
+ void (*)(struct distribute_ctx *ctx,
+ struct distribute *));
+extern void distribute_list_delete_hook(struct distribute_ctx *ctx,
+ void (*)(struct distribute_ctx *ctx,
+ struct distribute *));
+extern struct distribute *distribute_lookup(struct distribute_ctx *ctx,
+ const char *ifname);
+extern int config_write_distribute(struct vty *vty,
+ struct distribute_ctx *ctx);
+extern int config_show_distribute(struct vty *vty,
+ struct distribute_ctx *ctx);
extern enum filter_type distribute_apply_in(struct interface *,
struct prefix *);
diff --git a/lib/hook.c b/lib/hook.c
index 4fe305f282..870d158aac 100644
--- a/lib/hook.c
+++ b/lib/hook.c
@@ -1,23 +1,17 @@
/*
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
diff --git a/lib/hook.h b/lib/hook.h
index ee496ab365..96fec97d7e 100644
--- a/lib/hook.h
+++ b/lib/hook.h
@@ -1,23 +1,17 @@
/*
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _FRR_HOOK_H
diff --git a/lib/lib_errors.c b/lib/lib_errors.c
index b1ed7d2f6b..7e428f135c 100644
--- a/lib/lib_errors.c
+++ b/lib/lib_errors.c
@@ -105,10 +105,16 @@ static struct log_ref ferr_lib_warn[] = {
.suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries",
},
{
- .code = EC_LIB_NB_CB_CONFIG,
- .title = "A northbound configuration callback has failed",
- .description = "The northbound subsystem has detected that a callback used to process a configuration change has returned an error",
- .suggestion = "The log message should contain further details on the specific error that occurred; investigate the reported error.",
+ .code = EC_LIB_NB_CB_CONFIG_VALIDATE,
+ .title = "A northbound configuration callback has failed in the VALIDATE phase",
+ .description = "A callback used to process a configuration change has returned a validation error",
+ .suggestion = "The provided configuration is invalid. Fix any inconsistency and try again.",
+ },
+ {
+ .code = EC_LIB_NB_CB_CONFIG_PREPARE,
+ .title = "A northbound configuration callback has failed in the PREPARE phase",
+ .description = "A callback used to process a configuration change has returned a resource allocation error",
+ .suggestion = "The system might be running out of resources. Check the log for more details.",
},
{
.code = EC_LIB_NB_CB_STATE,
@@ -327,6 +333,18 @@ static struct log_ref ferr_lib_err[] = {
.suggestion = "Open an Issue with all relevant log files and restart FRR"
},
{
+ .code = EC_LIB_NB_CB_CONFIG_ABORT,
+ .title = "A northbound configuration callback has failed in the ABORT phase",
+ .description = "A callback used to process a configuration change has returned an error while trying to abort a change",
+ .suggestion = "Gather log data and open an Issue.",
+ },
+ {
+ .code = EC_LIB_NB_CB_CONFIG_APPLY,
+ .title = "A northbound configuration callback has failed in the APPLY phase",
+ .description = "A callback used to process a configuration change has returned an error while applying the changes",
+ .suggestion = "Gather log data and open an Issue.",
+ },
+ {
.code = END_FERR,
}
};
diff --git a/lib/lib_errors.h b/lib/lib_errors.h
index 5534edbd8d..86a83df46c 100644
--- a/lib/lib_errors.h
+++ b/lib/lib_errors.h
@@ -57,7 +57,10 @@ enum lib_log_refs {
EC_LIB_NB_CB_MISSING,
EC_LIB_NB_CB_INVALID_PRIO,
EC_LIB_NB_CBS_VALIDATION,
- EC_LIB_NB_CB_CONFIG,
+ EC_LIB_NB_CB_CONFIG_VALIDATE,
+ EC_LIB_NB_CB_CONFIG_PREPARE,
+ EC_LIB_NB_CB_CONFIG_ABORT,
+ EC_LIB_NB_CB_CONFIG_APPLY,
EC_LIB_NB_CB_STATE,
EC_LIB_NB_CB_RPC,
EC_LIB_NB_CANDIDATE_INVALID,
diff --git a/lib/mlag.c b/lib/mlag.c
new file mode 100644
index 0000000000..acdc662924
--- /dev/null
+++ b/lib/mlag.c
@@ -0,0 +1,41 @@
+/* mlag generic code.
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <zebra.h>
+
+#include <mlag.h>
+
+char *mlag_role2str(enum mlag_role role, char *buf, size_t size)
+{
+ switch (role) {
+ case MLAG_ROLE_NONE:
+ snprintf(buf, size, "NONE");
+ break;
+ case MLAG_ROLE_PRIMARY:
+ snprintf(buf, size, "PRIMARY");
+ break;
+ case MLAG_ROLE_SECONDARY:
+ snprintf(buf, size, "SECONDARY");
+ break;
+ }
+
+ return buf;
+}
diff --git a/lib/mlag.h b/lib/mlag.h
new file mode 100644
index 0000000000..73725ca3fd
--- /dev/null
+++ b/lib/mlag.h
@@ -0,0 +1,32 @@
+/* mlag header.
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef __MLAG_H__
+#define __MLAG_H__
+
+enum mlag_role {
+ MLAG_ROLE_NONE,
+ MLAG_ROLE_PRIMARY,
+ MLAG_ROLE_SECONDARY
+};
+
+extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
+#endif
diff --git a/lib/module.c b/lib/module.c
index 7d5671290b..6754b94579 100644
--- a/lib/module.c
+++ b/lib/module.c
@@ -1,23 +1,17 @@
/*
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
diff --git a/lib/module.h b/lib/module.h
index e66e5cd650..68ed959270 100644
--- a/lib/module.h
+++ b/lib/module.h
@@ -1,23 +1,17 @@
/*
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _FRR_MODULE_H
diff --git a/lib/northbound.c b/lib/northbound.c
index 8b96dc4a6c..a7f9c8620e 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -719,6 +719,7 @@ static int nb_configuration_callback(const enum nb_event event,
const struct lyd_node *dnode = change->cb.dnode;
union nb_resource *resource;
int ret = NB_ERR;
+ enum lib_log_refs ref;
if (debug_northbound) {
const char *value = "(none)";
@@ -751,12 +752,36 @@ static int nb_configuration_callback(const enum nb_event event,
break;
}
- if (ret != NB_OK)
- flog_warn(
- EC_LIB_NB_CB_CONFIG,
- "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
- __func__, nb_err_name(ret), nb_event_name(event),
- nb_operation_name(operation), xpath);
+ if (ret != NB_OK) {
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ref = EC_LIB_NB_CB_CONFIG_VALIDATE;
+ break;
+ case NB_EV_PREPARE:
+ ref = EC_LIB_NB_CB_CONFIG_PREPARE;
+ break;
+ case NB_EV_ABORT:
+ ref = EC_LIB_NB_CB_CONFIG_ABORT;
+ break;
+ case NB_EV_APPLY:
+ ref = EC_LIB_NB_CB_CONFIG_APPLY;
+ break;
+ }
+ if (event == NB_EV_VALIDATE || event == NB_EV_PREPARE)
+ flog_warn(
+ ref,
+ "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
+ __func__, nb_err_name(ret),
+ nb_event_name(event),
+ nb_operation_name(operation), xpath);
+ else
+ flog_err(
+ ref,
+ "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
+ __func__, nb_err_name(ret),
+ nb_event_name(event),
+ nb_operation_name(operation), xpath);
+ }
return ret;
}
@@ -1071,7 +1096,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
/* Iterate over all list entries. */
do {
struct yang_list_keys list_keys;
- char xpath[XPATH_MAXLEN];
+ char xpath[XPATH_MAXLEN * 2];
int ret;
/* Obtain list entry. */
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index d685a4e7c2..2b024ace93 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -71,7 +71,7 @@ void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
}
change = &vty->cfg_changes[vty->num_cfg_changes++];
- change->xpath = xpath;
+ strlcpy(change->xpath, xpath, sizeof(change->xpath));
change->operation = operation;
change->value = value;
}
@@ -79,8 +79,7 @@ void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
{
struct nb_config *candidate_transitory;
- char xpath_base[XPATH_MAXLEN];
- va_list ap;
+ char xpath_base[XPATH_MAXLEN] = {};
bool error = false;
int ret;
@@ -94,9 +93,13 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
candidate_transitory = nb_config_dup(vty->candidate_config);
/* Parse the base XPath format string. */
- va_start(ap, xpath_base_fmt);
- vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
- va_end(ap);
+ if (xpath_base_fmt) {
+ va_list ap;
+
+ va_start(ap, xpath_base_fmt);
+ vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
+ va_end(ap);
+ }
/* Edit candidate configuration. */
for (size_t i = 0; i < vty->num_cfg_changes; i++) {
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index 362a4bc325..884f250941 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -60,7 +60,7 @@ extern void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
*
* xpath_base_fmt
* Prepend the given XPath (absolute or relative) to all enqueued
- * configuration changes.
+ * configuration changes. This is an optional parameter.
*
* Returns:
* CMD_SUCCESS on success, CMD_WARNING_CONFIG_FAILED otherwise.
diff --git a/lib/subdir.am b/lib/subdir.am
index 43b39100cb..ccbe13bca6 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -44,6 +44,7 @@ lib_libfrr_la_SOURCES = \
lib/md5.c \
lib/memory.c \
lib/memory_vty.c \
+ lib/mlag.c \
lib/module.c \
lib/mpls.c \
lib/network.c \
@@ -134,6 +135,7 @@ pkginclude_HEADERS += \
lib/bitfield.h \
lib/buffer.h \
lib/checksum.h \
+ lib/mlag.h \
lib/command.h \
lib/command_graph.h \
lib/command_match.h \
diff --git a/lib/vrf.c b/lib/vrf.c
index 8409a1c9a1..0c82f6a3cd 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -330,6 +330,8 @@ vrf_id_t vrf_name_to_id(const char *name)
vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
// id/ routine not used.
+ if (!name)
+ return vrf_id;
vrf = vrf_lookup_by_name(name);
if (vrf)
vrf_id = vrf->vrf_id;
diff --git a/lib/vty.h b/lib/vty.h
index ad4dc273b9..79b1bd5e93 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -43,7 +43,7 @@ struct vty_error {
};
struct vty_cfg_change {
- const char *xpath;
+ char xpath[XPATH_MAXLEN];
enum nb_operation operation;
const char *value;
};
diff --git a/lib/workqueue.c b/lib/workqueue.c
index c927d5d714..24ef24c774 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -91,9 +91,10 @@ struct work_queue *work_queue_new(struct thread_master *m,
new->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY;
- /* Default values, can be overriden by caller */
+ /* Default values, can be overridden by caller */
new->spec.hold = WORK_QUEUE_DEFAULT_HOLD;
new->spec.yield = THREAD_YIELD_TIME_SLOT;
+ new->spec.retry = WORK_QUEUE_DEFAULT_RETRY;
return new;
}
@@ -133,8 +134,17 @@ static int work_queue_schedule(struct work_queue *wq, unsigned int delay)
if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL)
&& !work_queue_empty(wq)) {
wq->thread = NULL;
- thread_add_timer_msec(wq->master, work_queue_run, wq, delay,
- &wq->thread);
+
+ /* Schedule timer if there's a delay, otherwise just schedule
+ * as an 'event'
+ */
+ if (delay > 0)
+ thread_add_timer_msec(wq->master, work_queue_run, wq,
+ delay, &wq->thread);
+ else
+ thread_add_event(wq->master, work_queue_run, wq, 0,
+ &wq->thread);
+
/* set thread yield time, if needed */
if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT)
thread_set_yield_time(wq->thread, wq->spec.yield);
@@ -234,7 +244,7 @@ int work_queue_run(struct thread *thread)
{
struct work_queue *wq;
struct work_queue_item *item, *titem;
- wq_item_status ret;
+ wq_item_status ret = WQ_SUCCESS;
unsigned int cycles = 0;
char yielded = 0;
@@ -376,9 +386,14 @@ stats:
#endif
/* Is the queue done yet? If it is, call the completion callback. */
- if (!work_queue_empty(wq))
- work_queue_schedule(wq, 0);
- else if (wq->spec.completion_func)
+ if (!work_queue_empty(wq)) {
+ if (ret == WQ_RETRY_LATER ||
+ ret == WQ_QUEUE_BLOCKED)
+ work_queue_schedule(wq, wq->spec.retry);
+ else
+ work_queue_schedule(wq, 0);
+
+ } else if (wq->spec.completion_func)
wq->spec.completion_func(wq);
return 0;
diff --git a/lib/workqueue.h b/lib/workqueue.h
index fe1700f8de..7c84655063 100644
--- a/lib/workqueue.h
+++ b/lib/workqueue.h
@@ -30,6 +30,9 @@ DECLARE_MTYPE(WORK_QUEUE)
/* Hold time for the initial schedule of a queue run, in millisec */
#define WORK_QUEUE_DEFAULT_HOLD 50
+/* Retry for queue that is 'blocked' or 'retry later' */
+#define WORK_QUEUE_DEFAULT_RETRY 0
+
/* action value, for use by item processor and item error handlers */
typedef enum {
WQ_SUCCESS = 0,
@@ -90,6 +93,8 @@ struct work_queue {
unsigned long
yield; /* yield time in us for associated thread */
+
+ uint32_t retry; /* Optional retry timeout if queue is blocked */
} spec;
/* remaining fields should be opaque to users */
diff --git a/lib/yang.c b/lib/yang.c
index 462e693549..71b41c35d8 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -71,9 +71,11 @@ static const char *yang_module_imp_clb(const char *mod_name,
return NULL;
}
-static const char * const frr_native_modules[] = {
+static const char *const frr_native_modules[] = {
"frr-interface",
"frr-ripd",
+ "frr-ripngd",
+ "frr-isisd",
};
/* Generate the yang_modules tree. */
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index 96076d6468..6273dff3ce 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -171,6 +171,7 @@ int yang_str2enum(const char *xpath, const char *value)
{
const struct lys_node *snode;
const struct lys_node_leaf *sleaf;
+ const struct lys_type *type;
const struct lys_type_info_enums *enums;
snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0);
@@ -182,7 +183,12 @@ int yang_str2enum(const char *xpath, const char *value)
}
sleaf = (const struct lys_node_leaf *)snode;
- enums = &sleaf->type.info.enums;
+ type = &sleaf->type;
+ enums = &type->info.enums;
+ while (enums->count == 0 && type->der) {
+ type = &type->der->type;
+ enums = &type->info.enums;
+ }
for (unsigned int i = 0; i < enums->count; i++) {
const struct lys_type_enum *enm = &enums->enm[i];
diff --git a/lib/zclient.c b/lib/zclient.c
index beb3ca4f34..1c40750db0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1770,19 +1770,19 @@ struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t vrf_id,
vrf_id_t *new_vrf_id)
{
- unsigned int ifindex;
+ char ifname[INTERFACE_NAMSIZ];
struct interface *ifp;
vrf_id_t new_id;
- /* Get interface index. */
- ifindex = stream_getl(s);
+ /* Read interface name. */
+ stream_get(ifname, s, INTERFACE_NAMSIZ);
/* Lookup interface. */
- ifp = if_lookup_by_index(ifindex, vrf_id);
+ ifp = if_lookup_by_name(ifname, vrf_id);
if (ifp == NULL) {
flog_err(EC_LIB_ZAPI_ENCODE,
- "INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d",
- ifindex, vrf_id);
+ "INTERFACE_VRF_UPDATE: Cannot find IF %s in VRF %d",
+ ifname, vrf_id);
return NULL;
}
@@ -2355,6 +2355,7 @@ static void zclient_capability_decode(int command, struct zclient *zclient,
STREAM_GETC(s, mpls_enabled);
cap.mpls_enabled = !!mpls_enabled;
STREAM_GETL(s, cap.ecmp);
+ STREAM_GETC(s, cap.role);
if (zclient->zebra_capabilities)
(*zclient->zebra_capabilities)(&cap);
diff --git a/lib/zclient.h b/lib/zclient.h
index adb48b252a..831cccfb7e 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -36,6 +36,8 @@
/* For union pw_protocol_fields */
#include "pw.h"
+#include "mlag.h"
+
/* For input/output buffer to zebra. */
#define ZEBRA_MAX_PACKET_SIZ 16384
@@ -58,6 +60,10 @@
#define ZEBRA_IPTABLES_FORWARD 0
#define ZEBRA_IPTABLES_DROP 1
+/* Zebra FEC register command flags. */
+#define ZEBRA_FEC_REGISTER_LABEL 0x1
+#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x2
+
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
@@ -167,6 +173,7 @@ struct redist_proto {
struct zclient_capabilities {
uint32_t ecmp;
bool mpls_enabled;
+ enum mlag_role role;
};
/* Structure for the zebra client. */
diff --git a/lib/zebra.h b/lib/zebra.h
index 46721cc1ab..09115951e9 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -410,21 +410,47 @@ extern const char *zserv_command_string(unsigned int command);
#define strmatch(a,b) (!strcmp((a), (b)))
/* Zebra message flags */
+
+/*
+ * Cause Zebra to consider this routes nexthops recursively
+ */
#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
+/*
+ * This is a route that is read in on startup that was left around
+ * from a previous run of FRR
+ */
#define ZEBRA_FLAG_SELFROUTE 0x02
-#define ZEBRA_FLAG_IBGP 0x08
-#define ZEBRA_FLAG_SELECTED 0x10
-#define ZEBRA_FLAG_STATIC 0x40
-#define ZEBRA_FLAG_SCOPE_LINK 0x100
-#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
-#define ZEBRA_FLAG_EVPN_ROUTE 0x400
-#define ZEBRA_FLAG_RR_USE_DISTANCE 0x800
-#define ZEBRA_FLAG_ONLINK 0x1000
-/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
-/* ZEBRA_FLAG_REJECT was 0x80 */
-
-/* Zebra FEC flags. */
-#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
+/*
+ * This flag is used to tell Zebra that the BGP route being passed
+ * down is a IBGP route
+ */
+#define ZEBRA_FLAG_IBGP 0x04
+/*
+ * This is a route that has been selected for FIB installation.
+ * This flag is set in zebra and can be passed up to routing daemons
+ */
+#define ZEBRA_FLAG_SELECTED 0x08
+/*
+ * This is a route that we are telling Zebra that this route *must*
+ * win and will be installed even over ZEBRA_FLAG_SELECTED
+ */
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
+/*
+ * This flag tells Zebra that the route is a EVPN route and should
+ * be treated specially
+ */
+#define ZEBRA_FLAG_EVPN_ROUTE 0x20
+/*
+ * This flag tells Zebra that it should treat the distance passed
+ * down as an additional discriminator for route selection of the
+ * route entry. This mainly is used for backup static routes.
+ */
+#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
+/*
+ * This flag tells Zebra that the passed down route is ONLINK and the
+ * kernel install flag for it should be turned on
+ */
+#define ZEBRA_FLAG_ONLINK 0x80
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */