static void bs_down_handler(struct bfd_session *bs, int nstate);
static void bs_init_handler(struct bfd_session *bs, int nstate);
static void bs_up_handler(struct bfd_session *bs, int nstate);
-static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
- uint8_t diag);
/**
* Remove BFD profile from all BFD sessions so we don't leave dangling
static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd)
{
/* Send the scheduled echo packet */
- ptm_bfd_echo_snd(bfd);
+ /* if ipv4 use the new echo implementation that causes
+ * the packet to be looped in forwarding plane of peer
+ */
+ if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6) == 0)
+#ifdef BFD_LINUX
+ ptm_bfd_echo_fp_snd(bfd);
+#else
+ ptm_bfd_echo_snd(bfd);
+#endif
+ else
+ ptm_bfd_echo_snd(bfd);
/* Restart the timer for next time */
ptm_bfd_start_xmt_timer(bfd, true);
state_list[bfd->ses_state].str,
get_diag_str(bfd->local_diag));
}
+
+ /* clear peer's mac address */
+ UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
+ memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
+ /* reset local address ,it might has been be changed after bfd is up*/
+ memset(&bfd->local_address, 0, sizeof(bfd->local_address));
}
static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
return bfd_key_lookup(key);
}
-int bfd_xmt_cb(struct thread *t)
+void bfd_xmt_cb(struct thread *t)
{
struct bfd_session *bs = THREAD_ARG(t);
ptm_bfd_xmt_TO(bs, 0);
-
- return 0;
}
-int bfd_echo_xmt_cb(struct thread *t)
+void bfd_echo_xmt_cb(struct thread *t)
{
struct bfd_session *bs = THREAD_ARG(t);
if (bs->echo_xmt_TO > 0)
ptm_bfd_echo_xmt_TO(bs);
-
- return 0;
}
/* Was ptm_bfd_detect_TO() */
-int bfd_recvtimer_cb(struct thread *t)
+void bfd_recvtimer_cb(struct thread *t)
{
struct bfd_session *bs = THREAD_ARG(t);
case PTM_BFD_INIT:
case PTM_BFD_UP:
ptm_bfd_sess_dn(bs, BD_CONTROL_EXPIRED);
- bfd_recvtimer_update(bs);
- break;
-
- default:
- /* Second detect time expiration, zero remote discr (section
- * 6.5.1)
- */
- bs->discrs.remote_discr = 0;
break;
}
-
- return 0;
}
/* Was ptm_bfd_echo_detect_TO() */
-int bfd_echo_recvtimer_cb(struct thread *t)
+void bfd_echo_recvtimer_cb(struct thread *t)
{
struct bfd_session *bs = THREAD_ARG(t);
ptm_bfd_sess_dn(bs, BD_ECHO_FAILED);
break;
}
-
- return 0;
}
struct bfd_session *bfd_session_new(void)
* Apply profile last: it also calls `bfd_set_shutdown`.
*
* There is no problem calling `shutdown` twice if the value doesn't
- * change or if it is overriden by peer specific configuration.
+ * change or if it is overridden by peer specific configuration.
*/
if (bpc->bpc_has_profile)
bfd_profile_apply(bpc->bpc_profile, bs);
*/
bs->ses_state = PTM_BFD_INIT;
- /* Answer peer with INIT immediately in passive mode. */
+ /*
+ * RFC 5880, Section 6.1.
+ * A system taking the Passive role MUST NOT begin
+ * sending BFD packets for a particular session until
+ * it has received a BFD packet for that session, and thus
+ * has learned the remote system's discriminator value.
+ *
+ * Now we can start transmission timer in passive mode.
+ */
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
- ptm_bfd_snd(bs, 0);
+ ptm_bfd_xmt_TO(bs, 0);
+
break;
case PTM_BFD_INIT:
* Remote peer doesn't want to talk, so lets make the
* connection down.
*/
- bs->ses_state = PTM_BFD_DOWN;
+ ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
break;
case PTM_BFD_DOWN:
}
}
-static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
- uint8_t diag)
-{
- int old_state = bfd->ses_state;
-
- bfd->local_diag = diag;
- bfd->discrs.remote_discr = 0;
- bfd->ses_state = PTM_BFD_DOWN;
- bfd->polling = 0;
- bfd->demand_mode = 0;
- monotime(&bfd->downtime);
-
- /* Slow down the control packets, the connection is down. */
- bs_set_slow_timers(bfd);
-
- /* only signal clients when going from up->down state */
- if (old_state == PTM_BFD_UP)
- control_notify(bfd, PTM_BFD_ADM_DOWN);
-
- /* Stop echo packet transmission if they are active */
- if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
- ptm_bfd_echo_stop(bfd);
-
- if (old_state != bfd->ses_state) {
- bfd->stats.session_down++;
- if (bglobal.debug_peer_event)
- zlog_debug("state-change: [%s] %s -> %s reason:%s",
- bs_to_string(bfd), state_list[old_state].str,
- state_list[bfd->ses_state].str,
- get_diag_str(bfd->local_diag));
- }
-}
-
static void bs_up_handler(struct bfd_session *bs, int nstate)
{
switch (nstate) {
case PTM_BFD_ADM_DOWN:
- bs_neighbour_admin_down_handler(bs, BD_ADMIN_DOWN);
- break;
-
case PTM_BFD_DOWN:
/* Peer lost or asked to shutdown connection. */
ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
void integer2timestr(uint64_t time, char *buf, size_t buflen)
{
- unsigned int year, month, day, hour, minute, second;
+ uint64_t year, month, day, hour, minute, second;
int rv;
#define MINUTES (60)
year = time / YEARS;
time -= year * YEARS;
- rv = snprintf(buf, buflen, "%u year(s), ", year);
+ rv = snprintfrr(buf, buflen, "%" PRIu64 " year(s), ", year);
buf += rv;
buflen -= rv;
}
month = time / MONTHS;
time -= month * MONTHS;
- rv = snprintf(buf, buflen, "%u month(s), ", month);
+ rv = snprintfrr(buf, buflen, "%" PRIu64 " month(s), ", month);
buf += rv;
buflen -= rv;
}
day = time / DAYS;
time -= day * DAYS;
- rv = snprintf(buf, buflen, "%u day(s), ", day);
+ rv = snprintfrr(buf, buflen, "%" PRIu64 " day(s), ", day);
buf += rv;
buflen -= rv;
}
hour = time / HOURS;
time -= hour * HOURS;
- rv = snprintf(buf, buflen, "%u hour(s), ", hour);
+ rv = snprintfrr(buf, buflen, "%" PRIu64 " hour(s), ", hour);
buf += rv;
buflen -= rv;
}
minute = time / MINUTES;
time -= minute * MINUTES;
- rv = snprintf(buf, buflen, "%u minute(s), ", minute);
+ rv = snprintfrr(buf, buflen, "%" PRIu64 " minute(s), ", minute);
buf += rv;
buflen -= rv;
}
second = time % MINUTES;
- snprintf(buf, buflen, "%u second(s)", second);
+ snprintfrr(buf, buflen, "%" PRIu64 " second(s)", second);
}
const char *bs_to_string(const struct bfd_session *bs)
return 0;
}
-static int bfd_vrf_update(struct vrf *vrf)
-{
- if (!vrf_is_enabled(vrf))
- return 0;
-
- if (bglobal.debug_zebra)
- zlog_debug("VRF update: %s(%u)", vrf->name, vrf->vrf_id);
-
- /* a different name is given; update bfd list */
- bfdd_sessions_enable_vrf(vrf);
- return 0;
-}
-
static int bfd_vrf_enable(struct vrf *vrf)
{
struct bfd_vrf_global *bvrf;
void bfd_vrf_init(void)
{
- vrf_init(bfd_vrf_new, bfd_vrf_enable, bfd_vrf_disable,
- bfd_vrf_delete, bfd_vrf_update);
+ vrf_init(bfd_vrf_new, bfd_vrf_enable, bfd_vrf_disable, bfd_vrf_delete);
}
void bfd_vrf_terminate(void)
return bfd->vrf->info;
}
-void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf)
-{
- if (!vrf || !bs)
- return;
- /* update key */
- hash_release(bfd_key_hash, bs);
- /*
- * HACK: Change the BFD VRF in the running configuration directly,
- * bypassing the northbound layer. This is necessary to avoid deleting
- * the BFD and readding it in the new VRF, which would have
- * several implications.
- */
- if (yang_module_find("frr-bfdd") && bs->key.vrfname[0]) {
- struct lyd_node *bfd_dnode;
- char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32];
- char oldpath[XPATH_MAXLEN], newpath[XPATH_MAXLEN];
- char addr_buf[INET6_ADDRSTRLEN];
- int slen;
-
- /* build xpath */
- if (bs->key.mhop) {
- inet_ntop(bs->key.family, &bs->key.local, addr_buf, sizeof(addr_buf));
- snprintf(xpath_srcaddr, sizeof(xpath_srcaddr), "[source-addr='%s']",
- addr_buf);
- } else
- xpath_srcaddr[0] = 0;
- inet_ntop(bs->key.family, &bs->key.peer, addr_buf, sizeof(addr_buf));
- slen = snprintf(xpath, sizeof(xpath),
- "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
- bs->key.mhop ? "multi-hop" : "single-hop", xpath_srcaddr,
- addr_buf);
- if (bs->key.ifname[0])
- slen += snprintf(xpath + slen, sizeof(xpath) - slen,
- "[interface='%s']", bs->key.ifname);
- else
- slen += snprintf(xpath + slen, sizeof(xpath) - slen,
- "[interface='*']");
- snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']/vrf",
- bs->key.vrfname);
-
- bfd_dnode = yang_dnode_getf(running_config->dnode, xpath,
- bs->key.vrfname);
- if (bfd_dnode) {
- yang_dnode_get_path(lyd_parent(bfd_dnode), oldpath,
- sizeof(oldpath));
- yang_dnode_change_leaf(bfd_dnode, vrf->name);
- yang_dnode_get_path(lyd_parent(bfd_dnode), newpath,
- sizeof(newpath));
- nb_running_move_tree(oldpath, newpath);
- running_config->version++;
- }
- }
- memset(bs->key.vrfname, 0, sizeof(bs->key.vrfname));
- strlcpy(bs->key.vrfname, vrf->name, sizeof(bs->key.vrfname));
- hash_get(bfd_key_hash, bs, hash_alloc_intern);
-}
-
unsigned long bfd_get_session_count(void)
{
return bfd_key_hash->count;