When finding an peer id for a new templated host getpeerbyip() uses a rather dumb lookup loop which is super inefficent. Instead it is much better to just use getpeerbyid() and check its return. Also while there don't use the global conf for the peer list but instead use the argument c in all RB functions for all getpeer* functions.
OK? -- :wq Claudio Index: session.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/session.c,v retrieving revision 1.389 diff -u -p -r1.389 session.c --- session.c 12 Aug 2019 14:15:27 -0000 1.389 +++ session.c 13 Aug 2019 08:25:49 -0000 @@ -2894,7 +2894,7 @@ getpeerbydesc(struct bgpd_config *c, con struct peer *p, *res = NULL; int match = 0; - RB_FOREACH(p, peer_head, &conf->peers) + RB_FOREACH(p, peer_head, &c->peers) if (!strcmp(p->conf.descr, descr)) { res = p; match++; @@ -2920,13 +2920,13 @@ getpeerbyip(struct bgpd_config *c, struc sa2addr(ip, &addr, NULL); /* we might want a more effective way to find peers by IP */ - RB_FOREACH(p, peer_head, &conf->peers) + RB_FOREACH(p, peer_head, &c->peers) if (!p->conf.template && !memcmp(&addr, &p->conf.remote_addr, sizeof(addr))) return (p); /* try template matching */ - RB_FOREACH(p, peer_head, &conf->peers) + RB_FOREACH(p, peer_head, &c->peers) if (p->conf.template && p->conf.remote_addr.aid == addr.aid && session_match_mask(p, &addr)) @@ -2940,10 +2940,7 @@ getpeerbyip(struct bgpd_config *c, struc fatal(NULL); memcpy(newpeer, loose, sizeof(struct peer)); for (id = PEER_ID_DYN_MAX; id > PEER_ID_STATIC_MAX; id--) { - RB_FOREACH(p, peer_head, &conf->peers) - if (p->conf.id == id) - break; - if (p == NULL) /* we found a free id */ + if (getpeerbyid(c, id) == NULL) /* we found a free id */ break; } newpeer->template = loose;