diff options
Diffstat (limited to 'bfdd')
| -rw-r--r-- | bfdd/bfd.c | 151 | ||||
| -rw-r--r-- | bfdd/bfd.h | 2 | 
2 files changed, 105 insertions, 48 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index eb9c300313..f32bc2598b 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -1172,6 +1172,9 @@ void bfd_set_echo(struct bfd_session *bs, bool echo)  		if (bs->bdc == NULL)  			ptm_bfd_echo_stop(bs);  	} + +	if (bs->vrf && bs->vrf->info) +		bfd_vrf_toggle_echo(bs->vrf->info);  }  void bfd_set_shutdown(struct bfd_session *bs, bool shutdown) @@ -1800,6 +1803,69 @@ void bfd_profiles_remove(void)  		bfd_profile_free(bp);  } +struct __bfd_session_echo { +	/* VRF peers must match */ +	struct vrf *vrf; +	/* Echo enabled or not */ +	bool enabled; +}; + +static int __bfd_session_has_echo(struct hash_bucket *hb, void *arg) +{ +	const struct bfd_session *session = hb->data; +	struct __bfd_session_echo *has_echo = arg; + +	if (session->vrf != has_echo->vrf) +		return HASHWALK_CONTINUE; +	if (!CHECK_FLAG(session->flags, BFD_SESS_FLAG_ECHO)) +		return HASHWALK_CONTINUE; + +	has_echo->enabled = true; +	return HASHWALK_ABORT; +} + +void bfd_vrf_toggle_echo(struct bfd_vrf_global *bfd_vrf) +{ +	struct __bfd_session_echo has_echo = { +		.enabled = false, +		.vrf = bfd_vrf->vrf, +	}; + +	/* Check for peers using echo */ +	hash_walk(bfd_id_hash, __bfd_session_has_echo, &has_echo); + +	/* +	 * No peers using echo, close all echo sockets. +	 */ +	if (!has_echo.enabled) { +		if (bfd_vrf->bg_echo != -1) { +			event_cancel(&bfd_vrf->bg_ev[4]); +			close(bfd_vrf->bg_echo); +			bfd_vrf->bg_echo = -1; +		} + +		if (bfd_vrf->bg_echov6 != -1) { +			event_cancel(&bfd_vrf->bg_ev[5]); +			close(bfd_vrf->bg_echov6); +			bfd_vrf->bg_echov6 = -1; +		} +		return; +	} + +	/* +	 * At least one peer using echo, open echo sockets. +	 */ +	if (bfd_vrf->bg_echo == -1) +		bfd_vrf->bg_echo = bp_echo_socket(bfd_vrf->vrf); +	if (bfd_vrf->bg_echov6 == -1) +		bfd_vrf->bg_echov6 = bp_echov6_socket(bfd_vrf->vrf); + +	if (bfd_vrf->bg_ev[4] == NULL && bfd_vrf->bg_echo != -1) +		event_add_read(master, bfd_recv_cb, bfd_vrf, bfd_vrf->bg_echo, &bfd_vrf->bg_ev[4]); +	if (bfd_vrf->bg_ev[5] == NULL && bfd_vrf->bg_echov6 != -1) +		event_add_read(master, bfd_recv_cb, bfd_vrf, bfd_vrf->bg_echov6, &bfd_vrf->bg_ev[5]); +} +  /*   * Profile related hash functions.   */ @@ -1842,9 +1908,23 @@ static void bfd_profile_detach(struct bfd_profile *bp)   */  static int bfd_vrf_new(struct vrf *vrf)  { +	struct bfd_vrf_global *bvrf; +  	if (bglobal.debug_zebra)  		zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id); +	bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global)); +	bvrf->vrf = vrf; +	vrf->info = bvrf; + +	/* Invalidate all sockets */ +	bvrf->bg_shop = -1; +	bvrf->bg_mhop = -1; +	bvrf->bg_shop6 = -1; +	bvrf->bg_mhop6 = -1; +	bvrf->bg_echo = -1; +	bvrf->bg_echov6 = -1; +  	return 0;  } @@ -1853,70 +1933,53 @@ static int bfd_vrf_delete(struct vrf *vrf)  	if (bglobal.debug_zebra)  		zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id); +	XFREE(MTYPE_BFDD_VRF, vrf->info); +  	return 0;  }  static int bfd_vrf_enable(struct vrf *vrf)  { -	struct bfd_vrf_global *bvrf; - -	/* a different name */ -	if (!vrf->info) { -		bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global)); -		bvrf->vrf = vrf; -		vrf->info = (void *)bvrf; - -		/* Disable sockets if using data plane. */ -		if (bglobal.bg_use_dplane) { -			bvrf->bg_shop = -1; -			bvrf->bg_mhop = -1; -			bvrf->bg_shop6 = -1; -			bvrf->bg_mhop6 = -1; -			bvrf->bg_echo = -1; -			bvrf->bg_echov6 = -1; -		} -	} else -		bvrf = vrf->info; +	struct bfd_vrf_global *bvrf = vrf->info;  	if (bglobal.debug_zebra)  		zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id); -	if (!bvrf->bg_shop) +	/* Don't open sockets when using data plane */ +	if (bglobal.bg_use_dplane) +		goto skip_sockets; + +	if (bvrf->bg_shop == -1)  		bvrf->bg_shop = bp_udp_shop(vrf); -	if (!bvrf->bg_mhop) +	if (bvrf->bg_mhop == -1)  		bvrf->bg_mhop = bp_udp_mhop(vrf); -	if (!bvrf->bg_shop6) +	if (bvrf->bg_shop6 == -1)  		bvrf->bg_shop6 = bp_udp6_shop(vrf); -	if (!bvrf->bg_mhop6) +	if (bvrf->bg_mhop6 == -1)  		bvrf->bg_mhop6 = bp_udp6_mhop(vrf); -	if (!bvrf->bg_echo) -		bvrf->bg_echo = bp_echo_socket(vrf); -	if (!bvrf->bg_echov6) -		bvrf->bg_echov6 = bp_echov6_socket(vrf); -	if (!bvrf->bg_ev[0] && bvrf->bg_shop != -1) +	if (bvrf->bg_ev[0] == NULL && bvrf->bg_shop != -1)  		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,  			       &bvrf->bg_ev[0]); -	if (!bvrf->bg_ev[1] && bvrf->bg_mhop != -1) +	if (bvrf->bg_ev[1] == NULL && bvrf->bg_mhop != -1)  		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,  			       &bvrf->bg_ev[1]); -	if (!bvrf->bg_ev[2] && bvrf->bg_shop6 != -1) +	if (bvrf->bg_ev[2] == NULL && bvrf->bg_shop6 != -1)  		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,  			       &bvrf->bg_ev[2]); -	if (!bvrf->bg_ev[3] && bvrf->bg_mhop6 != -1) +	if (bvrf->bg_ev[3] == NULL && bvrf->bg_mhop6 != -1)  		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,  			       &bvrf->bg_ev[3]); -	if (!bvrf->bg_ev[4] && bvrf->bg_echo != -1) -		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo, -			       &bvrf->bg_ev[4]); -	if (!bvrf->bg_ev[5] && bvrf->bg_echov6 != -1) -		event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6, -			       &bvrf->bg_ev[5]); +	/* Toggle echo if VRF was disabled. */ +	bfd_vrf_toggle_echo(bvrf); + +skip_sockets:  	if (vrf->vrf_id != VRF_DEFAULT) {  		bfdd_zclient_register(vrf->vrf_id);  		bfdd_sessions_enable_vrf(vrf);  	} +  	return 0;  } @@ -1948,17 +2011,9 @@ static int bfd_vrf_disable(struct vrf *vrf)  	socket_close(&bvrf->bg_echo);  	socket_close(&bvrf->bg_shop);  	socket_close(&bvrf->bg_mhop); -	if (bvrf->bg_shop6 != -1) -		socket_close(&bvrf->bg_shop6); -	if (bvrf->bg_mhop6 != -1) -		socket_close(&bvrf->bg_mhop6); -	socket_close(&bvrf->bg_echo); -	if (bvrf->bg_echov6 != -1) -		socket_close(&bvrf->bg_echov6); - -	/* free context */ -	XFREE(MTYPE_BFDD_VRF, bvrf); -	vrf->info = NULL; +	socket_close(&bvrf->bg_shop6); +	socket_close(&bvrf->bg_mhop6); +	socket_close(&bvrf->bg_echov6);  	return 0;  } diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 2f83b245eb..d4d14ffce6 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -610,6 +610,8 @@ void bfd_sessions_remove_manual(void);  void bfd_profiles_remove(void);  void bfd_rtt_init(struct bfd_session *bfd); +extern void bfd_vrf_toggle_echo(struct bfd_vrf_global *bfd_vrf); +  /**   * Set the BFD session echo state.   *  | 
