Merge pull request #1163 from donaldsharp/deduplicate_nexthops

zebra: deduplicate nexthops
This commit is contained in:
Russ White 2017-09-13 16:18:41 -04:00 committed by GitHub
commit dcc4574ae6
6 changed files with 125 additions and 78 deletions

View File

@ -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
*/

View File

@ -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);

View File

@ -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))) {

View File

@ -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)

View File

@ -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.

View File

@ -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;
time_t uptime;
struct tm *tm;
uptime = time(NULL);
uptime -= re->uptime;
tm = gmtime(&uptime);
uptime = time(NULL);
uptime -= re->uptime;
tm = gmtime(&uptime);
vty_out(vty, " Last update ");
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");
}
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;
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);
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);
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");
}
}