mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-25 18:00:25 +00:00
bgpd: store and send bgp link-state attributes
Add the ability to store a raw copy of the incoming BGP Link-State attributes and to redistribute them as is to other routes. New types of data BGP_ATTR_LS and BGP_ATTR_LS_DATA are defined. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com> Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
parent
115f4f1ddd
commit
8b531b1107
153
bgpd/bgp_attr.c
153
bgpd/bgp_attr.c
@ -43,6 +43,9 @@
|
|||||||
#include "bgp_linkstate_tlv.h"
|
#include "bgp_linkstate_tlv.h"
|
||||||
#include "bgp_mac.h"
|
#include "bgp_mac.h"
|
||||||
|
|
||||||
|
DEFINE_MTYPE_STATIC(BGPD, BGP_ATTR_LS, "BGP Attribute Link-State");
|
||||||
|
DEFINE_MTYPE_STATIC(BGPD, BGP_ATTR_LS_DATA, "BGP Attribute Link-State Data");
|
||||||
|
|
||||||
/* Attribute strings for logging. */
|
/* Attribute strings for logging. */
|
||||||
static const struct message attr_str[] = {
|
static const struct message attr_str[] = {
|
||||||
{BGP_ATTR_ORIGIN, "ORIGIN"},
|
{BGP_ATTR_ORIGIN, "ORIGIN"},
|
||||||
@ -66,6 +69,7 @@ static const struct message attr_str[] = {
|
|||||||
#ifdef ENABLE_BGP_VNC_ATTR
|
#ifdef ENABLE_BGP_VNC_ATTR
|
||||||
{BGP_ATTR_VNC, "VNC"},
|
{BGP_ATTR_VNC, "VNC"},
|
||||||
#endif
|
#endif
|
||||||
|
{BGP_ATTR_LINK_STATE, "LINK_STATE"},
|
||||||
{BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
|
{BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
|
||||||
{BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
|
{BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
|
||||||
{BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
|
{BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
|
||||||
@ -200,6 +204,8 @@ static struct hash *vnc_hash = NULL;
|
|||||||
static struct hash *srv6_l3vpn_hash;
|
static struct hash *srv6_l3vpn_hash;
|
||||||
static struct hash *srv6_vpn_hash;
|
static struct hash *srv6_vpn_hash;
|
||||||
|
|
||||||
|
static struct hash *link_state_hash;
|
||||||
|
|
||||||
struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
|
struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
|
||||||
{
|
{
|
||||||
struct bgp_attr_encap_subtlv *new;
|
struct bgp_attr_encap_subtlv *new;
|
||||||
@ -717,6 +723,99 @@ static void srv6_finish(void)
|
|||||||
hash_clean_and_free(&srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
|
hash_clean_and_free(&srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *link_state_hash_alloc(void *p)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link_state_free(struct bgp_attr_ls *link_state)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_BGP_ATTR_LS_DATA, link_state->data);
|
||||||
|
XFREE(MTYPE_BGP_ATTR_LS, link_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bgp_attr_ls *link_state_intern(struct bgp_attr_ls *link_state)
|
||||||
|
{
|
||||||
|
struct bgp_attr_ls *find;
|
||||||
|
|
||||||
|
find = hash_get(link_state_hash, link_state, link_state_hash_alloc);
|
||||||
|
if (find != link_state)
|
||||||
|
link_state_free(link_state);
|
||||||
|
find->refcnt++;
|
||||||
|
return find;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link_state_unintern(struct bgp_attr_ls **link_statep)
|
||||||
|
{
|
||||||
|
struct bgp_attr_ls *link_state = *link_statep;
|
||||||
|
|
||||||
|
if (!*link_statep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (link_state->refcnt)
|
||||||
|
link_state->refcnt--;
|
||||||
|
|
||||||
|
if (link_state->refcnt == 0) {
|
||||||
|
hash_release(link_state_hash, link_state);
|
||||||
|
link_state_free(link_state);
|
||||||
|
*link_statep = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t link_state_hash_key_make(const void *p)
|
||||||
|
{
|
||||||
|
const struct bgp_attr_ls *link_state = p;
|
||||||
|
uint32_t key = 0;
|
||||||
|
|
||||||
|
key = jhash_1word(link_state->length, key);
|
||||||
|
key = jhash(link_state->data, link_state->length, key);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool link_state_hash_cmp(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
const struct bgp_attr_ls *link_state1 = p1;
|
||||||
|
const struct bgp_attr_ls *link_state2 = p2;
|
||||||
|
|
||||||
|
if (!link_state1 && link_state2)
|
||||||
|
return false;
|
||||||
|
if (!link_state1 && link_state2)
|
||||||
|
return false;
|
||||||
|
if (!link_state1 && !link_state2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (link_state1->length != link_state2->length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !memcmp(link_state1->data, link_state2->data,
|
||||||
|
link_state1->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool link_state_same(const struct bgp_attr_ls *h1,
|
||||||
|
const struct bgp_attr_ls *h2)
|
||||||
|
{
|
||||||
|
if (h1 == h2)
|
||||||
|
return true;
|
||||||
|
else if (h1 == NULL || h2 == NULL)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return link_state_hash_cmp((const void *)h1, (const void *)h2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link_state_init(void)
|
||||||
|
{
|
||||||
|
link_state_hash =
|
||||||
|
hash_create(link_state_hash_key_make, link_state_hash_cmp,
|
||||||
|
"BGP Link-State Attributes TLVs");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link_state_finish(void)
|
||||||
|
{
|
||||||
|
hash_clean_and_free(&link_state_hash,
|
||||||
|
(void (*)(void *))link_state_free);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int transit_hash_key_make(const void *p)
|
static unsigned int transit_hash_key_make(const void *p)
|
||||||
{
|
{
|
||||||
const struct transit *transit = p;
|
const struct transit *transit = p;
|
||||||
@ -806,6 +905,8 @@ unsigned int attrhash_key_make(const void *p)
|
|||||||
MIX(attr->bh_type);
|
MIX(attr->bh_type);
|
||||||
MIX(attr->otc);
|
MIX(attr->otc);
|
||||||
MIX(bgp_attr_get_aigp_metric(attr));
|
MIX(bgp_attr_get_aigp_metric(attr));
|
||||||
|
if (attr->link_state)
|
||||||
|
MIX(link_state_hash_key_make(attr->link_state));
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
@ -871,7 +972,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
|
|||||||
attr1->srte_color == attr2->srte_color &&
|
attr1->srte_color == attr2->srte_color &&
|
||||||
attr1->nh_type == attr2->nh_type &&
|
attr1->nh_type == attr2->nh_type &&
|
||||||
attr1->bh_type == attr2->bh_type &&
|
attr1->bh_type == attr2->bh_type &&
|
||||||
attr1->otc == attr2->otc)
|
attr1->otc == attr2->otc &&
|
||||||
|
link_state_same(attr1->link_state, attr2->link_state))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1133,12 @@ struct attr *bgp_attr_intern(struct attr *attr)
|
|||||||
else
|
else
|
||||||
attr->srv6_vpn->refcnt++;
|
attr->srv6_vpn->refcnt++;
|
||||||
}
|
}
|
||||||
|
if (attr->link_state) {
|
||||||
|
if (!attr->link_state->refcnt)
|
||||||
|
attr->link_state = link_state_intern(attr->link_state);
|
||||||
|
else
|
||||||
|
attr->link_state->refcnt++;
|
||||||
|
}
|
||||||
#ifdef ENABLE_BGP_VNC
|
#ifdef ENABLE_BGP_VNC
|
||||||
struct bgp_attr_encap_subtlv *vnc_subtlvs =
|
struct bgp_attr_encap_subtlv *vnc_subtlvs =
|
||||||
bgp_attr_get_vnc_subtlvs(attr);
|
bgp_attr_get_vnc_subtlvs(attr);
|
||||||
@ -1249,6 +1357,8 @@ void bgp_attr_unintern_sub(struct attr *attr)
|
|||||||
|
|
||||||
srv6_l3vpn_unintern(&attr->srv6_l3vpn);
|
srv6_l3vpn_unintern(&attr->srv6_l3vpn);
|
||||||
srv6_vpn_unintern(&attr->srv6_vpn);
|
srv6_vpn_unintern(&attr->srv6_vpn);
|
||||||
|
|
||||||
|
link_state_unintern(&attr->link_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free bgp attribute and aspath. */
|
/* Free bgp attribute and aspath. */
|
||||||
@ -1412,6 +1522,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
|
|||||||
case BGP_ATTR_ENCAP:
|
case BGP_ATTR_ENCAP:
|
||||||
case BGP_ATTR_OTC:
|
case BGP_ATTR_OTC:
|
||||||
return BGP_ATTR_PARSE_WITHDRAW;
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
|
case BGP_ATTR_LINK_STATE:
|
||||||
case BGP_ATTR_MP_REACH_NLRI:
|
case BGP_ATTR_MP_REACH_NLRI:
|
||||||
case BGP_ATTR_MP_UNREACH_NLRI:
|
case BGP_ATTR_MP_UNREACH_NLRI:
|
||||||
bgp_notify_send_with_data(peer->connection,
|
bgp_notify_send_with_data(peer->connection,
|
||||||
@ -1498,6 +1609,7 @@ const uint8_t attr_flags_values[] = {
|
|||||||
[BGP_ATTR_IPV6_EXT_COMMUNITIES] =
|
[BGP_ATTR_IPV6_EXT_COMMUNITIES] =
|
||||||
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
||||||
[BGP_ATTR_AIGP] = BGP_ATTR_FLAG_OPTIONAL,
|
[BGP_ATTR_AIGP] = BGP_ATTR_FLAG_OPTIONAL,
|
||||||
|
[BGP_ATTR_LINK_STATE] = BGP_ATTR_FLAG_OPTIONAL,
|
||||||
};
|
};
|
||||||
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
|
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
|
||||||
|
|
||||||
@ -3291,6 +3403,32 @@ aigp_ignore:
|
|||||||
return bgp_attr_ignore(peer, args->type);
|
return bgp_attr_ignore(peer, args->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Link-State (rfc7752) */
|
||||||
|
static enum bgp_attr_parse_ret
|
||||||
|
bgp_attr_linkstate(struct bgp_attr_parser_args *args)
|
||||||
|
{
|
||||||
|
struct peer *const peer = args->peer;
|
||||||
|
struct attr *const attr = args->attr;
|
||||||
|
const bgp_size_t length = args->length;
|
||||||
|
struct stream *s = peer->curr;
|
||||||
|
struct bgp_attr_ls *bgp_attr_ls;
|
||||||
|
void *bgp_attr_ls_data;
|
||||||
|
|
||||||
|
if (STREAM_READABLE(s) == 0)
|
||||||
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
|
||||||
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LINK_STATE);
|
||||||
|
|
||||||
|
bgp_attr_ls = XCALLOC(MTYPE_BGP_ATTR_LS, sizeof(struct bgp_attr_ls));
|
||||||
|
bgp_attr_ls->length = length;
|
||||||
|
bgp_attr_ls_data = XCALLOC(MTYPE_BGP_ATTR_LS_DATA, length);
|
||||||
|
bgp_attr_ls->data = bgp_attr_ls_data;
|
||||||
|
stream_get(bgp_attr_ls_data, s, length);
|
||||||
|
attr->link_state = link_state_intern(bgp_attr_ls);
|
||||||
|
|
||||||
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
}
|
||||||
|
|
||||||
/* OTC attribute. */
|
/* OTC attribute. */
|
||||||
static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
|
static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
|
||||||
{
|
{
|
||||||
@ -3748,6 +3886,9 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
|
|||||||
case BGP_ATTR_AIGP:
|
case BGP_ATTR_AIGP:
|
||||||
ret = bgp_attr_aigp(&attr_args);
|
ret = bgp_attr_aigp(&attr_args);
|
||||||
break;
|
break;
|
||||||
|
case BGP_ATTR_LINK_STATE:
|
||||||
|
ret = bgp_attr_linkstate(&attr_args);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = bgp_attr_unknown(&attr_args);
|
ret = bgp_attr_unknown(&attr_args);
|
||||||
break;
|
break;
|
||||||
@ -4840,6 +4981,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* BGP Link-State */
|
||||||
|
if (attr && attr->link_state) {
|
||||||
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
|
||||||
|
stream_putc(s, BGP_ATTR_LINK_STATE);
|
||||||
|
stream_putc(s, attr->link_state->length);
|
||||||
|
stream_put(s, attr->link_state->data, attr->link_state->length);
|
||||||
|
}
|
||||||
|
|
||||||
/* PMSI Tunnel */
|
/* PMSI Tunnel */
|
||||||
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
|
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
|
||||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
|
||||||
@ -4944,6 +5093,7 @@ void bgp_attr_init(void)
|
|||||||
transit_init();
|
transit_init();
|
||||||
encap_init();
|
encap_init();
|
||||||
srv6_init();
|
srv6_init();
|
||||||
|
link_state_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgp_attr_finish(void)
|
void bgp_attr_finish(void)
|
||||||
@ -4957,6 +5107,7 @@ void bgp_attr_finish(void)
|
|||||||
transit_finish();
|
transit_finish();
|
||||||
encap_finish();
|
encap_finish();
|
||||||
srv6_finish();
|
srv6_finish();
|
||||||
|
link_state_finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make attribute packet. */
|
/* Make attribute packet. */
|
||||||
|
@ -136,6 +136,13 @@ struct bgp_attr_srv6_l3vpn {
|
|||||||
uint8_t transposition_offset;
|
uint8_t transposition_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bgp_attr_ls {
|
||||||
|
unsigned long refcnt;
|
||||||
|
|
||||||
|
uint8_t length;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
/* BGP core attribute structure. */
|
/* BGP core attribute structure. */
|
||||||
struct attr {
|
struct attr {
|
||||||
/* AS Path structure */
|
/* AS Path structure */
|
||||||
@ -159,6 +166,8 @@ struct attr {
|
|||||||
/* Path origin attribute */
|
/* Path origin attribute */
|
||||||
uint8_t origin;
|
uint8_t origin;
|
||||||
|
|
||||||
|
struct bgp_attr_ls *link_state; /* BGP Link State attribute */
|
||||||
|
|
||||||
/* PMSI tunnel type (RFC 6514). */
|
/* PMSI tunnel type (RFC 6514). */
|
||||||
enum pta_type pmsi_tnl_type;
|
enum pta_type pmsi_tnl_type;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -219,5 +219,8 @@ extern char *bgp_linkstate_nlri_prefix_display(char *buf, size_t size,
|
|||||||
extern void bgp_linkstate_nlri_prefix_json(json_object *json,
|
extern void bgp_linkstate_nlri_prefix_json(json_object *json,
|
||||||
uint16_t nlri_type, uintptr_t prefix,
|
uint16_t nlri_type, uintptr_t prefix,
|
||||||
uint16_t len);
|
uint16_t len);
|
||||||
|
extern void bgp_linkstate_tlv_attribute_display(struct vty *vty,
|
||||||
|
struct bgp_attr_ls *attr_ls,
|
||||||
|
int indent, json_object *json);
|
||||||
|
|
||||||
#endif /* BGP_LINKSTATE_TLV_H */
|
#endif /* BGP_LINKSTATE_TLV_H */
|
||||||
|
@ -10112,6 +10112,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|
|||||||
json_object *json_peer = NULL;
|
json_object *json_peer = NULL;
|
||||||
json_object *json_string = NULL;
|
json_object *json_string = NULL;
|
||||||
json_object *json_adv_to = NULL;
|
json_object *json_adv_to = NULL;
|
||||||
|
json_object *json_bgp_ls_attr = NULL;
|
||||||
int first = 0;
|
int first = 0;
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
@ -11045,11 +11046,29 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|
|||||||
" Time until Long-lived stale route deleted: %lu\n",
|
" Time until Long-lived stale route deleted: %lu\n",
|
||||||
llgr_remaining);
|
llgr_remaining);
|
||||||
}
|
}
|
||||||
if (safi == SAFI_LINKSTATE && json_paths)
|
|
||||||
|
if (safi == SAFI_LINKSTATE) {
|
||||||
|
/* BGP Link-State NLRI */
|
||||||
|
if (json_paths)
|
||||||
bgp_linkstate_nlri_prefix_json(
|
bgp_linkstate_nlri_prefix_json(
|
||||||
json_path, bn->rn->p.u.prefix_linkstate.nlri_type,
|
json_path, bn->rn->p.u.prefix_linkstate.nlri_type,
|
||||||
bn->rn->p.u.prefix_linkstate.ptr, bn->rn->p.prefixlen);
|
bn->rn->p.u.prefix_linkstate.ptr, bn->rn->p.prefixlen);
|
||||||
|
|
||||||
|
/* BGP Link-State Attributes */
|
||||||
|
if (attr->link_state) {
|
||||||
|
if (json_paths) {
|
||||||
|
json_bgp_ls_attr = json_object_new_object();
|
||||||
|
json_object_object_add(json_path,
|
||||||
|
"linkStateAttributes",
|
||||||
|
json_bgp_ls_attr);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, " BGP-LS attributes:\n");
|
||||||
|
}
|
||||||
|
bgp_linkstate_tlv_attribute_display(
|
||||||
|
vty, attr->link_state, 4, json_bgp_ls_attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Output some debug about internal state of the dest flags */
|
/* Output some debug about internal state of the dest flags */
|
||||||
if (json_paths) {
|
if (json_paths) {
|
||||||
if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
|
if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
|
||||||
|
@ -1926,6 +1926,7 @@ struct bgp_nlri {
|
|||||||
#define BGP_ATTR_ENCAP 23
|
#define BGP_ATTR_ENCAP 23
|
||||||
#define BGP_ATTR_IPV6_EXT_COMMUNITIES 25
|
#define BGP_ATTR_IPV6_EXT_COMMUNITIES 25
|
||||||
#define BGP_ATTR_AIGP 26
|
#define BGP_ATTR_AIGP 26
|
||||||
|
#define BGP_ATTR_LINK_STATE 29
|
||||||
#define BGP_ATTR_LARGE_COMMUNITIES 32
|
#define BGP_ATTR_LARGE_COMMUNITIES 32
|
||||||
#define BGP_ATTR_OTC 35
|
#define BGP_ATTR_OTC 35
|
||||||
#define BGP_ATTR_PREFIX_SID 40
|
#define BGP_ATTR_PREFIX_SID 40
|
||||||
|
Loading…
Reference in New Issue
Block a user