diff options
| author | wumu.zsl <wumu.zsl@alibaba-inc.com> | 2025-01-20 13:48:38 +0000 | 
|---|---|---|
| committer | wumu.zsl <wumu.zsl@alibaba-inc.com> | 2025-01-22 15:00:24 +0000 | 
| commit | c4f9964aec03e1b076904452f124c50fbfa940f8 (patch) | |
| tree | f6214a7af1e6cea1fee8698d82d1aeeabcb21bfb /bfdd | |
| parent | 32705fe7206438fb9cd23c0a866992fcc13788e0 (diff) | |
bfdd: add bfdname in bfd_key
sbfd will use bfdname for key hash, We introduced a bfd-name for every sbfd session, normal BFD sessions can leave it as NULL.
A unique bfd-name can be used to identify a sbfd session quickly. This is quite useful in our Srv6 deployment for path protection case.
For example, if use the sbfd session to protect the SRv6 path A-B-D, we would assign the name 'path-a-b-d' or 'a-b-d' to the session.
Signed-off-by: wumu.zsl <wumu.zsl@alibaba-inc.com>
Diffstat (limited to 'bfdd')
| -rw-r--r-- | bfdd/bfd.c | 40 | ||||
| -rw-r--r-- | bfdd/bfd.h | 18 | ||||
| -rw-r--r-- | bfdd/bfdd_nb_config.c | 44 | ||||
| -rw-r--r-- | bfdd/bfdd_nb_state.c | 8 | 
4 files changed, 87 insertions, 23 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index f32bc2598b..fd02156372 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -222,10 +222,11 @@ void bfd_profile_remove(struct bfd_session *bs)  	bfd_session_apply(bs);  } -void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, -		 struct sockaddr_any *local, bool mhop, const char *ifname, -		 const char *vrfname) +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 vrf *vrf = NULL; +  	memset(key, 0, sizeof(*key));  	switch (peer->sa_sin.sin_family) { @@ -248,10 +249,20 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,  	key->mhop = mhop;  	if (ifname && ifname[0])  		strlcpy(key->ifname, ifname, sizeof(key->ifname)); -	if (vrfname && vrfname[0]) -		strlcpy(key->vrfname, vrfname, sizeof(key->vrfname)); -	else +	if (vrfname && vrfname[0] && strcmp(vrfname, VRF_DEFAULT_NAME) != 0) { +		vrf = vrf_lookup_by_name(vrfname); +		if (vrf) { +			strlcpy(key->vrfname, vrf->name, sizeof(key->vrfname)); +		} else { +			strlcpy(key->vrfname, vrfname, sizeof(key->vrfname)); +		} +	} else {  		strlcpy(key->vrfname, VRF_DEFAULT_NAME, sizeof(key->vrfname)); +	} + +	if (bfdname && bfdname[0]) { +		strlcpy(key->bfdname, bfdname, sizeof(key->bfdname)); +	}  }  struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc) @@ -259,8 +270,8 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)  	struct bfd_key key;  	/* Otherwise fallback to peer/local hash lookup. */ -	gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop, -		    bpc->bpc_localif, bpc->bpc_vrfname); +	gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop, bpc->bpc_localif, +		    bpc->bpc_vrfname, bpc->bfd_name);  	return bfd_key_lookup(key);  } @@ -599,7 +610,7 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,  	vrf = vrf_lookup_by_id(vrfid);  	gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL, -		    vrf ? vrf->name : VRF_DEFAULT_NAME); +		    vrf ? vrf->name : VRF_DEFAULT_NAME, NULL);  	/* XXX maybe remoteDiscr should be checked for remoteHeard cases. */  	return bfd_key_lookup(key); @@ -1713,6 +1724,7 @@ void bfd_shutdown(void)  struct bfd_session_iterator {  	int bsi_stop;  	bool bsi_mhop; +	uint32_t bsi_bfdmode;  	const struct bfd_session *bsi_bs;  }; @@ -1724,7 +1736,7 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)  	/* Previous entry signaled stop. */  	if (bsi->bsi_stop == 1) {  		/* Match the single/multi hop sessions. */ -		if (bs->key.mhop != bsi->bsi_mhop) +		if ((bs->key.mhop != bsi->bsi_mhop) || (bs->bfd_mode != bsi->bsi_bfdmode))  			return HASHWALK_CONTINUE;  		bsi->bsi_bs = bs; @@ -1736,7 +1748,8 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)  		bsi->bsi_stop = 1;  		/* Set entry to NULL to signal end of list. */  		bsi->bsi_bs = NULL; -	} else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop) { +	} else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop && +		   bsi->bsi_bfdmode == bs->bfd_mode) {  		/* We want the first list item. */  		bsi->bsi_stop = 1;  		bsi->bsi_bs = hb->data; @@ -1751,14 +1764,15 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)   *   * `bs` might point to NULL to get the first item of the data structure.   */ -const struct bfd_session *bfd_session_next(const struct bfd_session *bs, -					   bool mhop) +const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop, +					   uint32_t bfd_mode)  {  	struct bfd_session_iterator bsi;  	bsi.bsi_stop = 0;  	bsi.bsi_bs = bs;  	bsi.bsi_mhop = mhop; +	bsi.bsi_bfdmode = bfd_mode;  	hash_walk(bfd_key_hash, _bfd_session_next, &bsi);  	if (bsi.bsi_stop == 0)  		return NULL; diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 75204062f1..f79df1dcdd 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -19,6 +19,7 @@  #include "lib/qobj.h"  #include "lib/queue.h"  #include "lib/vrf.h" +#include "lib/bfd.h"  #ifdef BFD_DEBUG  #define BFDD_JSON_CONV_OPTIONS (JSON_C_TO_STRING_PRETTY) @@ -86,6 +87,10 @@ struct bfd_peer_cfg {  	bool bpc_has_profile;  	char bpc_profile[64]; + +	vrf_id_t vrf_id; +	char bfd_name[BFD_NAME_SIZE + 1]; +	uint8_t bfd_name_len;  };  /* bfd Authentication Type. */ @@ -260,6 +265,7 @@ struct bfd_key {  	struct in6_addr local;  	char ifname[IFNAMSIZ];  	char vrfname[VRF_NAMSIZ]; +	char bfdname[BFD_NAME_SIZE + 1];  } __attribute__((packed));  struct bfd_session_stats { @@ -381,6 +387,9 @@ struct bfd_session {  	uint8_t rtt_valid;	    /* number of valid samples */  	uint8_t rtt_index;	    /* last index added */  	uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */ +	char bfd_name[BFD_NAME_SIZE + 1]; + +	uint32_t bfd_mode;  };  struct bfd_diag_str_list { @@ -604,14 +613,13 @@ void bs_observer_del(struct bfd_session_observer *bso);  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); +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 *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); +const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop, +					   uint32_t bfd_mode);  void bfd_sessions_remove_manual(void);  void bfd_profiles_remove(void);  void bfd_rtt_init(struct bfd_session *bfd); diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index 48fbe7139c..c0e7bc16e7 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -13,14 +13,50 @@  #include "bfd.h"  #include "bfdd_nb.h" +#include <ifaddrs.h>  /*   * Helpers.   */ +static void get_ip_by_interface(const char *ifname, const char *vrfname, int family, char *ifip) +{ +	char intfip[INET6_ADDRSTRLEN]; +	const struct interface *interface; +	const struct connected *connected; +	struct vrf *vrf; + +	vrf = vrf_lookup_by_name(vrfname ? vrfname : VRF_DEFAULT_NAME); +	if (!vrf) +		return; + +	interface = if_lookup_by_name_vrf(ifname, vrf); +	if (interface == NULL) +		return; + +	frr_each (if_connected_const, interface->connected, connected) { +		if (!connected->address) +			continue; + +		if (family != connected->address->family) +			continue; + +		if (family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6)) +			continue; + +		inet_ntop(family, +			  family == AF_INET ? (void *)(&connected->address->u.prefix4) +					    : (void *)(&connected->address->u.prefix6), +			  intfip, INET6_ADDRSTRLEN); +		strlcpy(ifip, intfip, INET6_ADDRSTRLEN - 1); +		break; +	} +} +  static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,  				struct bfd_key *bk)  {  	const char *ifname = NULL, *vrfname = NULL; +	char ifip[INET6_ADDRSTRLEN] = { 0 };  	struct sockaddr_any psa, lsa;  	/* Required destination parameter. */ @@ -37,10 +73,16 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,  		ifname = yang_dnode_get_string(dnode, "interface");  		if (strcmp(ifname, "*") == 0)  			ifname = NULL; + +		if (ifname != NULL && !yang_dnode_exists(dnode, "source-addr") && +		    psa.sa_sin.sin_family != 0) { +			get_ip_by_interface(ifname, vrfname, psa.sa_sin.sin_family, ifip); +			strtosa(ifip, &lsa); +		}  	}  	/* Generate the corresponding key. */ -	gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); +	gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, NULL);  }  struct session_iter { diff --git a/bfdd/bfdd_nb_state.c b/bfdd/bfdd_nb_state.c index 12acda8fd8..1fc5b95887 100644 --- a/bfdd/bfdd_nb_state.c +++ b/bfdd/bfdd_nb_state.c @@ -20,7 +20,7 @@  const void *  bfdd_bfd_sessions_single_hop_get_next(struct nb_cb_get_next_args *args)  { -	return bfd_session_next(args->list_entry, false); +	return bfd_session_next(args->list_entry, false, BFD_MODE_TYPE_BFD);  }  int bfdd_bfd_sessions_single_hop_get_keys(struct nb_cb_get_keys_args *args) @@ -50,7 +50,7 @@ bfdd_bfd_sessions_single_hop_lookup_entry(struct nb_cb_lookup_entry_args *args)  	strtosa(dest_addr, &psa);  	memset(&lsa, 0, sizeof(lsa)); -	gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf); +	gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf, NULL);  	return bfd_key_lookup(bk);  } @@ -323,7 +323,7 @@ bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem(  const void *  bfdd_bfd_sessions_multi_hop_get_next(struct nb_cb_get_next_args *args)  { -	return bfd_session_next(args->list_entry, true); +	return bfd_session_next(args->list_entry, true, BFD_MODE_TYPE_BFD);  }  int bfdd_bfd_sessions_multi_hop_get_keys(struct nb_cb_get_keys_args *args) @@ -354,7 +354,7 @@ bfdd_bfd_sessions_multi_hop_lookup_entry(struct nb_cb_lookup_entry_args *args)  	strtosa(dest_addr, &psa);  	strtosa(source_addr, &lsa); -	gen_bfd_key(&bk, &psa, &lsa, true, NULL, vrf); +	gen_bfd_key(&bk, &psa, &lsa, true, NULL, vrf, NULL);  	return bfd_key_lookup(bk);  }  | 
