diff options
author | Peter Hessler <phessler@cvs.openbsd.org> | 2016-09-17 07:35:06 +0000 |
---|---|---|
committer | Peter Hessler <phessler@cvs.openbsd.org> | 2016-09-17 07:35:06 +0000 |
commit | d118dd90a16827cdeebcbdb0b3176a3eaab78e29 (patch) | |
tree | b7a7fab9274b436b4a998291e1c711e52bbda5f7 | |
parent | 5b23b35c9fbb526f2d34f69fe63d2f74c61f24f4 (diff) |
*** empty log message ***
-rw-r--r-- | sys/net/bfd.c | 493 | ||||
-rw-r--r-- | sys/net/bfd.h | 111 | ||||
-rw-r--r-- | sys/net/route.c | 4 | ||||
-rw-r--r-- | sys/net/rtsock.c | 6 |
4 files changed, 308 insertions, 306 deletions
diff --git a/sys/net/bfd.c b/sys/net/bfd.c index d7b44b56710..1301b67d616 100644 --- a/sys/net/bfd.c +++ b/sys/net/bfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bfd.c,v 1.26 2016/09/15 08:39:44 phessler Exp $ */ +/* $OpenBSD: bfd.c,v 1.27 2016/09/17 07:35:05 phessler Exp $ */ /* * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org> @@ -140,36 +140,19 @@ struct bfd_auth_header { #define BFD_MINIMUM 10000 /* 10,000 us == 10 ms */ -/* These spellings and capitalizations match RFC 5880 6.8.1*/ -/* Do not change */ -struct bfd_state { - uint32_t SessionState; - uint32_t RemoteSessionState; - uint32_t LocalDiscr; /* Unique identifier */ - uint32_t RemoteDiscr; /* Unique identifier */ - uint32_t LocalDiag; - uint32_t RemoteDiag; - uint32_t DesiredMinTxInterval; - uint32_t RequiredMinRxInterval; - uint32_t RemoteMinRxInterval; - uint32_t DemandMode; - uint32_t RemoteDemandMode; - uint32_t DetectMult; /* Detection Time Multiplier*/ - uint32_t AuthType; - uint32_t RcvAuthSeq; - uint32_t XmitAuthSeq; - uint32_t AuthSeqKnown; -}; - -struct pool bfd_pool, bfd_pool_peer, bfd_pool_time; +struct pool bfd_pool, bfd_pool_neigh, bfd_pool_time; struct taskq *bfdtq; -struct socket *bfd_listener(struct bfd_softc *, unsigned int); -struct socket *bfd_sender(struct bfd_softc *, unsigned int); -void bfd_input(struct bfd_softc *, struct mbuf *); -void bfd_set_state(struct bfd_softc *, int); -int bfd_send(struct bfd_softc *, struct mbuf *); +struct bfd_config *bfd_lookup(struct rtentry *); +void bfddestroy(void); + +struct socket *bfd_listener(struct bfd_config *, unsigned int); +struct socket *bfd_sender(struct bfd_config *, unsigned int); +void bfd_input(struct bfd_config *, struct mbuf *); +void bfd_set_state(struct bfd_config *, int); + +int bfd_send(struct bfd_config *, struct mbuf *); void bfd_send_control(void *); void bfd_start_task(void *); @@ -178,21 +161,21 @@ void bfd_timeout_rx(void *); void bfd_timeout_tx(void *); void bfd_upcall(struct socket *, caddr_t, int); -void bfd_senddown(struct bfd_softc *); -void bfd_reset(struct bfd_softc *); -void bfd_set_uptime(struct bfd_softc *); +void bfd_senddown(struct bfd_config *); +void bfd_reset(struct bfd_config *); +void bfd_set_uptime(struct bfd_config *); -void bfd_debug(struct bfd_softc *); +void bfd_debug(struct bfd_config *); -TAILQ_HEAD(bfd_queue, bfd_softc) bfd_queue; +TAILQ_HEAD(bfd_queue, bfd_config) bfd_queue; /* * allocate a new bfd session */ int -bfd_rtalloc(struct rtentry *rt) +bfdset(struct rtentry *rt) { - struct bfd_softc *sc; + struct bfd_config *bfd; /* at the moment it is not allowed to run BFD on indirect routes */ if (ISSET(rt->rt_flags, RTF_GATEWAY) || !ISSET(rt->rt_flags, RTF_HOST)) @@ -203,26 +186,26 @@ bfd_rtalloc(struct rtentry *rt) return (EADDRINUSE); /* Do our necessary memory allocations upfront */ - sc = pool_get(&bfd_pool, PR_WAITOK | PR_ZERO); - sc->sc_peer = pool_get(&bfd_pool_peer, PR_WAITOK | PR_ZERO); - sc->sc_time = pool_get(&bfd_pool_time, PR_WAITOK | PR_ZERO); + bfd = pool_get(&bfd_pool, PR_WAITOK | PR_ZERO); + bfd->bc_neighbor = pool_get(&bfd_pool_neigh, PR_WAITOK | PR_ZERO); + bfd->bc_time = pool_get(&bfd_pool_time, PR_WAITOK | PR_ZERO); - sc->sc_rt = rt; - rtref(sc->sc_rt); /* we depend on this route not going away */ + bfd->bc_rt = rt; + rtref(bfd->bc_rt); /* we depend on this route not going away */ - microtime(sc->sc_time); - bfd_reset(sc); - sc->sc_peer->LocalDiscr = arc4random(); /* XXX - MUST be globally unique */ + microtime(bfd->bc_time); + bfd_reset(bfd); + bfd->bc_neighbor->bn_ldiscr = arc4random(); /* XXX - MUST be globally unique */ - if (!timeout_initialized(&sc->sc_timo_rx)) - timeout_set(&sc->sc_timo_rx, bfd_timeout_rx, sc); - if (!timeout_initialized(&sc->sc_timo_tx)) - timeout_set(&sc->sc_timo_tx, bfd_timeout_tx, sc); + if (!timeout_initialized(&bfd->bc_timo_rx)) + timeout_set(&bfd->bc_timo_rx, bfd_timeout_rx, bfd); + if (!timeout_initialized(&bfd->bc_timo_tx)) + timeout_set(&bfd->bc_timo_tx, bfd_timeout_tx, bfd); - task_set(&sc->sc_bfd_task, bfd_start_task, sc); - task_add(bfdtq, &sc->sc_bfd_task); + task_set(&bfd->bc_bfd_task, bfd_start_task, bfd); + task_add(bfdtq, &bfd->bc_bfd_task); - TAILQ_INSERT_TAIL(&bfd_queue, sc, bfd_next); + TAILQ_INSERT_TAIL(&bfd_queue, bfd, bc_entry); return (0); } @@ -231,41 +214,41 @@ bfd_rtalloc(struct rtentry *rt) * remove and free a bfd session */ void -bfd_rtfree(struct rtentry *rt) +bfdclear(struct rtentry *rt) { - struct bfd_softc *sc; + struct bfd_config *bfd; - if ((sc = bfd_lookup(rt)) == NULL) + if ((bfd = bfd_lookup(rt)) == NULL) return; - timeout_del(&sc->sc_timo_rx); - timeout_del(&sc->sc_timo_tx); - task_del(bfdtq, &sc->sc_bfd_send_task); + timeout_del(&bfd->bc_timo_rx); + timeout_del(&bfd->bc_timo_tx); + task_del(bfdtq, &bfd->bc_bfd_send_task); /* XXX - punt this off to a task */ - TAILQ_REMOVE(&bfd_queue, sc, bfd_next); + TAILQ_REMOVE(&bfd_queue, bfd, bc_entry); /* send suicide packets immediately */ - if (rtisvalid(sc->sc_rt)) - bfd_senddown(sc); + if (rtisvalid(bfd->bc_rt)) + bfd_senddown(bfd); - if (sc->sc_so) { + if (bfd->bc_so) { /* remove upcall before calling soclose or it will be called */ - sc->sc_so->so_upcall = NULL; - soclose(sc->sc_so); + bfd->bc_so->so_upcall = NULL; + soclose(bfd->bc_so); } - if (sc->sc_soecho) { - sc->sc_soecho->so_upcall = NULL; - soclose(sc->sc_soecho); + if (bfd->bc_soecho) { + bfd->bc_soecho->so_upcall = NULL; + soclose(bfd->bc_soecho); } - if (sc->sc_sosend) - soclose(sc->sc_sosend); + if (bfd->bc_sosend) + soclose(bfd->bc_sosend); - rtfree(sc->sc_rt); + rtfree(bfd->bc_rt); - pool_put(&bfd_pool_time, sc->sc_time); - pool_put(&bfd_pool_peer, sc->sc_peer); - pool_put(&bfd_pool, sc); + pool_put(&bfd_pool_time, bfd->bc_time); + pool_put(&bfd_pool_neigh, bfd->bc_neighbor); + pool_put(&bfd_pool, bfd); } /* @@ -274,12 +257,12 @@ bfd_rtfree(struct rtentry *rt) void bfdinit(void) { - pool_init(&bfd_pool, sizeof(struct bfd_softc), 0, - IPL_SOFTNET, 0, "bfd_softc", NULL); - pool_init(&bfd_pool_peer, sizeof(struct bfd_state), 0, - IPL_SOFTNET, 0, "bfd_softc_peer", NULL); + pool_init(&bfd_pool, sizeof(struct bfd_config), 0, + IPL_SOFTNET, 0, "bfd_config", NULL); + pool_init(&bfd_pool_neigh, sizeof(struct bfd_neighbor), 0, + IPL_SOFTNET, 0, "bfd_config_peer", NULL); pool_init(&bfd_pool_time, sizeof(struct timeval), 0, - IPL_SOFTNET, 0, "bfd_softc_time", NULL); + IPL_SOFTNET, 0, "bfd_config_time", NULL); bfdtq = taskq_create("bfd", 1, IPL_SOFTNET, 0); if (bfdtq == NULL) @@ -295,30 +278,30 @@ bfdinit(void) void bfddestroy(void) { - struct bfd_softc *sc; + struct bfd_config *bfd; /* send suicide packets immediately */ - while ((sc = TAILQ_FIRST(&bfd_queue))) { - bfd_rtfree(sc->sc_rt); + while ((bfd = TAILQ_FIRST(&bfd_queue))) { + bfdclear(bfd->bc_rt); } taskq_destroy(bfdtq); pool_destroy(&bfd_pool_time); - pool_destroy(&bfd_pool_peer); + pool_destroy(&bfd_pool_neigh); pool_destroy(&bfd_pool); } /* * Return the matching bfd */ -struct bfd_softc * +struct bfd_config * bfd_lookup(struct rtentry *rt) { - struct bfd_softc *sc; + struct bfd_config *bfd; - TAILQ_FOREACH(sc, &bfd_queue, bfd_next) { - if (sc->sc_rt == rt) - return (sc); + TAILQ_FOREACH(bfd, &bfd_queue, bc_entry) { + if (bfd->bc_rt == rt) + return (bfd); } return (NULL); } @@ -335,23 +318,23 @@ bfd_lookup(struct rtentry *rt) void bfd_start_task(void *arg) { - struct bfd_softc *sc = (struct bfd_softc *)arg; + struct bfd_config *bfd = (struct bfd_config *)arg; /* start listeners */ - sc->sc_so = bfd_listener(sc, BFD_UDP_PORT_CONTROL); - if (!sc->sc_so) + bfd->bc_so = bfd_listener(bfd, BFD_UDP_PORT_CONTROL); + if (!bfd->bc_so) printf("bfd_listener(%d) failed\n", BFD_UDP_PORT_CONTROL); - sc->sc_soecho = bfd_listener(sc, BFD_UDP_PORT_ECHO); - if (!sc->sc_soecho) + bfd->bc_soecho = bfd_listener(bfd, BFD_UDP_PORT_ECHO); + if (!bfd->bc_soecho) printf("bfd_listener(%d) failed\n", BFD_UDP_PORT_ECHO); /* start sending */ - sc->sc_sosend = bfd_sender(sc, BFD_UDP_PORT_CONTROL); - if (sc->sc_sosend) { - task_set(&sc->sc_bfd_send_task, bfd_send_task, sc); - task_add(bfdtq, &sc->sc_bfd_send_task); + bfd->bc_sosend = bfd_sender(bfd, BFD_UDP_PORT_CONTROL); + if (bfd->bc_sosend) { + task_set(&bfd->bc_bfd_send_task, bfd_send_task, bfd); + task_add(bfdtq, &bfd->bc_bfd_send_task); } return; @@ -360,33 +343,33 @@ bfd_start_task(void *arg) void bfd_send_task(void *arg) { - struct bfd_softc *sc = (struct bfd_softc *)arg; - struct rtentry *rt = sc->sc_rt; + struct bfd_config *bfd = (struct bfd_config *)arg; + struct rtentry *rt = bfd->bc_rt; if (ISSET(rt->rt_flags, RTF_UP)) { - bfd_send_control(sc); + bfd_send_control(bfd); } else { - sc->error++; - sc->sc_peer->LocalDiag = BFD_DIAG_ADMIN_DOWN; - if (sc->sc_peer->SessionState > BFD_STATE_DOWN) { - bfd_reset(sc); - bfd_set_state(sc, BFD_STATE_DOWN); + bfd->bc_error++; + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_ADMIN_DOWN; + if (bfd->bc_neighbor->bn_lstate > BFD_STATE_DOWN) { + bfd_reset(bfd); + bfd_set_state(bfd, BFD_STATE_DOWN); } } /* re-add 70%-90% jitter to our transmits, rfc 5880 6.8.7 */ - timeout_add_usec(&sc->sc_timo_tx, - sc->mintx * (arc4random_uniform(20) + 70) / 100); + timeout_add_usec(&bfd->bc_timo_tx, + bfd->bc_mintx * (arc4random_uniform(20) + 70) / 100); } /* * Setup a bfd listener socket */ struct socket * -bfd_listener(struct bfd_softc *sc, unsigned int port) +bfd_listener(struct bfd_config *bfd, unsigned int port) { struct proc *p = curproc; - struct rtentry *rt = sc->sc_rt; + struct rtentry *rt = bfd->bc_rt; struct sockaddr *src = rt->rt_ifa->ifa_addr; struct sockaddr *dst = rt_key(rt); struct sockaddr *sa; @@ -441,7 +424,7 @@ bfd_listener(struct bfd_softc *sc, unsigned int port) __func__, error); goto close; } - so->so_upcallarg = (caddr_t)sc; + so->so_upcallarg = (caddr_t)bfd; so->so_upcall = bfd_upcall; return (so); @@ -457,10 +440,10 @@ bfd_listener(struct bfd_softc *sc, unsigned int port) * Setup the bfd sending process */ struct socket * -bfd_sender(struct bfd_softc *sc, unsigned int port) +bfd_sender(struct bfd_config *bfd, unsigned int port) { struct socket *so; - struct rtentry *rt = sc->sc_rt; + struct rtentry *rt = bfd->bc_rt; struct proc *p = curproc; struct mbuf *m = NULL, *mopt = NULL; struct sockaddr *src = rt->rt_ifa->ifa_addr; @@ -563,7 +546,7 @@ bfd_sender(struct bfd_softc *sc, unsigned int port) void bfd_upcall(struct socket *so, caddr_t arg, int waitflag) { - struct bfd_softc *sc = (struct bfd_softc *)arg; + struct bfd_config *bfd = (struct bfd_config *)arg; struct mbuf *m; struct uio uio; int flags, error; @@ -574,11 +557,11 @@ bfd_upcall(struct socket *so, caddr_t arg, int waitflag) flags = MSG_DONTWAIT; error = soreceive(so, NULL, &uio, &m, NULL, &flags, 0); if (error && error != EAGAIN) { - sc->error++; + bfd->bc_error++; return; } if (m != NULL) - bfd_input(sc, m); + bfd_input(bfd, m); } while (m != NULL); return; @@ -588,8 +571,8 @@ bfd_upcall(struct socket *so, caddr_t arg, int waitflag) void bfd_timeout_tx(void *v) { - struct bfd_softc *sc = v; - task_add(bfdtq, &sc->sc_bfd_send_task); + struct bfd_config *bfd = v; + task_add(bfdtq, &bfd->bc_bfd_send_task); } /* @@ -598,37 +581,37 @@ bfd_timeout_tx(void *v) void bfd_timeout_rx(void *v) { - struct bfd_softc *sc = v; + struct bfd_config *bfd = v; - if ((sc->sc_peer->SessionState > BFD_STATE_DOWN) && - (++sc->error >= sc->sc_peer->DetectMult)) { - sc->sc_peer->LocalDiag = BFD_DIAG_EXPIRED; -printf("%s: failed, sc->error %u\n", __func__, sc->error); - bfd_reset(sc); - bfd_set_state(sc, BFD_STATE_DOWN); + if ((bfd->bc_neighbor->bn_lstate > BFD_STATE_DOWN) && + (++bfd->bc_error >= bfd->bc_neighbor->bn_mult)) { + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_EXPIRED; +printf("%s: failed, bfd->bc_error %u\n", __func__, bfd->bc_error); + bfd_reset(bfd); + bfd_set_state(bfd, BFD_STATE_DOWN); return; } - timeout_add_usec(&sc->sc_timo_rx, sc->minrx); + timeout_add_usec(&bfd->bc_timo_rx, bfd->bc_minrx); } /* * Tell our neighbor that we are going down */ void -bfd_senddown(struct bfd_softc *sc) +bfd_senddown(struct bfd_config *bfd) { /* If we are down, return early */ - if (sc->state < BFD_STATE_INIT) + if (bfd->bc_state < BFD_STATE_INIT) return; - sc->sc_peer->SessionState = BFD_STATE_ADMINDOWN; - if (sc->sc_peer->LocalDiag == 0) - sc->sc_peer->LocalDiag = BFD_DIAG_ADMIN_DOWN; + bfd->bc_neighbor->bn_lstate = BFD_STATE_ADMINDOWN; + if (bfd->bc_neighbor->bn_ldiag == 0) + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_ADMIN_DOWN; - bfd_send_control(sc); + bfd_send_control(bfd); return; } @@ -637,44 +620,44 @@ bfd_senddown(struct bfd_softc *sc) * Clean a BFD peer to defaults */ void -bfd_reset(struct bfd_softc *sc) +bfd_reset(struct bfd_config *bfd) { -if (sc->error) -printf("%s: error=%u\n", __func__, sc->error); +if (bfd->bc_error) +printf("%s: error=%u\n", __func__, bfd->bc_error); /* Clean */ - sc->sc_peer->RemoteDiscr = 0; - sc->sc_peer->DemandMode = 0; - sc->sc_peer->RemoteDemandMode = 0; - sc->sc_peer->AuthType = 0; - sc->sc_peer->RcvAuthSeq = 0; - sc->sc_peer->XmitAuthSeq = 0; - sc->sc_peer->AuthSeqKnown = 0; - sc->sc_peer->LocalDiag = 0; - - sc->mode = BFD_MODE_ASYNC; - sc->state = BFD_STATE_DOWN; + bfd->bc_neighbor->bn_rdiscr = 0; + bfd->bc_neighbor->bn_demand = 0; + bfd->bc_neighbor->bn_rdemand = 0; + bfd->bc_neighbor->bn_authtype = 0; + bfd->bc_neighbor->bn_rauthseq = 0; + bfd->bc_neighbor->bn_lauthseq = 0; + bfd->bc_neighbor->bn_authseqknown = 0; + bfd->bc_neighbor->bn_ldiag = 0; + + bfd->bc_mode = BFD_MODE_ASYNC; + bfd->bc_state = BFD_STATE_DOWN; /* Set RFC mandated values */ - sc->sc_peer->SessionState = BFD_STATE_DOWN; - sc->sc_peer->RemoteSessionState = BFD_STATE_DOWN; - sc->sc_peer->DesiredMinTxInterval = BFD_SECOND; - sc->sc_peer->RequiredMinRxInterval = BFD_SECOND; /* rfc5880 6.8.18 */ - sc->sc_peer->RemoteMinRxInterval = 1; - sc->sc_peer->DetectMult = 3; /* XXX - MUST be nonzero */ + bfd->bc_neighbor->bn_lstate = BFD_STATE_DOWN; + bfd->bc_neighbor->bn_rstate = BFD_STATE_DOWN; + bfd->bc_neighbor->bn_mintx = BFD_SECOND; + bfd->bc_neighbor->bn_req_minrx = BFD_SECOND; /* rfc5880 6.8.18 */ + bfd->bc_neighbor->bn_rminrx = 1; + bfd->bc_neighbor->bn_mult = 3; /* XXX - MUST be nonzero */ - sc->mintx = sc->sc_peer->DesiredMinTxInterval; - sc->minrx = sc->sc_peer->RemoteMinRxInterval; - sc->multiplier = sc->sc_peer->DetectMult; + bfd->bc_mintx = bfd->bc_neighbor->bn_mintx; + bfd->bc_minrx = bfd->bc_neighbor->bn_rminrx; + bfd->bc_multiplier = bfd->bc_neighbor->bn_mult; - bfd_set_uptime(sc); -printf("%s: localdiscr: %u\n", __func__, sc->sc_peer->LocalDiscr); + bfd_set_uptime(bfd); +printf("%s: localdiscr: %u\n", __func__, bfd->bc_neighbor->bn_ldiscr); return; } void -bfd_input(struct bfd_softc *sc, struct mbuf *m) +bfd_input(struct bfd_config *bfd, struct mbuf *m) { struct bfd_header *peer; struct bfd_auth_header *auth; @@ -709,18 +692,18 @@ bfd_input(struct bfd_softc *sc, struct mbuf *m) BFD_STATE(peer->bfd_sta_flags) > BFD_STATE_DOWN) goto discard; if ((ntohl(peer->bfd_your_discriminator) != 0) && - (ntohl(peer->bfd_your_discriminator) != sc->sc_peer->LocalDiscr)) { - sc->error++; + (ntohl(peer->bfd_your_discriminator) != bfd->bc_neighbor->bn_ldiscr)) { + bfd->bc_error++; printf("%s: peer your discr %u != local %u\n", - __func__, ntohl(peer->bfd_your_discriminator), sc->sc_peer->LocalDiscr); - sc->sc_peer->LocalDiag = BFD_DIAG_EXPIRED; - bfd_senddown(sc); + __func__, ntohl(peer->bfd_your_discriminator), bfd->bc_neighbor->bn_ldiscr); + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_EXPIRED; + bfd_senddown(bfd); goto discard; } - if ((flags & BFD_FLAG_A) && sc->sc_peer->AuthType == 0) + if ((flags & BFD_FLAG_A) && bfd->bc_neighbor->bn_authtype == 0) goto discard; - if (!(flags & BFD_FLAG_A) && sc->sc_peer->AuthType != 0) + if (!(flags & BFD_FLAG_A) && bfd->bc_neighbor->bn_authtype != 0) goto discard; if (flags & BFD_FLAG_A) { mp0 = m_pulldown(mp, 0, sizeof(*auth), &offp); @@ -728,130 +711,130 @@ printf("%s: peer your discr %u != local %u\n", goto discard; auth = (struct bfd_auth_header *)(mp0->m_data + offp); #if 0 - if (bfd_process_auth(sc, auth) != 0) { + if (bfd_process_auth(bfd, auth) != 0) { m_free(mp0); goto discard; } #endif } - if ((sc->sc_peer->RemoteDiscr == 0) && + if ((bfd->bc_neighbor->bn_rdiscr == 0) && (ntohl(peer->bfd_my_discriminator) != 0)) - sc->sc_peer->RemoteDiscr = ntohl(peer->bfd_my_discriminator); + bfd->bc_neighbor->bn_rdiscr = ntohl(peer->bfd_my_discriminator); - if (sc->sc_peer->RemoteDiscr != ntohl(peer->bfd_my_discriminator)) + if (bfd->bc_neighbor->bn_rdiscr != ntohl(peer->bfd_my_discriminator)) goto discard; - sc->sc_peer->RemoteSessionState = state; + bfd->bc_neighbor->bn_rstate = state; - sc->sc_peer->RemoteMinRxInterval = + bfd->bc_neighbor->bn_rminrx = ntohl(peer->bfd_required_min_rx_interval); /* Local change to the algorithm, we don't accept below 10ms */ - if (sc->sc_peer->RequiredMinRxInterval < BFD_MINIMUM) + if (bfd->bc_neighbor->bn_req_minrx < BFD_MINIMUM) goto discard; /* * Local change to the algorithm, we can't use larger than signed * 32bits for a timeout. * That is Too Long(tm) anyways. */ - if (sc->sc_peer->RequiredMinRxInterval > INT32_MAX) + if (bfd->bc_neighbor->bn_req_minrx > INT32_MAX) goto discard; - sc->minrx = sc->sc_peer->RequiredMinRxInterval; + bfd->bc_minrx = bfd->bc_neighbor->bn_req_minrx; - sc->sc_peer->DesiredMinTxInterval = + bfd->bc_neighbor->bn_mintx = htonl(peer->bfd_desired_min_tx_interval); - if (sc->sc_peer->SessionState != BFD_STATE_UP) - sc->sc_peer->DesiredMinTxInterval = BFD_SECOND; + if (bfd->bc_neighbor->bn_lstate != BFD_STATE_UP) + bfd->bc_neighbor->bn_mintx = BFD_SECOND; - sc->sc_peer->RequiredMinRxInterval = + bfd->bc_neighbor->bn_req_minrx = ntohl(peer->bfd_required_min_rx_interval); /* rfc5880 6.8.7 */ - sc->mintx = max(sc->sc_peer->RemoteMinRxInterval, - sc->sc_peer->DesiredMinTxInterval); - - if (sc->sc_peer->RemoteSessionState == BFD_STATE_ADMINDOWN) { - if (sc->sc_peer->SessionState != BFD_STATE_DOWN) { - sc->sc_peer->LocalDiag = BFD_DIAG_NEIGHBOR_SIGDOWN; - sc->sc_peer->SessionState = BFD_STATE_DOWN; - bfd_set_state(sc, BFD_STATE_DOWN); + bfd->bc_mintx = max(bfd->bc_neighbor->bn_rminrx, + bfd->bc_neighbor->bn_mintx); + + if (bfd->bc_neighbor->bn_rstate == BFD_STATE_ADMINDOWN) { + if (bfd->bc_neighbor->bn_lstate != BFD_STATE_DOWN) { + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_NEIGHBOR_SIGDOWN; + bfd->bc_neighbor->bn_lstate = BFD_STATE_DOWN; + bfd_set_state(bfd, BFD_STATE_DOWN); } goto discard; } /* According the to pseudo-code RFC 5880 page 34 */ - if (sc->sc_peer->SessionState == BFD_STATE_DOWN) { + if (bfd->bc_neighbor->bn_lstate == BFD_STATE_DOWN) { printf("%s: BFD_STATE_DOWN remote 0x%x ", __func__, ntohl(peer->bfd_my_discriminator)); printf("local 0x%x\n", ntohl(peer->bfd_your_discriminator)); -bfd_debug(sc); - if (sc->sc_peer->RemoteSessionState == BFD_STATE_DOWN) - sc->sc_peer->SessionState = BFD_STATE_INIT; - else if (sc->sc_peer->RemoteSessionState == BFD_STATE_INIT) { +bfd_debug(bfd); + if (bfd->bc_neighbor->bn_rstate == BFD_STATE_DOWN) + bfd->bc_neighbor->bn_lstate = BFD_STATE_INIT; + else if (bfd->bc_neighbor->bn_rstate == BFD_STATE_INIT) { printf("%s: set BFD_STATE_UP\n", __func__); - sc->sc_peer->LocalDiag = 0; - bfd_set_state(sc, BFD_STATE_UP); + bfd->bc_neighbor->bn_ldiag = 0; + bfd_set_state(bfd, BFD_STATE_UP); } - } else if (sc->sc_peer->SessionState == BFD_STATE_INIT) { + } else if (bfd->bc_neighbor->bn_lstate == BFD_STATE_INIT) { printf("%s: BFD_STATE_INIT remote 0x%x ", __func__, ntohl(peer->bfd_my_discriminator)); printf("local 0x%x\n", ntohl(peer->bfd_your_discriminator)); - if (sc->sc_peer->RemoteSessionState >= BFD_STATE_INIT) { + if (bfd->bc_neighbor->bn_rstate >= BFD_STATE_INIT) { printf("%s: set BFD_STATE_UP\n", __func__); - sc->sc_peer->LocalDiag = 0; - bfd_set_state(sc, BFD_STATE_UP); + bfd->bc_neighbor->bn_ldiag = 0; + bfd_set_state(bfd, BFD_STATE_UP); } else { goto discard; } } else { - if (sc->sc_peer->RemoteSessionState == BFD_STATE_DOWN) { + if (bfd->bc_neighbor->bn_rstate == BFD_STATE_DOWN) { printf("%s: set BFD_STATE_DOWN\n", __func__); - sc->sc_peer->LocalDiag = BFD_DIAG_NEIGHBOR_SIGDOWN; - bfd_set_state(sc, BFD_STATE_DOWN); + bfd->bc_neighbor->bn_ldiag = BFD_DIAG_NEIGHBOR_SIGDOWN; + bfd_set_state(bfd, BFD_STATE_DOWN); goto discard; } } - if (sc->sc_peer->SessionState == BFD_STATE_UP) { - sc->sc_peer->LocalDiag = 0; - sc->sc_peer->DemandMode = 1; - sc->sc_peer->RemoteDemandMode = (flags & BFD_FLAG_D); + if (bfd->bc_neighbor->bn_lstate == BFD_STATE_UP) { + bfd->bc_neighbor->bn_ldiag = 0; + bfd->bc_neighbor->bn_demand = 1; + bfd->bc_neighbor->bn_rdemand = (flags & BFD_FLAG_D); } - sc->error = 0; + bfd->bc_error = 0; discard: m_free(m); - //XXX task_add(bfdtq, &sc->sc_bfd_send_task); - timeout_add_usec(&sc->sc_timo_rx, sc->minrx); + //XXX task_add(bfdtq, &bfd->bc_bfd_send_task); + timeout_add_usec(&bfd->bc_timo_rx, bfd->bc_minrx); return; } void -bfd_set_state(struct bfd_softc *sc, int state) +bfd_set_state(struct bfd_config *bfd, int state) { struct ifnet *ifp; - struct rtentry *rt = sc->sc_rt; + struct rtentry *rt = bfd->bc_rt; int new_state; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { printf("%s: cannot find interface index %u\n", __func__, rt->rt_ifidx); - sc->error++; - bfd_reset(sc); + bfd->bc_error++; + bfd_reset(bfd); return; } - bfd_set_uptime(sc); + bfd_set_uptime(bfd); - sc->state = sc->sc_peer->SessionState = state; + bfd->bc_state = bfd->bc_neighbor->bn_lstate = state; if (!rtisvalid(rt)) - sc->sc_peer->SessionState = BFD_STATE_ADMINDOWN; + bfd->bc_neighbor->bn_lstate = BFD_STATE_ADMINDOWN; - switch (sc->sc_peer->SessionState) { + switch (bfd->bc_neighbor->bn_lstate) { case BFD_STATE_ADMINDOWN: new_state = RTM_BFD; // rt->rt_flags &= ~RTF_BFDUP; @@ -878,47 +861,47 @@ printf("%s: BFD set linkstate %u (oldstate: %u)\n", ifp->if_xname, new_state, st } void -bfd_set_uptime(struct bfd_softc *sc) +bfd_set_uptime(struct bfd_config *bfd) { struct timeval tv; microtime(&tv); - sc->lastuptime = tv.tv_sec - sc->sc_time->tv_sec; - sc->laststate = sc->state; - memcpy(sc->sc_time, &tv, sizeof(tv)); + bfd->bc_lastuptime = tv.tv_sec - bfd->bc_time->tv_sec; + bfd->bc_laststate = bfd->bc_state; + memcpy(bfd->bc_time, &tv, sizeof(tv)); } void bfd_send_control(void *x) { - struct bfd_softc *sc = x; + struct bfd_config *bfd = x; struct mbuf *m; - struct bfd_header *bfd; + struct bfd_header *h; int error; MGETHDR(m, M_WAIT, MT_DATA); MCLGET(m, M_WAIT); m->m_len = m->m_pkthdr.len = sizeof(*bfd); - bfd = mtod(m, struct bfd_header *); + h = mtod(m, struct bfd_header *); - memset(bfd, 0xff, sizeof(*bfd)); /* canary */ + memset(bfd, 0xff, sizeof(*h)); /* canary */ - bfd->bfd_ver_diag = ((BFD_VERSION << 5) | (sc->sc_peer->LocalDiag)); - bfd->bfd_sta_flags = (sc->sc_peer->SessionState << 6); - bfd->bfd_detect_multi = sc->sc_peer->DetectMult; - bfd->bfd_length = BFD_HDRLEN; - bfd->bfd_my_discriminator = htonl(sc->sc_peer->LocalDiscr); - bfd->bfd_your_discriminator = htonl(sc->sc_peer->RemoteDiscr); + h->bfd_ver_diag = ((BFD_VERSION << 5) | (bfd->bc_neighbor->bn_ldiag)); + h->bfd_sta_flags = (bfd->bc_neighbor->bn_lstate << 6); + h->bfd_detect_multi = bfd->bc_neighbor->bn_mult; + h->bfd_length = BFD_HDRLEN; + h->bfd_my_discriminator = htonl(bfd->bc_neighbor->bn_ldiscr); + h->bfd_your_discriminator = htonl(bfd->bc_neighbor->bn_rdiscr); - bfd->bfd_desired_min_tx_interval = - htonl(sc->sc_peer->DesiredMinTxInterval); - bfd->bfd_required_min_rx_interval = - htonl(sc->sc_peer->RequiredMinRxInterval); - bfd->bfd_required_min_echo_interval = - htonl(sc->sc_peer->RemoteMinRxInterval); + h->bfd_desired_min_tx_interval = + htonl(bfd->bc_neighbor->bn_mintx); + h->bfd_required_min_rx_interval = + htonl(bfd->bc_neighbor->bn_req_minrx); + h->bfd_required_min_echo_interval = + htonl(bfd->bc_neighbor->bn_rminrx); - error = bfd_send(sc, m); + error = bfd_send(bfd, m); if (error) { if (!(error == EHOSTDOWN || error == ECONNREFUSED)) { @@ -928,25 +911,25 @@ bfd_send_control(void *x) } int -bfd_send(struct bfd_softc *sc, struct mbuf *m) +bfd_send(struct bfd_config *bfd, struct mbuf *m) { - struct rtentry *rt = sc->sc_rt; + struct rtentry *rt = bfd->bc_rt; if (!ISSET(rt->rt_flags, RTF_UP)) { m_freem(m); return (EHOSTDOWN); } - return (sosend(sc->sc_sosend, NULL, NULL, m, NULL, MSG_DONTWAIT)); + return (sosend(bfd->bc_sosend, NULL, NULL, m, NULL, MSG_DONTWAIT)); } /* * Print debug information about this bfd instance */ void -bfd_debug(struct bfd_softc *sc) +bfd_debug(struct bfd_config *bfd) { - struct rtentry *rt = sc->sc_rt; + struct rtentry *rt = bfd->bc_rt; struct timeval tv; char buf[64]; @@ -955,32 +938,32 @@ bfd_debug(struct bfd_softc *sc) sizeof(buf))); printf("\n"); printf("\t"); - printf("session state: %u ", sc->state); - printf("mode: %u ", sc->mode); - printf("error: %u ", sc->error); - printf("minrx: %u ", sc->minrx); - printf("mintx: %u ", sc->mintx); - printf("multiplier: %u ", sc->multiplier); + printf("session state: %u ", bfd->bc_state); + printf("mode: %u ", bfd->bc_mode); + printf("error: %u ", bfd->bc_error); + printf("minrx: %u ", bfd->bc_minrx); + printf("mintx: %u ", bfd->bc_mintx); + printf("multiplier: %u ", bfd->bc_multiplier); printf("\n"); printf("\t"); - printf("local session state: %u ", sc->sc_peer->SessionState); - printf("local diag: %u ", sc->sc_peer->LocalDiag); + printf("local session state: %u ", bfd->bc_neighbor->bn_lstate); + printf("local diag: %u ", bfd->bc_neighbor->bn_ldiag); printf("\n"); printf("\t"); - printf("remote discriminator: %u ", sc->sc_peer->RemoteDiscr); - printf("local discriminator: %u ", sc->sc_peer->LocalDiscr); + printf("remote discriminator: %u ", bfd->bc_neighbor->bn_rdiscr); + printf("local discriminator: %u ", bfd->bc_neighbor->bn_ldiscr); printf("\n"); printf("\t"); - printf("remote session state: %u ", sc->sc_peer->RemoteSessionState); - printf("remote diag: %u ", sc->sc_peer->RemoteDiag); - printf("remote min rx: %u ", sc->sc_peer->RemoteMinRxInterval); + printf("remote session state: %u ", bfd->bc_neighbor->bn_rstate); + printf("remote diag: %u ", bfd->bc_neighbor->bn_rdiag); + printf("remote min rx: %u ", bfd->bc_neighbor->bn_rminrx); printf("\n"); printf("\t"); - printf("last state: %u ", sc->laststate); + printf("last state: %u ", bfd->bc_laststate); getmicrotime(&tv); - printf("uptime %llds ", tv.tv_sec - sc->sc_time->tv_sec); - printf("time started %lld.%06ld ", sc->sc_time->tv_sec, - sc->sc_time->tv_usec); - printf("last uptime %llds ", sc->lastuptime); + printf("uptime %llds ", tv.tv_sec - bfd->bc_time->tv_sec); + printf("time started %lld.%06ld ", bfd->bc_time->tv_sec, + bfd->bc_time->tv_usec); + printf("last uptime %llds ", bfd->bc_lastuptime); printf("\n"); } diff --git a/sys/net/bfd.h b/sys/net/bfd.h index 26031dabd9d..b36f7948cac 100644 --- a/sys/net/bfd.h +++ b/sys/net/bfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bfd.h,v 1.6 2016/09/15 13:09:44 phessler Exp $ */ +/* $OpenBSD: bfd.h,v 1.7 2016/09/17 07:35:05 phessler Exp $ */ /* * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org> @@ -54,57 +54,76 @@ #define BFD_FLAG_M 0x01 struct bfd_msghdr { - unsigned short rtm_msglen; /* to skip over non-understood msgs */ - unsigned char rtm_version; /* future binary compatibility */ - unsigned char rtm_type; /* message type */ - unsigned short rtm_hdrlen; /* to skip over the header */ - - uint16_t mode; /* */ - uint32_t mintx; /* minimum time (us) to send */ - uint32_t minrx; /* minimum window (us) to receive */ - uint16_t multiplier; /* Retry backoff multiplier */ - - time_t uptime; - time_t lastuptime; - int state; - int laststate; - int error; - - uint32_t localdiscr; - uint32_t localdiag; - uint32_t remotediscr; - uint32_t remotediag; + unsigned short bm_msglen; + unsigned char bm_version; + unsigned char bm_type; + unsigned short bm_hdrlen; + /* above matches rtm_msghdr */ + + uint16_t bm_mode; + uint32_t bm_mintx; + uint32_t bm_minrx; + uint16_t bm_multiplier; + + time_t bm_uptime; + time_t bm_lastuptime; + int bm_state; + int bm_laststate; + int bm_error; + + uint32_t bm_localdiscr; + uint32_t bm_localdiag; + uint32_t bm_remotediscr; + uint32_t bm_remotediag; }; #ifdef _KERNEL -struct bfd_softc { - TAILQ_ENTRY(bfd_softc) bfd_next; - struct socket *sc_so; - struct socket *sc_soecho; - struct socket *sc_sosend; - struct rtentry *sc_rt; - struct bfd_state *sc_peer; - struct timeval *sc_time; - struct task sc_bfd_task; - struct task sc_bfd_send_task; - struct timeout sc_timo_rx; - struct timeout sc_timo_tx; - time_t lastuptime; - int laststate; - int state; - int mode; - int error; - int minrx; - int mintx; - int multiplier; +/* state machine from RFC 5880 6.8.1*/ +struct bfd_neighbor { + uint32_t bn_lstate; /* SessionState */ + uint32_t bn_rstate; /* RemoteSessionState */ + uint32_t bn_ldiscr; /* LocalDiscr */ + uint32_t bn_rdiscr; /* RemoteDiscr */ + uint32_t bn_ldiag; /* LocalDiag */ + uint32_t bn_rdiag; /* RemoteDiag */ + uint32_t bn_mintx; /* DesiredMinTxInterval */ + uint32_t bn_req_minrx; /* RequiredMinRxInterval */ + uint32_t bn_rminrx; /* RemoteMinRxInterval */ + uint32_t bn_demand; /* DemandMode */ + uint32_t bn_rdemand; /* RemoteDemandMode */ + uint32_t bn_mult; /* DetectMult */ + uint32_t bn_authtype; /* AuthType */ + uint32_t bn_rauthseq; /* RcvAuthSeq */ + uint32_t bn_lauthseq; /* XmitAuthSeq */ + uint32_t bn_authseqknown; /* AuthSeqKnown */ +}; + +struct bfd_config { + TAILQ_ENTRY(bfd_config) bc_entry; + struct socket *bc_so; + struct socket *bc_soecho; + struct socket *bc_sosend; + struct rtentry *bc_rt; + struct bfd_neighbor *bc_neighbor; + struct timeval *bc_time; + struct task bc_bfd_task; + struct task bc_bfd_send_task; + struct timeout bc_timo_rx; + struct timeout bc_timo_tx; + time_t bc_lastuptime; + int bc_laststate; + int bc_state; + int bc_mode; + int bc_error; + int bc_minrx; + int bc_mintx; + int bc_multiplier; }; -#endif /* _KERNEL */ -int bfd_rtalloc(struct rtentry *); -void bfd_rtfree(struct rtentry *); +int bfdset(struct rtentry *); +void bfdclear(struct rtentry *); void bfdinit(void); -void bfddestroy(void); -struct bfd_softc *bfd_lookup(struct rtentry *); +#endif /* _KERNEL */ #endif /* _NET_BFD_H_ */ diff --git a/sys/net/route.c b/sys/net/route.c index d15074e92cb..b80fbc459a8 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.329 2016/09/15 02:00:18 dlg Exp $ */ +/* $OpenBSD: route.c,v 1.330 2016/09/17 07:35:05 phessler Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -889,7 +889,7 @@ rtrequest_delete(struct rt_addrinfo *info, u_int8_t prio, struct ifnet *ifp, #ifdef BFD if (ISSET(rt->rt_flags, RTF_BFD)) - bfd_rtfree(rt); + bfdclear(rt); #endif /* Release next hop cache before flushing cloned entries. */ diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 014d46c82e8..9e0b4ef8087 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.204 2016/09/07 09:36:49 mpi Exp $ */ +/* $OpenBSD: rtsock.c,v 1.205 2016/09/17 07:35:05 phessler Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -885,11 +885,11 @@ change: #ifdef BFD if (ISSET(rtm->rtm_flags, RTF_BFD)) { - if ((error = bfd_rtalloc(rt))) + if ((error = bfdset(rt))) goto flush; } else if (!ISSET(rtm->rtm_flags, RTF_BFD) && ISSET(rtm->rtm_fmask, RTF_BFD)) { - bfd_rtfree(rt); + bfdclear(rt); } #endif |