summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.h5
-rw-r--r--lib/filter.h10
-rw-r--r--lib/filter_cli.c97
-rw-r--r--lib/filter_nb.c96
-rw-r--r--lib/grammar_sandbox_main.c2
-rw-r--r--lib/hash.c15
-rw-r--r--lib/if.c2
-rw-r--r--lib/if.h2
-rw-r--r--lib/keychain.c2
-rw-r--r--lib/ldp_sync.c93
-rw-r--r--lib/ldp_sync.h91
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/mpls.h3
-rw-r--r--lib/nexthop_group.c34
-rw-r--r--lib/nexthop_group.h3
-rw-r--r--lib/northbound.c8
-rw-r--r--lib/northbound.h5
-rw-r--r--lib/northbound_cli.c14
-rw-r--r--lib/pbr.h2
-rw-r--r--lib/prefix.c13
-rw-r--r--lib/prefix.h1
-rw-r--r--lib/privs.c6
-rw-r--r--lib/stream.c24
-rw-r--r--lib/stream.h9
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/yang.c3
-rw-r--r--lib/zclient.c33
-rw-r--r--lib/zclient.h13
-rw-r--r--lib/zlog_targets.c5
29 files changed, 496 insertions, 99 deletions
diff --git a/lib/command.h b/lib/command.h
index e20bfe3318..d828989118 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -421,6 +421,11 @@ struct cmd_node {
#define CMD_VNI_RANGE "(1-16777215)"
#define CONF_BACKUP_EXT ".sav"
+#define MPLS_LDP_SYNC_STR "Enable MPLS LDP-SYNC\n"
+#define NO_MPLS_LDP_SYNC_STR "Disable MPLS LDP-SYNC\n"
+#define MPLS_LDP_SYNC_HOLDDOWN_STR \
+ "Time to wait for LDP-SYNC to occur before restoring if cost\n"
+#define NO_MPLS_LDP_SYNC_HOLDDOWN_STR "holddown timer disable\n"
/* Command warnings. */
#define NO_PASSWD_CMD_WARNING \
diff --git a/lib/filter.h b/lib/filter.h
index d41f3b65cd..623fb94527 100644
--- a/lib/filter.h
+++ b/lib/filter.h
@@ -32,6 +32,16 @@ extern "C" {
/* Maximum ACL name length */
#define ACL_NAMSIZ 128
+/** Cisco host wildcard mask. */
+#define CISCO_HOST_WILDCARD_MASK "0.0.0.0"
+/** Cisco host wildcard binary mask. */
+#define CISCO_BIN_HOST_WILDCARD_MASK INADDR_ANY
+
+/** Cisco any wildcard mask. */
+#define CISCO_ANY_WILDCARD_MASK "255.255.255.255"
+/** Cisco binary any wildcard mask. */
+#define CISCO_BIN_ANY_WILDCARD_MASK INADDR_NONE
+
/* Filter direction. */
#define FILTER_IN 0
#define FILTER_OUT 1
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 8c7a515dc5..09fc3289ce 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -37,14 +37,8 @@
#define ACCESS_LIST_STR "Access list entry\n"
#define ACCESS_LIST_LEG_STR "IP standard access list\n"
-#define ACCESS_LIST_LEG_EXT_STR "IP standard access list (expanded range)\n"
#define ACCESS_LIST_ELEG_STR "IP extended access list\n"
#define ACCESS_LIST_ELEG_EXT_STR "IP extended access list (expanded range)\n"
-#define ACCESS_LIST_XLEG_STR \
- ACCESS_LIST_LEG_STR \
- ACCESS_LIST_LEG_EXT_STR \
- ACCESS_LIST_ELEG_STR \
- ACCESS_LIST_ELEG_EXT_STR
#define ACCESS_LIST_ZEBRA_STR "Access list entry\n"
#define ACCESS_LIST_SEQ_STR \
"Sequence number of an entry\n" \
@@ -68,7 +62,6 @@ static int64_t acl_cisco_get_seq(struct access_list *acl, const char *action,
struct filter f, *fn;
memset(&f, 0, sizeof(f));
- memset(&fc, 0, sizeof(fc));
f.cisco = 1;
if (strcmp(action, "permit") == 0)
f.type = FILTER_PERMIT;
@@ -110,7 +103,8 @@ static int64_t acl_zebra_get_seq(struct access_list *acl, const char *action,
f.type = FILTER_DENY;
fz = &f.u.zfilter;
- fz->prefix = *p;
+ if (p->family)
+ prefix_copy(&fz->prefix, p);
fz->exact = exact;
fn = filter_lookup_zebra(acl, &f);
@@ -130,6 +124,7 @@ static void concat_addr_mask_v4(const char *addr, const char *mask, char *dst,
int plen;
assert(inet_pton(AF_INET, mask, &ia) == 1);
+ ia.s_addr = ~ia.s_addr;
plen = ip_masklen(ia);
snprintf(dst, dstlen, "%s/%d", addr, plen);
}
@@ -171,17 +166,15 @@ static long acl_get_seq(struct vty *vty, const char *xpath)
*/
DEFPY_YANG(
access_list_std, access_list_std_cmd,
- "access-list <(1-99)|(1300-1999)>$number [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask|any>",
+ "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
ACCESS_LIST_STR
ACCESS_LIST_LEG_STR
- ACCESS_LIST_LEG_EXT_STR
ACCESS_LIST_SEQ_STR
ACCESS_LIST_ACTION_STR
"A single host address\n"
"Address to match\n"
"Address to match\n"
- "Wildcard bits\n"
- "Any source host\n")
+ "Wildcard bits\n")
{
int64_t sseq;
char ipmask[64];
@@ -193,8 +186,7 @@ DEFPY_YANG(
* none given (backward compatibility).
*/
snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv4'][name='%s']",
- number_str);
+ "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
@@ -222,18 +214,16 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_std, no_access_list_std_cmd,
- "no access-list <(1-99)|(1300-1999)>$number [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask|any>",
+ "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_LEG_STR
- ACCESS_LIST_LEG_EXT_STR
ACCESS_LIST_SEQ_STR
ACCESS_LIST_ACTION_STR
"A single host address\n"
"Address to match\n"
"Address to match\n"
- "Wildcard bits\n"
- "Any source host\n")
+ "Wildcard bits\n")
{
struct access_list *acl;
struct lyd_node *dnode;
@@ -246,15 +236,14 @@ DEFPY_YANG(
snprintf(
xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
- number_str, seq_str);
+ name, seq_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
/* Otherwise, to keep compatibility, we need to figure it out. */
snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv4'][name='%s']",
- number_str);
+ "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
@@ -263,13 +252,9 @@ DEFPY_YANG(
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
acl = nb_running_get_entry(dnode, NULL, true);
- if (host_str != NULL)
- sseq = acl_cisco_get_seq(acl, action, host_str,
- mask_str ? mask_str : "0.0.0.0", NULL,
- NULL);
- else
- sseq = acl_cisco_get_seq(acl, action, "0.0.0.0",
- "255.255.255.255", NULL, NULL);
+ sseq = acl_cisco_get_seq(acl, action, host_str,
+ mask_str ? mask_str : CISCO_HOST_WILDCARD_MASK,
+ NULL, NULL);
if (sseq == -1)
return CMD_WARNING;
@@ -282,10 +267,9 @@ DEFPY_YANG(
DEFPY_YANG(
access_list_ext, access_list_ext_cmd,
- "access-list <(100-199)|(2000-2699)>$number [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
+ "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
ACCESS_LIST_STR
ACCESS_LIST_ELEG_STR
- ACCESS_LIST_ELEG_EXT_STR
ACCESS_LIST_SEQ_STR
ACCESS_LIST_ACTION_STR
"IPv4 address\n"
@@ -301,7 +285,7 @@ DEFPY_YANG(
"Any destination host\n")
{
int64_t sseq;
- char ipmask[64];
+ char ipmask[64], ipmask_dst[64];
char xpath[XPATH_MAXLEN];
char xpath_entry[XPATH_MAXLEN + 128];
@@ -310,8 +294,7 @@ DEFPY_YANG(
* none given (backward compatibility).
*/
snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv4'][name='%s']",
- number_str);
+ "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
@@ -337,12 +320,12 @@ DEFPY_YANG(
if (dst_str != NULL && dst_mask_str == NULL) {
nb_cli_enqueue_change(vty, "./destination-host", NB_OP_MODIFY,
- src_str);
+ dst_str);
} else if (dst_str != NULL && dst_mask_str != NULL) {
- concat_addr_mask_v4(dst_str, dst_mask_str, ipmask,
- sizeof(ipmask));
+ concat_addr_mask_v4(dst_str, dst_mask_str, ipmask_dst,
+ sizeof(ipmask_dst));
nb_cli_enqueue_change(vty, "./destination-network",
- NB_OP_MODIFY, ipmask);
+ NB_OP_MODIFY, ipmask_dst);
} else {
nb_cli_enqueue_change(vty, "./destination-any", NB_OP_CREATE,
NULL);
@@ -353,11 +336,10 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_ext, no_access_list_ext_cmd,
- "no access-list <(100-199)|(2000-2699)>$number [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
+ "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ELEG_STR
- ACCESS_LIST_ELEG_EXT_STR
ACCESS_LIST_SEQ_STR
ACCESS_LIST_ACTION_STR
"Any Internet Protocol\n"
@@ -383,15 +365,14 @@ DEFPY_YANG(
snprintfrr(
xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
- number_str, seq_str);
+ name, seq_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
/* Otherwise, to keep compatibility, we need to figure it out. */
snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv4'][name='%s']",
- number_str);
+ "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
@@ -404,24 +385,28 @@ DEFPY_YANG(
if (dst_str != NULL)
sseq = acl_cisco_get_seq(
acl, action, src_str,
- src_mask_str ? src_mask_str : "0.0.0.0",
+ src_mask_str ? src_mask_str
+ : CISCO_HOST_WILDCARD_MASK,
dst_str,
- dst_mask_str ? dst_mask_str : "0.0.0.0");
+ dst_mask_str ? dst_mask_str
+ : CISCO_HOST_WILDCARD_MASK);
else
- sseq = acl_cisco_get_seq(acl, action, src_str,
- src_mask_str ? src_mask_str
- : "0.0.0.0",
- "0.0.0.0", "255.255.255.255");
+ sseq = acl_cisco_get_seq(
+ acl, action, src_str,
+ src_mask_str ? src_mask_str
+ : CISCO_HOST_WILDCARD_MASK,
+ "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
} else {
if (dst_str != NULL)
- sseq = acl_cisco_get_seq(acl, action, "0.0.0.0",
- "255.255.255.255", dst_str,
- dst_mask_str ? dst_mask_str
- : "0.0.0.0");
+ sseq = acl_cisco_get_seq(
+ acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
+ dst_str,
+ dst_mask_str ? dst_mask_str
+ : CISCO_HOST_WILDCARD_MASK);
else
- sseq = acl_cisco_get_seq(acl, action, "0.0.0.0",
- "255.255.255.255", "0.0.0.0",
- "255.255.255.255");
+ sseq = acl_cisco_get_seq(
+ acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
+ "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
}
if (sseq == -1)
return CMD_WARNING;
@@ -522,7 +507,7 @@ DEFPY_YANG(
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
acl = nb_running_get_entry(dnode, NULL, true);
- if (prefix == NULL) {
+ if (prefix_str == NULL) {
memset(&pany, 0, sizeof(pany));
pany.family = AF_INET;
sseq = acl_zebra_get_seq(acl, action, &pany, exact);
diff --git a/lib/filter_nb.c b/lib/filter_nb.c
index 91691d2f1d..8838a48abd 100644
--- a/lib/filter_nb.c
+++ b/lib/filter_nb.c
@@ -29,6 +29,7 @@
#include "lib/filter.h"
#include "lib/plist.h"
#include "lib/plist_int.h"
+#include "lib/routemap.h"
/* Helper function. */
static in_addr_t
@@ -40,6 +41,22 @@ ipv4_network_addr(in_addr_t hostaddr, int masklen)
return hostaddr & mask.s_addr;
}
+static void acl_notify_route_map(struct access_list *acl, int route_map_event)
+{
+ switch (route_map_event) {
+ case RMAP_EVENT_FILTER_ADDED:
+ if (acl->master->add_hook)
+ (*acl->master->add_hook)(acl);
+ break;
+ case RMAP_EVENT_FILTER_DELETED:
+ if (acl->master->delete_hook)
+ (*acl->master->delete_hook)(acl);
+ break;
+ }
+
+ route_map_notify_dependencies(acl->name, route_map_event);
+}
+
static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
{
int type = yang_dnode_get_enum(args->dnode, "../../type");
@@ -112,6 +129,19 @@ static void prefix_list_entry_set_empty(struct prefix_list_entry *ple)
ple->le = 0;
}
+/**
+ * Unsets the cisco style rule for addresses so it becomes disabled (the
+ * equivalent of setting: `0.0.0.0/32`).
+ *
+ * \param addr address part.
+ * \param mask mask part.
+ */
+static void cisco_unset_addr_mask(struct in_addr *addr, struct in_addr *mask)
+{
+ addr->s_addr = INADDR_ANY;
+ mask->s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
+}
+
/*
* XPath: /frr-filter:lib/access-list
*/
@@ -255,6 +285,8 @@ lib_access_list_entry_action_modify(struct nb_cb_modify_args *args)
else
f->type = FILTER_DENY;
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
+
return NB_OK;
}
@@ -275,6 +307,8 @@ lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
fz = &f->u.zfilter;
yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL);
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
+
return NB_OK;
}
@@ -291,6 +325,8 @@ lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
fz = &f->u.zfilter;
memset(&fz->prefix, 0, sizeof(fz->prefix));
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
+
return NB_OK;
}
@@ -310,6 +346,8 @@ lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args)
fz = &f->u.zfilter;
fz->exact = yang_dnode_get_bool(args->dnode, NULL);
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
+
return NB_OK;
}
@@ -326,6 +364,8 @@ lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args)
fz = &f->u.zfilter;
fz->exact = 0;
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
+
return NB_OK;
}
@@ -345,7 +385,9 @@ lib_access_list_entry_host_modify(struct nb_cb_modify_args *args)
f->cisco = 1;
fc = &f->u.cfilter;
yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
- fc->addr_mask.s_addr = INADDR_ANY;
+ fc->addr_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -361,8 +403,9 @@ lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args)
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
- fc->addr.s_addr = INADDR_ANY;
- fc->addr_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -386,6 +429,9 @@ lib_access_list_entry_network_modify(struct nb_cb_modify_args *args)
yang_dnode_get_prefix(&p, args->dnode, NULL);
fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen);
masklen2ip(p.prefixlen, &fc->addr_mask);
+ fc->addr_mask.s_addr = ~fc->addr_mask.s_addr;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -401,8 +447,9 @@ lib_access_list_entry_network_destroy(struct nb_cb_destroy_args *args)
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
- fc->addr.s_addr = INADDR_ANY;
- fc->addr_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -423,7 +470,9 @@ lib_access_list_entry_source_any_create(struct nb_cb_create_args *args)
f->cisco = 1;
fc = &f->u.cfilter;
fc->addr.s_addr = INADDR_ANY;
- fc->addr_mask.s_addr = INADDR_NONE;
+ fc->addr_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -439,8 +488,9 @@ lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args)
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
- fc->addr.s_addr = INADDR_ANY;
- fc->addr_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -461,7 +511,9 @@ static int lib_access_list_entry_destination_host_modify(
fc = &f->u.cfilter;
fc->extended = 1;
yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
- fc->mask_mask.s_addr = INADDR_ANY;
+ fc->mask_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -478,8 +530,9 @@ static int lib_access_list_entry_destination_host_destroy(
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
fc->extended = 0;
- fc->mask.s_addr = INADDR_ANY;
- fc->mask_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -503,6 +556,9 @@ static int lib_access_list_entry_destination_network_modify(
yang_dnode_get_prefix(&p, args->dnode, NULL);
fc->mask.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen);
masklen2ip(p.prefixlen, &fc->mask_mask);
+ fc->mask_mask.s_addr = ~fc->mask_mask.s_addr;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -519,8 +575,9 @@ static int lib_access_list_entry_destination_network_destroy(
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
fc->extended = 0;
- fc->mask.s_addr = INADDR_ANY;
- fc->mask_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -541,7 +598,9 @@ static int lib_access_list_entry_destination_any_create(
fc = &f->u.cfilter;
fc->extended = 1;
fc->mask.s_addr = INADDR_ANY;
- fc->mask_mask.s_addr = INADDR_NONE;
+ fc->mask_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
return NB_OK;
}
@@ -558,8 +617,9 @@ static int lib_access_list_entry_destination_any_destroy(
f = nb_running_get_entry(args->dnode, NULL, true);
fc = &f->u.cfilter;
fc->extended = 0;
- fc->mask.s_addr = INADDR_ANY;
- fc->mask_mask.s_addr = INADDR_NONE;
+ cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
+
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
return NB_OK;
}
@@ -594,6 +654,8 @@ static int lib_access_list_entry_any_create(struct nb_cb_create_args *args)
break;
}
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
+
return NB_OK;
}
@@ -609,6 +671,8 @@ static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args)
fz = &f->u.zfilter;
fz->prefix.family = 0;
+ acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
+
return NB_OK;
}
diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c
index fbb97d2dd5..2066e4c96d 100644
--- a/lib/grammar_sandbox_main.c
+++ b/lib/grammar_sandbox_main.c
@@ -55,7 +55,7 @@ int main(int argc, char **argv)
vty_init(master, true);
lib_cmd_init();
yang_init(true);
- nb_init(master, NULL, 0);
+ nb_init(master, NULL, 0, false);
vty_stdio(vty_do_exit);
diff --git a/lib/hash.c b/lib/hash.c
index 7f8a237047..85982774ac 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -77,9 +77,20 @@ void *hash_alloc_intern(void *arg)
return arg;
}
+/*
+ * ssq = ssq + (new^2 - old^2)
+ * = ssq + ((new + old) * (new - old))
+ */
#define hash_update_ssq(hz, old, new) \
- atomic_fetch_add_explicit(&hz->stats.ssq, (new + old) * (new - old), \
- memory_order_relaxed);
+ do { \
+ int _adjust = (new + old) * (new - old); \
+ if (_adjust < 0) \
+ atomic_fetch_sub_explicit(&hz->stats.ssq, -_adjust, \
+ memory_order_relaxed); \
+ else \
+ atomic_fetch_add_explicit(&hz->stats.ssq, _adjust, \
+ memory_order_relaxed); \
+ } while (0)
/* Expand hash if the chain length exceeds the threshold. */
static void hash_expand(struct hash *hash)
diff --git a/lib/if.c b/lib/if.c
index d8392708e1..10db574dc4 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -188,7 +188,9 @@ void if_destroy_via_zapi(struct interface *ifp)
if (ifp_master.destroy_hook)
(*ifp_master.destroy_hook)(ifp);
+ ifp->oldifindex = ifp->ifindex;
if_set_index(ifp, IFINDEX_INTERNAL);
+
if (!ifp->configured)
if_delete(&ifp);
}
diff --git a/lib/if.h b/lib/if.h
index 1fb0757db2..a2a40d0957 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -224,6 +224,8 @@ struct interface {
not work as expected.
*/
ifindex_t ifindex;
+ ifindex_t oldifindex;
+
/*
* ifindex of parent interface, if any
*/
diff --git a/lib/keychain.c b/lib/keychain.c
index 251211734b..82fd6a65f2 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -1041,6 +1041,8 @@ static int keychain_config_write(struct vty *vty)
}
vty_out(vty, "\n");
}
+
+ vty_out(vty, " exit\n");
}
vty_out(vty, "!\n");
}
diff --git a/lib/ldp_sync.c b/lib/ldp_sync.c
new file mode 100644
index 0000000000..5dd045d88d
--- /dev/null
+++ b/lib/ldp_sync.c
@@ -0,0 +1,93 @@
+/*
+ * ldp_sync.c: LDP-SYNC handling routines
+ * Copyright (C) 2020 Volta Networks, Inc.
+ *
+ * This program 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "memory.h"
+#include "prefix.h"
+#include "log.h"
+#include "thread.h"
+#include "stream.h"
+#include "zclient.h"
+#include "table.h"
+#include "vty.h"
+#include "ldp_sync.h"
+
+/* Library code */
+DEFINE_MTYPE_STATIC(LIB, LDP_SYNC_INFO, "LDP SYNC info")
+
+/*
+ * ldp_sync_info_create - Allocate the LDP_SYNC information
+ */
+struct ldp_sync_info *ldp_sync_info_create(void)
+{
+ struct ldp_sync_info *ldp_sync_info;
+
+ ldp_sync_info = XCALLOC(MTYPE_LDP_SYNC_INFO,
+ sizeof(struct ldp_sync_info));
+ assert(ldp_sync_info);
+
+ ldp_sync_info->flags = 0;
+ ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
+ ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
+ ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
+ ldp_sync_info->t_holddown = NULL;
+ return ldp_sync_info;
+}
+
+/*
+ * ldp_sync_info_free - Free the LDP_SYNC information.
+ */
+void ldp_sync_info_free(struct ldp_sync_info **ldp_sync_info)
+{
+ if (*ldp_sync_info)
+ XFREE(MTYPE_LDP_SYNC_INFO, *ldp_sync_info);
+}
+
+bool ldp_sync_if_is_enabled(struct ldp_sync_info *ldp_sync_info)
+{
+ /* return true if LDP-SYNC is configured on this interface */
+ if (ldp_sync_info &&
+ ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
+ ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP)
+ return true;
+
+ return false;
+}
+
+bool ldp_sync_if_down(struct ldp_sync_info *ldp_sync_info)
+{
+ /* Stop LDP-SYNC on this interface:
+ * if holddown timer is running stop it
+ * update state
+ */
+ if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) {
+ if (ldp_sync_info->t_holddown != NULL) {
+ THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
+ ldp_sync_info->t_holddown = NULL;
+ }
+ if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_UP)
+ ldp_sync_info->state =
+ LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
+ return true;
+ }
+
+ return false;
+}
diff --git a/lib/ldp_sync.h b/lib/ldp_sync.h
new file mode 100644
index 0000000000..daede566f0
--- /dev/null
+++ b/lib/ldp_sync.h
@@ -0,0 +1,91 @@
+/*
+ * Defines and structures common to LDP-Sync for OSPFv2 and OSPFv3 and ISIS
+ * Copyright (C) 2020 Volta Networks, Inc.
+ *
+ * This program 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _LIBLDPSYNC_H
+#define _LIBLDPSYNC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* LDP-IGP Sync values */
+#define LDP_SYNC_FLAG_ENABLE (1 << 0) /* LDP-SYNC enabled */
+#define LDP_SYNC_FLAG_HOLDDOWN (1 << 1) /* Holddown timer enabled */
+#define LDP_SYNC_FLAG_IF_CONFIG (1 << 2) /* LDP-SYNC enabled on interface */
+#define LDP_SYNC_FLAG_SET_METRIC (1 << 3) /* Metric has been set on ISIS intf */
+
+#define LDP_IGP_SYNC_DEFAULT 0
+#define LDP_IGP_SYNC_ENABLED 1
+
+#define LDP_IGP_SYNC_STATE_NOT_REQUIRED 0
+#define LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP 1
+#define LDP_IGP_SYNC_STATE_REQUIRED_UP 2
+
+#define LDP_IGP_SYNC_HOLDDOWN_DEFAULT 0
+
+#define LDP_IGP_SYNC_HELLO_TIMEOUT 1
+
+/* LDP-IGP Sync structures */
+struct ldp_sync_info_cmd {
+ uint16_t flags;
+ uint16_t holddown; /* timer value */
+ uint32_t sequence; /* hello sequence number */
+ struct thread *t_hello; /* hello timer for detecting LDP going down */
+};
+
+struct ldp_sync_info {
+ uint16_t flags; /* indicate if set on interface or globally */
+ uint8_t enabled; /* enabled */
+ uint8_t state; /* running state */
+ uint16_t holddown; /* timer value */
+ struct thread *t_holddown; /* holddown timer*/
+ uint32_t metric[2]; /* isis interface metric */
+};
+
+/* Prototypes. */
+extern struct ldp_sync_info *ldp_sync_info_create(void);
+extern bool ldp_sync_if_is_enabled(struct ldp_sync_info *ldp_sync_info);
+extern bool ldp_sync_if_down(struct ldp_sync_info *ldp_sync_info);
+extern void ldp_sync_info_free(struct ldp_sync_info **ldp_sync_info);
+
+struct ldp_igp_sync_announce {
+ int proto;
+};
+
+struct ldp_igp_sync_if_state {
+ ifindex_t ifindex;
+ bool sync_start;
+};
+
+struct ldp_igp_sync_if_state_req {
+ int proto;
+ ifindex_t ifindex;
+ char name[INTERFACE_NAMSIZ];
+};
+
+struct ldp_igp_sync_hello {
+ int proto;
+ unsigned int sequence;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBLDPSYNC_H */
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 2597eb61e2..500a02aacd 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -719,7 +719,7 @@ struct thread_master *frr_init(void)
debug_init_cli();
- nb_init(master, di->yang_modules, di->n_yang_modules);
+ nb_init(master, di->yang_modules, di->n_yang_modules, true);
if (nb_db_init() != NB_OK)
flog_warn(EC_LIB_NB_DATABASE,
"%s: failed to initialize northbound database",
diff --git a/lib/mpls.h b/lib/mpls.h
index 8922a36664..74bd7aae3e 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -72,8 +72,7 @@ extern "C" {
/* Maximum # labels that can be pushed. */
#define MPLS_MAX_LABELS 16
-#define IS_MPLS_RESERVED_LABEL(label) \
- (label >= MPLS_LABEL_RESERVED_MIN && label <= MPLS_LABEL_RESERVED_MAX)
+#define IS_MPLS_RESERVED_LABEL(label) (label <= MPLS_LABEL_RESERVED_MAX)
#define IS_MPLS_UNRESERVED_LABEL(label) \
(label >= MPLS_LABEL_UNRESERVED_MIN \
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 8ae001e42a..687cac4062 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -940,6 +940,12 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
nhg_hooks.add_nexthop(nhgc, nh);
}
+ if (intf) {
+ struct interface *ifp = if_lookup_by_name_all_vrf(intf);
+
+ if (ifp)
+ ifp->configured = true;
+ }
return CMD_SUCCESS;
}
@@ -952,24 +958,29 @@ static struct cmd_node nexthop_group_node = {
.config_write = nexthop_group_write,
};
-void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
+void nexthop_group_write_nexthop_simple(struct vty *vty,
+ const struct nexthop *nh,
+ char *altifname)
{
char buf[100];
- struct vrf *vrf;
- int i;
+ char *ifname;
vty_out(vty, "nexthop ");
+ if (altifname)
+ ifname = altifname;
+ else
+ ifname = (char *)ifindex2ifname(nh->ifindex, nh->vrf_id);
+
switch (nh->type) {
case NEXTHOP_TYPE_IFINDEX:
- vty_out(vty, "%s", ifindex2ifname(nh->ifindex, nh->vrf_id));
+ vty_out(vty, "%s", ifname);
break;
case NEXTHOP_TYPE_IPV4:
vty_out(vty, "%s", inet_ntoa(nh->gate.ipv4));
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out(vty, "%s %s", inet_ntoa(nh->gate.ipv4),
- ifindex2ifname(nh->ifindex, nh->vrf_id));
+ vty_out(vty, "%s %s", inet_ntoa(nh->gate.ipv4), ifname);
break;
case NEXTHOP_TYPE_IPV6:
vty_out(vty, "%s",
@@ -978,11 +989,19 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
case NEXTHOP_TYPE_IPV6_IFINDEX:
vty_out(vty, "%s %s",
inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)),
- ifindex2ifname(nh->ifindex, nh->vrf_id));
+ ifname);
break;
case NEXTHOP_TYPE_BLACKHOLE:
break;
}
+}
+
+void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
+{
+ struct vrf *vrf;
+ int i;
+
+ nexthop_group_write_nexthop_simple(vty, nh, NULL);
if (nh->vrf_id != VRF_DEFAULT) {
vrf = vrf_lookup_by_id(nh->vrf_id);
@@ -1229,6 +1248,7 @@ void nexthop_group_interface_state_change(struct interface *ifp,
if (ifp->ifindex != nhop.ifindex)
continue;
+ ifp->configured = true;
nh = nexthop_new();
memcpy(nh, &nhop, sizeof(nhop));
diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h
index 0b5ac91bb2..5f7bde0def 100644
--- a/lib/nexthop_group.h
+++ b/lib/nexthop_group.h
@@ -135,6 +135,9 @@ extern bool nexthop_group_equal(const struct nexthop_group *nhg1,
extern struct nexthop_group_cmd *nhgc_find(const char *name);
+extern void nexthop_group_write_nexthop_simple(struct vty *vty,
+ const struct nexthop *nh,
+ char *altifname);
extern void nexthop_group_write_nexthop(struct vty *vty,
const struct nexthop *nh);
diff --git a/lib/northbound.c b/lib/northbound.c
index 29e843a84e..18500a8bd2 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -57,6 +57,8 @@ static struct {
const void *owner_user;
} running_config_mgmt_lock;
+/* Knob to record config transaction */
+static bool nb_db_enabled;
/*
* Global lock used to prevent multiple configuration transactions from
* happening concurrently.
@@ -732,7 +734,7 @@ void nb_candidate_commit_apply(struct nb_transaction *transaction,
nb_config_replace(running_config, transaction->config, true);
/* Record transaction. */
- if (save_transaction
+ if (save_transaction && nb_db_enabled
&& nb_db_transaction_save(transaction, transaction_id) != NB_OK)
flog_warn(EC_LIB_NB_TRANSACTION_RECORD_FAILED,
"%s: failed to record transaction", __func__);
@@ -2216,7 +2218,7 @@ static void nb_load_callbacks(const struct frr_yang_module_info *module)
void nb_init(struct thread_master *tm,
const struct frr_yang_module_info *const modules[],
- size_t nmodules)
+ size_t nmodules, bool db_enabled)
{
unsigned int errors = 0;
@@ -2241,6 +2243,8 @@ void nb_init(struct thread_master *tm,
exit(1);
}
+ nb_db_enabled = db_enabled;
+
/* Create an empty running configuration. */
running_config = nb_config_new(NULL);
running_config_entries = hash_create(running_config_entry_key_make,
diff --git a/lib/northbound.h b/lib/northbound.h
index fa5ac5616c..7b481273cb 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -1239,10 +1239,13 @@ extern const char *nb_client_name(enum nb_client client);
*
* nmodules
* Size of the modules array.
+ *
+ * db_enabled
+ * Set this to record the transactions in the transaction log.
*/
extern void nb_init(struct thread_master *tm,
const struct frr_yang_module_info *const modules[],
- size_t nmodules);
+ size_t nmodules, bool db_enabled);
/*
* Finish the northbound layer gracefully. Should be called only when the daemon
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 2f6aef5398..ee080bca3f 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -63,7 +63,15 @@ static int nb_cli_classic_commit(struct vty *vty)
context.user = vty;
ret = nb_candidate_commit(&context, vty->candidate_config, true, NULL,
NULL, errmsg, sizeof(errmsg));
- if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) {
+ switch (ret) {
+ case NB_OK:
+ /* Successful commit. Print warnings (if any). */
+ if (strlen(errmsg) > 0)
+ vty_out(vty, "%s\n", errmsg);
+ break;
+ case NB_ERR_NO_CHANGES:
+ break;
+ default:
vty_out(vty, "%% Configuration failed.\n\n");
vty_show_nb_errors(vty, ret, errmsg);
if (vty->t_pending_commit)
@@ -74,9 +82,7 @@ static int nb_cli_classic_commit(struct vty *vty)
/* Regenerate candidate for consistency. */
nb_config_replace(vty->candidate_config, running_config, true);
return CMD_WARNING_CONFIG_FAILED;
- } else if (strlen(errmsg) > 0)
- /* Successful commit. Print warnings (if any). */
- vty_out(vty, "%s\n", errmsg);
+ }
return CMD_SUCCESS;
}
diff --git a/lib/pbr.h b/lib/pbr.h
index fd183d7115..53a63122cc 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -129,6 +129,8 @@ struct pbr_rule {
#define MATCH_FRAGMENT_INVERSE_SET (1 << 9)
#define MATCH_ICMP_SET (1 << 10)
#define MATCH_PROTOCOL_SET (1 << 11)
+#define MATCH_FLOW_LABEL_SET (1 << 12)
+#define MATCH_FLOW_LABEL_INVERSE_SET (1 << 13)
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
struct pbr_rule *zrule);
diff --git a/lib/prefix.c b/lib/prefix.c
index 697e1a6239..0a88f9eca6 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -188,6 +188,10 @@ int prefix_match(const struct prefix *n, const struct prefix *p)
if (n->family == AF_FLOWSPEC) {
/* prefixlen is unused. look at fs prefix len */
+ if (n->u.prefix_flowspec.family !=
+ p->u.prefix_flowspec.family)
+ return 0;
+
if (n->u.prefix_flowspec.prefixlen >
p->u.prefix_flowspec.prefixlen)
return 0;
@@ -325,6 +329,8 @@ void prefix_copy(union prefixptr udest, union prefixconstptr usrc)
len = src->u.prefix_flowspec.prefixlen;
dest->u.prefix_flowspec.prefixlen =
src->u.prefix_flowspec.prefixlen;
+ dest->u.prefix_flowspec.family =
+ src->u.prefix_flowspec.family;
dest->family = src->family;
temp = XCALLOC(MTYPE_PREFIX_FLOWSPEC, len);
dest->u.prefix_flowspec.ptr = (uintptr_t)temp;
@@ -374,6 +380,9 @@ int prefix_same(union prefixconstptr up1, union prefixconstptr up2)
sizeof(struct evpn_addr)))
return 1;
if (p1->family == AF_FLOWSPEC) {
+ if (p1->u.prefix_flowspec.family !=
+ p2->u.prefix_flowspec.family)
+ return 0;
if (p1->u.prefix_flowspec.prefixlen !=
p2->u.prefix_flowspec.prefixlen)
return 0;
@@ -415,6 +424,10 @@ int prefix_cmp(union prefixconstptr up1, union prefixconstptr up2)
pp1 = (const uint8_t *)p1->u.prefix_flowspec.ptr;
pp2 = (const uint8_t *)p2->u.prefix_flowspec.ptr;
+ if (p1->u.prefix_flowspec.family !=
+ p2->u.prefix_flowspec.family)
+ return 1;
+
if (p1->u.prefix_flowspec.prefixlen !=
p2->u.prefix_flowspec.prefixlen)
return numcmp(p1->u.prefix_flowspec.prefixlen,
diff --git a/lib/prefix.h b/lib/prefix.h
index 400f07386f..2a33d532c8 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -176,6 +176,7 @@ struct evpn_addr {
#endif
struct flowspec_prefix {
+ uint8_t family;
uint16_t prefixlen; /* length in bytes */
uintptr_t ptr;
};
diff --git a/lib/privs.c b/lib/privs.c
index 5c7e1240e2..dc43b7279d 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -1020,11 +1020,11 @@ void zprivs_get_ids(struct zprivs_ids_t *ids)
ids->uid_priv = getuid();
(zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
- : (ids->uid_normal = -1);
+ : (ids->uid_normal = (uid_t)-1);
(zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
- : (ids->gid_normal = -1);
+ : (ids->gid_normal = (uid_t)-1);
(zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
- : (ids->gid_vty = -1);
+ : (ids->gid_vty = (uid_t)-1);
return;
}
diff --git a/lib/stream.c b/lib/stream.c
index 6e62e11380..dc207c16a4 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -268,6 +268,30 @@ bool stream_forward_getp2(struct stream *s, size_t size)
return true;
}
+void stream_rewind_getp(struct stream *s, size_t size)
+{
+ STREAM_VERIFY_SANE(s);
+
+ if (size > s->getp || !GETP_VALID(s, s->getp - size)) {
+ STREAM_BOUND_WARN(s, "rewind getp");
+ return;
+ }
+
+ s->getp -= size;
+}
+
+bool stream_rewind_getp2(struct stream *s, size_t size)
+{
+ STREAM_VERIFY_SANE(s);
+
+ if (size > s->getp || !GETP_VALID(s, s->getp - size))
+ return false;
+
+ s->getp -= size;
+
+ return true;
+}
+
void stream_forward_endp(struct stream *s, size_t size)
{
STREAM_VERIFY_SANE(s);
diff --git a/lib/stream.h b/lib/stream.h
index f2c16b3486..23f85d809b 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -160,7 +160,6 @@ extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
extern size_t stream_get_getp(const struct stream *s);
extern size_t stream_get_endp(const struct stream *s);
extern size_t stream_get_size(const struct stream *s);
-extern uint8_t *stream_get_data(struct stream *s);
/**
* Create a new stream structure; copy offset bytes from s1 to the new
@@ -174,6 +173,8 @@ extern void stream_set_getp(struct stream *, size_t);
extern void stream_set_endp(struct stream *, size_t);
extern void stream_forward_getp(struct stream *, size_t);
extern bool stream_forward_getp2(struct stream *, size_t);
+extern void stream_rewind_getp(struct stream *s, size_t size);
+extern bool stream_rewind_getp2(struct stream *s, size_t size);
extern void stream_forward_endp(struct stream *, size_t);
extern bool stream_forward_endp2(struct stream *, size_t);
@@ -461,6 +462,12 @@ static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out)
goto stream_failure; \
} while (0)
+#define STREAM_REWIND_GETP(STR, SIZE) \
+ do { \
+ if (!stream_rewind_getp2((STR), (SIZE))) \
+ goto stream_failure; \
+ } while (0)
+
#define STREAM_FORWARD_ENDP(STR, SIZE) \
do { \
if (!stream_forward_endp2((STR), (SIZE))) \
diff --git a/lib/subdir.am b/lib/subdir.am
index 1feaa56d13..b8bcee139b 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -42,6 +42,7 @@ lib_libfrr_la_SOURCES = \
lib/jhash.c \
lib/json.c \
lib/keychain.c \
+ lib/ldp_sync.c \
lib/lib_errors.c \
lib/lib_vty.c \
lib/libfrr.c \
@@ -198,6 +199,7 @@ pkginclude_HEADERS += \
lib/jhash.h \
lib/json.h \
lib/keychain.h \
+ lib/ldp_sync.h \
lib/lib_errors.h \
lib/lib_vty.h \
lib/libfrr.h \
diff --git a/lib/yang.c b/lib/yang.c
index 6ab9492d52..9bfdcb858c 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -84,6 +84,9 @@ static const char *yang_module_imp_clb(const char *mod_name,
static const char *const frr_native_modules[] = {
"frr-interface",
"frr-vrf",
+ "frr-routing",
+ "frr-route-map",
+ "frr-nexthop",
"frr-ripd",
"frr-ripngd",
"frr-isisd",
diff --git a/lib/zclient.c b/lib/zclient.c
index 808aa18bbe..b842e7c31b 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -871,6 +871,37 @@ static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
break;
}
+ if (next1->srte_color < next2->srte_color)
+ return -1;
+ if (next1->srte_color > next2->srte_color)
+ return 1;
+
+ if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
+ CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+
+ if (!CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
+ CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
+ return -1;
+
+ if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
+ !CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
+ return 1;
+
+ if (next1->backup_num > 0 || next2->backup_num > 0) {
+
+ if (next1->backup_num < next2->backup_num)
+ return -1;
+
+ if (next1->backup_num > next2->backup_num)
+ return 1;
+
+ ret = memcmp(next1->backup_idx,
+ next2->backup_idx, next1->backup_num);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
return 0;
}
@@ -2037,7 +2068,7 @@ static void zebra_interface_if_set_value(struct stream *s,
uint8_t link_params_status = 0;
ifindex_t old_ifindex, new_ifindex;
- old_ifindex = ifp->ifindex;
+ old_ifindex = ifp->oldifindex;
/* Read interface's index. */
STREAM_GETL(s, new_ifindex);
if_set_index(ifp, new_ifindex);
diff --git a/lib/zclient.h b/lib/zclient.h
index dab384d5ec..b8444e8a86 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -391,6 +391,11 @@ struct zmsghdr {
} __attribute__((packed));
#define ZAPI_HEADER_CMD_LOCATION offsetof(struct zmsghdr, command)
+/*
+ * ZAPI nexthop. Note that these are sorted when associated with ZAPI routes,
+ * and that sorting must be aligned with the sorting of nexthops in
+ * lib/nexthop.c. Any new fields must be accounted for in zapi_nexthop_cmp().
+ */
struct zapi_nexthop {
enum nexthop_types_t type;
vrf_id_t vrf_id;
@@ -950,6 +955,14 @@ enum zapi_opaque_registry {
LINK_STATE_REQUEST = 1,
/* Update containing link-state db info */
LINK_STATE_UPDATE = 2,
+ /* Request LDP-SYNC state from LDP */
+ LDP_IGP_SYNC_IF_STATE_REQUEST = 3,
+ /* Update containing LDP IGP Sync State info */
+ LDP_IGP_SYNC_IF_STATE_UPDATE = 4,
+ /* Announce that LDP is up */
+ LDP_IGP_SYNC_ANNOUNCE_UPDATE = 5,
+ /* Heartbeat indicating that LDP is running */
+ LDP_IGP_SYNC_HELLO_UPDATE = 6,
};
/* Send the hello message.
diff --git a/lib/zlog_targets.c b/lib/zlog_targets.c
index b23ab073b4..8f4c2a46a8 100644
--- a/lib/zlog_targets.c
+++ b/lib/zlog_targets.c
@@ -225,10 +225,11 @@ static bool zlog_file_cycle(struct zlog_cfg_file *zcf)
zlt->zt.logfn_sigsafe = zlog_fd_sigsafe;
} while (0);
- old = zlog_target_replace(&zcf->active->zt, &zlt->zt);
+ old = zlog_target_replace(zcf->active ? &zcf->active->zt : NULL,
+ zlt ? &zlt->zt : NULL);
zcf->active = zlt;
- zlog_file_target_free(container_of(old, struct zlt_fd, zt));
+ zlog_file_target_free(container_of_null(old, struct zlt_fd, zt));
return rv;
}