isisd: add support for TLV 240 P2P Three-Way Adjacency

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
Christian Franke 2018-03-05 18:51:17 +01:00
parent 9703538621
commit 9fe2120814
3 changed files with 171 additions and 0 deletions

View File

@ -1329,6 +1329,119 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
return 0;
}
/* Functions related to TLV 240 P2P Three-Way Adjacency */
const char *isis_threeway_state_name(enum isis_threeway_state state)
{
switch (state) {
case ISIS_THREEWAY_DOWN:
return "Down";
case ISIS_THREEWAY_INITIALIZING:
return "Initializing";
case ISIS_THREEWAY_UP:
return "Up";
default:
return "Invalid!";
}
}
static struct isis_threeway_adj *copy_tlv_threeway_adj(
const struct isis_threeway_adj *threeway_adj)
{
if (!threeway_adj)
return NULL;
struct isis_threeway_adj *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
memcpy(rv, threeway_adj, sizeof(*rv));
return rv;
}
static void format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
struct sbuf *buf, int indent)
{
if (!threeway_adj)
return;
sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
sbuf_push(buf, indent, " State: %s (%d)\n",
isis_threeway_state_name(threeway_adj->state),
threeway_adj->state);
sbuf_push(buf, indent, " Extended Local Circuit ID: %" PRIu32 "\n",
threeway_adj->local_circuit_id);
if (!threeway_adj->neighbor_set)
return;
sbuf_push(buf, indent, " Neighbor System ID: %s\n",
isis_format_id(threeway_adj->neighbor_id, 6));
sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %" PRIu32 "\n",
threeway_adj->neighbor_circuit_id);
}
static void free_tlv_threeway_adj(struct isis_threeway_adj *threeway_adj)
{
XFREE(MTYPE_ISIS_TLV, threeway_adj);
}
static int pack_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
struct stream *s)
{
if (!threeway_adj)
return 0;
uint8_t tlv_len = (threeway_adj->neighbor_set) ? 15 : 5;
if (STREAM_WRITEABLE(s) < (unsigned)(2 + tlv_len))
return 1;
stream_putc(s, ISIS_TLV_THREE_WAY_ADJ);
stream_putc(s, tlv_len);
stream_putc(s, threeway_adj->state);
stream_putl(s, threeway_adj->local_circuit_id);
if (threeway_adj->neighbor_set) {
stream_put(s, threeway_adj->neighbor_id, 6);
stream_putl(s, threeway_adj->neighbor_circuit_id);
}
return 0;
}
static int unpack_tlv_threeway_adj(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 P2P Three-Way Adjacency TLV...\n");
if (tlv_len != 5 && tlv_len != 15) {
sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
stream_forward_getp(s, tlv_len);
return 0;
}
if (tlvs->threeway_adj) {
sbuf_push(log, indent,
"WARNING: P2P Three-Way Adjacency TLV present multiple times.\n");
stream_forward_getp(s, tlv_len);
return 0;
}
tlvs->threeway_adj = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->threeway_adj));
tlvs->threeway_adj->state = stream_getc(s);
tlvs->threeway_adj->local_circuit_id = stream_getl(s);
if (tlv_len == 15) {
tlvs->threeway_adj->neighbor_set = true;
stream_get(tlvs->threeway_adj->neighbor_id, s, 6);
tlvs->threeway_adj->neighbor_circuit_id = stream_getl(s);
}
return 0;
}
/* Functions related to TLVs 236/237 IPv6/MT-IPv6 reach */
static struct isis_item *copy_item_ipv6_reach(struct isis_item *i)
@ -2067,6 +2180,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
copy_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
&tlvs->mt_ipv6_reach, &rv->mt_ipv6_reach);
rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
return rv;
}
@ -2128,6 +2243,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
&tlvs->mt_ipv6_reach, buf, indent);
format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
}
const char *isis_format_tlvs(struct isis_tlvs *tlvs)
@ -2178,6 +2295,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach);
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
&tlvs->mt_ipv6_reach);
free_tlv_threeway_adj(tlvs->threeway_adj);
XFREE(MTYPE_ISIS_TLV, tlvs);
}
@ -2349,6 +2467,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
copy_tlv_te_router_id(tlvs->te_router_id);
}
rv = pack_tlv_threeway_adj(tlvs->threeway_adj, stream);
if (rv)
return rv;
if (fragment_tlvs) {
fragment_tlvs->threeway_adj =
copy_tlv_threeway_adj(tlvs->threeway_adj);
}
for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
pack_idx++) {
rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
@ -2549,6 +2675,7 @@ 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");
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");
ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
@ -2572,6 +2699,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_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,
[ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
[ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
@ -3072,6 +3200,25 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
append_item(l, (struct isis_item *)r);
}
void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
enum isis_threeway_state state,
uint32_t local_circuit_id,
const uint8_t *neighbor_id,
uint32_t neighbor_circuit_id)
{
assert(!tlvs->threeway_adj);
tlvs->threeway_adj = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->threeway_adj));
tlvs->threeway_adj->state = state;
tlvs->threeway_adj->local_circuit_id = local_circuit_id;
if (neighbor_id) {
tlvs->threeway_adj->neighbor_set = true;
memcpy(tlvs->threeway_adj->neighbor_id, neighbor_id, 6);
tlvs->threeway_adj->neighbor_circuit_id = neighbor_circuit_id;
}
}
struct isis_mt_router_info *
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
{

View File

@ -103,6 +103,20 @@ struct isis_protocols_supported {
uint8_t *protocols;
};
enum isis_threeway_state {
ISIS_THREEWAY_DOWN = 2,
ISIS_THREEWAY_INITIALIZING = 1,
ISIS_THREEWAY_UP = 0
};
struct isis_threeway_adj {
enum isis_threeway_state state;
uint32_t local_circuit_id;
bool neighbor_set;
uint8_t neighbor_id[6];
uint32_t neighbor_circuit_id;
};
struct isis_item;
struct isis_item {
struct isis_item *next;
@ -190,6 +204,7 @@ struct isis_tlvs {
char *hostname;
struct isis_item_list ipv6_reach;
struct isis_mt_item_list mt_ipv6_reach;
struct isis_threeway_adj *threeway_adj;
};
struct isis_subtlvs {
@ -227,6 +242,7 @@ enum isis_tlv_type {
ISIS_TLV_MT_IP_REACH = 235,
ISIS_TLV_IPV6_REACH = 236,
ISIS_TLV_MT_IPV6_REACH = 237,
ISIS_TLV_THREE_WAY_ADJ = 240,
ISIS_TLV_MAX = 256,
ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
@ -303,6 +319,14 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
uint8_t *id, uint32_t metric,
uint8_t *subtlvs, uint8_t subtlv_len);
const char *isis_threeway_state_name(enum isis_threeway_state state);
void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
enum isis_threeway_state state,
uint32_t local_circuit_id,
const uint8_t *neighbor_id,
uint32_t neighbor_circuit_id);
struct isis_mt_router_info *
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
#endif