summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_main.c1
-rw-r--r--eigrpd/eigrpd.c7
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--lib/log.c94
-rw-r--r--lib/nexthop.c33
-rw-r--r--lib/nexthop.h10
-rw-r--r--ospfd/ospfd.c3
-rw-r--r--pimd/pimd.c2
-rw-r--r--ripd/rip_main.c1
-rw-r--r--ripngd/ripng_main.c1
-rw-r--r--zebra/rt_netlink.c6
-rw-r--r--zebra/rt_socket.c4
-rw-r--r--zebra/zebra_rib.c16
-rw-r--r--zebra/zebra_vty.c140
14 files changed, 202 insertions, 118 deletions
diff --git a/babeld/babel_main.c b/babeld/babel_main.c
index 54626a4aeb..6a8f9bb75f 100644
--- a/babeld/babel_main.c
+++ b/babeld/babel_main.c
@@ -335,6 +335,7 @@ babel_exit_properly(void)
babel_save_state_file();
debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
debugf(BABEL_DEBUG_COMMON, "Done.");
+ frr_fini();
exit(0);
}
diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c
index 99d88b2d00..ee60898f86 100644
--- a/eigrpd/eigrpd.c
+++ b/eigrpd/eigrpd.c
@@ -42,6 +42,7 @@
#include "plist.h"
#include "sockopt.h"
#include "keychain.h"
+#include "libfrr.h"
#include "eigrpd/eigrp_structs.h"
#include "eigrpd/eigrpd.h"
@@ -241,12 +242,10 @@ void eigrp_terminate(void)
SET_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN);
- /* exit immediately if EIGRP not actually running */
- if (listcount(eigrp_om->eigrp) == 0)
- exit(0);
-
for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp))
eigrp_finish(eigrp);
+
+ frr_fini();
}
void eigrp_finish(struct eigrp *eigrp)
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index ed96bd31c2..99eb698b75 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -35,6 +35,7 @@
#include "linklist.h"
#include "nexthop.h"
#include "vrf.h"
+#include "libfrr.h"
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
@@ -427,4 +428,5 @@ void isis_zebra_stop(void)
{
zclient_stop(zclient);
zclient_free(zclient);
+ frr_fini();
}
diff --git a/lib/log.c b/lib/log.c
index ea2e804cda..02af55d465 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -43,6 +43,9 @@ static int logfile_fd = -1; /* Used in signal handler. */
struct zlog *zlog_default = NULL;
bool zlog_startup_stderr = true;
+/* lock protecting zlog_default for mt-safe zlog */
+pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;
+
const char *zlog_priority[] = {
"emergencies", "alerts", "critical", "errors", "warnings",
"notifications", "informational", "debugging", NULL,
@@ -195,6 +198,8 @@ static void vzlog_file(struct zlog *zl, struct timestamp_control *tsctl,
/* va_list version of zlog. */
void vzlog(int priority, const char *format, va_list args)
{
+ pthread_mutex_lock(&loglock);
+
char proto_str[32];
int original_errno = errno;
struct timestamp_control tsctl;
@@ -212,6 +217,7 @@ void vzlog(int priority, const char *format, va_list args)
/* In this case we return at here. */
errno = original_errno;
+ pthread_mutex_unlock(&loglock);
return;
}
tsctl.precision = zl->timestamp_precision;
@@ -252,37 +258,36 @@ void vzlog(int priority, const char *format, va_list args)
proto_str, format, &tsctl, args);
errno = original_errno;
+ pthread_mutex_unlock(&loglock);
}
int vzlog_test(int priority)
{
+ pthread_mutex_lock(&loglock);
+
+ int ret = 0;
+
struct zlog *zl = zlog_default;
/* When zlog_default is also NULL, use stderr for logging. */
- if (zl == NULL) {
- return 1;
- }
-
+ if (zl == NULL)
+ ret = 1;
/* Syslog output */
- if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) {
- return 1;
- }
-
+ else if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
+ ret = 1;
/* File output. */
- if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) {
- return 1;
- }
-
+ else if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
+ ret = 1;
/* stdout output. */
- if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) {
- return 1;
- }
-
+ else if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
+ ret = 1;
/* Terminal monitor. */
- if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
- return 1;
+ else if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
+ ret = 1;
- return 0;
+ pthread_mutex_unlock(&loglock);
+
+ return ret;
}
static char *str_append(char *dst, int len, const char *src)
@@ -737,7 +742,10 @@ void openzlog(const char *progname, const char *protoname, u_short instance,
zl->default_lvl = LOG_DEBUG;
openlog(progname, syslog_flags, zl->facility);
+
+ pthread_mutex_lock(&loglock);
zlog_default = zl;
+ pthread_mutex_unlock(&loglock);
#ifdef HAVE_GLIBC_BACKTRACE
/* work around backtrace() using lazily resolved dynamically linked
@@ -754,6 +762,7 @@ void openzlog(const char *progname, const char *protoname, u_short instance,
void closezlog(void)
{
+ pthread_mutex_lock(&loglock);
struct zlog *zl = zlog_default;
closelog();
@@ -766,19 +775,23 @@ void closezlog(void)
XFREE(MTYPE_ZLOG, zl);
zlog_default = NULL;
+ pthread_mutex_unlock(&loglock);
}
/* Called from command.c. */
void zlog_set_level(zlog_dest_t dest, int log_level)
{
+ pthread_mutex_lock(&loglock);
zlog_default->maxlvl[dest] = log_level;
+ pthread_mutex_unlock(&loglock);
}
int zlog_set_file(const char *filename, int log_level)
{
- struct zlog *zl = zlog_default;
+ struct zlog *zl;
FILE *fp;
mode_t oldumask;
+ int ret = 1;
/* There is opend file. */
zlog_reset_file();
@@ -787,21 +800,28 @@ int zlog_set_file(const char *filename, int log_level)
oldumask = umask(0777 & ~LOGFILE_MASK);
fp = fopen(filename, "a");
umask(oldumask);
- if (fp == NULL)
- return 0;
-
- /* Set flags. */
- zl->filename = XSTRDUP(MTYPE_ZLOG, filename);
- zl->maxlvl[ZLOG_DEST_FILE] = log_level;
- zl->fp = fp;
- logfile_fd = fileno(fp);
+ if (fp == NULL) {
+ ret = 0;
+ } else {
+ pthread_mutex_lock(&loglock);
+ zl = zlog_default;
+
+ /* Set flags. */
+ zl->filename = XSTRDUP(MTYPE_ZLOG, filename);
+ zl->maxlvl[ZLOG_DEST_FILE] = log_level;
+ zl->fp = fp;
+ logfile_fd = fileno(fp);
+ pthread_mutex_unlock(&loglock);
+ }
- return 1;
+ return ret;
}
/* Reset opend file. */
int zlog_reset_file(void)
{
+ pthread_mutex_lock(&loglock);
+
struct zlog *zl = zlog_default;
if (zl->fp)
@@ -814,14 +834,19 @@ int zlog_reset_file(void)
XFREE(MTYPE_ZLOG, zl->filename);
zl->filename = NULL;
+ pthread_mutex_unlock(&loglock);
+
return 1;
}
/* Reopen log file. */
int zlog_rotate(void)
{
+ pthread_mutex_lock(&loglock);
+
struct zlog *zl = zlog_default;
int level;
+ int ret = 1;
if (zl->fp)
fclose(zl->fp);
@@ -842,13 +867,16 @@ int zlog_rotate(void)
zlog_err(
"Log rotate failed: cannot open file %s for append: %s",
zl->filename, safe_strerror(save_errno));
- return -1;
+ ret = -1;
+ } else {
+ logfile_fd = fileno(zl->fp);
+ zl->maxlvl[ZLOG_DEST_FILE] = level;
}
- logfile_fd = fileno(zl->fp);
- zl->maxlvl[ZLOG_DEST_FILE] = level;
}
- return 1;
+ pthread_mutex_unlock(&loglock);
+
+ return ret;
}
/* Wrapper around strerror to handle case where it returns NULL. */
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 2dba412f45..ea6a310a4a 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -71,6 +71,39 @@ int nexthop_same_no_recurse(const struct nexthop *next1,
return 1;
}
+int
+nexthop_same_firsthop (struct nexthop *next1, struct nexthop *next2)
+{
+ int type1 = NEXTHOP_FIRSTHOPTYPE(next1->type);
+ int type2 = NEXTHOP_FIRSTHOPTYPE(next2->type);
+
+ if (type1 != type2)
+ return 0;
+ switch (type1)
+ {
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
+ return 0;
+ if (next1->ifindex != next2->ifindex)
+ return 0;
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ if (next1->ifindex != next2->ifindex)
+ return 0;
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
+ return 0;
+ if (next1->ifindex != next2->ifindex)
+ return 0;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return 1;
+}
+
/*
* nexthop_type_to_str
*/
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 781eb93413..20b0cd5227 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -50,6 +50,11 @@ enum blackhole_type {
BLACKHOLE_ADMINPROHIB,
};
+/* IPV[46] -> IPV[46]_IFINDEX */
+#define NEXTHOP_FIRSTHOPTYPE(type) \
+ ((type) == NEXTHOP_TYPE_IFINDEX || (type) == NEXTHOP_TYPE_BLACKHOLE) \
+ ? (type) : ((type) | 1)
+
/* Nexthop label structure. */
struct nexthop_label {
u_int8_t num_labels;
@@ -74,6 +79,10 @@ struct nexthop {
#define NEXTHOP_FLAG_ONLINK (1 << 3) /* Nexthop should be installed onlink. */
#define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */
#define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */
+#define NEXTHOP_FLAG_DUPLICATE (1 << 6) /* nexthop duplicates another active one */
+#define NEXTHOP_IS_ACTIVE(flags) \
+ (CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
+ && !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE))
/* Nexthop address */
union {
@@ -141,6 +150,7 @@ extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
extern int nexthop_same_no_recurse(const struct nexthop *next1,
const struct nexthop *next2);
extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2);
+extern int nexthop_same_firsthop (struct nexthop *next1, struct nexthop *next2);
extern const char *nexthop2str(struct nexthop *nexthop, char *str, int size);
extern struct nexthop *nexthop_next(struct nexthop *nexthop);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 20cee713bd..ed1d8901fb 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -35,6 +35,7 @@
#include "plist.h"
#include "sockopt.h"
#include "bfd.h"
+#include "libfrr.h"
#include "defaults.h"
#include "ospfd/ospfd.h"
@@ -489,6 +490,8 @@ void ospf_terminate(void)
*/
zclient_stop(zclient);
zclient_free(zclient);
+
+ frr_fini();
}
void ospf_finish(struct ospf *ospf)
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 9a8e92cbb2..37c79d4554 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -139,4 +139,6 @@ void pim_terminate()
zclient_stop(zclient);
zclient_free(zclient);
}
+
+ frr_fini();
}
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 91b623beb4..9a448e8958 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -89,6 +89,7 @@ static void sigint(void)
rip_clean();
rip_zclient_stop();
+ frr_fini();
exit(0);
}
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 0cb54d4335..8ef27daaba 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -92,6 +92,7 @@ static void sigint(void)
ripng_clean();
ripng_zebra_stop();
+ frr_fini();
exit(0);
}
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 12b6185395..e59d5f00fb 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1383,7 +1383,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
if (cmd == RTM_NEWROUTE
- && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ && !NEXTHOP_IS_ACTIVE(nexthop->flags))
continue;
if (cmd == RTM_DELROUTE
&& !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
@@ -1438,7 +1438,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
}
if ((cmd == RTM_NEWROUTE
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ && NEXTHOP_IS_ACTIVE(nexthop->flags))
|| (cmd == RTM_DELROUTE
&& CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB))) {
@@ -1521,7 +1521,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
}
if ((cmd == RTM_NEWROUTE
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ && NEXTHOP_IS_ACTIVE(nexthop->flags))
|| (cmd == RTM_DELROUTE
&& CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB))) {
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index d8e37a10c3..75207a2dde 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -136,7 +136,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
* other than ADD and DELETE?
*/
if ((cmd == RTM_ADD
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ && NEXTHOP_IS_ACTIVE(nexthop->flags))
|| (cmd == RTM_DELETE
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) {
if (nexthop->type == NEXTHOP_TYPE_IPV4
@@ -314,7 +314,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
gate = 0;
if ((cmd == RTM_ADD
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ && NEXTHOP_IS_ACTIVE(nexthop->flags))
|| (cmd == RTM_DELETE
#if 0
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 376425329b..d04b64b19c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1000,8 +1000,24 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
for (ALL_NEXTHOPS(re->nexthop, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return ret;
+ } else {
+ struct nexthop *prev;
+
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
+ for (ALL_NEXTHOPS(re->nexthop, prev)) {
+ if (prev == nexthop)
+ break;
+ if (nexthop_same_firsthop (nexthop, prev))
+ {
+ SET_FLAG (nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
+ break;
+ }
+ }
+ }
}
+
/*
* Make sure we update the FPM any time we send new information to
* the kernel.
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 1573646adc..1ce4f66b16 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -408,39 +408,34 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
vty_out(vty, ", best");
vty_out(vty, "\n");
- if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
- || re->type == ZEBRA_ROUTE_ISIS
- || re->type == ZEBRA_ROUTE_NHRP
- || re->type == ZEBRA_ROUTE_TABLE
- || re->type == ZEBRA_ROUTE_BGP) {
- time_t uptime;
- struct tm *tm;
-
- uptime = time(NULL);
- uptime -= re->uptime;
- tm = gmtime(&uptime);
-
- vty_out(vty, " Last update ");
-
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d", tm->tm_hour,
- tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm", tm->tm_yday,
- tm->tm_hour, tm->tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
- tm->tm_yday - ((tm->tm_yday / 7) * 7),
- tm->tm_hour);
- vty_out(vty, " ago\n");
- }
+ time_t uptime;
+ struct tm *tm;
+
+ uptime = time(NULL);
+ uptime -= re->uptime;
+ tm = gmtime(&uptime);
+
+ vty_out(vty, " Last update ");
+
+ if (uptime < ONE_DAY_SECOND)
+ vty_out(vty, "%02d:%02d:%02d", tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ vty_out(vty, "%dd%02dh%02dm", tm->tm_yday,
+ tm->tm_hour, tm->tm_min);
+ else
+ vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
+ tm->tm_yday - ((tm->tm_yday / 7) * 7),
+ tm->tm_hour);
+ vty_out(vty, " ago\n");
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
char addrstr[32];
vty_out(vty, " %c%s",
CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*'
+ ? CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
+ ? ' ' : '*'
: ' ',
nexthop->rparent ? " " : "");
@@ -489,6 +484,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
default:
break;
}
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ vty_out(vty, " (duplicate nexthop removed)");
+
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
vty_out(vty, " inactive");
@@ -553,6 +551,12 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_nexthop = NULL;
json_object *json_route = NULL;
json_object *json_labels = NULL;
+ time_t uptime;
+ struct tm *tm;
+
+ uptime = time(NULL);
+ uptime -= re->uptime;
+ tm = gmtime(&uptime);
if (json) {
json_route = json_object_new_object();
@@ -579,35 +583,26 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_int_add(json_route, "metric", re->metric);
}
- if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
- || re->type == ZEBRA_ROUTE_ISIS
- || re->type == ZEBRA_ROUTE_NHRP
- || re->type == ZEBRA_ROUTE_TABLE
- || re->type == ZEBRA_ROUTE_BGP) {
- time_t uptime;
- struct tm *tm;
-
- uptime = time(NULL);
- uptime -= re->uptime;
- tm = gmtime(&uptime);
-
- if (uptime < ONE_DAY_SECOND)
- sprintf(buf, "%02d:%02d:%02d", tm->tm_hour,
- tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- sprintf(buf, "%dd%02dh%02dm", tm->tm_yday,
- tm->tm_hour, tm->tm_min);
- else
- sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
- tm->tm_yday - ((tm->tm_yday / 7) * 7),
- tm->tm_hour);
+ if (uptime < ONE_DAY_SECOND)
+ sprintf(buf, "%02d:%02d:%02d", tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ sprintf(buf, "%dd%02dh%02dm", tm->tm_yday,
+ tm->tm_hour, tm->tm_min);
+ else
+ sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
+ tm->tm_yday - ((tm->tm_yday / 7) * 7),
+ tm->tm_hour);
- json_object_string_add(json_route, "uptime", buf);
- }
+ json_object_string_add(json_route, "uptime", buf);
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
json_nexthop = json_object_new_object();
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop,
+ "duplicate");
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
json_object_boolean_true_add(json_nexthop,
"fib");
@@ -687,6 +682,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop,
+ "duplicate");
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
json_object_boolean_true_add(json_nexthop,
"active");
@@ -774,12 +773,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (re->type != ZEBRA_ROUTE_CONNECT)
len += vty_out(vty, " [%d/%d]", re->distance,
re->metric);
- } else
+ } else {
vty_out(vty, " %c%*c",
CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*'
+ ? CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
+ ? ' ' : '*'
: ' ',
len - 3 + (2 * nexthop_level(nexthop)), ' ');
+ }
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
@@ -862,29 +863,16 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
sizeof buf, 1));
}
- if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
- || re->type == ZEBRA_ROUTE_ISIS
- || re->type == ZEBRA_ROUTE_NHRP
- || re->type == ZEBRA_ROUTE_TABLE
- || re->type == ZEBRA_ROUTE_BGP) {
- time_t uptime;
- struct tm *tm;
-
- uptime = time(NULL);
- uptime -= re->uptime;
- tm = gmtime(&uptime);
-
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
- tm->tm_min, tm->tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
- tm->tm_hour, tm->tm_min);
- else
- vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
- tm->tm_yday - ((tm->tm_yday / 7) * 7),
- tm->tm_hour);
- }
+ if (uptime < ONE_DAY_SECOND)
+ vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
+ tm->tm_hour, tm->tm_min);
+ else
+ vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
+ tm->tm_yday - ((tm->tm_yday / 7) * 7),
+ tm->tm_hour);
vty_out(vty, "\n");
}
}