In bgpd there are a few objects that use reference counts to keep track on how many things point to them. Those are struct pt_entry, rde_aspath, rde_communities, and nexthop. The way this reference counting is done and especially the cleanup is a bit different everywhere. This diff is making them more similar by calling all functions _ref and _unref also the _unref function will remove the element once the last reference is dropped. There are still some internal differences but all in all for the callers this makes the code look a lot more similar.
OK? -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.474 diff -u -p -r1.474 rde.c --- rde.c 25 Jun 2019 09:04:42 -0000 1.474 +++ rde.c 25 Jun 2019 09:05:27 -0000 @@ -1353,7 +1353,7 @@ rde_update_dispatch(struct imsg *imsg) } /* unlock the previously locked nexthop, it is no longer used */ - (void)nexthop_put(state.nexthop); + nexthop_unref(state.nexthop); state.nexthop = NULL; if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, &state)) == -1) { log_peer_warnx(&peer->conf, "bad nlri nexthop"); @@ -1653,7 +1653,7 @@ bad_flags: op, len); return (-1); } - nexthop_put(state->nexthop); /* just to be sure */ + nexthop_unref(state->nexthop); /* just to be sure */ state->nexthop = nexthop_get(&nexthop); break; case ATTR_MED: @@ -2015,7 +2015,7 @@ rde_get_mp_nexthop(u_char *data, u_int16 return (-1); } - nexthop_put(state->nexthop); /* just to be sure */ + nexthop_unref(state->nexthop); /* just to be sure */ state->nexthop = nexthop_get(&nexthop); /* ignore reserved (old SNPA) field as per RFC4760 */ Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.218 diff -u -p -r1.218 rde.h --- rde.h 24 Jun 2019 06:39:49 -0000 1.218 +++ rde.h 25 Jun 2019 09:05:27 -0000 @@ -423,7 +423,7 @@ void communities_copy(struct rde_commun void communities_clean(struct rde_community *); static inline struct rde_community * -communities_get(struct rde_community *comm) +communities_ref(struct rde_community *comm) { if (comm->refcnt == 0) fatalx("%s: not-referenced community", __func__); @@ -433,12 +433,12 @@ communities_get(struct rde_community *co } static inline void -communities_put(struct rde_community *comm) +communities_unref(struct rde_community *comm) { if (comm == NULL) return; rdemem.comm_refs--; - if (--comm->refcnt == 1) + if (--comm->refcnt == 1) /* last ref is hold internally */ communities_unlink(comm); } @@ -460,11 +460,15 @@ int rde_filter_equal(struct filter_hea void rde_filter_calc_skip_steps(struct filter_head *); /* rde_prefix.c */ -static inline int -pt_empty(struct pt_entry *pt) -{ - return (pt->refcnt == 0); -} +void pt_init(void); +void pt_shutdown(void); +void pt_getaddr(struct pt_entry *, struct bgpd_addr *); +struct pt_entry *pt_fill(struct bgpd_addr *, int); +struct pt_entry *pt_get(struct bgpd_addr *, int); +struct pt_entry *pt_add(struct bgpd_addr *, int); +void pt_remove(struct pt_entry *); +struct pt_entry *pt_lookup(struct bgpd_addr *); +int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); static inline struct pt_entry * pt_ref(struct pt_entry *pt) @@ -475,25 +479,15 @@ pt_ref(struct pt_entry *pt) return pt; } -static inline int +static inline void pt_unref(struct pt_entry *pt) { if (pt->refcnt == 0) fatalx("pt_unref: underflow"); - --pt->refcnt; - return pt_empty(pt); + if (--pt->refcnt == 0) + pt_remove(pt); } -void pt_init(void); -void pt_shutdown(void); -void pt_getaddr(struct pt_entry *, struct bgpd_addr *); -struct pt_entry *pt_fill(struct bgpd_addr *, int); -struct pt_entry *pt_get(struct bgpd_addr *, int); -struct pt_entry *pt_add(struct bgpd_addr *, int); -void pt_remove(struct pt_entry *); -struct pt_entry *pt_lookup(struct bgpd_addr *); -int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); - /* rde_rib.c */ extern u_int16_t rib_size; extern struct rib_desc *ribs; @@ -608,7 +602,7 @@ void nexthop_unlink(struct prefix *); void nexthop_update(struct kroute_nexthop *); struct nexthop *nexthop_get(struct bgpd_addr *); struct nexthop *nexthop_ref(struct nexthop *); -int nexthop_put(struct nexthop *); +int nexthop_unref(struct nexthop *); int nexthop_compare(struct nexthop *, struct nexthop *); /* rde_update.c */ Index: rde_filter.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v retrieving revision 1.120 diff -u -p -r1.120 rde_filter.c --- rde_filter.c 22 Jun 2019 05:44:05 -0000 1.120 +++ rde_filter.c 25 Jun 2019 09:05:27 -0000 @@ -444,7 +444,7 @@ rde_filterstate_clean(struct filterstate { path_clean(&state->aspath); communities_clean(&state->communities); - nexthop_put(state->nexthop); + nexthop_unref(state->nexthop); state->nexthop = NULL; } @@ -481,7 +481,7 @@ filterset_free(struct filter_set_head *s pftable_unref(s->action.id); else if (s->type == ACTION_SET_NEXTHOP && bgpd_process == PROC_RDE) - nexthop_put(s->action.nh); + nexthop_unref(s->action.nh); free(s); } } Index: rde_prefix.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_prefix.c,v retrieving revision 1.38 diff -u -p -r1.38 rde_prefix.c --- rde_prefix.c 15 Feb 2019 09:55:21 -0000 1.38 +++ rde_prefix.c 25 Jun 2019 09:05:27 -0000 @@ -188,7 +188,7 @@ pt_add(struct bgpd_addr *prefix, int pre void pt_remove(struct pt_entry *pte) { - if (!pt_empty(pte)) + if (pte->refcnt != 0) fatalx("pt_remove: entry still holds references"); if (RB_REMOVE(pt_tree, &pttable, pte) == NULL) Index: rde_rib.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v retrieving revision 1.195 diff -u -p -r1.195 rde_rib.c --- rde_rib.c 22 Jun 2019 05:44:05 -0000 1.195 +++ rde_rib.c 25 Jun 2019 09:05:27 -0000 @@ -62,11 +62,11 @@ struct rib_context { }; LIST_HEAD(, rib_context) rib_dumps = LIST_HEAD_INITIALIZER(rib_dumps); -static int prefix_add(struct bgpd_addr *, int, struct rib *, +static int prefix_add(struct bgpd_addr *, int, struct rib *, struct rde_peer *, struct rde_aspath *, struct rde_community *, struct nexthop *, u_int8_t, u_int8_t); -static int prefix_move(struct prefix *, struct rde_peer *, +static int prefix_move(struct prefix *, struct rde_peer *, struct rde_aspath *, struct rde_community *, struct nexthop *, u_int8_t, u_int8_t); @@ -326,8 +326,7 @@ rib_remove(struct rib_entry *re) /* entry is locked, don't free it. */ return; - if (pt_unref(re->prefix)) - pt_remove(re->prefix); + pt_unref(re->prefix); if (RB_REMOVE(rib_tree, rib_tree(re_rib(re)), re) == NULL) log_warnx("rib_remove: remove failed."); @@ -501,12 +500,6 @@ SIPHASH_KEY pathtablekey; #define PATH_HASH(x) &pathtable.path_hashtbl[x & pathtable.path_hashmask] -static inline int -path_empty(struct rde_aspath *asp) -{ - return (asp == NULL || asp->refcnt <= 0); -} - static inline struct rde_aspath * path_ref(struct rde_aspath *asp) { @@ -521,10 +514,14 @@ path_ref(struct rde_aspath *asp) static inline void path_unref(struct rde_aspath *asp) { + if (asp == NULL) + return; if ((asp->flags & F_ATTR_LINKED) == 0) fatalx("%s: unlinked object", __func__); asp->refcnt--; rdemem.path_refs--; + if (asp->refcnt <= 0) + path_unlink(asp); } void @@ -765,8 +762,8 @@ path_unlink(struct rde_aspath *asp) return; /* make sure no reference is hold for this rde_aspath */ - if (!path_empty(asp)) - fatalx("%s: still has prefixes", __func__); + if (asp->refcnt != 0) + fatalx("%s: still holds references", __func__); LIST_REMOVE(asp, path_l); asp->flags &= ~F_ATTR_LINKED; @@ -938,7 +935,7 @@ prefix_move(struct prefix *p, struct rde np = prefix_alloc(); /* add reference to new AS path and communities */ np->aspath = path_ref(asp); - np->communities = communities_get(comm); + np->communities = communities_ref(comm); np->peer = peer; np->pt = p->pt; /* skip refcnt update since ref is moved */ np->re = p->re; @@ -970,10 +967,9 @@ prefix_move(struct prefix *p, struct rde /* destroy all references to other objects and free the old prefix */ nexthop_unlink(p); - nexthop_put(p->nexthop); - communities_put(p->communities); - if (oasp) - path_unref(oasp); + nexthop_unref(p->nexthop); + communities_unref(p->communities); + path_unref(oasp); p->communities = NULL; p->nexthop = NULL; p->aspath = NULL; @@ -982,10 +978,6 @@ prefix_move(struct prefix *p, struct rde p->pt = NULL; prefix_free(p); - /* destroy old path if empty */ - if (path_empty(oasp)) - path_unlink(oasp); - return (0); } @@ -1061,28 +1053,22 @@ prefix_withdraw(struct rib *rib, struct struct bgpd_addr *prefix, int prefixlen) { struct prefix *p; - struct rde_aspath *asp; p = prefix_get(rib, peer, prefix, prefixlen); if (p == NULL) /* Got a dummy withdrawn request. */ return (0); /* unlink from aspath ...*/ - asp = p->aspath; - if (asp != NULL) { - path_unref(asp); - p->aspath = NULL; - if (path_empty(asp)) - path_unlink(asp); - } + path_unref(p->aspath); + p->aspath = NULL; /* ... communities ... */ - communities_put(p->communities); + communities_unref(p->communities); p->communities = NULL; /* ... and nexthop but keep the re link */ nexthop_unlink(p); - nexthop_put(p->nexthop); + nexthop_unref(p->nexthop); p->nexthop = NULL; p->nhflags = 0; /* re link still exists */ @@ -1271,14 +1257,8 @@ prefix_updateall(struct prefix *p, enum void prefix_destroy(struct prefix *p) { - struct rde_aspath *asp; - - asp = prefix_aspath(p); prefix_unlink(p); prefix_free(p); - - if (path_empty(asp)) - path_unlink(asp); } /* @@ -1290,7 +1270,7 @@ prefix_link(struct prefix *p, struct rib struct nexthop *nexthop, u_int8_t nhflags, u_int8_t vstate) { p->aspath = path_ref(asp); - p->communities = communities_get(comm); + p->communities = communities_ref(comm); p->peer = peer; p->pt = pt_ref(re->prefix); p->re = re; @@ -1321,12 +1301,10 @@ prefix_unlink(struct prefix *p) /* destroy all references to other objects */ nexthop_unlink(p); - nexthop_put(p->nexthop); - communities_put(p->communities); - if (p->aspath) - path_unref(p->aspath); - if (pt_unref(p->pt)) - pt_remove(p->pt); + nexthop_unref(p->nexthop); + communities_unref(p->communities); + path_unref(p->aspath); + pt_unref(p->pt); p->communities = NULL; p->nexthop = NULL; p->aspath = NULL; @@ -1418,7 +1396,7 @@ nexthop_shutdown(void) nh != NULL; nh = nnh) { nnh = LIST_NEXT(nh, nexthop_l); nh->state = NEXTHOP_UNREACH; - (void)nexthop_put(nh); + nexthop_unref(nh); } if (!LIST_EMPTY(&nexthoptable.nexthop_hashtbl[i])) { nh = LIST_FIRST(&nexthoptable.nexthop_hashtbl[i]); @@ -1481,7 +1459,7 @@ nexthop_update(struct kroute_nexthop *ms nh->oldstate = nh->state; if (nh->oldstate == NEXTHOP_LOOKUP) /* drop reference which was hold during the lookup */ - if (nexthop_put(nh)) + if (nexthop_unref(nh)) return; /* nh lost last ref, no work left */ if (nh->next_prefix) { @@ -1546,7 +1524,7 @@ nexthop_modify(struct nexthop *setnh, en */ if (aid != setnh->exit_nexthop.aid) break; - nexthop_put(*nexthop); + nexthop_unref(*nexthop); *nexthop = nexthop_ref(setnh); *flags = 0; break; @@ -1617,11 +1595,10 @@ nexthop_ref(struct nexthop *nexthop) } int -nexthop_put(struct nexthop *nh) +nexthop_unref(struct nexthop *nh) { if (nh == NULL) return (0); - if (--nh->refcnt > 0) return (0);