diff options
Diffstat (limited to 'bfdd/ptm_adapter.c')
| -rw-r--r-- | bfdd/ptm_adapter.c | 152 |
1 files changed, 118 insertions, 34 deletions
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 8d80b9468d..3e2ace6ea6 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -58,7 +58,7 @@ static struct zclient *zclient; static int _ptm_msg_address(struct stream *msg, int family, const void *addr); static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa); -static int _ptm_msg_read(struct stream *msg, int command, +static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, struct bfd_peer_cfg *bpc, struct ptm_client **pc); static struct ptm_client *pc_lookup(uint32_t pid); @@ -72,8 +72,8 @@ static struct ptm_client_notification *pcn_lookup(struct ptm_client *pc, static void pcn_free(struct ptm_client_notification *pcn); -static void bfdd_dest_register(struct stream *msg); -static void bfdd_dest_deregister(struct stream *msg); +static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id); +static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id); static void bfdd_client_register(struct stream *msg); static void bfdd_client_deregister(struct stream *msg); @@ -89,6 +89,7 @@ static void debug_printbpc(const char *func, unsigned int line, { char addr[3][128]; char timers[3][128]; + char cbit_str[10]; addr[0][0] = addr[1][0] = addr[2][0] = timers[0][0] = timers[1][0] = timers[2][0] = 0; @@ -117,9 +118,11 @@ static void debug_printbpc(const char *func, unsigned int line, snprintf(timers[2], sizeof(timers[2]), " detect-multiplier:%d", bpc->bpc_detectmultiplier); - log_debug("%s:%d: %s %s%s%s%s%s%s", func, line, + sprintf(cbit_str, "CB %x", bpc->bpc_cbit); + + log_debug("%s:%d: %s %s%s%s%s%s%s %s", func, line, bpc->bpc_mhop ? "multi-hop" : "single-hop", addr[0], addr[1], - addr[2], timers[0], timers[1], timers[2]); + addr[2], timers[0], timers[1], timers[2], cbit_str); } #define DEBUG_PRINTBPC(bpc) debug_printbpc(__FILE__, __LINE__, (bpc)) @@ -173,6 +176,7 @@ int ptm_bfd_notify(struct bfd_session *bs) * - AF_INET6: * - 16 bytes: ipv6 * - c: prefix length + * - c: cbit * * Commands: ZEBRA_BFD_DEST_REPLAY * @@ -182,7 +186,10 @@ int ptm_bfd_notify(struct bfd_session *bs) stream_reset(msg); /* TODO: VRF handling */ - zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT); + if (bs->vrf) + zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, bs->vrf->vrf_id); + else + zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT); /* This header will be handled by `zebra_ptm.c`. */ stream_putl(msg, ZEBRA_INTERFACE_BFD_DEST_UPDATE); @@ -216,6 +223,8 @@ int ptm_bfd_notify(struct bfd_session *bs) /* BFD source prefix information. */ _ptm_msg_address(msg, bs->key.family, &bs->key.local); + stream_putc(msg, bs->remote_cbit); + /* Write packet size. */ stream_putw_at(msg, 0, stream_get_endp(msg)); @@ -256,7 +265,7 @@ stream_failure: memset(sa, 0, sizeof(*sa)); } -static int _ptm_msg_read(struct stream *msg, int command, +static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, struct bfd_peer_cfg *bpc, struct ptm_client **pc) { uint32_t pid; @@ -290,6 +299,7 @@ static int _ptm_msg_read(struct stream *msg, int command, * - 16 bytes: ipv6 address * - c: ifname length * - X bytes: interface name + * - c: bfd_cbit * * q(64), l(32), w(16), c(8) */ @@ -355,6 +365,20 @@ static int _ptm_msg_read(struct stream *msg, int command, bpc->bpc_localif[ifnamelen] = 0; } } + if (vrf_id != VRF_DEFAULT) { + struct vrf *vrf; + + vrf = vrf_lookup_by_id(vrf_id); + if (vrf) { + bpc->bpc_has_vrfname = true; + strlcpy(bpc->bpc_vrfname, vrf->name, sizeof(bpc->bpc_vrfname)); + } else { + log_error("ptm-read: vrf id %u could not be identified", vrf_id); + return -1; + } + } + + STREAM_GETC(msg, bpc->bpc_cbit); /* Sanity check: peer and local address must match IP types. */ if (bpc->bpc_local.sa_sin.sin_family != 0 @@ -370,7 +394,7 @@ stream_failure: return -1; } -static void bfdd_dest_register(struct stream *msg) +static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id) { struct ptm_client *pc; struct ptm_client_notification *pcn; @@ -378,7 +402,7 @@ static void bfdd_dest_register(struct stream *msg) struct bfd_peer_cfg bpc; /* Read the client context and peer data. */ - if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, &bpc, &pc) == -1) + if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, vrf_id, &bpc, &pc) == -1) return; DEBUG_PRINTBPC(&bpc); @@ -408,7 +432,7 @@ static void bfdd_dest_register(struct stream *msg) ptm_bfd_notify(bs); } -static void bfdd_dest_deregister(struct stream *msg) +static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id) { struct ptm_client *pc; struct ptm_client_notification *pcn; @@ -416,7 +440,7 @@ static void bfdd_dest_deregister(struct stream *msg) struct bfd_peer_cfg bpc; /* Read the client context and peer data. */ - if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, &bpc, &pc) == -1) + if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, vrf_id, &bpc, &pc) == -1) return; DEBUG_PRINTBPC(&bpc); @@ -431,6 +455,10 @@ static void bfdd_dest_deregister(struct stream *msg) /* Unregister client peer notification. */ pcn = pcn_lookup(pc, bs); pcn_free(pcn); + if (bs->refcount || + BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) + return; + ptm_bfd_sess_del(&bpc); } /* @@ -483,9 +511,9 @@ stream_failure: log_error("ptm-del-client: failed to deregister client"); } -static int bfdd_replay(int cmd, struct zclient *zc, uint16_t len, vrf_id_t vid) +static int bfdd_replay(ZAPI_CALLBACK_ARGS) { - struct stream *msg = zc->ibuf; + struct stream *msg = zclient->ibuf; uint32_t rcmd; STREAM_GETL(msg, rcmd); @@ -493,10 +521,10 @@ static int bfdd_replay(int cmd, struct zclient *zc, uint16_t len, vrf_id_t vid) switch (rcmd) { case ZEBRA_BFD_DEST_REGISTER: case ZEBRA_BFD_DEST_UPDATE: - bfdd_dest_register(msg); + bfdd_dest_register(msg, vrf_id); break; case ZEBRA_BFD_DEST_DEREGISTER: - bfdd_dest_deregister(msg); + bfdd_dest_deregister(msg, vrf_id); break; case ZEBRA_BFD_CLIENT_REGISTER: bfdd_client_register(msg); @@ -544,15 +572,21 @@ static void bfdd_sessions_enable_interface(struct interface *ifp) { struct bfd_session_observer *bso; struct bfd_session *bs; + struct vrf *vrf; TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) { + bs = bso->bso_bs; if (bso->bso_isinterface == false) continue; - /* Interface name mismatch. */ - bs = bso->bso_bs; if (strcmp(ifp->name, bs->key.ifname)) continue; + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (!vrf) + continue; + if (bs->key.vrfname[0] && + strcmp(vrf->name, bs->key.vrfname)) + continue; /* Skip enabled sessions. */ if (bs->sock != -1) continue; @@ -582,13 +616,56 @@ static void bfdd_sessions_disable_interface(struct interface *ifp) /* Try to enable it. */ bfd_session_disable(bs); - TAILQ_INSERT_HEAD(&bglobal.bg_obslist, bso, bso_entry); } } -static int bfdd_interface_update(int cmd, struct zclient *zc, - uint16_t len __attribute__((__unused__)), - vrf_id_t vrfid) +void bfdd_sessions_enable_vrf(struct vrf *vrf) +{ + struct bfd_session_observer *bso; + struct bfd_session *bs; + + /* it may affect configs without interfaces */ + TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) { + bs = bso->bso_bs; + if (bs->vrf) + continue; + if (bs->key.vrfname[0] && + strcmp(vrf->name, bs->key.vrfname)) + continue; + /* need to update the vrf information on + * bs so that callbacks are handled + */ + bs->vrf = vrf; + /* Skip enabled sessions. */ + if (bs->sock != -1) + continue; + /* Try to enable it. */ + bfd_session_enable(bs); + } +} + +void bfdd_sessions_disable_vrf(struct vrf *vrf) +{ + struct bfd_session_observer *bso; + struct bfd_session *bs; + + TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) { + if (bso->bso_isinterface) + continue; + bs = bso->bso_bs; + if (bs->key.vrfname[0] && + strcmp(vrf->name, bs->key.vrfname)) + continue; + /* Skip disabled sessions. */ + if (bs->sock == -1) + continue; + + /* Try to enable it. */ + bfd_session_disable(bs); + } +} + +static int bfdd_interface_update(ZAPI_CALLBACK_ARGS) { struct interface *ifp; @@ -598,7 +675,7 @@ static int bfdd_interface_update(int cmd, struct zclient *zc, * rolling our own. */ if (cmd == ZEBRA_INTERFACE_ADD) { - ifp = zebra_interface_add_read(zc->ibuf, vrfid); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); if (ifp == NULL) return 0; @@ -607,7 +684,7 @@ static int bfdd_interface_update(int cmd, struct zclient *zc, } /* Update interface information. */ - ifp = zebra_interface_state_read(zc->ibuf, vrfid); + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); if (ifp == NULL) return 0; @@ -618,16 +695,12 @@ static int bfdd_interface_update(int cmd, struct zclient *zc, return 0; } -static int bfdd_interface_vrf_update(int command __attribute__((__unused__)), - struct zclient *zclient, - zebra_size_t length - __attribute__((__unused__)), - vrf_id_t vrfid) +static int bfdd_interface_vrf_update(ZAPI_CALLBACK_ARGS) { struct interface *ifp; vrf_id_t nvrfid; - ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrfid, &nvrfid); + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, &nvrfid); if (ifp == NULL) return 0; @@ -662,14 +735,11 @@ static void bfdd_sessions_enable_address(struct connected *ifc) } } -static int bfdd_interface_address_update(int cmd, struct zclient *zc, - zebra_size_t len - __attribute__((__unused__)), - vrf_id_t vrfid) +static int bfdd_interface_address_update(ZAPI_CALLBACK_ARGS) { struct connected *ifc; - ifc = zebra_interface_address_read(cmd, zc->ibuf, vrfid); + ifc = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); if (ifc == NULL) return 0; @@ -706,6 +776,20 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) zclient->interface_address_delete = bfdd_interface_address_update; } +void bfdd_zclient_register(vrf_id_t vrf_id) +{ + if (!zclient || zclient->sock < 0) + return; + zclient_send_reg_requests(zclient, vrf_id); +} + +void bfdd_zclient_unregister(vrf_id_t vrf_id) +{ + if (!zclient || zclient->sock < 0) + return; + zclient_send_dereg_requests(zclient, vrf_id); +} + void bfdd_zclient_stop(void) { zclient_stop(zclient); |
