diff options
author | denis <denis@cvs.openbsd.org> | 2019-12-28 09:25:25 +0000 |
---|---|---|
committer | denis <denis@cvs.openbsd.org> | 2019-12-28 09:25:25 +0000 |
commit | 903500dc4a2183156151b6afd2f75e04634083cd (patch) | |
tree | 893d963b46e90318e6656349b6465c3a534f2cce | |
parent | b2a2cd7db2df4ee95ee301a9dffe87358f00bdfa (diff) |
Refactor link state ack/req.
OK remi@
-rw-r--r-- | usr.sbin/ospf6d/lsack.c | 107 | ||||
-rw-r--r-- | usr.sbin/ospf6d/lsreq.c | 8 | ||||
-rw-r--r-- | usr.sbin/ospf6d/lsupdate.c | 92 | ||||
-rw-r--r-- | usr.sbin/ospf6d/ospfe.c | 4 | ||||
-rw-r--r-- | usr.sbin/ospf6d/ospfe.h | 4 |
5 files changed, 117 insertions, 98 deletions
diff --git a/usr.sbin/ospf6d/lsack.c b/usr.sbin/ospf6d/lsack.c index 26aa263af91..abacf022241 100644 --- a/usr.sbin/ospf6d/lsack.c +++ b/usr.sbin/ospf6d/lsack.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lsack.c,v 1.7 2019/12/11 21:33:56 denis Exp $ */ +/* $OpenBSD: lsack.c,v 1.8 2019/12/28 09:25:24 denis Exp $ */ /* * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org> @@ -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, void *arg) { 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, void *arg) 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 diff --git a/usr.sbin/ospf6d/lsreq.c b/usr.sbin/ospf6d/lsreq.c index 0817771ec2e..55220a1992e 100644 --- a/usr.sbin/ospf6d/lsreq.c +++ b/usr.sbin/ospf6d/lsreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lsreq.c,v 1.10 2019/12/11 21:33:56 denis Exp $ */ +/* $OpenBSD: lsreq.c,v 1.11 2019/12/28 09:25:24 denis Exp $ */ /* * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org> @@ -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); diff --git a/usr.sbin/ospf6d/lsupdate.c b/usr.sbin/ospf6d/lsupdate.c index d85fb17a37c..9dfb5ea5894 100644 --- a/usr.sbin/ospf6d/lsupdate.c +++ b/usr.sbin/ospf6d/lsupdate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lsupdate.c,v 1.14 2019/12/11 21:33:56 denis Exp $ */ +/* $OpenBSD: lsupdate.c,v 1.15 2019/12/28 09:25:24 denis Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -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 nbr *originator, struct lsa_hdr *lsa_hdr, } 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 iface *iface, void *data, int len, 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 iface *iface, struct in6_addr addr, 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, void *bula) 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, void *bula) } 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, void *bula) 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, void *bula) 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) { diff --git a/usr.sbin/ospf6d/ospfe.c b/usr.sbin/ospf6d/ospfe.c index 85f352a4add..ffdec467e84 100644 --- a/usr.sbin/ospf6d/ospfe.c +++ b/usr.sbin/ospf6d/ospfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.c,v 1.58 2019/12/23 07:33:49 denis Exp $ */ +/* $OpenBSD: ospfe.c,v 1.59 2019/12/28 09:25:24 denis Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -699,7 +699,7 @@ ospfe_dispatch_rde(int fd, short event, void *bula) 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; diff --git a/usr.sbin/ospf6d/ospfe.h b/usr.sbin/ospf6d/ospfe.h index 07dce1d20f1..dcdde44bdcd 100644 --- a/usr.sbin/ospf6d/ospfe.h +++ b/usr.sbin/ospf6d/ospfe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.h,v 1.21 2019/12/22 15:34:52 denis Exp $ */ +/* $OpenBSD: ospfe.h,v 1.22 2019/12/28 09:25:24 denis Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -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 *); |