mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 19:39:28 +00:00
isisd: track intersecting set of supported MTs for each adj
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
parent
99894f9a17
commit
d8fba7d974
@ -148,6 +148,8 @@ isis_delete_adj (void *arg)
|
|||||||
if (adj->ipv6_addrs)
|
if (adj->ipv6_addrs)
|
||||||
list_delete (adj->ipv6_addrs);
|
list_delete (adj->ipv6_addrs);
|
||||||
|
|
||||||
|
adj_mt_finish(adj);
|
||||||
|
|
||||||
XFREE (MTYPE_ISIS_ADJACENCY, adj);
|
XFREE (MTYPE_ISIS_ADJACENCY, adj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -521,3 +523,20 @@ isis_adj_build_up_list (struct list *adjdb, struct list *list)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isis_adj_usage2levels(enum isis_adj_usage usage)
|
||||||
|
{
|
||||||
|
switch (usage)
|
||||||
|
{
|
||||||
|
case ISIS_ADJ_LEVEL1:
|
||||||
|
return IS_LEVEL_1;
|
||||||
|
case ISIS_ADJ_LEVEL2:
|
||||||
|
return IS_LEVEL_2;
|
||||||
|
case ISIS_ADJ_LEVEL1AND2:
|
||||||
|
return IS_LEVEL_1 | IS_LEVEL_2;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -97,6 +97,8 @@ struct isis_adjacency
|
|||||||
int flaps; /* number of adjacency flaps */
|
int flaps; /* number of adjacency flaps */
|
||||||
struct thread *t_expire; /* expire after hold_time */
|
struct thread *t_expire; /* expire after hold_time */
|
||||||
struct isis_circuit *circuit; /* back pointer */
|
struct isis_circuit *circuit; /* back pointer */
|
||||||
|
uint16_t *mt_set; /* Topologies this adjacency is valid for */
|
||||||
|
unsigned int mt_count; /* Number of entries in mt_set */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct isis_adjacency *isis_adj_lookup (const u_char * sysid, struct list *adjdb);
|
struct isis_adjacency *isis_adj_lookup (const u_char * sysid, struct list *adjdb);
|
||||||
@ -112,5 +114,6 @@ int isis_adj_expire (struct thread *thread);
|
|||||||
void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail);
|
void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail);
|
||||||
void isis_adj_build_neigh_list (struct list *adjdb, struct list *list);
|
void isis_adj_build_neigh_list (struct list *adjdb, struct list *list);
|
||||||
void isis_adj_build_up_list (struct list *adjdb, struct list *list);
|
void isis_adj_build_up_list (struct list *adjdb, struct list *list);
|
||||||
|
int isis_adj_usage2levels(enum isis_adj_usage usage);
|
||||||
|
|
||||||
#endif /* ISIS_ADJACENCY_H */
|
#endif /* ISIS_ADJACENCY_H */
|
||||||
|
@ -24,14 +24,19 @@
|
|||||||
#include "isisd/isisd.h"
|
#include "isisd/isisd.h"
|
||||||
#include "isisd/isis_memory.h"
|
#include "isisd/isis_memory.h"
|
||||||
#include "isisd/isis_circuit.h"
|
#include "isisd/isis_circuit.h"
|
||||||
|
#include "isisd/isis_adjacency.h"
|
||||||
|
#include "isisd/isis_tlv.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")
|
||||||
|
|
||||||
/* MT naming api */
|
/* MT naming api */
|
||||||
const char *isis_mtid2str(uint16_t mtid)
|
const char *isis_mtid2str(uint16_t mtid)
|
||||||
{
|
{
|
||||||
|
static char buf[sizeof("65535")];
|
||||||
|
|
||||||
switch(mtid)
|
switch(mtid)
|
||||||
{
|
{
|
||||||
case ISIS_MT_IPV4_UNICAST:
|
case ISIS_MT_IPV4_UNICAST:
|
||||||
@ -47,7 +52,8 @@ const char *isis_mtid2str(uint16_t mtid)
|
|||||||
case ISIS_MT_IPV6_MGMT:
|
case ISIS_MT_IPV6_MGMT:
|
||||||
return "ipv6-mgmt";
|
return "ipv6-mgmt";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
snprintf(buf, sizeof(buf), "%" PRIu16, mtid);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,3 +361,79 @@ circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count)
|
|||||||
*mt_count = count;
|
*mt_count = count;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
|
||||||
|
uint16_t mtid)
|
||||||
|
{
|
||||||
|
if (adj->mt_count < index + 1)
|
||||||
|
{
|
||||||
|
adj->mt_set = XREALLOC(MTYPE_MT_ADJ_INFO, adj->mt_set,
|
||||||
|
(index + 1) * sizeof(*adj->mt_set));
|
||||||
|
adj->mt_count = index + 1;
|
||||||
|
}
|
||||||
|
adj->mt_set[index] = mtid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
|
||||||
|
struct isis_adjacency *adj)
|
||||||
|
{
|
||||||
|
struct isis_circuit_mt_setting **mt_settings;
|
||||||
|
unsigned int circuit_mt_count;
|
||||||
|
|
||||||
|
unsigned int intersect_count = 0;
|
||||||
|
|
||||||
|
uint16_t *old_mt_set;
|
||||||
|
unsigned int old_mt_count;
|
||||||
|
|
||||||
|
old_mt_count = adj->mt_count;
|
||||||
|
if (old_mt_count)
|
||||||
|
{
|
||||||
|
old_mt_set = XCALLOC(MTYPE_TMP, old_mt_count * sizeof(*old_mt_set));
|
||||||
|
memcpy(old_mt_set, adj->mt_set, old_mt_count * sizeof(*old_mt_set));
|
||||||
|
}
|
||||||
|
|
||||||
|
mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count);
|
||||||
|
for (unsigned int i = 0; i < circuit_mt_count; i++)
|
||||||
|
{
|
||||||
|
if (!tlvs->mt_router_info)
|
||||||
|
{
|
||||||
|
/* Other end does not have MT enabled */
|
||||||
|
if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST)
|
||||||
|
adj_mt_set(adj, intersect_count++, ISIS_MT_IPV4_UNICAST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct listnode *node;
|
||||||
|
struct mt_router_info *info;
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node, info))
|
||||||
|
{
|
||||||
|
if (mt_settings[i]->mtid == info->mtid)
|
||||||
|
adj_mt_set(adj, intersect_count++, info->mtid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adj->mt_count = intersect_count;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (adj->mt_count != old_mt_count)
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (!changed && old_mt_count
|
||||||
|
&& memcmp(adj->mt_set, old_mt_set,
|
||||||
|
old_mt_count * sizeof(*old_mt_set)))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (old_mt_count)
|
||||||
|
XFREE(MTYPE_TMP, old_mt_set);
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adj_mt_finish(struct isis_adjacency *adj)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set);
|
||||||
|
adj->mt_count = 0;
|
||||||
|
}
|
||||||
|
@ -67,8 +67,10 @@ struct isis_circuit_mt_setting {
|
|||||||
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);
|
||||||
|
|
||||||
|
struct isis_adjacency;
|
||||||
struct isis_area;
|
struct isis_area;
|
||||||
struct isis_circuit;
|
struct isis_circuit;
|
||||||
|
struct tlvs;
|
||||||
|
|
||||||
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);
|
||||||
@ -102,4 +104,7 @@ struct isis_circuit_mt_setting* circuit_get_mt_setting(
|
|||||||
int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty);
|
int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty);
|
||||||
struct isis_circuit_mt_setting** circuit_mt_settings(struct isis_circuit *circuit,
|
struct isis_circuit_mt_setting** circuit_mt_settings(struct isis_circuit *circuit,
|
||||||
unsigned int *mt_count);
|
unsigned int *mt_count);
|
||||||
|
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);
|
||||||
#endif
|
#endif
|
||||||
|
@ -635,6 +635,8 @@ process_p2p_hello (struct isis_circuit *circuit)
|
|||||||
if (found & TLVFLAG_IPV6_ADDR)
|
if (found & TLVFLAG_IPV6_ADDR)
|
||||||
tlvs_to_adj_ipv6_addrs (&tlvs, adj);
|
tlvs_to_adj_ipv6_addrs (&tlvs, adj);
|
||||||
|
|
||||||
|
bool mt_set_changed = tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj);
|
||||||
|
|
||||||
/* lets take care of the expiry */
|
/* lets take care of the expiry */
|
||||||
THREAD_TIMER_OFF (adj->t_expire);
|
THREAD_TIMER_OFF (adj->t_expire);
|
||||||
THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
|
THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
|
||||||
@ -871,6 +873,13 @@ process_p2p_hello (struct isis_circuit *circuit)
|
|||||||
/* down - area mismatch */
|
/* down - area mismatch */
|
||||||
isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
|
isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed)
|
||||||
|
{
|
||||||
|
lsp_regenerate_schedule(adj->circuit->area,
|
||||||
|
isis_adj_usage2levels(adj->adj_usage), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* 8.2.5.2 c) if the action was up - comparing circuit IDs */
|
/* 8.2.5.2 c) if the action was up - comparing circuit IDs */
|
||||||
/* FIXME - Missing parts */
|
/* FIXME - Missing parts */
|
||||||
|
|
||||||
@ -1226,6 +1235,8 @@ process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa)
|
|||||||
|
|
||||||
adj->circuit_t = hdr.circuit_t;
|
adj->circuit_t = hdr.circuit_t;
|
||||||
|
|
||||||
|
bool mt_set_changed = tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj);
|
||||||
|
|
||||||
/* lets take care of the expiry */
|
/* lets take care of the expiry */
|
||||||
THREAD_TIMER_OFF (adj->t_expire);
|
THREAD_TIMER_OFF (adj->t_expire);
|
||||||
THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
|
THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
|
||||||
@ -1269,6 +1280,9 @@ process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa)
|
|||||||
"no LAN Neighbours TLV found");
|
"no LAN Neighbours TLV found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed)
|
||||||
|
lsp_regenerate_schedule(adj->circuit->area, level, 0);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (isis->debugs & DEBUG_ADJ_PACKETS)
|
if (isis->debugs & DEBUG_ADJ_PACKETS)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user