mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
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>
This commit is contained in:
parent
32705fe720
commit
c4f9964aec
40
bfdd/bfd.c
40
bfdd/bfd.c
|
@ -222,10 +222,11 @@ void bfd_profile_remove(struct bfd_session *bs)
|
||||||
bfd_session_apply(bs);
|
bfd_session_apply(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
|
void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct sockaddr_any *local,
|
||||||
struct sockaddr_any *local, bool mhop, const char *ifname,
|
bool mhop, const char *ifname, const char *vrfname, const char *bfdname)
|
||||||
const char *vrfname)
|
|
||||||
{
|
{
|
||||||
|
struct vrf *vrf = NULL;
|
||||||
|
|
||||||
memset(key, 0, sizeof(*key));
|
memset(key, 0, sizeof(*key));
|
||||||
|
|
||||||
switch (peer->sa_sin.sin_family) {
|
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;
|
key->mhop = mhop;
|
||||||
if (ifname && ifname[0])
|
if (ifname && ifname[0])
|
||||||
strlcpy(key->ifname, ifname, sizeof(key->ifname));
|
strlcpy(key->ifname, ifname, sizeof(key->ifname));
|
||||||
if (vrfname && vrfname[0])
|
if (vrfname && vrfname[0] && strcmp(vrfname, VRF_DEFAULT_NAME) != 0) {
|
||||||
strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
|
vrf = vrf_lookup_by_name(vrfname);
|
||||||
else
|
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));
|
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)
|
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;
|
struct bfd_key key;
|
||||||
|
|
||||||
/* Otherwise fallback to peer/local hash lookup. */
|
/* Otherwise fallback to peer/local hash lookup. */
|
||||||
gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop,
|
gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop, bpc->bpc_localif,
|
||||||
bpc->bpc_localif, bpc->bpc_vrfname);
|
bpc->bpc_vrfname, bpc->bfd_name);
|
||||||
|
|
||||||
return bfd_key_lookup(key);
|
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);
|
vrf = vrf_lookup_by_id(vrfid);
|
||||||
|
|
||||||
gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
|
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. */
|
/* XXX maybe remoteDiscr should be checked for remoteHeard cases. */
|
||||||
return bfd_key_lookup(key);
|
return bfd_key_lookup(key);
|
||||||
|
@ -1713,6 +1724,7 @@ void bfd_shutdown(void)
|
||||||
struct bfd_session_iterator {
|
struct bfd_session_iterator {
|
||||||
int bsi_stop;
|
int bsi_stop;
|
||||||
bool bsi_mhop;
|
bool bsi_mhop;
|
||||||
|
uint32_t bsi_bfdmode;
|
||||||
const struct bfd_session *bsi_bs;
|
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. */
|
/* Previous entry signaled stop. */
|
||||||
if (bsi->bsi_stop == 1) {
|
if (bsi->bsi_stop == 1) {
|
||||||
/* Match the single/multi hop sessions. */
|
/* 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;
|
return HASHWALK_CONTINUE;
|
||||||
|
|
||||||
bsi->bsi_bs = bs;
|
bsi->bsi_bs = bs;
|
||||||
|
@ -1736,7 +1748,8 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)
|
||||||
bsi->bsi_stop = 1;
|
bsi->bsi_stop = 1;
|
||||||
/* Set entry to NULL to signal end of list. */
|
/* Set entry to NULL to signal end of list. */
|
||||||
bsi->bsi_bs = NULL;
|
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. */
|
/* We want the first list item. */
|
||||||
bsi->bsi_stop = 1;
|
bsi->bsi_stop = 1;
|
||||||
bsi->bsi_bs = hb->data;
|
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.
|
* `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,
|
const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop,
|
||||||
bool mhop)
|
uint32_t bfd_mode)
|
||||||
{
|
{
|
||||||
struct bfd_session_iterator bsi;
|
struct bfd_session_iterator bsi;
|
||||||
|
|
||||||
bsi.bsi_stop = 0;
|
bsi.bsi_stop = 0;
|
||||||
bsi.bsi_bs = bs;
|
bsi.bsi_bs = bs;
|
||||||
bsi.bsi_mhop = mhop;
|
bsi.bsi_mhop = mhop;
|
||||||
|
bsi.bsi_bfdmode = bfd_mode;
|
||||||
hash_walk(bfd_key_hash, _bfd_session_next, &bsi);
|
hash_walk(bfd_key_hash, _bfd_session_next, &bsi);
|
||||||
if (bsi.bsi_stop == 0)
|
if (bsi.bsi_stop == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
18
bfdd/bfd.h
18
bfdd/bfd.h
|
@ -19,6 +19,7 @@
|
||||||
#include "lib/qobj.h"
|
#include "lib/qobj.h"
|
||||||
#include "lib/queue.h"
|
#include "lib/queue.h"
|
||||||
#include "lib/vrf.h"
|
#include "lib/vrf.h"
|
||||||
|
#include "lib/bfd.h"
|
||||||
|
|
||||||
#ifdef BFD_DEBUG
|
#ifdef BFD_DEBUG
|
||||||
#define BFDD_JSON_CONV_OPTIONS (JSON_C_TO_STRING_PRETTY)
|
#define BFDD_JSON_CONV_OPTIONS (JSON_C_TO_STRING_PRETTY)
|
||||||
|
@ -86,6 +87,10 @@ struct bfd_peer_cfg {
|
||||||
|
|
||||||
bool bpc_has_profile;
|
bool bpc_has_profile;
|
||||||
char bpc_profile[64];
|
char bpc_profile[64];
|
||||||
|
|
||||||
|
vrf_id_t vrf_id;
|
||||||
|
char bfd_name[BFD_NAME_SIZE + 1];
|
||||||
|
uint8_t bfd_name_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* bfd Authentication Type. */
|
/* bfd Authentication Type. */
|
||||||
|
@ -260,6 +265,7 @@ struct bfd_key {
|
||||||
struct in6_addr local;
|
struct in6_addr local;
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
char vrfname[VRF_NAMSIZ];
|
char vrfname[VRF_NAMSIZ];
|
||||||
|
char bfdname[BFD_NAME_SIZE + 1];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct bfd_session_stats {
|
struct bfd_session_stats {
|
||||||
|
@ -381,6 +387,9 @@ struct bfd_session {
|
||||||
uint8_t rtt_valid; /* number of valid samples */
|
uint8_t rtt_valid; /* number of valid samples */
|
||||||
uint8_t rtt_index; /* last index added */
|
uint8_t rtt_index; /* last index added */
|
||||||
uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */
|
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 {
|
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 bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
|
||||||
|
|
||||||
void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
|
void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct sockaddr_any *local,
|
||||||
struct sockaddr_any *local, bool mhop, const char *ifname,
|
bool mhop, const char *ifname, const char *vrfname, const char *bfdname);
|
||||||
const char *vrfname);
|
|
||||||
struct bfd_session *bfd_session_new(void);
|
struct bfd_session *bfd_session_new(void);
|
||||||
struct bfd_session *bs_registrate(struct bfd_session *bs);
|
struct bfd_session *bs_registrate(struct bfd_session *bs);
|
||||||
void bfd_session_free(struct bfd_session *bs);
|
void bfd_session_free(struct bfd_session *bs);
|
||||||
const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
|
const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop,
|
||||||
bool mhop);
|
uint32_t bfd_mode);
|
||||||
void bfd_sessions_remove_manual(void);
|
void bfd_sessions_remove_manual(void);
|
||||||
void bfd_profiles_remove(void);
|
void bfd_profiles_remove(void);
|
||||||
void bfd_rtt_init(struct bfd_session *bfd);
|
void bfd_rtt_init(struct bfd_session *bfd);
|
||||||
|
|
|
@ -13,14 +13,50 @@
|
||||||
|
|
||||||
#include "bfd.h"
|
#include "bfd.h"
|
||||||
#include "bfdd_nb.h"
|
#include "bfdd_nb.h"
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers.
|
* 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,
|
static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
|
||||||
struct bfd_key *bk)
|
struct bfd_key *bk)
|
||||||
{
|
{
|
||||||
const char *ifname = NULL, *vrfname = NULL;
|
const char *ifname = NULL, *vrfname = NULL;
|
||||||
|
char ifip[INET6_ADDRSTRLEN] = { 0 };
|
||||||
struct sockaddr_any psa, lsa;
|
struct sockaddr_any psa, lsa;
|
||||||
|
|
||||||
/* Required destination parameter. */
|
/* 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");
|
ifname = yang_dnode_get_string(dnode, "interface");
|
||||||
if (strcmp(ifname, "*") == 0)
|
if (strcmp(ifname, "*") == 0)
|
||||||
ifname = NULL;
|
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. */
|
/* 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 {
|
struct session_iter {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
const void *
|
const void *
|
||||||
bfdd_bfd_sessions_single_hop_get_next(struct nb_cb_get_next_args *args)
|
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)
|
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);
|
strtosa(dest_addr, &psa);
|
||||||
memset(&lsa, 0, sizeof(lsa));
|
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);
|
return bfd_key_lookup(bk);
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem(
|
||||||
const void *
|
const void *
|
||||||
bfdd_bfd_sessions_multi_hop_get_next(struct nb_cb_get_next_args *args)
|
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)
|
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(dest_addr, &psa);
|
||||||
strtosa(source_addr, &lsa);
|
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);
|
return bfd_key_lookup(bk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ extern "C" {
|
||||||
|
|
||||||
#define BFD_PROFILE_NAME_LEN 64
|
#define BFD_PROFILE_NAME_LEN 64
|
||||||
|
|
||||||
|
#define BFD_NAME_SIZE 255
|
||||||
|
|
||||||
const char *bfd_get_status_str(int status);
|
const char *bfd_get_status_str(int status);
|
||||||
|
|
||||||
extern void bfd_client_sendmsg(struct zclient *zclient, int command,
|
extern void bfd_client_sendmsg(struct zclient *zclient, int command,
|
||||||
|
@ -409,6 +411,8 @@ struct bfd_session_arg {
|
||||||
uint32_t min_tx;
|
uint32_t min_tx;
|
||||||
/** Detection multiplier. */
|
/** Detection multiplier. */
|
||||||
uint32_t detection_multiplier;
|
uint32_t detection_multiplier;
|
||||||
|
/* bfd session name*/
|
||||||
|
char bfd_name[BFD_NAME_SIZE + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue