mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-11-03 06:28:33 +00:00
Merge pull request #1163 from donaldsharp/deduplicate_nexthops
zebra: deduplicate nexthops
This commit is contained in:
commit
dcc4574ae6
@ -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
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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))) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user