The way lsacks were generated always bugged me. I was not happy how the packets were filled. This new version is more like the lsupdate code. This removes another READ_BUF_SIZE and kills the stupid PKG_DEF_SIZE define. In the end nothing should change.
OK? -- :wq Claudio Index: lsack.c =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/lsack.c,v retrieving revision 1.19 diff -u -p -r1.19 lsack.c --- lsack.c 26 May 2010 13:56:08 -0000 1.19 +++ lsack.c 4 Mar 2011 13:57:24 -0000 @@ -31,44 +31,70 @@ #include "log.h" #include "ospfe.h" -void start_ls_ack_tx_timer_now(struct iface *); +int send_ls_ack(struct iface *, struct in_addr, struct ibuf *); +struct ibuf *prepare_ls_ack(struct iface *); +void start_ls_ack_tx_timer_now(struct iface *); /* link state acknowledgement packet handling */ +struct ibuf * +prepare_ls_ack(struct iface *iface) +{ + struct ibuf *buf; + + if ((buf = ibuf_open(iface->mtu - sizeof(struct ip))) == NULL) { + log_warn("prepare_ls_ack"); + return (NULL); + } + + /* OSPF header */ + if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK)) { + log_warn("prepare_ls_ack"); + ibuf_free(buf); + return (NULL); + } + + return (buf); +} + int -send_ls_ack(struct iface *iface, struct in_addr addr, void *data, size_t len) +send_ls_ack(struct iface *iface, struct in_addr addr, struct ibuf *buf) { - struct sockaddr_in dst; - struct ibuf *buf; - int ret; + struct sockaddr_in dst; + int ret; - /* XXX IBUF_READ_SIZE */ - if ((buf = ibuf_dynamic(PKG_DEF_SIZE, READ_BUF_SIZE)) == NULL) - fatal("send_ls_ack"); + /* update authentication and calculate checksum */ + if (auth_gen(buf, iface)) { + log_warn("send_ls_ack"); + return (-1); + } dst.sin_family = AF_INET; dst.sin_len = sizeof(struct sockaddr_in); dst.sin_addr.s_addr = addr.s_addr; - /* OSPF header */ - if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK)) - goto fail; + ret = send_packet(iface, buf, &dst); + return (ret); +} - /* LS ack(s) */ - if (ibuf_add(buf, data, len)) - goto fail; +int +send_direct_ack(struct iface *iface, struct in_addr addr, void *d, size_t len) +{ + struct ibuf *buf; + int ret; - /* update authentication and calculate checksum */ - if (auth_gen(buf, iface)) - goto fail; + if ((buf = prepare_ls_ack(iface)) == NULL) + return (-1); - ret = send_packet(iface, buf, &dst); + /* 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 @@ -168,12 +194,9 @@ ls_ack_list_add(struct iface *iface, str le->le_lsa = lsa; iface->ls_ack_cnt++; - /* reschedule now if we have enough for a full packet */ - if (iface->ls_ack_cnt > - ((iface->mtu - PACKET_HDR) / sizeof(struct lsa_hdr))) { + /* reschedule now if we have enough for a reasonably sized packet */ + if (iface->ls_ack_cnt > IP_MSS / sizeof(struct lsa_hdr)) start_ls_ack_tx_timer_now(iface); - } - } void @@ -212,40 +235,45 @@ ls_ack_tx_timer(int fd, short event, voi { struct in_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) + + MD5_DIGEST_LENGTH) + 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_aton(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_aton(AllSPFRouters, &addr); else inet_aton(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: @@ -255,15 +283,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: ospf.h =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/ospf.h,v retrieving revision 1.19 diff -u -p -r1.19 ospf.h --- ospf.h 26 Jun 2010 18:02:07 -0000 1.19 +++ ospf.h 17 Feb 2011 19:19:19 -0000 @@ -30,8 +30,6 @@ #define AllSPFRouters "224.0.0.5" #define AllDRouters "224.0.0.6" -#define PACKET_HDR 100 /* XXX used to calculate the IP payload */ - #define DEFAULT_METRIC 10 #define DEFAULT_REDIST_METRIC 100 #define MIN_METRIC 1 Index: ospfe.c =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/ospfe.c,v retrieving revision 1.78 diff -u -p -r1.78 ospfe.c --- ospfe.c 8 Mar 2011 10:56:02 -0000 1.78 +++ ospfe.c 9 Mar 2011 18:20:00 -0000 @@ -641,7 +641,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/ospfd/ospfe.h,v retrieving revision 1.42 diff -u -p -r1.42 ospfe.h --- ospfe.h 26 May 2010 13:56:08 -0000 1.42 +++ ospfe.h 17 Feb 2011 19:19:19 -0000 @@ -157,7 +157,7 @@ int if_set_ip_hdrincl(int); /* lsack.c */ int delay_lsa_ack(struct iface *, struct lsa_hdr *); -int send_ls_ack(struct iface *, struct in_addr, void *, size_t); +int send_direct_ack(struct iface *, struct in_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 *);