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; }