From 94c608d636b9b8d8bedc23fec75454d8deff8e37 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 19 Jul 2017 18:20:02 +0000 Subject: [PATCH 01/13] zebra: "debug zebra packet" config display Signed-off-by: Daniel Walton --- zebra/debug.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/zebra/debug.c b/zebra/debug.c index dfee6b74c0..fc2cd44e5f 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -145,17 +145,15 @@ DEFUN (debug_zebra_packet, if (argv_find(argv, argc, "send", &idx)) SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - idx = 0; - if (argv_find(argv, argc, "recv", &idx)) + else if (argv_find(argv, argc, "recv", &idx)) SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - idx = 0; - if (argv_find(argv, argc, "detail", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); - - if (!(zebra_debug_packet & ZEBRA_DEBUG_SEND & ZEBRA_DEBUG_RECV)) { + else { SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); } + + if (argv_find(argv, argc, "detail", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); return CMD_SUCCESS; } From a72730d34a8ca9ecd91b356c8e70914ccbccc8a7 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Thu, 20 Jul 2017 11:48:52 -0400 Subject: [PATCH 02/13] eigrpd, vtysh: add dummy route-map cli eigrpd will successfully accept `(conf)# route-map foo ...` because it is not sent to eigrpd from vtysh, but of course, this is the classic node sync syndrome. Since eigrpd apparently doesn't support proper routemaps yet just add the cli so we can suppress the vtysh errors. Signed-off-by: Quentin Young --- eigrpd/eigrp_main.c | 7 ++++++- vtysh/vtysh.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index d593f5ceea..e7532778a9 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -50,7 +50,7 @@ #include "keychain.h" #include "distribute.h" #include "libfrr.h" -//#include "routemap.h" +#include "routemap.h" //#include "if_rmap.h" #include "eigrpd/eigrp_structs.h" @@ -194,6 +194,11 @@ int main(int argc, char **argv, char **envp) prefix_list_add_hook(eigrp_distribute_update_all); prefix_list_delete_hook(eigrp_distribute_update_all); + /* + * XXX: This is just to get the CLI installed to suppress VTYSH errors. + * Routemaps in EIGRP are not yet functional. + */ + route_map_init(); /*eigrp_route_map_init(); route_map_add_hook (eigrp_rmap_update); route_map_delete_hook (eigrp_rmap_update);*/ diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 67ee8898c9..bef4b82d3f 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -44,7 +44,7 @@ DECLARE_MGROUP(MVTYSH) * run on it (logging & co. should stay in a fixed/frozen config, and * things like prefix lists are not even initialised) */ #define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD -#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD +#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD|VTYSH_EIGRPD #define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD #define VTYSH_NS VTYSH_ZEBRA #define VTYSH_VRF VTYSH_ZEBRA From 874402831268edb872774f18b2d5701d604f3530 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 20 Jul 2017 17:11:43 +0000 Subject: [PATCH 03/13] lib: copy_nexthops() only copies the first nexthop Signed-off-by: Daniel Walton Before the fix NHT had each path resolving via swp1 cel-redxp-10# show ip route 20.0.11.253 Routing entry for 20.0.11.0/24 Known via "bgp", distance 20, metric 0, best Last update 00:00:20 ago * 169.254.0.1, via swp1 * 169.254.0.17, via swp2 cel-redxp-10# cel-redxp-10# show ip nht [snip] 20.0.11.253 resolved via bgp via 169.254.0.1, swp1 via 169.254.0.1, swp1 Client list: pim(fd 19) After the fix cel-redxp-10# show ip nht [snip] 20.0.11.253 resolved via bgp via 169.254.0.1, swp1 via 169.254.0.17, swp2 Client list: pim(fd 19) --- lib/nexthop.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/nexthop.c b/lib/nexthop.c index 9b0c2d73f4..7180be33dd 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -133,17 +133,17 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh, for (nh1 = nh; nh1; nh1 = nh1->next) { nexthop = nexthop_new(); - nexthop->ifindex = nh->ifindex; - nexthop->type = nh->type; - nexthop->flags = nh->flags; - memcpy(&nexthop->gate, &nh->gate, sizeof(nh->gate)); - memcpy(&nexthop->src, &nh->src, sizeof(nh->src)); - memcpy(&nexthop->rmap_src, &nh->rmap_src, sizeof(nh->rmap_src)); + nexthop->ifindex = nh1->ifindex; + nexthop->type = nh1->type; + nexthop->flags = nh1->flags; + memcpy(&nexthop->gate, &nh1->gate, sizeof(nh1->gate)); + memcpy(&nexthop->src, &nh1->src, sizeof(nh1->src)); + memcpy(&nexthop->rmap_src, &nh1->rmap_src, sizeof(nh1->rmap_src)); nexthop->rparent = rparent; - if (nh->nh_label) - nexthop_add_labels(nexthop, nh->nh_label_type, - nh->nh_label->num_labels, - &nh->nh_label->label[0]); + if (nh1->nh_label) + nexthop_add_labels(nexthop, nh1->nh_label_type, + nh1->nh_label->num_labels, + &nh1->nh_label->label[0]); nexthop_add(tnh, nexthop); if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) From 40e344cc4bc4c6da92d213302231cce77edf596e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 24 Jul 2017 15:59:36 -0400 Subject: [PATCH 04/13] ripngd: Fix failure returned with some debug commands Signed-off-by: Donald Sharp --- ripngd/ripng_debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ripngd/ripng_debug.c b/ripngd/ripng_debug.c index 5d7a2cf9ff..d56161d39e 100644 --- a/ripngd/ripng_debug.c +++ b/ripngd/ripng_debug.c @@ -67,7 +67,7 @@ DEFUN (debug_ripng_events, "Debug option set for ripng events\n") { ripng_debug_event = RIPNG_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (debug_ripng_packet, @@ -114,7 +114,7 @@ DEFUN (debug_ripng_zebra, "Debug option set for ripng and zebra communication\n") { ripng_debug_zebra = RIPNG_DEBUG_ZEBRA; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (no_debug_ripng_events, @@ -179,7 +179,7 @@ DEFUN (no_debug_ripng_zebra, "Debug option set for ripng and zebra communication\n") { ripng_debug_zebra = 0; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } /* Debug node. */ From 9c9d843baa9b8320f22f5976b2d0b79753dd202e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 24 Jul 2017 16:00:20 -0400 Subject: [PATCH 05/13] ripd: Fix debug config failures Signed-off-by: Donald Sharp --- ripd/rip_debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ripd/rip_debug.c b/ripd/rip_debug.c index b2c80817dd..492d036991 100644 --- a/ripd/rip_debug.c +++ b/ripd/rip_debug.c @@ -66,7 +66,7 @@ DEFUN (debug_rip_events, "RIP events\n") { rip_debug_event = RIP_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (debug_rip_packet, @@ -112,7 +112,7 @@ DEFUN (debug_rip_zebra, "RIP and ZEBRA communication\n") { rip_debug_zebra = RIP_DEBUG_ZEBRA; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (no_debug_rip_events, @@ -177,7 +177,7 @@ DEFUN (no_debug_rip_zebra, "RIP and ZEBRA communication\n") { rip_debug_zebra = 0; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } /* Debug node. */ From 52535beec1fe85682094b625d3f2e19520a803a8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 24 Jul 2017 18:36:51 -0300 Subject: [PATCH 06/13] lib: revert reindent of files imported from OpenBSD We should preserve the original indentation to make it easier to keep these files in sync with the upstream. Signed-off-by: Renato Westphal --- lib/imsg-buffer.c | 105 +++--- lib/imsg.c | 117 ++++--- lib/imsg.h | 110 +++---- lib/openbsd-tree.c | 146 +++++---- lib/openbsd-tree.h | 793 ++++++++++++++++++++++----------------------- 5 files changed, 654 insertions(+), 617 deletions(-) diff --git a/lib/imsg-buffer.c b/lib/imsg-buffer.c index 4068e31c51..a486fc17c1 100644 --- a/lib/imsg-buffer.c +++ b/lib/imsg-buffer.c @@ -21,13 +21,14 @@ #include "openbsd-queue.h" #include "imsg.h" -int ibuf_realloc(struct ibuf *, size_t); -void ibuf_enqueue(struct msgbuf *, struct ibuf *); -void ibuf_dequeue(struct msgbuf *, struct ibuf *); +int ibuf_realloc(struct ibuf *, size_t); +void ibuf_enqueue(struct msgbuf *, struct ibuf *); +void ibuf_dequeue(struct msgbuf *, struct ibuf *); -struct ibuf *ibuf_open(size_t len) +struct ibuf * +ibuf_open(size_t len) { - struct ibuf *buf; + struct ibuf *buf; if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) return (NULL); @@ -41,9 +42,10 @@ struct ibuf *ibuf_open(size_t len) return (buf); } -struct ibuf *ibuf_dynamic(size_t len, size_t max) +struct ibuf * +ibuf_dynamic(size_t len, size_t max) { - struct ibuf *buf; + struct ibuf *buf; if (max < len) return (NULL); @@ -57,9 +59,10 @@ struct ibuf *ibuf_dynamic(size_t len, size_t max) return (buf); } -int ibuf_realloc(struct ibuf *buf, size_t len) +int +ibuf_realloc(struct ibuf *buf, size_t len) { - u_char *b; + u_char *b; /* on static buffers max is eq size and so the following fails */ if (buf->wpos + len > buf->max) { @@ -76,7 +79,8 @@ int ibuf_realloc(struct ibuf *buf, size_t len) return (0); } -int ibuf_add(struct ibuf *buf, const void *data, size_t len) +int +ibuf_add(struct ibuf *buf, const void *data, size_t len) { if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) @@ -87,9 +91,10 @@ int ibuf_add(struct ibuf *buf, const void *data, size_t len) return (0); } -void *ibuf_reserve(struct ibuf *buf, size_t len) +void * +ibuf_reserve(struct ibuf *buf, size_t len) { - void *b; + void *b; if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) @@ -100,7 +105,8 @@ void *ibuf_reserve(struct ibuf *buf, size_t len) return (b); } -void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len) +void * +ibuf_seek(struct ibuf *buf, size_t pos, size_t len) { /* only allowed to seek in already written parts */ if (pos + len > buf->wpos) @@ -109,31 +115,34 @@ void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len) return (buf->buf + pos); } -size_t ibuf_size(struct ibuf *buf) +size_t +ibuf_size(struct ibuf *buf) { return (buf->wpos); } -size_t ibuf_left(struct ibuf *buf) +size_t +ibuf_left(struct ibuf *buf) { return (buf->max - buf->wpos); } -void ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) +void +ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) { ibuf_enqueue(msgbuf, buf); } -int ibuf_write(struct msgbuf *msgbuf) +int +ibuf_write(struct msgbuf *msgbuf) { - struct iovec iov[IOV_MAX]; - struct ibuf *buf; - unsigned int i = 0; - ssize_t n; + struct iovec iov[IOV_MAX]; + struct ibuf *buf; + unsigned int i = 0; + ssize_t n; memset(&iov, 0, sizeof(iov)); - TAILQ_FOREACH(buf, &msgbuf->bufs, entry) - { + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { if (i >= IOV_MAX) break; iov[i].iov_base = buf->buf + buf->rpos; @@ -150,7 +159,7 @@ again: return (-1); } - if (n == 0) { /* connection closed */ + if (n == 0) { /* connection closed */ errno = 0; return (0); } @@ -160,7 +169,8 @@ again: return (1); } -void ibuf_free(struct ibuf *buf) +void +ibuf_free(struct ibuf *buf) { if (buf == NULL) return; @@ -168,19 +178,21 @@ void ibuf_free(struct ibuf *buf) free(buf); } -void msgbuf_init(struct msgbuf *msgbuf) +void +msgbuf_init(struct msgbuf *msgbuf) { msgbuf->queued = 0; msgbuf->fd = -1; TAILQ_INIT(&msgbuf->bufs); } -void msgbuf_drain(struct msgbuf *msgbuf, size_t n) +void +msgbuf_drain(struct msgbuf *msgbuf, size_t n) { - struct ibuf *buf, *next; + struct ibuf *buf, *next; for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; - buf = next) { + buf = next) { next = TAILQ_NEXT(buf, entry); if (buf->rpos + n >= buf->wpos) { n -= buf->wpos - buf->rpos; @@ -192,32 +204,33 @@ void msgbuf_drain(struct msgbuf *msgbuf, size_t n) } } -void msgbuf_clear(struct msgbuf *msgbuf) +void +msgbuf_clear(struct msgbuf *msgbuf) { - struct ibuf *buf; + struct ibuf *buf; while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) ibuf_dequeue(msgbuf, buf); } -int msgbuf_write(struct msgbuf *msgbuf) +int +msgbuf_write(struct msgbuf *msgbuf) { - struct iovec iov[IOV_MAX]; - struct ibuf *buf; - unsigned int i = 0; - ssize_t n; - struct msghdr msg; - struct cmsghdr *cmsg; + struct iovec iov[IOV_MAX]; + struct ibuf *buf; + unsigned int i = 0; + ssize_t n; + struct msghdr msg; + struct cmsghdr *cmsg; union { - struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int))]; + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; memset(&iov, 0, sizeof(iov)); memset(&msg, 0, sizeof(msg)); memset(&cmsgbuf, 0, sizeof(cmsgbuf)); - TAILQ_FOREACH(buf, &msgbuf->bufs, entry) - { + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { if (i >= IOV_MAX) break; iov[i].iov_base = buf->buf + buf->rpos; @@ -249,7 +262,7 @@ again: return (-1); } - if (n == 0) { /* connection closed */ + if (n == 0) { /* connection closed */ errno = 0; return (0); } @@ -268,13 +281,15 @@ again: return (1); } -void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) +void +ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) { TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); msgbuf->queued++; } -void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) +void +ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) { TAILQ_REMOVE(&msgbuf->bufs, buf, entry); diff --git a/lib/imsg.c b/lib/imsg.c index 10650f648a..fc62c13734 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -21,21 +21,22 @@ #include "openbsd-queue.h" #include "imsg.h" -int imsg_fd_overhead = 0; +int imsg_fd_overhead = 0; -int imsg_get_fd(struct imsgbuf *); +int imsg_get_fd(struct imsgbuf *); #ifndef __OpenBSD__ /* * The original code calls getdtablecount() which is OpenBSD specific. Use * available_fds() from OpenSMTPD instead. */ -static int available_fds(unsigned int n) +static int +available_fds(unsigned int n) { - unsigned int i; - int ret, fds[256]; + unsigned int i; + int ret, fds[256]; - if (n > (sizeof(fds) / sizeof(fds[0]))) + if (n > (sizeof(fds)/sizeof(fds[0]))) return (1); ret = 0; @@ -58,7 +59,8 @@ static int available_fds(unsigned int n) } #endif -void imsg_init(struct imsgbuf *ibuf, int fd) +void +imsg_init(struct imsgbuf *ibuf, int fd) { msgbuf_init(&ibuf->w); memset(&ibuf->r, 0, sizeof(ibuf->r)); @@ -68,18 +70,19 @@ void imsg_init(struct imsgbuf *ibuf, int fd) TAILQ_INIT(&ibuf->fds); } -ssize_t imsg_read(struct imsgbuf *ibuf) +ssize_t +imsg_read(struct imsgbuf *ibuf) { - struct msghdr msg; - struct cmsghdr *cmsg; + struct msghdr msg; + struct cmsghdr *cmsg; union { struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int) * 1)]; + char buf[CMSG_SPACE(sizeof(int) * 1)]; } cmsgbuf; - struct iovec iov; - ssize_t n = -1; - int fd; - struct imsg_fd *ifd; + struct iovec iov; + ssize_t n = -1; + int fd; + struct imsg_fd *ifd; memset(&msg, 0, sizeof(msg)); memset(&cmsgbuf, 0, sizeof(cmsgbuf)); @@ -96,14 +99,12 @@ ssize_t imsg_read(struct imsgbuf *ibuf) again: #ifdef __OpenBSD__ - if (getdtablecount() + imsg_fd_overhead - + (int)((CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0)) - / sizeof(int)) + if (getdtablecount() + imsg_fd_overhead + + (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int)) >= getdtablesize()) { #else - if (available_fds(imsg_fd_overhead - + (CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0)) - / sizeof(int))) { + if (available_fds(imsg_fd_overhead + + (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) { #endif errno = EAGAIN; free(ifd); @@ -119,9 +120,9 @@ again: ibuf->r.wpos += n; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_RIGHTS) { + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { int i; int j; @@ -130,15 +131,14 @@ again: * padding rules, our control buffer might contain * more than one fd, and we must close them. */ - j = ((char *)cmsg + cmsg->cmsg_len - - (char *)CMSG_DATA(cmsg)) - / sizeof(int); + j = ((char *)cmsg + cmsg->cmsg_len - + (char *)CMSG_DATA(cmsg)) / sizeof(int); for (i = 0; i < j; i++) { fd = ((int *)CMSG_DATA(cmsg))[i]; if (ifd != NULL) { ifd->fd = fd; TAILQ_INSERT_TAIL(&ibuf->fds, ifd, - entry); + entry); ifd = NULL; } else close(fd); @@ -152,9 +152,10 @@ fail: return (n); } -ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) +ssize_t +imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) { - size_t av, left, datalen; + size_t av, left, datalen; av = ibuf->r.wpos; @@ -162,7 +163,8 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) return (0); memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); - if (imsg->hdr.len < IMSG_HEADER_SIZE || imsg->hdr.len > MAX_IMSGSIZE) { + if (imsg->hdr.len < IMSG_HEADER_SIZE || + imsg->hdr.len > MAX_IMSGSIZE) { errno = ERANGE; return (-1); } @@ -181,7 +183,7 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) imsg->fd = -1; if (imsg->data) - memcpy(imsg->data, ibuf->r.rptr, datalen); + memcpy(imsg->data, ibuf->r.rptr, datalen); if (imsg->hdr.len < av) { left = av - imsg->hdr.len; @@ -193,10 +195,11 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) return (datalen + IMSG_HEADER_SIZE); } -int imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const void *data, u_int16_t datalen) +int +imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, int fd, const void *data, u_int16_t datalen) { - struct ibuf *wbuf; + struct ibuf *wbuf; if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) return (-1); @@ -211,11 +214,12 @@ int imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, return (1); } -int imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const struct iovec *iov, int iovcnt) +int +imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, int fd, const struct iovec *iov, int iovcnt) { - struct ibuf *wbuf; - int i, datalen = 0; + struct ibuf *wbuf; + int i, datalen = 0; for (i = 0; i < iovcnt; i++) datalen += iov[i].iov_len; @@ -235,11 +239,12 @@ int imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, } /* ARGSUSED */ -struct ibuf *imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, u_int16_t datalen) +struct ibuf * +imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, u_int16_t datalen) { - struct ibuf *wbuf; - struct imsg_hdr hdr; + struct ibuf *wbuf; + struct imsg_hdr hdr; datalen += IMSG_HEADER_SIZE; if (datalen > MAX_IMSGSIZE) { @@ -261,7 +266,8 @@ struct ibuf *imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, return (wbuf); } -int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) +int +imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) { if (datalen) if (ibuf_add(msg, data, datalen) == -1) { @@ -271,9 +277,10 @@ int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) return (datalen); } -void imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) +void +imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) { - struct imsg_hdr *hdr; + struct imsg_hdr *hdr; hdr = (struct imsg_hdr *)msg->buf; @@ -286,15 +293,17 @@ void imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) ibuf_close(&ibuf->w, msg); } -void imsg_free(struct imsg *imsg) +void +imsg_free(struct imsg *imsg) { free(imsg->data); } -int imsg_get_fd(struct imsgbuf *ibuf) +int +imsg_get_fd(struct imsgbuf *ibuf) { - int fd; - struct imsg_fd *ifd; + int fd; + struct imsg_fd *ifd; if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) return (-1); @@ -306,7 +315,8 @@ int imsg_get_fd(struct imsgbuf *ibuf) return (fd); } -int imsg_flush(struct imsgbuf *ibuf) +int +imsg_flush(struct imsgbuf *ibuf) { while (ibuf->w.queued) if (msgbuf_write(&ibuf->w) <= 0) @@ -314,9 +324,10 @@ int imsg_flush(struct imsgbuf *ibuf) return (0); } -void imsg_clear(struct imsgbuf *ibuf) +void +imsg_clear(struct imsgbuf *ibuf) { - int fd; + int fd; msgbuf_clear(&ibuf->w); while ((fd = imsg_get_fd(ibuf)) != -1) diff --git a/lib/imsg.h b/lib/imsg.h index ddaf71344e..d053d01956 100644 --- a/lib/imsg.h +++ b/lib/imsg.h @@ -26,87 +26,87 @@ #define MAX_IMSGSIZE 16384 struct ibuf { - TAILQ_ENTRY(ibuf) entry; - u_char *buf; - size_t size; - size_t max; - size_t wpos; - size_t rpos; - int fd; + TAILQ_ENTRY(ibuf) entry; + u_char *buf; + size_t size; + size_t max; + size_t wpos; + size_t rpos; + int fd; }; struct msgbuf { - TAILQ_HEAD(, ibuf) bufs; - u_int32_t queued; - int fd; + TAILQ_HEAD(, ibuf) bufs; + u_int32_t queued; + int fd; }; struct ibuf_read { - u_char buf[IBUF_READ_SIZE]; - u_char *rptr; - size_t wpos; + u_char buf[IBUF_READ_SIZE]; + u_char *rptr; + size_t wpos; }; struct imsg_fd { - TAILQ_ENTRY(imsg_fd) entry; - int fd; + TAILQ_ENTRY(imsg_fd) entry; + int fd; }; struct imsgbuf { - TAILQ_HEAD(, imsg_fd) fds; - struct ibuf_read r; - struct msgbuf w; - int fd; - pid_t pid; + TAILQ_HEAD(, imsg_fd) fds; + struct ibuf_read r; + struct msgbuf w; + int fd; + pid_t pid; }; #define IMSGF_HASFD 1 struct imsg_hdr { - u_int32_t type; - u_int16_t len; - u_int16_t flags; - u_int32_t peerid; - u_int32_t pid; + u_int32_t type; + u_int16_t len; + u_int16_t flags; + u_int32_t peerid; + u_int32_t pid; }; struct imsg { - struct imsg_hdr hdr; - int fd; - void *data; + struct imsg_hdr hdr; + int fd; + void *data; }; /* buffer.c */ -struct ibuf *ibuf_open(size_t); -struct ibuf *ibuf_dynamic(size_t, size_t); -int ibuf_add(struct ibuf *, const void *, size_t); -void *ibuf_reserve(struct ibuf *, size_t); -void *ibuf_seek(struct ibuf *, size_t, size_t); -size_t ibuf_size(struct ibuf *); -size_t ibuf_left(struct ibuf *); -void ibuf_close(struct msgbuf *, struct ibuf *); -int ibuf_write(struct msgbuf *); -void ibuf_free(struct ibuf *); -void msgbuf_init(struct msgbuf *); -void msgbuf_clear(struct msgbuf *); -int msgbuf_write(struct msgbuf *); -void msgbuf_drain(struct msgbuf *, size_t); +struct ibuf *ibuf_open(size_t); +struct ibuf *ibuf_dynamic(size_t, size_t); +int ibuf_add(struct ibuf *, const void *, size_t); +void *ibuf_reserve(struct ibuf *, size_t); +void *ibuf_seek(struct ibuf *, size_t, size_t); +size_t ibuf_size(struct ibuf *); +size_t ibuf_left(struct ibuf *); +void ibuf_close(struct msgbuf *, struct ibuf *); +int ibuf_write(struct msgbuf *); +void ibuf_free(struct ibuf *); +void msgbuf_init(struct msgbuf *); +void msgbuf_clear(struct msgbuf *); +int msgbuf_write(struct msgbuf *); +void msgbuf_drain(struct msgbuf *, size_t); /* imsg.c */ -void imsg_init(struct imsgbuf *, int); -ssize_t imsg_read(struct imsgbuf *); -ssize_t imsg_get(struct imsgbuf *, struct imsg *); -int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int, - const void *, u_int16_t); -int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int, - const struct iovec *, int); +void imsg_init(struct imsgbuf *, int); +ssize_t imsg_read(struct imsgbuf *); +ssize_t imsg_get(struct imsgbuf *, struct imsg *); +int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, + int, const void *, u_int16_t); +int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, + int, const struct iovec *, int); struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - u_int16_t); -int imsg_add(struct ibuf *, const void *, u_int16_t); -void imsg_close(struct imsgbuf *, struct ibuf *); -void imsg_free(struct imsg *); -int imsg_flush(struct imsgbuf *); -void imsg_clear(struct imsgbuf *); + u_int16_t); +int imsg_add(struct ibuf *, const void *, u_int16_t); +void imsg_close(struct imsgbuf *, struct ibuf *); +void imsg_free(struct imsg *); +int imsg_flush(struct imsgbuf *); +void imsg_clear(struct imsgbuf *); #endif diff --git a/lib/openbsd-tree.c b/lib/openbsd-tree.c index 5d77ac2a47..7e753554c9 100644 --- a/lib/openbsd-tree.c +++ b/lib/openbsd-tree.c @@ -45,14 +45,16 @@ #include -static inline struct rb_entry *rb_n2e(const struct rb_type *t, void *node) +static inline struct rb_entry * +rb_n2e(const struct rb_type *t, void *node) { unsigned long addr = (unsigned long)node; return ((struct rb_entry *)(addr + t->t_offset)); } -static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe) +static inline void * +rb_e2n(const struct rb_type *t, struct rb_entry *rbe) { unsigned long addr = (unsigned long)rbe; @@ -66,33 +68,37 @@ static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe) #define RBH_ROOT(_rbt) (_rbt)->rbt_root -static inline void rbe_set(struct rb_entry *rbe, struct rb_entry *parent) +static inline void +rbe_set(struct rb_entry *rbe, struct rb_entry *parent) { RBE_PARENT(rbe) = parent; RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL; RBE_COLOR(rbe) = RB_RED; } -static inline void rbe_set_blackred(struct rb_entry *black, - struct rb_entry *red) +static inline void +rbe_set_blackred(struct rb_entry *black, struct rb_entry *red) { RBE_COLOR(black) = RB_BLACK; RBE_COLOR(red) = RB_RED; } -static inline void rbe_augment(const struct rb_type *t, struct rb_entry *rbe) +static inline void +rbe_augment(const struct rb_type *t, struct rb_entry *rbe) { (*t->t_augment)(rb_e2n(t, rbe)); } -static inline void rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe) +static inline void +rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe) { if (t->t_augment != NULL) rbe_augment(t, rbe); } -static inline void rbe_rotate_left(const struct rb_type *t, - struct rbt_tree *rbt, struct rb_entry *rbe) +static inline void +rbe_rotate_left(const struct rb_type *t, struct rbt_tree *rbt, + struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; @@ -124,8 +130,9 @@ static inline void rbe_rotate_left(const struct rb_type *t, } } -static inline void rbe_rotate_right(const struct rb_type *t, - struct rbt_tree *rbt, struct rb_entry *rbe) +static inline void +rbe_rotate_right(const struct rb_type *t, struct rbt_tree *rbt, + struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; @@ -157,13 +164,14 @@ static inline void rbe_rotate_right(const struct rb_type *t, } } -static inline void rbe_insert_color(const struct rb_type *t, - struct rbt_tree *rbt, struct rb_entry *rbe) +static inline void +rbe_insert_color(const struct rb_type *t, struct rbt_tree *rbt, + struct rb_entry *rbe) { struct rb_entry *parent, *gparent, *tmp; - while ((parent = RBE_PARENT(rbe)) != NULL - && RBE_COLOR(parent) == RB_RED) { + while ((parent = RBE_PARENT(rbe)) != NULL && + RBE_COLOR(parent) == RB_RED) { gparent = RBE_PARENT(parent); if (parent == RBE_LEFT(gparent)) { @@ -208,10 +216,9 @@ static inline void rbe_insert_color(const struct rb_type *t, RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK; } -static inline void rbe_remove_color(const struct rb_type *t, - struct rbt_tree *rbt, - struct rb_entry *parent, - struct rb_entry *rbe) +static inline void +rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, + struct rb_entry *parent, struct rb_entry *rbe) { struct rb_entry *tmp; @@ -219,8 +226,8 @@ static inline void rbe_remove_color(const struct rb_type *t, if (parent == NULL) return; - while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) - && rbe != RBH_ROOT(rbt)) { + while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) && + rbe != RBH_ROOT(rbt)) { if (RBE_LEFT(parent) == rbe) { tmp = RBE_RIGHT(parent); if (RBE_COLOR(tmp) == RB_RED) { @@ -228,16 +235,16 @@ static inline void rbe_remove_color(const struct rb_type *t, rbe_rotate_left(t, rbt, parent); tmp = RBE_RIGHT(parent); } - if ((RBE_LEFT(tmp) == NULL - || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) - && (RBE_RIGHT(tmp) == NULL - || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { + if ((RBE_LEFT(tmp) == NULL || + RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && + (RBE_RIGHT(tmp) == NULL || + RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { - if (RBE_RIGHT(tmp) == NULL - || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) { + if (RBE_RIGHT(tmp) == NULL || + RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) { struct rb_entry *oleft; oleft = RBE_LEFT(tmp); @@ -266,16 +273,16 @@ static inline void rbe_remove_color(const struct rb_type *t, tmp = RBE_LEFT(parent); } - if ((RBE_LEFT(tmp) == NULL - || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) - && (RBE_RIGHT(tmp) == NULL - || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { + if ((RBE_LEFT(tmp) == NULL || + RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && + (RBE_RIGHT(tmp) == NULL || + RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { - if (RBE_LEFT(tmp) == NULL - || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) { + if (RBE_LEFT(tmp) == NULL || + RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) { struct rb_entry *oright; oright = RBE_RIGHT(tmp); @@ -385,7 +392,8 @@ color: return (old); } -void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) +void * +_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *old; @@ -395,7 +403,8 @@ void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) return (old == NULL ? NULL : rb_e2n(t, old)); } -void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) +void * +_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *tmp; @@ -435,7 +444,8 @@ void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) } /* Finds the node with the same key as elm */ -void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) +void * +_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; @@ -456,7 +466,8 @@ void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) } /* Finds the first node greater than or equal to the search key */ -void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) +void * +_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; @@ -478,7 +489,8 @@ void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) return (res); } -void *_rb_next(const struct rb_type *t, void *elm) +void * +_rb_next(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); @@ -487,11 +499,12 @@ void *_rb_next(const struct rb_type *t, void *elm) while (RBE_LEFT(rbe) != NULL) rbe = RBE_LEFT(rbe); } else { - if (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) + if (RBE_PARENT(rbe) && + (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { - while (RBE_PARENT(rbe) - && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) + while (RBE_PARENT(rbe) && + (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } @@ -500,7 +513,8 @@ void *_rb_next(const struct rb_type *t, void *elm) return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void *_rb_prev(const struct rb_type *t, void *elm) +void * +_rb_prev(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); @@ -509,11 +523,12 @@ void *_rb_prev(const struct rb_type *t, void *elm) while (RBE_RIGHT(rbe)) rbe = RBE_RIGHT(rbe); } else { - if (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) + if (RBE_PARENT(rbe) && + (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { - while (RBE_PARENT(rbe) - && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) + while (RBE_PARENT(rbe) && + (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } @@ -522,14 +537,16 @@ void *_rb_prev(const struct rb_type *t, void *elm) return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void *_rb_root(const struct rb_type *t, struct rbt_tree *rbt) +void * +_rb_root(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); return (rbe == NULL ? rbe : rb_e2n(t, rbe)); } -void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt) +void * +_rb_min(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; @@ -542,7 +559,8 @@ void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt) return (parent == NULL ? NULL : rb_e2n(t, parent)); } -void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt) +void * +_rb_max(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; @@ -555,28 +573,32 @@ void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt) return (parent == NULL ? NULL : rb_e2n(t, parent)); } -void *_rb_left(const struct rb_type *t, void *node) +void * +_rb_left(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_LEFT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void *_rb_right(const struct rb_type *t, void *node) +void * +_rb_right(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_RIGHT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void *_rb_parent(const struct rb_type *t, void *node) +void * +_rb_parent(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_PARENT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void _rb_set_left(const struct rb_type *t, void *node, void *left) +void +_rb_set_left(const struct rb_type *t, void *node, void *left) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left); @@ -584,7 +606,8 @@ void _rb_set_left(const struct rb_type *t, void *node, void *left) RBE_LEFT(rbe) = rbl; } -void _rb_set_right(const struct rb_type *t, void *node, void *right) +void +_rb_set_right(const struct rb_type *t, void *node, void *right) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right); @@ -592,7 +615,8 @@ void _rb_set_right(const struct rb_type *t, void *node, void *right) RBE_RIGHT(rbe) = rbr; } -void _rb_set_parent(const struct rb_type *t, void *node, void *parent) +void +_rb_set_parent(const struct rb_type *t, void *node, void *parent) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent); @@ -600,19 +624,21 @@ void _rb_set_parent(const struct rb_type *t, void *node, void *parent) RBE_PARENT(rbe) = rbp; } -void _rb_poison(const struct rb_type *t, void *node, unsigned long poison) +void +_rb_poison(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) = - (struct rb_entry *)poison; + (struct rb_entry *)poison; } -int _rb_check(const struct rb_type *t, void *node, unsigned long poison) +int +_rb_check(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); - return ((unsigned long)RBE_PARENT(rbe) == poison - && (unsigned long)RBE_LEFT(rbe) == poison - && (unsigned long)RBE_RIGHT(rbe) == poison); + return ((unsigned long)RBE_PARENT(rbe) == poison && + (unsigned long)RBE_LEFT(rbe) == poison && + (unsigned long)RBE_RIGHT(rbe) == poison); } diff --git a/lib/openbsd-tree.h b/lib/openbsd-tree.h index 859f751678..22cb9252f5 100644 --- a/lib/openbsd-tree.h +++ b/lib/openbsd-tree.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SYS_TREE_H_ +#ifndef _SYS_TREE_H_ #define _SYS_TREE_H_ /* @@ -54,26 +54,23 @@ * The maximum height of a red-black tree is 2lg (n+1). */ -#define SPLAY_HEAD(name, type) \ - struct name { \ - struct type *sph_root; /* root of the tree */ \ - } +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} -#define SPLAY_INITIALIZER(root) \ - { \ - NULL \ - } +#define SPLAY_INITIALIZER(root) \ + { NULL } -#define SPLAY_INIT(root) \ - do { \ - (root)->sph_root = NULL; \ - } while (0) +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) -#define SPLAY_ENTRY(type) \ - struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ - } +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} #define SPLAY_LEFT(elm, field) (elm)->field.spe_left #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right @@ -81,220 +78,197 @@ #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) \ - do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ - } while (0) +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) -#define SPLAY_ROTATE_LEFT(head, tmp, field) \ - do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ - } while (0) +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) -#define SPLAY_LINKLEFT(head, tmp, field) \ - do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ - } while (0) +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) -#define SPLAY_LINKRIGHT(head, tmp, field) \ - do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ - } while (0) +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) -#define SPLAY_ASSEMBLE(head, node, left, right, field) \ - do { \ - SPLAY_RIGHT(left, field) = \ - SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = \ - SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT((head)->sph_root, field) = \ - SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = \ - SPLAY_LEFT(node, field); \ - } while (0) +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) /* Generates prototypes and inline functions */ -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ - void name##_SPLAY(struct name *, struct type *); \ - void name##_SPLAY_MINMAX(struct name *, int); \ - struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ - struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ - /* Finds the node with the same key as elm */ \ - static __inline struct type *name##_SPLAY_FIND(struct name *head, \ - struct type *elm) \ - { \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ - } \ - \ - static __inline struct type *name##_SPLAY_NEXT(struct name *head, \ - struct type *elm) \ - { \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ - } \ - \ - static __inline struct type *name##_SPLAY_MIN_MAX(struct name *head, \ - int val) \ - { \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ - } +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} /* Main splay operation. * Moves node close to the key of elm to top */ -#define SPLAY_GENERATE(name, type, field, cmp) \ - struct type *name##_SPLAY_INSERT(struct name *head, struct type *elm) \ - { \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = \ - NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if (__comp < 0) { \ - SPLAY_LEFT(elm, field) = \ - SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = \ - SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ - } \ - \ - struct type *name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ - { \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = \ - SPLAY_RIGHT((head)->sph_root, field); \ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = \ - SPLAY_LEFT((head)->sph_root, field); \ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ - } \ - \ - void name##_SPLAY(struct name *head, struct type *elm) \ - { \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \ - NULL; \ - __left = __right = &__node; \ - \ - while ((__comp = (cmp)(elm, (head)->sph_root))) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0) { \ - SPLAY_ROTATE_RIGHT(head, __tmp, \ - field); \ - if (SPLAY_LEFT((head)->sph_root, \ - field) \ - == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, \ - field) \ - == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ - } \ - \ - /* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ - void name##_SPLAY_MINMAX(struct name *head, int __comp) \ - { \ - struct type __node, *__left, *__right, *__tmp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \ - NULL; \ - __left = __right = &__node; \ - \ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0) { \ - SPLAY_ROTATE_RIGHT(head, __tmp, \ - field); \ - if (SPLAY_LEFT((head)->sph_root, \ - field) \ - == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, \ - field) \ - == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ - } +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} #define SPLAY_NEGINF -1 #define SPLAY_INF 1 @@ -303,13 +277,14 @@ #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) \ - (SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) \ - (SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); (x) != NULL; \ +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ (x) = SPLAY_NEXT(name, head, x)) /* @@ -332,197 +307,203 @@ #define RB_RED 1 struct rb_type { - int (*t_compare)(const void *, const void *); - void (*t_augment)(void *); - unsigned int t_offset; /* offset of rb_entry in type */ + int (*t_compare)(const void *, const void *); + void (*t_augment)(void *); + unsigned int t_offset; /* offset of rb_entry in type */ }; struct rbt_tree { - struct rb_entry *rbt_root; + struct rb_entry *rbt_root; }; struct rb_entry { - struct rb_entry *rbt_parent; - struct rb_entry *rbt_left; - struct rb_entry *rbt_right; - unsigned int rbt_color; + struct rb_entry *rbt_parent; + struct rb_entry *rbt_left; + struct rb_entry *rbt_right; + unsigned int rbt_color; }; -#define RB_HEAD(_name, _type) \ - struct _name { \ - struct rbt_tree rbh_root; \ - } +#define RB_HEAD(_name, _type) \ +struct _name { \ + struct rbt_tree rbh_root; \ +} #define RB_ENTRY(_type) struct rb_entry -static inline void _rb_init(struct rbt_tree *rbt) +static inline void +_rb_init(struct rbt_tree *rbt) { rbt->rbt_root = NULL; } -static inline int _rb_empty(struct rbt_tree *rbt) +static inline int +_rb_empty(struct rbt_tree *rbt) { return (rbt->rbt_root == NULL); } -void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *); -void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *); -void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *); -void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *); -void *_rb_root(const struct rb_type *, struct rbt_tree *); -void *_rb_min(const struct rb_type *, struct rbt_tree *); -void *_rb_max(const struct rb_type *, struct rbt_tree *); -void *_rb_next(const struct rb_type *, void *); -void *_rb_prev(const struct rb_type *, void *); -void *_rb_left(const struct rb_type *, void *); -void *_rb_right(const struct rb_type *, void *); -void *_rb_parent(const struct rb_type *, void *); -void _rb_set_left(const struct rb_type *, void *, void *); -void _rb_set_right(const struct rb_type *, void *, void *); -void _rb_set_parent(const struct rb_type *, void *, void *); -void _rb_poison(const struct rb_type *, void *, unsigned long); -int _rb_check(const struct rb_type *, void *, unsigned long); +void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *); +void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *); +void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *); +void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *); +void *_rb_root(const struct rb_type *, struct rbt_tree *); +void *_rb_min(const struct rb_type *, struct rbt_tree *); +void *_rb_max(const struct rb_type *, struct rbt_tree *); +void *_rb_next(const struct rb_type *, void *); +void *_rb_prev(const struct rb_type *, void *); +void *_rb_left(const struct rb_type *, void *); +void *_rb_right(const struct rb_type *, void *); +void *_rb_parent(const struct rb_type *, void *); +void _rb_set_left(const struct rb_type *, void *, void *); +void _rb_set_right(const struct rb_type *, void *, void *); +void _rb_set_parent(const struct rb_type *, void *, void *); +void _rb_poison(const struct rb_type *, void *, unsigned long); +int _rb_check(const struct rb_type *, void *, unsigned long); #define RB_INITIALIZER(_head) { { NULL } } -#define RB_PROTOTYPE(_name, _type, _field, _cmp) \ - extern const struct rb_type *const _name##_RB_TYPE; \ - \ - __attribute__((__unused__)) static inline void _name##_RB_INIT( \ - struct _name *head) \ - { \ - _rb_init(&head->rbh_root); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_INSERT(struct _name *head, struct _type *elm) \ - { \ - return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_REMOVE(struct _name *head, struct _type *elm) \ - { \ - return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_FIND(struct _name *head, const struct _type *key) \ - { \ - return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_NFIND(struct _name *head, const struct _type *key) \ - { \ - return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_ROOT(struct _name *head) \ - { \ - return _rb_root(_name##_RB_TYPE, &head->rbh_root); \ - } \ - \ - __attribute__((__unused__)) static inline int _name##_RB_EMPTY( \ - struct _name *head) \ - { \ - return _rb_empty(&head->rbh_root); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_MIN(struct _name *head) \ - { \ - return _rb_min(_name##_RB_TYPE, &head->rbh_root); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_MAX(struct _name *head) \ - { \ - return _rb_max(_name##_RB_TYPE, &head->rbh_root); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_NEXT(struct _type *elm) \ - { \ - return _rb_next(_name##_RB_TYPE, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_PREV(struct _type *elm) \ - { \ - return _rb_prev(_name##_RB_TYPE, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_LEFT(struct _type *elm) \ - { \ - return _rb_left(_name##_RB_TYPE, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_RIGHT(struct _type *elm) \ - { \ - return _rb_right(_name##_RB_TYPE, elm); \ - } \ - \ - __attribute__((__unused__)) static inline struct _type \ - *_name##_RB_PARENT(struct _type *elm) \ - { \ - return _rb_parent(_name##_RB_TYPE, elm); \ - } \ - \ - __attribute__((__unused__)) static inline void _name##_RB_SET_LEFT( \ - struct _type *elm, struct _type *left) \ - { \ - return _rb_set_left(_name##_RB_TYPE, elm, left); \ - } \ - \ - __attribute__((__unused__)) static inline void _name##_RB_SET_RIGHT( \ - struct _type *elm, struct _type *right) \ - { \ - return _rb_set_right(_name##_RB_TYPE, elm, right); \ - } \ - \ - __attribute__((__unused__)) static inline void _name##_RB_SET_PARENT( \ - struct _type *elm, struct _type *parent) \ - { \ - return _rb_set_parent(_name##_RB_TYPE, elm, parent); \ - } \ - \ - __attribute__((__unused__)) static inline void _name##_RB_POISON( \ - struct _type *elm, unsigned long poison) \ - { \ - return _rb_poison(_name##_RB_TYPE, elm, poison); \ - } \ - \ - __attribute__((__unused__)) static inline int _name##_RB_CHECK( \ - struct _type *elm, unsigned long poison) \ - { \ - return _rb_check(_name##_RB_TYPE, elm, poison); \ - } +#define RB_PROTOTYPE(_name, _type, _field, _cmp) \ +extern const struct rb_type *const _name##_RB_TYPE; \ + \ +__attribute__((__unused__)) static inline void \ +_name##_RB_INIT(struct _name *head) \ +{ \ + _rb_init(&head->rbh_root); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_INSERT(struct _name *head, struct _type *elm) \ +{ \ + return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_REMOVE(struct _name *head, struct _type *elm) \ +{ \ + return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_FIND(struct _name *head, const struct _type *key) \ +{ \ + return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_NFIND(struct _name *head, const struct _type *key) \ +{ \ + return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_ROOT(struct _name *head) \ +{ \ + return _rb_root(_name##_RB_TYPE, &head->rbh_root); \ +} \ + \ +__attribute__((__unused__)) static inline int \ +_name##_RB_EMPTY(struct _name *head) \ +{ \ + return _rb_empty(&head->rbh_root); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_MIN(struct _name *head) \ +{ \ + return _rb_min(_name##_RB_TYPE, &head->rbh_root); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_MAX(struct _name *head) \ +{ \ + return _rb_max(_name##_RB_TYPE, &head->rbh_root); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_NEXT(struct _type *elm) \ +{ \ + return _rb_next(_name##_RB_TYPE, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_PREV(struct _type *elm) \ +{ \ + return _rb_prev(_name##_RB_TYPE, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_LEFT(struct _type *elm) \ +{ \ + return _rb_left(_name##_RB_TYPE, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_RIGHT(struct _type *elm) \ +{ \ + return _rb_right(_name##_RB_TYPE, elm); \ +} \ + \ +__attribute__((__unused__)) static inline struct _type * \ +_name##_RB_PARENT(struct _type *elm) \ +{ \ + return _rb_parent(_name##_RB_TYPE, elm); \ +} \ + \ +__attribute__((__unused__)) static inline void \ +_name##_RB_SET_LEFT(struct _type *elm, struct _type *left) \ +{ \ + return _rb_set_left(_name##_RB_TYPE, elm, left); \ +} \ + \ +__attribute__((__unused__)) static inline void \ +_name##_RB_SET_RIGHT(struct _type *elm, struct _type *right) \ +{ \ + return _rb_set_right(_name##_RB_TYPE, elm, right); \ +} \ + \ +__attribute__((__unused__)) static inline void \ +_name##_RB_SET_PARENT(struct _type *elm, struct _type *parent) \ +{ \ + return _rb_set_parent(_name##_RB_TYPE, elm, parent); \ +} \ + \ +__attribute__((__unused__)) static inline void \ +_name##_RB_POISON(struct _type *elm, unsigned long poison) \ +{ \ + return _rb_poison(_name##_RB_TYPE, elm, poison); \ +} \ + \ +__attribute__((__unused__)) static inline int \ +_name##_RB_CHECK(struct _type *elm, unsigned long poison) \ +{ \ + return _rb_check(_name##_RB_TYPE, elm, poison); \ +} -#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \ - static int _name##_RB_COMPARE(const void *lptr, const void *rptr) \ - { \ - const struct _type *l = lptr, *r = rptr; \ - return _cmp(l, r); \ - } \ - static const struct rb_type _name##_RB_INFO = { \ - _name##_RB_COMPARE, _aug, offsetof(struct _type, _field), \ - }; \ - const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO; +#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \ +static int \ +_name##_RB_COMPARE(const void *lptr, const void *rptr) \ +{ \ + const struct _type *l = lptr, *r = rptr; \ + return _cmp(l, r); \ +} \ +static const struct rb_type _name##_RB_INFO = { \ + _name##_RB_COMPARE, \ + _aug, \ + offsetof(struct _type, _field), \ +}; \ +const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO; -#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \ - static void _name##_RB_AUGMENT(void *ptr) \ - { \ - struct _type *p = ptr; \ - return _aug(p); \ - } \ - RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT) +#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \ +static void \ +_name##_RB_AUGMENT(void *ptr) \ +{ \ + struct _type *p = ptr; \ + return _aug(p); \ +} \ +RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT) -#define RB_GENERATE(_name, _type, _field, _cmp) \ - RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL) +#define RB_GENERATE(_name, _type, _field, _cmp) \ + RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL) #define RB_INIT(_name, _head) _name##_RB_INIT(_head) #define RB_INSERT(_name, _head, _elm) _name##_RB_INSERT(_head, _elm) @@ -544,20 +525,24 @@ int _rb_check(const struct rb_type *, void *, unsigned long); #define RB_POISON(_name, _elm, _p) _name##_RB_POISON(_elm, _p) #define RB_CHECK(_name, _elm, _p) _name##_RB_CHECK(_elm, _p) -#define RB_FOREACH(_e, _name, _head) \ - for ((_e) = RB_MIN(_name, (_head)); (_e) != NULL; \ +#define RB_FOREACH(_e, _name, _head) \ + for ((_e) = RB_MIN(_name, (_head)); \ + (_e) != NULL; \ (_e) = RB_NEXT(_name, (_e))) -#define RB_FOREACH_SAFE(_e, _name, _head, _n) \ - for ((_e) = RB_MIN(_name, (_head)); \ - (_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); (_e) = (_n)) +#define RB_FOREACH_SAFE(_e, _name, _head, _n) \ + for ((_e) = RB_MIN(_name, (_head)); \ + (_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); \ + (_e) = (_n)) -#define RB_FOREACH_REVERSE(_e, _name, _head) \ - for ((_e) = RB_MAX(_name, (_head)); (_e) != NULL; \ +#define RB_FOREACH_REVERSE(_e, _name, _head) \ + for ((_e) = RB_MAX(_name, (_head)); \ + (_e) != NULL; \ (_e) = RB_PREV(_name, (_e))) -#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \ - for ((_e) = RB_MAX(_name, (_head)); \ - (_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); (_e) = (_n)) +#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \ + for ((_e) = RB_MAX(_name, (_head)); \ + (_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); \ + (_e) = (_n)) -#endif /* _SYS_TREE_H_ */ +#endif /* _SYS_TREE_H_ */ From 145b205177ab47860a78b68329dd4b0ac0d19036 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 24 Jul 2017 18:41:30 -0300 Subject: [PATCH 07/13] lib: fix corrupted RB trees Commit 8f942af90 introduced a bug while silencing a clang warning. Silence the warning in a different way to fix our red-black tree implementation. Fixes #841. Signed-off-by: Renato Westphal --- lib/openbsd-tree.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/openbsd-tree.c b/lib/openbsd-tree.c index 7e753554c9..d171e14d25 100644 --- a/lib/openbsd-tree.c +++ b/lib/openbsd-tree.c @@ -222,12 +222,8 @@ rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, { struct rb_entry *tmp; - /* Silence clang possible NULL deference warning. */ - if (parent == NULL) - return; - while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) && - rbe != RBH_ROOT(rbt)) { + rbe != RBH_ROOT(rbt) && parent) { if (RBE_LEFT(parent) == rbe) { tmp = RBE_RIGHT(parent); if (RBE_COLOR(tmp) == RB_RED) { From 6058ea8cb16ee387585eea6cbb98119c6b7c0cef Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 21 Jul 2017 11:33:38 -0400 Subject: [PATCH 08/13] COMMUNITY.md: update style guide Signed-off-by: Quentin Young --- COMMUNITY.md | 98 ++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index 8ab6a624ee..dfdcf89a17 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -264,10 +264,52 @@ Portions: Copyright (C) 2016 Your name [optional brief change description] ``` -### Code styling / format +### Code style / format -Coding style standards in FRR vary depending on location. Pre-existing -code uses GNU coding standards. New code may use Linux kernel coding style. +FRR uses Linux kernel style except where noted below. + +To help with compliance, in the project root there is a .clang-format +configuration file which can be used with the `clang-format` tool from the LLVM +project. In the `tools/` directory there is a Python script named `indent.py` +that wraps clang-format and handles some edge cases specific to FRR. If you are +submitting a new file, it is recommended to run that script over the new file +after ensuring that the latest stable release of `clang-format` is in your +PATH. + +**Whitespace changes in untouched parts of the code are not acceptable in +patches that change actual code.** To change/fix formatting issues, please +create a separate patch that only does formatting changes and nothing else. + +Kernel and BSD styles are documented externally: + +* [https://www.kernel.org/doc/html/latest/process/coding-style.html](https://www.kernel.org/doc/html/latest/process/coding-style.html) +* [http://man.openbsd.org/style](http://man.openbsd.org/style) + +For GNU coding style, use `indent` with the following invocation: + +``` +indent -nut -nfc1 file_for_submission.c +``` + +#### Exceptions + +FRR project code comes from a variety of sources, so there are some stylistic +exceptions in place. Here they are, by branch. + +**For `master`:** + +BSD coding style applies to: + +* ldpd/ + +`babeld` uses, approximately, the following style: + +* K&R style braces +* Indents are 4 spaces +* Function return types are on their own line + + +**For `stable/3.0` and `stable/2.0`:** GNU coding style apply to the following parts: @@ -281,57 +323,15 @@ GNU coding style apply to the following parts: * ripngd/ * vtysh/ -Linux kernel coding style applies to: - -* nhrpd/ -* watchfrr/ -* pimd/ -* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch] - BSD coding style applies to: * ldpd/ -**Whitespace changes in untouched parts of the code are not acceptable in -patches that change actual code.** To change/fix formatting issues, please -create a separate patch that only does formatting changes and nothing else. - -It is acceptable to rewrap entire files to Linux kernel style, but this -**MUST** come as a separate patch that does nothing other than this -reformatting. - - -#### GNU style - -For GNU coding style, Indentation follows the result of invoking GNU indent: - -``` -indent -nut -nfc1 file_for_submission.c -``` - -Originally, tabs were used instead of spaces, with tabs are every 8 columns. -However, tab interoperability issues mean space characters are now preferred for -new changes. We generally only clean up whitespace when code is unmaintainable -due to whitespace issues, to minimise merging conflicts. - - -#### Linux kernel & BSD style - -These styles are documented externally: - -* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle). -* [http://man.openbsd.org/style](http://man.openbsd.org/style) - -They are relatively similar but differ in details. - -pimd deviates from Linux kernel style in using 2 spaces for indentation, with -Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`. -It is acceptable to convert indentation in pimd/ to Linux kernel style, but -please convert an entire file at a time. (Rationale: apart from 2-space -indentation, the styles are sufficiently close to not upset when mixed.) - -Unlike GNU style, these styles use tabs, not spaces. +#### Policy +The above standards relate to code formatting. For other stylistic choices e.g. +use of `typedef`, variable naming, etc. refer to the Linux kernel style +documentation. ### Compile-Time conditional code From c545559d4a9b4edbdc1bad12f7cbffd332e22a12 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 21 Jul 2017 12:12:52 -0400 Subject: [PATCH 09/13] COMMUNITY.md: s/PROJECT/FRRouting Also: * Make headers consistently capitalized * Some extra backticks where needed Signed-off-by: Quentin Young --- COMMUNITY.md | 105 ++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index dfdcf89a17..6fd82c0541 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -1,4 +1,4 @@ -# Developing for PROJECT (DRAFT) +# Developing for FRRouting [TOC] @@ -14,8 +14,8 @@ it's the document that needs to be updated, not reality. ## Git Structure -The master Git for PROJECT resides on Github at -[https://github.com/PROJECT/XXX](https://github.com/PROJECT/XXX) +The master Git for FRRouting resides on Github at +[https://github.com/frrouting/frr](https://github.com/FRRouting/XXX) ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") @@ -38,23 +38,24 @@ is still here, this document obviously wasn't updated. ## Programming language, Tools and Libraries -The core of PROJECT is written in C (gcc or clang supported). A few -non-essential scripts are implemented in Perl and Python. PROJECT requires -the following tools to build distribution packages: automake, autoconf, -texinfo, libtool and gawk and various libraries (i.e. libpam and libjson-c). +The core of FRRouting is written in C (gcc or clang supported) and makes use of +GNU compiler extensions. A few non-essential scripts are implemented in Perl +and Python. FRRouting requires the following tools to build distribution +packages: automake, autoconf, texinfo, libtool and gawk and various libraries +(i.e. libpam and libjson-c). If your contribution requires a new library or other tool, then please -highlight this in your description of the change. Also make sure it’s -supported by all PROJECT platform OSes or provide a way to build without the -library (potentially without the new feature) on the other platforms. +highlight this in your description of the change. Also make sure it’s supported +by all FRRouting platform OSes or provide a way to build without the library +(potentially without the new feature) on the other platforms. Documentation should be written in Tex (.texi) or Markdown (.md) format with -preference on Markdown. +a preference for Markdown. ## Before Submitting your changes -* Format code (see [Code Styling requirements](#code-styling-requirements)) +* Format code (see [Code style requirements](#code-styling-requirements)) * Verify and acknowledge license (see [License for contributions](#license-for-contributions)) * Test building with various configurations: * `buildtest.sh` @@ -77,13 +78,13 @@ for the release notes. ### License for contributions -PROJECT is under a “GPLv2 or later” license. Any code submitted must be +FRRouting is under a “GPLv2 or later” license. Any code submitted must be released under the same license (preferred) or any license which allows redistribution under this GPLv2 license (eg MIT License). ### Signed-off required -Submissions to PROJECT require a “Signed-off” in the patch or git commit. +Submissions to FRRouting require a “Signed-off” in the patch or git commit. We follow the same standard as the Linux Kernel Development. > Developer's Certificate of Origin 1.1 @@ -143,7 +144,7 @@ the question of a maintainer. Preferred submission of code is by using a Github Pull Request against the Develop branch. Code submitted by Pull Request will have an email generated to -the PROJECT-devel mailing list for review and the submission will be +the FRRouting-devel mailing list for review and the submission will be automatically tested by one or more CI systems. Only after this test succeeds (and the submission is based on the head of the develop branch), then it will be automatically merged into the develop branch. In case of failed tests, it is @@ -154,9 +155,9 @@ Further (manual) code review and discussion happens after the merge into the develop branch. -### Code submission - Mailing Patch to PROJECT-Devel list +### Code submission - Mailing Patch to FRRouting-Devel list -As an alternative submission, a patch can be mailed to the PROJECT-Devel +As an alternative submission, a patch can be mailed to the FRRouting-Devel mailing list. Preferred way to send the patch is using git send-mail. Patches received on the mailing list will be picked up by Patchwork and tested against the latest develop branch. After a further ACK by someone on the mailing list, @@ -194,9 +195,9 @@ and will allow your changes to merge faster less than 2 hrs of the submission. If you don’t get the email, then check status on the github pull request (if submitted by pull request) or on Patchwork at - [https://patchwork.PROJECT.org](https://patchwork.PROJECT.org) (if + [https://patchwork.FRRouting.org](https://patchwork.PROJECT.org) (if submitted as patch to mailing list). - * Please notify PROJECT-Devel mailing list if you think something doesn’t + * Please notify FRRouting-Devel mailing list if you think something doesn’t work * If the tests failed: * In general, expect the community to ignore the submission until the tests @@ -206,23 +207,23 @@ and will allow your changes to merge faster changes broke or changed them. * It also includes fixing distribution packages for the failing platforms (ie if new libraries are required) - * Feel free to ask for help on PROJECT-Devel list + * Feel free to ask for help on FRRouting-Devel list * Go back to the submission process and repeat until the tests pass. * If the tests pass: * If the changes are done as a pull request, then they should be automatically merged to the develop branch. * Changes sent to mailing list require a manual ACK to be merged and should be merged within 2 weeks. If you don’t see the merge or any - reason/discussion on PROJECT-Devel, then please ask. + reason/discussion on FRRouting-Devel, then please ask. * Watch out for questions on the mailing list. At this time there will be a manual code review and further (longer) tests by various community members. * Your submission is done once it is merged to the master branch. (which should happen every few weeks from the develop branch) -## Code Styling requirements +## Code style requirements -### File header required for new files added +### Source file header New files need to have a Copyright header (see [License for contributions](#license-for-contributions) above) added to the file. Preferred @@ -251,7 +252,7 @@ form of the header is as follows: #include ``` -### Adding Copyright claims to already existing file +### Adding copyright claims to existing files When adding copyright claims for modifications to an existing file, please preface the claim with "Portions: " on a line before it and indent the @@ -264,7 +265,7 @@ Portions: Copyright (C) 2016 Your name [optional brief change description] ``` -### Code style / format +### Code formatting FRR uses Linux kernel style except where noted below. @@ -294,13 +295,13 @@ indent -nut -nfc1 file_for_submission.c #### Exceptions FRR project code comes from a variety of sources, so there are some stylistic -exceptions in place. Here they are, by branch. +exceptions in place. They are organized here by branch. **For `master`:** BSD coding style applies to: -* ldpd/ +* `ldpd/` `babeld` uses, approximately, the following style: @@ -313,46 +314,46 @@ BSD coding style applies to: GNU coding style apply to the following parts: -* lib/ -* zebra/ -* bgpd/ -* ospfd/ -* ospf6d/ -* isisd/ -* ripd/ -* ripngd/ -* vtysh/ +* `lib/` +* `zebra/` +* `bgpd/` +* `ospfd/` +* `ospf6d/` +* `isisd/` +* `ripd/` +* `ripngd/` +* `vtysh/` BSD coding style applies to: -* ldpd/ +* `ldpd/` #### Policy -The above standards relate to code formatting. For other stylistic choices e.g. -use of `typedef`, variable naming, etc. refer to the Linux kernel style +The above standards relate to code formatting. For other stylistic choices, +such as use of `typedef`, variable naming, etc. refer to the Linux kernel style documentation. -### Compile-Time conditional code +### Compile-time conditional code -Many users access PROJECT via binary packages from 3rd party sources; +Many users access FRR via binary packages from 3rd party sources; compile-time code puts inclusion/exclusion in the hands of the package maintainer. Please think very carefully before making code conditional at compile time, as it increases regression testing, maintenance burdens, and user -confusion. In particular, please avoid gratuitous --enable-… switches to the -configure script - typically code should be good enough to be in PROJECT, or it -shouldn’t be there at all. +confusion. In particular, please avoid gratuitous `--enable-…` switches to the +configure script - in general, code should be of high quality and in working +condition, or it shouldn’t be in FRR at all. When code must be compile-time conditional, try have the compiler make it -conditional rather than the C pre-processor - so that it will still be checked -by the compiler, even if disabled. I.e. this: +conditional rather than the C pre-processor so that it will still be checked by +the compiler, even if disabled. For example, ``` if (SOME_SYMBOL) frobnicate(); ``` -rather than +is preferred to ``` #ifdef SOME_SYMBOL @@ -363,18 +364,18 @@ frobnicate (); Note that the former approach requires ensuring that `SOME_SYMBOL` will be defined (watch your `AC_DEFINE`s). -### Debug-Guards in code +### Debug-guards in code -Debugs are an important methodology to allow developers to fix issues +Debugging statements are an important methodology to allow developers to fix issues found in the code after it has been released. The caveat here is that the developer must remember that people will be using the code at scale and in ways that can be unexpected for the original implementor. -As such debugs MUST be guarded in such a way that they can be turned off. -This PROJECT has the ability to turn on/off debugs from the CLI and it is +As such debugs **MUST** be guarded in such a way that they can be turned off. +FRR has the ability to turn on/off debugs from the CLI and it is expected that the developer will use this convention to allow control of their debugs. -### CLI-Changes +### CLI changes CLI's are a complicated ugly beast. Additions or changes to the CLI should use a DEFUN to encapsulate one setting as much as is possible. From b0ff7312a46570dd2d237fda78c76485bb895221 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 21 Jul 2017 12:50:59 -0400 Subject: [PATCH 10/13] COMMUNITY.md: miscellaneous documentation Also: - Add documentation on mailing list - Update mentions of unit tests - Update process description Signed-off-by: Quentin Young --- COMMUNITY.md | 163 +++++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 78 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index 6fd82c0541..8a02d13cc6 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -1,4 +1,7 @@ -# Developing for FRRouting +Developing for FRRouting +========================= + +## Table of Contents [TOC] @@ -15,7 +18,7 @@ it's the document that needs to be updated, not reality. ## Git Structure The master Git for FRRouting resides on Github at -[https://github.com/frrouting/frr](https://github.com/FRRouting/XXX) +[https://github.com/frrouting/frr](https://github.com/FRRouting/frr) ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") @@ -53,17 +56,18 @@ Documentation should be written in Tex (.texi) or Markdown (.md) format with a preference for Markdown. -## Before Submitting your changes +## Mailing lists + +Italicized lists are private. + +| Topic | List | +|--------------------------------|------------------------------| +| Development | dev@lists.frrouting.org | +| Users & Operators | frog@lists.frrouting.org | +| Announcements | announce@lists.frrouting.org | +| _Security_ | security@lists.frrouting.org | +| _Technical Steering Committee_ | tsc@lists.frrouting.org | -* Format code (see [Code style requirements](#code-styling-requirements)) -* Verify and acknowledge license (see [License for contributions](#license-for-contributions)) -* Test building with various configurations: - * `buildtest.sh` -* Verify building source distribution: - * `make dist` (and try rebuilding from the resulting tar file) -* Run DejaGNU unit tests: - * `make test` -* Document Regression Runs and plans for continued maintenance of the feature ### Changelog @@ -76,16 +80,45 @@ for the release notes. ## Submitting Patches and Enhancements +### Pre-submission Checklist + +* Format code (see [Coding style requirements](#coding-style-requirements)) +* Verify and acknowledge license (see [License for contributions](#license-for-contributions)) +* Ensure you have properly signed off (see [Signing Off](#signing-off)) +* Test building with various configurations: + * `buildtest.sh` +* Verify building source distribution: + * `make dist` (and try rebuilding from the resulting tar file) +* Run unit tests: + * `make test` +* Document Regression Runs and plans for continued maintenance of the feature + ### License for contributions FRRouting is under a “GPLv2 or later” license. Any code submitted must be released under the same license (preferred) or any license which allows redistribution under this GPLv2 license (eg MIT License). -### Signed-off required +### Signing Off -Submissions to FRRouting require a “Signed-off” in the patch or git commit. -We follow the same standard as the Linux Kernel Development. +Code submitted to FRRouting must be signed off. We have the same requirements +for using the signed-off-by process as the Linux kernel. In short, you must +include a signed-off-by tag in every patch. + +`Signed-off-by:` this is a developer's certification that he or she has the +right to submit the patch for inclusion into the project. It is an agreement to +the Developer's Certificate of Origin (below). Code without a proper signoff +cannot and will not be merged. + +If you are unfamiliar with this process, you should read the [official policy +at kernel.org](http://www.kernel.org/doc/Documentation/SubmittingPatches) and +you might find this article about [participating in the Linux community on the +Linux Foundation +website](http://www.linuxfoundation.org/content/how-participate-linux-community-0) +to be a helpful resource. + +In short, when you sign off on a commit, you assert your agreement to all of +the following: > Developer's Certificate of Origin 1.1 > @@ -113,79 +146,52 @@ We follow the same standard as the Linux Kernel Development. > maintained indefinitely and may be redistributed consistent with > this project or the open source license(s) involved. -#### Using this Process - -We have the same requirements for using the signed-off-by process as the Linux -kernel. In short, you need to include a signed-off-by tag in every patch: - -* `Signed-off-by:` this is a developer's certification that he or she has the -right to submit the patch for inclusion into the project. It is an agreement to -the Developer's Certificate of Origin (above). Code without a proper signoff -cannot be merged into the mainline. - -Please make sure to have a `Signed-off-by:` in each commit/patch or the patches -will be rejected until this is added. - -If you are unfamiliar with this process, you should read the [official policy -at kernel.org](http://www.kernel.org/doc/Documentation/SubmittingPatches) and -you might find this article about [participating in the Linux community on the -Linux Foundation -website](http://www.linuxfoundation.org/content/how-participate-linux-community-0) -to be a helpful resource. - -### Code submission - What do I submit my changes against? +### What do I submit my changes against? We've documented where we would like to have the different fixes applied at https://github.com/FRRouting/frr/wiki/Where-Do-I-create-a-Pull-Request-against%3F If you are unsure where your submission goes, look at that document or ask -the question of a maintainer. +a project maintainer. -### Code submission - Github Pull Request (Strongly Preferred) +### Github pull requests -Preferred submission of code is by using a Github Pull Request against the -Develop branch. Code submitted by Pull Request will have an email generated to -the FRRouting-devel mailing list for review and the submission will be -automatically tested by one or more CI systems. Only after this test succeeds -(and the submission is based on the head of the develop branch), then it will -be automatically merged into the develop branch. In case of failed tests, it is -up to the submitter to either amend the request with further commits or close, -fix and create a new pull request. +The preferred method of submitting changes is a Github pull request. Code +submitted by pull request will have an email generated to the FRRouting-devel +mailing list for review and the submission will be automatically tested by one +or more CI systems. Only after this test succeeds it will be automatically merged into +the develop branch. In case of failed tests, it is up to the submitter to +either amend the request with further commits or close, fix and create a new +pull request. Further (manual) code review and discussion happens after the merge into the develop branch. -### Code submission - Mailing Patch to FRRouting-Devel list +### Patch submission via mailing list -As an alternative submission, a patch can be mailed to the FRRouting-Devel -mailing list. Preferred way to send the patch is using git send-mail. Patches -received on the mailing list will be picked up by Patchwork and tested against -the latest develop branch. After a further ACK by someone on the mailing list, -the patch is then merged into the develop branch. - -Further (manual) code review and discussion happens after the merge into the -develop branch. - -#### Sending patch to mailing list +As an alternative submission method, a patch can be mailed to the development +mailing list. Patches received on the mailing list will be picked up by +Patchwork and tested against the latest development branch. The recommended way to send the patch (or series of NN patches) to the list is -by using ‘git send-email’ as follows (assuming they are the most recent NN +by using `git send-email` as follows (assuming they are the N most recent commit(s) in your git history: ``` -git send-email -NN --annotate --to=XXX-Devel@XXX.org +git send-email -NN --annotate --to=dev@lists.frrouting.org ``` If your commits do not already contain a `Signed-off-by` line, then use the -following version to add it (after making sure to be able to agree to the -Developer Certificate of Origin as outlined above): +following command to add it (after making sure you agree to the Developer +Certificate of Origin as outlined above): ``` -git send-email -NN --annotate --signoff --to=XXX-Devel@XXX.org +git send-email -NN --annotate --signoff --to=dev@lists.frrouting.org ``` -Submitting multi-commit patches as a Github Pull Request is strongly encouraged -and will allow your changes to merge faster +Submitting multi-commit patches as a Github pull request is **strongly +encouraged** and increases the probability of your patch getting reviewed and +merged in a timely manner. ## After submitting your changes @@ -195,33 +201,32 @@ and will allow your changes to merge faster less than 2 hrs of the submission. If you don’t get the email, then check status on the github pull request (if submitted by pull request) or on Patchwork at - [https://patchwork.FRRouting.org](https://patchwork.PROJECT.org) (if + [https://patchwork.frrouting.org](https://patchwork.frrouting.org) (if submitted as patch to mailing list). - * Please notify FRRouting-Devel mailing list if you think something doesn’t + * Please notify development mailing list if you think something doesn’t work * If the tests failed: * In general, expect the community to ignore the submission until the tests pass. * It is up to you to fix and resubmit. - * This includes fixing existing dejagnu (“make test”) tests if your + * This includes fixing existing unit (“make test”) tests if your changes broke or changed them. * It also includes fixing distribution packages for the failing platforms (ie if new libraries are required) - * Feel free to ask for help on FRRouting-Devel list + * Feel free to ask for help on development list * Go back to the submission process and repeat until the tests pass. * If the tests pass: - * If the changes are done as a pull request, then they should be - automatically merged to the develop branch. - * Changes sent to mailing list require a manual ACK to be merged and should - be merged within 2 weeks. If you don’t see the merge or any - reason/discussion on FRRouting-Devel, then please ask. + * Wait for reviewers. Someone will review your code or be assigned to + review your code. + * Respond to any comments or concerns the reviewer has. + * After all comments and concerns are addressed, expect your patch to be + merged. * Watch out for questions on the mailing list. At this time there will be a manual code review and further (longer) tests by various community members. -* Your submission is done once it is merged to the master branch. (which should - happen every few weeks from the develop branch) +* Your submission is done once it is merged to the master branch. -## Code style requirements +## Coding style requirements ### Source file header @@ -267,9 +272,10 @@ Portions: ### Code formatting -FRR uses Linux kernel style except where noted below. +FRR uses Linux kernel style except where noted below. Code which does not +comply with these style guidelines will not be accepted. -To help with compliance, in the project root there is a .clang-format +To assist with compliance, in the project root there is a .clang-format configuration file which can be used with the `clang-format` tool from the LLVM project. In the `tools/` directory there is a Python script named `indent.py` that wraps clang-format and handles some edge cases specific to FRR. If you are @@ -281,6 +287,7 @@ PATH. patches that change actual code.** To change/fix formatting issues, please create a separate patch that only does formatting changes and nothing else. +#### Style documentation Kernel and BSD styles are documented externally: * [https://www.kernel.org/doc/html/latest/process/coding-style.html](https://www.kernel.org/doc/html/latest/process/coding-style.html) From a03e352668b36772ec0a3049fd17667f7266c397 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 25 Jul 2017 15:34:41 -0400 Subject: [PATCH 11/13] COMMUNITY.md: document documentation Add guidelines for documentation to COMMUNITY.md Signed-off-by: Quentin Young --- COMMUNITY.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index 8a02d13cc6..b9f152fa12 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -226,7 +226,7 @@ merged in a timely manner. * Your submission is done once it is merged to the master branch. -## Coding style requirements +## Developer's Guidelines ### Source file header @@ -335,11 +335,61 @@ BSD coding style applies to: * `ldpd/` -#### Policy -The above standards relate to code formatting. For other stylistic choices, -such as use of `typedef`, variable naming, etc. refer to the Linux kernel style -documentation. +### Documentation + +FRRouting is a large and complex software project developed by many different +people over a long period of time. Without adequate documentation, it can be +exceedingly difficult to understand code segments, APIs and other interfaces. +In the interest of keeping the project healthy and maintainable, you should +make every effort to document your code so that other people can understand +what it does without needing to closely read the code itself. + +Some specific guidelines that contributors should follow are: + +* Functions exposed in header files should have descriptive comments above + their signatures in the header file. At a minimum, a function comment should + contain information about the return value, parameters, and a general summary + of the function's purpose. Documentation on parameter values can be omitted + if it is (very) obvious what they are used for. + + Function comments must follow the style for multiline comments laid out in + the kernel style guide. + +Example: + +``` +/* + * Determines whether or not a string is cool. + * + * @param text - the string to check for coolness + * @param is_clccfc - whether capslock is cruise control for cool + * @return 7 if the text is cool, 0 otherwise + */ +int check_coolness(const char *text, bool is_clccfc); +``` + +The Javadoc-style annotations are not required, but you should still strive to +make it equally clear what parameters and return values are used for. + +* Static functions should have descriptive comments in the same form as above + if what they do is not immediately obvious. Use good engineering judgement + when deciding whether a comment is necessary. If you are unsure, document + your code. + +* Global variables, static or not, should have a comment describing their use. + +* **For new code in `lib/`, these guidelines are hard requirements.** + + +If you are contributing code that adds significant user-visible functionality +or introduces a new API, please document it in `doc/`. Markdown and LaTeX are +acceptable formats, although Markdown is currently preferred for new +documentation. This may change in the near future. + +Finally, if you come across some code that is undocumented and feel like going +above and beyond, document it! We absolutely appreciate and accept patches that +document previously undocumented code. ### Compile-time conditional code @@ -421,3 +471,8 @@ That said, compatibility measures can (and should) be removed when either: In all cases, compatibility pieces should be marked with compiler/preprocessor annotations to print warnings at compile time, pointing to the appropriate update path. A `-Werror` build should fail if compatibility bits are used. + +### Miscellaneous + +When in doubt, follow the guidelines in the Linux kernel style guide, or ask on +the development mailing list / public Slack instance. From 4b8ac525ff61438e02b7c50651cb0fd8c6f1978f Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 25 Jul 2017 15:39:05 -0400 Subject: [PATCH 12/13] COMMUNITY.md: minor grammatical fixes Signed-off-by: Quentin Young --- COMMUNITY.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index b9f152fa12..198d23b0b8 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -108,7 +108,7 @@ include a signed-off-by tag in every patch. `Signed-off-by:` this is a developer's certification that he or she has the right to submit the patch for inclusion into the project. It is an agreement to the Developer's Certificate of Origin (below). Code without a proper signoff -cannot and will not be merged. +can not and will not be merged. If you are unfamiliar with this process, you should read the [official policy at kernel.org](http://www.kernel.org/doc/Documentation/SubmittingPatches) and @@ -203,8 +203,8 @@ merged in a timely manner. Patchwork at [https://patchwork.frrouting.org](https://patchwork.frrouting.org) (if submitted as patch to mailing list). - * Please notify development mailing list if you think something doesn’t - work + * Please notify the development mailing list if you think something doesn’t + work. * If the tests failed: * In general, expect the community to ignore the submission until the tests pass. @@ -212,8 +212,8 @@ merged in a timely manner. * This includes fixing existing unit (“make test”) tests if your changes broke or changed them. * It also includes fixing distribution packages for the failing - platforms (ie if new libraries are required) - * Feel free to ask for help on development list + platforms (ie if new libraries are required). + * Feel free to ask for help on the development list. * Go back to the submission process and repeat until the tests pass. * If the tests pass: * Wait for reviewers. Someone will review your code or be assigned to From f1423462b1287177f05e5216eb3449ba0f450590 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 25 Jul 2017 15:53:05 -0400 Subject: [PATCH 13/13] COMMUNITY.md: rewrap paragraphs, update PR section * Wrap paragraphs at 80 lines * Update Github PR section to remove mention of develop branch Signed-off-by: Quentin Young --- COMMUNITY.md | 117 ++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index 198d23b0b8..bbc5bb6d10 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -23,20 +23,20 @@ The master Git for FRRouting resides on Github at ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") -There is one main branch for development and a release branch for each -major release. +There is one main branch for development and a release branch for each major +release. New contributions are done against the head of the master branch. The CI -systems will pick up the Github Pull Requests or the new patch from -Patchwork, run some basic build and functional tests. +systems will pick up the Github Pull Requests or the new patch from Patchwork, +run some basic build and functional tests. -For each major release (1.0, 1.1 etc) a new release branch is created based -on the master. +For each major release (1.0, 1.1 etc) a new release branch is created based on +the master. -There was an attempt to use a "develop" branch automatically maintained by -the CI system. This is not currently in active use, though the system is -operational. If the "develop" branch is in active use and this paragraph -is still here, this document obviously wasn't updated. +There was an attempt to use a "develop" branch automatically maintained by the +CI system. This is not currently in active use, though the system is +operational. If the "develop" branch is in active use and this paragraph is +still here, this document obviously wasn't updated. ## Programming language, Tools and Libraries @@ -52,8 +52,8 @@ highlight this in your description of the change. Also make sure it’s supporte by all FRRouting platform OSes or provide a way to build without the library (potentially without the new feature) on the other platforms. -Documentation should be written in Tex (.texi) or Markdown (.md) format with -a preference for Markdown. +Documentation should be written in Tex (.texi) or Markdown (.md) format with a +preference for Markdown. ## Mailing lists @@ -150,22 +150,16 @@ the following: We've documented where we would like to have the different fixes applied at https://github.com/FRRouting/frr/wiki/Where-Do-I-create-a-Pull-Request-against%3F -If you are unsure where your submission goes, look at that document or ask -a project maintainer. +If you are unsure where your submission goes, look at that document or ask a +project maintainer. ### Github pull requests The preferred method of submitting changes is a Github pull request. Code -submitted by pull request will have an email generated to the FRRouting-devel -mailing list for review and the submission will be automatically tested by one -or more CI systems. Only after this test succeeds it will be automatically merged into -the develop branch. In case of failed tests, it is up to the submitter to -either amend the request with further commits or close, fix and create a new -pull request. - -Further (manual) code review and discussion happens after the merge into the -develop branch. - +submitted by pull request will be automatically tested by one or more CI +systems. Once the automated tests succeed, other developers will review your +code for quality and correctness. After any concerns are resolved, your code +will be merged into the branch it was submitted against. ### Patch submission via mailing list @@ -393,13 +387,13 @@ document previously undocumented code. ### Compile-time conditional code -Many users access FRR via binary packages from 3rd party sources; -compile-time code puts inclusion/exclusion in the hands of the package -maintainer. Please think very carefully before making code conditional at -compile time, as it increases regression testing, maintenance burdens, and user -confusion. In particular, please avoid gratuitous `--enable-…` switches to the -configure script - in general, code should be of high quality and in working -condition, or it shouldn’t be in FRR at all. +Many users access FRR via binary packages from 3rd party sources; compile-time +code puts inclusion/exclusion in the hands of the package maintainer. Please +think very carefully before making code conditional at compile time, as it +increases regression testing, maintenance burdens, and user confusion. In +particular, please avoid gratuitous `--enable-…` switches to the configure +script - in general, code should be of high quality and in working condition, +or it shouldn’t be in FRR at all. When code must be compile-time conditional, try have the compiler make it conditional rather than the C pre-processor so that it will still be checked by @@ -423,50 +417,47 @@ defined (watch your `AC_DEFINE`s). ### Debug-guards in code -Debugging statements are an important methodology to allow developers to fix issues -found in the code after it has been released. The caveat here is -that the developer must remember that people will be using the code -at scale and in ways that can be unexpected for the original implementor. -As such debugs **MUST** be guarded in such a way that they can be turned off. -FRR has the ability to turn on/off debugs from the CLI and it is -expected that the developer will use this convention to allow control -of their debugs. +Debugging statements are an important methodology to allow developers to fix +issues found in the code after it has been released. The caveat here is that +the developer must remember that people will be using the code at scale and in +ways that can be unexpected for the original implementor. As such debugs +**MUST** be guarded in such a way that they can be turned off. FRR has the +ability to turn on/off debugs from the CLI and it is expected that the +developer will use this convention to allow control of their debugs. ### CLI changes -CLI's are a complicated ugly beast. Additions or changes to the CLI -should use a DEFUN to encapsulate one setting as much as is possible. -Additionally as new DEFUN's are added to the system, documentation -should be provided for the new commands. +CLI's are a complicated ugly beast. Additions or changes to the CLI should use +a DEFUN to encapsulate one setting as much as is possible. Additionally as new +DEFUN's are added to the system, documentation should be provided for the new +commands. ### Backwards Compatibility -As a general principle, changes to CLI and code in the lib/ directory -should be made in a backwards compatible fashion. This means that -changes that are purely stylistic in nature should be avoided, e.g., -renaming an existing macro or library function name without any -functional change. When adding new parameters to common functions, it is -also good to consider if this too should be done in a backward -compatible fashion, e.g., by preserving the old form in addition to +As a general principle, changes to CLI and code in the lib/ directory should be +made in a backwards compatible fashion. This means that changes that are purely +stylistic in nature should be avoided, e.g., renaming an existing macro or +library function name without any functional change. When adding new parameters +to common functions, it is also good to consider if this too should be done in +a backward compatible fashion, e.g., by preserving the old form in addition to adding the new form. -This is not to say that minor or even major functional changes to CLI -and common code should be avoided, but rather that the benefit gained -from a change should be weighed against the added cost/complexity to -existing code. Also, that when making such changes, it is good to -preserve compatibility when possible to do so without introducing -maintenance overhead/cost. It is also important to keep in mind, -existing code includes code that may reside in private repositories (and -is yet to be submitted) or code that has yet to be migrated from Quagga -to FRR. +This is not to say that minor or even major functional changes to CLI and +common code should be avoided, but rather that the benefit gained from a change +should be weighed against the added cost/complexity to existing code. Also, +that when making such changes, it is good to preserve compatibility when +possible to do so without introducing maintenance overhead/cost. It is also +important to keep in mind, existing code includes code that may reside in +private repositories (and is yet to be submitted) or code that has yet to be +migrated from Quagga to FRR. That said, compatibility measures can (and should) be removed when either: -* they become a significant burden, e.g. when data structures change and - the compatibility measure would need a complex adaptation layer or becomes +* they become a significant burden, e.g. when data structures change and the + compatibility measure would need a complex adaptation layer or becomes flat-out impossible -* some measure of time (dependent on the specific case) has passed, so that - the compatibility grace period is considered expired. +* some measure of time (dependent on the specific case) has passed, so that the + compatibility grace period is considered expired. In all cases, compatibility pieces should be marked with compiler/preprocessor annotations to print warnings at compile time, pointing to the appropriate