On Sat, Mar 21, 2020 at 05:25:45PM +0100, Denis Fondras wrote: > Biggest chunk is rework of rde_asext_get()/rde_asext_put(). > Also change get_net_link() and get_rtr_link() to work like ospfd couterpart.
Reads good to me and I didn't spot any issues running tests with it. One question: why "if 0" the "Dump SPF tree to log"? > > Index: rde.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/rde.c,v > retrieving revision 1.84 > diff -u -p -r1.84 rde.c > --- rde.c 17 Feb 2020 08:12:22 -0000 1.84 > +++ rde.c 21 Mar 2020 16:04:47 -0000 > @@ -59,8 +59,9 @@ int rde_req_list_exists(struct rde_nbr > void rde_req_list_del(struct rde_nbr *, struct lsa_hdr *); > void rde_req_list_free(struct rde_nbr *); > > -struct lsa *rde_asext_get(struct kroute *); > -struct lsa *rde_asext_put(struct kroute *); > +struct iface *rde_asext_lookup(struct in6_addr, int); > +void rde_asext_get(struct kroute *); > +void rde_asext_put(struct kroute *); > > int comp_asext(struct lsa *, struct lsa *); > struct lsa *orig_asext_lsa(struct kroute *, u_int16_t); > @@ -217,6 +218,7 @@ __dead void > rde_shutdown(void) > { > struct area *a; > + struct vertex *v, *nv; > > /* close pipes */ > msgbuf_clear(&iev_ospfe->ibuf.w); > @@ -232,6 +234,10 @@ rde_shutdown(void) > LIST_REMOVE(a, entry); > area_del(a); > } > + for (v = RB_MIN(lsa_tree, &asext_tree); v != NULL; v = nv) { > + nv = RB_NEXT(lsa_tree, &asext_tree, v); > + vertex_free(v); > + } > rde_nbr_free(); > > free(iev_ospfe); > @@ -643,8 +649,6 @@ rde_dispatch_parent(int fd, short event, > struct kroute kr; > struct imsgev *iev = bula; > struct imsgbuf *ibuf = &iev->ibuf; > - struct lsa *lsa; > - struct vertex *v; > ssize_t n; > int shut = 0, link_ok, prev_link_ok, orig_lsa; > unsigned int ifindex; > @@ -676,13 +680,7 @@ rde_dispatch_parent(int fd, short event, > break; > } > memcpy(&kr, imsg.data, sizeof(kr)); > - > - if ((lsa = rde_asext_get(&kr)) != NULL) { > - v = lsa_find(NULL, lsa->hdr.type, > - lsa->hdr.ls_id, lsa->hdr.adv_rtr); > - > - lsa_merge(nbrself, lsa, v); > - } > + rde_asext_get(&kr); > break; > case IMSG_NETWORK_DEL: > if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { > @@ -691,20 +689,7 @@ rde_dispatch_parent(int fd, short event, > break; > } > memcpy(&kr, imsg.data, sizeof(kr)); > - > - if ((lsa = rde_asext_put(&kr)) != NULL) { > - v = lsa_find(NULL, lsa->hdr.type, > - lsa->hdr.ls_id, lsa->hdr.adv_rtr); > - > - /* > - * if v == NULL no LSA is in the table and > - * nothing has to be done. > - */ > - if (v) > - lsa_merge(nbrself, lsa, v); > - else > - free(lsa); > - } > + rde_asext_put(&kr); > break; > case IMSG_IFINFO: > if (imsg.hdr.len != IMSG_HEADER_SIZE + > @@ -1202,48 +1187,77 @@ rde_req_list_free(struct rde_nbr *nbr) > /* > * as-external LSA handling > */ > -struct lsa * > -rde_asext_get(struct kroute *kr) > +struct iface * > +rde_asext_lookup(struct in6_addr prefix, int plen) > { > + > struct area *area; > struct iface *iface; > struct iface_addr *ia; > - struct in6_addr addr; > - > - LIST_FOREACH(area, &rdeconf->area_list, entry) > - LIST_FOREACH(iface, &area->iface_list, entry) > + struct in6_addr ina, inb; > + > + LIST_FOREACH(area, &rdeconf->area_list, entry) { > + LIST_FOREACH(iface, &area->iface_list, entry) { > TAILQ_FOREACH(ia, &iface->ifa_list, entry) { > if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) > continue; > > - inet6applymask(&addr, &ia->addr, > - kr->prefixlen); > - if (!memcmp(&addr, &kr->prefix, > - sizeof(addr)) && kr->prefixlen == > - ia->prefixlen) { > - /* already announced as Prefix LSA */ > - log_debug("rde_asext_get: %s/%d is " > - "part of prefix LSA", > - log_in6addr(&kr->prefix), > - kr->prefixlen); > - return (NULL); > - } > + inet6applymask(&ina, &ia->addr, ia->prefixlen); > + inet6applymask(&inb, &prefix, ia->prefixlen); > + if (IN6_ARE_ADDR_EQUAL(&ina, &inb) && > + (plen == -1 || plen == ia->prefixlen)) > + return (iface); > } > + } > + } > + return (NULL); > +} > + > +void > +rde_asext_get(struct kroute *kr) > +{ > + struct vertex *v; > + struct lsa *lsa; > + > + if (rde_asext_lookup(kr->prefix, kr->prefixlen)) { > + /* already announced as (stub) net LSA */ > + log_debug("rde_asext_get: %s/%d is net LSA", > + log_in6addr(&kr->prefix), kr->prefixlen); > + return; > + } > > /* update of seqnum is done by lsa_merge */ > - return (orig_asext_lsa(kr, DEFAULT_AGE)); > + if ((lsa = orig_asext_lsa(kr, DEFAULT_AGE))) { > + v = lsa_find(NULL, lsa->hdr.type, lsa->hdr.ls_id, > + lsa->hdr.adv_rtr); > + lsa_merge(nbrself, lsa, v); > + } > } > > -struct lsa * > +void > rde_asext_put(struct kroute *kr) > { > + struct vertex *v; > + struct lsa *lsa; > /* > * just try to remove the LSA. If the prefix is announced as > * stub net LSA lsa_find() will fail later and nothing will happen. > */ > > /* remove by reflooding with MAX_AGE */ > - return (orig_asext_lsa(kr, MAX_AGE)); > + if ((lsa = orig_asext_lsa(kr, MAX_AGE))) { > + v = lsa_find(NULL, lsa->hdr.type, lsa->hdr.ls_id, > + lsa->hdr.adv_rtr); > + > + /* > + * if v == NULL no LSA is in the table and > + * nothing has to be done. > + */ > + if (v) > + lsa_merge(nbrself, lsa, v); > + else > + free(lsa); > + } > } > > /* > @@ -1706,8 +1720,7 @@ orig_asext_lsa(struct kroute *kr, u_int1 > } > > lsa->hdr.ls_chksum = 0; > - lsa->hdr.ls_chksum = > - htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); > + lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); > > return (lsa); > } > Index: rde_spf.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/rde_spf.c,v > retrieving revision 1.26 > diff -u -p -r1.26 rde_spf.c > --- rde_spf.c 22 Dec 2019 11:19:07 -0000 1.26 > +++ rde_spf.c 21 Mar 2020 16:04:47 -0000 > @@ -44,10 +44,11 @@ void calc_nexthop(struct vertex *, str > struct area *, struct lsa_rtr_link *); > void rt_nexthop_clear(struct rt_node *); > void rt_nexthop_add(struct rt_node *, struct v_nexthead *, > - struct in_addr); > + u_int16_t, struct in_addr); > void rt_update(struct in6_addr *, u_int8_t, struct v_nexthead *, > - u_int32_t, u_int32_t, struct in_addr, struct in_addr, > - enum path_type, enum dst_type, u_int8_t, u_int32_t); > + u_int16_t, u_int32_t, u_int32_t, struct in_addr, > + struct in_addr, enum path_type, enum dst_type, u_int8_t, > + u_int32_t); > struct rt_node *rt_lookup(enum dst_type, struct in6_addr *); > void rt_invalidate(struct area *); > int linked(struct vertex *, struct vertex *); > @@ -167,6 +168,7 @@ spf_calc(struct area *area) > /* spf_dump(area); */ > log_debug("spf_calc: area %s calculated", inet_ntoa(area->id)); > > +#if 0 > /* Dump SPF tree to log */ > RB_FOREACH(v, lsa_tree, &area->lsa_tree) { > struct v_nexthop *vn; > @@ -191,6 +193,7 @@ spf_calc(struct area *area) > v == spf_root ? "*" : " ", log_rtr_id(htonl(v->adv_rtr)), > v->type, log_rtr_id(htonl(v->ls_id)), v->cost, hops); > } > +#endif > > area->num_spf_calc++; > start_spf_timer(); > @@ -225,7 +228,7 @@ rt_calc(struct vertex *v, struct area *a > adv_rtr.s_addr = htonl(v->adv_rtr); > bcopy(&adv_rtr, &ia6.s6_addr[12], sizeof(adv_rtr)); > > - rt_update(&ia6, 128, &v->nexthop, v->cost, 0, area->id, > + rt_update(&ia6, 128, &v->nexthop, v->type, v->cost, 0, area->id, > adv_rtr, PT_INTER_AREA, DT_RTR, flags, 0); > break; > case LSA_TYPE_INTRA_A_PREFIX: > @@ -279,7 +282,7 @@ rt_calc(struct vertex *v, struct area *a > adv_rtr.s_addr = htonl(w->adv_rtr); > > rt_update(&ia6, prefix->prefixlen, &w->nexthop, > - w->cost + ntohs(prefix->metric), 0, > + v->type, w->cost + ntohs(prefix->metric), 0, > area->id, adv_rtr, PT_INTRA_AREA, DT_NET, > flags, 0); > } > @@ -315,9 +318,10 @@ rt_calc(struct vertex *v, struct area *a > bzero(&ia6, sizeof(ia6)); > bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen)); > > - rt_update(&ia6, prefix->prefixlen, &w->nexthop, w->cost + > - (ntohs(v->lsa->data.rtr_sum.metric) & LSA_METRIC_MASK), 0, > - area->id, adv_rtr, PT_INTER_AREA, DT_NET, 0, 0); > + rt_update(&ia6, prefix->prefixlen, &w->nexthop, v->type, > + w->cost + (ntohs(v->lsa->data.rtr_sum.metric) & > + LSA_METRIC_MASK), 0, area->id, adv_rtr, PT_INTER_AREA, > + DT_NET, 0, 0); > break; > case LSA_TYPE_INTER_A_ROUTER: > /* XXX if ABR only look at area 0.0.0.0 LSA */ > @@ -343,7 +347,7 @@ rt_calc(struct vertex *v, struct area *a > bcopy(&v->lsa->data.rtr_sum.dest_rtr_id, &ia6.s6_addr[12], > 4); > > - rt_update(&ia6, 128, &w->nexthop, w->cost + > + rt_update(&ia6, 128, &w->nexthop, v->type, w->cost + > (ntohs(v->lsa->data.rtr_sum.metric) & LSA_METRIC_MASK), 0, > area->id, adv_rtr, PT_INTER_AREA, DT_RTR, 0, 0); > break; > @@ -434,8 +438,8 @@ asext_calc(struct vertex *v) > rn->ifindex); > } > > - rt_update(&addr, prefix->prefixlen, &v->nexthop, v->cost, cost2, > - area, adv_rtr, type, DT_NET, 0, ext_tag); > + rt_update(&addr, prefix->prefixlen, &v->nexthop, v->type, > + v->cost, cost2, area, adv_rtr, type, DT_NET, 0, ext_tag); > break; > default: > fatalx("asext_calc: invalid LSA type"); > @@ -863,7 +867,7 @@ rt_nexthop_clear(struct rt_node *r) > } > > void > -rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, > +rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int16_t type, > struct in_addr adv_rtr) > { > struct v_nexthop *vn; > @@ -876,7 +880,9 @@ rt_nexthop_add(struct rt_node *r, struct > continue; > > rn->adv_rtr.s_addr = adv_rtr.s_addr; > - rn->connected = vn->prev == spf_root; > + rn->connected = (type == LSA_TYPE_NETWORK && > + vn->prev == spf_root) || > + (IN6_IS_ADDR_UNSPECIFIED(&vn->nexthop)); > rn->invalid = 0; > > r->invalid = 0; > @@ -973,7 +979,7 @@ rt_dump(struct in_addr area, pid_t pid, > > void > rt_update(struct in6_addr *prefix, u_int8_t prefixlen, struct v_nexthead > *vnh, > - u_int32_t cost, u_int32_t cost2, struct in_addr area, > + u_int16_t v_type, u_int32_t cost, u_int32_t cost2, struct in_addr area, > struct in_addr adv_rtr, enum path_type p_type, enum dst_type d_type, > u_int8_t flags, u_int32_t tag) > { > @@ -999,7 +1005,7 @@ rt_update(struct in6_addr *prefix, u_int > rte->flags = flags; > rte->ext_tag = tag; > > - rt_nexthop_add(rte, vnh, adv_rtr); > + rt_nexthop_add(rte, vnh, v_type, adv_rtr); > > rt_insert(rte); > } else { > @@ -1054,7 +1060,7 @@ rt_update(struct in6_addr *prefix, u_int > } > > if (equal || better) > - rt_nexthop_add(rte, vnh, adv_rtr); > + rt_nexthop_add(rte, vnh, v_type, adv_rtr); > } > } > > @@ -1115,7 +1121,7 @@ get_rtr_link(struct vertex *v, unsigned > v = lsa_find_rtr_frag(v->area, htonl(v->adv_rtr), frag++); > } while (v); > > - return (NULL); > + fatalx("get_rtr_link: index not found"); > } > > /* network LSA links */ > @@ -1124,21 +1130,23 @@ get_net_link(struct vertex *v, unsigned > { > struct lsa_net_link *net_link = NULL; > char *buf = (char *)v->lsa; > - unsigned int i; > + unsigned int i, nlinks; > > if (v->type != LSA_TYPE_NETWORK) > fatalx("get_net_link: invalid LSA type"); > > - /* number of links validated earlier by lsa_check() */ > net_link = (struct lsa_net_link *)(buf + sizeof(v->lsa->hdr) + > sizeof(struct lsa_net)); > - for (i = 0; i < lsa_num_links(v); i++) { > + > + /* number of links validated earlier by lsa_check() */ > + nlinks = lsa_num_links(v); > + for (i = 0; i < nlinks; i++) { > if (i == idx) > return (net_link); > net_link++; > } > > - return (NULL); > + fatalx("get_net_link: index not found"); > } > > /* misc */ >