diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index d3d54c1780..90e2df2367 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -84,10 +84,11 @@ static void bfdd_client_deregister(struct stream *msg); static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...) { char timers[3][128] = {}; + char minttl_str[32] = {}; char addr[3][128] = {}; char profile[128] = {}; char cbit_str[32]; - char msgbuf[256]; + char msgbuf[512]; va_list vl; /* Avoid debug calculations if it's disabled. */ @@ -120,6 +121,10 @@ static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...) snprintf(cbit_str, sizeof(cbit_str), " cbit:0x%02x", bpc->bpc_cbit); + if (bpc->bpc_has_minimum_ttl) + snprintf(minttl_str, sizeof(minttl_str), " minimum-ttl:%d", + bpc->bpc_minimum_ttl); + if (bpc->bpc_has_profile) snprintf(profile, sizeof(profile), " profile:%s", bpc->bpc_profile); @@ -128,9 +133,10 @@ static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...) vsnprintf(msgbuf, sizeof(msgbuf), fmt, vl); va_end(vl); - zlog_debug("%s [mhop:%s %s%s%s%s%s%s%s%s]", msgbuf, + zlog_debug("%s [mhop:%s %s%s%s%s%s%s%s%s%s]", msgbuf, bpc->bpc_mhop ? "yes" : "no", addr[0], addr[1], addr[2], - timers[0], timers[1], timers[2], cbit_str, profile); + timers[0], timers[1], timers[2], cbit_str, minttl_str, + profile); } static void _ptm_bfd_session_del(struct bfd_session *bs, uint8_t diag) @@ -307,6 +313,8 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, /* * Register/Deregister/Update Message format: + * + * Old format (being used by PTM BFD). * - header: Command, VRF * - l: pid * - w: family @@ -322,16 +330,37 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, * - multihop: * - w: family * - AF_INET: - * - l: destination ipv4 + * - l: source IPv4 address * - AF_INET6: - * - 16 bytes: destination IPv6 + * - 16 bytes: source IPv6 address * - c: ttl * - no multihop * - AF_INET6: * - w: family - * - 16 bytes: ipv6 address + * - 16 bytes: source IPv6 address * - c: ifname length * - X bytes: interface name + * + * New format: + * - header: Command, VRF + * - l: pid + * - w: family + * - AF_INET: + * - l: destination IPv4 address + * - AF_INET6: + * - 16 bytes: destination IPv6 address + * - l: min_rx + * - l: min_tx + * - c: detect multiplier + * - c: is_multihop? + * - w: family + * - AF_INET: + * - l: source IPv4 address + * - AF_INET6: + * - 16 bytes: source IPv6 address + * - c: ttl + * - c: ifname length + * - X bytes: interface name * - c: bfd_cbit * - c: profile name length. * - X bytes: profile name. @@ -355,58 +384,50 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, bpc->bpc_ipv4 = (bpc->bpc_peer.sa_sin.sin_family == AF_INET); /* Get peer configuration. */ - if (command != ZEBRA_BFD_DEST_DEREGISTER) { - STREAM_GETL(msg, bpc->bpc_recvinterval); - bpc->bpc_has_recvinterval = - (bpc->bpc_recvinterval != BPC_DEF_RECEIVEINTERVAL); + STREAM_GETL(msg, bpc->bpc_recvinterval); + bpc->bpc_has_recvinterval = + (bpc->bpc_recvinterval != BPC_DEF_RECEIVEINTERVAL); - STREAM_GETL(msg, bpc->bpc_txinterval); - bpc->bpc_has_txinterval = - (bpc->bpc_txinterval != BPC_DEF_TRANSMITINTERVAL); + STREAM_GETL(msg, bpc->bpc_txinterval); + bpc->bpc_has_txinterval = + (bpc->bpc_txinterval != BPC_DEF_TRANSMITINTERVAL); - STREAM_GETC(msg, bpc->bpc_detectmultiplier); - bpc->bpc_has_detectmultiplier = - (bpc->bpc_detectmultiplier != BPC_DEF_DETECTMULTIPLIER); - } + STREAM_GETC(msg, bpc->bpc_detectmultiplier); + bpc->bpc_has_detectmultiplier = + (bpc->bpc_detectmultiplier != BPC_DEF_DETECTMULTIPLIER); /* Read (single|multi)hop and its options. */ STREAM_GETC(msg, bpc->bpc_mhop); - if (bpc->bpc_mhop) { - /* Read multihop source address and TTL. */ - _ptm_msg_read_address(msg, &bpc->bpc_local); - STREAM_GETC(msg, bpc->bpc_minimum_ttl); - if (bpc->bpc_minimum_ttl >= BFD_TTL_VAL - || bpc->bpc_minimum_ttl == 0) { - zlog_warn("%s: received invalid TTL configuration %d", - __func__, bpc->bpc_has_minimum_ttl); - bpc->bpc_minimum_ttl = BFD_DEF_MHOP_TTL; - bpc->bpc_has_minimum_ttl = false; - } else { - bpc->bpc_minimum_ttl = - (BFD_TTL_VAL + 1) - bpc->bpc_minimum_ttl; - bpc->bpc_has_minimum_ttl = true; - } + + /* Read multihop source address and TTL. */ + _ptm_msg_read_address(msg, &bpc->bpc_local); + + /* Read the minimum TTL (0 means unset or invalid). */ + STREAM_GETC(msg, bpc->bpc_minimum_ttl); + if (bpc->bpc_minimum_ttl == 0) { + bpc->bpc_minimum_ttl = BFD_DEF_MHOP_TTL; + bpc->bpc_has_minimum_ttl = false; } else { - /* If target is IPv6, then we must obtain local address. */ - if (bpc->bpc_ipv4 == false) - _ptm_msg_read_address(msg, &bpc->bpc_local); - - /* - * Read interface name and make sure it fits our data - * structure, otherwise fail. - */ - STREAM_GETC(msg, ifnamelen); - if (ifnamelen >= sizeof(bpc->bpc_localif)) { - zlog_err("ptm-read: interface name is too big"); - return -1; - } - - bpc->bpc_has_localif = ifnamelen > 0; - if (bpc->bpc_has_localif) { - STREAM_GET(bpc->bpc_localif, msg, ifnamelen); - bpc->bpc_localif[ifnamelen] = 0; - } + bpc->bpc_minimum_ttl = (BFD_TTL_VAL + 1) - bpc->bpc_minimum_ttl; + bpc->bpc_has_minimum_ttl = true; } + + /* + * Read interface name and make sure it fits our data + * structure, otherwise fail. + */ + STREAM_GETC(msg, ifnamelen); + if (ifnamelen >= sizeof(bpc->bpc_localif)) { + zlog_err("ptm-read: interface name is too big"); + return -1; + } + + bpc->bpc_has_localif = ifnamelen > 0; + if (bpc->bpc_has_localif) { + STREAM_GET(bpc->bpc_localif, msg, ifnamelen); + bpc->bpc_localif[ifnamelen] = 0; + } + if (vrf_id != VRF_DEFAULT) { struct vrf *vrf; @@ -424,6 +445,7 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname)); } + /* Read control plane independant configuration. */ STREAM_GETC(msg, bpc->bpc_cbit); /* Handle profile names. */ diff --git a/lib/bfd.c b/lib/bfd.c index d1a0ec671e..1a37b348f8 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -104,7 +104,10 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, if (((*bfd_info)->required_min_rx != min_rx) || ((*bfd_info)->desired_min_tx != min_tx) || ((*bfd_info)->detect_mult != detect_mult) - || (profile && strcmp((*bfd_info)->profile, profile))) + || ((*bfd_info)->profile[0] == 0 && profile) + || ((*bfd_info)->profile[0] && profile == NULL) + || (profile && (*bfd_info)->profile[0] + && strcmp((*bfd_info)->profile, profile))) *command = ZEBRA_BFD_DEST_UPDATE; } @@ -468,6 +471,39 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) : sizeof(struct in6_addr); stream_put(s, &args->dst, addrlen); + /* + * For more BFD integration protocol details, see function + * `_ptm_msg_read` in `bfdd/ptm_adapter.c`. + */ +#if HAVE_BFDD > 0 + /* Session timers. */ + stream_putl(s, args->min_rx); + stream_putl(s, args->min_tx); + stream_putc(s, args->detection_multiplier); + + /* Is multi hop? */ + stream_putc(s, args->mhop != 0); + + /* Source address. */ + stream_putw(s, args->family); + stream_put(s, &args->src, addrlen); + + /* Send the expected TTL. */ + stream_putc(s, args->ttl); + + /* Send interface name if any. */ + stream_putc(s, args->ifnamelen); + if (args->ifnamelen) + stream_put(s, args->ifname, args->ifnamelen); + + /* Send the C bit indicator. */ + stream_putc(s, args->cbit); + + /* Send profile name if any. */ + stream_putc(s, args->profilelen); + if (args->profilelen) + stream_put(s, args->profile, args->profilelen); +#else /* PTM BFD */ /* Encode timers if this is a registration message. */ if (args->command != ZEBRA_BFD_DEST_DEREGISTER) { stream_putl(s, args->min_rx); @@ -500,16 +536,6 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) if (args->ifnamelen) stream_put(s, args->ifname, args->ifnamelen); } - - /* Send the C bit indicator. */ - stream_putc(s, args->cbit); - - /* `ptm-bfd` doesn't support profiles yet. */ -#if HAVE_BFDD > 0 - /* Send profile name if any. */ - stream_putc(s, args->profilelen); - if (args->profilelen) - stream_put(s, args->profile, args->profilelen); #endif /* HAVE_BFDD */ /* Finish the message by writing the size. */