From dd3b9a80516716eb7d3616a923f2076c1f1589de Mon Sep 17 00:00:00 2001 From: sthen Date: Wed, 21 Jun 2023 09:47:03 +0000 Subject: [PATCH] add "fib reload" support to ospf6d/ospf6ctl, and trigger it automatically on a timeout after RTM_DESYNC (i.e. route socket overflow). ported across from ospfd. fixes/ok claudio@ (it's much harder to overflow the routing socket buffer these days since it was bumped to 2MB, but still happens occasionally on a busy machine). --- usr.sbin/ospf6ctl/ospf6ctl.8 | 7 ++- usr.sbin/ospf6ctl/ospf6ctl.c | 8 ++- usr.sbin/ospf6ctl/parser.c | 3 +- usr.sbin/ospf6ctl/parser.h | 3 +- usr.sbin/ospf6d/control.c | 3 +- usr.sbin/ospf6d/kroute.c | 108 +++++++++++++++++++++++++++++++---- usr.sbin/ospf6d/ospf6.h | 6 +- usr.sbin/ospf6d/ospf6d.c | 5 +- usr.sbin/ospf6d/ospf6d.h | 4 +- 9 files changed, 128 insertions(+), 19 deletions(-) diff --git a/usr.sbin/ospf6ctl/ospf6ctl.8 b/usr.sbin/ospf6ctl/ospf6ctl.8 index 5cf5e52d76c..f07408f1996 100644 --- a/usr.sbin/ospf6ctl/ospf6ctl.8 +++ b/usr.sbin/ospf6ctl/ospf6ctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ospf6ctl.8,v 1.13 2023/03/02 17:09:53 jmc Exp $ +.\" $OpenBSD: ospf6ctl.8,v 1.14 2023/06/21 09:47:03 sthen Exp $ .\" .\" Copyright (c) 2004, 2005, 2007 Esben Norby .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 2 2023 $ +.Dd $Mdocdate: June 21 2023 $ .Dt OSPF6CTL 8 .Os .Sh NAME @@ -58,6 +58,9 @@ Remove the learned routes from the FIB. Decoupling the FIB from an OSPF router may create routing loops and could cause major routing issues in the complete OSPF cloud. Only routers with just one link to the OSPF cloud can safely decouple the FIB. +.It Cm fib reload +Refetches and relearns the routes in the Forwarding Information Base +a.k.a. the kernel routing table. .It Cm log brief Disable verbose debug logging. .It Cm log verbose diff --git a/usr.sbin/ospf6ctl/ospf6ctl.c b/usr.sbin/ospf6ctl/ospf6ctl.c index af034dcb925..488ac927ea6 100644 --- a/usr.sbin/ospf6ctl/ospf6ctl.c +++ b/usr.sbin/ospf6ctl/ospf6ctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6ctl.c,v 1.53 2022/12/27 12:11:39 claudio Exp $ */ +/* $OpenBSD: ospf6ctl.c,v 1.54 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2005 Claudio Jeker @@ -225,6 +225,11 @@ main(int argc, char *argv[]) printf("decouple request sent.\n"); done = 1; break; + case FIB_RELOAD: + imsg_compose(ibuf, IMSG_CTL_FIB_RELOAD, 0, 0, -1, NULL, 0); + printf("reload request sent.\n"); + done = 1; + break; case LOG_VERBOSE: verbose = 1; /* FALLTHROUGH */ @@ -304,6 +309,7 @@ main(int argc, char *argv[]) case FIB: case FIB_COUPLE: case FIB_DECOUPLE: + case FIB_RELOAD: case LOG_VERBOSE: case LOG_BRIEF: case RELOAD: diff --git a/usr.sbin/ospf6ctl/parser.c b/usr.sbin/ospf6ctl/parser.c index a23bd44d6e8..5f91a6c5eeb 100644 --- a/usr.sbin/ospf6ctl/parser.c +++ b/usr.sbin/ospf6ctl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.14 2019/05/26 09:27:09 remi Exp $ */ +/* $OpenBSD: parser.c,v 1.15 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2004 Esben Norby @@ -73,6 +73,7 @@ static const struct token t_main[] = { static const struct token t_fib[] = { { KEYWORD, "couple", FIB_COUPLE, NULL}, { KEYWORD, "decouple", FIB_DECOUPLE, NULL}, + { KEYWORD, "reload", FIB_RELOAD, NULL}, { ENDTOKEN, "", NONE, NULL} }; diff --git a/usr.sbin/ospf6ctl/parser.h b/usr.sbin/ospf6ctl/parser.h index b5bf971419b..7fc50f8c7c0 100644 --- a/usr.sbin/ospf6ctl/parser.h +++ b/usr.sbin/ospf6ctl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.9 2019/05/26 09:27:09 remi Exp $ */ +/* $OpenBSD: parser.h,v 1.10 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2004 Esben Norby @@ -29,6 +29,7 @@ enum actions { FIB, FIB_COUPLE, FIB_DECOUPLE, + FIB_RELOAD, LOG_VERBOSE, LOG_BRIEF, SHOW, diff --git a/usr.sbin/ospf6d/control.c b/usr.sbin/ospf6d/control.c index 2bb656c1df7..c83a8a51fb6 100644 --- a/usr.sbin/ospf6d/control.c +++ b/usr.sbin/ospf6d/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.31 2023/03/08 04:43:14 guenther Exp $ */ +/* $OpenBSD: control.c,v 1.32 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -279,6 +279,7 @@ control_dispatch_imsg(int fd, short event, void *bula) case IMSG_CTL_FIB_DECOUPLE: ospfe_fib_update(imsg.hdr.type); /* FALLTHROUGH */ + case IMSG_CTL_FIB_RELOAD: case IMSG_CTL_RELOAD: c->iev.ibuf.pid = imsg.hdr.pid; ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); diff --git a/usr.sbin/ospf6d/kroute.c b/usr.sbin/ospf6d/kroute.c index a7d2491a9a1..28ca7fac800 100644 --- a/usr.sbin/ospf6d/kroute.c +++ b/usr.sbin/ospf6d/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.67 2023/03/08 04:43:14 guenther Exp $ */ +/* $OpenBSD: kroute.c,v 1.68 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2004 Esben Norby @@ -45,16 +45,23 @@ struct { u_int32_t rtseq; pid_t pid; int fib_sync; + int fib_serial; u_int8_t fib_prio; int fd; struct event ev; + struct event reload; u_int rdomain; +#define KR_RELOAD_IDLE 0 +#define KR_RELOAD_FETCH 1 +#define KR_RELOAD_HOLD 2 + int reload_state; } kr_state; struct kroute_node { RB_ENTRY(kroute_node) entry; struct kroute_node *next; struct kroute r; + int serial; }; void kr_redist_remove(struct kroute_node *, struct kroute_node *); @@ -90,7 +97,10 @@ void if_announce(void *); int send_rtmsg(int, int, struct kroute *); int dispatch_rtmsg(void); int fetchtable(void); -int rtmsg_process(char *, size_t); +int refetchtable(void); +int rtmsg_process(char *, size_t); +void kr_fib_reload_timer(int, short, void *); +void kr_fib_reload_arm_timer(int); RB_HEAD(kroute_tree, kroute_node) krt; RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) @@ -165,6 +175,9 @@ kr_init(int fs, u_int rdomain, int redis_label_or_prefix, u_int8_t fib_prio) kr_dispatch_msg, NULL); event_add(&kr_state.ev, NULL); + kr_state.reload_state = KR_RELOAD_IDLE; + evtimer_set(&kr_state.reload, kr_fib_reload_timer, NULL); + return (0); } @@ -373,6 +386,64 @@ kr_fib_decouple(void) log_info("kernel routing table decoupled"); } +void +kr_fib_reload_timer(int fd, short event, void *bula) +{ + if (kr_state.reload_state == KR_RELOAD_FETCH) { + kr_fib_reload(); + kr_state.reload_state = KR_RELOAD_HOLD; + kr_fib_reload_arm_timer(KR_RELOAD_HOLD_TIMER); + } else { + kr_state.reload_state = KR_RELOAD_IDLE; + } +} + +void +kr_fib_reload_arm_timer(int delay) +{ + struct timeval tv; + + timerclear(&tv); + tv.tv_sec = delay / 1000; + tv.tv_usec = (delay % 1000) * 1000; + + if (evtimer_add(&kr_state.reload, &tv) == -1) + fatal("add_reload_timer"); +} + +void +kr_fib_reload(void) +{ + struct kroute_node *krn, *kr, *kn; + + log_info("reloading interface list and routing table"); + + kr_state.fib_serial++; + + if (fetchifs(0) != 0 || fetchtable() != 0) + return; + + for (kr = RB_MIN(kroute_tree, &krt); kr != NULL; kr = krn) { + krn = RB_NEXT(kroute_tree, &krt, kr); + + do { + kn = kr->next; + + if (kr->serial != kr_state.fib_serial) { + + if (kr->r.priority == kr_state.fib_prio) { + kr->serial = kr_state.fib_serial; + if (send_rtmsg(kr_state.fd, + RTM_ADD, &kr->r) != 0) + break; + } else + kroute_remove(kr); + } + + } while ((kr = kn) != NULL); + } +} + void kr_fib_update_prio(u_int8_t fib_prio) { @@ -664,6 +735,8 @@ kroute_insert(struct kroute_node *kr) { struct kroute_node *krm, *krh; + kr->serial = kr_state.fib_serial; + if ((krh = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { /* * Multipath route, add at end of list. @@ -1279,7 +1352,7 @@ rtmsg_process(char *buf, size_t len) int flags, mpath; unsigned int scope; u_short ifindex = 0; - int rv; + int rv, delay; size_t offset; char *next; @@ -1395,13 +1468,10 @@ rtmsg_process(char *buf, size_t len) if ((okr = kroute_find(&prefix, prefixlen, prio)) != NULL) { - /* just add new multipath routes */ - if (mpath && rtm->rtm_type == RTM_ADD) - goto add; - /* get the correct route */ kr = okr; - if (mpath && (kr = kroute_matchgw(okr, - &nexthop, scope)) == NULL) { + if ((mpath || prio == kr_state.fib_prio) && + (kr = kroute_matchgw(okr, &nexthop, scope)) == + NULL) { log_warnx("rtmsg_process: mpath route" " not found"); /* add routes we missed out earlier */ @@ -1432,7 +1502,8 @@ rtmsg_process(char *buf, size_t len) kr->r.flags |= F_DOWN; /* just readd, the RDE will care */ - kr_redistribute(okr); + kr->serial = kr_state.fib_serial; + kr_redistribute(kr); } else { add: if ((kr = calloc(1, @@ -1518,6 +1589,23 @@ add: case RTM_IFANNOUNCE: if_announce(next); break; + case RTM_DESYNC: + /* + * We lost some routing packets. Schedule a reload + * of the kernel route/interface information. + */ + if (kr_state.reload_state == KR_RELOAD_IDLE) { + delay = KR_RELOAD_TIMER; + log_info("desync; scheduling fib reload"); + } else { + delay = KR_RELOAD_HOLD_TIMER; + log_debug("desync during KR_RELOAD_%s", + kr_state.reload_state == + KR_RELOAD_FETCH ? "FETCH" : "HOLD"); + } + kr_state.reload_state = KR_RELOAD_FETCH; + kr_fib_reload_arm_timer(delay); + break; default: /* ignore for now */ break; diff --git a/usr.sbin/ospf6d/ospf6.h b/usr.sbin/ospf6d/ospf6.h index 296fe1ff339..b75a64a316d 100644 --- a/usr.sbin/ospf6d/ospf6.h +++ b/usr.sbin/ospf6d/ospf6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6.h,v 1.21 2013/03/25 14:29:35 markus Exp $ */ +/* $OpenBSD: ospf6.h,v 1.22 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2004, 2005, 2007 Esben Norby @@ -69,6 +69,10 @@ #define MIN_SPF_HOLDTIME 1 #define MAX_SPF_HOLDTIME 5 +/* msec */ +#define KR_RELOAD_TIMER 250 +#define KR_RELOAD_HOLD_TIMER 5000 + #define MIN_MD_ID 0 #define MAX_MD_ID 255 diff --git a/usr.sbin/ospf6d/ospf6d.c b/usr.sbin/ospf6d/ospf6d.c index a85f8771c0a..224d6cd5b1f 100644 --- a/usr.sbin/ospf6d/ospf6d.c +++ b/usr.sbin/ospf6d/ospf6d.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6d.c,v 1.53 2023/03/08 04:43:14 guenther Exp $ */ +/* $OpenBSD: ospf6d.c,v 1.54 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2005 Claudio Jeker @@ -372,6 +372,9 @@ main_dispatch_ospfe(int fd, short event, void *bula) case IMSG_CTL_FIB_DECOUPLE: kr_fib_decouple(); break; + case IMSG_CTL_FIB_RELOAD: + kr_fib_reload(); + break; case IMSG_CTL_KROUTE: case IMSG_CTL_KROUTE_ADDR: kr_show_route(&imsg); diff --git a/usr.sbin/ospf6d/ospf6d.h b/usr.sbin/ospf6d/ospf6d.h index e9233b6484e..a8f2a929ebc 100644 --- a/usr.sbin/ospf6d/ospf6d.h +++ b/usr.sbin/ospf6d/ospf6d.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6d.h,v 1.50 2021/01/19 09:46:51 claudio Exp $ */ +/* $OpenBSD: ospf6d.h,v 1.51 2023/06/21 09:47:03 sthen Exp $ */ /* * Copyright (c) 2004, 2007 Esben Norby @@ -93,6 +93,7 @@ enum imsg_type { IMSG_CTL_SHOW_SUM_AREA, IMSG_CTL_FIB_COUPLE, IMSG_CTL_FIB_DECOUPLE, + IMSG_CTL_FIB_RELOAD, IMSG_CTL_AREA, IMSG_CTL_IFACE, IMSG_CTL_KROUTE, @@ -546,6 +547,7 @@ int kr_delete(struct kroute *); void kr_shutdown(void); void kr_fib_couple(void); void kr_fib_decouple(void); +void kr_fib_reload(void); void kr_fib_update_prio(u_int8_t); void kr_dispatch_msg(int, short, void *); void kr_show_route(struct imsg *); -- 2.20.1