isisd: announce and parse MT IS reachabilities

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
Christian Franke 2017-04-27 13:56:43 +02:00
parent d8fba7d974
commit 206f4aae58
6 changed files with 404 additions and 76 deletions

View File

@ -47,6 +47,7 @@
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_events.h"
#include "isisd/isis_mt.h"
extern struct isis *isis;

View File

@ -828,6 +828,34 @@ lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost)
lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
}
static void
lsp_print_mt_reach(struct list *list, struct vty *vty,
char dynhost, uint16_t mtid)
{
struct listnode *node;
struct te_is_neigh *neigh;
for (ALL_LIST_ELEMENTS_RO (list, node, neigh))
{
u_char lspid[255];
lspid_print(neigh->neigh_id, lspid, dynhost, 0);
if (mtid == ISIS_MT_IPV4_UNICAST)
{
vty_out(vty, " Metric : %-8d IS-Extended : %s%s",
GET_TE_METRIC(neigh), lspid, VTY_NEWLINE);
}
else
{
vty_out(vty, " Metric : %-8d MT-Reach : %s %s%s",
GET_TE_METRIC(neigh), lspid,
isis_mtid2str(mtid), VTY_NEWLINE);
}
if (IS_MPLS_TE(isisMplsTE))
mpls_te_print_detail(vty, neigh);
}
}
void
lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
{
@ -835,12 +863,12 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
int i;
struct listnode *lnode;
struct is_neigh *is_neigh;
struct te_is_neigh *te_is_neigh;
struct ipv4_reachability *ipv4_reach;
struct in_addr *ipv4_addr;
struct te_ipv4_reachability *te_ipv4_reach;
struct ipv6_reachability *ipv6_reach;
struct mt_router_info *mt_router_info;
struct tlv_mt_neighbors *mt_is_neigh;
struct in6_addr in6;
u_char buff[BUFSIZ];
u_char LSPid[255];
@ -978,15 +1006,12 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
}
/* TE IS neighbor tlv */
if (lsp->tlv_data.te_is_neighs)
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, lnode, te_is_neigh))
{
lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
vty_out (vty, " Metric : %-8d IS-Extended : %s%s",
GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE);
if (IS_MPLS_TE(isisMplsTE))
mpls_te_print_detail(vty, te_is_neigh);
}
lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty,
dynhost, ISIS_MT_IPV4_UNICAST);
/* MT IS neighbor tlv */
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.mt_is_neighs, lnode, mt_is_neigh))
lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost, mt_is_neigh->mtid);
/* TE IPv4 tlv */
if (lsp->tlv_data.te_ipv4_reachs)
@ -1039,6 +1064,42 @@ lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
return lsp_count;
}
static void
_lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
int frag_thold,
unsigned int tlv_build_func (struct list *, struct stream *,
void *arg),
void *arg)
{
while (*from && listcount(*from))
{
unsigned int count;
count = tlv_build_func(*from, lsp->pdu, arg);
if (listcount(*to) != 0 || count != listcount(*from))
{
struct listnode *node, *nnode;
void *elem;
for (ALL_LIST_ELEMENTS(*from, node, nnode, elem))
{
if (!count)
break;
listnode_add (*to, elem);
list_delete_node (*from, node);
--count;
}
}
else
{
list_free (*to);
*to = *from;
*from = NULL;
}
}
}
#define FRAG_THOLD(S,T) \
((STREAM_SIZE(S)*T)/100)
@ -1637,10 +1698,8 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
/* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
te_is_neigh->sub_tlvs_length = 0;
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor",
area->area_tag, sysid_print(te_is_neigh->neigh_id),
LSP_PSEUDO_ID(te_is_neigh->neigh_id));
tlvs_add_mt_bcast(&tlv_data, circuit, level, te_is_neigh);
XFREE(MTYPE_ISIS_TLV, te_is_neigh);
}
}
}
@ -1697,9 +1756,9 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
else
/* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
te_is_neigh->sub_tlvs_length = 0;
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag,
sysid_print(te_is_neigh->neigh_id));
tlvs_add_mt_p2p(&tlv_data, circuit, te_is_neigh);
XFREE(MTYPE_ISIS_TLV, te_is_neigh);
}
}
else
@ -1791,13 +1850,31 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
{
if (lsp->tlv_data.te_is_neighs == NULL)
lsp->tlv_data.te_is_neighs = list_new ();
lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
tlv_add_te_is_neighs);
_lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
area->lsp_frag_threshold, tlv_add_te_is_neighs, NULL);
if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
lsp0, area, level);
}
struct tlv_mt_neighbors *mt_neighs;
for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_is_neighs, node, mt_neighs))
{
while (mt_neighs->list && listcount(mt_neighs->list))
{
struct tlv_mt_neighbors *frag_mt_neighs;
frag_mt_neighs = tlvs_get_mt_neighbors(&lsp->tlv_data, mt_neighs->mtid);
_lsp_tlv_fit (lsp, &mt_neighs->list, &frag_mt_neighs->list,
area->lsp_frag_threshold, tlv_add_te_is_neighs,
&mt_neighs->mtid);
if (mt_neighs->list && listcount(mt_neighs->list))
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
lsp0, area, level);
}
}
lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
free_tlvs (&tlv_data);
@ -2234,7 +2311,7 @@ lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
if (lsp->tlv_data.te_is_neighs && listcount (lsp->tlv_data.te_is_neighs) > 0)
tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu);
tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu, NULL);
if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);

View File

@ -26,11 +26,14 @@
#include "isisd/isis_circuit.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_mt.h"
DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info")
DEFINE_MTYPE_STATIC(ISISD, MT_NEIGHBORS, "ISIS MT Neighbors for TLV")
/* MT naming api */
const char *isis_mtid2str(uint16_t mtid)
@ -362,6 +365,7 @@ circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count)
return rv;
}
/* ADJ specific MT API */
static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
uint16_t mtid)
{
@ -437,3 +441,156 @@ adj_mt_finish(struct isis_adjacency *adj)
XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set);
adj->mt_count = 0;
}
/* TLV MT Neighbors api */
struct tlv_mt_neighbors*
tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid)
{
return lookup_mt_setting(tlvs->mt_is_neighs, mtid);
}
static struct tlv_mt_neighbors*
tlvs_new_mt_neighbors(uint16_t mtid)
{
struct tlv_mt_neighbors *rv;
rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv));
rv->mtid = mtid;
rv->list = list_new();
return rv;
};
static void
tlvs_free_mt_neighbors(void *arg)
{
struct tlv_mt_neighbors *neighbors = arg;
if (neighbors && neighbors->list)
list_delete(neighbors->list);
XFREE(MTYPE_MT_NEIGHBORS, neighbors);
}
static void
tlvs_add_mt_neighbors(struct tlvs *tlvs, struct tlv_mt_neighbors *neighbors)
{
add_mt_setting(&tlvs->mt_is_neighs, neighbors);
tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors;
}
struct tlv_mt_neighbors*
tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid)
{
struct tlv_mt_neighbors *neighbors;
neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid);
if (!neighbors)
{
neighbors = tlvs_new_mt_neighbors(mtid);
tlvs_add_mt_neighbors(tlvs, neighbors);
}
return neighbors;
}
static void
mt_set_add(uint16_t **mt_set, unsigned int *size,
unsigned int *index, uint16_t mtid)
{
for (unsigned int i = 0; i < *index; i++)
{
if ((*mt_set)[i] == mtid)
return;
}
if (*index >= *size)
{
*mt_set = XREALLOC(MTYPE_TMP, *mt_set, sizeof(**mt_set) * ((*index) + 1));
*size = (*index) + 1;
}
(*mt_set)[*index] = mtid;
*index = (*index) + 1;
}
static uint16_t *
circuit_bcast_mt_set(struct isis_circuit *circuit, int level,
unsigned int *mt_count)
{
static uint16_t *rv;
static unsigned int size;
struct listnode *node;
struct isis_adjacency *adj;
unsigned int count = 0;
if (circuit->circ_type != CIRCUIT_T_BROADCAST)
{
*mt_count = 0;
return NULL;
}
for (ALL_LIST_ELEMENTS_RO(circuit->u.bc.adjdb[level - 1], node, adj))
{
if (adj->adj_state != ISIS_ADJ_UP)
continue;
for (unsigned int i = 0; i < adj->mt_count; i++)
mt_set_add(&rv, &size, &count, adj->mt_set[i]);
}
*mt_count = count;
return rv;
}
static void
tlvs_add_mt_set(struct isis_area *area,
struct tlvs *tlvs, unsigned int mt_count,
uint16_t *mt_set, struct te_is_neigh *neigh)
{
for (unsigned int i = 0; i < mt_count; i++)
{
uint16_t mtid = mt_set[i];
struct te_is_neigh *ne_copy;
ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy));
memcpy(ne_copy, neigh, sizeof(*ne_copy));
if (mt_set[i] == ISIS_MT_IPV4_UNICAST)
{
listnode_add(tlvs->te_is_neighs, ne_copy);
lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor",
area->area_tag, sysid_print(ne_copy->neigh_id),
LSP_PSEUDO_ID(ne_copy->neigh_id));
}
else
{
struct tlv_mt_neighbors *neighbors;
neighbors = tlvs_get_mt_neighbors(tlvs, mtid);
neighbors->list->del = free_tlv;
listnode_add(neighbors->list, ne_copy);
lsp_debug("ISIS (%s): Adding %s.%02x as mt-style neighbor for %s",
area->area_tag, sysid_print(ne_copy->neigh_id),
LSP_PSEUDO_ID(ne_copy->neigh_id), isis_mtid2str(mtid));
}
}
}
void
tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
int level, struct te_is_neigh *neigh)
{
unsigned int mt_count;
uint16_t *mt_set = circuit_bcast_mt_set(circuit, level,
&mt_count);
tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh);
}
void
tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
struct te_is_neigh *neigh)
{
struct isis_adjacency *adj = circuit->u.p2p.neighbor;
tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh);
}

View File

@ -53,6 +53,8 @@
#define ISIS_MT_INFO_FIELDS \
uint16_t mtid;
struct list;
struct isis_area_mt_setting {
ISIS_MT_INFO_FIELDS
bool enabled;
@ -64,6 +66,11 @@ struct isis_circuit_mt_setting {
bool enabled;
};
struct tlv_mt_neighbors {
ISIS_MT_INFO_FIELDS
struct list *list;
};
const char *isis_mtid2str(uint16_t mtid);
uint16_t isis_str2mtid(const char *name);
@ -71,6 +78,10 @@ struct isis_adjacency;
struct isis_area;
struct isis_circuit;
struct tlvs;
struct te_is_neigh;
struct tlv_mt_neighbors* tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid);
struct tlv_mt_neighbors* tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid);
struct isis_area_mt_setting* area_lookup_mt_setting(struct isis_area *area,
uint16_t mtid);
@ -107,4 +118,8 @@ struct isis_circuit_mt_setting** circuit_mt_settings(struct isis_circuit *circui
bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
struct isis_adjacency *adj);
void adj_mt_finish(struct isis_adjacency *adj);
void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
int level, struct te_is_neigh *neigh);
void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
struct te_is_neigh *neigh);
#endif

View File

@ -43,6 +43,7 @@
#include "isisd/isis_pdu.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
void
free_tlv (void *val)
@ -67,6 +68,8 @@ free_tlvs (struct tlvs *tlvs)
list_delete (tlvs->is_neighs);
if (tlvs->te_is_neighs)
list_delete (tlvs->te_is_neighs);
if (tlvs->mt_is_neighs)
list_delete (tlvs->mt_is_neighs);
if (tlvs->es_neighs)
list_delete (tlvs->es_neighs);
if (tlvs->lsp_entries)
@ -93,6 +96,83 @@ free_tlvs (struct tlvs *tlvs)
return;
}
static int
parse_mt_is_neighs(struct tlvs *tlvs, bool read_mtid,
unsigned int length, u_char *pnt)
{
struct list *neigh_list;
uint16_t mtid;
if (read_mtid)
{
uint16_t mtid_buf;
if (length < sizeof(mtid_buf))
{
zlog_warn("ISIS-TLV: mt tlv too short to contain MT id");
return ISIS_WARNING;
}
memcpy(&mtid_buf, pnt, sizeof(mtid_buf));
pnt += sizeof(mtid_buf);
length -= sizeof(mtid_buf);
mtid = ntohs(mtid_buf) & ISIS_MT_MASK;
}
else
{
mtid = ISIS_MT_IPV4_UNICAST;
}
if (mtid == ISIS_MT_IPV4_UNICAST)
{
if (!tlvs->te_is_neighs)
{
tlvs->te_is_neighs = list_new();
tlvs->te_is_neighs->del = free_tlv;
}
neigh_list = tlvs->te_is_neighs;
}
else
{
struct tlv_mt_neighbors *neighbors;
neighbors = tlvs_get_mt_neighbors(tlvs, mtid);
neighbors->list->del = free_tlv;
neigh_list = neighbors->list;
}
while (length >= IS_NEIGHBOURS_LEN)
{
struct te_is_neigh *neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(*neigh));
memcpy(neigh, pnt, IS_NEIGHBOURS_LEN);
pnt += IS_NEIGHBOURS_LEN;
length -= IS_NEIGHBOURS_LEN;
if (neigh->sub_tlvs_length > length)
{
zlog_warn("ISIS-TLV: neighbor subtlv length exceeds TLV size");
XFREE(MTYPE_ISIS_TLV, neigh);
return ISIS_WARNING;
}
memcpy(neigh->sub_tlvs, pnt, neigh->sub_tlvs_length);
pnt += neigh->sub_tlvs_length;
length -= neigh->sub_tlvs_length;
listnode_add(neigh_list, neigh);
}
if (length)
{
zlog_warn("ISIS-TLV: TE/MT neighor TLV has trailing data");
return ISIS_WARNING;
}
return ISIS_OK;
}
/*
* Parses the tlvs found in the variant length part of the PDU.
* Caller tells with flags in "expected" which TLV's it is interested in.
@ -105,7 +185,6 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
struct lan_neigh *lan_nei;
struct area_addr *area_addr;
struct is_neigh *is_nei;
struct te_is_neigh *te_is_nei;
struct es_neigh *es_nei;
struct lsp_entry *lsp_entry;
struct in_addr *ipv4_addr;
@ -209,54 +288,25 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
break;
case TE_IS_NEIGHBOURS:
/* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Neighbour ID | 7
* +---------------------------------------------------------------+
* | TE Metric | 3
* +---------------------------------------------------------------+
* | SubTLVs Length | 1
* +---------------------------------------------------------------+
* : :
*/
*found |= TLVFLAG_TE_IS_NEIGHS;
#ifdef EXTREME_TLV_DEBUG
zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
areatag, length);
#endif /* EXTREME_TLV_DEBUG */
if (TLVFLAG_TE_IS_NEIGHS & *expected)
{
while (length > value_len)
{
te_is_nei = (struct te_is_neigh *) pnt;
value_len += IS_NEIGHBOURS_LEN;
pnt += IS_NEIGHBOURS_LEN;
/* FIXME - subtlvs are handled here, for now we skip */
/* FIXME: All TE SubTLVs are not necessary present in LSP PDU. */
/* So, it must be copied in a new te_is_neigh structure */
/* rather than just initialize pointer to the original LSP PDU */
/* to avoid consider the rest of lspdu as subTLVs or buffer overflow */
if (IS_MPLS_TE(isisMplsTE))
{
struct te_is_neigh *new = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh));
memcpy(new->neigh_id, te_is_nei->neigh_id, ISIS_SYS_ID_LEN + 1);
memcpy(new->te_metric, te_is_nei->te_metric, 3);
new->sub_tlvs_length = te_is_nei->sub_tlvs_length;
memcpy(new->sub_tlvs, pnt, te_is_nei->sub_tlvs_length);
te_is_nei = new;
}
/* Skip SUB TLVs payload */
value_len += te_is_nei->sub_tlvs_length;
pnt += te_is_nei->sub_tlvs_length;
retval = parse_mt_is_neighs(tlvs, false, length, pnt);
pnt += length;
break;
if (!tlvs->te_is_neighs)
tlvs->te_is_neighs = list_new ();
listnode_add (tlvs->te_is_neighs, te_is_nei);
}
}
else
{
pnt += length;
}
case MT_IS_NEIGHBOURS:
*found |= TLVFLAG_TE_IS_NEIGHS;
#ifdef EXTREME_TLV_DEBUG
zlog_debug ("ISIS-TLV (%s): MT IS Neighbours length %d",
areatag, length);
#endif
if (TLVFLAG_TE_IS_NEIGHS & *expected)
retval = parse_mt_is_neighs(tlvs, true, length, pnt);
pnt += length;
break;
case ES_NEIGHBOURS:
@ -950,26 +1000,44 @@ tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
}
int
tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
static size_t
max_tlv_size(struct stream *stream)
{
size_t avail = stream_get_size (stream) - stream_get_endp(stream);
if (avail < 2)
return 0;
if (avail < 257)
return avail - 2;
return 255;
}
unsigned int
tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream, void *arg)
{
struct listnode *node;
struct te_is_neigh *te_is_neigh;
u_char value[255];
u_char *pos = value;
int retval;
uint16_t mtid = arg ? *(uint16_t*)arg : ISIS_MT_IPV4_UNICAST;
unsigned int consumed = 0;
size_t max_size = max_tlv_size(stream);
if (mtid != ISIS_MT_IPV4_UNICAST)
{
uint16_t mtid_conversion = ntohs(mtid);
memcpy(pos, &mtid_conversion, sizeof(mtid_conversion));
pos += sizeof(mtid_conversion);
}
for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
{
/* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255)
{
retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
if (retval != ISIS_OK)
return retval;
pos = value;
}
if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > max_size)
break;
memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
pos += ISIS_SYS_ID_LEN + 1;
memcpy (pos, te_is_neigh->te_metric, 3);
@ -983,9 +1051,17 @@ tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length);
pos += te_is_neigh->sub_tlvs_length;
}
consumed++;
}
return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
if (consumed)
{
int rv = add_tlv ((mtid != ISIS_MT_IPV4_UNICAST) ? MT_IS_NEIGHBOURS
: TE_IS_NEIGHBOURS,
pos - value, value, stream);
assert(rv == ISIS_OK);
}
return consumed;
}
int

View File

@ -111,6 +111,7 @@
#define TE_IPV4_REACHABILITY 135
#define DYNAMIC_HOSTNAME 137
#define GRACEFUL_RESTART 211
#define MT_IS_NEIGHBOURS 222
#define MT_ROUTER_INFORMATION 229
#define IPV6_ADDR 232
#define IPV6_REACHABILITY 236
@ -272,6 +273,7 @@ struct tlvs
struct list *mt_router_info;
struct list *is_neighs;
struct list *te_is_neighs;
struct list *mt_is_neighs;
struct list *es_neighs;
struct list *lsp_entries;
struct list *prefix_neighs;
@ -324,7 +326,7 @@ void free_tlv (void *val);
int tlv_add_mt_router_info (struct list *mt_router_info, struct stream *stream);
int tlv_add_area_addrs (struct list *area_addrs, struct stream *stream);
int tlv_add_is_neighs (struct list *is_neighs, struct stream *stream);
int tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream);
unsigned int tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream, void *arg);
int tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream);
int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream);
int tlv_add_checksum (struct checksum *checksum, struct stream *stream);