This is a work-in-progress diff that I would like to commit. I can print a few things, but there is a problem when trying to bring in more fields. Printing is also ugly, but I can fix that in-tree.
While here, I print the descr's as ints, the same way Juniper does it. I also had to add RTM_INVALIDATE, to keep the ordering correct. Am I tying this into route(8) and rtsock.c correctly? OK? Index: sbin/route/route.c =================================================================== RCS file: /cvs/openbsd/src/sbin/route/route.c,v retrieving revision 1.190 diff -u -p -u -p -r1.190 route.c --- sbin/route/route.c 4 Sep 2016 09:41:03 -0000 1.190 +++ sbin/route/route.c 14 Sep 2016 10:20:04 -0000 @@ -41,6 +41,10 @@ #include <netinet/in.h> #include <netmpls/mpls.h> +#include <sys/task.h> +#include <sys/timeout.h> +#include <net/bfd.h> + #include <arpa/inet.h> #include <netdb.h> @@ -90,6 +94,7 @@ void sodump(sup, char *); char *priorityname(uint8_t); uint8_t getpriority(char *); void print_getmsg(struct rt_msghdr *, int); +void print_bfdmsg(struct bfd_msghdr *); const char *get_linkstate(int, int); void print_rtmsg(struct rt_msghdr *, int); void pmsg_common(struct rt_msghdr *); @@ -1240,6 +1245,7 @@ char *msgtypes[] = { "RTM_IFINFO: iface status change", "RTM_IFANNOUNCE: iface arrival/departure", "RTM_DESYNC: route socket overflow", + "RTM_INVALIDATE: invalidate cache of L2 route", "RTM_BFD: bidirectional forwarding detection", }; @@ -1277,6 +1283,7 @@ print_rtmsg(struct rt_msghdr *rtm, int m struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct if_announcemsghdr *ifan; + struct bfd_msghdr *bfd; char ifname[IF_NAMESIZE]; if (verbose == 0) @@ -1333,7 +1340,9 @@ print_rtmsg(struct rt_msghdr *rtm, int m printf("\n"); break; case RTM_BFD: - printf("bfd\n"); /* XXX - expand*/ + bfd = (struct bfd_msghdr *)rtm; + printf(", BFD "); + print_bfdmsg(bfd); break; default: printf(", priority %d, table %u, ifidx %u, ", @@ -1524,6 +1533,48 @@ print_getmsg(struct rt_msghdr *rtm, int putchar('\n'); } #undef RTA_IGN +} + +void +print_bfdmsg(struct bfd_msghdr *bfd) +{ + printf("mode "); + switch (bfd->mode) { + case BFD_MODE_ASYNC: + printf("ASYNC"); + break; + case BFD_MODE_DEMAND: + printf("DEMAND"); + break; + } + printf(" state "); + switch (bfd->state) { + case BFD_STATE_ADMINDOWN: + printf("AdminDown"); + break; + case BFD_STATE_DOWN: + printf("Down"); + break; + case BFD_STATE_INIT: + printf("Init"); + break; + case BFD_STATE_UP: + printf("Up"); + break; + } + printf(" error %d", bfd->error); + printf(" localdiscr %u", bfd->localdiscr); + printf(" remotediscr %u", bfd->remotediscr); + printf(" localdiag %u", bfd->localdiag); + printf(" remotediag %u", bfd->remotediag); + printf(" uptime %lld", bfd->uptime); + printf(" lastuptime %lld", bfd->lastuptime); + + printf(" mintx %ums", bfd->mintx / 1000); + printf(" minrx %ums", bfd->minrx / 1000); + printf(" multiplier %ux", bfd->multiplier); + + printf("\n"); } void Index: sys/net/bfd.c =================================================================== RCS file: /cvs/openbsd/src/sys/net/bfd.c,v retrieving revision 1.24 diff -u -p -u -p -r1.24 bfd.c --- sys/net/bfd.c 13 Sep 2016 07:56:05 -0000 1.24 +++ sys/net/bfd.c 14 Sep 2016 10:48:39 -0000 @@ -161,7 +161,7 @@ struct bfd_state { uint32_t AuthSeqKnown; }; -struct pool bfd_pool, bfd_pool_peer, bfd_pool_time; +struct pool bfd_pool, bfd_pool_peer, bfd_pool_time, bfd_pool_msghdr; struct taskq *bfdtq; struct socket *bfd_listener(struct bfd_softc *, unsigned int); @@ -182,6 +182,7 @@ void bfd_senddown(struct bfd_softc *); void bfd_reset(struct bfd_softc *); void bfd_set_uptime(struct bfd_softc *); +void bfd_prepmsg(struct bfd_softc *); void bfd_debug(struct bfd_softc *); TAILQ_HEAD(bfd_queue, bfd_softc) bfd_queue; @@ -224,9 +225,38 @@ bfd_rtalloc(struct rtentry *rt) TAILQ_INSERT_TAIL(&bfd_queue, sc, bfd_next); + bfd_prepmsg(sc); return (0); } +void +bfd_prepmsg(struct bfd_softc *sc) +{ + struct bfd_msghdr *bfd; + + bfd = pool_get(&bfd_pool_msghdr, PR_WAITOK | PR_ZERO); + + bfd->mode = sc->mode; + bfd->mintx = sc->mintx; + bfd->minrx = sc->minrx; + bfd->multiplier = sc->multiplier; + + bfd->uptime = sc->sc_time->tv_sec; + bfd->lastuptime = sc->lastuptime; + bfd->state = sc->state; + bfd->laststate = sc->laststate; + bfd->error = sc->error; + + bfd->localdiscr = sc->sc_peer->LocalDiscr; + bfd->localdiag = sc->sc_peer->LocalDiag; + bfd->remotediscr = sc->sc_peer->RemoteDiscr; + bfd->remotediag = sc->sc_peer->RemoteDiag; + + bfd_msg(bfd); + + pool_put(&bfd_pool, bfd); +} + /* * remove and free a bfd session */ @@ -283,6 +313,9 @@ bfdinit(void) pool_init(&bfd_pool_time, sizeof(struct timeval), 0, 0, 0, "bfd_softc_time", NULL); pool_setipl(&bfd_pool_time, IPL_SOFTNET); + pool_init(&bfd_pool_msghdr, sizeof(struct bfd_msghdr), 0, 0, 0, + "bfd_msghdr", NULL); + pool_setipl(&bfd_pool_msghdr, IPL_SOFTNET); bfdtq = taskq_create("bfd", 1, IPL_SOFTNET, 0); if (bfdtq == NULL) @@ -306,6 +339,7 @@ bfddestroy(void) } taskq_destroy(bfdtq); + pool_destroy(&bfd_pool_msghdr); pool_destroy(&bfd_pool_time); pool_destroy(&bfd_pool_peer); pool_destroy(&bfd_pool); @@ -376,6 +410,7 @@ bfd_send_task(void *arg) bfd_set_state(sc, BFD_STATE_DOWN); } } +bfd_prepmsg(sc); /* re-add 70%-90% jitter to our transmits, rfc 5880 6.8.7 */ timeout_add_usec(&sc->sc_timo_tx, @@ -873,7 +908,7 @@ bfd_set_state(struct bfd_softc *sc, int } printf("%s: BFD set linkstate %u (oldstate: %u)\n", ifp->if_xname, new_state, state); - rt_sendmsg(rt, new_state, ifp->if_rdomain); + bfd_prepmsg(sc); if_put(ifp); @@ -970,8 +1005,8 @@ bfd_debug(struct bfd_softc *sc) printf("local diag: %u ", sc->sc_peer->LocalDiag); printf("\n"); printf("\t"); - printf("remote discriminator: 0x%x ", sc->sc_peer->RemoteDiscr); - printf("local discriminator: 0x%x ", sc->sc_peer->LocalDiscr); + printf("remote discriminator: %u ", sc->sc_peer->RemoteDiscr); + printf("local discriminator: %u ", sc->sc_peer->LocalDiscr); printf("\n"); printf("\t"); printf("remote session state: %u ", sc->sc_peer->RemoteSessionState); Index: sys/net/route.h =================================================================== RCS file: /cvs/openbsd/src/sys/net/route.h,v retrieving revision 1.147 diff -u -p -u -p -r1.147 route.h --- sys/net/route.h 4 Sep 2016 10:32:01 -0000 1.147 +++ sys/net/route.h 14 Sep 2016 09:09:29 -0000 @@ -356,6 +356,7 @@ struct mbuf; struct socket; struct ifnet; struct sockaddr_in6; +struct bfd_msghdr; void route_init(void); int route_output(struct mbuf *, ...); @@ -363,6 +364,7 @@ int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct proc *); void rt_ifmsg(struct ifnet *); void rt_ifannouncemsg(struct ifnet *, int); +void bfd_msg(struct bfd_msghdr *); void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); struct sockaddr *rt_plen2mask(struct rtentry *, struct sockaddr_in6 *); Index: sys/net/rtsock.c =================================================================== RCS file: /cvs/openbsd/src/sys/net/rtsock.c,v retrieving revision 1.204 diff -u -p -u -p -r1.204 rtsock.c --- sys/net/rtsock.c 7 Sep 2016 09:36:49 -0000 1.204 +++ sys/net/rtsock.c 14 Sep 2016 13:37:04 -0000 @@ -1100,6 +1100,9 @@ rt_msg1(int type, struct rt_addrinfo *rt case RTM_IFANNOUNCE: len = sizeof(struct if_announcemsghdr); break; + case RTM_BFD: + len = sizeof(struct bfd_msghdr); + break; default: len = sizeof(struct rt_msghdr); break; @@ -1329,6 +1332,27 @@ rt_ifannouncemsg(struct ifnet *ifp, int ifan->ifan_index = ifp->if_index; strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name)); ifan->ifan_what = what; + route_proto.sp_protocol = 0; + route_input(m, &route_proto, &route_src, &route_dst); +} + +void +bfd_msg(struct bfd_msghdr *bfd0) +{ + struct bfd_msghdr *bfd; + struct mbuf *m; + + if (route_cb.any_count == 0) + return; + m = rt_msg1(RTM_BFD, NULL); + if (m == NULL) + return; + bfd = mtod(m, struct bfd_msghdr *); + + bfd->mode = bfd0->mode; + bfd->localdiscr = bfd0->localdiscr; + bfd->state = bfd0->state; + route_proto.sp_protocol = 0; route_input(m, &route_proto, &route_src, &route_dst); } -- The algorithm to do that is extremely nasty. You might want to mug someone with it. -- M. Devine, Computer Science 340