mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 10:54:47 +00:00
fabricd: Add support for TLV 150 (Spine-Leaf-Extension)
To flood the tier calculated by the fabric locality detection, OpenFabric makes use of TLV 150, defined in draft-shen-isis-spine-leaf-ext-06, so add support for that TLV. Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
parent
cbd8e49e3e
commit
41a145f18d
@ -1329,6 +1329,126 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions related to TLV 150 Spine-Leaf-Extension */
|
||||
|
||||
static struct isis_spine_leaf *copy_tlv_spine_leaf(
|
||||
const struct isis_spine_leaf *spine_leaf)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return NULL;
|
||||
|
||||
struct isis_spine_leaf *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
|
||||
memcpy(rv, spine_leaf, sizeof(*rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
|
||||
struct sbuf *buf, int indent)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return;
|
||||
|
||||
sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
|
||||
if (spine_leaf->has_tier) {
|
||||
if (spine_leaf->tier == ISIS_TIER_UNDEFINED) {
|
||||
sbuf_push(buf, indent, " Tier: undefined\n");
|
||||
} else {
|
||||
sbuf_push(buf, indent, " Tier: %" PRIu8 "\n",
|
||||
spine_leaf->tier);
|
||||
}
|
||||
}
|
||||
|
||||
sbuf_push(buf, indent, " Flags:%s%s%s\n",
|
||||
spine_leaf->is_leaf ? " LEAF" : "",
|
||||
spine_leaf->is_spine ? " SPINE" : "",
|
||||
spine_leaf->is_backup ? " BACKUP" : "");
|
||||
|
||||
}
|
||||
|
||||
static void free_tlv_spine_leaf(struct isis_spine_leaf *spine_leaf)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_TLV, spine_leaf);
|
||||
}
|
||||
|
||||
#define ISIS_SPINE_LEAF_FLAG_TIER 0x08
|
||||
#define ISIS_SPINE_LEAF_FLAG_BACKUP 0x04
|
||||
#define ISIS_SPINE_LEAF_FLAG_SPINE 0x02
|
||||
#define ISIS_SPINE_LEAF_FLAG_LEAF 0x01
|
||||
|
||||
static int pack_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
|
||||
struct stream *s)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return 0;
|
||||
|
||||
uint8_t tlv_len = 2;
|
||||
|
||||
if (STREAM_WRITEABLE(s) < (unsigned)(2 + tlv_len))
|
||||
return 1;
|
||||
|
||||
stream_putc(s, ISIS_TLV_SPINE_LEAF_EXT);
|
||||
stream_putc(s, tlv_len);
|
||||
|
||||
uint16_t spine_leaf_flags = 0;
|
||||
|
||||
if (spine_leaf->has_tier) {
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_TIER;
|
||||
spine_leaf_flags |= spine_leaf->tier << 12;
|
||||
}
|
||||
|
||||
if (spine_leaf->is_leaf)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_LEAF;
|
||||
|
||||
if (spine_leaf->is_spine)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_SPINE;
|
||||
|
||||
if (spine_leaf->is_backup)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_BACKUP;
|
||||
|
||||
stream_putw(s, spine_leaf_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_tlv_spine_leaf(enum isis_tlv_context context,
|
||||
uint8_t tlv_type, uint8_t tlv_len,
|
||||
struct stream *s, struct sbuf *log,
|
||||
void *dest, int indent)
|
||||
{
|
||||
struct isis_tlvs *tlvs = dest;
|
||||
|
||||
sbuf_push(log, indent, "Unpacking Spine Leaf Extension TLV...\n");
|
||||
if (tlv_len < 2) {
|
||||
sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
|
||||
stream_forward_getp(s, tlv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tlvs->spine_leaf) {
|
||||
sbuf_push(log, indent,
|
||||
"WARNING: Spine Leaf Extension TLV present multiple times.\n");
|
||||
stream_forward_getp(s, tlv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
|
||||
|
||||
uint16_t spine_leaf_flags = stream_getw(s);
|
||||
|
||||
if (spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_TIER) {
|
||||
tlvs->spine_leaf->has_tier = true;
|
||||
tlvs->spine_leaf->tier = spine_leaf_flags >> 12;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf->is_leaf = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_LEAF;
|
||||
tlvs->spine_leaf->is_spine = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_SPINE;
|
||||
tlvs->spine_leaf->is_backup = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_BACKUP;
|
||||
|
||||
stream_forward_getp(s, tlv_len - 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions related to TLV 240 P2P Three-Way Adjacency */
|
||||
|
||||
const char *isis_threeway_state_name(enum isis_threeway_state state)
|
||||
@ -2187,6 +2307,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
|
||||
|
||||
rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
|
||||
rv->spine_leaf = copy_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -2250,6 +2372,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
|
||||
&tlvs->mt_ipv6_reach, buf, indent);
|
||||
|
||||
format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
|
||||
|
||||
format_tlv_spine_leaf(tlvs->spine_leaf, buf, indent);
|
||||
}
|
||||
|
||||
const char *isis_format_tlvs(struct isis_tlvs *tlvs)
|
||||
@ -2301,6 +2425,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
|
||||
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
|
||||
&tlvs->mt_ipv6_reach);
|
||||
free_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
free_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
|
||||
XFREE(MTYPE_ISIS_TLV, tlvs);
|
||||
}
|
||||
@ -2480,6 +2605,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
|
||||
copy_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
}
|
||||
|
||||
rv = pack_tlv_spine_leaf(tlvs->spine_leaf, stream);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (fragment_tlvs) {
|
||||
fragment_tlvs->spine_leaf =
|
||||
copy_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
}
|
||||
|
||||
for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
|
||||
pack_idx++) {
|
||||
rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
|
||||
@ -2679,6 +2812,7 @@ ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
|
||||
TLV_OPS(te_router_id, "TLV 134 TE Router ID");
|
||||
ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
|
||||
TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
|
||||
TLV_OPS(spine_leaf, "TLV 150 Spine Leaf Extensions");
|
||||
ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
|
||||
TLV_OPS(threeway_adj, "TLV 240 P2P Three-Way Adjacency");
|
||||
ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
|
||||
@ -2703,6 +2837,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
|
||||
[ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
|
||||
[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
|
||||
[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
|
||||
[ISIS_TLV_SPINE_LEAF_EXT] = &tlv_spine_leaf_ops,
|
||||
[ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
|
||||
[ISIS_TLV_THREE_WAY_ADJ] = &tlv_threeway_adj_ops,
|
||||
[ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
|
||||
@ -3239,6 +3374,24 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
|
||||
}
|
||||
}
|
||||
|
||||
void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
|
||||
bool has_tier, bool is_leaf, bool is_spine,
|
||||
bool is_backup)
|
||||
{
|
||||
assert(!tlvs->spine_leaf);
|
||||
|
||||
tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
|
||||
|
||||
if (has_tier) {
|
||||
tlvs->spine_leaf->tier = tier;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf->has_tier = has_tier;
|
||||
tlvs->spine_leaf->is_leaf = is_leaf;
|
||||
tlvs->spine_leaf->is_spine = is_spine;
|
||||
tlvs->spine_leaf->is_backup = is_backup;
|
||||
}
|
||||
|
||||
struct isis_mt_router_info *
|
||||
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
|
||||
{
|
||||
|
@ -103,6 +103,17 @@ struct isis_protocols_supported {
|
||||
uint8_t *protocols;
|
||||
};
|
||||
|
||||
#define ISIS_TIER_UNDEFINED 15
|
||||
|
||||
struct isis_spine_leaf {
|
||||
uint8_t tier;
|
||||
|
||||
bool has_tier;
|
||||
bool is_leaf;
|
||||
bool is_spine;
|
||||
bool is_backup;
|
||||
};
|
||||
|
||||
enum isis_threeway_state {
|
||||
ISIS_THREEWAY_DOWN = 2,
|
||||
ISIS_THREEWAY_INITIALIZING = 1,
|
||||
@ -205,6 +216,7 @@ struct isis_tlvs {
|
||||
struct isis_item_list ipv6_reach;
|
||||
struct isis_mt_item_list mt_ipv6_reach;
|
||||
struct isis_threeway_adj *threeway_adj;
|
||||
struct isis_spine_leaf *spine_leaf;
|
||||
};
|
||||
|
||||
struct isis_subtlvs {
|
||||
@ -236,6 +248,7 @@ enum isis_tlv_type {
|
||||
ISIS_TLV_TE_ROUTER_ID = 134,
|
||||
ISIS_TLV_EXTENDED_IP_REACH = 135,
|
||||
ISIS_TLV_DYNAMIC_HOSTNAME = 137,
|
||||
ISIS_TLV_SPINE_LEAF_EXT = 150,
|
||||
ISIS_TLV_MT_REACH = 222,
|
||||
ISIS_TLV_MT_ROUTER_INFO = 229,
|
||||
ISIS_TLV_IPV6_ADDRESS = 232,
|
||||
@ -331,6 +344,10 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
|
||||
const uint8_t *neighbor_id,
|
||||
uint32_t neighbor_circuit_id);
|
||||
|
||||
void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
|
||||
bool has_tier, bool is_leaf, bool is_spine,
|
||||
bool is_backup);
|
||||
|
||||
struct isis_mt_router_info *
|
||||
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user