mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 21:33:55 +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_lsp.h"
|
||||||
#include "isisd/isis_spf.h"
|
#include "isisd/isis_spf.h"
|
||||||
#include "isisd/isis_events.h"
|
#include "isisd/isis_events.h"
|
||||||
|
#include "isisd/isis_mt.h"
|
||||||
|
|
||||||
extern struct isis *isis;
|
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);
|
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
|
void
|
||||||
lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
|
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;
|
int i;
|
||||||
struct listnode *lnode;
|
struct listnode *lnode;
|
||||||
struct is_neigh *is_neigh;
|
struct is_neigh *is_neigh;
|
||||||
struct te_is_neigh *te_is_neigh;
|
|
||||||
struct ipv4_reachability *ipv4_reach;
|
struct ipv4_reachability *ipv4_reach;
|
||||||
struct in_addr *ipv4_addr;
|
struct in_addr *ipv4_addr;
|
||||||
struct te_ipv4_reachability *te_ipv4_reach;
|
struct te_ipv4_reachability *te_ipv4_reach;
|
||||||
struct ipv6_reachability *ipv6_reach;
|
struct ipv6_reachability *ipv6_reach;
|
||||||
struct mt_router_info *mt_router_info;
|
struct mt_router_info *mt_router_info;
|
||||||
|
struct tlv_mt_neighbors *mt_is_neigh;
|
||||||
struct in6_addr in6;
|
struct in6_addr in6;
|
||||||
u_char buff[BUFSIZ];
|
u_char buff[BUFSIZ];
|
||||||
u_char LSPid[255];
|
u_char LSPid[255];
|
||||||
@ -978,15 +1006,12 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TE IS neighbor tlv */
|
/* TE IS neighbor tlv */
|
||||||
if (lsp->tlv_data.te_is_neighs)
|
lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty,
|
||||||
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, lnode, te_is_neigh))
|
dynhost, ISIS_MT_IPV4_UNICAST);
|
||||||
{
|
|
||||||
lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
|
/* MT IS neighbor tlv */
|
||||||
vty_out (vty, " Metric : %-8d IS-Extended : %s%s",
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.mt_is_neighs, lnode, mt_is_neigh))
|
||||||
GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE);
|
lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost, mt_is_neigh->mtid);
|
||||||
if (IS_MPLS_TE(isisMplsTE))
|
|
||||||
mpls_te_print_detail(vty, te_is_neigh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TE IPv4 tlv */
|
/* TE IPv4 tlv */
|
||||||
if (lsp->tlv_data.te_ipv4_reachs)
|
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;
|
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) \
|
#define FRAG_THOLD(S,T) \
|
||||||
((STREAM_SIZE(S)*T)/100)
|
((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 */
|
/* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
|
||||||
te_is_neigh->sub_tlvs_length = 0;
|
te_is_neigh->sub_tlvs_length = 0;
|
||||||
|
|
||||||
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
|
tlvs_add_mt_bcast(&tlv_data, circuit, level, te_is_neigh);
|
||||||
lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor",
|
XFREE(MTYPE_ISIS_TLV, te_is_neigh);
|
||||||
area->area_tag, sysid_print(te_is_neigh->neigh_id),
|
|
||||||
LSP_PSEUDO_ID(te_is_neigh->neigh_id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1697,9 +1756,9 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
|
|||||||
else
|
else
|
||||||
/* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
|
/* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
|
||||||
te_is_neigh->sub_tlvs_length = 0;
|
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,
|
tlvs_add_mt_p2p(&tlv_data, circuit, te_is_neigh);
|
||||||
sysid_print(te_is_neigh->neigh_id));
|
XFREE(MTYPE_ISIS_TLV, te_is_neigh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1791,13 +1850,31 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
|
|||||||
{
|
{
|
||||||
if (lsp->tlv_data.te_is_neighs == NULL)
|
if (lsp->tlv_data.te_is_neighs == NULL)
|
||||||
lsp->tlv_data.te_is_neighs = list_new ();
|
lsp->tlv_data.te_is_neighs = list_new ();
|
||||||
lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
|
_lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
|
||||||
IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
|
area->lsp_frag_threshold, tlv_add_te_is_neighs, NULL);
|
||||||
tlv_add_te_is_neighs);
|
|
||||||
if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
|
if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
|
||||||
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
|
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
|
||||||
lsp0, area, level);
|
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));
|
lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
|
||||||
|
|
||||||
free_tlvs (&tlv_data);
|
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);
|
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)
|
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)
|
if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
|
||||||
tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
|
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_circuit.h"
|
||||||
#include "isisd/isis_adjacency.h"
|
#include "isisd/isis_adjacency.h"
|
||||||
#include "isisd/isis_tlv.h"
|
#include "isisd/isis_tlv.h"
|
||||||
|
#include "isisd/isis_misc.h"
|
||||||
|
#include "isisd/isis_lsp.h"
|
||||||
#include "isisd/isis_mt.h"
|
#include "isisd/isis_mt.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting")
|
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_CIRCUIT_SETTING, "ISIS MT Circuit Setting")
|
||||||
DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info")
|
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 */
|
/* MT naming api */
|
||||||
const char *isis_mtid2str(uint16_t mtid)
|
const char *isis_mtid2str(uint16_t mtid)
|
||||||
@ -362,6 +365,7 @@ circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ADJ specific MT API */
|
||||||
static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
|
static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
|
||||||
uint16_t mtid)
|
uint16_t mtid)
|
||||||
{
|
{
|
||||||
@ -437,3 +441,156 @@ adj_mt_finish(struct isis_adjacency *adj)
|
|||||||
XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set);
|
XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set);
|
||||||
adj->mt_count = 0;
|
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 \
|
#define ISIS_MT_INFO_FIELDS \
|
||||||
uint16_t mtid;
|
uint16_t mtid;
|
||||||
|
|
||||||
|
struct list;
|
||||||
|
|
||||||
struct isis_area_mt_setting {
|
struct isis_area_mt_setting {
|
||||||
ISIS_MT_INFO_FIELDS
|
ISIS_MT_INFO_FIELDS
|
||||||
bool enabled;
|
bool enabled;
|
||||||
@ -64,6 +66,11 @@ struct isis_circuit_mt_setting {
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tlv_mt_neighbors {
|
||||||
|
ISIS_MT_INFO_FIELDS
|
||||||
|
struct list *list;
|
||||||
|
};
|
||||||
|
|
||||||
const char *isis_mtid2str(uint16_t mtid);
|
const char *isis_mtid2str(uint16_t mtid);
|
||||||
uint16_t isis_str2mtid(const char *name);
|
uint16_t isis_str2mtid(const char *name);
|
||||||
|
|
||||||
@ -71,6 +78,10 @@ struct isis_adjacency;
|
|||||||
struct isis_area;
|
struct isis_area;
|
||||||
struct isis_circuit;
|
struct isis_circuit;
|
||||||
struct tlvs;
|
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,
|
struct isis_area_mt_setting* area_lookup_mt_setting(struct isis_area *area,
|
||||||
uint16_t mtid);
|
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,
|
bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
|
||||||
struct isis_adjacency *adj);
|
struct isis_adjacency *adj);
|
||||||
void adj_mt_finish(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
|
#endif
|
||||||
|
184
isisd/isis_tlv.c
184
isisd/isis_tlv.c
@ -43,6 +43,7 @@
|
|||||||
#include "isisd/isis_pdu.h"
|
#include "isisd/isis_pdu.h"
|
||||||
#include "isisd/isis_lsp.h"
|
#include "isisd/isis_lsp.h"
|
||||||
#include "isisd/isis_te.h"
|
#include "isisd/isis_te.h"
|
||||||
|
#include "isisd/isis_mt.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
free_tlv (void *val)
|
free_tlv (void *val)
|
||||||
@ -67,6 +68,8 @@ free_tlvs (struct tlvs *tlvs)
|
|||||||
list_delete (tlvs->is_neighs);
|
list_delete (tlvs->is_neighs);
|
||||||
if (tlvs->te_is_neighs)
|
if (tlvs->te_is_neighs)
|
||||||
list_delete (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)
|
if (tlvs->es_neighs)
|
||||||
list_delete (tlvs->es_neighs);
|
list_delete (tlvs->es_neighs);
|
||||||
if (tlvs->lsp_entries)
|
if (tlvs->lsp_entries)
|
||||||
@ -93,6 +96,83 @@ free_tlvs (struct tlvs *tlvs)
|
|||||||
return;
|
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.
|
* 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.
|
* 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 lan_neigh *lan_nei;
|
||||||
struct area_addr *area_addr;
|
struct area_addr *area_addr;
|
||||||
struct is_neigh *is_nei;
|
struct is_neigh *is_nei;
|
||||||
struct te_is_neigh *te_is_nei;
|
|
||||||
struct es_neigh *es_nei;
|
struct es_neigh *es_nei;
|
||||||
struct lsp_entry *lsp_entry;
|
struct lsp_entry *lsp_entry;
|
||||||
struct in_addr *ipv4_addr;
|
struct in_addr *ipv4_addr;
|
||||||
@ -209,54 +288,25 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TE_IS_NEIGHBOURS:
|
case TE_IS_NEIGHBOURS:
|
||||||
/* +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
||||||
* | Neighbour ID | 7
|
|
||||||
* +---------------------------------------------------------------+
|
|
||||||
* | TE Metric | 3
|
|
||||||
* +---------------------------------------------------------------+
|
|
||||||
* | SubTLVs Length | 1
|
|
||||||
* +---------------------------------------------------------------+
|
|
||||||
* : :
|
|
||||||
*/
|
|
||||||
*found |= TLVFLAG_TE_IS_NEIGHS;
|
*found |= TLVFLAG_TE_IS_NEIGHS;
|
||||||
#ifdef EXTREME_TLV_DEBUG
|
#ifdef EXTREME_TLV_DEBUG
|
||||||
zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
|
zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
|
||||||
areatag, length);
|
areatag, length);
|
||||||
#endif /* EXTREME_TLV_DEBUG */
|
#endif /* EXTREME_TLV_DEBUG */
|
||||||
if (TLVFLAG_TE_IS_NEIGHS & *expected)
|
if (TLVFLAG_TE_IS_NEIGHS & *expected)
|
||||||
{
|
retval = parse_mt_is_neighs(tlvs, false, length, pnt);
|
||||||
while (length > value_len)
|
pnt += length;
|
||||||
{
|
break;
|
||||||
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;
|
|
||||||
|
|
||||||
if (!tlvs->te_is_neighs)
|
case MT_IS_NEIGHBOURS:
|
||||||
tlvs->te_is_neighs = list_new ();
|
*found |= TLVFLAG_TE_IS_NEIGHS;
|
||||||
listnode_add (tlvs->te_is_neighs, te_is_nei);
|
#ifdef EXTREME_TLV_DEBUG
|
||||||
}
|
zlog_debug ("ISIS-TLV (%s): MT IS Neighbours length %d",
|
||||||
}
|
areatag, length);
|
||||||
else
|
#endif
|
||||||
{
|
if (TLVFLAG_TE_IS_NEIGHS & *expected)
|
||||||
pnt += length;
|
retval = parse_mt_is_neighs(tlvs, true, length, pnt);
|
||||||
}
|
pnt += length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ES_NEIGHBOURS:
|
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);
|
return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static size_t
|
||||||
tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
|
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 listnode *node;
|
||||||
struct te_is_neigh *te_is_neigh;
|
struct te_is_neigh *te_is_neigh;
|
||||||
u_char value[255];
|
u_char value[255];
|
||||||
u_char *pos = value;
|
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))
|
for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
|
||||||
{
|
{
|
||||||
/* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
|
/* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
|
||||||
if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255)
|
if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > max_size)
|
||||||
{
|
break;
|
||||||
retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
|
|
||||||
if (retval != ISIS_OK)
|
|
||||||
return retval;
|
|
||||||
pos = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
|
memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
|
||||||
pos += ISIS_SYS_ID_LEN + 1;
|
pos += ISIS_SYS_ID_LEN + 1;
|
||||||
memcpy (pos, te_is_neigh->te_metric, 3);
|
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);
|
memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length);
|
||||||
pos += 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
|
int
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
#define TE_IPV4_REACHABILITY 135
|
#define TE_IPV4_REACHABILITY 135
|
||||||
#define DYNAMIC_HOSTNAME 137
|
#define DYNAMIC_HOSTNAME 137
|
||||||
#define GRACEFUL_RESTART 211
|
#define GRACEFUL_RESTART 211
|
||||||
|
#define MT_IS_NEIGHBOURS 222
|
||||||
#define MT_ROUTER_INFORMATION 229
|
#define MT_ROUTER_INFORMATION 229
|
||||||
#define IPV6_ADDR 232
|
#define IPV6_ADDR 232
|
||||||
#define IPV6_REACHABILITY 236
|
#define IPV6_REACHABILITY 236
|
||||||
@ -272,6 +273,7 @@ struct tlvs
|
|||||||
struct list *mt_router_info;
|
struct list *mt_router_info;
|
||||||
struct list *is_neighs;
|
struct list *is_neighs;
|
||||||
struct list *te_is_neighs;
|
struct list *te_is_neighs;
|
||||||
|
struct list *mt_is_neighs;
|
||||||
struct list *es_neighs;
|
struct list *es_neighs;
|
||||||
struct list *lsp_entries;
|
struct list *lsp_entries;
|
||||||
struct list *prefix_neighs;
|
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_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_area_addrs (struct list *area_addrs, struct stream *stream);
|
||||||
int tlv_add_is_neighs (struct list *is_neighs, 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_lan_neighs (struct list *lan_neighs, struct stream *stream);
|
||||||
int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream);
|
int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream);
|
||||||
int tlv_add_checksum (struct checksum *checksum, struct stream *stream);
|
int tlv_add_checksum (struct checksum *checksum, struct stream *stream);
|
||||||
|
Loading…
Reference in New Issue
Block a user