mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 00:41:20 +00:00
isisd: announce and parse MT IS reachabilities
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
parent
d8fba7d974
commit
206f4aae58
@ -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;
|
||||
|
||||
|
119
isisd/isis_lsp.c
119
isisd/isis_lsp.c
@ -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);
|
||||
|
157
isisd/isis_mt.c
157
isisd/isis_mt.c
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
184
isisd/isis_tlv.c
184
isisd/isis_tlv.c
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user