When running something like: bgpctl show rib | head -5 bgpctl will exit quickly but bgpd will still do the full table walk, sending imsg from RDE to SE and then the SE will drop them since the connection to bgpctl died. In most cases this is not a big deal but for the show rib commands a lot of work is done for nothing.
Introduce IMSG_CTL_TERMINATE and use it for those bgpctl commands that are using rde_dump_ctx_new() to walk the RIB. When the RDE gets a IMSG_CTL_TERMINATE command it will terminate the RIB walker. Noticed and requested by job@ -- :wq Claudio Index: bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.357 diff -u -p -r1.357 bgpd.h --- bgpd.h 11 Dec 2018 09:02:14 -0000 1.357 +++ bgpd.h 19 Dec 2018 15:34:09 -0000 @@ -437,6 +437,7 @@ enum imsg_type { IMSG_CTL_SHOW_TIMER, IMSG_CTL_LOG_VERBOSE, IMSG_CTL_SHOW_FIB_TABLES, + IMSG_CTL_TERMINATE, IMSG_NETWORK_ADD, IMSG_NETWORK_ASPATH, IMSG_NETWORK_ATTR, Index: control.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/control.c,v retrieving revision 1.91 diff -u -p -r1.91 control.c --- control.c 28 Nov 2018 08:32:27 -0000 1.91 +++ control.c 19 Dec 2018 15:38:20 -0000 @@ -188,6 +188,9 @@ control_close(int fd) return (0); } + if (c->terminate && c->ibuf.pid) + imsg_ctl_rde(IMSG_CTL_TERMINATE, c->ibuf.pid, NULL, 0); + msgbuf_clear(&c->ibuf.w); TAILQ_REMOVE(&ctl_conns, c, entry); @@ -247,12 +250,12 @@ control_dispatch_msg(struct pollfd *pfd, case IMSG_CTL_SHOW_NEIGHBOR: case IMSG_CTL_SHOW_NEXTHOP: case IMSG_CTL_SHOW_INTERFACE: - case IMSG_CTL_SHOW_RIB: - case IMSG_CTL_SHOW_RIB_PREFIX: case IMSG_CTL_SHOW_RIB_MEM: - case IMSG_CTL_SHOW_NETWORK: case IMSG_CTL_SHOW_TERSE: case IMSG_CTL_SHOW_TIMER: + case IMSG_CTL_SHOW_NETWORK: + case IMSG_CTL_SHOW_RIB: + case IMSG_CTL_SHOW_RIB_PREFIX: break; default: /* clear imsg type to prevent processing */ @@ -459,14 +462,17 @@ control_dispatch_msg(struct pollfd *pfd, break; } c->ibuf.pid = imsg.hdr.pid; + c->terminate = 1; imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); } else log_warnx("got IMSG_CTL_SHOW_RIB with " "wrong length"); break; - case IMSG_CTL_SHOW_RIB_MEM: case IMSG_CTL_SHOW_NETWORK: + c->terminate = 1; + /* FALLTHROUGH */ + case IMSG_CTL_SHOW_RIB_MEM: c->ibuf.pid = imsg.hdr.pid; imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); @@ -511,6 +517,10 @@ control_imsg_relay(struct imsg *imsg) if ((c = control_connbypid(imsg->hdr.pid)) == NULL) return (0); + + /* if command finished no need to send exit message */ + if (imsg->hdr.type == IMSG_CTL_END || imsg->hdr.type == IMSG_CTL_RESULT) + c->terminate = 0; if (!c->throttled && c->ibuf.w.queued > CTL_MSG_HIGH_MARK) { if (imsg_ctl_rde(IMSG_XOFF, imsg->hdr.pid, NULL, 0) != -1) Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.452 diff -u -p -r1.452 rde.c --- rde.c 11 Dec 2018 09:02:14 -0000 1.452 +++ rde.c 19 Dec 2018 15:33:55 -0000 @@ -71,7 +71,8 @@ void rde_reflector(struct rde_peer *, void rde_dump_ctx_new(struct ctl_show_rib_request *, pid_t, enum imsg_type); -void rde_dump_ctx_throttle(pid_t pid, int throttle); +void rde_dump_ctx_throttle(pid_t, int); +void rde_dump_ctx_terminate(pid_t); void rde_dump_mrt_new(struct mrt *, pid_t, int); int rde_rdomain_import(struct rde_aspath *, struct rdomain *); @@ -133,7 +134,7 @@ int softreconfig; struct rde_dump_ctx { LIST_ENTRY(rde_dump_ctx) entry; struct ctl_show_rib_request req; - sa_family_t af; + u_int16_t rid; u_int8_t throttled; }; @@ -658,6 +659,9 @@ badnetdel: rde_dump_ctx_throttle(imsg.hdr.pid, 1); } break; + case IMSG_CTL_TERMINATE: + rde_dump_ctx_terminate(imsg.hdr.pid); + break; default: break; } @@ -2320,6 +2324,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req memcpy(&ctx->req, req, sizeof(struct ctl_show_rib_request)); ctx->req.pid = pid; ctx->req.type = type; + ctx->rid = rid; switch (ctx->req.type) { case IMSG_CTL_SHOW_NETWORK: if (rib_dump_new(rid, ctx->req.aid, CTL_MSG_HIGH_MARK, ctx, @@ -2363,7 +2368,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req free(ctx); return; default: - fatalx("rde_dump_ctx_new: unsupported imsg type"); + fatalx("%s: unsupported imsg type", __func__); } LIST_INSERT_HEAD(&rde_dump_h, ctx, entry); } @@ -2376,6 +2381,33 @@ rde_dump_ctx_throttle(pid_t pid, int thr LIST_FOREACH(ctx, &rde_dump_h, entry) { if (ctx->req.pid == pid) { ctx->throttled = throttle; + return; + } + } +} + +void +rde_dump_ctx_terminate(pid_t pid) +{ + struct rde_dump_ctx *ctx; + + LIST_FOREACH(ctx, &rde_dump_h, entry) { + if (ctx->req.pid == pid) { + void (*upcall)(struct rib_entry *, void *); + switch (ctx->req.type) { + case IMSG_CTL_SHOW_NETWORK: + upcall = network_dump_upcall; + break; + case IMSG_CTL_SHOW_RIB: + upcall = rde_dump_upcall; + break; + case IMSG_CTL_SHOW_RIB_PREFIX: + upcall = rde_dump_prefix_upcall; + break; + default: + fatalx("%s: unsupported imsg type", __func__); + } + rib_dump_terminate(ctx->rid, ctx, upcall); return; } } Index: session.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/session.h,v retrieving revision 1.125 diff -u -p -r1.125 session.h --- session.h 24 Oct 2018 08:26:37 -0000 1.125 +++ session.h 19 Dec 2018 15:38:03 -0000 @@ -143,6 +143,7 @@ struct ctl_conn { struct imsgbuf ibuf; int restricted; int throttled; + int terminate; }; TAILQ_HEAD(ctl_conns, ctl_conn) ctl_conns;