When an interface loses link, we delete all directly connected and
cloned routes. However, this means we also lose any BFD configuration
on those routes.
Surviving link-down is pretty much mandatory for BFD to work.
So instead, I bypass the route deletion, and clean up the link-local
gateway information.
$ arp -n | grep 203.0.113.9
203.0.113.9 (incomplete) em1 expired
$ netstat -rnf inet | grep 203.0.113.9
203.0.113.9 link#2 HLcF 2 53 - 3 em1
OK?
Index: sys/net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.347
diff -u -p -u -p -r1.347 route.c
--- sys/net/route.c 20 Jan 2017 08:10:54 -0000 1.347
+++ sys/net/route.c 24 Jan 2017 01:32:23 -0000
@@ -1760,13 +1760,28 @@ rt_if_linkstate_change(struct rtentry *r
* new routes from a better source.
*/
if (ISSET(rt->rt_flags, RTF_CLONED|RTF_DYNAMIC) &&
- !ISSET(rt->rt_flags, RTF_CACHED)) {
+ !ISSET(rt->rt_flags, RTF_CACHED)
+#ifdef BFD
+ && !ISSET(rt->rt_flags, RTF_BFD)
+#endif
+ ) {
int error;
if ((error = rtdeletemsg(rt, ifp, id)))
return (error);
return (EAGAIN);
}
+#ifdef BFD
+ if (ISSET(rt->rt_flags, RTF_BFD) &&
+ ISSET(rt->rt_flags, RTF_CLONED) &&
+ (rt->rt_gateway->sa_family == AF_LINK)) {
+ struct sockaddr_dl *sdl;
+ sdl = (struct sockaddr_dl *)rt->rt_gateway;
+ memset(sdl->sdl_data, 0, sdl->sdl_alen);
+ sdl->sdl_alen = 0;
+ rt->rt_expire = time_uptime;
+ }
+#endif
/* take route down */
rt->rt_flags &= ~RTF_UP;
rtable_mpath_reprio(id, rt_key(rt),
--
Show me a man who is a good loser and I'll show you a man who is
playing golf with his boss.