On Tue, Dec 24, 2019 at 10:02:37PM +0100, Denis Fondras wrote: > Refactor link state ack/req in ospf6d so it looks closer to ospfd.
ok remi@ > Index: lsack.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/lsack.c,v > retrieving revision 1.7 > diff -u -p -r1.7 lsack.c > --- lsack.c 11 Dec 2019 21:33:56 -0000 1.7 > +++ lsack.c 24 Dec 2019 20:51:56 -0000 > @@ -19,7 +19,7 @@ > #include <sys/types.h> > #include <sys/socket.h> > #include <netinet/in.h> > -#include <netinet/ip.h> > +#include <netinet/ip6.h> > #include <arpa/inet.h> > > #include <stdlib.h> > @@ -30,39 +30,66 @@ > #include "log.h" > #include "ospfe.h" > > -void start_ls_ack_tx_timer_now(struct iface *); > +int send_ls_ack(struct iface *, struct in6_addr, struct ibuf *); > +struct ibuf *prepare_ls_ack(struct iface *); > +void start_ls_ack_tx_timer_now(struct iface *); > > /* link state acknowledgement packet handling */ > -int > -send_ls_ack(struct iface *iface, struct in6_addr addr, void *data, size_t > len) > +struct ibuf * > +prepare_ls_ack(struct iface *iface) > { > struct ibuf *buf; > - int ret; > > - /* XXX IBUF_READ_SIZE */ > - if ((buf = ibuf_dynamic(PKG_DEF_SIZE, IBUF_READ_SIZE)) == NULL) > - fatal("send_ls_ack"); > + if ((buf = ibuf_open(iface->mtu - sizeof(struct ip6_hdr))) == NULL) { > + log_warn("prepare_ls_ack"); > + return (NULL); > + } > > /* OSPF header */ > - if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK)) > - goto fail; > + if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK)) { > + log_warn("prepare_ls_ack"); > + ibuf_free(buf); > + return (NULL); > + } > > - /* LS ack(s) */ > - if (ibuf_add(buf, data, len)) > - goto fail; > + return (buf); > +} > > +int > +send_ls_ack(struct iface *iface, struct in6_addr addr, struct ibuf *buf) > +{ > /* calculate checksum */ > - if (upd_ospf_hdr(buf, iface)) > - goto fail; > + if (upd_ospf_hdr(buf, iface)) { > + log_warn("send_ls_ack"); > + return (-1); > + } > > - ret = send_packet(iface, buf, &addr); > + if (send_packet(iface, buf, &addr) == -1) { > + log_warn("send_ls_ack"); > + return (-1); > + } > + return (0); > +} > > +int > +send_direct_ack(struct iface *iface, struct in6_addr addr, void *d, size_t > len) > +{ > + struct ibuf *buf; > + int ret; > + > + if ((buf = prepare_ls_ack(iface)) == NULL) > + return (-1); > + > + /* LS ack(s) */ > + if (ibuf_add(buf, d, len)) { > + log_warn("send_direct_ack"); > + ibuf_free(buf); > + return (-1); > + } > + > + ret = send_ls_ack(iface, addr, buf); > ibuf_free(buf); > return (ret); > -fail: > - log_warn("send_ls_ack"); > - ibuf_free(buf); > - return (-1); > } > > void > @@ -207,41 +234,44 @@ ls_ack_tx_timer(int fd, short event, voi > { > struct in6_addr addr; > struct iface *iface = arg; > - struct lsa_hdr *lsa_hdr; > struct lsa_entry *le, *nle; > struct nbr *nbr; > - char *buf; > - char *ptr; > - int cnt = 0; > - > - if ((buf = calloc(1, READ_BUF_SIZE)) == NULL) > - fatal("ls_ack_tx_timer"); > + struct ibuf *buf; > + int cnt; > > while (!ls_ack_list_empty(iface)) { > - ptr = buf; > + if ((buf = prepare_ls_ack(iface)) == NULL) > + fatal("ls_ack_tx_timer"); > cnt = 0; > - for (le = TAILQ_FIRST(&iface->ls_ack_list); le != NULL && > - (ptr - buf < iface->mtu - PACKET_HDR); le = nle) { > + > + for (le = TAILQ_FIRST(&iface->ls_ack_list); le != NULL; > + le = nle) { > nle = TAILQ_NEXT(le, entry); > - memcpy(ptr, le->le_lsa, sizeof(struct lsa_hdr)); > - ptr += sizeof(*lsa_hdr); > + if (ibuf_left(buf) < sizeof(struct lsa_hdr)) > + break; > + if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) > + break; > ls_ack_list_free(iface, le); > cnt++; > } > + if (cnt == 0) { > + log_warnx("ls_ack_tx_timer: lost in space"); > + ibuf_free(buf); > + return; > + } > > /* send LS ack(s) but first set correct destination */ > switch (iface->type) { > case IF_TYPE_POINTOPOINT: > inet_pton(AF_INET6, AllSPFRouters, &addr); > - send_ls_ack(iface, addr, buf, ptr - buf); > + send_ls_ack(iface, addr, buf); > break; > case IF_TYPE_BROADCAST: > if (iface->state & IF_STA_DRORBDR) > inet_pton(AF_INET6, AllSPFRouters, &addr); > else > inet_pton(AF_INET6, AllDRouters, &addr); > - > - send_ls_ack(iface, addr, buf, ptr - buf); > + send_ls_ack(iface, addr, buf); > break; > case IF_TYPE_NBMA: > case IF_TYPE_POINTOMULTIPOINT: > @@ -251,15 +281,14 @@ ls_ack_tx_timer(int fd, short event, voi > continue; > if (!(nbr->state & NBR_STA_FLOOD)) > continue; > - send_ls_ack(iface, nbr->addr, buf, ptr - buf); > + send_ls_ack(iface, nbr->addr, buf); > } > break; > default: > fatalx("lsa_ack_tx_timer: unknown interface type"); > } > + ibuf_free(buf); > } > - > - free(buf); > } > > void > Index: lsreq.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/lsreq.c,v > retrieving revision 1.10 > diff -u -p -r1.10 lsreq.c > --- lsreq.c 11 Dec 2019 21:33:56 -0000 1.10 > +++ lsreq.c 24 Dec 2019 20:51:56 -0000 > @@ -38,7 +38,6 @@ send_ls_req(struct nbr *nbr) > struct ls_req_hdr ls_req_hdr; > struct lsa_entry *le, *nle; > struct ibuf *buf; > - int ret; > > if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip6_hdr))) == NULL) > fatal("send_ls_req"); > @@ -77,10 +76,11 @@ send_ls_req(struct nbr *nbr) > if (upd_ospf_hdr(buf, nbr->iface)) > goto fail; > > - ret = send_packet(nbr->iface, buf, &dst); > + if (send_packet(nbr->iface, buf, &dst) == -1) > + goto fail; > > ibuf_free(buf); > - return (ret); > + return (0); > fail: > log_warn("send_ls_req"); > ibuf_free(buf); > Index: lsupdate.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/lsupdate.c,v > retrieving revision 1.14 > diff -u -p -r1.14 lsupdate.c > --- lsupdate.c 11 Dec 2019 21:33:56 -0000 1.14 > +++ lsupdate.c 24 Dec 2019 20:51:56 -0000 > @@ -37,12 +37,14 @@ > extern struct ospfd_conf *oeconf; > extern struct imsgev *iev_rde; > > -struct ibuf *prepare_ls_update(struct iface *, int); > -int add_ls_update(struct ibuf *, struct iface *, void *, int, u_int16_t); > -int send_ls_update(struct ibuf *, struct iface *, struct in6_addr, > u_int32_t); > +struct ibuf *prepare_ls_update(struct iface *); > +int add_ls_update(struct ibuf *, struct iface *, void *, u_int16_t, > + u_int16_t); > +int send_ls_update(struct ibuf *, struct iface *, struct in6_addr, > + u_int32_t); > > -void ls_retrans_list_insert(struct nbr *, struct lsa_entry *); > -void ls_retrans_list_remove(struct nbr *, struct lsa_entry *); > +void ls_retrans_list_insert(struct nbr *, struct lsa_entry *); > +void ls_retrans_list_remove(struct nbr *, struct lsa_entry *); > > /* link state update packet handling */ > int > @@ -149,27 +151,24 @@ lsa_flood(struct iface *iface, struct nb > } > > struct ibuf * > -prepare_ls_update(struct iface *iface, int bigpkt) > +prepare_ls_update(struct iface *iface) > { > struct ibuf *buf; > - size_t size; > + size_t reserved; > > - size = bigpkt ? IPV6_MAXPACKET : iface->mtu; > - if (size < IPV6_MMTU) > - size = IPV6_MMTU; > - size -= sizeof(struct ip6_hdr); > /* > * Reserve space for optional ah or esp encryption. The > * algorithm is taken from ah_output and esp_output, the > * values are the maxima of crypto/xform.c. > */ > - size -= max( > + reserved = max( > /* base-ah-header replay authsize */ > AH_FLENGTH + sizeof(u_int32_t) + 32, > /* spi sequence ivlen blocksize pad-length next-header authsize */ > 2 * sizeof(u_int32_t) + 16 + 16 + 2 * sizeof(u_int8_t) + 32); > > - if ((buf = ibuf_open(size)) == NULL) > + if ((buf = ibuf_dynamic(IPV6_MMTU - sizeof(struct ip6_hdr) - reserved, > + IPV6_MAXPACKET - sizeof(struct ip6_hdr) - reserved)) == NULL) > fatal("prepare_ls_update"); > > /* OSPF header */ > @@ -188,16 +187,16 @@ fail: > } > > int > -add_ls_update(struct ibuf *buf, struct iface *iface, void *data, int len, > +add_ls_update(struct ibuf *buf, struct iface *iface, void *data, u_int16_t > len, > u_int16_t older) > { > - size_t pos; > - u_int16_t age; > + void *lsage; > + u_int16_t age; > > if (buf->wpos + len >= buf->max) > return (0); > > - pos = buf->wpos; > + lsage = ibuf_reserve(buf, 0); > if (ibuf_add(buf, data, len)) { > log_warn("add_ls_update"); > return (0); > @@ -209,7 +208,7 @@ add_ls_update(struct ibuf *buf, struct i > if ((age += older + iface->transmit_delay) >= MAX_AGE) > age = MAX_AGE; > age = htons(age); > - memcpy(ibuf_seek(buf, pos, sizeof(age)), &age, sizeof(age)); > + memcpy(lsage, &age, sizeof(age)); > > return (1); > } > @@ -218,8 +217,6 @@ int > send_ls_update(struct ibuf *buf, struct iface *iface, struct in6_addr addr, > u_int32_t nlsa) > { > - int ret; > - > nlsa = htonl(nlsa); > memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(nlsa)), > &nlsa, sizeof(nlsa)); > @@ -227,10 +224,11 @@ send_ls_update(struct ibuf *buf, struct > if (upd_ospf_hdr(buf, iface)) > goto fail; > > - ret = send_packet(iface, buf, &addr); > + if (send_packet(iface, buf, &addr) == -1) > + goto fail; > > ibuf_free(buf); > - return (ret); > + return (0); > fail: > log_warn("send_ls_update"); > ibuf_free(buf); > @@ -443,7 +441,7 @@ ls_retrans_timer(int fd, short event, vo > struct lsa_entry *le; > struct ibuf *buf; > time_t now; > - int bigpkt, d; > + int d; > u_int32_t nlsa = 0; > > if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) > @@ -479,17 +477,7 @@ ls_retrans_timer(int fd, short event, vo > } else > memcpy(&addr, &nbr->addr, sizeof(addr)); > > - /* > - * Allow big ipv6 packets that may get fragmented if a > - * single lsa might be too big for an unfragmented packet. > - * To avoid the exact algorithm duplicated here, just make > - * a good guess. If the first lsa is bigger than 1024 > - * bytes, reserve a separate big packet for it. The kernel > - * will figure out if fragmentation is necessary. For > - * smaller lsas, we avoid big packets and fragmentation. > - */ > - bigpkt = le->le_ref->len > 1024; > - if ((buf = prepare_ls_update(nbr->iface, bigpkt)) == NULL) { > + if ((buf = prepare_ls_update(nbr->iface)) == NULL) { > le->le_when = 1; > goto done; > } > @@ -504,18 +492,20 @@ ls_retrans_timer(int fd, short event, vo > > if (add_ls_update(buf, nbr->iface, le->le_ref->data, > le->le_ref->len, d) == 0) { > - if (nlsa) > - break; > - /* > - * A single lsa is too big to fit into an update > - * packet. In this case drop the lsa, otherwise > - * we send empty update packets in an endless loop. > - */ > - log_warnx("ls_retrans_timer: cannot send lsa, dropped"); > - log_debug("ls_retrans_timer: type: %04x len: %u", > - ntohs(le->le_ref->hdr.type), le->le_ref->len); > - ls_retrans_list_free(nbr, le); > - continue; > + if (nlsa == 0) { > + /* something bad happened retry later */ > + log_warnx("ls_retrans_timer: sending LS update " > + "to neighbor ID %s failed", > + inet_ntoa(nbr->id)); > + log_debug("ls_retrans_timer: type: %04x len: > %u", > + ntohs(le->le_ref->hdr.type), > + le->le_ref->len); > + TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry); > + nbr->ls_ret_cnt--; > + le->le_when = nbr->iface->rxmt_interval; > + ls_retrans_list_insert(nbr, le); > + } > + break; > } > nlsa++; > if (le->le_oneshot) > @@ -526,11 +516,11 @@ ls_retrans_timer(int fd, short event, vo > le->le_when = nbr->iface->rxmt_interval; > ls_retrans_list_insert(nbr, le); > } > - /* do not put additional lsa into fragmented big packet */ > - if (bigpkt) > - break; > } > - send_ls_update(buf, nbr->iface, addr, nlsa); > + if (nlsa) > + send_ls_update(buf, nbr->iface, addr, nlsa); > + else > + ibuf_free(buf); > > done: > if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) { > Index: ospfe.c > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/ospfe.c,v > retrieving revision 1.58 > diff -u -p -r1.58 ospfe.c > --- ospfe.c 23 Dec 2019 07:33:49 -0000 1.58 > +++ ospfe.c 24 Dec 2019 20:51:56 -0000 > @@ -699,7 +699,7 @@ ospfe_dispatch_rde(int fd, short event, > break; > > /* send a direct acknowledgement */ > - send_ls_ack(nbr->iface, nbr->addr, imsg.data, > + send_direct_ack(nbr->iface, nbr->addr, imsg.data, > imsg.hdr.len - IMSG_HEADER_SIZE); > > break; > Index: ospfe.h > =================================================================== > RCS file: /cvs/src/usr.sbin/ospf6d/ospfe.h,v > retrieving revision 1.21 > diff -u -p -r1.21 ospfe.h > --- ospfe.h 22 Dec 2019 15:34:52 -0000 1.21 > +++ ospfe.h 24 Dec 2019 20:51:56 -0000 > @@ -149,7 +149,7 @@ int if_set_ipv6_checksum(int); > > /* lsack.c */ > int delay_lsa_ack(struct iface *, struct lsa_hdr *); > -int send_ls_ack(struct iface *, struct in6_addr, void *, size_t); > +int send_direct_ack(struct iface *, struct in6_addr, void *, size_t); > void recv_ls_ack(struct nbr *, char *, u_int16_t); > int lsa_hdr_check(struct nbr *, struct lsa_hdr *); > void ls_ack_list_add(struct iface *, struct lsa_hdr *); >