As mentioned I need a TAILQ for the list of prefixes that belong to a rib entry. Mainly because I need TAILQ_PREV. This diff does this replacement. I did not change the nexhtop LIST of prefixes to a TAILQ. Maybe something to consider but there is no real need for that.
This is mostly a mechanical change. The only thing that had to change is rde_softreconfig_sync_reeval() where before the LIST_HEAD was copied which is not possible with TAILQ (there is a pointer to the TAILQ_HEAD struct from inside the TAILQ). Instead use TAILQ_CONCAT() to move the queue from the rib_entry to the local tailq head. I checked the rest of the code and did not find any other case where the rib_entry prefix_h was copied around. I also have a fix for the unittest regress ready for this change. I left that one out since it is just a trivial mechanical change. -- :wq Claudio Index: mrt.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/mrt.c,v retrieving revision 1.106 diff -u -p -r1.106 mrt.c --- mrt.c 6 Feb 2022 09:51:19 -0000 1.106 +++ mrt.c 21 Mar 2022 17:51:09 -0000 @@ -620,7 +620,7 @@ mrt_dump_entry_v2_rib(struct rib_entry * *np = 0; *app = 0; - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { struct nexthop *nexthop; struct bgpd_addr *nh; struct ibuf *tbuf; @@ -895,7 +895,7 @@ mrt_dump_upcall(struct rib_entry *re, vo * dumps the table so we do the same. If only the active route should * be dumped p should be set to p = pt->active. */ - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { if (mrtbuf->type == MRT_TABLE_DUMP) mrt_dump_entry(mrtbuf, p, mrtbuf->seqnum++, prefix_peer(p)); Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.543 diff -u -p -r1.543 rde.c --- rde.c 21 Mar 2022 17:35:56 -0000 1.543 +++ rde.c 21 Mar 2022 17:41:29 -0000 @@ -2536,7 +2536,7 @@ rde_dump_upcall(struct rib_entry *re, vo struct rde_dump_ctx *ctx = ptr; struct prefix *p; - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) rde_dump_filter(p, &ctx->req, 0); } @@ -2557,14 +2557,14 @@ rde_dump_prefix_upcall(struct rib_entry return; if (!prefix_compare(&ctx->req.prefix, &addr, ctx->req.prefixlen)) - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) rde_dump_filter(p, &ctx->req, 0); } else { if (ctx->req.prefixlen < pt->prefixlen) return; if (!prefix_compare(&addr, &ctx->req.prefix, pt->prefixlen)) - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) rde_dump_filter(p, &ctx->req, 0); } } @@ -3673,7 +3673,7 @@ rde_softreconfig_in(struct rib_entry *re pt = re->prefix; pt_getaddr(pt, &prefix); - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { asp = prefix_aspath(p); peer = prefix_peer(p); @@ -3736,7 +3736,7 @@ rde_softreconfig_out(struct rib_entry *r static void rde_softreconfig_sync_reeval(struct rib_entry *re, void *arg) { - struct prefix_list prefixes; + struct prefix_queue prefixes = TAILQ_HEAD_INITIALIZER(prefixes); struct prefix *p, *next; struct rib *rib = arg; @@ -3746,7 +3746,7 @@ rde_softreconfig_sync_reeval(struct rib_ * all dependent adj-rib-out were already flushed * unlink nexthop if it was linked */ - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { if (p->flags & PREFIX_NEXTHOP_LINKED) nexthop_unlink(p); } @@ -3754,8 +3754,7 @@ rde_softreconfig_sync_reeval(struct rib_ } /* evaluation process is turned on, so evaluate all prefixes again */ - prefixes = re->prefix_h; - LIST_INIT(&re->prefix_h); + TAILQ_CONCAT(&prefixes, &re->prefix_h, entry.list.rib); /* * TODO: this code works but is not optimal. prefix_evaluate() @@ -3763,9 +3762,9 @@ rde_softreconfig_sync_reeval(struct rib_ * to resort the list once and then call rde_generate_updates() * and rde_send_kroute() once. */ - LIST_FOREACH_SAFE(p, &prefixes, entry.list.rib, next) { + TAILQ_FOREACH_SAFE(p, &prefixes, entry.list.rib, next) { /* need to re-link the nexthop if not already linked */ - LIST_REMOVE(p, entry.list.rib); + TAILQ_REMOVE(&prefixes, p, entry.list.rib); if ((p->flags & PREFIX_NEXTHOP_LINKED) == 0) nexthop_link(p); prefix_evaluate(re, p, NULL); @@ -3818,7 +3817,7 @@ rde_roa_softreload(struct rib_entry *re, pt = re->prefix; pt_getaddr(pt, &prefix); - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { asp = prefix_aspath(p); peer = prefix_peer(p); @@ -4163,7 +4162,7 @@ network_dump_upcall(struct rib_entry *re struct bgpd_addr addr; struct rde_dump_ctx *ctx = ptr; - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) { + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) { asp = prefix_aspath(p); if (!(asp->flags & F_PREFIX_ANNOUNCED)) continue; Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.250 diff -u -p -r1.250 rde.h --- rde.h 21 Mar 2022 17:35:56 -0000 1.250 +++ rde.h 21 Mar 2022 17:40:10 -0000 @@ -38,11 +38,12 @@ enum peer_state { }; LIST_HEAD(prefix_list, prefix); +TAILQ_HEAD(prefix_queue, prefix); RB_HEAD(rib_tree, rib_entry); struct rib_entry { RB_ENTRY(rib_entry) rib_e; - struct prefix_list prefix_h; + struct prefix_queue prefix_h; struct pt_entry *prefix; uint16_t rib_id; uint16_t lock; @@ -315,7 +316,8 @@ struct pt_entry_vpn6 { struct prefix { union { struct { - LIST_ENTRY(prefix) rib, nexthop; + TAILQ_ENTRY(prefix) rib; + LIST_ENTRY(prefix) nexthop; struct rib_entry *re; } list; struct { Index: rde_decide.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.90 diff -u -p -r1.90 rde_decide.c --- rde_decide.c 21 Mar 2022 17:35:56 -0000 1.90 +++ rde_decide.c 21 Mar 2022 17:50:37 -0000 @@ -301,16 +301,16 @@ prefix_cmp(struct prefix *p1, struct pre void prefix_insert(struct prefix *new, struct prefix *ep, struct rib_entry *re) { - struct prefix_list redo = LIST_HEAD_INITIALIZER(redo); - struct prefix *xp, *np, *tailp = NULL, *insertp = ep; + struct prefix_queue redo = TAILQ_HEAD_INITIALIZER(redo); + struct prefix *xp, *np, *insertp = ep; int testall, selected = 0; /* start scan at the entry point (ep) or the head if ep == NULL */ if (ep == NULL) - ep = LIST_FIRST(&re->prefix_h); + ep = TAILQ_FIRST(&re->prefix_h); for (xp = ep; xp != NULL; xp = np) { - np = LIST_NEXT(xp, entry.list.rib); + np = TAILQ_NEXT(xp, entry.list.rib); if (prefix_cmp(new, xp, &testall) > 0) { /* new is preferred over xp */ @@ -321,14 +321,8 @@ prefix_insert(struct prefix *new, struct * MED inversion, take out prefix and * put it onto redo queue. */ - LIST_REMOVE(xp, entry.list.rib); - if (tailp == NULL) - LIST_INSERT_HEAD(&redo, xp, - entry.list.rib); - else - LIST_INSERT_AFTER(tailp, xp, - entry.list.rib); - tailp = xp; + TAILQ_REMOVE(&re->prefix_h, xp, entry.list.rib); + TAILQ_INSERT_TAIL(&redo, xp, entry.list.rib); } else { /* * lock insertion point and @@ -355,14 +349,14 @@ prefix_insert(struct prefix *new, struct } if (insertp == NULL) - LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); + TAILQ_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); else - LIST_INSERT_AFTER(insertp, new, entry.list.rib); + TAILQ_INSERT_AFTER(&re->prefix_h, insertp, new, entry.list.rib); /* Fixup MED order again. All elements are < new */ - while (!LIST_EMPTY(&redo)) { - xp = LIST_FIRST(&redo); - LIST_REMOVE(xp, entry.list.rib); + while (!TAILQ_EMPTY(&redo)) { + xp = TAILQ_FIRST(&redo); + TAILQ_REMOVE(&redo, xp, entry.list.rib); prefix_insert(xp, new, re); } @@ -380,18 +374,18 @@ prefix_insert(struct prefix *new, struct void prefix_remove(struct prefix *old, struct rib_entry *re) { - struct prefix_list redo = LIST_HEAD_INITIALIZER(redo); - struct prefix *xp, *np, *tailp = NULL; + struct prefix_queue redo = TAILQ_HEAD_INITIALIZER(redo); + struct prefix *xp, *np; int testall; - xp = LIST_NEXT(old, entry.list.rib); - LIST_REMOVE(old, entry.list.rib); + xp = TAILQ_NEXT(old, entry.list.rib); + TAILQ_REMOVE(&re->prefix_h, old, entry.list.rib); /* check if a MED inversion could be possible */ prefix_cmp(old, xp, &testall); if (testall > 0) { /* maybe MED route, scan tail for other possible routes */ for (; xp != NULL; xp = np) { - np = LIST_NEXT(xp, entry.list.rib); + np = TAILQ_NEXT(xp, entry.list.rib); /* only interested in the testall result */ prefix_cmp(old, xp, &testall); @@ -402,22 +396,16 @@ prefix_remove(struct prefix *old, struct * possible MED inversion, take out prefix and * put it onto redo queue. */ - LIST_REMOVE(xp, entry.list.rib); - if (tailp == NULL) - LIST_INSERT_HEAD(&redo, xp, - entry.list.rib); - else - LIST_INSERT_AFTER(tailp, xp, - entry.list.rib); - tailp = xp; + TAILQ_REMOVE(&re->prefix_h, xp, entry.list.rib); + TAILQ_INSERT_HEAD(&redo, xp, entry.list.rib); } } } /* Fixup MED order again, reinsert prefixes from the start */ - while (!LIST_EMPTY(&redo)) { - xp = LIST_FIRST(&redo); - LIST_REMOVE(xp, entry.list.rib); + while (!TAILQ_EMPTY(&redo)) { + xp = TAILQ_FIRST(&redo); + TAILQ_REMOVE(&redo, xp, entry.list.rib); prefix_insert(xp, NULL, re); } @@ -454,7 +442,7 @@ prefix_best(struct rib_entry *re) /* decision process is turned off */ return NULL; - xp = LIST_FIRST(&re->prefix_h); + xp = TAILQ_FIRST(&re->prefix_h); if (xp != NULL && !prefix_eligible(xp)) xp = NULL; return xp; @@ -477,9 +465,9 @@ prefix_evaluate(struct rib_entry *re, st if (rib->flags & F_RIB_NOEVALUATE) { /* decision process is turned off */ if (old != NULL) - LIST_REMOVE(old, entry.list.rib); + TAILQ_REMOVE(&re->prefix_h, old, entry.list.rib); if (new != NULL) - LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); + TAILQ_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); return; } @@ -491,7 +479,7 @@ prefix_evaluate(struct rib_entry *re, st if (new != NULL) prefix_insert(new, NULL, re); - xp = LIST_FIRST(&re->prefix_h); + xp = TAILQ_FIRST(&re->prefix_h); if (xp != NULL && !prefix_eligible(xp)) xp = NULL; Index: rde_peer.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_peer.c,v retrieving revision 1.14 diff -u -p -r1.14 rde_peer.c --- rde_peer.c 21 Mar 2022 17:35:56 -0000 1.14 +++ rde_peer.c 21 Mar 2022 17:52:23 -0000 @@ -248,7 +248,7 @@ peer_flush_upcall(struct rib_entry *re, pt_getaddr(re->prefix, &addr); prefixlen = re->prefix->prefixlen; - LIST_FOREACH_SAFE(p, &re->prefix_h, entry.list.rib, np) { + TAILQ_FOREACH_SAFE(p, &re->prefix_h, entry.list.rib, np) { if (peer != prefix_peer(p)) continue; if (staletime && p->lastchange > staletime) Index: rde_rib.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v retrieving revision 1.236 diff -u -p -r1.236 rde_rib.c --- rde_rib.c 21 Mar 2022 17:35:56 -0000 1.236 +++ rde_rib.c 21 Mar 2022 17:43:17 -0000 @@ -252,7 +252,7 @@ rib_free(struct rib *rib) * an empty check in prefix_destroy() it is not possible to * use the default for loop. */ - while ((p = LIST_FIRST(&re->prefix_h))) { + while ((p = TAILQ_FIRST(&re->prefix_h))) { struct rde_aspath *asp = prefix_aspath(p); if (asp && asp->pftableid) rde_pftable_del(asp->pftableid, p); @@ -353,7 +353,7 @@ rib_add(struct rib *rib, struct bgpd_add if ((re = calloc(1, sizeof(*re))) == NULL) fatal("rib_add"); - LIST_INIT(&re->prefix_h); + TAILQ_INIT(&re->prefix_h); re->prefix = pt_ref(pte); re->rib_id = rib->id; @@ -391,7 +391,7 @@ rib_remove(struct rib_entry *re) int rib_empty(struct rib_entry *re) { - return LIST_EMPTY(&re->prefix_h); + return TAILQ_EMPTY(&re->prefix_h); } static struct rib_entry * @@ -1496,7 +1496,7 @@ prefix_bypeer(struct rib_entry *re, stru { struct prefix *p; - LIST_FOREACH(p, &re->prefix_h, entry.list.rib) + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) if (prefix_peer(p) == peer && p->path_id == path_id) return (p); return (NULL); Index: rde_update.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v retrieving revision 1.137 diff -u -p -r1.137 rde_update.c --- rde_update.c 15 Mar 2022 16:50:29 -0000 1.137 +++ rde_update.c 21 Mar 2022 17:51:39 -0000 @@ -154,7 +154,7 @@ again: prefixlen, prefix_vstate(new), &state) == ACTION_DENY) { rde_filterstate_clean(&state); if (peer->flags & PEERFLAG_EVALUATE_ALL) - new = LIST_NEXT(new, entry.list.rib); + new = TAILQ_NEXT(new, entry.list.rib); else new = NULL; if (new != NULL && !prefix_eligible(new))