diff options
| author | wumu.zsl <wumu.zsl@alibaba-inc.com> | 2025-01-21 03:11:03 +0000 | 
|---|---|---|
| committer | wumu.zsl <wumu.zsl@alibaba-inc.com> | 2025-01-23 02:29:09 +0000 | 
| commit | 12af5e19a16630e9ae6e0c9c5fe9eb8ef400b5da (patch) | |
| tree | 6cf185781bd2eb915ab19dfbb4dddbbb80d8d8ba /bfdd | |
| parent | 2d6a4265e1576819a843cd24a0d9383f5ae402b5 (diff) | |
bfdd: support sbfd session create and destroy
refactor bfd_session_create and bfd_session_destroy to support SBFD
Signed-off-by: wumu.zsl <wumu.zsl@alibaba-inc.com>
Diffstat (limited to 'bfdd')
| -rw-r--r-- | bfdd/bfd.c | 8 | ||||
| -rw-r--r-- | bfdd/bfd.h | 2 | ||||
| -rw-r--r-- | bfdd/bfdd_nb_config.c | 203 | 
3 files changed, 181 insertions, 32 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index fd02156372..a0094fd85f 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -657,11 +657,13 @@ void bfd_echo_recvtimer_cb(struct event *t)  	}  } -struct bfd_session *bfd_session_new(void) +struct bfd_session *bfd_session_new(enum bfd_mode_type mode)  {  	struct bfd_session *bs; -	bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs)); +	bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(struct bfd_session)); +	bs->segnum = 0; +	bs->bfd_mode = mode;  	/* Set peer session defaults. */  	bfd_profile_set_default(&bs->peer_profile); @@ -799,7 +801,7 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)  	}  	/* Get BFD session storage with its defaults. */ -	bfd = bfd_session_new(); +	bfd = bfd_session_new(BFD_MODE_TYPE_BFD);  	/*  	 * Store interface/VRF name in case we need to delay session diff --git a/bfdd/bfd.h b/bfdd/bfd.h index f79df1dcdd..6b3df63e3d 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -615,7 +615,7 @@ void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);  void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct sockaddr_any *local,  		 bool mhop, const char *ifname, const char *vrfname, const char *bfdname); -struct bfd_session *bfd_session_new(void); +struct bfd_session *bfd_session_new(enum bfd_mode_type mode);  struct bfd_session *bs_registrate(struct bfd_session *bs);  void bfd_session_free(struct bfd_session *bs);  const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop, diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index c0e7bc16e7..91084ba02e 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -85,6 +85,26 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,  	gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, NULL);  } +static void sbfd_session_get_key(bool mhop, const struct lyd_node *dnode, struct bfd_key *bk) +{ +	const char *ifname = NULL, *vrfname = NULL, *bfdname = NULL; +	struct sockaddr_any psa, lsa; + +	/* Required source parameter. */ +	strtosa(yang_dnode_get_string(dnode, "source-addr"), &lsa); + +	strtosa(yang_dnode_get_string(dnode, "dest-addr"), &psa); + +	if (yang_dnode_exists(dnode, "bfd-name")) +		bfdname = yang_dnode_get_string(dnode, "bfd-name"); + +	if (yang_dnode_exists(dnode, "vrf")) +		vrfname = yang_dnode_get_string(dnode, "vrf"); + +	/* Generate the corresponding key. */ +	gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, bfdname); +} +  struct session_iter {  	int count;  	bool wildcard; @@ -105,7 +125,25 @@ static int session_iter_cb(const struct lyd_node *dnode, void *arg)  	return YANG_ITER_CONTINUE;  } -static int bfd_session_create(struct nb_cb_create_args *args, bool mhop) +static int segment_list_iter_cb(const struct lyd_node *dnode, void *arg) +{ +	struct bfd_session *bs = arg; +	uint8_t segnum = bs->segnum; +	const char *addr; +	struct sockaddr_any sa; + +	addr = yang_dnode_get_string(dnode, NULL); + +	if (strtosa(addr, &sa) < 0 || sa.sa_sin6.sin6_family != AF_INET6) +		return YANG_ITER_STOP; + +	memcpy(&bs->seg_list[segnum], &sa.sa_sin6.sin6_addr, sizeof(struct in6_addr)); +	bs->segnum = segnum + 1; + +	return YANG_ITER_CONTINUE; +} + +static int bfd_session_create(struct nb_cb_create_args *args, bool mhop, uint32_t bfd_mode)  {  	const struct lyd_node *sess_dnode;  	struct session_iter iter; @@ -115,10 +153,20 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)  	const char *vrfname;  	struct bfd_key bk;  	struct prefix p; +	const char *bfd_name = NULL; +	struct sockaddr_any out_sip6;  	switch (args->event) {  	case NB_EV_VALIDATE: -		yang_dnode_get_prefix(&p, args->dnode, "dest-addr"); +		if ((bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) || (bfd_mode == BFD_MODE_TYPE_SBFD_INIT)) { +			if (bfd_session_get_by_name(yang_dnode_get_string(args->dnode, "bfd-name"))) { +				snprintf(args->errmsg, args->errmsg_len, "bfd name already exist."); +				return NB_ERR_VALIDATION; +			} +			return NB_OK; +		} + +		yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");  		if (mhop) {  			/* @@ -170,34 +218,123 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)  		break;  	case NB_EV_PREPARE: -		bfd_session_get_key(mhop, args->dnode, &bk); -		bs = bfd_key_lookup(bk); +		if (bfd_mode == BFD_MODE_TYPE_BFD) { +			bfd_session_get_key(mhop, args->dnode, &bk); +			bs = bfd_key_lookup(bk); + +			/* This session was already configured by another daemon. */ +			if (bs != NULL) { +				/* Now it is configured also by CLI. */ +				SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); +				bs->refcount++; + +				args->resource->ptr = bs; +				break; +			} + +			bs = bfd_session_new(BFD_MODE_TYPE_BFD); -		/* This session was already configured by another daemon. */ -		if (bs != NULL) { -			/* Now it is configured also by CLI. */ +			/* Fill the session key. */ +			bfd_session_get_key(mhop, args->dnode, &bs->key); +			/* Set configuration flags. */ +			bs->refcount = 1;  			SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); -			bs->refcount++; +			if (mhop) +				SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); +			if (bs->key.family == AF_INET6) +				SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);  			args->resource->ptr = bs;  			break; -		} +		} else if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO || +			   bfd_mode == BFD_MODE_TYPE_SBFD_INIT) { +			sbfd_session_get_key(mhop, args->dnode, &bk); +			bs = bfd_key_lookup(bk); + +			/* This session was already configured by another daemon. */ +			if (bs != NULL) { +				/* Now it is configured also by CLI. */ +				SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); +				bs->refcount++; + +				args->resource->ptr = bs; +				break; +			} -		bs = bfd_session_new(); +			if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO && +			    !yang_dnode_exists(args->dnode, "srv6-encap-data")) { +				//srv6-encap-data should not be null for sbfd echo +				snprintf(args->errmsg, args->errmsg_len, +					 "srv6-encap-data should not be null"); +				return NB_ERR_RESOURCE; +			} -		/* Fill the session key. */ -		bfd_session_get_key(mhop, args->dnode, &bs->key); +			if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO && +			    !yang_dnode_exists(args->dnode, "srv6-source-ipv6")) { +				snprintf(args->errmsg, args->errmsg_len, +					 "source_ipv6 should not be null"); +				return NB_ERR_RESOURCE; +			} -		/* Set configuration flags. */ -		bs->refcount = 1; -		SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); -		if (mhop) -			SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); -		if (bs->key.family == AF_INET6) -			SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6); +			if (bfd_mode == BFD_MODE_TYPE_SBFD_INIT) { +				if (!yang_dnode_exists(args->dnode, "remote-discr")) { +					snprintf(args->errmsg, args->errmsg_len, +						 "remote-discr should not be null"); +					return NB_ERR_RESOURCE; +				} +			} -		args->resource->ptr = bs; -		break; +			bfd_name = yang_dnode_get_string(args->dnode, "bfd-name"); + +			bs = bfd_session_new(bfd_mode); +			if (bs == NULL) { +				snprintf(args->errmsg, args->errmsg_len, +					 "session-new: allocation failed"); +				return NB_ERR_RESOURCE; +			} +			/* Fill the session key. */ +			sbfd_session_get_key(mhop, args->dnode, &bs->key); +			strlcpy(bs->bfd_name, bfd_name, BFD_NAME_SIZE); + +			if (yang_dnode_exists(args->dnode, "srv6-encap-data")) { +				yang_dnode_iterate(segment_list_iter_cb, bs, args->dnode, +						   "./srv6-encap-data"); + + +				strtosa(yang_dnode_get_string(args->dnode, "./srv6-source-ipv6"), +					&out_sip6); +				memcpy(&bs->out_sip6, &out_sip6.sa_sin6.sin6_addr, +				       sizeof(struct in6_addr)); +			} + +			if (bfd_mode == BFD_MODE_TYPE_SBFD_INIT) { +				bs->discrs.remote_discr = yang_dnode_get_uint32(args->dnode, +										"./remote-discr"); +			} + +			/* Set configuration flags. */ +			bs->refcount = 1; +			SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); +			if (mhop) +				SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); + +			if (bs->key.family == AF_INET6) +				SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6); + +			if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) { +				memcpy(&bs->key.peer, &bs->key.local, sizeof(struct in6_addr)); +			} else { +				bs->xmt_TO = bs->timers.desired_min_tx; +				bs->detect_TO = bs->detect_mult * bs->xmt_TO; +			} + +			args->resource->ptr = bs; +			break; + +		} else { +			snprintf(args->errmsg, args->errmsg_len, "bfd mode must be bfd or sbfd."); +			return NB_ERR_VALIDATION; +		}  	case NB_EV_APPLY:  		bs = args->resource->ptr; @@ -219,15 +356,19 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)  	return NB_OK;  } -static int bfd_session_destroy(enum nb_event event, -			       const struct lyd_node *dnode, bool mhop) +static int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, bool mhop, +			       uint32_t bfd_mode)  {  	struct bfd_session *bs;  	struct bfd_key bk;  	switch (event) {  	case NB_EV_VALIDATE: -		bfd_session_get_key(mhop, dnode, &bk); +		if (bfd_mode == BFD_MODE_TYPE_BFD) +			bfd_session_get_key(mhop, dnode, &bk); +		else +			sbfd_session_get_key(mhop, dnode, &bk); +  		if (bfd_key_lookup(bk) == NULL)  			return NB_ERR_INCONSISTENCY;  		break; @@ -248,6 +389,12 @@ static int bfd_session_destroy(enum nb_event event,  		if (bs->refcount > 0)  			break; +		if (bglobal.debug_peer_event) +			zlog_info("session destroy: %s", bs_to_string(bs)); + +		if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO || bfd_mode == BFD_MODE_TYPE_SBFD_INIT) +			ptm_bfd_notify(bs, PTM_BFD_DOWN); +  		bfd_session_free(bs);  		break; @@ -552,12 +699,12 @@ int bfdd_bfd_profile_required_echo_receive_interval_modify(   */  int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)  { -	return bfd_session_create(args, false); +	return bfd_session_create(args, false, BFD_MODE_TYPE_BFD);  }  int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)  { -	return bfd_session_destroy(args->event, args->dnode, false); +	return bfd_session_destroy(args->event, args->dnode, false, BFD_MODE_TYPE_BFD);  }  /* @@ -853,12 +1000,12 @@ int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(   */  int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)  { -	return bfd_session_create(args, true); +	return bfd_session_create(args, true, BFD_MODE_TYPE_BFD);  }  int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)  { -	return bfd_session_destroy(args->event, args->dnode, true); +	return bfd_session_destroy(args->event, args->dnode, true, BFD_MODE_TYPE_BFD);  }  /*  | 
