summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c6
-rw-r--r--bgpd/bgp_clist.c3
-rw-r--r--bgpd/bgp_community.c8
-rw-r--r--bgpd/bgp_dump.c2
-rw-r--r--bgpd/bgp_ecommunity.c22
-rw-r--r--bgpd/bgp_filter.c2
-rw-r--r--bgpd/bgp_lcommunity.c6
-rw-r--r--bgpd/bgp_routemap.c22
-rw-r--r--bgpd/bgp_vty.c27
-rw-r--r--debian/.gitignore13
-rw-r--r--doc/developer/building-frr-for-centos6.rst2
-rw-r--r--doc/developer/building-frr-for-centos7.rst2
-rw-r--r--doc/developer/building-frr-for-debian8.rst2
-rw-r--r--doc/developer/building-frr-for-debian9.rst2
-rw-r--r--doc/developer/building-frr-for-fedora.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1404.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1604.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1804.rst2
-rw-r--r--doc/developer/lists.rst32
-rw-r--r--doc/figures/nodes.dot1
-rw-r--r--doc/user/installation.rst14
-rw-r--r--doc/user/isisd.rst6
-rw-r--r--doc/user/ospf6d.rst2
-rw-r--r--doc/user/ospfd.rst19
-rw-r--r--doc/user/overview.rst9
-rw-r--r--doc/user/routemap.rst4
-rw-r--r--doc/user/sharp.rst2
-rw-r--r--doc/user/zebra.rst19
-rw-r--r--eigrpd/eigrp_cli.c920
-rw-r--r--eigrpd/eigrp_main.c9
-rw-r--r--eigrpd/eigrp_northbound.c1584
-rw-r--r--eigrpd/eigrp_vty.c1071
-rw-r--r--eigrpd/eigrp_vty.h1
-rw-r--r--eigrpd/eigrpd.h47
-rw-r--r--eigrpd/subdir.am10
-rw-r--r--isisd/isis_misc.c6
-rw-r--r--isisd/isis_tlvs.c2
-rw-r--r--ldpd/lde.c39
-rw-r--r--ldpd/lde.h1
-rw-r--r--ldpd/lde_lib.c3
-rw-r--r--lib/atomlist.h10
-rw-r--r--lib/command.c12
-rw-r--r--lib/command.h1
-rw-r--r--lib/command_graph.c2
-rw-r--r--lib/command_match.c6
-rw-r--r--lib/filter.c2
-rw-r--r--lib/frrstr.c2
-rw-r--r--lib/log.c17
-rw-r--r--lib/logicalrouter.c158
-rw-r--r--lib/logicalrouter.h49
-rw-r--r--lib/netns_other.c2
-rw-r--r--lib/ns.h12
-rw-r--r--lib/plist.c2
-rw-r--r--lib/pqueue.c185
-rw-r--r--lib/pqueue.h54
-rw-r--r--lib/ptm_lib.c2
-rw-r--r--lib/subdir.am5
-rw-r--r--lib/thread.c98
-rw-r--r--lib/thread.h7
-rw-r--r--lib/typerb.c5
-rw-r--r--lib/typerb.h23
-rw-r--r--lib/typesafe.c13
-rw-r--r--lib/typesafe.h45
-rw-r--r--lib/vty.c9
-rw-r--r--ospfd/ospf_flood.c25
-rw-r--r--ospfd/ospf_lsa.c160
-rw-r--r--ospfd/ospf_lsa.h4
-rw-r--r--ospfd/ospf_nsm.c28
-rw-r--r--ospfd/ospf_vty.c17
-rw-r--r--ospfd/ospf_zebra.c132
-rw-r--r--ospfd/ospfd.c32
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--sharpd/sharp_vty.c41
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--staticd/static_nht.c165
-rw-r--r--staticd/static_nht.h29
-rw-r--r--staticd/static_routes.c6
-rw-r--r--staticd/static_routes.h26
-rw-r--r--staticd/static_zebra.c22
-rw-r--r--staticd/static_zebra.h3
-rw-r--r--tests/lib/cli/test_commands.c3
-rw-r--r--tests/lib/cxxcompat.c2
-rw-r--r--tests/lib/test_timer_correctness.c1
-rw-r--r--tests/lib/test_timer_performance.c1
-rw-r--r--tests/lib/test_typelist.h16
-rw-r--r--tests/topotests/bgp_comm-list_delete/__init__.py0
-rw-r--r--tests/topotests/bgp_comm-list_delete/r1/bgpd.conf9
-rw-r--r--tests/topotests/bgp_comm-list_delete/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_comm-list_delete/r2/bgpd.conf11
-rw-r--r--tests/topotests/bgp_comm-list_delete/r2/zebra.conf6
-rw-r--r--tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py105
-rw-r--r--tests/topotests/lib/bgp.py12
-rw-r--r--tools/coccinelle/ctype_cast.cocci11
-rw-r--r--tools/gen_northbound_callbacks.c73
-rw-r--r--tools/start-stop-daemon.c2
-rw-r--r--vrrpd/vrrp.c29
-rw-r--r--vrrpd/vrrp_zebra.c8
-rwxr-xr-xvtysh/extract.pl.in6
-rw-r--r--vtysh/vtysh.c54
-rw-r--r--vtysh/vtysh.h1
-rw-r--r--vtysh/vtysh_config.c41
-rw-r--r--yang/frr-eigrpd.yang2
-rw-r--r--yang/frr-filter.yang353
-rw-r--r--yang/frr-route-map.yang404
-rw-r--r--yang/subdir.am4
-rw-r--r--zebra/if_netlink.c6
-rw-r--r--zebra/main.c4
-rw-r--r--zebra/zebra_ns.c19
-rw-r--r--zebra/zebra_rib.c7
-rw-r--r--zebra/zebra_rnh.c2
-rw-r--r--zebra/zebra_vty.c2
-rw-r--r--zebra/zebra_vxlan.c69
112 files changed, 4381 insertions, 2234 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index cf0d28887e..1385345d64 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1885,7 +1885,7 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
const char *p = buf;
/* Skip seperators (space for sequences, ',' for sets). */
- while (isspace((int)*p) || *p == ',')
+ while (isspace((unsigned char)*p) || *p == ',')
p++;
/* Check the end of the string and type specify characters
@@ -1920,14 +1920,14 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
}
/* Check actual AS value. */
- if (isdigit((int)*p)) {
+ if (isdigit((unsigned char)*p)) {
as_t asval;
*token = as_token_asval;
asval = (*p - '0');
p++;
- while (isdigit((int)*p)) {
+ while (isdigit((unsigned char)*p)) {
asval *= 10;
asval += (*p - '0');
p++;
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index ff2ea6f7cd..29e668d179 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -157,7 +157,7 @@ community_list_insert(struct community_list_handler *ch, const char *name,
/* If name is made by all digit character. We treat it as
number. */
for (number = 0, i = 0; i < strlen(name); i++) {
- if (isdigit((int)name[i]))
+ if (isdigit((unsigned char)name[i]))
number = (number * 10) + (name[i] - '0');
else
break;
@@ -823,6 +823,7 @@ struct community *community_list_match_delete(struct community *com,
/* Delete all of the communities we flagged for deletion */
for (i = delete_index - 1; i >= 0; i--) {
val = community_val_get(com, com_index_to_delete[i]);
+ val = htonl(val);
community_del_val(com, &val);
}
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 6fc52ff9e0..22d61f702d 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -651,7 +651,7 @@ community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
const char *p = buf;
/* Skip white space. */
- while (isspace((int)*p))
+ while (isspace((unsigned char)*p))
p++;
/* Check the end of the line. */
@@ -659,7 +659,7 @@ community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
return NULL;
/* Well known community string check. */
- if (isalpha((int)*p)) {
+ if (isalpha((unsigned char)*p)) {
if (strncmp(p, "internet", strlen("internet")) == 0) {
*val = COMMUNITY_INTERNET;
*token = community_token_no_export;
@@ -770,13 +770,13 @@ community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
}
/* Community value. */
- if (isdigit((int)*p)) {
+ if (isdigit((unsigned char)*p)) {
int separator = 0;
int digit = 0;
uint32_t community_low = 0;
uint32_t community_high = 0;
- while (isdigit((int)*p) || *p == ':') {
+ while (isdigit((unsigned char)*p) || *p == ':') {
if (*p == ':') {
if (separator) {
*token = community_token_unknown;
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index 7ea6ae586b..535f36ab5e 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -584,7 +584,7 @@ static unsigned int bgp_dump_parse_time(const char *str)
len = strlen(str);
for (i = 0; i < len; i++) {
- if (isdigit((int)str[i])) {
+ if (isdigit((unsigned char)str[i])) {
time *= 10;
time += str[i] - '0';
} else if (str[i] == 'H' || str[i] == 'h') {
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 76bd0e815e..850b85aa6a 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -352,7 +352,7 @@ static const char *ecommunity_gettoken(const char *str,
char buf[INET_ADDRSTRLEN + 1];
/* Skip white space. */
- while (isspace((int)*p)) {
+ while (isspace((unsigned char)*p)) {
p++;
str++;
}
@@ -362,38 +362,38 @@ static const char *ecommunity_gettoken(const char *str,
return NULL;
/* "rt" and "soo" keyword parse. */
- if (!isdigit((int)*p)) {
+ if (!isdigit((unsigned char)*p)) {
/* "rt" match check. */
- if (tolower((int)*p) == 'r') {
+ if (tolower((unsigned char)*p) == 'r') {
p++;
- if (tolower((int)*p) == 't') {
+ if (tolower((unsigned char)*p) == 't') {
p++;
*token = ecommunity_token_rt;
return p;
}
- if (isspace((int)*p) || *p == '\0') {
+ if (isspace((unsigned char)*p) || *p == '\0') {
*token = ecommunity_token_rt;
return p;
}
goto error;
}
/* "soo" match check. */
- else if (tolower((int)*p) == 's') {
+ else if (tolower((unsigned char)*p) == 's') {
p++;
- if (tolower((int)*p) == 'o') {
+ if (tolower((unsigned char)*p) == 'o') {
p++;
- if (tolower((int)*p) == 'o') {
+ if (tolower((unsigned char)*p) == 'o') {
p++;
*token = ecommunity_token_soo;
return p;
}
- if (isspace((int)*p) || *p == '\0') {
+ if (isspace((unsigned char)*p) || *p == '\0') {
*token = ecommunity_token_soo;
return p;
}
goto error;
}
- if (isspace((int)*p) || *p == '\0') {
+ if (isspace((unsigned char)*p) || *p == '\0') {
*token = ecommunity_token_soo;
return p;
}
@@ -415,7 +415,7 @@ static const char *ecommunity_gettoken(const char *str,
* OPQR: Four byte value
*
*/
- while (isdigit((int)*p) || *p == ':' || *p == '.') {
+ while (isdigit((unsigned char)*p) || *p == ':' || *p == '.') {
if (*p == ':') {
if (separator)
goto error;
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index d4f608d40f..30a964a22c 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -193,7 +193,7 @@ static struct as_list *as_list_insert(const char *name)
/* If name is made by all digit character. We treat it as
number. */
for (number = 0, i = 0; i < strlen(name); i++) {
- if (isdigit((int)name[i]))
+ if (isdigit((unsigned char)name[i]))
number = (number * 10) + (name[i] - '0');
else
break;
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index 098374fa9f..2b09a2954e 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -359,7 +359,7 @@ static const char *lcommunity_gettoken(const char *str,
const char *p = str;
/* Skip white space. */
- while (isspace((int)*p)) {
+ while (isspace((unsigned char)*p)) {
p++;
str++;
}
@@ -369,14 +369,14 @@ static const char *lcommunity_gettoken(const char *str,
return NULL;
/* Community value. */
- if (isdigit((int)*p)) {
+ if (isdigit((unsigned char)*p)) {
int separator = 0;
int digit = 0;
uint32_t globaladmin = 0;
uint32_t localdata1 = 0;
uint32_t localdata2 = 0;
- while (isdigit((int)*p) || *p == ':') {
+ while (isdigit((unsigned char)*p) || *p == ':') {
if (*p == ':') {
if (separator == 2) {
*token = lcommunity_token_unknown;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index dd3382a1e7..5ffc416dc5 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2091,12 +2091,19 @@ route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
static void *route_set_lcommunity_delete_compile(const char *arg)
{
struct rmap_community *rcom;
+ char **splits;
+ int num;
- rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ frrstr_split(arg, " ", &splits, &num);
- rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
rcom->name_hash = bgp_clist_hash_key(rcom->name);
+ for (int i = 0; i < num; i++)
+ XFREE(MTYPE_TMP, splits[i]);
+ XFREE(MTYPE_TMP, splits);
+
return rcom;
}
@@ -2174,12 +2181,19 @@ route_set_community_delete(void *rule, const struct prefix *prefix,
static void *route_set_community_delete_compile(const char *arg)
{
struct rmap_community *rcom;
+ char **splits;
+ int num;
- rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ frrstr_split(arg, " ", &splits, &num);
- rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
rcom->name_hash = bgp_clist_hash_key(rcom->name);
+ for (int i = 0; i < num; i++)
+ XFREE(MTYPE_TMP, splits[i]);
+ XFREE(MTYPE_TMP, splits);
+
return rcom;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 27042017dd..58a202d510 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -7770,7 +7770,7 @@ static void bgp_show_bestpath_json(struct bgp *bgp, json_object *json)
/* Show BGP peer's summary information. */
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
- bool use_json, json_object *json)
+ bool use_json)
{
struct peer *peer;
struct listnode *node, *nnode;
@@ -7781,6 +7781,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
int len;
int max_neighbor_width = 0;
int pfx_rcd_safi;
+ json_object *json = NULL;
json_object *json_peer = NULL;
json_object *json_peers = NULL;
struct peer_af *paf;
@@ -7795,9 +7796,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
pfx_rcd_safi = safi;
if (use_json) {
- if (json == NULL)
- json = json_object_new_object();
-
+ json = json_object_new_object();
json_peers = json_object_new_object();
} else {
/* Loop over all neighbors that will be displayed to determine
@@ -8202,8 +8201,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
}
static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
- int safi, bool use_json,
- json_object *json)
+ int safi, bool use_json)
{
int is_first = 1;
int afi_wildcard = (afi == AFI_MAX);
@@ -8221,6 +8219,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
while (safi < SAFI_MAX) {
if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
nbr_output = true;
+
if (is_wildcard) {
/*
* So limit output to those afi/safi
@@ -8229,8 +8228,6 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
* them
*/
if (use_json) {
- json = json_object_new_object();
-
if (!is_first)
vty_out(vty, ",\n");
else
@@ -8245,8 +8242,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
safi));
}
}
- bgp_show_summary(vty, bgp, afi, safi, use_json,
- json);
+ bgp_show_summary(vty, bgp, afi, safi, use_json);
}
safi++;
if (!safi_wildcard)
@@ -8272,7 +8268,6 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
{
struct listnode *node, *nnode;
struct bgp *bgp;
- json_object *json = NULL;
int is_first = 1;
bool nbr_output = false;
@@ -8282,8 +8277,6 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
nbr_output = true;
if (use_json) {
- json = json_object_new_object();
-
if (!is_first)
vty_out(vty, ",\n");
else
@@ -8299,7 +8292,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
? VRF_DEFAULT_NAME
: bgp->name);
}
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, json);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
}
if (use_json)
@@ -8330,8 +8323,8 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
return CMD_WARNING;
}
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json,
- NULL);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi,
+ use_json);
return CMD_SUCCESS;
}
}
@@ -8339,7 +8332,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
bgp = bgp_get_default();
if (bgp)
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, NULL);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
else {
if (use_json)
vty_out(vty, "{}\n");
diff --git a/debian/.gitignore b/debian/.gitignore
new file mode 100644
index 0000000000..0b267c6f5c
--- /dev/null
+++ b/debian/.gitignore
@@ -0,0 +1,13 @@
+
+/.debhelper/
+/*/
+!/tests/
+!/source
+
+/*.log
+/*.substvars
+/*.debhelper
+/autoreconf.*
+/files
+/frr.init
+/frr.service
diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst
index ee0ffc2bf7..3d9edbe3a1 100644
--- a/doc/developer/building-frr-for-centos6.rst
+++ b/doc/developer/building-frr-for-centos6.rst
@@ -45,7 +45,7 @@ Add packages:
sudo yum install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
- json-c-devel pam-devel flex epel-release c-ares-devel
+ json-c-devel pam-devel flex epel-release c-ares-devel libcap-devel
Install newer version of bison (CentOS 6 package source is too old) from CentOS
7:
diff --git a/doc/developer/building-frr-for-centos7.rst b/doc/developer/building-frr-for-centos7.rst
index 67f71bc3a5..cd90d41ffb 100644
--- a/doc/developer/building-frr-for-centos7.rst
+++ b/doc/developer/building-frr-for-centos7.rst
@@ -21,7 +21,7 @@ Add packages:
sudo yum install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \
- python-devel systemd-devel python-sphinx
+ python-devel systemd-devel python-sphinx libcap-devel
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-debian8.rst b/doc/developer/building-frr-for-debian8.rst
index 76f927853d..c12bf46f8d 100644
--- a/doc/developer/building-frr-for-debian8.rst
+++ b/doc/developer/building-frr-for-debian8.rst
@@ -18,7 +18,7 @@ Add packages:
sudo apt-get install git autoconf automake libtool make \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex python3-pip \
libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev \
- libsnmp-dev
+ libsnmp-dev libcap-dev
Install newer pytest (>3.0) from pip
diff --git a/doc/developer/building-frr-for-debian9.rst b/doc/developer/building-frr-for-debian9.rst
index e58c59f451..f976b9f49a 100644
--- a/doc/developer/building-frr-for-debian9.rst
+++ b/doc/developer/building-frr-for-debian9.rst
@@ -11,7 +11,7 @@ Add packages:
sudo apt-get install git autoconf automake libtool make \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
libc-ares-dev python3-dev python3-pytest python3-sphinx build-essential \
- libsnmp-dev libsystemd-dev
+ libsnmp-dev libsystemd-dev libcap-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-fedora.rst b/doc/developer/building-frr-for-fedora.rst
index 0bfd43e93c..d8405eb351 100644
--- a/doc/developer/building-frr-for-fedora.rst
+++ b/doc/developer/building-frr-for-fedora.rst
@@ -14,7 +14,7 @@ Installing Dependencies
sudo dnf install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig json-c-devel \
pam-devel python3-pytest bison flex c-ares-devel python3-devel \
- python3-sphinx perl-core patch systemd-devel
+ python3-sphinx perl-core patch systemd-devel libcap-devel
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst
index 569b3bded1..cc54415266 100644
--- a/doc/developer/building-frr-for-ubuntu1404.rst
+++ b/doc/developer/building-frr-for-ubuntu1404.rst
@@ -14,7 +14,7 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev python3-sphinx install-info build-essential \
- libsnmp-dev perl
+ libsnmp-dev perl libcap-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst
index 03852a62aa..63c6f8648c 100644
--- a/doc/developer/building-frr-for-ubuntu1604.rst
+++ b/doc/developer/building-frr-for-ubuntu1604.rst
@@ -14,7 +14,7 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
- install-info build-essential libsystemd-dev libsnmp-dev perl
+ install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst
index 96c0efe02a..9d85957d88 100644
--- a/doc/developer/building-frr-for-ubuntu1804.rst
+++ b/doc/developer/building-frr-for-ubuntu1804.rst
@@ -14,7 +14,7 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
- install-info build-essential libsystemd-dev libsnmp-dev perl
+ install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index fc47a67e42..5f020060ce 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -611,6 +611,38 @@ Head removal (pop) and deallocation:
* note nothing between wrlock() and unlock() */
XFREE(MTYPE_ITEM, i);
+FAQ
+---
+
+Why is the list head not ``const`` in the list APIs?
+ The semantics that a ``const`` list head would imply are not obvious. It
+ could mean any of the following:
+
+ * the list just shouldn't be allocated/deallocated, but may be modified.
+ This doesn't actually work since the list head needs to be modified for
+ inserting or deleting items.
+
+ * the list shouldn't be modified, but items can. This may make sense for
+ iterating, but it's not exactly consistent - an item might be on more
+ than one list, does it apply to all of them? If not, which one?
+
+ * neither the list nor the items should be modified. This is consistent,
+ but hard to do without creating a ``const`` copy of every single list
+ function. Ease of use trumps this.
+
+Why is there no "is this item on a/the list" test?
+ It's slow for several of the data structures, and the work of adding it
+ just hasn't been done. It can certainly be added if it's needed.
+
+Why is it ``PREDECL`` + ``DECLARE`` instead of ``DECLARE`` + ``DEFINE``?
+ The rule is that a ``DEFINE`` must be in a ``.c`` file, and linked exactly
+ once because it defines some kind of global symbol. This is not the case
+ for the data structure macros; they only define ``static`` symbols and it
+ is perfectly fine to include both ``PREDECL`` and ``DECLARE`` in a header
+ file. It is also perfectly fine to have the same ``DECLARE`` statement in
+ 2 ``.c`` files, but only **if the macro arguments are identical.** Maybe
+ don't do that unless you really need it.
+
FRR lists
---------
diff --git a/doc/figures/nodes.dot b/doc/figures/nodes.dot
index d0e234958f..b548b5529a 100644
--- a/doc/figures/nodes.dot
+++ b/doc/figures/nodes.dot
@@ -55,7 +55,6 @@ digraph climodes {
CONFIG_NODE -> KEYCHAIN_KEY_NODE [ label="key (0-2147483647)" ];
KEYCHAIN_NODE -> KEYCHAIN_KEY_NODE [ label="key (0-2147483647)" ];
KEYCHAIN_KEY_NODE -> KEYCHAIN_NODE [ label="no key (0-2147483647)" ];
- CONFIG_NODE -> LOGICALROUTER_NODE [ label="logical-router (1-65535) ns NAME" ];
CONFIG_NODE -> VRF_NODE [ label="vrf NAME" ];
CONFIG_NODE -> INTERFACE_NODE [ label="interface IFNAME vrf NAME" ];
INTERFACE_NODE -> LINK_PARAMS_NODE [ label="link-params" ];
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index b45c83ca1c..45549dccad 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -149,6 +149,11 @@ options from the list below.
Turn off building of pimd. On some BSD platforms pimd will not build properly due
to lack of kernel support.
+.. option:: --disable-vrrpd
+
+ Turn off building of vrrpd. Linux is required for vrrpd support;
+ other platforms are not supported.
+
.. option:: --disable-pbrd
Turn off building of pbrd. This daemon currently requires linux in order to function
@@ -194,11 +199,6 @@ options from the list below.
Disable building of the example OSPF-API client.
-.. option:: --disable-ospf-ri
-
- Disable support for OSPF Router Information (RFC4970 & RFC5088) this
- requires support for Opaque LSAs and Traffic Engineering.
-
.. option:: --disable-isisd
Do not build isisd.
@@ -211,10 +211,6 @@ options from the list below.
Enable IS-IS topology generator.
-.. option:: --enable-isis-te
-
- Enable Traffic Engineering Extension for ISIS (RFC5305)
-
.. option:: --enable-realms
Enable the support of Linux Realms. Convert tag values from 1-255 into a
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index f7607a54f7..6684a83e1f 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -423,6 +423,12 @@ Showing ISIS information
Traffic Engineering
===================
+.. note::
+
+ At this time, FRR offers partial support for some of the routing
+ protocol extensions that can be used with MPLS-TE. FRR does not
+ support a complete RSVP-TE solution currently.
+
.. index:: mpls-te on
.. clicmd:: mpls-te on
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 6413c62995..2300cb0e19 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -195,7 +195,7 @@ Example of ospf6d configured on one interface and area:
ipv6 ospf6 instance-id 0
!
router ospf6
- router-id 212.17.55.53
+ ospf6 router-id 212.17.55.53
area 0.0.0.0 range 2001:770:105:2::/64
interface eth0 area 0.0.0.0
!
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 83e14d474f..3772cf9556 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -69,7 +69,7 @@ The instance number should be specified in the config when addressing a particul
.. code-block:: frr
router ospf 5
- router-id 1.2.3.4
+ ospf router-id 1.2.3.4
area 0.0.0.0 authentication message-digest
...
@@ -906,10 +906,13 @@ Opaque LSA
.. index:: no capability opaque
.. clicmd:: no capability opaque
- *ospfd* supports Opaque LSA (:rfc:`2370`) as fundamental for MPLS Traffic
- Engineering LSA. Prior to used MPLS TE, opaque-lsa must be enable in the
- configuration file. Alternate command could be "mpls-te on"
- (:ref:`ospf-traffic-engineering`).
+ *ospfd* supports Opaque LSA (:rfc:`2370`) as partial support for
+ MPLS Traffic Engineering LSAs. The opaque-lsa capability must be
+ enabled in the configuration. An alternate command could be
+ "mpls-te on" (:ref:`ospf-traffic-engineering`). Note that FRR
+ offers only partial support for some of the routing protocol
+ extensions that are used with MPLS-TE; it does not support a
+ complete RSVP-TE solution.
.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external)
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external)
@@ -936,6 +939,12 @@ Opaque LSA
Traffic Engineering
===================
+.. note::
+
+ At this time, FRR offers partial support for some of the routing
+ protocol extensions that can be used with MPLS-TE. FRR does not
+ support a complete RSVP-TE solution currently.
+
.. index:: mpls-te on
.. clicmd:: mpls-te on
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index 7f8ea392dc..5f9a7b937e 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -239,6 +239,15 @@ The indicators have the following semantics:
* :mark:`CP` - control plane only (i.e. BGP route server / route reflector)
* :mark:`N` - daemon/feature not supported by operating system
+
+Known Kernel Issues:
+====================
+
+- Linux
+ v6 Route Replacement - Linux kernels before 4.11 can cause issues with v6 route deletion when you
+ have ecmp routes installed into the kernel. This especially becomes apparent if the route is being
+ transformed from one ecmp path to another.
+
.. _supported-rfcs:
Supported RFCs
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index bac61cbc58..09cbd7c7b0 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -153,8 +153,8 @@ Route Map Match Command
Matches the specified `ipv4_addr`.
-.. index:: match aspath AS_PATH
-.. clicmd:: match aspath AS_PATH
+.. index:: match as-path AS_PATH
+.. clicmd:: match as-path AS_PATH
Matches the specified `as_path`.
diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst
index 4568c2a901..111e9dc9e8 100644
--- a/doc/user/sharp.rst
+++ b/doc/user/sharp.rst
@@ -71,7 +71,7 @@ keyword. At present, no sharp commands will be preserved in the config.
be used for pop and forward operations when the specified label is seen.
.. index:: sharp watch
-.. clicmd:: [no] sharp watch <nexthop|import> <A.B.C.D|X:X::X:X> [connected]
+.. clicmd:: [no] sharp watch <nexthop <A.B.C.D|X:X::X:X>|import <A.B.C.D/M:X:X::X:X/M> [connected]
Instruct zebra to monitor and notify sharp when the specified nexthop is
changed. The notification from zebra is written into the debug log.
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 2744cb66ed..50c518d456 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -193,18 +193,25 @@ Standard Commands
Link Parameters Commands
------------------------
+.. note::
+
+ At this time, FRR offers partial support for some of the routing
+ protocol extensions that can be used with MPLS-TE. FRR does not
+ support a complete RSVP-TE solution currently.
+
.. index:: link-params
.. clicmd:: link-params
.. index:: no link-param
.. clicmd:: no link-param
- Enter into the link parameters sub node. At least 'enable' must be set to
- activate the link parameters, and consequently Traffic Engineering on this
- interface. MPLS-TE must be enable at the OSPF
- (:ref:`ospf-traffic-engineering`) or ISIS (:ref:`isis-traffic-engineering`)
- router level in complement to this. Disable link parameters for this
- interface.
+ Enter into the link parameters sub node. At least 'enable' must be
+ set to activate the link parameters, and consequently routing
+ information that could be used as part of Traffic Engineering on
+ this interface. MPLS-TE must be enable at the OSPF
+ (:ref:`ospf-traffic-engineering`) or ISIS
+ (:ref:`isis-traffic-engineering`) router level in complement to
+ this. Disable link parameters for this interface.
Under link parameter statement, the following commands set the different TE values:
diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c
new file mode 100644
index 0000000000..ba657a7d5d
--- /dev/null
+++ b/eigrpd/eigrp_cli.c
@@ -0,0 +1,920 @@
+/*
+ * EIGRP daemon CLI implementation.
+ *
+ * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
+ * Rafael Zalamena
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <zebra.h>
+
+#include "lib/command.h"
+#include "lib/log.h"
+#include "lib/northbound_cli.h"
+
+#include "eigrp_structs.h"
+#include "eigrpd.h"
+#include "eigrp_zebra.h"
+
+#ifndef VTYSH_EXTRACT_PL
+#include "eigrpd/eigrp_cli_clippy.c"
+#endif /* VTYSH_EXTRACT_PL */
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance
+ */
+DEFPY_NOSH(
+ router_eigrp,
+ router_eigrp_cmd,
+ "router eigrp (1-65535)$as",
+ ROUTER_STR
+ EIGRP_STR
+ AS_STR)
+{
+ char xpath[XPATH_MAXLEN];
+ int rv;
+
+ snprintf(xpath, sizeof(xpath),
+ "/frr-eigrpd:eigrpd/instance[asn='%s'][vrf='']",
+ as_str);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ rv = nb_cli_apply_changes(vty, NULL);
+ if (rv == CMD_SUCCESS)
+ VTY_PUSH_XPATH(EIGRP_NODE, xpath);
+
+ return rv;
+}
+
+DEFPY_NOSH(
+ no_router_eigrp,
+ no_router_eigrp_cmd,
+ "no router eigrp (1-65535)$as",
+ NO_STR
+ ROUTER_STR
+ EIGRP_STR
+ AS_STR)
+{
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath),
+ "/frr-eigrpd:eigrpd/instance[asn='%s'][vrf='']",
+ as_str);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *asn = yang_dnode_get_string(dnode, "./asn");
+
+ vty_out(vty, "router eigrp %s\n", asn);
+}
+
+void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode)
+{
+ vty_out(vty, "!\n");
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/router-id
+ */
+DEFPY(
+ eigrp_router_id,
+ eigrp_router_id_cmd,
+ "eigrp router-id A.B.C.D$addr",
+ EIGRP_STR
+ "Router ID for this EIGRP process\n"
+ "EIGRP Router-ID in IP address format\n")
+{
+ nb_cli_enqueue_change(vty, "./router-id", NB_OP_MODIFY, addr_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_router_id,
+ no_eigrp_router_id_cmd,
+ "no eigrp router-id [A.B.C.D]",
+ NO_STR
+ EIGRP_STR
+ "Router ID for this EIGRP process\n"
+ "EIGRP Router-ID in IP address format\n")
+{
+ nb_cli_enqueue_change(vty, "./router-id", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_router_id(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *router_id = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " eigrp router-id %s\n", router_id);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/passive-interface
+ */
+DEFPY(
+ eigrp_passive_interface,
+ eigrp_passive_interface_cmd,
+ "[no] passive-interface IFNAME",
+ NO_STR
+ "Suppress routing updates on an interface\n"
+ "Interface to suppress on\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty, "./passive-interface",
+ NB_OP_DESTROY, ifname);
+ else
+ nb_cli_enqueue_change(vty, "./passive-interface",
+ NB_OP_CREATE, ifname);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_passive_interface(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *ifname = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " passive-interface %s\n", ifname);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/active-time
+ */
+DEFPY(
+ eigrp_timers_active,
+ eigrp_timers_active_cmd,
+ "timers active-time <(1-65535)$timer|disabled$disabled>",
+ "Adjust routing timers\n"
+ "Time limit for active state\n"
+ "Active state time limit in seconds\n"
+ "Disable time limit for active state\n")
+{
+ if (disabled)
+ nb_cli_enqueue_change(vty, "./active-time", NB_OP_MODIFY, "0");
+ else
+ nb_cli_enqueue_change(vty, "./active-time",
+ NB_OP_MODIFY, timer_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_timers_active,
+ no_eigrp_timers_active_cmd,
+ "no timers active-time [<(1-65535)|disabled>]",
+ NO_STR
+ "Adjust routing timers\n"
+ "Time limit for active state\n"
+ "Active state time limit in seconds\n"
+ "Disable time limit for active state\n")
+{
+ nb_cli_enqueue_change(vty, "./active-time", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_active_time(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *timer = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " timers active-time %s\n", timer);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/variance
+ */
+DEFPY(
+ eigrp_variance,
+ eigrp_variance_cmd,
+ "variance (1-128)$variance",
+ "Control load balancing variance\n"
+ "Metric variance multiplier\n")
+{
+ nb_cli_enqueue_change(vty, "./variance", NB_OP_MODIFY, variance_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_variance,
+ no_eigrp_variance_cmd,
+ "no variance [(1-128)]",
+ NO_STR
+ "Control load balancing variance\n"
+ "Metric variance multiplier\n")
+{
+ nb_cli_enqueue_change(vty, "./variance", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_variance(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *variance = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " variance %s\n", variance);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/maximum-paths
+ */
+DEFPY(
+ eigrp_maximum_paths,
+ eigrp_maximum_paths_cmd,
+ "maximum-paths (1-32)$maximum_paths",
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ nb_cli_enqueue_change(vty, "./maximum-paths", NB_OP_MODIFY,
+ maximum_paths_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_maximum_paths,
+ no_eigrp_maximum_paths_cmd,
+ "no maximum-paths [(1-32)]",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ nb_cli_enqueue_change(vty, "./maximum-paths", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_maximum_paths(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *maximum_paths = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " maximum-paths %s\n", maximum_paths);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K1
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K2
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K3
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K4
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K5
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K6
+ */
+DEFPY(
+ eigrp_metric_weights,
+ eigrp_metric_weights_cmd,
+ "metric weights (0-255)$k1 (0-255)$k2 (0-255)$k3 (0-255)$k4 (0-255)$k5 [(0-255)$k6]",
+ "Modify metrics and parameters for advertisement\n"
+ "Modify metric coefficients\n"
+ "K1\n"
+ "K2\n"
+ "K3\n"
+ "K4\n"
+ "K5\n"
+ "K6\n")
+{
+ nb_cli_enqueue_change(vty, "./metric-weights/K1", NB_OP_MODIFY, k1_str);
+ nb_cli_enqueue_change(vty, "./metric-weights/K2", NB_OP_MODIFY, k2_str);
+ nb_cli_enqueue_change(vty, "./metric-weights/K3", NB_OP_MODIFY, k3_str);
+ nb_cli_enqueue_change(vty, "./metric-weights/K4", NB_OP_MODIFY, k4_str);
+ nb_cli_enqueue_change(vty, "./metric-weights/K5", NB_OP_MODIFY, k5_str);
+ if (k6)
+ nb_cli_enqueue_change(vty, "./metric-weights/K6",
+ NB_OP_MODIFY, k6_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_metric_weights,
+ no_eigrp_metric_weights_cmd,
+ "no metric weights [(0-255) (0-255) (0-255) (0-255) (0-255) (0-255)]",
+ NO_STR
+ "Modify metrics and parameters for advertisement\n"
+ "Modify metric coefficients\n"
+ "K1\n"
+ "K2\n"
+ "K3\n"
+ "K4\n"
+ "K5\n"
+ "K6\n")
+{
+ nb_cli_enqueue_change(vty, "./metric-weights/K1", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./metric-weights/K2", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./metric-weights/K3", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./metric-weights/K4", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./metric-weights/K5", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./metric-weights/K6", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_metrics(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *k1, *k2, *k3, *k4, *k5, *k6;
+
+ k1 = yang_dnode_exists(dnode, "./K1") ?
+ yang_dnode_get_string(dnode, "./K1") : "0";
+ k2 = yang_dnode_exists(dnode, "./K2") ?
+ yang_dnode_get_string(dnode, "./K2") : "0";
+ k3 = yang_dnode_exists(dnode, "./K3") ?
+ yang_dnode_get_string(dnode, "./K3") : "0";
+ k4 = yang_dnode_exists(dnode, "./K4") ?
+ yang_dnode_get_string(dnode, "./K4") : "0";
+ k5 = yang_dnode_exists(dnode, "./K5") ?
+ yang_dnode_get_string(dnode, "./K5") : "0";
+ k6 = yang_dnode_exists(dnode, "./K6") ?
+ yang_dnode_get_string(dnode, "./K6") : "0";
+
+ vty_out(vty, " metric weights %s %s %s %s %s",
+ k1, k2, k3, k4, k5);
+ if (k6)
+ vty_out(vty, " %s", k6);
+ vty_out(vty, "\n");
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/network
+ */
+DEFPY(
+ eigrp_network,
+ eigrp_network_cmd,
+ "[no] network A.B.C.D/M$prefix",
+ NO_STR
+ "Enable routing on an IP network\n"
+ "EIGRP network prefix\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty, "./network", NB_OP_DESTROY,
+ prefix_str);
+ else
+ nb_cli_enqueue_change(vty, "./network", NB_OP_CREATE,
+ prefix_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_network(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *prefix = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " network %s\n", prefix);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/neighbor
+ */
+DEFPY(
+ eigrp_neighbor,
+ eigrp_neighbor_cmd,
+ "[no] neighbor A.B.C.D$addr",
+ NO_STR
+ "Specify a neighbor router\n"
+ "Neighbor address\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty, "./neighbor", NB_OP_DESTROY,
+ addr_str);
+ else
+ nb_cli_enqueue_change(vty, "./neighbor", NB_OP_CREATE,
+ addr_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_neighbor(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *prefix = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " neighbor %s\n", prefix);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/route-map
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/bandwidth
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/delay
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/reliability
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/load
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/mtu
+ */
+DEFPY(
+ eigrp_redistribute_source_metric,
+ eigrp_redistribute_source_metric_cmd,
+ "[no] redistribute " FRR_REDIST_STR_EIGRPD
+ "$proto [metric (1-4294967295)$bw (0-4294967295)$delay (0-255)$rlbt (1-255)$load (1-65535)$mtu]",
+ NO_STR
+ REDIST_STR
+ FRR_REDIST_HELP_STR_EIGRPD
+ "Metric for redistributed routes\n"
+ "Bandwidth metric in Kbits per second\n"
+ "EIGRP delay metric, in 10 microsecond units\n"
+ "EIGRP reliability metric where 255 is 100% reliable2 ?\n"
+ "EIGRP Effective bandwidth metric (Loading) where 255 is 100% loaded\n"
+ "EIGRP MTU of the path\n")
+{
+ char xpath[XPATH_MAXLEN], xpath_metric[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./redistribute[protocol='%s']", proto);
+
+ if (no) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+ }
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ if (bw == 0 || delay == 0 || rlbt == 0 || load == 0 || mtu == 0)
+ return nb_cli_apply_changes(vty, NULL);
+
+ snprintf(xpath_metric, sizeof(xpath_metric), "%s/metrics/bandwidth",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_metric, NB_OP_MODIFY, bw_str);
+ snprintf(xpath_metric, sizeof(xpath_metric), "%s/metrics/delay", xpath);
+ nb_cli_enqueue_change(vty, xpath_metric, NB_OP_MODIFY, delay_str);
+ snprintf(xpath_metric, sizeof(xpath_metric), "%s/metrics/reliability",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_metric, NB_OP_MODIFY, rlbt_str);
+ snprintf(xpath_metric, sizeof(xpath_metric), "%s/metrics/load", xpath);
+ nb_cli_enqueue_change(vty, xpath_metric, NB_OP_MODIFY, load_str);
+ snprintf(xpath_metric, sizeof(xpath_metric), "%s/metrics/mtu", xpath);
+ nb_cli_enqueue_change(vty, xpath_metric, NB_OP_MODIFY, mtu_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_redistribute(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *proto = yang_dnode_get_string(dnode, "./protocol");
+ const char *bw, *delay, *load, *mtu, *rlbt;
+
+ bw = yang_dnode_exists(dnode, "./metrics/bandwidth") ?
+ yang_dnode_get_string(dnode, "./metrics/bandwidth") : NULL;
+ delay = yang_dnode_exists(dnode, "./metrics/delay") ?
+ yang_dnode_get_string(dnode, "./metrics/delay") : NULL;
+ rlbt = yang_dnode_exists(dnode, "./metrics/reliability") ?
+ yang_dnode_get_string(dnode, "./metrics/reliability") : NULL;
+ load = yang_dnode_exists(dnode, "./metrics/load") ?
+ yang_dnode_get_string(dnode, "./metrics/load") : NULL;
+ mtu = yang_dnode_exists(dnode, "./metrics/mtu") ?
+ yang_dnode_get_string(dnode, "./metrics/mtu") : NULL;
+
+ vty_out(vty, " redistribute %s", proto);
+ if (bw || rlbt || delay || load || mtu)
+ vty_out(vty, " metric %s %s %s %s %s", bw, delay, rlbt, load,
+ mtu);
+ vty_out(vty, "\n");
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/delay
+ */
+DEFPY(
+ eigrp_if_delay,
+ eigrp_if_delay_cmd,
+ "delay (1-16777215)$delay",
+ "Specify interface throughput delay\n"
+ "Throughput delay (tens of microseconds)\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/delay",
+ NB_OP_MODIFY, delay_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_if_delay,
+ no_eigrp_if_delay_cmd,
+ "no delay [(1-16777215)]",
+ NO_STR
+ "Specify interface throughput delay\n"
+ "Throughput delay (tens of microseconds)\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/delay",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_delay(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *delay = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " delay %s\n", delay);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/bandwidth
+ */
+DEFPY(
+ eigrp_if_bandwidth,
+ eigrp_if_bandwidth_cmd,
+ "eigrp bandwidth (1-10000000)$bw",
+ EIGRP_STR
+ "Set bandwidth informational parameter\n"
+ "Bandwidth in kilobits\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/bandwidth",
+ NB_OP_MODIFY, bw_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_if_bandwidth,
+ no_eigrp_if_bandwidth_cmd,
+ "no eigrp bandwidth [(1-10000000)]",
+ NO_STR
+ EIGRP_STR
+ "Set bandwidth informational parameter\n"
+ "Bandwidth in kilobits\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/bandwidth",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_bandwidth(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *bandwidth = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " eigrp bandwidth %s\n", bandwidth);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hello-interval
+ */
+DEFPY(
+ eigrp_if_ip_hellointerval,
+ eigrp_if_ip_hellointerval_cmd,
+ "ip hello-interval eigrp (1-65535)$hello",
+ "Interface Internet Protocol config commands\n"
+ "Configures EIGRP hello interval\n"
+ EIGRP_STR
+ "Seconds between hello transmissions\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/hello-interval",
+ NB_OP_MODIFY, hello_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_if_ip_hellointerval,
+ no_eigrp_if_ip_hellointerval_cmd,
+ "no ip hello-interval eigrp [(1-65535)]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Configures EIGRP hello interval\n"
+ EIGRP_STR
+ "Seconds between hello transmissions\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/hello-interval",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+
+void eigrp_cli_show_hello_interval(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *hello = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " ip hello-interval eigrp %s\n", hello);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hold-time
+ */
+DEFPY(
+ eigrp_if_ip_holdinterval,
+ eigrp_if_ip_holdinterval_cmd,
+ "ip hold-time eigrp (1-65535)$hold",
+ "Interface Internet Protocol config commands\n"
+ "Configures EIGRP IPv4 hold time\n"
+ EIGRP_STR
+ "Seconds before neighbor is considered down\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/hold-time",
+ NB_OP_MODIFY, hold_str);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_if_ip_holdinterval,
+ no_eigrp_if_ip_holdinterval_cmd,
+ "no ip hold-time eigrp [(1-65535)]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Configures EIGRP IPv4 hold time\n"
+ EIGRP_STR
+ "Seconds before neighbor is considered down\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-eigrpd:eigrp/hold-time",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_hold_time(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *holdtime = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " ip hold-time eigrp %s\n", holdtime);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/split-horizon
+ */
+/* NOT implemented. */
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/summarize-addresses
+ */
+DEFPY(
+ eigrp_ip_summary_address,
+ eigrp_ip_summary_address_cmd,
+ "ip summary-address eigrp (1-65535)$as A.B.C.D/M$prefix",
+ "Interface Internet Protocol config commands\n"
+ "Perform address summarization\n"
+ EIGRP_STR
+ AS_STR
+ "Summary <network>/<length>, e.g. 192.168.0.0/16\n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/summarize-address", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_CREATE, prefix_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_ip_summary_address,
+ no_eigrp_ip_summary_address_cmd,
+ "no ip summary-address eigrp (1-65535)$as A.B.C.D/M$prefix",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Perform address summarization\n"
+ EIGRP_STR
+ AS_STR
+ "Summary <network>/<length>, e.g. 192.168.0.0/16\n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/summarize-address", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_DESTROY, prefix_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_summarize_address(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const struct eigrp_interface *eif = nb_running_get_entry(dnode, NULL,
+ true);
+ const char *summarize_address = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " ip summary-address eigrp %d %s\n",
+ eif->eigrp->AS, summarize_address);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/authentication
+ */
+DEFPY(
+ eigrp_authentication_mode,
+ eigrp_authentication_mode_cmd,
+ "ip authentication mode eigrp (1-65535)$as <md5|hmac-sha-256>$crypt",
+ "Interface Internet Protocol config commands\n"
+ "Authentication subcommands\n"
+ "Mode\n"
+ EIGRP_STR
+ AS_STR
+ "Keyed message digest\n"
+ "HMAC SHA256 algorithm \n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/authentication", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_MODIFY, crypt);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_authentication_mode,
+ no_eigrp_authentication_mode_cmd,
+ "no ip authentication mode eigrp (1-65535)$as [<md5|hmac-sha-256>]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Authentication subcommands\n"
+ "Mode\n"
+ EIGRP_STR
+ AS_STR
+ "Keyed message digest\n"
+ "HMAC SHA256 algorithm \n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/authentication", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_MODIFY, "none");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_authentication(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const struct eigrp_interface *eif = nb_running_get_entry(dnode, NULL,
+ true);
+ const char *crypt = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " ip authentication mode eigrp %d %s\n",
+ eif->eigrp->AS, crypt);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/keychain
+ */
+DEFPY(
+ eigrp_authentication_keychain,
+ eigrp_authentication_keychain_cmd,
+ "ip authentication key-chain eigrp (1-65535)$as WORD$name",
+ "Interface Internet Protocol config commands\n"
+ "Authentication subcommands\n"
+ "Key-chain\n"
+ EIGRP_STR
+ AS_STR
+ "Name of key-chain\n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/keychain", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_MODIFY, name);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(
+ no_eigrp_authentication_keychain,
+ no_eigrp_authentication_keychain_cmd,
+ "no ip authentication key-chain eigrp (1-65535)$as [WORD]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Authentication subcommands\n"
+ "Key-chain\n"
+ EIGRP_STR
+ AS_STR
+ "Name of key-chain\n")
+{
+ char xpath[XPATH_MAXLEN], xpath_auth[XPATH_MAXLEN + 64];
+
+ snprintf(xpath, sizeof(xpath), "./frr-eigrpd:eigrp/instance[asn='%s']",
+ as_str);
+ snprintf(xpath_auth, sizeof(xpath_auth), "%s/keychain", xpath);
+ nb_cli_enqueue_change(vty, xpath_auth, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void eigrp_cli_show_keychain(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const struct eigrp_interface *eif = nb_running_get_entry(dnode, NULL,
+ true);
+ const char *keychain = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " ip authentication key-chain eigrp %d %s\n",
+ eif->eigrp->AS, keychain);
+}
+
+
+/*
+ * CLI installation procedures.
+ */
+static struct cmd_node eigrp_node = {EIGRP_NODE, "%s(config-router)# ", 1};
+
+static int eigrp_config_write(struct vty *vty)
+{
+ struct lyd_node *dnode;
+ int written = 0;
+
+ dnode = yang_dnode_get(running_config->dnode, "/frr-eigrpd:eigrpd");
+ if (dnode) {
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ written = 1;
+ }
+
+ return written;
+}
+
+static struct cmd_node eigrp_interface_node = {INTERFACE_NODE,
+ "%s(config-if)# ", 1};
+
+
+static int eigrp_write_interface(struct vty *vty)
+{
+ struct lyd_node *dnode;
+ struct interface *ifp;
+ struct vrf *vrf;
+ int written = 0;
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+ FOR_ALL_INTERFACES(vrf, ifp) {
+ dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+ ifp->name, vrf->name);
+ if (dnode == NULL)
+ continue;
+
+ written = 1;
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ }
+ }
+
+ return written;
+}
+
+void
+eigrp_cli_init(void)
+{
+ install_element(CONFIG_NODE, &router_eigrp_cmd);
+ install_element(CONFIG_NODE, &no_router_eigrp_cmd);
+
+ install_node(&eigrp_node, eigrp_config_write);
+ install_default(EIGRP_NODE);
+
+ install_element(EIGRP_NODE, &eigrp_router_id_cmd);
+ install_element(EIGRP_NODE, &no_eigrp_router_id_cmd);
+ install_element(EIGRP_NODE, &eigrp_passive_interface_cmd);
+ install_element(EIGRP_NODE, &eigrp_timers_active_cmd);
+ install_element(EIGRP_NODE, &no_eigrp_timers_active_cmd);
+ install_element(EIGRP_NODE, &eigrp_variance_cmd);
+ install_element(EIGRP_NODE, &no_eigrp_variance_cmd);
+ install_element(EIGRP_NODE, &eigrp_maximum_paths_cmd);
+ install_element(EIGRP_NODE, &no_eigrp_maximum_paths_cmd);
+ install_element(EIGRP_NODE, &eigrp_metric_weights_cmd);
+ install_element(EIGRP_NODE, &no_eigrp_metric_weights_cmd);
+ install_element(EIGRP_NODE, &eigrp_network_cmd);
+ install_element(EIGRP_NODE, &eigrp_neighbor_cmd);
+ install_element(EIGRP_NODE, &eigrp_redistribute_source_metric_cmd);
+
+ install_node(&eigrp_interface_node, eigrp_write_interface);
+ if_cmd_init();
+
+ install_element(INTERFACE_NODE, &eigrp_if_delay_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_if_delay_cmd);
+ install_element(INTERFACE_NODE, &eigrp_if_bandwidth_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_if_bandwidth_cmd);
+ install_element(INTERFACE_NODE, &eigrp_if_ip_hellointerval_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_if_ip_hellointerval_cmd);
+ install_element(INTERFACE_NODE, &eigrp_if_ip_holdinterval_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_if_ip_holdinterval_cmd);
+ install_element(INTERFACE_NODE, &eigrp_ip_summary_address_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_ip_summary_address_cmd);
+ install_element(INTERFACE_NODE, &eigrp_authentication_mode_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_authentication_mode_cmd);
+ install_element(INTERFACE_NODE, &eigrp_authentication_keychain_cmd);
+ install_element(INTERFACE_NODE, &no_eigrp_authentication_keychain_cmd);
+}
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c
index 3db59a838b..1781a88173 100644
--- a/eigrpd/eigrp_main.c
+++ b/eigrpd/eigrp_main.c
@@ -90,10 +90,16 @@ struct option longopts[] = {{0}};
/* Master of threads. */
struct thread_master *master;
+/* Forward declaration of daemon info structure. */
+static struct frr_daemon_info eigrpd_di;
+
/* SIGHUP handler. */
static void sighup(void)
{
zlog_info("SIGHUP received");
+
+ /* Reload config file. */
+ vty_read_config(NULL, eigrpd_di.config_file, config_default);
}
/* SIGINT / SIGTERM handler. */
@@ -131,6 +137,7 @@ struct quagga_signal_t eigrp_signals[] = {
};
static const struct frr_yang_module_info *eigrpd_yang_modules[] = {
+ &frr_eigrpd_info,
&frr_interface_info,
};
@@ -187,7 +194,7 @@ int main(int argc, char **argv, char **envp)
eigrp_vty_init();
keychain_init();
eigrp_vty_show_init();
- eigrp_vty_if_init();
+ eigrp_cli_init();
#ifdef HAVE_SNMP
eigrp_snmp_init();
diff --git a/eigrpd/eigrp_northbound.c b/eigrpd/eigrp_northbound.c
new file mode 100644
index 0000000000..5f0c91809e
--- /dev/null
+++ b/eigrpd/eigrp_northbound.c
@@ -0,0 +1,1584 @@
+/*
+ * EIGRP daemon northbound implementation.
+ *
+ * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
+ * Rafael Zalamena
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <zebra.h>
+
+#include "lib/keychain.h"
+#include "lib/log.h"
+#include "lib/northbound.h"
+#include "lib/table.h"
+#include "lib/vrf.h"
+#include "lib/zclient.h"
+
+#include "eigrp_structs.h"
+#include "eigrpd.h"
+#include "eigrp_interface.h"
+#include "eigrp_network.h"
+#include "eigrp_zebra.h"
+
+/* Helper functions. */
+static void redistribute_get_metrics(const struct lyd_node *dnode,
+ struct eigrp_metrics *em)
+{
+ memset(em, 0, sizeof(*em));
+
+ if (yang_dnode_exists(dnode, "./bandwidth"))
+ em->bandwidth = yang_dnode_get_uint32(dnode, "./bandwidth");
+ if (yang_dnode_exists(dnode, "./delay"))
+ em->delay = yang_dnode_get_uint32(dnode, "./delay");
+#if 0 /* TODO: How does MTU work? */
+ if (yang_dnode_exists(dnode, "./mtu"))
+ em->mtu[0] = yang_dnode_get_uint32(dnode, "./mtu");
+#endif
+ if (yang_dnode_exists(dnode, "./load"))
+ em->load = yang_dnode_get_uint32(dnode, "./load");
+ if (yang_dnode_exists(dnode, "./reliability"))
+ em->reliability = yang_dnode_get_uint32(dnode, "./reliability");
+}
+
+static struct eigrp_interface *eigrp_interface_lookup(const struct eigrp *eigrp,
+ const char *ifname)
+{
+ struct eigrp_interface *eif;
+ struct listnode *ln;
+
+ for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, ln, eif)) {
+ if (strcmp(ifname, eif->ifp->name))
+ continue;
+
+ return eif;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance
+ */
+static int eigrpd_instance_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* NOTHING */
+ break;
+ case NB_EV_PREPARE:
+ eigrp = eigrp_get(yang_dnode_get_string(dnode, "./asn"));
+ resource->ptr = eigrp;
+ break;
+ case NB_EV_ABORT:
+ eigrp_finish_final(resource->ptr);
+ break;
+ case NB_EV_APPLY:
+ nb_running_set_entry(dnode, resource->ptr);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_unset_entry(dnode);
+ eigrp_finish_final(eigrp);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/router-id
+ */
+static int eigrpd_instance_router_id_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv4(&eigrp->router_id_static, dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_router_id_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->router_id_static.s_addr = 0;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/passive-interface
+ */
+static int
+eigrpd_instance_passive_interface_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_interface *eif;
+ struct eigrp *eigrp;
+ const char *ifname;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ eigrp = nb_running_get_entry(dnode, NULL, false);
+ if (eigrp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ ifname = yang_dnode_get_string(dnode, NULL);
+ eif = eigrp_interface_lookup(eigrp, ifname);
+ if (eif == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+ eif = eigrp_interface_lookup(eigrp, ifname);
+ if (eif == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ eif->params.passive_interface = EIGRP_IF_PASSIVE;
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp_interface *eif;
+ struct eigrp *eigrp;
+ const char *ifname;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+ eif = eigrp_interface_lookup(eigrp, ifname);
+ if (eif == NULL)
+ break;
+
+ eif->params.passive_interface = EIGRP_IF_ACTIVE;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/active-time
+ */
+static int eigrpd_instance_active_time_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/variance
+ */
+static int eigrpd_instance_variance_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->variance = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_variance_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->variance = EIGRP_VARIANCE_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/maximum-paths
+ */
+static int eigrpd_instance_maximum_paths_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->max_paths = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_maximum_paths_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K1
+ */
+static int
+eigrpd_instance_metric_weights_K1_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[0] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K1_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[0] = EIGRP_K1_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K2
+ */
+static int
+eigrpd_instance_metric_weights_K2_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[1] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K2_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[1] = EIGRP_K2_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K3
+ */
+static int
+eigrpd_instance_metric_weights_K3_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[2] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K3_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[2] = EIGRP_K3_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K4
+ */
+static int
+eigrpd_instance_metric_weights_K4_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[3] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K4_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[3] = EIGRP_K4_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K5
+ */
+static int
+eigrpd_instance_metric_weights_K5_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[4] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K5_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[4] = EIGRP_K5_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K6
+ */
+static int
+eigrpd_instance_metric_weights_K6_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[5] = yang_dnode_get_uint8(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_metric_weights_K6_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp->k_values[5] = EIGRP_K6_DEFAULT;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/network
+ */
+static int eigrpd_instance_network_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct route_node *rnode;
+ struct prefix prefix;
+ struct eigrp *eigrp;
+ int exists;
+
+ yang_dnode_get_ipv4p(&prefix, dnode, NULL);
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ eigrp = nb_running_get_entry(dnode, NULL, false);
+ /* If entry doesn't exist it means the list is empty. */
+ if (eigrp == NULL)
+ break;
+
+ rnode = route_node_get(eigrp->networks, &prefix);
+ exists = (rnode->info != NULL);
+ route_unlock_node(rnode);
+ if (exists)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ if (eigrp_network_set(eigrp, &prefix) == 0)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_network_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct route_node *rnode;
+ struct prefix prefix;
+ struct eigrp *eigrp;
+ int exists = 0;
+
+ yang_dnode_get_ipv4p(&prefix, dnode, NULL);
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ eigrp = nb_running_get_entry(dnode, NULL, false);
+ /* If entry doesn't exist it means the list is empty. */
+ if (eigrp == NULL)
+ break;
+
+ rnode = route_node_get(eigrp->networks, &prefix);
+ exists = (rnode->info != NULL);
+ route_unlock_node(rnode);
+ if (exists == 0)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ eigrp_network_unset(eigrp, &prefix);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/neighbor
+ */
+static int eigrpd_instance_neighbor_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_neighbor_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute
+ */
+static int eigrpd_instance_redistribute_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_metrics metrics;
+ struct eigrp *eigrp;
+ uint32_t proto;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ proto = yang_dnode_get_enum(dnode, "./protocol");
+ if (vrf_bitmap_check(zclient->redist[AFI_IP][proto],
+ VRF_DEFAULT))
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ proto = yang_dnode_get_enum(dnode, "./protocol");
+ redistribute_get_metrics(dnode, &metrics);
+ eigrp_redistribute_set(eigrp, proto, metrics);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_redistribute_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp *eigrp;
+ uint32_t proto;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ proto = yang_dnode_get_enum(dnode, "./protocol");
+ eigrp_redistribute_unset(eigrp, proto);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/route-map
+ */
+static int
+eigrpd_instance_redistribute_route_map_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+eigrpd_instance_redistribute_route_map_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/bandwidth
+ */
+static int eigrpd_instance_redistribute_metrics_bandwidth_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_metrics metrics;
+ struct eigrp *eigrp;
+ uint32_t proto;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ proto = yang_dnode_get_enum(dnode, "../../protocol");
+ redistribute_get_metrics(dnode, &metrics);
+ eigrp_redistribute_set(eigrp, proto, metrics);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int eigrpd_instance_redistribute_metrics_bandwidth_destroy(
+ enum nb_event event, const struct lyd_node *dnode)
+{
+ struct eigrp_metrics metrics;
+ struct eigrp *eigrp;
+ uint32_t proto;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eigrp = nb_running_get_entry(dnode, NULL, true);
+ proto = yang_dnode_get_enum(dnode, "../../protocol");
+ redistribute_get_metrics(dnode, &metrics);
+ eigrp_redistribute_set(eigrp, proto, metrics);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/delay
+ */
+static int
+eigrpd_instance_redistribute_metrics_delay_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_modify(event,
+ dnode,
+ resource);
+}
+
+static int
+eigrpd_instance_redistribute_metrics_delay_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_destroy(event,
+ dnode);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/reliability
+ */
+static int eigrpd_instance_redistribute_metrics_reliability_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_modify(event,
+ dnode,
+ resource);
+}
+
+static int eigrpd_instance_redistribute_metrics_reliability_destroy(
+ enum nb_event event, const struct lyd_node *dnode)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_destroy(event,
+ dnode);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/load
+ */
+static int
+eigrpd_instance_redistribute_metrics_load_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_modify(event,
+ dnode,
+ resource);
+}
+
+static int
+eigrpd_instance_redistribute_metrics_load_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_destroy(event,
+ dnode);
+}
+
+/*
+ * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/mtu
+ */
+static int
+eigrpd_instance_redistribute_metrics_mtu_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_modify(event,
+ dnode,
+ resource);
+}
+
+static int
+eigrpd_instance_redistribute_metrics_mtu_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ return eigrpd_instance_redistribute_metrics_bandwidth_destroy(event,
+ dnode);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/delay
+ */
+static int lib_interface_eigrp_delay_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_interface *ei;
+ struct interface *ifp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ifp = nb_running_get_entry(dnode, NULL, false);
+ if (ifp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ ei->params.delay = yang_dnode_get_uint32(dnode, NULL);
+ eigrp_if_reset(ifp);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/bandwidth
+ */
+static int lib_interface_eigrp_bandwidth_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct interface *ifp;
+ struct eigrp_interface *ei;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ifp = nb_running_get_entry(dnode, NULL, false);
+ if (ifp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ ei->params.bandwidth = yang_dnode_get_uint32(dnode, NULL);
+ eigrp_if_reset(ifp);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hello-interval
+ */
+static int
+lib_interface_eigrp_hello_interval_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct interface *ifp;
+ struct eigrp_interface *ei;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ifp = nb_running_get_entry(dnode, NULL, false);
+ if (ifp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ ei->params.v_hello = yang_dnode_get_uint16(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hold-time
+ */
+static int lib_interface_eigrp_hold_time_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct interface *ifp;
+ struct eigrp_interface *ei;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ifp = nb_running_get_entry(dnode, NULL, false);
+ if (ifp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ ei = ifp->info;
+ if (ei == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ ei->params.v_wait = yang_dnode_get_uint16(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/split-horizon
+ */
+static int
+lib_interface_eigrp_split_horizon_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance
+ */
+static int lib_interface_eigrp_instance_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_interface *eif;
+ struct interface *ifp;
+ struct eigrp *eigrp;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ifp = nb_running_get_entry(dnode, NULL, false);
+ if (ifp == NULL) {
+ /*
+ * XXX: we can't verify if the interface exists
+ * and is active until EIGRP is up.
+ */
+ break;
+ }
+
+ eigrp = eigrp_get(yang_dnode_get_string(dnode, "./asn"));
+ eif = eigrp_interface_lookup(eigrp, ifp->name);
+ if (eif == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ eigrp = eigrp_get(yang_dnode_get_string(dnode, "./asn"));
+ eif = eigrp_interface_lookup(eigrp, ifp->name);
+ if (eif == NULL)
+ return NB_ERR_INCONSISTENCY;
+
+ nb_running_set_entry(dnode, eif);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int lib_interface_eigrp_instance_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ nb_running_unset_entry(dnode);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/summarize-addresses
+ */
+static int lib_interface_eigrp_instance_summarize_addresses_create(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int lib_interface_eigrp_instance_summarize_addresses_destroy(
+ enum nb_event event, const struct lyd_node *dnode)
+{
+ switch (event) {
+ case NB_EV_VALIDATE:
+ /* TODO: Not implemented. */
+ return NB_ERR_INCONSISTENCY;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ /* NOTHING */
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/authentication
+ */
+static int
+lib_interface_eigrp_instance_authentication_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_interface *eif;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eif = nb_running_get_entry(dnode, NULL, true);
+ eif->params.auth_type = yang_dnode_get_enum(dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/keychain
+ */
+static int
+lib_interface_eigrp_instance_keychain_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct eigrp_interface *eif;
+ struct keychain *keychain;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ keychain = keychain_lookup(yang_dnode_get_string(dnode, NULL));
+ if (keychain == NULL)
+ return NB_ERR_INCONSISTENCY;
+ break;
+ case NB_EV_PREPARE:
+ resource->ptr = strdup(yang_dnode_get_string(dnode, NULL));
+ if (resource->ptr == NULL)
+ return NB_ERR_RESOURCE;
+ break;
+ case NB_EV_ABORT:
+ free(resource->ptr);
+ resource->ptr = NULL;
+ break;
+ case NB_EV_APPLY:
+ eif = nb_running_get_entry(dnode, NULL, true);
+ if (eif->params.auth_keychain)
+ free(eif->params.auth_keychain);
+
+ eif->params.auth_keychain = resource->ptr;
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+lib_interface_eigrp_instance_keychain_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct eigrp_interface *eif;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ /* NOTHING */
+ break;
+ case NB_EV_APPLY:
+ eif = nb_running_get_entry(dnode, NULL, true);
+ if (eif->params.auth_keychain)
+ free(eif->params.auth_keychain);
+
+ eif->params.auth_keychain = NULL;
+ break;
+ }
+
+ return NB_OK;
+}
+
+/* clang-format off */
+const struct frr_yang_module_info frr_eigrpd_info = {
+ .name = "frr-eigrpd",
+ .nodes = {
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance",
+ .cbs = {
+ .create = eigrpd_instance_create,
+ .destroy = eigrpd_instance_destroy,
+ .cli_show = eigrp_cli_show_header,
+ .cli_show_end = eigrp_cli_show_end_header,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/router-id",
+ .cbs = {
+ .modify = eigrpd_instance_router_id_modify,
+ .destroy = eigrpd_instance_router_id_destroy,
+ .cli_show = eigrp_cli_show_router_id,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/passive-interface",
+ .cbs = {
+ .create = eigrpd_instance_passive_interface_create,
+ .destroy = eigrpd_instance_passive_interface_destroy,
+ .cli_show = eigrp_cli_show_passive_interface,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/active-time",
+ .cbs = {
+ .modify = eigrpd_instance_active_time_modify,
+ .cli_show = eigrp_cli_show_active_time,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/variance",
+ .cbs = {
+ .modify = eigrpd_instance_variance_modify,
+ .destroy = eigrpd_instance_variance_destroy,
+ .cli_show = eigrp_cli_show_variance,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/maximum-paths",
+ .cbs = {
+ .modify = eigrpd_instance_maximum_paths_modify,
+ .destroy = eigrpd_instance_maximum_paths_destroy,
+ .cli_show = eigrp_cli_show_maximum_paths,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights",
+ .cbs = {
+ .cli_show = eigrp_cli_show_metrics,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K1",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K1_modify,
+ .destroy = eigrpd_instance_metric_weights_K1_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K2",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K2_modify,
+ .destroy = eigrpd_instance_metric_weights_K2_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K3",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K3_modify,
+ .destroy = eigrpd_instance_metric_weights_K3_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K4",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K4_modify,
+ .destroy = eigrpd_instance_metric_weights_K4_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K5",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K5_modify,
+ .destroy = eigrpd_instance_metric_weights_K5_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K6",
+ .cbs = {
+ .modify = eigrpd_instance_metric_weights_K6_modify,
+ .destroy = eigrpd_instance_metric_weights_K6_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/network",
+ .cbs = {
+ .create = eigrpd_instance_network_create,
+ .destroy = eigrpd_instance_network_destroy,
+ .cli_show = eigrp_cli_show_network,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/neighbor",
+ .cbs = {
+ .create = eigrpd_instance_neighbor_create,
+ .destroy = eigrpd_instance_neighbor_destroy,
+ .cli_show = eigrp_cli_show_neighbor,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute",
+ .cbs = {
+ .create = eigrpd_instance_redistribute_create,
+ .destroy = eigrpd_instance_redistribute_destroy,
+ .cli_show = eigrp_cli_show_redistribute,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/route-map",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_route_map_modify,
+ .destroy = eigrpd_instance_redistribute_route_map_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/bandwidth",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_metrics_bandwidth_modify,
+ .destroy = eigrpd_instance_redistribute_metrics_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/delay",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_metrics_delay_modify,
+ .destroy = eigrpd_instance_redistribute_metrics_delay_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/reliability",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_metrics_reliability_modify,
+ .destroy = eigrpd_instance_redistribute_metrics_reliability_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/load",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_metrics_load_modify,
+ .destroy = eigrpd_instance_redistribute_metrics_load_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/mtu",
+ .cbs = {
+ .modify = eigrpd_instance_redistribute_metrics_mtu_modify,
+ .destroy = eigrpd_instance_redistribute_metrics_mtu_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/delay",
+ .cbs = {
+ .modify = lib_interface_eigrp_delay_modify,
+ .cli_show = eigrp_cli_show_delay,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/bandwidth",
+ .cbs = {
+ .modify = lib_interface_eigrp_bandwidth_modify,
+ .cli_show = eigrp_cli_show_bandwidth,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/hello-interval",
+ .cbs = {
+ .modify = lib_interface_eigrp_hello_interval_modify,
+ .cli_show = eigrp_cli_show_hello_interval,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/hold-time",
+ .cbs = {
+ .modify = lib_interface_eigrp_hold_time_modify,
+ .cli_show = eigrp_cli_show_hold_time,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/split-horizon",
+ .cbs = {
+ .modify = lib_interface_eigrp_split_horizon_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance",
+ .cbs = {
+ .create = lib_interface_eigrp_instance_create,
+ .destroy = lib_interface_eigrp_instance_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/summarize-addresses",
+ .cbs = {
+ .create = lib_interface_eigrp_instance_summarize_addresses_create,
+ .destroy = lib_interface_eigrp_instance_summarize_addresses_destroy,
+ .cli_show = eigrp_cli_show_summarize_address,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/authentication",
+ .cbs = {
+ .modify = lib_interface_eigrp_instance_authentication_modify,
+ .cli_show = eigrp_cli_show_authentication,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/keychain",
+ .cbs = {
+ .modify = lib_interface_eigrp_instance_keychain_modify,
+ .destroy = lib_interface_eigrp_instance_keychain_destroy,
+ .cli_show = eigrp_cli_show_keychain,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c
index d51faaac59..207622e659 100644
--- a/eigrpd/eigrp_vty.c
+++ b/eigrpd/eigrp_vty.c
@@ -59,402 +59,6 @@
#include "eigrpd/eigrp_vty_clippy.c"
#endif
-static int config_write_network(struct vty *vty, struct eigrp *eigrp)
-{
- struct route_node *rn;
- int i;
-
- /* `network area' print. */
- for (rn = route_top(eigrp->networks); rn; rn = route_next(rn))
- if (rn->info) {
- /* Network print. */
- vty_out(vty, " network %s/%d \n",
- inet_ntoa(rn->p.u.prefix4), rn->p.prefixlen);
- }
-
- if (eigrp->max_paths != EIGRP_MAX_PATHS_DEFAULT)
- vty_out(vty, " maximum-paths %d\n", eigrp->max_paths);
-
- if (eigrp->variance != EIGRP_VARIANCE_DEFAULT)
- vty_out(vty, " variance %d\n", eigrp->variance);
-
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (i != zclient->redist_default
- && vrf_bitmap_check(zclient->redist[AFI_IP][i],
- VRF_DEFAULT))
- vty_out(vty, " redistribute %s\n",
- zebra_route_string(i));
-
- /*Separate EIGRP configuration from the rest of the config*/
- vty_out(vty, "!\n");
-
- return 0;
-}
-
-static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
-{
- struct eigrp_interface *ei;
- struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
- vty_frame(vty, "interface %s\n", ei->ifp->name);
-
- if (ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) {
- vty_out(vty, " ip authentication mode eigrp %d md5\n",
- eigrp->AS);
- }
-
- if (ei->params.auth_type == EIGRP_AUTH_TYPE_SHA256) {
- vty_out(vty,
- " ip authentication mode eigrp %d hmac-sha-256\n",
- eigrp->AS);
- }
-
- if (ei->params.auth_keychain) {
- vty_out(vty,
- " ip authentication key-chain eigrp %d %s\n",
- eigrp->AS, ei->params.auth_keychain);
- }
-
- if (ei->params.v_hello != EIGRP_HELLO_INTERVAL_DEFAULT) {
- vty_out(vty, " ip hello-interval eigrp %d\n",
- ei->params.v_hello);
- }
-
- if (ei->params.v_wait != EIGRP_HOLD_INTERVAL_DEFAULT) {
- vty_out(vty, " ip hold-time eigrp %d\n",
- ei->params.v_wait);
- }
-
- /*Separate this EIGRP interface configuration from the others*/
- vty_endframe(vty, "!\n");
- }
-
- return 0;
-}
-
-static int eigrp_write_interface(struct vty *vty)
-{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
- struct eigrp_interface *ei;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- ei = ifp->info;
- if (!ei)
- continue;
-
- vty_frame(vty, "interface %s\n", ifp->name);
-
- if (ifp->desc)
- vty_out(vty, " description %s\n", ifp->desc);
-
- if (ei->params.bandwidth != EIGRP_BANDWIDTH_DEFAULT)
- vty_out(vty, " bandwidth %u\n", ei->params.bandwidth);
- if (ei->params.delay != EIGRP_DELAY_DEFAULT)
- vty_out(vty, " delay %u\n", ei->params.delay);
- if (ei->params.v_hello != EIGRP_HELLO_INTERVAL_DEFAULT)
- vty_out(vty, " ip hello-interval eigrp %u\n",
- ei->params.v_hello);
- if (ei->params.v_wait != EIGRP_HOLD_INTERVAL_DEFAULT)
- vty_out(vty, " ip hold-time eigrp %u\n",
- ei->params.v_wait);
-
- vty_endframe(vty, "!\n");
- }
-
- return 0;
-}
-
-/**
- * Writes distribute lists to config
- */
-static int config_write_eigrp_distribute(struct vty *vty, struct eigrp *eigrp)
-{
- int write = 0;
-
- /* Distribute configuration. */
- write += config_write_distribute(vty, eigrp->distribute_ctx);
-
- return write;
-}
-
-/**
- * Writes 'router eigrp' section to config
- */
-static int config_write_eigrp_router(struct vty *vty, struct eigrp *eigrp)
-{
- int write = 0;
-
- /* `router eigrp' print. */
- vty_out(vty, "router eigrp %d\n", eigrp->AS);
-
- write++;
-
- /* Router ID print. */
- if (eigrp->router_id_static.s_addr != 0) {
- vty_out(vty, " eigrp router-id %s\n",
- inet_ntoa(eigrp->router_id_static));
- }
-
- /* Network area print. */
- config_write_network(vty, eigrp);
-
- /* Distribute-list and default-information print. */
- config_write_eigrp_distribute(vty, eigrp);
-
- /*Separate EIGRP configuration from the rest of the config*/
- vty_out(vty, "!\n");
-
- return write;
-}
-
-DEFUN_NOSH (router_eigrp,
- router_eigrp_cmd,
- "router eigrp (1-65535)",
- "Enable a routing process\n"
- "Start EIGRP configuration\n"
- "AS Number to use\n")
-{
- struct eigrp *eigrp = eigrp_get(argv[2]->arg);
- VTY_PUSH_CONTEXT(EIGRP_NODE, eigrp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_router_eigrp,
- no_router_eigrp_cmd,
- "no router eigrp (1-65535)",
- NO_STR
- "Routing process\n"
- "EIGRP configuration\n"
- "AS number to use\n")
-{
- vty->node = CONFIG_NODE;
-
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (eigrp->AS != atoi(argv[3]->arg)) {
- vty_out(vty, "%% Attempting to deconfigure non-existent AS\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- eigrp_finish_final(eigrp);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (eigrp_router_id,
- eigrp_router_id_cmd,
- "eigrp router-id A.B.C.D$addr",
- "EIGRP specific commands\n"
- "Router ID for this EIGRP process\n"
- "EIGRP Router-ID in IP address format\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
-
- eigrp->router_id_static = addr;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (no_eigrp_router_id,
- no_eigrp_router_id_cmd,
- "no eigrp router-id [A.B.C.D$addr]",
- NO_STR
- "EIGRP specific commands\n"
- "Router ID for this EIGRP process\n"
- "EIGRP Router-ID in IP address format\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
-
- eigrp->router_id_static.s_addr = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_passive_interface,
- eigrp_passive_interface_cmd,
- "passive-interface IFNAME",
- "Suppress routing updates on an interface\n"
- "Interface to suppress on\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- struct eigrp_interface *ei;
- struct listnode *node;
- char *ifname = argv[1]->arg;
-
- for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
- if (strcmp(ifname, ei->ifp->name) == 0) {
- ei->params.passive_interface = EIGRP_IF_PASSIVE;
- return CMD_SUCCESS;
- }
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_passive_interface,
- no_eigrp_passive_interface_cmd,
- "no passive-interface IFNAME",
- NO_STR
- "Suppress routing updates on an interface\n"
- "Interface to suppress on\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- struct eigrp_interface *ei;
- struct listnode *node;
- char *ifname = argv[2]->arg;
-
- for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
- if (strcmp(ifname, ei->ifp->name) == 0) {
- ei->params.passive_interface = EIGRP_IF_ACTIVE;
- return CMD_SUCCESS;
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_timers_active,
- eigrp_timers_active_cmd,
- "timers active-time <(1-65535)|disabled>",
- "Adjust routing timers\n"
- "Time limit for active state\n"
- "Active state time limit in seconds\n"
- "Disable time limit for active state\n")
-{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_timers_active,
- no_eigrp_timers_active_cmd,
- "no timers active-time <(1-65535)|disabled>",
- NO_STR
- "Adjust routing timers\n"
- "Time limit for active state\n"
- "Active state time limit in seconds\n"
- "Disable time limit for active state\n")
-{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-
-DEFUN (eigrp_metric_weights,
- eigrp_metric_weights_cmd,
- "metric weights (0-255) (0-255) (0-255) (0-255) (0-255) ",
- "Modify metrics and parameters for advertisement\n"
- "Modify metric coefficients\n"
- "K1\n"
- "K2\n"
- "K3\n"
- "K4\n"
- "K5\n")
-{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_metric_weights,
- no_eigrp_metric_weights_cmd,
- "no metric weights (0-255) (0-255) (0-255) (0-255) (0-255)",
- NO_STR
- "Modify metrics and parameters for advertisement\n"
- "Modify metric coefficients\n"
- "K1\n"
- "K2\n"
- "K3\n"
- "K4\n"
- "K5\n")
-{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-
-DEFUN (eigrp_network,
- eigrp_network_cmd,
- "network A.B.C.D/M",
- "Enable routing on an IP network\n"
- "EIGRP network prefix\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- struct prefix p;
- int ret;
-
- (void)str2prefix(argv[1]->arg, &p);
-
- ret = eigrp_network_set(eigrp, &p);
-
- if (ret == 0) {
- vty_out(vty, "There is already same network statement.\n");
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_network,
- no_eigrp_network_cmd,
- "no network A.B.C.D/M",
- NO_STR
- "Disable routing on an IP network\n"
- "EIGRP network prefix\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- struct prefix p;
- int ret;
-
- (void)str2prefix(argv[2]->arg, &p);
-
- ret = eigrp_network_unset(eigrp, &p);
-
- if (ret == 0) {
- vty_out(vty, "Can't find specified network configuration.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_neighbor,
- eigrp_neighbor_cmd,
- "neighbor A.B.C.D",
- "Specify a neighbor router\n"
- "Neighbor address\n")
-{
- // struct eigrp *eigrp = vty->index;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_neighbor,
- no_eigrp_neighbor_cmd,
- "no neighbor A.B.C.D",
- NO_STR
- "Specify a neighbor router\n"
- "Neighbor address\n")
-{
- // struct eigrp *eigrp = vty->index;
-
- return CMD_SUCCESS;
-}
-
static void eigrp_vty_display_prefix_entry(struct vty *vty,
struct eigrp *eigrp,
struct eigrp_prefix_entry *pe,
@@ -650,585 +254,6 @@ DEFUN (show_ip_eigrp_neighbors,
return CMD_SUCCESS;
}
-DEFUN (eigrp_if_delay,
- eigrp_if_delay_cmd,
- "delay (1-16777215)",
- "Specify interface throughput delay\n"
- "Throughput delay (tens of microseconds)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
- uint32_t delay;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
-
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
- delay = atoi(argv[1]->arg);
-
- ei->params.delay = delay;
- eigrp_if_reset(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_if_delay,
- no_eigrp_if_delay_cmd,
- "no delay (1-16777215)",
- NO_STR
- "Specify interface throughput delay\n"
- "Throughput delay (tens of microseconds)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
-
- return CMD_SUCCESS;
- }
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.delay = EIGRP_DELAY_DEFAULT;
- eigrp_if_reset(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (eigrp_if_bandwidth,
- eigrp_if_bandwidth_cmd,
- "eigrp bandwidth (1-10000000)$bw",
- "EIGRP specific commands\n"
- "Set bandwidth informational parameter\n"
- "Bandwidth in kilobits\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.bandwidth = bw;
- eigrp_if_reset(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_if_bandwidth,
- no_eigrp_if_bandwidth_cmd,
- "no eigrp bandwidth [(1-10000000)]",
- NO_STR
- "EIGRP specific commands\n"
- "Set bandwidth informational parameter\n"
- "Bandwidth in kilobits\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.bandwidth = EIGRP_BANDWIDTH_DEFAULT;
- eigrp_if_reset(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_if_ip_hellointerval,
- eigrp_if_ip_hellointerval_cmd,
- "ip hello-interval eigrp (1-65535)",
- "Interface Internet Protocol config commands\n"
- "Configures EIGRP hello interval\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Seconds between hello transmissions\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- uint32_t hello;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- hello = atoi(argv[3]->arg);
-
- ei->params.v_hello = hello;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_if_ip_hellointerval,
- no_eigrp_if_ip_hellointerval_cmd,
- "no ip hello-interval eigrp [(1-65535)]",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Configures EIGRP hello interval\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Seconds between hello transmissions\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.v_hello = EIGRP_HELLO_INTERVAL_DEFAULT;
-
- THREAD_TIMER_OFF(ei->t_hello);
- thread_add_timer(master, eigrp_hello_timer, ei, 1, &ei->t_hello);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_if_ip_holdinterval,
- eigrp_if_ip_holdinterval_cmd,
- "ip hold-time eigrp (1-65535)",
- "Interface Internet Protocol config commands\n"
- "Configures EIGRP IPv4 hold time\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Seconds before neighbor is considered down\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- uint32_t hold;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- hold = atoi(argv[3]->arg);
-
- ei->params.v_wait = hold;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_ip_summary_address,
- eigrp_ip_summary_address_cmd,
- "ip summary-address eigrp (1-65535) A.B.C.D/M",
- "Interface Internet Protocol config commands\n"
- "Perform address summarization\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "AS number\n"
- "Summary <network>/<length>, e.g. 192.168.0.0/16\n")
-{
- // VTY_DECLVAR_CONTEXT(interface, ifp);
- // uint32_t AS;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- // AS = atoi (argv[3]->arg);
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_ip_summary_address,
- no_eigrp_ip_summary_address_cmd,
- "no ip summary-address eigrp (1-65535) A.B.C.D/M",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Perform address summarization\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "AS number\n"
- "Summary <network>/<length>, e.g. 192.168.0.0/16\n")
-{
- // VTY_DECLVAR_CONTEXT(interface, ifp);
- // uint32_t AS;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- // AS = atoi (argv[4]->arg);
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_if_ip_holdinterval,
- no_eigrp_if_ip_holdinterval_cmd,
- "no ip hold-time eigrp",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Configures EIGRP hello interval\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.v_wait = EIGRP_HOLD_INTERVAL_DEFAULT;
-
- return CMD_SUCCESS;
-}
-
-static int str2auth_type(const char *str, struct eigrp_interface *ei)
-{
- /* Sanity check. */
- if (str == NULL)
- return CMD_WARNING_CONFIG_FAILED;
-
- if (strncmp(str, "md5", 3) == 0) {
- ei->params.auth_type = EIGRP_AUTH_TYPE_MD5;
- return CMD_SUCCESS;
- } else if (strncmp(str, "hmac-sha-256", 12) == 0) {
- ei->params.auth_type = EIGRP_AUTH_TYPE_SHA256;
- return CMD_SUCCESS;
- }
-
- return CMD_WARNING_CONFIG_FAILED;
-}
-
-DEFUN (eigrp_authentication_mode,
- eigrp_authentication_mode_cmd,
- "ip authentication mode eigrp (1-65535) <md5|hmac-sha-256>",
- "Interface Internet Protocol config commands\n"
- "Authentication subcommands\n"
- "Mode\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Autonomous system number\n"
- "Keyed message digest\n"
- "HMAC SHA256 algorithm \n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- // if(strncmp(argv[2], "md5",3))
- // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_MD5;
- // else if(strncmp(argv[2], "hmac-sha-256",12))
- // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_SHA256;
-
- return str2auth_type(argv[5]->arg, ei);
-}
-
-DEFUN (no_eigrp_authentication_mode,
- no_eigrp_authentication_mode_cmd,
- "no ip authentication mode eigrp (1-65535) <md5|hmac-sha-256>",
- "Disable\n"
- "Interface Internet Protocol config commands\n"
- "Authentication subcommands\n"
- "Mode\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Autonomous system number\n"
- "Keyed message digest\n"
- "HMAC SHA256 algorithm \n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, " EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- ei->params.auth_type = EIGRP_AUTH_TYPE_NONE;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (eigrp_authentication_keychain,
- eigrp_authentication_keychain_cmd,
- "[no] ip authentication key-chain eigrp (1-65535)$as WORD$name",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Authentication subcommands\n"
- "Key-chain\n"
- "Enhanced Interior Gateway Routing Protocol (EIGRP)\n"
- "Autonomous system number\n"
- "Name of key-chain\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct eigrp_interface *ei = ifp->info;
- struct eigrp *eigrp;
- struct keychain *keychain;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, "EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- if (!ei) {
- vty_out(vty, " EIGRP not configured on this interface\n");
- return CMD_SUCCESS;
- }
-
- if (no) {
- if ((ei->params.auth_keychain != NULL)
- && (strcmp(ei->params.auth_keychain, name) == 0)) {
- free(ei->params.auth_keychain);
- ei->params.auth_keychain = NULL;
- } else
- vty_out(vty,
- "Key chain with specified name not configured on interface\n");
- return CMD_SUCCESS;
- }
-
- keychain = keychain_lookup(name);
- if (keychain != NULL) {
- if (ei->params.auth_keychain) {
- free(ei->params.auth_keychain);
- ei->params.auth_keychain = strdup(keychain->name);
- } else
- ei->params.auth_keychain = strdup(keychain->name);
- } else {
- vty_out(vty,
- "Key chain with specified name not found\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_redistribute_source_metric,
- eigrp_redistribute_source_metric_cmd,
- "redistribute " FRR_REDIST_STR_EIGRPD
- " [metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)]",
- REDIST_STR
- FRR_REDIST_HELP_STR_EIGRPD
- "Metric for redistributed routes\n"
- "Bandwidth metric in Kbits per second\n"
- "EIGRP delay metric, in 10 microsecond units\n"
- "EIGRP reliability metric where 255 is 100% reliable2 ?\n"
- "EIGRP Effective bandwidth metric (Loading) where 255 is 100% loaded\n"
- "EIGRP MTU of the path\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- struct eigrp_metrics metrics_from_command = {0};
- int source;
- int idx = 0;
-
- /* Get distribute source. */
- argv_find(argv, argc, "redistribute", &idx);
- source = proto_redistnum(AFI_IP, argv[idx + 1]->text);
- if (source < 0) {
- vty_out(vty, "%% Invalid route type\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Get metrics values */
-
- return eigrp_redistribute_set(eigrp, source, metrics_from_command);
-}
-
-DEFUN (no_eigrp_redistribute_source_metric,
- no_eigrp_redistribute_source_metric_cmd,
- "no redistribute " FRR_REDIST_STR_EIGRPD
- " [metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)]",
- "Disable\n"
- REDIST_STR
- FRR_REDIST_HELP_STR_EIGRPD
- "Metric for redistributed routes\n"
- "Bandwidth metric in Kbits per second\n"
- "EIGRP delay metric, in 10 microsecond units\n"
- "EIGRP reliability metric where 255 is 100% reliable2 ?\n"
- "EIGRP Effective bandwidth metric (Loading) where 255 is 100% loaded\n"
- "EIGRP MTU of the path\n")
-{
- VTY_DECLVAR_CONTEXT(eigrp, eigrp);
- int source;
- int idx = 0;
-
- /* Get distribute source. */
- argv_find(argv, argc, "redistribute", &idx);
- source = proto_redistnum(AFI_IP, argv[idx + 1]->text);
- if (source < 0) {
- vty_out(vty, "%% Invalid route type\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Get metrics values */
-
- return eigrp_redistribute_unset(eigrp, source);
-}
-
-DEFUN (eigrp_variance,
- eigrp_variance_cmd,
- "variance (1-128)",
- "Control load balancing variance\n"
- "Metric variance multiplier\n")
-{
- struct eigrp *eigrp;
- uint8_t variance;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, "EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
- variance = atoi(argv[1]->arg);
-
- eigrp->variance = variance;
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_variance,
- no_eigrp_variance_cmd,
- "no variance (1-128)",
- "Disable\n"
- "Control load balancing variance\n"
- "Metric variance multiplier\n")
-{
- struct eigrp *eigrp;
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, "EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- eigrp->variance = EIGRP_VARIANCE_DEFAULT;
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (eigrp_maximum_paths,
- eigrp_maximum_paths_cmd,
- "maximum-paths (1-32)",
- "Forward packets over multiple paths\n"
- "Number of paths\n")
-{
- struct eigrp *eigrp;
- uint8_t max;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, "EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- max = atoi(argv[1]->arg);
-
- eigrp->max_paths = max;
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_eigrp_maximum_paths,
- no_eigrp_maximum_paths_cmd,
- "no maximum-paths (1-32)",
- NO_STR
- "Forward packets over multiple paths\n"
- "Number of paths\n")
-{
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp == NULL) {
- vty_out(vty, "EIGRP Routing Process not enabled\n");
- return CMD_SUCCESS;
- }
-
- eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT;
-
- /*TODO: */
-
- return CMD_SUCCESS;
-}
-
/*
* Execute hard restart for all neighbors
*/
@@ -1492,40 +517,6 @@ DEFUN (clear_ip_eigrp_neighbors_IP_soft,
return CMD_SUCCESS;
}
-static struct cmd_node eigrp_node = {EIGRP_NODE, "%s(config-router)# ", 1};
-
-/* Save EIGRP configuration */
-static int eigrp_config_write(struct vty *vty)
-{
- struct eigrp *eigrp;
-
- eigrp = eigrp_lookup();
- if (eigrp != NULL) {
- /* Writes 'router eigrp' section to config */
- config_write_eigrp_router(vty, eigrp);
-
- /* Interface config print */
- config_write_interfaces(vty, eigrp);
- //
- // /* static neighbor print. */
- // config_write_eigrp_nbr_nbma (vty, eigrp);
- //
- // /* Virtual-Link print. */
- // config_write_virtual_link (vty, eigrp);
- //
- // /* Default metric configuration. */
- // config_write_eigrp_default_metric (vty, eigrp);
- //
- // /* Distribute-list and default-information print. */
- // config_write_eigrp_distribute (vty, eigrp);
- //
- // /* Distance configuration. */
- // config_write_eigrp_distance (vty, eigrp)
- }
-
- return 0;
-}
-
void eigrp_vty_show_init(void)
{
install_element(VIEW_NODE, &show_ip_eigrp_interfaces_cmd);
@@ -1536,69 +527,9 @@ void eigrp_vty_show_init(void)
install_element(VIEW_NODE, &show_ip_eigrp_topology_all_cmd);
}
-/* eigrpd's interface node. */
-static struct cmd_node eigrp_interface_node = {INTERFACE_NODE,
- "%s(config-if)# ", 1};
-
-void eigrp_vty_if_init(void)
-{
- install_node(&eigrp_interface_node, eigrp_write_interface);
- if_cmd_init();
-
- /* Delay and bandwidth configuration commands*/
- install_element(INTERFACE_NODE, &eigrp_if_delay_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_if_delay_cmd);
- install_element(INTERFACE_NODE, &eigrp_if_bandwidth_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_if_bandwidth_cmd);
-
- /*Hello-interval and hold-time interval configuration commands*/
- install_element(INTERFACE_NODE, &eigrp_if_ip_holdinterval_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_if_ip_holdinterval_cmd);
- install_element(INTERFACE_NODE, &eigrp_if_ip_hellointerval_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_if_ip_hellointerval_cmd);
-
- /* "Authentication configuration commands */
- install_element(INTERFACE_NODE, &eigrp_authentication_mode_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_authentication_mode_cmd);
- install_element(INTERFACE_NODE, &eigrp_authentication_keychain_cmd);
-
- /*EIGRP Summarization commands*/
- install_element(INTERFACE_NODE, &eigrp_ip_summary_address_cmd);
- install_element(INTERFACE_NODE, &no_eigrp_ip_summary_address_cmd);
-}
-
-static void eigrp_vty_zebra_init(void)
-{
- install_element(EIGRP_NODE, &eigrp_redistribute_source_metric_cmd);
- install_element(EIGRP_NODE, &no_eigrp_redistribute_source_metric_cmd);
-}
-
/* Install EIGRP related vty commands. */
void eigrp_vty_init(void)
{
- install_node(&eigrp_node, eigrp_config_write);
-
- install_default(EIGRP_NODE);
-
- install_element(CONFIG_NODE, &router_eigrp_cmd);
- install_element(CONFIG_NODE, &no_router_eigrp_cmd);
- install_element(EIGRP_NODE, &eigrp_network_cmd);
- install_element(EIGRP_NODE, &no_eigrp_network_cmd);
- install_element(EIGRP_NODE, &eigrp_variance_cmd);
- install_element(EIGRP_NODE, &no_eigrp_variance_cmd);
- install_element(EIGRP_NODE, &eigrp_router_id_cmd);
- install_element(EIGRP_NODE, &no_eigrp_router_id_cmd);
- install_element(EIGRP_NODE, &eigrp_passive_interface_cmd);
- install_element(EIGRP_NODE, &no_eigrp_passive_interface_cmd);
- install_element(EIGRP_NODE, &eigrp_timers_active_cmd);
- install_element(EIGRP_NODE, &no_eigrp_timers_active_cmd);
- install_element(EIGRP_NODE, &eigrp_metric_weights_cmd);
- install_element(EIGRP_NODE, &no_eigrp_metric_weights_cmd);
- install_element(EIGRP_NODE, &eigrp_maximum_paths_cmd);
- install_element(EIGRP_NODE, &no_eigrp_maximum_paths_cmd);
- install_element(EIGRP_NODE, &eigrp_neighbor_cmd);
- install_element(EIGRP_NODE, &no_eigrp_neighbor_cmd);
-
/* commands for manual hard restart */
install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd);
install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd);
@@ -1607,6 +538,4 @@ void eigrp_vty_init(void)
install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd);
install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd);
install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd);
-
- eigrp_vty_zebra_init();
}
diff --git a/eigrpd/eigrp_vty.h b/eigrpd/eigrp_vty.h
index 3fbadf6dfb..ebbf503857 100644
--- a/eigrpd/eigrp_vty.h
+++ b/eigrpd/eigrp_vty.h
@@ -35,6 +35,5 @@
/* Prototypes. */
extern void eigrp_vty_init(void);
extern void eigrp_vty_show_init(void);
-extern void eigrp_vty_if_init(void);
#endif /* _Quagga_EIGRP_VTY_H_ */
diff --git a/eigrpd/eigrpd.h b/eigrpd/eigrpd.h
index de7c881ac0..3ef3a9c0cc 100644
--- a/eigrpd/eigrpd.h
+++ b/eigrpd/eigrpd.h
@@ -52,4 +52,51 @@ extern struct eigrp *eigrp_get(const char *);
extern struct eigrp *eigrp_lookup(void);
extern void eigrp_router_id_update(struct eigrp *);
+/* eigrp_cli.c */
+extern void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode);
+extern void eigrp_cli_show_router_id(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_passive_interface(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_active_time(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_variance(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_maximum_paths(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_metrics(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_network(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_neighbor(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_redistribute(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_delay(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_bandwidth(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_hello_interval(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_hold_time(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_summarize_address(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_authentication(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_show_keychain(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+extern void eigrp_cli_init(void);
+
+/* eigrp_northbound.c */
+extern const struct frr_yang_module_info frr_eigrpd_info;
+
#endif /* _ZEBRA_EIGRPD_H */
diff --git a/eigrpd/subdir.am b/eigrpd/subdir.am
index 4503030fdf..cc46766586 100644
--- a/eigrpd/subdir.am
+++ b/eigrpd/subdir.am
@@ -7,6 +7,7 @@ noinst_LIBRARIES += eigrpd/libeigrp.a
sbin_PROGRAMS += eigrpd/eigrpd
dist_examples_DATA += eigrpd/eigrpd.conf.sample
vtysh_scan += \
+ $(top_srcdir)/eigrpd/eigrp_cli.c \
$(top_srcdir)/eigrpd/eigrp_dump.c \
$(top_srcdir)/eigrpd/eigrp_vty.c \
# end
@@ -15,6 +16,7 @@ man8 += $(MANBUILD)/eigrpd.8
endif
eigrpd_libeigrp_a_SOURCES = \
+ eigrpd/eigrp_cli.c \
eigrpd/eigrp_dump.c \
eigrpd/eigrp_errors.c \
eigrpd/eigrp_filter.c \
@@ -24,6 +26,7 @@ eigrpd_libeigrp_a_SOURCES = \
eigrpd/eigrp_memory.c \
eigrpd/eigrp_neighbor.c \
eigrpd/eigrp_network.c \
+ eigrpd/eigrp_northbound.c \
eigrpd/eigrp_packet.c \
eigrpd/eigrp_query.c \
eigrpd/eigrp_reply.c \
@@ -47,6 +50,9 @@ eigrpdheader_HEADERS = \
eigrpd/eigrp_vty_clippy.c: $(CLIPPY_DEPS)
eigrpd/eigrp_vty.$(OBJEXT): eigrpd/eigrp_vty_clippy.c
+eigrpd/eigrp_cli_clippy.c: $(CLIPPY_DEPS)
+eigrpd/eigrp_cli.$(OBJEXT): eigrpd/eigrp_cli_clippy.c
+
noinst_HEADERS += \
eigrpd/eigrp_const.h \
eigrpd/eigrp_errors.h \
@@ -64,5 +70,9 @@ noinst_HEADERS += \
eigrpd/eigrp_zebra.h \
# end
+nodist_eigrpd_eigrpd_SOURCES = \
+ yang/frr-eigrpd.yang.c \
+ # end
+
eigrpd_eigrpd_SOURCES = eigrpd/eigrp_main.c
eigrpd_eigrpd_LDADD = eigrpd/libeigrp.a lib/libfrr.la $(LIBCAP)
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 3ad8278e10..a7f491e87d 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -117,7 +117,8 @@ int dotformat2buff(uint8_t *buff, const char *dotted)
break;
}
- if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) {
+ if ((isxdigit((unsigned char)*pos)) &&
+ (isxdigit((unsigned char)*(pos + 1)))) {
memcpy(number, pos, 2);
pos += 2;
} else {
@@ -157,7 +158,8 @@ int sysid2buff(uint8_t *buff, const char *dotted)
pos++;
continue;
}
- if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) {
+ if ((isxdigit((unsigned char)*pos)) &&
+ (isxdigit((unsigned char)*(pos + 1)))) {
memcpy(number, pos, 2);
pos += 2;
} else {
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 6edfeb4c97..488dfedae4 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -1478,7 +1478,7 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
bool sane = true;
for (uint8_t i = 0; i < tlv_len; i++) {
if ((unsigned char)tlvs->hostname[i] > 127
- || !isprint((int)tlvs->hostname[i])) {
+ || !isprint((unsigned char)tlvs->hostname[i])) {
sane = false;
tlvs->hostname[i] = '?';
}
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 0ddf4f07d9..ac680b47a9 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -1654,6 +1654,19 @@ lde_del_label_chunk(void *val)
}
static int
+lde_release_label_chunk(uint32_t start, uint32_t end)
+{
+ int ret;
+
+ ret = lm_release_label_chunk(zclient_sync, start, end);
+ if (ret < 0) {
+ log_warnx("Error releasing label chunk!");
+ return (-1);
+ }
+ return (0);
+}
+
+static int
lde_get_label_chunk(void)
{
int ret;
@@ -1709,6 +1722,32 @@ on_get_label_chunk_response(uint32_t start, uint32_t end)
current_label_chunk = listtail(label_chunk_list);
}
+void
+lde_free_label(uint32_t label)
+{
+ struct listnode *node;
+ struct label_chunk *label_chunk;
+ uint64_t pos;
+
+ for (ALL_LIST_ELEMENTS_RO(label_chunk_list, node, label_chunk)) {
+ if (label <= label_chunk->end && label >= label_chunk->start) {
+ pos = 1ULL << (label - label_chunk->start);
+ label_chunk->used_mask &= ~pos;
+ /* if nobody is using this chunk and it's not current_label_chunk, then free it */
+ if (!label_chunk->used_mask && (current_label_chunk != node)) {
+ if (lde_release_label_chunk(label_chunk->start, label_chunk->end) != 0)
+ log_warnx("%s: Error releasing label chunk!", __func__);
+ else {
+ listnode_delete(label_chunk_list, label_chunk);
+ lde_del_label_chunk(label_chunk);
+ }
+ }
+ break;
+ }
+ }
+ return;
+}
+
static uint32_t
lde_get_next_label(void)
{
diff --git a/ldpd/lde.h b/ldpd/lde.h
index 94077d1631..0a7d0a58fe 100644
--- a/ldpd/lde.h
+++ b/ldpd/lde.h
@@ -147,6 +147,7 @@ void lde_imsg_compose_parent_sync(int, pid_t, void *, uint16_t);
int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t);
int lde_acl_check(char *, int, union ldpd_addr *, uint8_t);
uint32_t lde_update_label(struct fec_node *);
+void lde_free_label(uint32_t label);
void lde_send_change_klabel(struct fec_node *, struct fec_nh *);
void lde_send_delete_klabel(struct fec_node *, struct fec_nh *);
void lde_fec2map(struct fec *, struct map *);
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index 28e455c7a5..0957a5455e 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -919,6 +919,9 @@ lde_gc_timer(struct thread *thread)
!RB_EMPTY(lde_map_head, &fn->upstream))
continue;
+ if (fn->local_label != NO_LABEL)
+ lde_free_label(fn->local_label);
+
fec_remove(&ft, &fn->fec);
free(fn);
count++;
diff --git a/lib/atomlist.h b/lib/atomlist.h
index e4098ccb54..621db6824f 100644
--- a/lib/atomlist.h
+++ b/lib/atomlist.h
@@ -135,8 +135,10 @@ macro_inline void prefix ## _add_tail(struct prefix##_head *h, type *item) \
macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \
_Atomic atomptr_t *hint) \
{ atomlist_del_hint(&h->ah, &item->field.ai, hint); } \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
-{ atomlist_del_hint(&h->ah, &item->field.ai, NULL); } \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
+{ atomlist_del_hint(&h->ah, &item->field.ai, NULL); \
+ /* TODO: Return NULL if not found */ \
+ return item; } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ char *p = (char *)atomlist_pop(&h->ah); \
return p ? (type *)(p - offsetof(type, field)) : NULL; } \
@@ -273,9 +275,11 @@ macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \
{ \
atomsort_del_hint(&h->ah, &item->field.ai, hint); \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
atomsort_del_hint(&h->ah, &item->field.ai, NULL); \
+ /* TODO: Return NULL if not found */ \
+ return item; \
} \
macro_inline size_t prefix ## _count(struct prefix##_head *h) \
{ \
diff --git a/lib/command.c b/lib/command.c
index c8fbf22721..9dabc2af7e 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -89,7 +89,6 @@ const char *node_names[] = {
"aaa", // AAA_NODE,
"keychain", // KEYCHAIN_NODE,
"keychain key", // KEYCHAIN_KEY_NODE,
- "logical-router", // LOGICALROUTER_NODE,
"static ip", // IP_NODE,
"vrf", // VRF_NODE,
"interface", // INTERFACE_NODE,
@@ -290,7 +289,7 @@ vector cmd_make_strvec(const char *string)
const char *copy = string;
/* skip leading whitespace */
- while (isspace((int)*copy) && *copy != '\0')
+ while (isspace((unsigned char)*copy) && *copy != '\0')
copy++;
/* if the entire string was whitespace or a comment, return */
@@ -1456,7 +1455,6 @@ void cmd_exit(struct vty *vty)
break;
case INTERFACE_NODE:
case PW_NODE:
- case LOGICALROUTER_NODE:
case VRF_NODE:
case NH_GROUP_NODE:
case ZEBRA_NODE:
@@ -1936,7 +1934,7 @@ DEFUN(config_domainname,
{
struct cmd_token *word = argv[1];
- if (!isalpha((int)word->arg[0])) {
+ if (!isalpha((unsigned char)word->arg[0])) {
vty_out(vty, "Please specify string starting with alphabet\n");
return CMD_WARNING_CONFIG_FAILED;
}
@@ -1970,7 +1968,7 @@ DEFUN (config_hostname,
{
struct cmd_token *word = argv[1];
- if (!isalnum((int)word->arg[0])) {
+ if (!isalnum((unsigned char)word->arg[0])) {
vty_out(vty,
"Please specify string starting with alphabet or number\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -2018,7 +2016,7 @@ DEFUN (config_password,
return CMD_SUCCESS;
}
- if (!isalnum((int)argv[idx_8]->arg[0])) {
+ if (!isalnum((unsigned char)argv[idx_8]->arg[0])) {
vty_out(vty,
"Please specify string starting with alphanumeric\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -2098,7 +2096,7 @@ DEFUN (config_enable_password,
}
}
- if (!isalnum((int)argv[idx_8]->arg[0])) {
+ if (!isalnum((unsigned char)argv[idx_8]->arg[0])) {
vty_out(vty,
"Please specify string starting with alphanumeric\n");
return CMD_WARNING_CONFIG_FAILED;
diff --git a/lib/command.h b/lib/command.h
index 08d6128af4..8dc35a0fdc 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -98,7 +98,6 @@ enum node_type {
AAA_NODE, /* AAA node. */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
- LOGICALROUTER_NODE, /* Logical-Router node. */
IP_NODE, /* Static ip route node. */
VRF_NODE, /* VRF mode node. */
INTERFACE_NODE, /* Interface mode node. */
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 4757fd951f..d30d9ab702 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -97,7 +97,7 @@ void cmd_token_varname_set(struct cmd_token *token, const char *varname)
token->varname[i] = '_';
break;
default:
- token->varname[i] = tolower((int)varname[i]);
+ token->varname[i] = tolower((unsigned char)varname[i]);
}
token->varname[len] = '\0';
}
diff --git a/lib/command_match.c b/lib/command_match.c
index 9456e1585a..26d763849d 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -714,7 +714,7 @@ static enum match_type match_ipv4(const char *str)
dots++;
break;
}
- if (!isdigit((int)*str))
+ if (!isdigit((unsigned char)*str))
return no_match;
str++;
@@ -765,7 +765,7 @@ static enum match_type match_ipv4_prefix(const char *str)
break;
}
- if (!isdigit((int)*str))
+ if (!isdigit((unsigned char)*str))
return no_match;
str++;
@@ -797,7 +797,7 @@ static enum match_type match_ipv4_prefix(const char *str)
sp = str;
while (*str != '\0') {
- if (!isdigit((int)*str))
+ if (!isdigit((unsigned char)*str))
return no_match;
str++;
diff --git a/lib/filter.c b/lib/filter.c
index 14b89217b8..fe62ca1c13 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -273,7 +273,7 @@ static struct access_list *access_list_insert(afi_t afi, const char *name)
/* If name is made by all digit character. We treat it as
number. */
for (number = 0, i = 0; i < strlen(name); i++) {
- if (isdigit((int)name[i]))
+ if (isdigit((unsigned char)name[i]))
number = (number * 10) + (name[i] - '0');
else
break;
diff --git a/lib/frrstr.c b/lib/frrstr.c
index c575c0b568..8a72a35af0 100644
--- a/lib/frrstr.c
+++ b/lib/frrstr.c
@@ -209,7 +209,7 @@ bool frrstr_endswith(const char *str, const char *suffix)
int all_digit(const char *str)
{
for (; *str != '\0'; str++)
- if (!isdigit((int)*str))
+ if (!isdigit((unsigned char)*str))
return 0;
return 1;
}
diff --git a/lib/log.c b/lib/log.c
index 399d1af0c4..51a0ddd6b7 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -387,10 +387,8 @@ void vzlog(int priority, const char *format, va_list args)
/* If it doesn't match on a filter, do nothing with the debug log */
if ((priority == LOG_DEBUG) && zlog_filter_count
- && vzlog_filter(zl, &tsctl, proto_str, priority, msg)) {
- pthread_mutex_unlock(&loglock);
+ && vzlog_filter(zl, &tsctl, proto_str, priority, msg))
goto out;
- }
/* call external hook */
hook_call(zebra_ext_log, priority, format, args);
@@ -1267,6 +1265,7 @@ void zlog_hexdump(const void *mem, unsigned int len)
size_t bs = ((len / 8) + 1) * 53 + 1;
char buf[bs];
char *s = buf;
+ const unsigned char *memch = mem;
memset(buf, 0, sizeof(buf));
@@ -1275,12 +1274,11 @@ void zlog_hexdump(const void *mem, unsigned int len)
/* print offset */
if (i % columns == 0)
s += snprintf(s, bs - (s - buf),
- "0x%016lx: ", (unsigned long)mem + i);
+ "0x%016lx: ", (unsigned long)memch + i);
/* print hex data */
if (i < len)
- s += snprintf(s, bs - (s - buf), "%02x ",
- 0xFF & ((const char *)mem)[i]);
+ s += snprintf(s, bs - (s - buf), "%02x ", memch[i]);
/* end of block, just aligning for ASCII dump */
else
@@ -1292,10 +1290,9 @@ void zlog_hexdump(const void *mem, unsigned int len)
/* end of block not really printing */
if (j >= len)
s += snprintf(s, bs - (s - buf), " ");
- else if (isprint((int)((const char *)mem)[j]))
- s += snprintf(
- s, bs - (s - buf), "%c",
- 0xFF & ((const char *)mem)[j]);
+ else if (isprint(memch[j]))
+ s += snprintf(s, bs - (s - buf), "%c",
+ memch[j]);
else /* other char */
s += snprintf(s, bs - (s - buf), ".");
}
diff --git a/lib/logicalrouter.c b/lib/logicalrouter.c
deleted file mode 100644
index da69ae5312..0000000000
--- a/lib/logicalrouter.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Logical Router functions.
- * Copyright (C) 2018 6WIND S.A.
- *
- * 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 "ns.h"
-#include "log.h"
-#include "memory.h"
-
-#include "command.h"
-#include "vty.h"
-#include "logicalrouter.h"
-
-/* Comment that useless define to avoid compilation error
- * in order to use it, one could provide the kind of NETNS to NS backend
- * so that the allocation will match the logical router
- * DEFINE_MTYPE_STATIC(LIB, LOGICALROUTER, "LogicalRouter Context")
- */
-DEFINE_MTYPE_STATIC(LIB, LOGICALROUTER_NAME, "Logical Router Name")
-
-/* Logical Router node has no interface. */
-static struct cmd_node logicalrouter_node = {LOGICALROUTER_NODE, "", 1};
-
-static int logicalrouter_backend;
-
-/* Get a NS. If not found, create one. */
-static struct ns *logicalrouter_get(ns_id_t ns_id)
-{
- struct ns *ns;
-
- ns = ns_lookup(ns_id);
- if (ns)
- return (ns);
- ns = ns_get_created(ns, NULL, ns_id);
- return ns;
-}
-
-static int logicalrouter_is_backend_netns(void)
-{
- return (logicalrouter_backend == LOGICALROUTER_BACKEND_NETNS);
-}
-
-
-DEFUN_NOSH (logicalrouter,
- logicalrouter_cmd,
- "logical-router (1-65535) ns NAME",
- "Enable a logical-router\n"
- "Specify the logical-router indentifier\n"
- "The Name Space\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-{
- int idx_number = 1;
- int idx_name = 3;
- ns_id_t ns_id;
- struct ns *ns = NULL;
- char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
-
- if (!pathname)
- return CMD_WARNING_CONFIG_FAILED;
-
- ns_id = strtoul(argv[idx_number]->arg, NULL, 10);
- ns = logicalrouter_get(ns_id);
-
- if (ns->name && strcmp(ns->name, pathname) != 0) {
- vty_out(vty, "NS %u is already configured with NETNS %s\n",
- ns->ns_id, ns->name);
- return CMD_WARNING;
- }
-
- if (!ns->name)
- ns->name = XSTRDUP(MTYPE_LOGICALROUTER_NAME, pathname);
-
- if (!ns_enable(ns, NULL)) {
- vty_out(vty, "Can not associate NS %u with NETNS %s\n",
- ns->ns_id, ns->name);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_logicalrouter,
- no_logicalrouter_cmd,
- "no logical-router (1-65535) ns NAME",
- NO_STR
- "Enable a Logical-Router\n"
- "Specify the Logical-Router identifier\n"
- "The Name Space\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-{
- int idx_number = 2;
- int idx_name = 4;
- ns_id_t ns_id;
- struct ns *ns = NULL;
- char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
-
- if (!pathname)
- return CMD_WARNING_CONFIG_FAILED;
-
- ns_id = strtoul(argv[idx_number]->arg, NULL, 10);
- ns = ns_lookup(ns_id);
-
- if (!ns) {
- vty_out(vty, "NS %u is not found\n", ns_id);
- return CMD_SUCCESS;
- }
-
- if (ns->name && strcmp(ns->name, pathname) != 0) {
- vty_out(vty, "Incorrect NETNS file name\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ns_disable(ns);
-
- if (ns->name) {
- XFREE(MTYPE_LOGICALROUTER_NAME, ns->name);
- ns->name = NULL;
- }
-
- return CMD_SUCCESS;
-}
-
-/* Initialize NS module. */
-void logicalrouter_init(int (*writefunc)(struct vty *vty))
-{
- if (ns_have_netns() && logicalrouter_is_backend_netns()) {
- /* Install LogicalRouter commands. */
- install_node(&logicalrouter_node, writefunc);
- install_element(CONFIG_NODE, &logicalrouter_cmd);
- install_element(CONFIG_NODE, &no_logicalrouter_cmd);
- }
-}
-
-void logicalrouter_terminate(void)
-{
- ns_terminate();
-}
-
-void logicalrouter_configure_backend(int backend_netns)
-{
- logicalrouter_backend = backend_netns;
-}
diff --git a/lib/logicalrouter.h b/lib/logicalrouter.h
deleted file mode 100644
index d18832ef70..0000000000
--- a/lib/logicalrouter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Logical Router related header.
- * Copyright (C) 2018 6WIND S.A.
- *
- * 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 _ZEBRA_LOGICAL_ROUTER_H
-#define _ZEBRA_LOGICAL_ROUTER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Logical Router Backend defines */
-#define LOGICALROUTER_BACKEND_OFF 0
-#define LOGICALROUTER_BACKEND_NETNS 1
-
-/*
- * Logical Router initializer/destructor
- */
-extern void logicalrouter_init(int (*writefunc)(struct vty *vty));
-extern void logicalrouter_terminate(void);
-
-/* used to configure backend for logical router
- * Currently, the whole NETNS feature is exclusively shared
- * between logical router and VRF backend NETNS
- * However, when logical router feature will be available,
- * one can think of having exclusivity only per NETNS
- */
-extern void logicalrouter_configure_backend(int backend_netns);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_ZEBRA_LOGICAL_ROUTER_H*/
diff --git a/lib/netns_other.c b/lib/netns_other.c
index 4c7be05fab..b0aae4f8df 100644
--- a/lib/netns_other.c
+++ b/lib/netns_other.c
@@ -82,7 +82,7 @@ const char *ns_get_name(struct ns *ns)
}
/* only called from vrf ( when removing netns from vrf)
- * or at VRF or logical router termination
+ * or at VRF termination
*/
void ns_delete(struct ns *ns)
{
diff --git a/lib/ns.h b/lib/ns.h
index f3ad837889..1963b8a359 100644
--- a/lib/ns.h
+++ b/lib/ns.h
@@ -41,7 +41,7 @@ typedef uint32_t ns_id_t;
#ifdef HAVE_NETNS
#define NS_DEFAULT_NAME "/proc/self/ns/net"
#else /* !HAVE_NETNS */
-#define NS_DEFAULT_NAME "Default-logical-router"
+#define NS_DEFAULT_NAME "default-netns"
#endif /* HAVE_NETNS */
struct ns {
@@ -82,10 +82,10 @@ extern struct ns_head ns_tree;
* NS hooks
*/
-#define NS_NEW_HOOK 0 /* a new logical-router is just created */
-#define NS_DELETE_HOOK 1 /* a logical-router is to be deleted */
-#define NS_ENABLE_HOOK 2 /* a logical-router is ready to use */
-#define NS_DISABLE_HOOK 3 /* a logical-router is to be unusable */
+#define NS_NEW_HOOK 0 /* a new netns is just created */
+#define NS_DELETE_HOOK 1 /* a netns is to be deleted */
+#define NS_ENABLE_HOOK 2 /* a netns is ready to use */
+#define NS_DISABLE_HOOK 3 /* a netns is to be unusable */
/*
* Add a specific hook ns module.
@@ -128,7 +128,7 @@ extern void ns_walk_func(int (*func)(struct ns *));
extern const char *ns_get_name(struct ns *ns);
/* only called from vrf ( when removing netns from vrf)
- * or at VRF or logical router termination
+ * or at VRF termination
*/
extern void ns_delete(struct ns *ns);
diff --git a/lib/plist.c b/lib/plist.c
index 1ba8982499..64571a05b7 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -218,7 +218,7 @@ static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
/* If name is made by all digit character. We treat it as
number. */
for (number = 0, i = 0; i < strlen(name); i++) {
- if (isdigit((int)name[i]))
+ if (isdigit((unsigned char)name[i]))
number = (number * 10) + (name[i] - '0');
else
break;
diff --git a/lib/pqueue.c b/lib/pqueue.c
deleted file mode 100644
index 87b54a681a..0000000000
--- a/lib/pqueue.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Priority queue functions.
- * Copyright (C) 2003 Yasuhiro Ohara
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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.
- *
- * GNU Zebra 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 "memory.h"
-#include "pqueue.h"
-
-DEFINE_MTYPE_STATIC(LIB, PQUEUE, "Priority queue")
-DEFINE_MTYPE_STATIC(LIB, PQUEUE_DATA, "Priority queue data")
-
-/* priority queue using heap sort */
-
-/* pqueue->cmp() controls the order of sorting (i.e, ascending or
- descending). If you want the left node to move upper of the heap
- binary tree, make cmp() to return less than 0. for example, if cmp
- (10, 20) returns -1, the sorting is ascending order. if cmp (10,
- 20) returns 1, the sorting is descending order. if cmp (10, 20)
- returns 0, this library does not do sorting (which will not be what
- you want). To be brief, if the contents of cmp_func (left, right)
- is left - right, dequeue () returns the smallest node. Otherwise
- (if the contents is right - left), dequeue () returns the largest
- node. */
-
-#define DATA_SIZE (sizeof (void *))
-#define PARENT_OF(x) ((x - 1) / 2)
-#define LEFT_OF(x) (2 * x + 1)
-#define RIGHT_OF(x) (2 * x + 2)
-#define HAVE_CHILD(x,q) (x < (q)->size / 2)
-
-void trickle_up(int index, struct pqueue *queue)
-{
- void *tmp;
-
- /* Save current node as tmp node. */
- tmp = queue->array[index];
-
- /* Continue until the node reaches top or the place where the parent
- node should be upper than the tmp node. */
- while (index > 0
- && (*queue->cmp)(tmp, queue->array[PARENT_OF(index)]) < 0) {
- /* actually trickle up */
- queue->array[index] = queue->array[PARENT_OF(index)];
- if (queue->update != NULL)
- (*queue->update)(queue->array[index], index);
- index = PARENT_OF(index);
- }
-
- /* Restore the tmp node to appropriate place. */
- queue->array[index] = tmp;
- if (queue->update != NULL)
- (*queue->update)(tmp, index);
-}
-
-void trickle_down(int index, struct pqueue *queue)
-{
- void *tmp;
- int which;
-
- /* Save current node as tmp node. */
- tmp = queue->array[index];
-
- /* Continue until the node have at least one (left) child. */
- while (HAVE_CHILD(index, queue)) {
- /* If right child exists, and if the right child is more proper
- to be moved upper. */
- if (RIGHT_OF(index) < queue->size
- && (*queue->cmp)(queue->array[LEFT_OF(index)],
- queue->array[RIGHT_OF(index)])
- > 0)
- which = RIGHT_OF(index);
- else
- which = LEFT_OF(index);
-
- /* If the tmp node should be upper than the child, break. */
- if ((*queue->cmp)(queue->array[which], tmp) > 0)
- break;
-
- /* Actually trickle down the tmp node. */
- queue->array[index] = queue->array[which];
- if (queue->update != NULL)
- (*queue->update)(queue->array[index], index);
- index = which;
- }
-
- /* Restore the tmp node to appropriate place. */
- queue->array[index] = tmp;
- if (queue->update != NULL)
- (*queue->update)(tmp, index);
-}
-
-struct pqueue *pqueue_create(void)
-{
- struct pqueue *queue;
-
- queue = XCALLOC(MTYPE_PQUEUE, sizeof(struct pqueue));
-
- queue->array =
- XCALLOC(MTYPE_PQUEUE_DATA, DATA_SIZE * PQUEUE_INIT_ARRAYSIZE);
- queue->array_size = PQUEUE_INIT_ARRAYSIZE;
-
- /* By default we want nothing to happen when a node changes. */
- queue->update = NULL;
- return queue;
-}
-
-void pqueue_delete(struct pqueue *queue)
-{
- XFREE(MTYPE_PQUEUE_DATA, queue->array);
- XFREE(MTYPE_PQUEUE, queue);
-}
-
-static int pqueue_expand(struct pqueue *queue)
-{
- void **newarray;
-
- newarray =
- XCALLOC(MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2);
-
- memcpy(newarray, queue->array, queue->array_size * DATA_SIZE);
-
- XFREE(MTYPE_PQUEUE_DATA, queue->array);
- queue->array = newarray;
- queue->array_size *= 2;
-
- return 1;
-}
-
-void pqueue_enqueue(void *data, struct pqueue *queue)
-{
- if (queue->size + 2 >= queue->array_size && !pqueue_expand(queue))
- return;
-
- queue->array[queue->size] = data;
- if (queue->update != NULL)
- (*queue->update)(data, queue->size);
- trickle_up(queue->size, queue);
- queue->size++;
-}
-
-void *pqueue_dequeue(struct pqueue *queue)
-{
- void *data = queue->array[0];
- queue->array[0] = queue->array[--queue->size];
- trickle_down(0, queue);
- return data;
-}
-
-void pqueue_remove_at(int index, struct pqueue *queue)
-{
- queue->array[index] = queue->array[--queue->size];
-
- if (index > 0
- && (*queue->cmp)(queue->array[index],
- queue->array[PARENT_OF(index)])
- < 0) {
- trickle_up(index, queue);
- } else {
- trickle_down(index, queue);
- }
-}
-
-void pqueue_remove(void *data, struct pqueue *queue)
-{
- for (int i = 0; i < queue->size; i++)
- if (queue->array[i] == data)
- pqueue_remove_at(i, queue);
-}
diff --git a/lib/pqueue.h b/lib/pqueue.h
deleted file mode 100644
index 032ee9db4c..0000000000
--- a/lib/pqueue.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Priority queue functions.
- * Copyright (C) 2003 Yasuhiro Ohara
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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.
- *
- * GNU Zebra 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 _ZEBRA_PQUEUE_H
-#define _ZEBRA_PQUEUE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct pqueue {
- void **array;
- int array_size;
- int size;
-
- int (*cmp)(void *, void *);
- void (*update)(void *node, int actual_position);
-};
-
-#define PQUEUE_INIT_ARRAYSIZE 32
-
-extern struct pqueue *pqueue_create(void);
-extern void pqueue_delete(struct pqueue *queue);
-
-extern void pqueue_enqueue(void *data, struct pqueue *queue);
-extern void *pqueue_dequeue(struct pqueue *queue);
-extern void pqueue_remove_at(int index, struct pqueue *queue);
-extern void pqueue_remove(void *data, struct pqueue *queue);
-
-extern void trickle_down(int index, struct pqueue *queue);
-extern void trickle_up(int index, struct pqueue *queue);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZEBRA_PQUEUE_H */
diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c
index 7f868beda4..a2ce9a0e2f 100644
--- a/lib/ptm_lib.c
+++ b/lib/ptm_lib.c
@@ -125,7 +125,7 @@ static int _ptm_lib_decode_header(csv_t *csv, int *msglen, int *version,
}
/* remove leading spaces */
for (i = j = 0; i < csv_field_len(fld); i++) {
- if (!isspace((int)hdr[i])) {
+ if (!isspace((unsigned char)hdr[i])) {
client_name[j] = hdr[i];
j++;
}
diff --git a/lib/subdir.am b/lib/subdir.am
index becc80c3f3..2be7537bcc 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -62,7 +62,6 @@ lib_libfrr_la_SOURCES = \
lib/openbsd-tree.c \
lib/pid_output.c \
lib/plist.c \
- lib/pqueue.c \
lib/prefix.c \
lib/privs.c \
lib/ptm_lib.c \
@@ -96,7 +95,6 @@ lib_libfrr_la_SOURCES = \
lib/yang_translator.c \
lib/yang_wrappers.c \
lib/zclient.c \
- lib/logicalrouter.c \
lib/printf/printf-pos.c \
lib/printf/vfprintf.c \
lib/printf/glue.c \
@@ -114,7 +112,6 @@ vtysh_scan += \
$(top_srcdir)/lib/if.c \
$(top_srcdir)/lib/if_rmap.c \
$(top_srcdir)/lib/keychain.c \
- $(top_srcdir)/lib/logicalrouter.c \
$(top_srcdir)/lib/nexthop_group.c \
$(top_srcdir)/lib/plist.c \
$(top_srcdir)/lib/routemap.c \
@@ -202,7 +199,6 @@ pkginclude_HEADERS += \
lib/openbsd-queue.h \
lib/openbsd-tree.h \
lib/plist.h \
- lib/pqueue.h \
lib/prefix.h \
lib/printfrr.h \
lib/privs.h \
@@ -243,7 +239,6 @@ pkginclude_HEADERS += \
lib/zassert.h \
lib/zclient.h \
lib/zebra.h \
- lib/logicalrouter.h \
lib/pbr.h \
# end
diff --git a/lib/thread.c b/lib/thread.c
index 0436f31c3d..5756ebc1f9 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -28,7 +28,6 @@
#include "frrcu.h"
#include "log.h"
#include "hash.h"
-#include "pqueue.h"
#include "command.h"
#include "sigevent.h"
#include "network.h"
@@ -43,6 +42,22 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
DECLARE_LIST(thread_list, struct thread, threaditem)
+static int thread_timer_cmp(const struct thread *a, const struct thread *b)
+{
+ if (a->u.sands.tv_sec < b->u.sands.tv_sec)
+ return -1;
+ if (a->u.sands.tv_sec > b->u.sands.tv_sec)
+ return 1;
+ if (a->u.sands.tv_usec < b->u.sands.tv_usec)
+ return -1;
+ if (a->u.sands.tv_usec > b->u.sands.tv_usec)
+ return 1;
+ return 0;
+}
+
+DECLARE_HEAP(thread_timer_list, struct thread, timeritem,
+ thread_timer_cmp)
+
#if defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
@@ -402,25 +417,6 @@ void thread_cmd_init(void)
/* CLI end ------------------------------------------------------------------ */
-static int thread_timer_cmp(void *a, void *b)
-{
- struct thread *thread_a = a;
- struct thread *thread_b = b;
-
- if (timercmp(&thread_a->u.sands, &thread_b->u.sands, <))
- return -1;
- if (timercmp(&thread_a->u.sands, &thread_b->u.sands, >))
- return 1;
- return 0;
-}
-
-static void thread_timer_update(void *node, int actual_position)
-{
- struct thread *thread = node;
-
- thread->index = actual_position;
-}
-
static void cancelreq_del(void *cr)
{
XFREE(MTYPE_TMP, cr);
@@ -465,11 +461,7 @@ struct thread_master *thread_master_create(const char *name)
thread_list_init(&rv->event);
thread_list_init(&rv->ready);
thread_list_init(&rv->unuse);
-
- /* Initialize the timer queues */
- rv->timer = pqueue_create();
- rv->timer->cmp = thread_timer_cmp;
- rv->timer->update = thread_timer_update;
+ thread_timer_list_init(&rv->timer);
/* Initialize thread_fetch() settings */
rv->spin = true;
@@ -567,16 +559,6 @@ static void thread_array_free(struct thread_master *m,
XFREE(MTYPE_THREAD_POLL, thread_array);
}
-static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
-{
- int i;
-
- for (i = 0; i < queue->size; i++)
- thread_free(m, queue->array[i]);
-
- pqueue_delete(queue);
-}
-
/*
* thread_master_free_unused
*
@@ -599,6 +581,8 @@ void thread_master_free_unused(struct thread_master *m)
/* Stop thread scheduler. */
void thread_master_free(struct thread_master *m)
{
+ struct thread *t;
+
pthread_mutex_lock(&masters_mtx);
{
listnode_delete(masters, m);
@@ -610,7 +594,8 @@ void thread_master_free(struct thread_master *m)
thread_array_free(m, m->read);
thread_array_free(m, m->write);
- thread_queue_free(m, m->timer);
+ while ((t = thread_timer_list_pop(&m->timer)))
+ thread_free(m, t);
thread_list_free(m, &m->event);
thread_list_free(m, &m->ready);
thread_list_free(m, &m->unuse);
@@ -684,7 +669,6 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
thread->add_type = type;
thread->master = m;
thread->arg = arg;
- thread->index = -1;
thread->yield = THREAD_YIELD_TIME_SLOT; /* default */
thread->ref = NULL;
@@ -860,7 +844,6 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
struct thread **t_ptr, debugargdef)
{
struct thread *thread;
- struct pqueue *queue;
assert(m != NULL);
@@ -876,7 +859,6 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
return NULL;
}
- queue = m->timer;
thread = thread_get(m, type, func, arg, debugargpass);
pthread_mutex_lock(&thread->mtx);
@@ -884,7 +866,7 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
monotime(&thread->u.sands);
timeradd(&thread->u.sands, time_relative,
&thread->u.sands);
- pqueue_enqueue(thread, queue);
+ thread_timer_list_add(&m->timer, thread);
if (t_ptr) {
*t_ptr = thread;
thread->ref = t_ptr;
@@ -1061,7 +1043,6 @@ static void thread_cancel_rw(struct thread_master *master, int fd, short state)
static void do_thread_cancel(struct thread_master *master)
{
struct thread_list_head *list = NULL;
- struct pqueue *queue = NULL;
struct thread **thread_array = NULL;
struct thread *thread;
@@ -1117,7 +1098,7 @@ static void do_thread_cancel(struct thread_master *master)
thread_array = master->write;
break;
case THREAD_TIMER:
- queue = master->timer;
+ thread_timer_list_del(&master->timer, thread);
break;
case THREAD_EVENT:
list = &master->event;
@@ -1130,16 +1111,10 @@ static void do_thread_cancel(struct thread_master *master)
break;
}
- if (queue) {
- assert(thread->index >= 0);
- assert(thread == queue->array[thread->index]);
- pqueue_remove_at(thread->index, queue);
- } else if (list) {
+ if (list) {
thread_list_del(list, thread);
} else if (thread_array) {
thread_array[thread->u.fd] = NULL;
- } else {
- assert(!"Thread should be either in queue or list or array!");
}
if (thread->ref)
@@ -1257,15 +1232,15 @@ void thread_cancel_async(struct thread_master *master, struct thread **thread,
}
/* ------------------------------------------------------------------------- */
-static struct timeval *thread_timer_wait(struct pqueue *queue,
+static struct timeval *thread_timer_wait(struct thread_timer_list_head *timers,
struct timeval *timer_val)
{
- if (queue->size) {
- struct thread *next_timer = queue->array[0];
- monotime_until(&next_timer->u.sands, timer_val);
- return timer_val;
- }
- return NULL;
+ if (!thread_timer_list_count(timers))
+ return NULL;
+
+ struct thread *next_timer = thread_timer_list_first(timers);
+ monotime_until(&next_timer->u.sands, timer_val);
+ return timer_val;
}
static struct thread *thread_run(struct thread_master *m, struct thread *thread,
@@ -1375,17 +1350,16 @@ static void thread_process_io(struct thread_master *m, unsigned int num)
}
/* Add all timers that have popped to the ready list. */
-static unsigned int thread_process_timers(struct pqueue *queue,
+static unsigned int thread_process_timers(struct thread_timer_list_head *timers,
struct timeval *timenow)
{
struct thread *thread;
unsigned int ready = 0;
- while (queue->size) {
- thread = queue->array[0];
+ while ((thread = thread_timer_list_first(timers))) {
if (timercmp(timenow, &thread->u.sands, <))
return ready;
- pqueue_dequeue(queue);
+ thread_timer_list_pop(timers);
thread->type = THREAD_READY;
thread_list_add_tail(&thread->master->ready, thread);
ready++;
@@ -1467,7 +1441,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
* once per loop to avoid starvation by events
*/
if (!thread_list_count(&m->ready))
- tw = thread_timer_wait(m->timer, &tv);
+ tw = thread_timer_wait(&m->timer, &tv);
if (thread_list_count(&m->ready) ||
(tw && !timercmp(tw, &zerotime, >)))
@@ -1512,7 +1486,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
/* Post timers to ready queue. */
monotime(&now);
- thread_process_timers(m->timer, &now);
+ thread_process_timers(&m->timer, &now);
/* Post I/O to ready queue. */
if (num > 0)
diff --git a/lib/thread.h b/lib/thread.h
index 7897265120..412a4d93bf 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -41,8 +41,7 @@ struct rusage_t {
#define GETRUSAGE(X) thread_getrusage(X)
PREDECL_LIST(thread_list)
-
-struct pqueue;
+PREDECL_HEAP(thread_timer_list)
struct fd_handler {
/* number of pfd that fit in the allocated space of pfds. This is a
@@ -73,7 +72,7 @@ struct thread_master {
struct thread **read;
struct thread **write;
- struct pqueue *timer;
+ struct thread_timer_list_head timer;
struct thread_list_head event, ready, unuse;
struct list *cancel_req;
bool canceled;
@@ -95,6 +94,7 @@ struct thread {
uint8_t type; /* thread type */
uint8_t add_type; /* thread type */
struct thread_list_item threaditem;
+ struct thread_timer_list_item timeritem;
struct thread **ref; /* external reference (if given) */
struct thread_master *master; /* pointer to the struct thread_master */
int (*func)(struct thread *); /* event function */
@@ -104,7 +104,6 @@ struct thread {
int fd; /* file descriptor in case of r/w */
struct timeval sands; /* rest of time sands value. */
} u;
- int index; /* queue position for timers */
struct timeval real;
struct cpu_thread_history *hist; /* cache pointer to cpu_history */
unsigned long yield; /* yield time in microseconds */
diff --git a/lib/typerb.c b/lib/typerb.c
index 4c48d6434f..3886fc678e 100644
--- a/lib/typerb.c
+++ b/lib/typerb.c
@@ -333,9 +333,10 @@ color:
return (old);
}
-void typed_rb_remove(struct rbt_tree *rbt, struct rb_entry *rbe)
+struct typed_rb_entry *typed_rb_remove(struct rbt_tree *rbt,
+ struct rb_entry *rbe)
{
- rbe_remove(rbt, rbe);
+ return rbe_remove(rbt, rbe);
}
struct typed_rb_entry *typed_rb_insert(struct rbt_tree *rbt,
diff --git a/lib/typerb.h b/lib/typerb.h
index ce8446f853..2d7b0ba637 100644
--- a/lib/typerb.h
+++ b/lib/typerb.h
@@ -38,29 +38,30 @@ struct typed_rb_root {
size_t count;
};
-struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *,
+struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *rbt,
struct typed_rb_entry *rbe,
int (*cmpfn)(
const struct typed_rb_entry *a,
const struct typed_rb_entry *b));
-void typed_rb_remove(struct typed_rb_root *, struct typed_rb_entry *rbe);
-struct typed_rb_entry *typed_rb_find(struct typed_rb_root *,
+struct typed_rb_entry *typed_rb_remove(struct typed_rb_root *rbt,
+ struct typed_rb_entry *rbe);
+struct typed_rb_entry *typed_rb_find(struct typed_rb_root *rbt,
const struct typed_rb_entry *rbe,
int (*cmpfn)(
const struct typed_rb_entry *a,
const struct typed_rb_entry *b));
-struct typed_rb_entry *typed_rb_find_gteq(struct typed_rb_root *,
+struct typed_rb_entry *typed_rb_find_gteq(struct typed_rb_root *rbt,
const struct typed_rb_entry *rbe,
int (*cmpfn)(
const struct typed_rb_entry *a,
const struct typed_rb_entry *b));
-struct typed_rb_entry *typed_rb_find_lt(struct typed_rb_root *,
+struct typed_rb_entry *typed_rb_find_lt(struct typed_rb_root *rbt,
const struct typed_rb_entry *rbe,
int (*cmpfn)(
const struct typed_rb_entry *a,
const struct typed_rb_entry *b));
-struct typed_rb_entry *typed_rb_min(struct typed_rb_root *);
-struct typed_rb_entry *typed_rb_next(struct typed_rb_entry *);
+struct typed_rb_entry *typed_rb_min(struct typed_rb_root *rbt);
+struct typed_rb_entry *typed_rb_next(struct typed_rb_entry *rbe);
#define _PREDECL_RBTREE(prefix) \
struct prefix ## _head { struct typed_rb_root rr; }; \
@@ -99,9 +100,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
re = typed_rb_find_lt(&h->rr, &item->field.re, cmpfn_nuq); \
return container_of_null(re, type, field.re); \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
- typed_rb_remove(&h->rr, &item->field.re); \
+ struct typed_rb_entry *re; \
+ re = typed_rb_remove(&h->rr, &item->field.re); \
+ return container_of_null(re, type, field.re); \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -130,7 +133,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
re = item ? typed_rb_next(&item->field.re) : NULL; \
return container_of_null(re, type, field.re); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->rr.count; \
} \
diff --git a/lib/typesafe.c b/lib/typesafe.c
index f2ca67b7c6..7e5939d5b3 100644
--- a/lib/typesafe.c
+++ b/lib/typesafe.c
@@ -341,13 +341,14 @@ struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head,
return best;
}
-void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
- int (*cmpfn)(const struct sskip_item *a,
- const struct sskip_item *b))
+struct sskip_item *typesafe_skiplist_del(
+ struct sskip_head *head, struct sskip_item *item,
+ int (*cmpfn)(const struct sskip_item *a, const struct sskip_item *b))
{
size_t level = SKIPLIST_MAXDEPTH;
struct sskip_item *prev = &head->hitem, *next;
int cmpval;
+ bool found = false;
while (level) {
next = sl_level_get(prev, level - 1);
@@ -359,6 +360,7 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
sl_level_set(prev, level - 1,
sl_level_get(item, level - 1));
level--;
+ found = true;
continue;
}
cmpval = cmpfn(next, item);
@@ -369,6 +371,9 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
level--;
}
+ if (!found)
+ return NULL;
+
/* TBD: assert when trying to remove non-existing item? */
head->count--;
@@ -379,6 +384,8 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
XFREE(MTYPE_SKIPLIST_OFLOW, oflow);
}
memset(item, 0, sizeof(*item));
+
+ return item;
}
struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head)
diff --git a/lib/typesafe.h b/lib/typesafe.h
index ee244c78ae..c30d73d1b3 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -109,17 +109,18 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
typesafe_list_add(&h->sh, nextp, &item->field.si); \
} \
/* TODO: del_hint */ \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct slist_item **iter = &h->sh.first; \
while (*iter && *iter != &item->field.si) \
iter = &(*iter)->next; \
if (!*iter) \
- return; \
+ return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
if (!item->field.si.next) \
h->sh.last_next = iter; \
+ return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -149,7 +150,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
sitem = &item->field.si; \
return container_of_null(sitem->next, type, field.si); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->sh.count; \
} \
@@ -212,13 +213,14 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
prev = after ? &after->field.di : &h->dh.hitem; \
typesafe_dlist_add(&h->dh, prev, &item->field.di); \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct dlist_item *ditem = &item->field.di; \
ditem->prev->next = ditem->next; \
ditem->next->prev = ditem->prev; \
h->dh.count--; \
ditem->prev = ditem->next = NULL; \
+ return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -250,7 +252,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
return NULL; \
return prefix ## _next(h, item); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->dh.count; \
} \
@@ -308,7 +310,7 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
h->hh.count++; \
return NULL; \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct heap_item *other; \
uint32_t index = item->field.hi.index; \
@@ -321,6 +323,7 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
typesafe_heap_pushdown(&h->hh, index, other, prefix ## __cmp); \
if (HEAP_RESIZE_TRESH_DN(h)) \
typesafe_heap_resize(&h->hh, false); \
+ return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -354,7 +357,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
return NULL; \
return prefix ## _next(h, item); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
@@ -449,15 +452,16 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
return container_of_null(prev, type, field.si); \
} \
/* TODO: del_hint */ \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct ssort_item **iter = &h->sh.first; \
while (*iter && *iter != &item->field.si) \
iter = &(*iter)->next; \
if (!*iter) \
- return; \
+ return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
+ return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -485,7 +489,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
sitem = &item->field.si; \
return container_of_null(sitem->next, type, field.si); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->sh.count; \
} \
@@ -617,10 +621,10 @@ macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \
} \
return NULL; \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
if (!h->hh.tabshift) \
- return; \
+ return NULL; \
uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \
struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \
@@ -628,12 +632,13 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
while (*np && *np != &item->field.hi && (*np)->hashval == hval) \
np = &(*np)->next; \
if (*np != &item->field.hi) \
- return; \
+ return NULL; \
*np = item->field.hi.next; \
item->field.hi.next = NULL; \
h->hh.count--; \
if (HASH_SHRINK_THRESHOLD(h->hh)) \
typesafe_hash_shrink(&h->hh); \
+ return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -675,7 +680,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
return NULL; \
return prefix ## _next(h, item); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
@@ -751,9 +756,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
&item->field.si, cmpfn_nuq); \
return container_of_null(sitem, type, field.si); \
} \
-macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
+macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
- typesafe_skiplist_del(&h->sh, &item->field.si, cmpfn_uq); \
+ struct sskip_item *sitem = typesafe_skiplist_del(&h->sh, \
+ &item->field.si, cmpfn_uq); \
+ return container_of_null(sitem, type, field.si); \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
@@ -776,7 +783,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
next = item ? item->field.si.next[0] : NULL; \
return container_of_null(next, type, field.si); \
} \
-macro_pure size_t prefix ## _count(struct prefix##_head *h) \
+macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->sh.count; \
} \
@@ -848,8 +855,8 @@ extern struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head,
const struct sskip_item *item, int (*cmpfn)(
const struct sskip_item *a,
const struct sskip_item *b));
-extern void typesafe_skiplist_del(struct sskip_head *head,
- struct sskip_item *item, int (*cmpfn)(
+extern struct sskip_item *typesafe_skiplist_del(
+ struct sskip_head *head, struct sskip_item *item, int (*cmpfn)(
const struct sskip_item *a,
const struct sskip_item *b));
extern struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head);
diff --git a/lib/vty.c b/lib/vty.c
index 18a449f647..c1535802cf 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -337,7 +337,8 @@ void vty_hello(struct vty *vty)
/* work backwards to ignore trailling isspace()
*/
for (s = buf + strlen(buf);
- (s > buf) && isspace((int)*(s - 1)); s--)
+ (s > buf) && isspace((unsigned char)s[-1]);
+ s--)
;
*s = '\0';
vty_out(vty, "%s\n", buf);
@@ -468,7 +469,7 @@ static int vty_command(struct vty *vty, char *buf)
cp = buf;
if (cp != NULL) {
/* Skip white spaces. */
- while (isspace((int)*cp) && *cp != '\0')
+ while (isspace((unsigned char)*cp) && *cp != '\0')
cp++;
}
if (cp != NULL && *cp != '\0') {
@@ -892,7 +893,7 @@ static void vty_complete_command(struct vty *vty)
return;
/* In case of 'help \t'. */
- if (isspace((int)vty->buf[vty->length - 1]))
+ if (isspace((unsigned char)vty->buf[vty->length - 1]))
vector_set(vline, NULL);
matched = cmd_complete_command(vline, vty, &ret);
@@ -1006,7 +1007,7 @@ static void vty_describe_command(struct vty *vty)
if (vline == NULL) {
vline = vector_init(1);
vector_set(vline, NULL);
- } else if (isspace((int)vty->buf[vty->length - 1]))
+ } else if (isspace((unsigned char)vty->buf[vty->length - 1]))
vector_set(vline, NULL);
describe = cmd_describe_command(vline, vty, &ret);
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 6d1e44996e..1d85a04984 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -83,6 +83,9 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
struct as_external_lsa *al;
struct prefix_ipv4 p;
struct route_node *rn;
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
int type;
al = (struct as_external_lsa *)lsa->data;
@@ -91,7 +94,7 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
p.prefix = lsa->data->id;
p.prefixlen = ip_masklen(al->mask);
- for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
int redist_on = 0;
redist_on =
@@ -105,10 +108,6 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
ospf->vrf_id));
// Pending: check for MI above.
if (redist_on) {
- struct list *ext_list;
- struct listnode *node;
- struct ospf_external *ext;
-
ext_list = ospf->external[type];
if (!ext_list)
continue;
@@ -129,6 +128,22 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
}
}
+ if (is_prefix_default(&p) && ospf->external[DEFAULT_ROUTE]) {
+ ext_list = ospf->external[DEFAULT_ROUTE];
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ if (!ext->external_info)
+ continue;
+
+ rn = route_node_lookup(ext->external_info,
+ (struct prefix *)&p);
+ if (!rn)
+ continue;
+ route_unlock_node(rn);
+ if (rn->info != NULL)
+ return (struct external_info *)rn->info;
+ }
+ }
return NULL;
}
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index bf46d22031..db41df7c47 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1979,6 +1979,13 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
*/
+ if (ospf->router_id.s_addr == 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:%pI4]: deferring AS-external-LSA origination, router ID is zero",
+ &ei->p.prefix);
+ return NULL;
+ }
+
/* Check the AS-external-LSA should be originated. */
if (!ospf_redistribute_check(ospf, ei, NULL))
return NULL;
@@ -2019,50 +2026,6 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
return new;
}
-/* Originate AS-external-LSA from external info with initial flag. */
-int ospf_external_lsa_originate_timer(struct thread *thread)
-{
- struct ospf *ospf = THREAD_ARG(thread);
- struct route_node *rn;
- struct external_info *ei;
- struct route_table *rt;
- int type = THREAD_VAL(thread);
- struct list *ext_list;
- struct listnode *node;
- struct ospf_external *ext;
-
- ospf->t_external_lsa = NULL;
-
- ext_list = ospf->external[type];
- if (!ext_list)
- return 0;
-
- for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
- /* Originate As-external-LSA from all type of distribute source.
- */
- rt = ext->external_info;
- if (!rt)
- continue;
-
- for (rn = route_top(rt); rn; rn = route_next(rn)) {
- ei = rn->info;
-
- if (!ei)
- continue;
-
- if (is_prefix_default((struct prefix_ipv4 *)&ei->p))
- continue;
-
- if (!ospf_external_lsa_originate(ospf, ei))
- flog_warn(
- EC_OSPF_LSA_INSTALL_FAILURE,
- "LSA: AS-external-LSA was not originated.");
- }
- }
-
- return 0;
-}
-
static struct external_info *ospf_default_external_info(struct ospf *ospf)
{
int type;
@@ -2102,31 +2065,52 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf)
return NULL;
}
-int ospf_default_originate_timer(struct thread *thread)
+void ospf_external_lsa_rid_change(struct ospf *ospf)
{
- struct prefix_ipv4 p;
- struct in_addr nexthop;
struct external_info *ei;
- struct ospf *ospf;
+ int type;
- ospf = THREAD_ARG(thread);
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
+ struct route_node *rn;
+ struct route_table *rt;
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
+ ext_list = ospf->external[type];
+ if (!ext_list)
+ continue;
- if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) {
- /* If there is no default route via redistribute,
- then originate AS-external-LSA with nexthop 0 (self). */
- nexthop.s_addr = 0;
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop,
- 0);
- }
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ /* Originate As-external-LSA from all type of
+ * distribute source.
+ */
+ rt = ext->external_info;
+ if (!rt)
+ continue;
- if ((ei = ospf_default_external_info(ospf)))
- ospf_external_lsa_originate(ospf, ei);
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ ei = rn->info;
- return 0;
+ if (!ei)
+ continue;
+
+ if (is_prefix_default(
+ (struct prefix_ipv4 *)&ei->p))
+ continue;
+
+ if (!ospf_external_lsa_originate(ospf, ei))
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "LSA: AS-external-LSA was not originated.");
+ }
+ }
+ }
+
+ ei = ospf_default_external_info(ospf);
+ if (ei && !ospf_external_lsa_originate(ospf, ei)) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "LSA: AS-external-LSA for default route was not originated.");
+ }
}
/* Flush any NSSA LSAs for given prefix */
@@ -2218,44 +2202,20 @@ void ospf_external_lsa_refresh_default(struct ospf *ospf)
ei = ospf_default_external_info(ospf);
lsa = ospf_external_info_find_lsa(ospf, &p);
- if (ei) {
- if (lsa) {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
- (void *)lsa);
- ospf_external_lsa_refresh(ospf, lsa, ei,
- LSA_REFRESH_FORCE);
- } else {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
- ospf_external_lsa_originate(ospf, ei);
- }
- } else {
- if (lsa) {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
- ospf_refresher_unregister_lsa(ospf, lsa);
- ospf_lsa_flush_as(ospf, lsa);
- }
- }
-}
-
-void ospf_default_originate_lsa_update(struct ospf *ospf)
-{
- struct prefix_ipv4 p;
- struct ospf_lsa *lsa;
-
- p.family = AF_INET;
- p.prefixlen = 0;
- p.prefix.s_addr = 0;
-
- lsa = ospf_external_info_find_lsa(ospf, &p);
- if (lsa && IS_LSA_MAXAGE(lsa)) {
- ospf_discard_from_db(ospf, lsa->lsdb, lsa);
- ospf_lsdb_delete(lsa->lsdb, lsa);
+ if (ei && lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
+ (void *)lsa);
+ ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE);
+ } else if (ei && !lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
+ ospf_external_lsa_originate(ospf, ei);
+ } else if (lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
+ ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
}
}
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 5e3dabc27a..4033659bff 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -275,8 +275,7 @@ extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *);
extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *,
struct external_info *);
-extern int ospf_external_lsa_originate_timer(struct thread *);
-extern int ospf_default_originate_timer(struct thread *);
+extern void ospf_external_lsa_rid_change(struct ospf *ospf);
extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
uint32_t, struct in_addr,
struct in_addr);
@@ -301,7 +300,6 @@ extern int ospf_lsa_maxage_walker(struct thread *);
extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *, struct ospf_lsa *);
extern void ospf_external_lsa_refresh_default(struct ospf *);
-extern void ospf_default_originate_lsa_update(struct ospf *ospf);
extern void ospf_external_lsa_refresh_type(struct ospf *, uint8_t,
unsigned short, int);
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index f7c73fee33..ee27ec0942 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -616,8 +616,6 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
struct ospf_interface *oi = nbr->oi;
struct ospf_area *vl_area = NULL;
uint8_t old_state;
- int x;
- int force = 1;
/* Preserve old status. */
old_state = nbr->state;
@@ -664,32 +662,6 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
if (++vl_area->full_vls == 1)
ospf_schedule_abr_task(oi->ospf);
-
- /* kevinm: refresh any redistributions */
- for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) {
- struct list *red_list;
- struct listnode *node;
- struct ospf_redist *red;
-
- if (x == ZEBRA_ROUTE_OSPF6)
- continue;
-
- red_list = oi->ospf->redist[x];
- if (!red_list)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
- ospf_external_lsa_refresh_type(
- oi->ospf, x, red->instance,
- force);
- }
- /* XXX: Clearly some thing is wrong with refresh of
- * external LSAs
- * this added to hack around defaults not refreshing
- * after a timer
- * jump.
- */
- ospf_external_lsa_refresh_default(oi->ospf);
} else {
oi->full_nbrs--;
oi->area->full_nbrs--;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 98ddd6a79e..2564c6f330 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -8487,22 +8487,8 @@ DEFUN (no_ospf_default_information_originate,
"Pointer to route-map entries\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- struct prefix_ipv4 p;
- struct ospf_external *ext;
struct ospf_redist *red;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
-
- ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
-
- ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0);
- if (ext && EXTERNAL_INFO(ext)) {
- ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);
- ospf_external_del(ospf, DEFAULT_ROUTE, 0);
- }
-
red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0);
if (!red)
return CMD_SUCCESS;
@@ -8510,7 +8496,8 @@ DEFUN (no_ospf_default_information_originate,
ospf_routemap_unset(red);
ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
- return ospf_redistribute_default_unset(ospf);
+ return ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE,
+ 0, 0);
}
DEFUN (ospf_default_metric,
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 951402f47f..47438b985e 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -744,10 +744,10 @@ int ospf_redistribute_unset(struct ospf *ospf, int type,
int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
int mvalue)
{
- struct ospf_external *ext;
struct prefix_ipv4 p;
struct in_addr nexthop;
int cur_originate = ospf->default_originate;
+ const char *type_str = NULL;
nexthop.s_addr = 0;
p.family = AF_INET;
@@ -756,41 +756,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
ospf->default_originate = originate;
- ospf_external_add(ospf, DEFAULT_ROUTE, 0);
-
- if (cur_originate == DEFAULT_ORIGINATE_NONE) {
- /* First time configuration */
- if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
- metric_type(ospf, DEFAULT_ROUTE, 0),
- metric_value(ospf, DEFAULT_ROUTE, 0));
-
- if (ospf->router_id.s_addr == 0)
- ospf->external_origin |= (1 << DEFAULT_ROUTE);
- if ((originate == DEFAULT_ORIGINATE_ALWAYS)
- && (ospf->router_id.s_addr)) {
-
- /* always , so originate lsa even it doesn't
- * exist in RIB.
- */
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0,
- p, 0, nexthop, 0);
- ospf_external_lsa_refresh_default(ospf);
-
- } else if (originate == DEFAULT_ORIGINATE_ZEBRA) {
- /* Send msg to Zebra to validate default route
- * existance.
- */
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, AFI_IP,
- ospf->vrf_id);
- }
-
- ospf_asbr_status_update(ospf, ++ospf->redistribute);
- return CMD_SUCCESS;
-
-
- } else if (originate == cur_originate) {
+ if (cur_originate == originate) {
/* Refresh the lsa since metric might different */
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
zlog_debug(
@@ -800,67 +766,51 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
metric_value(ospf, DEFAULT_ROUTE, 0));
ospf_external_lsa_refresh_default(ospf);
-
- } else {
- /* "default-info originate always" configured now,
- * where "default-info originate" configured previoulsly.
- */
- if (originate == DEFAULT_ORIGINATE_ALWAYS) {
-
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- zclient, AFI_IP, ospf->vrf_id);
- /* here , ex-info should be added since ex-info might
- * have not updated earlier if def route is not exist.
- * If ex-iinfo ex-info already exist , it will return
- * smoothly.
- */
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0,
- p, 0, nexthop, 0);
- ospf_external_lsa_refresh_default(ospf);
-
- } else {
- /* "default-info originate" configured now,where
- * "default-info originate always" configured
- * previoulsy.
- */
-
- ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
-
- ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0);
- if (ext && EXTERNAL_INFO(ext))
- ospf_external_info_delete(ospf,
- DEFAULT_ROUTE, 0, p);
-
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- zclient, AFI_IP, ospf->vrf_id);
- }
+ return CMD_SUCCESS;
}
- return CMD_SUCCESS;
-}
-int ospf_redistribute_default_unset(struct ospf *ospf)
-{
- if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) {
- if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0))
- return CMD_SUCCESS;
+ switch (cur_originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
zclient, AFI_IP, ospf->vrf_id);
+ ospf->redistribute--;
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);
+ ospf_external_del(ospf, DEFAULT_ROUTE, 0);
+ ospf->redistribute--;
+ break;
}
- ospf->default_originate = DEFAULT_ORIGINATE_NONE;
+ switch (originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ type_str = "none";
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
+ type_str = "normal";
+ ospf->redistribute++;
+ zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
+ zclient, AFI_IP, ospf->vrf_id);
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ type_str = "always";
+ ospf->redistribute++;
+ ospf_external_add(ospf, DEFAULT_ROUTE, 0);
+ ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop,
+ 0);
+ break;
+ }
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("Redistribute[DEFAULT]: Stop");
-
- // Pending: how does the external_info cleanup work in this case?
-
- ospf_asbr_status_update(ospf, --ospf->redistribute);
-
- /* clean up maxage default originate external lsa */
- ospf_default_originate_lsa_update(ospf);
+ zlog_debug("Redistribute[DEFAULT]: %s Type[%d], Metric[%d]",
+ type_str,
+ metric_type(ospf, DEFAULT_ROUTE, 0),
+ metric_value(ospf, DEFAULT_ROUTE, 0));
+ ospf_external_lsa_refresh_default(ospf);
+ ospf_asbr_status_update(ospf, ospf->redistribute);
return CMD_SUCCESS;
}
@@ -1067,11 +1017,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
/* Nothing has changed, so nothing to do; return */
return 0;
}
- if (ospf->router_id.s_addr == 0)
- /* Set flags to generate AS-external-LSA originate event
- for each redistributed protocols later. */
- ospf->external_origin |= (1 << rt_type);
- else {
+ if (ospf->router_id.s_addr != 0) {
if (ei) {
if (is_prefix_default(&p))
ospf_external_lsa_refresh_default(ospf);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index a64ddbc3b7..b91a55f635 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -91,7 +91,6 @@ void ospf_router_id_update(struct ospf *ospf)
struct ospf_interface *oi;
struct interface *ifp;
struct listnode *node;
- int type;
if (!ospf->oi_running) {
if (IS_DEBUG_OSPF_EVENT)
@@ -135,24 +134,6 @@ void ospf_router_id_update(struct ospf *ospf)
ospf_nbr_self_reset(oi, router_id);
}
- /* If AS-external-LSA is queued, then flush those LSAs. */
- if (router_id_old.s_addr == 0 && ospf->external_origin) {
- /* Originate each redistributed external route. */
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
- if (ospf->external_origin & (1 << type))
- thread_add_event(
- master,
- ospf_external_lsa_originate_timer,
- ospf, type, NULL);
- /* Originate Deafult. */
- if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
- thread_add_event(master,
- ospf_default_originate_timer,
- ospf, 0, NULL);
-
- ospf->external_origin = 0;
- }
-
/* Flush (inline) all external LSAs based on the OSPF_LSA_SELF
* flag */
if (ospf->lsdb) {
@@ -196,20 +177,14 @@ void ospf_router_id_update(struct ospf *ospf)
}
}
- /* Originate each redistributed external route. */
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
- thread_add_event(master,
- ospf_external_lsa_originate_timer,
- ospf, type, NULL);
- thread_add_event(master, ospf_default_originate_timer, ospf, 0,
- NULL);
-
/* update router-lsa's for each area */
ospf_router_lsa_update(ospf);
/* update ospf_interface's */
FOR_ALL_INTERFACES (vrf, ifp)
ospf_if_update(ospf, ifp);
+
+ ospf_external_lsa_rid_change(ospf);
}
}
@@ -633,7 +608,7 @@ static void ospf_finish_final(struct ospf *ospf)
ospf_redist_del(ospf, i, red->instance);
}
}
- ospf_redistribute_default_unset(ospf);
+ ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
ospf_remove_vls_through_area(ospf, area);
@@ -702,7 +677,6 @@ static void ospf_finish_final(struct ospf *ospf)
/* Cancel all timers. */
OSPF_TIMER_OFF(ospf->t_read);
OSPF_TIMER_OFF(ospf->t_write);
- OSPF_TIMER_OFF(ospf->t_external_lsa);
OSPF_TIMER_OFF(ospf->t_spf_calc);
OSPF_TIMER_OFF(ospf->t_ase_calc);
OSPF_TIMER_OFF(ospf->t_maxage);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index cbea033b73..b31ad30375 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -202,7 +202,6 @@ struct ospf {
struct ospf_lsdb *lsdb;
/* Flags. */
- int external_origin; /* AS-external-LSA origin flag. */
int ase_calc; /* ASE calculation flag. */
struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */
@@ -233,7 +232,6 @@ struct ospf {
struct thread *t_distribute_update; /* Distirbute list update timer. */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
- struct thread *t_external_lsa; /* AS-external-LSA origin timer. */
struct thread
*t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
struct thread *t_sr_update; /* Segment Routing update timer */
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index a7552547e9..60cfb2e486 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -39,14 +39,15 @@
#endif
DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
- "sharp watch [vrf NAME$name] <nexthop$n|import$import> X:X::X:X$nhop [connected$connected]",
+ "sharp watch [vrf NAME$name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
"The NAME of the vrf\n"
"Watch for nexthop changes\n"
- "Watch for import check changes\n"
"The v6 nexthop to signal for watching\n"
+ "Watch for import check changes\n"
+ "The v6 prefix to signal for watching\n"
"Should the route be connected\n")
{
struct vrf *vrf;
@@ -62,16 +63,17 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
return CMD_WARNING;
}
- if (n)
- type_import = false;
- else
- type_import = true;
-
memset(&p, 0, sizeof(p));
- p.prefixlen = 128;
- memcpy(&p.u.prefix6, &nhop, 16);
- p.family = AF_INET6;
+ if (n) {
+ type_import = false;
+ p.prefixlen = 128;
+ memcpy(&p.u.prefix6, &nhop, 16);
+ p.family = AF_INET6;
+ } else {
+ type_import = true;
+ p = *(const struct prefix *)inhop;
+ }
sharp_nh_tracker_get(&p);
sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
@@ -81,14 +83,15 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
}
DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
- "sharp watch [vrf NAME$name] <nexthop$n|import$import> A.B.C.D$nhop [connected$connected]",
+ "sharp watch [vrf NAME$name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
"The NAME of the vrf\n"
"Watch for nexthop changes\n"
+ "The v4 address to signal for watching\n"
"Watch for import check changes\n"
- "The v4 nexthop to signal for watching\n"
+ "The v4 prefix for import check to watch\n"
"Should the route be connected\n")
{
struct vrf *vrf;
@@ -106,14 +109,16 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
memset(&p, 0, sizeof(p));
- if (n)
+ if (n) {
type_import = false;
- else
+ p.prefixlen = 32;
+ p.u.prefix4 = nhop;
+ p.family = AF_INET;
+ }
+ else {
type_import = true;
-
- p.prefixlen = 32;
- p.u.prefix4 = nhop;
- p.family = AF_INET;
+ p = *(const struct prefix *)inhop;
+ }
sharp_nh_tracker_get(&p);
sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index cd6f956580..6263f429ea 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -188,7 +188,7 @@ static void handle_repeated(bool installed)
sg.r.inst, sg.r.total_routes);
}
- if (installed) {
+ if (!installed) {
sg.r.installed_routes = 0;
sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
&sg.r.nhop_group,
diff --git a/staticd/static_nht.c b/staticd/static_nht.c
index 2aa0db59f1..1a2ddd7f05 100644
--- a/staticd/static_nht.c
+++ b/staticd/static_nht.c
@@ -23,18 +23,48 @@
#include "table.h"
#include "vrf.h"
#include "nexthop.h"
+#include "srcdest_table.h"
#include "static_vrf.h"
#include "static_routes.h"
#include "static_zebra.h"
#include "static_nht.h"
-static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
- afi_t afi, safi_t safi, struct vrf *vrf,
- vrf_id_t nh_vrf_id)
+static void static_nht_update_rn(struct route_node *rn,
+ struct prefix *nhp, uint32_t nh_num,
+ vrf_id_t nh_vrf_id, struct vrf *vrf,
+ safi_t safi)
{
- struct route_table *stable;
struct static_route *si;
+
+ for (si = rn->info; si; si = si->next) {
+ if (si->nh_vrf_id != nh_vrf_id)
+ continue;
+
+ if (si->type != STATIC_IPV4_GATEWAY
+ && si->type != STATIC_IPV4_GATEWAY_IFNAME
+ && si->type != STATIC_IPV6_GATEWAY
+ && si->type != STATIC_IPV6_GATEWAY_IFNAME)
+ continue;
+
+ if (nhp->family == AF_INET
+ && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr)
+ si->nh_valid = !!nh_num;
+
+ if (nhp->family == AF_INET6
+ && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0)
+ si->nh_valid = !!nh_num;
+
+ if (si->state == STATIC_START)
+ static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
+ }
+}
+
+static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
+ uint32_t nh_num, afi_t afi, safi_t safi,
+ struct vrf *vrf, vrf_id_t nh_vrf_id)
+{
+ struct route_table *stable;
struct static_vrf *svrf;
struct route_node *rn;
@@ -46,40 +76,129 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
if (!stable)
return;
+ if (sp) {
+ rn = srcdest_rnode_lookup(stable, sp, NULL);
+ if (rn) {
+ static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id,
+ vrf, safi);
+ route_unlock_node(rn);
+ }
+ return;
+ }
+
+ for (rn = route_top(stable); rn; rn = route_next(rn))
+ static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, vrf, safi);
+
+}
+
+void static_nht_update(struct prefix *sp, struct prefix *nhp,
+ uint32_t nh_num, afi_t afi, vrf_id_t nh_vrf_id)
+{
+
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST,
+ vrf, nh_vrf_id);
+ static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST,
+ vrf, nh_vrf_id);
+ }
+}
+
+static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
+ safi_t safi, struct vrf *vrf,
+ vrf_id_t nh_vrf_id)
+{
+ struct static_vrf *svrf;
+ struct route_table *stable;
+ struct static_route *si;
+ struct route_node *rn;
+
+ svrf = vrf->info;
+ if (!svrf)
+ return;
+
+ stable = static_vrf_static_table(afi, safi, svrf);
+ if (!stable)
+ return;
+
for (rn = route_top(stable); rn; rn = route_next(rn)) {
for (si = rn->info; si; si = si->next) {
if (si->nh_vrf_id != nh_vrf_id)
continue;
- if (si->type != STATIC_IPV4_GATEWAY
- && si->type != STATIC_IPV4_GATEWAY_IFNAME
- && si->type != STATIC_IPV6_GATEWAY
- && si->type != STATIC_IPV6_GATEWAY_IFNAME)
+ if (nhp->family == AF_INET
+ && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr)
continue;
- if (p->family == AF_INET
- && p->u.prefix4.s_addr == si->addr.ipv4.s_addr)
- si->nh_valid = !!nh_num;
-
- if (p->family == AF_INET6
- && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0)
- si->nh_valid = !!nh_num;
+ if (nhp->family == AF_INET6
+ && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0)
+ continue;
- static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
+ /*
+ * We've been told that a nexthop we depend
+ * on has changed in some manner, so reset
+ * the state machine to allow us to start
+ * over.
+ */
+ si->state = STATIC_START;
}
}
}
-void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi,
- vrf_id_t nh_vrf_id)
+void static_nht_reset_start(struct prefix *nhp, afi_t afi, vrf_id_t nh_vrf_id)
{
-
struct vrf *vrf;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- static_nht_update_safi(p, nh_num, afi, SAFI_UNICAST,
- vrf, nh_vrf_id);
- static_nht_update_safi(p, nh_num, afi, SAFI_MULTICAST,
- vrf, nh_vrf_id);
+ static_nht_reset_start_safi(nhp, afi, SAFI_UNICAST,
+ vrf, nh_vrf_id);
+ static_nht_reset_start_safi(nhp, afi, SAFI_MULTICAST,
+ vrf, nh_vrf_id);
}
}
+
+static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
+ safi_t safi, struct vrf *vrf,
+ enum static_install_states state)
+{
+ struct static_vrf *svrf;
+ struct route_table *stable;
+ struct static_route *si;
+ struct route_node *rn;
+
+ svrf = vrf->info;
+ if (!svrf)
+ return;
+
+ stable = static_vrf_static_table(afi, safi, svrf);
+ if (!stable)
+ return;
+
+ rn = srcdest_rnode_lookup(stable, sp, NULL);
+ if (!rn)
+ return;
+
+ for (si = rn->info; si; si = si->next)
+ si->state = state;
+
+ route_unlock_node(rn);
+}
+
+void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
+ enum static_install_states state)
+{
+ struct vrf *vrf;
+
+ afi_t afi = AFI_IP;
+
+ if (sp->family == AF_INET6)
+ afi = AFI_IP6;
+
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf || !vrf->info)
+ return;
+
+ static_nht_mark_state_safi(sp, afi, SAFI_UNICAST, vrf, state);
+ static_nht_mark_state_safi(sp, afi, SAFI_MULTICAST, vrf, state);
+}
diff --git a/staticd/static_nht.h b/staticd/static_nht.h
index f273c71bba..18bb9e39ca 100644
--- a/staticd/static_nht.h
+++ b/staticd/static_nht.h
@@ -20,6 +20,31 @@
#ifndef __STATIC_NHT_H__
#define __STATIC_NHT_H__
-extern void static_nht_update(struct prefix *p, uint32_t nh_num,
- afi_t afi, vrf_id_t vrf_id);
+/*
+ * When we get notification that nexthop tracking has an answer for
+ * us call this function to find the nexthop we are tracking so it
+ * can be installed or removed.
+ *
+ * sp -> The route we are looking at. If NULL then look at all
+ * routes.
+ * nhp -> The nexthop that is being tracked.
+ * nh_num -> number of valid nexthops.
+ * afi -> The afi we are working in.
+ * vrf_id -> The vrf the nexthop is in.
+ */
+extern void static_nht_update(struct prefix *sp, struct prefix *nhp,
+ uint32_t nh_num, afi_t afi, vrf_id_t vrf_id);
+
+/*
+ * For the given tracked nexthop, nhp, mark all routes that use
+ * this route as in starting state again.
+ */
+extern void static_nht_reset_start(struct prefix *nhp, afi_t afi,
+ vrf_id_t nh_vrf_id);
+
+/*
+ * For the given prefix, sp, mark it as in a particular state
+ */
+extern void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
+ enum static_install_states state);
#endif
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index 5f9ecad694..b2c61bcbab 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -39,7 +39,7 @@ static void static_install_route(struct route_node *rn,
struct static_route *si;
for (si = rn->info; si; si = si->next)
- static_zebra_nht_register(si, true);
+ static_zebra_nht_register(rn, si, true);
si = rn->info;
if (si)
@@ -183,7 +183,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
/* check whether interface exists in system & install if it does */
if (!ifname)
- static_install_route(rn, si, safi);
+ static_zebra_nht_register(rn, si, true);
else {
struct interface *ifp;
@@ -242,7 +242,7 @@ int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
return 0;
}
- static_zebra_nht_register(si, false);
+ static_zebra_nht_register(rn, si, false);
/* Unlink static route from linked list. */
if (si->prev)
diff --git a/staticd/static_routes.h b/staticd/static_routes.h
index 6036bfe396..6414947b16 100644
--- a/staticd/static_routes.h
+++ b/staticd/static_routes.h
@@ -44,6 +44,26 @@ typedef enum {
STATIC_IPV6_GATEWAY_IFNAME,
} static_types;
+/*
+ * Route Creation gives us:
+ * START -> Initial State, only exit is when we send the route to
+ * zebra for installation
+ * When we send the route to Zebra move to SENT_TO_ZEBRA
+ * SENT_TO_ZEBRA -> A way to notice that we've sent the route to zebra
+ * But have not received a response on it's status yet
+ * After The response from zebra we move to INSTALLED or FAILED
+ * INSTALLED -> Route was accepted
+ * FAILED -> Route was rejected
+ * When we receive notification about a nexthop that a route uses
+ * We move the route back to START and initiate the process again.
+ */
+enum static_install_states {
+ STATIC_START,
+ STATIC_SENT_TO_ZEBRA,
+ STATIC_INSTALLED,
+ STATIC_NOT_INSTALLED,
+};
+
/* Static route information. */
struct static_route {
/* For linked list. */
@@ -55,6 +75,12 @@ struct static_route {
vrf_id_t nh_vrf_id;
char nh_vrfname[VRF_NAMSIZ + 1];
+ /*
+ * States that we walk the route through
+ * To know where we are.
+ */
+ enum static_install_states state;
+
/* Administrative distance. */
uint8_t distance;
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index c6da00418b..13c04259d7 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -43,6 +43,8 @@
#include "static_nht.h"
#include "static_vty.h"
+bool debug;
+
/* Zebra structure to hold current status. */
struct zclient *zclient;
static struct hash *static_nht_hash;
@@ -154,18 +156,23 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
switch (note) {
case ZAPI_ROUTE_FAIL_INSTALL:
+ static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
zlog_warn("%s: Route %s failed to install for table: %u",
__PRETTY_FUNCTION__, buf, table_id);
break;
case ZAPI_ROUTE_BETTER_ADMIN_WON:
+ static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
zlog_warn("%s: Route %s over-ridden by better route for table: %u",
__PRETTY_FUNCTION__, buf, table_id);
break;
case ZAPI_ROUTE_INSTALLED:
+ static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
break;
case ZAPI_ROUTE_REMOVED:
+ static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
break;
case ZAPI_ROUTE_REMOVE_FAIL:
+ static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
zlog_warn("%s: Route %s failure to remove for table: %u",
__PRETTY_FUNCTION__, buf, table_id);
break;
@@ -210,7 +217,8 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
if (nhtd) {
nhtd->nh_num = nhr.nexthop_num;
- static_nht_update(&nhr.prefix, nhr.nexthop_num, afi,
+ static_nht_reset_start(&nhr.prefix, afi, nhtd->nh_vrf_id);
+ static_nht_update(NULL, &nhr.prefix, nhr.nexthop_num, afi,
nhtd->nh_vrf_id);
} else
zlog_err("No nhtd?");
@@ -267,7 +275,8 @@ static void static_nht_hash_free(void *data)
XFREE(MTYPE_TMP, nhtd);
}
-void static_zebra_nht_register(struct static_route *si, bool reg)
+void static_zebra_nht_register(struct route_node *rn,
+ struct static_route *si, bool reg)
{
struct static_nht_data *nhtd, lookup;
uint32_t cmd;
@@ -315,8 +324,11 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
static_nht_hash_alloc);
nhtd->refcount++;
- if (nhtd->refcount > 1) {
- static_nht_update(nhtd->nh, nhtd->nh_num,
+ if (debug)
+ zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p,
+ rn, nhtd->nh_num);
+ if (nhtd->refcount > 1 && nhtd->nh_num) {
+ static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num,
afi, si->nh_vrf_id);
return;
}
@@ -389,6 +401,8 @@ extern void static_zebra_route_add(struct route_node *rn,
api_nh->vrf_id = si->nh_vrf_id;
api_nh->onlink = si->onlink;
+ si->state = STATIC_SENT_TO_ZEBRA;
+
switch (si->type) {
case STATIC_IFNAME:
if (si->ifindex == IFINDEX_INTERNAL)
diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h
index a82eb162e1..15f5410b81 100644
--- a/staticd/static_zebra.h
+++ b/staticd/static_zebra.h
@@ -21,7 +21,8 @@
extern struct thread_master *master;
-extern void static_zebra_nht_register(struct static_route *si, bool reg);
+extern void static_zebra_nht_register(struct route_node *rn,
+ struct static_route *si, bool reg);
extern void static_zebra_route_add(struct route_node *rn,
struct static_route *si_changed,
diff --git a/tests/lib/cli/test_commands.c b/tests/lib/cli/test_commands.c
index ba46bdcea9..bbdc8b238d 100644
--- a/tests/lib/cli/test_commands.c
+++ b/tests/lib/cli/test_commands.c
@@ -243,7 +243,8 @@ static void test_run(struct prng *prng, struct vty *vty, const char *cmd,
(test_buf[0] != '\0') ? ", " : "",
test_buf);
- if (isspace((int)test_str[strlen(test_str) - 1])) {
+ if (isspace((unsigned char)test_str[
+ strlen(test_str) - 1])) {
vector_set(vline, NULL);
appended_null = 1;
}
diff --git a/tests/lib/cxxcompat.c b/tests/lib/cxxcompat.c
index 6624de7386..88126e84bc 100644
--- a/tests/lib/cxxcompat.c
+++ b/tests/lib/cxxcompat.c
@@ -55,7 +55,6 @@
#include "lib/libospf.h"
#include "lib/linklist.h"
#include "lib/log.h"
-#include "lib/logicalrouter.h"
#include "lib/md5.h"
#include "lib/memory.h"
#include "lib/memory_vty.h"
@@ -73,7 +72,6 @@
#include "lib/openbsd-tree.h"
#include "lib/pbr.h"
#include "lib/plist.h"
-#include "lib/pqueue.h"
#include "lib/prefix.h"
#include "lib/privs.h"
#include "lib/ptm_lib.h"
diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c
index 43e79ba9d0..cbf9b05546 100644
--- a/tests/lib/test_timer_correctness.c
+++ b/tests/lib/test_timer_correctness.c
@@ -28,7 +28,6 @@
#include <unistd.h>
#include "memory.h"
-#include "pqueue.h"
#include "prng.h"
#include "thread.h"
diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c
index d5f4badc85..2960e0d81e 100644
--- a/tests/lib/test_timer_performance.c
+++ b/tests/lib/test_timer_performance.c
@@ -28,7 +28,6 @@
#include <unistd.h>
#include "thread.h"
-#include "pqueue.h"
#include "prng.h"
#define SCHEDULE_TIMERS 1000000
diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h
index b288f0bd8e..7ff210cae3 100644
--- a/tests/lib/test_typelist.h
+++ b/tests/lib/test_typelist.h
@@ -209,7 +209,7 @@ static void concat(test_, TYPE)(void)
assert(list_add(&head, &dummy) == &itm[j]);
else {
assert(list_add(&head, &dummy) == NULL);
- list_del(&head, &dummy);
+ assert(list_del(&head, &dummy) != NULL);
}
}
ts_hashx("add-dup", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
@@ -255,7 +255,7 @@ static void concat(test_, TYPE)(void)
list_first(&head) == &dummy);
} else if (list_next(&head, &dummy))
assert(list_next(&head, &dummy)->val > j);
- list_del(&head, &dummy);
+ assert(list_del(&head, &dummy) != NULL);
}
ts_hash("add-dup+find_{lt,gteq}", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
#endif
@@ -295,7 +295,7 @@ static void concat(test_, TYPE)(void)
(void)prng_rand(prng);
j = prng_rand(prng) % NITEM;
if (itm[j].scratchpad == 1) {
- list_del(&head, &itm[j]);
+ assert(list_del(&head, &itm[j]) != NULL);
itm[j].scratchpad = 0;
l++;
}
@@ -307,7 +307,7 @@ static void concat(test_, TYPE)(void)
assert(item->scratchpad != 0);
if (item->val & 1) {
- list_del(&head, item);
+ assert(list_del(&head, item) != NULL);
item->scratchpad = 0;
l++;
}
@@ -333,7 +333,7 @@ static void concat(test_, TYPE)(void)
for (i = 0; i < NITEM / 2; i++) {
j = prng_rand(prng) % NITEM;
if (itm[j].scratchpad == 1) {
- list_del(&head, &itm[j]);
+ assert(list_del(&head, &itm[j]) != NULL);
itm[j].scratchpad = 0;
k--;
}
@@ -371,7 +371,7 @@ static void concat(test_, TYPE)(void)
for (i = 0; i < NITEM / 2; i++) {
j = prng_rand(prng) % NITEM;
if (itm[j].scratchpad == 1) {
- list_del(&head, &itm[j]);
+ assert(list_del(&head, &itm[j]) != NULL);
itm[j].scratchpad = 0;
k--;
}
@@ -424,7 +424,7 @@ static void concat(test_, TYPE)(void)
item = &itm[j];
if (item->scratchpad == 0)
continue;
- list_del(&head, item);
+ assert(list_del(&head, item) != NULL);
}
item->scratchpad = 0;
k--;
@@ -469,7 +469,7 @@ static void concat(test_, TYPE)(void)
item = &itm[j];
if (item->scratchpad == 0)
continue;
- list_del(&head, item);
+ assert(list_del(&head, item) != NULL);
}
item->scratchpad = 0;
k--;
diff --git a/tests/topotests/bgp_comm-list_delete/__init__.py b/tests/topotests/bgp_comm-list_delete/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/__init__.py
diff --git a/tests/topotests/bgp_comm-list_delete/r1/bgpd.conf b/tests/topotests/bgp_comm-list_delete/r1/bgpd.conf
new file mode 100644
index 0000000000..6e1273f464
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/r1/bgpd.conf
@@ -0,0 +1,9 @@
+router bgp 65000
+ neighbor 192.168.255.2 remote-as 65001
+ address-family ipv4 unicast
+ redistribute connected route-map r2-out
+ exit-address-family
+!
+route-map r2-out permit 10
+ set community 111:111 222:222 333:333 444:444
+!
diff --git a/tests/topotests/bgp_comm-list_delete/r1/zebra.conf b/tests/topotests/bgp_comm-list_delete/r1/zebra.conf
new file mode 100644
index 0000000000..0a283c06d5
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/r1/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_comm-list_delete/r2/bgpd.conf b/tests/topotests/bgp_comm-list_delete/r2/bgpd.conf
new file mode 100644
index 0000000000..3d354d56b1
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/r2/bgpd.conf
@@ -0,0 +1,11 @@
+router bgp 65001
+ neighbor 192.168.255.1 remote-as 65000
+ address-family ipv4
+ neighbor 192.168.255.1 route-map r1-in in
+ exit-address-family
+!
+bgp community-list standard r1 permit 333:333
+!
+route-map r1-in permit 10
+ set comm-list r1 delete
+!
diff --git a/tests/topotests/bgp_comm-list_delete/r2/zebra.conf b/tests/topotests/bgp_comm-list_delete/r2/zebra.conf
new file mode 100644
index 0000000000..606c17bec9
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/r2/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
new file mode 100644
index 0000000000..de6c35ba8f
--- /dev/null
+++ b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+#
+# bgp_comm-list_delete.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or 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 NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF 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.
+#
+
+"""
+bgp_comm-list_delete.py:
+
+Test if works the following commands:
+route-map test permit 10
+ set comm-list <arg> delete
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 3):
+ tgen.add_router('r{}'.format(routern))
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.iteritems(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+ )
+
+ tgen.start_router()
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+def test_bgp_maximum_prefix_invalid():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_converge(router):
+ while True:
+ output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ if output['192.168.255.1']['bgpState'] == 'Established':
+ if output['192.168.255.1']['addressFamilyInfo']['IPv4 Unicast']['acceptedPrefixCounter'] == 2:
+ return True
+
+ def _bgp_comm_list_delete(router):
+ output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp 172.16.255.254/32 json"))
+ if '333:333' in output['paths'][0]['community']['list']:
+ return False
+ return True
+
+ if _bgp_converge('r2'):
+ assert _bgp_comm_list_delete('r2') == True
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 13f8824976..2613f45f1c 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -932,7 +932,7 @@ def clear_bgp_and_verify(tgen, topo, router):
# Peer up time dictionary
peer_uptime_before_clear_bgp[bgp_neighbor] = \
- ipv4_data[neighbor_ip]["peerUptime"]
+ ipv4_data[neighbor_ip]["peerUptimeEstablishedEpoch"]
else:
ipv6_data = show_bgp_json["ipv6Unicast"][
"peers"]
@@ -940,7 +940,7 @@ def clear_bgp_and_verify(tgen, topo, router):
# Peer up time dictionary
peer_uptime_before_clear_bgp[bgp_neighbor] = \
- ipv6_data[neighbor_ip]["peerUptime"]
+ ipv6_data[neighbor_ip]["peerUptimeEstablishedEpoch"]
if nh_state == "Established":
no_of_peer += 1
@@ -953,6 +953,7 @@ def clear_bgp_and_verify(tgen, topo, router):
logger.warning("BGP is not yet Converged for router %s "
"before bgp clear", router)
+ logger.info(peer_uptime_before_clear_bgp)
# Clearing BGP
logger.info("Clearing BGP neighborship for router %s..", router)
for addr_type in bgp_addr_type.keys():
@@ -1010,14 +1011,14 @@ def clear_bgp_and_verify(tgen, topo, router):
"peers"]
nh_state = ipv4_data[neighbor_ip]["state"]
peer_uptime_after_clear_bgp[bgp_neighbor] = \
- ipv4_data[neighbor_ip]["peerUptime"]
+ ipv4_data[neighbor_ip]["peerUptimeEstablishedEpoch"]
else:
ipv6_data = show_bgp_json["ipv6Unicast"][
"peers"]
nh_state = ipv6_data[neighbor_ip]["state"]
# Peer up time dictionary
peer_uptime_after_clear_bgp[bgp_neighbor] = \
- ipv6_data[neighbor_ip]["peerUptime"]
+ ipv6_data[neighbor_ip]["peerUptimeEstablishedEpoch"]
if nh_state == "Established":
no_of_peer += 1
@@ -1030,7 +1031,8 @@ def clear_bgp_and_verify(tgen, topo, router):
logger.warning("BGP is not yet Converged for router %s after"
" bgp clear", router)
- # Compariung peerUptime dictionaries
+ logger.info(peer_uptime_after_clear_bgp)
+ # Comparing peerUptimeEstablishedEpoch dictionaries
if peer_uptime_before_clear_bgp != peer_uptime_after_clear_bgp:
logger.info("BGP neighborship is reset after clear BGP on router %s",
router)
diff --git a/tools/coccinelle/ctype_cast.cocci b/tools/coccinelle/ctype_cast.cocci
new file mode 100644
index 0000000000..b0b00959da
--- /dev/null
+++ b/tools/coccinelle/ctype_cast.cocci
@@ -0,0 +1,11 @@
+
+@@
+identifier func =~ "^(to|is)(alnum|cntrl|print|xdigit|alpha|digit|punct|ascii|graph|space|blank|lower|upper)$";
+expression e;
+@@
+
+ func(
+- (int)
++ (unsigned char)
+ e)
+
diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c
index f6c757f5d7..14f648e8da 100644
--- a/tools/gen_northbound_callbacks.c
+++ b/tools/gen_northbound_callbacks.c
@@ -28,7 +28,8 @@
static void __attribute__((noreturn)) usage(int status)
{
- fprintf(stderr, "usage: gen_northbound_callbacks [-h] MODULE\n");
+ extern const char *__progname;
+ fprintf(stderr, "usage: %s [-h] [-p path] MODULE\n", __progname);
exit(status);
}
@@ -152,6 +153,36 @@ static void generate_callback_name(struct lys_node *snode,
replace_hyphens_by_underscores(buffer);
}
+static void generate_callback(const struct nb_callback_info *ncinfo,
+ const char *cb_name)
+{
+ printf("static %s%s(%s)\n{\n",
+ ncinfo->return_type, cb_name, ncinfo->arguments);
+
+ switch (ncinfo->operation) {
+ case NB_OP_CREATE:
+ case NB_OP_MODIFY:
+ case NB_OP_DESTROY:
+ case NB_OP_MOVE:
+ printf("\tswitch (event) {\n"
+ "\tcase NB_EV_VALIDATE:\n"
+ "\tcase NB_EV_PREPARE:\n"
+ "\tcase NB_EV_ABORT:\n"
+ "\tcase NB_EV_APPLY:\n"
+ "\t\t/* TODO: implement me. */\n"
+ "\t\tbreak;\n"
+ "\t}\n\n"
+ );
+ break;
+
+ default:
+ printf("\t/* TODO: implement me. */\n");
+ break;
+ }
+
+ printf("\treturn %s;\n}\n\n", ncinfo->return_value);
+}
+
static int generate_callbacks(const struct lys_node *snode, void *arg)
{
bool first = true;
@@ -191,14 +222,7 @@ static int generate_callbacks(const struct lys_node *snode, void *arg)
generate_callback_name((struct lys_node *)snode, cb->operation,
cb_name, sizeof(cb_name));
- printf("static %s%s(%s)\n"
- "{\n"
- "\t/* TODO: implement me. */\n"
- "\treturn %s;\n"
- "}\n\n",
- nb_callbacks[cb->operation].return_type, cb_name,
- nb_callbacks[cb->operation].arguments,
- nb_callbacks[cb->operation].return_value);
+ generate_callback(cb, cb_name);
}
return YANG_ITER_CONTINUE;
@@ -237,32 +261,52 @@ static int generate_nb_nodes(const struct lys_node *snode, void *arg)
printf("\t\t{\n"
"\t\t\t.xpath = \"%s\",\n",
xpath);
+ printf("\t\t\t.cbs = {\n");
first = false;
}
generate_callback_name((struct lys_node *)snode, cb->operation,
cb_name, sizeof(cb_name));
- printf("\t\t\t.cbs.%s = %s,\n",
- nb_operation_name(cb->operation), cb_name);
+ printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb->operation),
+ cb_name);
}
- if (!first)
+ if (!first) {
+ printf("\t\t\t}\n");
printf("\t\t},\n");
+ }
return YANG_ITER_CONTINUE;
}
int main(int argc, char *argv[])
{
+ const char *search_path = NULL;
struct yang_module *module;
char module_name_underscores[64];
+ struct stat st;
int opt;
- while ((opt = getopt(argc, argv, "h")) != -1) {
+ while ((opt = getopt(argc, argv, "hp:")) != -1) {
switch (opt) {
case 'h':
usage(EXIT_SUCCESS);
/* NOTREACHED */
+ case 'p':
+ if (stat(optarg, &st) == -1) {
+ fprintf(stderr,
+ "error: invalid search path '%s': %s\n",
+ optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (S_ISDIR(st.st_mode) == 0) {
+ fprintf(stderr,
+ "error: search path is not directory");
+ exit(EXIT_FAILURE);
+ }
+
+ search_path = optarg;
+ break;
default:
usage(EXIT_FAILURE);
/* NOTREACHED */
@@ -275,6 +319,9 @@ int main(int argc, char *argv[])
yang_init();
+ if (search_path)
+ ly_ctx_set_searchdir(ly_native_ctx, search_path);
+
/* Load all FRR native models to ensure all augmentations are loaded. */
yang_module_load_all();
module = yang_module_find(argv[0]);
diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c
index 5903f8732f..c75306a959 100644
--- a/tools/start-stop-daemon.c
+++ b/tools/start-stop-daemon.c
@@ -401,7 +401,7 @@ static void parse_schedule_item(const char *string, struct schedule_item *item)
if (!strcmp(string, "forever")) {
item->type = sched_forever;
- } else if (isdigit((int)string[0])) {
+ } else if (isdigit((unsigned char)string[0])) {
item->type = sched_timeout;
if (parse_integer(string, &item->value) != 0)
badusage("invalid timeout value in schedule");
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index 5213b27d32..951ad3f58f 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -196,9 +196,20 @@ static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
{
struct interface *p;
- if (!mvl_ifp || !mvl_ifp->link_ifindex
- || !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ if (!mvl_ifp || mvl_ifp->link_ifindex == 0
+ || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) {
+ if (mvl_ifp && mvl_ifp->link_ifindex == 0)
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has no parent ifindex; disregarding",
+ mvl_ifp->name);
+ if (mvl_ifp && !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has a non-VRRP MAC; disregarding",
+ mvl_ifp->name);
return NULL;
+ }
p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
uint8_t vrid = mvl_ifp->hw_addr[5];
@@ -2028,9 +2039,19 @@ static void vrrp_bind_pending(struct interface *mvl_ifp)
{
struct vrrp_vrouter *vr;
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Searching for instances that could use interface %s",
+ mvl_ifp->name);
+
vr = vrrp_lookup_by_if_mvl(mvl_ifp);
if (vr) {
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "<-- This instance can probably use interface %s",
+ vr->vrid, mvl_ifp->name);
+
if (mvl_ifp->hw_addr[4] == 0x01 && !vr->v4->mvl_ifp)
vrrp_attach_interface(vr->v4);
else if (mvl_ifp->hw_addr[4] == 0x02 && !vr->v6->mvl_ifp)
@@ -2112,9 +2133,13 @@ void vrrp_if_down(struct interface *ifp)
struct listnode *ln;
struct list *vrs;
+ vrrp_bind_pending(ifp);
+
vrs = vrrp_lookup_by_if_any(ifp);
for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
+ vrrp_check_start(vr);
+
if (vr->ifp == ifp || vr->v4->mvl_ifp == ifp
|| vr->v6->mvl_ifp == ifp) {
DEBUGD(&vrrp_dbg_auto,
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index dbfcbe945e..72b77c1313 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -38,9 +38,11 @@ static void vrrp_zebra_debug_if_state(struct interface *ifp, vrf_id_t vrf_id,
const char *func)
{
DEBUGD(&vrrp_dbg_zebra,
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- func, ifp->name, ifp->ifindex, vrf_id, (long)ifp->flags,
- ifp->metric, ifp->mtu, if_is_operative(ifp));
+ "%s: %s index %d(%u) parent %d mac %02x:%02x:%02x:%02x:%02x:%02x flags %ld metric %d mtu %d operative %d",
+ func, ifp->name, vrf_id, ifp->link_ifindex, ifp->ifindex,
+ ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2],
+ ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5],
+ (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp));
}
static void vrrp_zebra_debug_if_dump_address(struct interface *ifp,
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index 4dc34d10ef..d0b0c701a7 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -96,18 +96,12 @@ sub scan_file {
elsif ($file =~ /lib\/if\.c$/) {
$protocol = "VTYSH_INTERFACE";
}
- elsif ($file =~ /lib\/logicalrouter\.c$/) {
- $protocol = "VTYSH_ALL";
- }
elsif ($file =~ /lib\/filter\.c$/) {
$protocol = "VTYSH_ALL";
}
elsif ($file =~ /lib\/agentx\.c$/) {
$protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
}
- elsif ($file =~ /lib\/ns\.c$/) {
- $protocol = "VTYSH_ZEBRA";
- }
elsif ($file =~ /lib\/nexthop_group\.c$/) {
$protocol = "VTYSH_PBRD | VTYSH_SHARPD";
}
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 82dbe06a9c..cec5675e01 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -668,11 +668,11 @@ static char *trim(char *s)
return s;
end = s + size - 1;
- while (end >= s && isspace((int)*end))
+ while (end >= s && isspace((unsigned char)*end))
end--;
*(end + 1) = '\0';
- while (*s && isspace((int)*s))
+ while (*s && isspace((unsigned char)*s))
s++;
return s;
@@ -979,7 +979,7 @@ static int vtysh_process_questionmark(const char *input, int input_len)
if (vline == NULL) {
vline = vector_init(1);
vector_set(vline, NULL);
- } else if (input_len && isspace((int)input[input_len - 1]))
+ } else if (input_len && isspace((unsigned char)input[input_len - 1]))
vector_set(vline, NULL);
describe = cmd_describe_command(vline, vty, &ret);
@@ -1127,7 +1127,8 @@ static char *command_generator(const char *text, int state)
if (vline == NULL)
return NULL;
- if (rl_end && isspace((int)rl_line_buffer[rl_end - 1]))
+ if (rl_end &&
+ isspace((unsigned char)rl_line_buffer[rl_end - 1]))
vector_set(vline, NULL);
matched = cmd_complete_command(vline, vty, &complete_status);
@@ -1188,10 +1189,6 @@ static struct cmd_node pw_node = {
PW_NODE, "%s(config-pw)# ",
};
-static struct cmd_node logicalrouter_node = {
- LOGICALROUTER_NODE, "%s(config-logical-router)# ",
-};
-
static struct cmd_node vrf_node = {
VRF_NODE, "%s(config-vrf)# ",
};
@@ -1798,7 +1795,6 @@ static int vtysh_exit(struct vty *vty)
break;
case INTERFACE_NODE:
case PW_NODE:
- case LOGICALROUTER_NODE:
case VRF_NODE:
case NH_GROUP_NODE:
case ZEBRA_NODE:
@@ -2128,24 +2124,6 @@ DEFUNSH(VTYSH_ZEBRA, vtysh_pseudowire, vtysh_pseudowire_cmd,
return CMD_SUCCESS;
}
-DEFUNSH(VTYSH_ZEBRA, vtysh_logicalrouter, vtysh_logicalrouter_cmd,
- "logical-router (1-65535) ns NAME",
- "Enable a logical-router\n"
- "Specify the logical-router indentifier\n"
- "The Name Space\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-{
- vty->node = LOGICALROUTER_NODE;
- return CMD_SUCCESS;
-}
-
-DEFSH(VTYSH_ZEBRA, vtysh_no_logicalrouter_cmd,
- "no logical-router (1-65535) ns NAME", NO_STR
- "Enable a Logical-Router\n"
- "Specify the Logical-Router identifier\n"
- "The Name Space\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-
DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
"nexthop-group NHGNAME",
"Nexthop Group configuration\n"
@@ -2180,20 +2158,6 @@ DEFSH(VTYSH_ZEBRA, vtysh_no_vrf_netns_cmd,
"Detach VRF from a Namespace\n"
"The file name in " NS_RUN_DIR ", or a full pathname\n")
-DEFUNSH(VTYSH_NS, vtysh_exit_logicalrouter,
- vtysh_exit_logicalrouter_cmd, "exit",
- "Exit current mode and down to previous mode\n")
-{
- return vtysh_exit(vty);
-}
-
-DEFUNSH(VTYSH_NS, vtysh_quit_logicalrouter,
- vtysh_quit_logicalrouter_cmd, "quit",
- "Exit current mode and down to previous mode\n")
-{
- return vtysh_exit_logicalrouter(self, vty, argc, argv);
-}
-
DEFUNSH(VTYSH_VRF, vtysh_exit_vrf, vtysh_exit_vrf_cmd, "exit",
"Exit current mode and down to previous mode\n")
{
@@ -3609,7 +3573,6 @@ void vtysh_init_vty(void)
install_node(&interface_node, NULL);
install_node(&pw_node, NULL);
install_node(&link_params_node, NULL);
- install_node(&logicalrouter_node, NULL);
install_node(&vrf_node, NULL);
install_node(&nh_group_node, NULL);
install_node(&rmap_node, NULL);
@@ -3819,13 +3782,6 @@ void vtysh_init_vty(void)
install_element(PW_NODE, &vtysh_exit_interface_cmd);
install_element(PW_NODE, &vtysh_quit_interface_cmd);
- install_element(LOGICALROUTER_NODE, &vtysh_end_all_cmd);
-
- install_element(CONFIG_NODE, &vtysh_logicalrouter_cmd);
- install_element(CONFIG_NODE, &vtysh_no_logicalrouter_cmd);
- install_element(LOGICALROUTER_NODE, &vtysh_exit_logicalrouter_cmd);
- install_element(LOGICALROUTER_NODE, &vtysh_quit_logicalrouter_cmd);
-
install_element(CONFIG_NODE, &vtysh_nexthop_group_cmd);
install_element(NH_GROUP_NODE, &vtysh_end_all_cmd);
install_element(NH_GROUP_NODE, &vtysh_exit_nexthop_group_cmd);
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 3b0b570a56..b16761b41a 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -54,7 +54,6 @@ DECLARE_MGROUP(MVTYSH)
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD|VTYSH_VRRPD
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_SHARPD|VTYSH_FABRICD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD|VTYSH_VRRPD
-#define VTYSH_NS VTYSH_ZEBRA
#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_STATICD
#define VTYSH_KEYS VTYSH_RIPD|VTYSH_EIGRPD
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 1e45e6f972..3ec2eb239d 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -23,6 +23,7 @@
#include "command.h"
#include "linklist.h"
#include "memory.h"
+#include "typesafe.h"
#include "vtysh/vtysh.h"
#include "vtysh/vtysh_user.h"
@@ -33,6 +34,8 @@ DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG_LINE, "Vtysh configuration line")
vector configvec;
+PREDECL_RBTREE_UNIQ(config_master);
+
struct config {
/* Configuration node name. */
char *name;
@@ -45,6 +48,9 @@ struct config {
/* Index of this config. */
uint32_t index;
+
+ /* Node entry for the typed Red-black tree */
+ struct config_master_item rbt_item;
};
struct list *config_top;
@@ -66,7 +72,7 @@ static struct config *config_new(void)
return config;
}
-static int config_cmp(struct config *c1, struct config *c2)
+static int config_cmp(const struct config *c1, const struct config *c2)
{
return strcmp(c1->name, c2->name);
}
@@ -78,28 +84,23 @@ static void config_del(struct config *config)
XFREE(MTYPE_VTYSH_CONFIG, config);
}
+DECLARE_RBTREE_UNIQ(config_master, struct config, rbt_item, config_cmp)
+
static struct config *config_get(int index, const char *line)
{
struct config *config;
- struct config *config_loop;
- struct list *master;
- struct listnode *node, *nnode;
-
- config = config_loop = NULL;
+ struct config_master_head *master;
master = vector_lookup_ensure(configvec, index);
if (!master) {
- master = list_new();
- master->del = (void (*)(void *))config_del;
- master->cmp = (int (*)(void *, void *))config_cmp;
+ master = XMALLOC(MTYPE_VTYSH_CONFIG, sizeof(struct config_master_head));
+ config_master_init(master);
vector_set_index(configvec, index, master);
}
- for (ALL_LIST_ELEMENTS(master, node, nnode, config_loop)) {
- if (strcmp(config_loop->name, line) == 0)
- config = config_loop;
- }
+ const struct config config_ref = { .name = (char *)line };
+ config = config_master_find(master, &config_ref);
if (!config) {
config = config_new();
@@ -108,7 +109,7 @@ static struct config *config_get(int index, const char *line)
config->line->cmp = (int (*)(void *, void *))line_cmp;
config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
config->index = index;
- listnode_add(master, config);
+ config_master_add(master, config);
}
return config;
}
@@ -263,7 +264,6 @@ void vtysh_config_parse_line(void *arg, const char *line)
config_add_line(config->line, line);
} else if (config->index == RMAP_NODE
|| config->index == INTERFACE_NODE
- || config->index == LOGICALROUTER_NODE
|| config->index == VTY_NODE
|| config->index == VRF_NODE
|| config->index == NH_GROUP_NODE)
@@ -278,8 +278,6 @@ void vtysh_config_parse_line(void *arg, const char *line)
config = config_get(INTERFACE_NODE, line);
else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
config = config_get(PW_NODE, line);
- else if (strncmp(line, "logical-router", strlen("logical-router")) == 0)
- config = config_get(LOGICALROUTER_NODE, line);
else if (strncmp(line, "vrf", strlen("vrf")) == 0)
config = config_get(VRF_NODE, line);
else if (strncmp(line, "nexthop-group", strlen("nexthop-group"))
@@ -435,7 +433,7 @@ void vtysh_config_dump(void)
struct listnode *node, *nnode;
struct listnode *mnode, *mnnode;
struct config *config;
- struct list *master;
+ struct config_master_head *master;
char *line;
unsigned int i;
@@ -446,7 +444,7 @@ void vtysh_config_dump(void)
for (i = 0; i < vector_active(configvec); i++)
if ((master = vector_slot(configvec, i)) != NULL) {
- for (ALL_LIST_ELEMENTS(master, node, nnode, config)) {
+ while ((config = config_master_pop(master))) {
/* Don't print empty sections for interface.
* Route maps on the
* other hand could have a legitimate empty
@@ -466,6 +464,8 @@ void vtysh_config_dump(void)
vty_out(vty, "%s\n", line);
if (!NO_DELIMITER(i))
vty_out(vty, "!\n");
+
+ config_del(config);
}
if (NO_DELIMITER(i))
vty_out(vty, "!\n");
@@ -473,7 +473,8 @@ void vtysh_config_dump(void)
for (i = 0; i < vector_active(configvec); i++)
if ((master = vector_slot(configvec, i)) != NULL) {
- list_delete(&master);
+ config_master_fini(master);
+ XFREE(MTYPE_VTYSH_CONFIG, master);
vector_slot(configvec, i) = NULL;
}
list_delete_all_node(config_top);
diff --git a/yang/frr-eigrpd.yang b/yang/frr-eigrpd.yang
index 26de7a71ae..853d823880 100644
--- a/yang/frr-eigrpd.yang
+++ b/yang/frr-eigrpd.yang
@@ -57,7 +57,7 @@ module frr-eigrpd {
value 2;
}
- enum hmac-sha2 {
+ enum hmac-sha-256 {
description "HMAC SHA256 algorithm";
value 3;
}
diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang
new file mode 100644
index 0000000000..e79ede87b7
--- /dev/null
+++ b/yang/frr-filter.yang
@@ -0,0 +1,353 @@
+module frr-filter {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/filter";
+ prefix frr-filter;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description "This module defines filter settings";
+
+ revision 2019-07-04 {
+ description "Initial revision";
+ }
+
+ /*
+ * Types.
+ */
+ typedef access-list-standard {
+ description "Standard IPv4 access list (any, host or a prefix)";
+ type uint16 {
+ range "1..99 | 1300..1999";
+ }
+ }
+
+ typedef access-list-extended {
+ description
+ "Extended IPv4 access list (source / destination any, hosts or prefixes)";
+ type uint16 {
+ range "100..199 | 2000..2699";
+ }
+ }
+
+ typedef access-list-legacy {
+ description "Standard/Extended IPv4 access list";
+ type uint16 {
+ range "1..199 | 1300..2699";
+ }
+ }
+
+ typedef access-list-name {
+ description "Access list name formatting";
+ type string;
+ }
+
+ typedef access-list-sequence {
+ description "Access list sequence number";
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+
+ typedef access-list-action {
+ description "Access list return action on match";
+ type enumeration {
+ enum deny {
+ description "Deny an entry";
+ value 0;
+ }
+ enum permit {
+ description "Accept an entry";
+ value 1;
+ }
+ }
+ }
+
+ /*
+ * Configuration data.
+ */
+ container filter-list {
+ list access-list-legacy {
+ description "Access list legacy instance";
+
+ key "number sequence";
+
+ leaf number {
+ description "Access list sequence value";
+ type access-list-legacy;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Access list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf remark {
+ description "Access list remark";
+ type string;
+ }
+
+ choice value {
+ description
+ "Standard access list: value to match.
+ Extended access list: source value to match.";
+ mandatory true;
+
+ leaf host {
+ description "Host to match";
+ type inet:ipv4-address;
+ }
+ leaf network {
+ description "Network to match";
+ type inet:ipv4-prefix;
+ }
+ leaf any {
+ description "Match any";
+ type empty;
+ }
+ }
+
+ choice extended-value {
+ when "./sequence >= 100 and ./sequence <= 199 or
+ ./sequence >= 2000 and ./sequence <= 2699";
+ description "Destination value to match";
+
+ leaf destination-host {
+ description "Host to match";
+ type inet:ipv4-address;
+ }
+ leaf destination-network {
+ description "Network to match";
+ type inet:ipv4-prefix;
+ }
+ leaf destination-any {
+ description "Match any";
+ type empty;
+ }
+ }
+ }
+
+ list access-list {
+ description "Access list instance";
+
+ key "type identifier sequence";
+
+ leaf type {
+ description "Access list content type";
+ type enumeration {
+ enum ipv4 {
+ description "Internet Protocol address version 4";
+ value 0;
+ }
+ enum ipv6 {
+ description "Internet Protocol address version 6";
+ value 1;
+ }
+ enum mac {
+ description "Media Access Control address";
+ value 2;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `value` leaf to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum custom {
+ description "Custom data type";
+ value 100;
+ }
+ }
+ }
+
+ leaf identifier {
+ description "Access list identifier";
+ type access-list-name;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Access list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf remark {
+ description "Access list remark";
+ type string;
+ }
+
+ choice value {
+ description "Access list value to match";
+ mandatory true;
+
+ case ipv4-prefix {
+ when "./type = 'ipv4'";
+
+ leaf ipv4-prefix {
+ description "Configure IPv4 prefix to match";
+ type inet:ipv4-prefix;
+ }
+
+ leaf ipv4-exact-match {
+ description "Exact match of prefix";
+ type boolean;
+ default false;
+ }
+ }
+ case ipv6-prefix {
+ when "./type = 'ipv6'";
+
+ leaf ipv6-prefix {
+ description "Configure IPv6 prefix to match";
+ type inet:ipv6-prefix;
+ }
+
+ leaf ipv6-exact-match {
+ description "Exact match of prefix";
+ type boolean;
+ default false;
+ }
+ }
+ case mac {
+ when "./type = 'mac'";
+
+ leaf mac {
+ description "Configure MAC address to match";
+ type yang:mac-address;
+ }
+ }
+ case any {
+ leaf any {
+ description "Match anything";
+ type empty;
+ }
+ }
+ }
+ }
+
+ list prefix-list {
+ description "Prefix list instance";
+
+ key "type name sequence";
+
+ leaf type {
+ description "Prefix list type";
+ type enumeration {
+ enum ipv4 {
+ description "Internet Protocol address version 4";
+ value 0;
+ }
+ enum ipv6 {
+ description "Internet Protocol address version 6";
+ value 1;
+ }
+ }
+ }
+
+ leaf name {
+ description "Prefix list name";
+ type access-list-name;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Prefix list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf description {
+ description "Prefix list user description";
+ type string;
+ }
+
+ choice value {
+ description "Prefix list value to match";
+ mandatory true;
+
+ case ipv4-prefix {
+ when "./type = 'ipv4'";
+
+ leaf ipv4-prefix {
+ description "Configure IPv4 prefix to match";
+ type inet:ipv4-prefix;
+ }
+
+ leaf ipv4-prefix-length-greater-or-equal {
+ description
+ "Specifies if matching prefixes with length greater than
+ or equal to value";
+ type uint8 {
+ range "0..32";
+ }
+ }
+
+ leaf ipv4-prefix-length-lesser-or-equal {
+ description
+ "Specifies if matching prefixes with length lesser than
+ or equal to value";
+ type uint8 {
+ range "0..32";
+ }
+ }
+ }
+ case ipv6-prefix {
+ when "./type = 'ipv6'";
+
+ leaf ipv6-prefix {
+ description "Configure IPv6 prefix to match";
+ type inet:ipv6-prefix;
+ }
+
+ leaf ipv6-prefix-length-greater-or-equal {
+ description
+ "Specifies if matching prefixes with length greater than
+ or equal to value";
+ type uint8 {
+ range "0..128";
+ }
+ }
+
+ leaf ipv6-prefix-length-lesser-or-equal {
+ description
+ "Specifies if matching prefixes with length lesser than
+ or equal to value";
+ type uint8 {
+ range "0..128";
+ }
+ }
+ }
+ case any {
+ leaf any {
+ description "Match anything";
+ type empty;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
new file mode 100644
index 0000000000..0ce40b474b
--- /dev/null
+++ b/yang/frr-route-map.yang
@@ -0,0 +1,404 @@
+module frr-route-map {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/route-map";
+ prefix frr-route-map;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import frr-filter {
+ prefix filter;
+ }
+
+ organization "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description "This module defines route map settings";
+
+ revision 2019-07-01 {
+ description "Initial revision";
+ }
+
+ /*
+ * Types.
+ */
+ typedef route-map-sequence {
+ description "Route map valid sequence numbers";
+ type uint16 {
+ range "1..65535";
+ }
+ }
+
+ typedef route-map-name {
+ description "Route map name format";
+ type string;
+ }
+
+ /*
+ * Operational data.
+ */
+ container route-map {
+ list instance {
+ description "Route map instance";
+
+ key "name sequence";
+
+ leaf name {
+ description "Route map instance name";
+ type route-map-name;
+ }
+
+ leaf sequence {
+ description
+ "Route map instance priority (low number means higher priority)";
+ type route-map-sequence;
+ }
+
+ leaf description {
+ description "Route map description";
+ type string;
+ }
+
+ leaf action {
+ description
+ "Route map actions: permit (executes action), deny (quits evaluation)";
+ mandatory true;
+ type enumeration {
+ enum permit {
+ description
+ "Executes configured action and permits the prefix/route
+ if the conditions matched. An alternative exit action can
+ be configured to continue processing the route map list
+ or jump to process another route map.";
+ value 0;
+ }
+ enum deny {
+ description
+ "If all conditions are met the prefix/route is denied and
+ route map processing stops.";
+ value 1;
+ }
+ }
+ }
+
+ list match-condition {
+ description "Route map match conditions";
+
+ key "condition";
+
+ leaf condition {
+ description "Match condition";
+ type enumeration {
+ enum interface {
+ description "Match interface";
+ value 0;
+ }
+ enum ipv4-address-list {
+ description "Match an IPv4 access-list";
+ value 1;
+ }
+ enum ipv4-prefix-list {
+ description "Match an IPv4 prefix-list";
+ value 2;
+ }
+ enum ipv4-prefix-length {
+ description "Match an IPv4 prefix length";
+ value 3;
+ }
+ enum ipv4-next-hop-list {
+ description "Match an IPv4 next-hop";
+ value 4;
+ }
+ enum ipv4-next-hop-prefix-list {
+ description "Match an IPv4 next-hop prefix list";
+ value 5;
+ }
+ enum ipv4-next-hop-prefix-length {
+ description "Match an IPv4 next-hop prefix length";
+ value 6;
+ }
+ enum ipv4-next-hop-type {
+ description "Match an IPv4 next-hop type";
+ value 7;
+ }
+ enum ipv6-address-list {
+ description "Match an IPv6 access-list";
+ value 8;
+ }
+ enum ipv6-prefix-list {
+ description "Match an IPv6 prefix-list";
+ value 9;
+ }
+ enum ipv6-prefix-length {
+ description "Match an IPv6 prefix length";
+ value 10;
+ }
+ enum ipv6-next-hop {
+ description "Match an IPv6 next-hop";
+ value 11;
+ }
+ enum ipv6-next-hop-type {
+ description "Match an IPv6 next-hop type";
+ value 12;
+ }
+ enum metric {
+ description "Match a route metric";
+ value 13;
+ }
+ enum tag {
+ description "Match a route tag";
+ value 14;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `condition-value` to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum routing-protocol-specific {
+ description "Match a routing protocol specific type";
+ value 100;
+ }
+ }
+ }
+
+ choice condition-value {
+ description
+ "Value to match (interpretation depends on condition type)";
+ case access-list-num {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-next-hop-list'";
+ leaf access-list-num {
+ type filter:access-list-standard;
+ }
+ }
+ case access-list-num-extended {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-next-hop-list'";
+ leaf access-list-num-extended {
+ type filter:access-list-extended;
+ }
+ }
+ case list-name {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-prefix-list' or
+ ./condition = 'ipv4-next-hop-list' or
+ ./condition = 'ipv4-next-hop-prefix-list' or
+ ./condition = 'ipv6-address-list' or
+ ./condition = 'ipv6-prefix-list'";
+ leaf list-name {
+ type filter:access-list-name;
+ }
+ }
+ case ipv6-address {
+ when "./condition = 'ipv6-next-hop'";
+ leaf ipv6-address {
+ type inet:ipv6-address;
+ }
+ }
+ case ipv4-prefix-length {
+ when "./condition = 'ipv4-prefix-length' or
+ ./condition = 'ipv4-next-hop-prefix-length'";
+ leaf ipv4-prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ }
+ }
+ case ipv6-prefix-length {
+ when "./condition = 'ipv6-prefix-length'";
+ leaf ipv6-prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ }
+ }
+ case ipv4-next-hop-type {
+ when "./condition = 'ipv4-next-hop-type'";
+ leaf ipv4-next-hop-type {
+ type enumeration {
+ enum blackhole {
+ value 0;
+ }
+ }
+ }
+ }
+ case ipv6-next-hop-type {
+ when "./condition = 'ipv6-next-hop-type'";
+ leaf ipv6-next-hop-type {
+ type enumeration {
+ enum blackhole {
+ value 0;
+ }
+ }
+ }
+ }
+ case metric {
+ when "./condition = 'metric'";
+ leaf metric {
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+ }
+ case tag {
+ when "./condition = 'tag'";
+ leaf tag {
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+ }
+ }
+ }
+
+ list set-action {
+ description "Route map set actions";
+
+ key "action";
+
+ leaf action {
+ description "Action to do when the route map matches";
+ type enumeration {
+ enum ipv4-next-hop {
+ description "Set IPv4 address of the next hop";
+ value 0;
+ }
+ enum ipv6-next-hop {
+ description "Set IPv6 address of the next hop";
+ value 1;
+ }
+ enum metric {
+ description "Set prefix/route metric";
+ value 2;
+ }
+ enum tag {
+ description "Set tag";
+ value 3;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `action-value` to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum routing-protocol-specific {
+ description "Set a routing protocol specific action";
+ value 100;
+ }
+ }
+ }
+
+ choice action-value {
+ description
+ "Value to set (interpretation depends on action-type)";
+ case ipv4-address {
+ when "./action = 'ipv4-next-hop'";
+ leaf ipv4-address {
+ description "IPv4 address";
+ type inet:ipv4-address;
+ }
+ }
+ case ipv6-address {
+ when "./action = 'ipv6-next-hop'";
+ leaf ipv6-address {
+ description "IPv6 address";
+ type inet:ipv6-address;
+ }
+ }
+ case metric {
+ when "./action = 'metric'";
+ choice metric-value {
+ description "Metric to set or use";
+ case value {
+ leaf value {
+ description "Use the following metric value";
+ type uint32 {
+ range "0..4294967295";
+ }
+ }
+ }
+ case add-metric {
+ leaf add-metric {
+ description "Add unit to metric";
+ type boolean;
+ }
+ }
+ case subtract-metric {
+ leaf subtract-metric {
+ description "Subtract unit from metric";
+ type boolean;
+ }
+ }
+ case use-round-trip-time {
+ leaf use-round-trip-time {
+ description "Use the round trip time as metric";
+ type boolean;
+ }
+ }
+ case add-round-trip-time {
+ leaf add-round-trip-time {
+ description "Add round trip time to metric";
+ type boolean;
+ }
+ }
+ case subtract-round-trip-time {
+ leaf subtract-round-trip-time {
+ description "Subtract round trip time to metric";
+ type boolean;
+ }
+ }
+ }
+ }
+ case tag {
+ leaf tag {
+ description "Tag value";
+ type uint32 {
+ range "0..4294967295";
+ }
+ }
+ }
+ }
+ }
+
+ leaf call {
+ description
+ "Call another route map before calling `exit-policy`. If the
+ called route map returns deny then this route map will also
+ return deny";
+ type string;
+ }
+
+ leaf exit-policy {
+ description "What do to after route map successful match, set and call";
+ type enumeration {
+ enum permit-or-deny {
+ description "End route map evaluation and return";
+ value 0;
+ }
+ enum next {
+ description
+ "Proceed evaluating next route map entry per sequence";
+ value 1;
+ }
+ enum goto {
+ description
+ "Go to route map entry with the provided sequence number";
+ value 2;
+ }
+ }
+ default "permit-or-deny";
+ }
+
+ leaf goto-value {
+ when "../exit-policy = 'goto'";
+ description
+ "Sequence number to jump (when using `goto` exit policy)";
+ type route-map-sequence;
+ }
+ }
+ }
+}
diff --git a/yang/subdir.am b/yang/subdir.am
index 4b3baeea9d..18d2bf160c 100644
--- a/yang/subdir.am
+++ b/yang/subdir.am
@@ -28,6 +28,10 @@ if BFDD
dist_yangmodels_DATA += yang/frr-bfdd.yang
endif
+if EIGRPD
+dist_yangmodels_DATA += yang/frr-eigrpd.yang
+endif
+
if RIPD
dist_yangmodels_DATA += yang/frr-ripd.yang
endif
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index df8d4bfe15..63e72fed00 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1347,6 +1347,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
"Intf %s(%u) has come UP",
name, ifp->ifindex);
if_up(ifp);
+ } else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) has gone DOWN",
+ name, ifp->ifindex);
+ if_down(ifp);
}
}
diff --git a/zebra/main.c b/zebra/main.c
index 84e83bc37e..657d1247e9 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -34,7 +34,6 @@
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
-#include "logicalrouter.h"
#include "libfrr.h"
#include "routemap.h"
#include "frr_pthread.h"
@@ -262,7 +261,6 @@ int main(int argc, char **argv)
graceful_restart = 0;
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
- logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
frr_preinit(&zebra_di, argc, argv);
@@ -349,8 +347,6 @@ int main(int argc, char **argv)
break;
case 'n':
vrf_configure_backend(VRF_BACKEND_NETNS);
- logicalrouter_configure_backend(
- LOGICALROUTER_BACKEND_OFF);
break;
case OPTION_V6_RR_SEMANTICS:
v6_rr_semantics = true;
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index db4f9d0015..94918365a3 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -23,7 +23,6 @@
#include "lib/ns.h"
#include "lib/vrf.h"
-#include "lib/logicalrouter.h"
#include "lib/prefix.h"
#include "lib/memory.h"
@@ -45,7 +44,6 @@ DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space")
static struct zebra_ns *dzns;
-static int logicalrouter_config_write(struct vty *vty);
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete);
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id)
@@ -188,8 +186,6 @@ int zebra_ns_init(const char *optional_default_name)
ns_id_external = ns_map_nsid_with_external(ns_id, true);
ns_init_management(ns_id_external, ns_id);
- logicalrouter_init(logicalrouter_config_write);
-
/* Do any needed per-NS data structure allocation. */
dzns->if_table = route_table_init();
@@ -215,21 +211,6 @@ int zebra_ns_init(const char *optional_default_name)
return 0;
}
-static int logicalrouter_config_write(struct vty *vty)
-{
- struct ns *ns;
- int write = 0;
-
- RB_FOREACH (ns, ns_head, &ns_tree) {
- if (ns->ns_id == NS_DEFAULT || ns->name == NULL)
- continue;
- vty_out(vty, "logical-router %u netns %s\n", ns->ns_id,
- ns->name);
- write = 1;
- }
- return write;
-}
-
int zebra_ns_config_write(struct vty *vty, struct ns *ns)
{
if (ns && ns->name != NULL)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index ca19971d64..3608b887ee 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1774,7 +1774,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
/* Redistribute */
redistribute_update(dest_pfx, src_pfx,
- re, NULL);
+ re, old_re);
}
/*
@@ -1926,6 +1926,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
goto done;
}
+ /* Ensure we clear the QUEUED flag */
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+
/* Is this a notification that ... matters? We only really care about
* the route that is currently selected for installation.
*/
@@ -1990,7 +1993,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_vrf(ctx), dest_str);
/* We expect this to be the selected route, so we want
- * to tell others about this transistion.
+ * to tell others about this transition.
*/
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 0397b96983..da2fe4a30c 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -924,7 +924,7 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
}
for (rn = route_top(table); rn; rn = route_next(rn)) {
- if (p && prefix_cmp(&rn->p, p) != 0)
+ if (p && !prefix_match(&rn->p, p))
continue;
if (rn->info)
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 91edfab10f..99431e7e6d 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -2444,7 +2444,7 @@ DEFPY (clear_evpn_dup_addr,
zvrf = zebra_vrf_get_evpn();
if (vni_str) {
- if (mac) {
+ if (!is_zero_mac(&mac->eth_addr)) {
ret = zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf,
vni,
&mac->eth_addr);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 359585df73..2e8c81bddd 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -3403,6 +3403,39 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
return 0;
}
+static bool zvni_check_mac_del_from_db(struct mac_walk_ctx *wctx,
+ zebra_mac_t *mac)
+{
+ if ((wctx->flags & DEL_LOCAL_MAC) &&
+ (mac->flags & ZEBRA_MAC_LOCAL))
+ return true;
+ else if ((wctx->flags & DEL_REMOTE_MAC) &&
+ (mac->flags & ZEBRA_MAC_REMOTE))
+ return true;
+ else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) &&
+ (mac->flags & ZEBRA_MAC_REMOTE) &&
+ IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
+ return true;
+ else if ((wctx->flags & DEL_LOCAL_MAC) &&
+ (mac->flags & ZEBRA_MAC_AUTO) &&
+ !listcount(mac->neigh_list)) {
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char buf[ETHER_ADDR_STRLEN];
+
+ zlog_debug("%s: Del MAC %s flags 0x%x",
+ __PRETTY_FUNCTION__,
+ prefix_mac2str(&mac->macaddr,
+ buf, sizeof(buf)),
+ mac->flags);
+ }
+ wctx->uninstall = 0;
+
+ return true;
+ }
+
+ return false;
+}
+
/*
* Free MAC hash entry (callback)
*/
@@ -3411,18 +3444,11 @@ static void zvni_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
struct mac_walk_ctx *wctx = arg;
zebra_mac_t *mac = bucket->data;
- if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
- || ((wctx->flags & DEL_REMOTE_MAC)
- && (mac->flags & ZEBRA_MAC_REMOTE))
- || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
- && (mac->flags & ZEBRA_MAC_REMOTE)
- && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
- &wctx->r_vtep_ip))) {
+ if (zvni_check_mac_del_from_db(wctx, mac)) {
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
zvni_mac_send_del_to_client(wctx->zvni->vni,
&mac->macaddr);
}
-
if (wctx->uninstall)
zvni_mac_uninstall(wctx->zvni, mac);
@@ -5332,8 +5358,6 @@ static void process_remote_macip_add(vni_t vni,
if (ipa_len)
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
} else {
- const char *mac_type;
-
/* When host moves but changes its (MAC,IP)
* binding, BGP may install a MACIP entry that
* corresponds to "older" location of the host
@@ -5342,16 +5366,14 @@ static void process_remote_macip_add(vni_t vni,
* the sequence number and ignore this update
* if appropriate.
*/
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
tmp_seq = mac->loc_seq;
- mac_type = "local";
- } else {
+ else
tmp_seq = mac->rem_seq;
- mac_type = "remote";
- }
+
if (seq < tmp_seq) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
+ zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
vni,
prefix_mac2str(macaddr,
buf, sizeof(buf)),
@@ -5359,8 +5381,7 @@ static void process_remote_macip_add(vni_t vni,
ipa_len ?
ipaddr2str(ipaddr,
buf1, sizeof(buf1)) : "",
- mac_type,
- tmp_seq);
+ tmp_seq, mac->flags);
return;
}
}
@@ -7274,8 +7295,13 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
* of a VxLAN bridge.
*/
zvni = zvni_from_svi(ifp, link_if);
- if (!zvni)
+ if (!zvni) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s: Del neighbor %s VNI is not present for interface %s",
+ __PRETTY_FUNCTION__,
+ ipaddr2str(ip, buf, sizeof(buf)), ifp->name);
return 0;
+ }
if (!zvni->vxlan_if) {
zlog_debug(
@@ -7672,9 +7698,10 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
+ zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
- ifp->ifindex, vid, zvni->vni, mac->flags);
+ ifp->ifindex, vid, zvni->vni, mac->loc_seq,
+ mac->flags, listcount(mac->neigh_list));
/* Update all the neigh entries associated with this mac */
zvni_process_neigh_on_local_mac_del(zvni, mac);