So here is another try and I guess some people will not like it.
BGP unlike other routing protocols needs to find the true nexthop because
the passed IP in the NEXT_HOP attribute can be more then one hop away.
So bgpd uses the fib (as stored in the parent) to figure out the gateway
for a nexthop. In the beginning we had some troubles with correctly
tracking those nexthops (I think all problems are fixed now but that does
not matter). bgpctl show nexthop should return all necessary information
to understand the decision bgpd did. The current output is missing the
single most important information -- the route that is used to verify this
nexthop. Without this info nobody knows why a wrong nexthop is used.
This diff sends the kroute to bgpctl so that we can show the route which
got used.
Nexthop State Route Prio Gateway Iface
62.48.4.1 valid 62.48.4.0/24 4 connected fxp0
62.48.0.1 invalid
Having the link state in the output would be nice but there are only about
4-5 char left till we hit the 80-char wide wall. I tried out to use a "*"
for valid nexthops but that single char (even though the most important
one) is easily missed in longer outputs.
I'm open to suggestions
--
:wq Claudio
Index: bgpctl/bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.144
diff -u -p -r1.144 bgpctl.c
--- bgpctl/bgpctl.c 21 Jul 2009 11:49:36 -0000 1.144
+++ bgpctl/bgpctl.c 22 Jul 2009 13:20:33 -0000
@@ -848,35 +848,56 @@ show_fib_msg(struct imsg *imsg)
void
show_nexthop_head(void)
{
- printf("%-20s %-10s\n", "Nexthop", "State");
+ printf("%-16s %-7s %-20s%-4s %-16s %-8s\n", "Nexthop", "State",
+ "Route", "Prio", "Gateway", "Iface");
}
int
show_nexthop_msg(struct imsg *imsg)
{
struct ctl_show_nexthop *p;
- int ifms_type;
+ struct kroute *k;
+ struct kroute6 *k6;
+ char *s;
switch (imsg->hdr.type) {
case IMSG_CTL_SHOW_NEXTHOP:
p = imsg->data;
- printf("%-20s %-10s", log_addr(&p->addr),
+ printf("%-16s %-7s ", log_addr(&p->addr),
p->valid ? "valid" : "invalid");
+ if (!p->krvalid) {
+ printf("\n");
+ return (0);
+ }
+ switch (p->addr.af) {
+ case AF_INET:
+ k = &p->kr.kr4;
+ if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix),
+ k->prefixlen) == -1)
+ err(1, NULL);
+ printf("%-20s", s);
+ free(s);
+ printf("%4i %-16s ", k->priority,
+ k->flags & F_CONNECTED ? "connected" :
+ inet_ntoa(k->nexthop));
+ break;
+ case AF_INET6:
+ k6 = &p->kr.kr6;
+ if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix),
+ k6->prefixlen) == -1)
+ err(1, NULL);
+ printf("%-20s", s);
+ free(s);
+ printf("%4i %-16s ", k6->priority,
+ k6->flags & F_CONNECTED ? "connected" :
+ log_in6addr(&k6->nexthop));
+ break;
+ default:
+ printf("unknown address familiy %d\n", p->addr.af);
+ return (0);
+ }
if (p->kif.ifname[0]) {
printf("%-8s", p->kif.ifname);
- if (p->kif.flags & IFF_UP) {
- printf("UP");
- ifms_type = ift2ifm(p->kif.media_type);
- if (ifms_type != 0)
- printf(", %s, %s",
- get_media_descr(ifms_type),
- get_linkstate(ifms_type,
- p->kif.link_state));
- if (p->kif.baudrate) {
- printf(", ");
- print_baudrate(p->kif.baudrate);
- }
- }
}
printf("\n");
break;
Index: bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.242
diff -u -p -r1.242 bgpd.h
--- bgpd/bgpd.h 20 Jul 2009 15:03:16 -0000 1.242
+++ bgpd/bgpd.h 22 Jul 2009 11:48:34 -0000
@@ -437,10 +437,13 @@ struct pftable_msg {
struct ctl_show_nexthop {
struct bgpd_addr addr;
- struct bgpd_addr gateway;
struct kif kif;
+ union {
+ struct kroute kr4;
+ struct kroute6 kr6;
+ } kr;
u_int8_t valid;
- u_int8_t connected;
+ u_int8_t krvalid;;
};
struct ctl_neighbor {
Index: bgpd/kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.170
diff -u -p -r1.170 kroute.c
--- bgpd/kroute.c 20 Jul 2009 15:03:16 -0000 1.170
+++ bgpd/kroute.c 22 Jul 2009 11:46:53 -0000
@@ -587,26 +587,17 @@ kr_show_route(struct imsg *imsg)
case AF_INET:
kr = h->kroute;
snh.valid = kroute_validate(&kr->r);
- snh.connected =
- kr->r.flags & F_CONNECTED;
- if ((snh.gateway.v4.s_addr =
- kr->r.nexthop.s_addr) != 0)
- snh.gateway.af = AF_INET;
+ snh.krvalid = 1;
+ memcpy(&snh.kr.kr4, &kr->r,
+ sizeof(snh.kr.kr4));
ifindex = kr->r.ifindex;
break;
case AF_INET6:
kr6 = h->kroute;
snh.valid = kroute6_validate(&kr6->r);
- snh.connected =
- kr6->r.flags & F_CONNECTED;
- if (memcmp(&kr6->r.nexthop,
- &in6addr_any,
- sizeof(struct in6_addr)) != 0) {
- snh.gateway.af = AF_INET6;
- memcpy(&snh.gateway.v6,
- &kr6->r.nexthop,
- sizeof(struct in6_addr));
- }
+ snh.krvalid = 1;
+ memcpy(&snh.kr.kr6, &kr6->r,
+ sizeof(snh.kr.kr6));
ifindex = kr6->r.ifindex;
break;
}