mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 23:53:28 +00:00
isisd: merge osr/google-is-is
this is essentially half of a rewrite of isisd. please note that a lot of things are still broken and isisd is not ready for production use.
This commit is contained in:
commit
d75318cc8d
@ -1,3 +1,4 @@
|
||||
Sampo Saaristo <sambo@cs.tut.fi>
|
||||
Ofer Wald <ofersf@islands.co.il>
|
||||
Hannes Gredler <hannes@gredler.at>
|
||||
Sampo Saaristo <sambo@cs.tut.fi>
|
||||
Ofer Wald <ofersf@islands.co.il>
|
||||
Hannes Gredler <hannes@gredler.at>
|
||||
Subbaiah Venkata <svenkata@google.com>
|
||||
|
29
isisd/dict.c
29
isisd/dict.c
@ -15,17 +15,11 @@
|
||||
* contain a copyright notice related to this source.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include "zebra.h"
|
||||
#include "zassert.h"
|
||||
#define DICT_IMPLEMENTATION
|
||||
#include "memory.h"
|
||||
#include "dict.h"
|
||||
|
||||
#ifdef KAZLIB_RCSID
|
||||
static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros provide short convenient names for structure members,
|
||||
* which are embellished with dict_ prefixes so that they are
|
||||
@ -243,7 +237,7 @@ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
|
||||
|
||||
dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
|
||||
{
|
||||
dict_t *new = malloc(sizeof *new);
|
||||
dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t));
|
||||
|
||||
if (new) {
|
||||
new->compare = comp;
|
||||
@ -284,7 +278,7 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
|
||||
void dict_destroy(dict_t *dict)
|
||||
{
|
||||
assert (dict_isempty(dict));
|
||||
free(dict);
|
||||
XFREE(MTYPE_ISIS_DICT, dict);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -307,9 +301,6 @@ void dict_free_nodes(dict_t *dict)
|
||||
|
||||
void dict_free(dict_t *dict)
|
||||
{
|
||||
#ifdef KAZLIB_OBSOLESCENT_DEBUG
|
||||
assert ("call to obsolescent function dict_free()" && 0);
|
||||
#endif
|
||||
dict_free_nodes(dict);
|
||||
}
|
||||
|
||||
@ -810,7 +801,7 @@ dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
|
||||
|
||||
int dict_alloc_insert(dict_t *dict, const void *key, void *data)
|
||||
{
|
||||
dnode_t *node = dict->allocnode(dict->context);
|
||||
dnode_t *node = dict->allocnode (dict->context);
|
||||
|
||||
if (node) {
|
||||
dnode_init(node, data);
|
||||
@ -946,17 +937,17 @@ int dict_contains(dict_t *dict, dnode_t *node)
|
||||
|
||||
static dnode_t *dnode_alloc(void *context)
|
||||
{
|
||||
return malloc(sizeof *dnode_alloc(NULL));
|
||||
return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
|
||||
}
|
||||
|
||||
static void dnode_free(dnode_t *node, void *context)
|
||||
{
|
||||
free(node);
|
||||
XFREE(MTYPE_ISIS_DICT_NODE, node);
|
||||
}
|
||||
|
||||
dnode_t *dnode_create(void *data)
|
||||
{
|
||||
dnode_t *new = malloc(sizeof *new);
|
||||
dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
|
||||
if (new) {
|
||||
new->data = data;
|
||||
new->parent = NULL;
|
||||
@ -978,7 +969,7 @@ dnode_t *dnode_init(dnode_t *dnode, void *data)
|
||||
void dnode_destroy(dnode_t *dnode)
|
||||
{
|
||||
assert (!dnode_is_in_a_dict(dnode));
|
||||
free(dnode);
|
||||
XFREE(MTYPE_ISIS_DICT_NODE, dnode);
|
||||
}
|
||||
|
||||
void *dnode_get(dnode_t *dnode)
|
||||
@ -1232,7 +1223,7 @@ static int comparef(const void *key1, const void *key2)
|
||||
static char *dupstring(char *str)
|
||||
{
|
||||
int sz = strlen(str) + 1;
|
||||
char *new = malloc(sz);
|
||||
char *new = XCALLOC(MTYPE_ISIS_TMP, sz);
|
||||
if (new)
|
||||
memcpy(new, str, sz);
|
||||
return new;
|
||||
@ -1347,7 +1338,7 @@ int main(void)
|
||||
"s switch to non-functioning allocator\n"
|
||||
"q quit";
|
||||
|
||||
for (i = 0; i < sizeof darray / sizeof *darray; i++)
|
||||
for (i = 0; i < 10; i++)
|
||||
dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
|
||||
|
||||
for (;;) {
|
||||
|
21
isisd/dict.h
21
isisd/dict.h
@ -22,9 +22,6 @@
|
||||
#define DICT_H
|
||||
|
||||
#include <limits.h>
|
||||
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
||||
#include "sfx.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Blurb for inclusion into C++ translation units
|
||||
@ -44,16 +41,12 @@ typedef unsigned long dictcount_t;
|
||||
typedef enum { dnode_red, dnode_black } dnode_color_t;
|
||||
|
||||
typedef struct dnode_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
struct dnode_t *dict_left;
|
||||
struct dnode_t *dict_right;
|
||||
struct dnode_t *dict_parent;
|
||||
dnode_color_t dict_color;
|
||||
const void *dict_key;
|
||||
void *dict_data;
|
||||
#else
|
||||
int dict_dummy;
|
||||
#endif
|
||||
} dnode_t;
|
||||
|
||||
typedef int (*dict_comp_t)(const void *, const void *);
|
||||
@ -61,7 +54,6 @@ typedef dnode_t *(*dnode_alloc_t)(void *);
|
||||
typedef void (*dnode_free_t)(dnode_t *, void *);
|
||||
|
||||
typedef struct dict_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
dnode_t dict_nilnode;
|
||||
dictcount_t dict_nodecount;
|
||||
dictcount_t dict_maxcount;
|
||||
@ -70,20 +62,13 @@ typedef struct dict_t {
|
||||
dnode_free_t dict_freenode;
|
||||
void *dict_context;
|
||||
int dict_dupes;
|
||||
#else
|
||||
int dict_dummmy;
|
||||
#endif
|
||||
} dict_t;
|
||||
|
||||
typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
|
||||
|
||||
typedef struct dict_load_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
dict_t *dict_dictptr;
|
||||
dnode_t dict_nilnode;
|
||||
#else
|
||||
int dict_dummmy;
|
||||
#endif
|
||||
} dict_load_t;
|
||||
|
||||
extern dict_t *dict_create(dictcount_t, dict_comp_t);
|
||||
@ -124,18 +109,12 @@ extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
|
||||
extern void dict_load_end(dict_load_t *);
|
||||
extern void dict_merge(dict_t *, dict_t *);
|
||||
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
||||
#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
|
||||
#else
|
||||
#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
|
||||
#endif
|
||||
#define dict_count(D) ((D)->dict_nodecount)
|
||||
#define dict_isempty(D) ((D)->dict_nodecount == 0)
|
||||
#define dnode_get(N) ((N)->dict_data)
|
||||
#define dnode_getkey(N) ((N)->dict_key)
|
||||
#define dnode_put(N, X) ((N)->dict_data = (X))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "isisd/include-netbsd/iso.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
@ -43,6 +44,10 @@
|
||||
#include "isisd/isis_dr.h"
|
||||
#include "isisd/isis_dynhn.h"
|
||||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_tlv.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_spf.h"
|
||||
#include "isisd/isis_events.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
|
||||
@ -73,9 +78,9 @@ isis_new_adj (u_char * id, u_char * snpa, int level,
|
||||
}
|
||||
|
||||
if (snpa) {
|
||||
memcpy (adj->snpa, snpa, 6);
|
||||
memcpy (adj->snpa, snpa, ETH_ALEN);
|
||||
} else {
|
||||
memset (adj->snpa, ' ', 6);
|
||||
memset (adj->snpa, ' ', ETH_ALEN);
|
||||
}
|
||||
|
||||
adj->circuit = circuit;
|
||||
@ -125,37 +130,60 @@ isis_adj_lookup_snpa (u_char * ssnpa, struct list *adjdb)
|
||||
}
|
||||
|
||||
void
|
||||
isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb)
|
||||
isis_delete_adj (void *arg)
|
||||
{
|
||||
struct isis_adjacency *adj = arg;
|
||||
|
||||
if (!adj)
|
||||
return;
|
||||
/* When we recieve a NULL list, we will know its p2p. */
|
||||
if (adjdb)
|
||||
listnode_delete (adjdb, adj);
|
||||
|
||||
THREAD_OFF (adj->t_expire);
|
||||
THREAD_TIMER_OFF (adj->t_expire);
|
||||
|
||||
/* remove from SPF trees */
|
||||
spftree_area_adj_del (adj->circuit->area, adj);
|
||||
|
||||
if (adj->area_addrs)
|
||||
list_delete (adj->area_addrs);
|
||||
if (adj->ipv4_addrs)
|
||||
list_delete (adj->ipv4_addrs);
|
||||
#ifdef HAVE_IPV6
|
||||
if (adj->ipv6_addrs)
|
||||
list_delete (adj->ipv6_addrs);
|
||||
#endif
|
||||
|
||||
|
||||
XFREE (MTYPE_ISIS_ADJACENCY, adj);
|
||||
return;
|
||||
}
|
||||
|
||||
static const char *
|
||||
adj_state2string (int state)
|
||||
{
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ISIS_ADJ_INITIALIZING:
|
||||
return "Initializing";
|
||||
case ISIS_ADJ_UP:
|
||||
return "Up";
|
||||
case ISIS_ADJ_DOWN:
|
||||
return "Down";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return NULL; /* not reached */
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
|
||||
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state,
|
||||
const char *reason)
|
||||
{
|
||||
int old_state;
|
||||
int level = adj->level;
|
||||
int level;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
old_state = adj->adj_state;
|
||||
adj->adj_state = state;
|
||||
adj->adj_state = new_state;
|
||||
|
||||
circuit = adj->circuit;
|
||||
|
||||
@ -163,42 +191,107 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
|
||||
{
|
||||
zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
|
||||
circuit->area->area_tag,
|
||||
old_state, state, reason ? reason : "unspecified");
|
||||
old_state, new_state, reason ? reason : "unspecified");
|
||||
}
|
||||
|
||||
if (circuit->area->log_adj_changes)
|
||||
{
|
||||
const char *adj_name;
|
||||
struct isis_dynhn *dyn;
|
||||
|
||||
dyn = dynhn_find_by_id (adj->sysid);
|
||||
if (dyn)
|
||||
adj_name = (const char *)dyn->name.name;
|
||||
else
|
||||
adj_name = adj->sysid ? sysid_print (adj->sysid) : "unknown";
|
||||
|
||||
zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s",
|
||||
adj_name,
|
||||
adj->circuit ? adj->circuit->interface->name : "no circuit",
|
||||
adj_state2string (old_state),
|
||||
adj_state2string (new_state),
|
||||
reason ? reason : "unspecified");
|
||||
}
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
{
|
||||
if (state == ISIS_ADJ_UP)
|
||||
circuit->upadjcount[level - 1]++;
|
||||
if (state == ISIS_ADJ_DOWN)
|
||||
{
|
||||
listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj);
|
||||
circuit->upadjcount[level - 1]--;
|
||||
}
|
||||
for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
|
||||
{
|
||||
if ((adj->level & level) == 0)
|
||||
continue;
|
||||
if (new_state == ISIS_ADJ_UP)
|
||||
{
|
||||
circuit->upadjcount[level - 1]++;
|
||||
isis_event_adjacency_state_change (adj, new_state);
|
||||
/* update counter & timers for debugging purposes */
|
||||
adj->last_flap = time (NULL);
|
||||
adj->flaps++;
|
||||
}
|
||||
else if (new_state == ISIS_ADJ_DOWN)
|
||||
{
|
||||
listnode_delete (circuit->u.bc.adjdb[level - 1], adj);
|
||||
circuit->upadjcount[level - 1]--;
|
||||
if (circuit->upadjcount[level - 1] == 0)
|
||||
{
|
||||
/* Clean lsp_queue when no adj is up. */
|
||||
if (circuit->lsp_queue)
|
||||
list_delete_all_node (circuit->lsp_queue);
|
||||
}
|
||||
isis_event_adjacency_state_change (adj, new_state);
|
||||
isis_delete_adj (adj);
|
||||
}
|
||||
|
||||
list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
|
||||
isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
|
||||
circuit->u.bc.lan_neighs[level - 1]);
|
||||
}
|
||||
else if (state == ISIS_ADJ_UP)
|
||||
{ /* p2p interface */
|
||||
if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
|
||||
send_hello (circuit, 1);
|
||||
if (circuit->u.bc.lan_neighs[level - 1])
|
||||
{
|
||||
list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
|
||||
isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
|
||||
circuit->u.bc.lan_neighs[level - 1]);
|
||||
}
|
||||
|
||||
/* update counter & timers for debugging purposes */
|
||||
adj->last_flap = time (NULL);
|
||||
adj->flaps++;
|
||||
/* On adjacency state change send new pseudo LSP if we are the DR */
|
||||
if (circuit->u.bc.is_dr[level - 1])
|
||||
lsp_regenerate_schedule_pseudo (circuit, level);
|
||||
}
|
||||
}
|
||||
else if (circuit->circ_type == CIRCUIT_T_P2P)
|
||||
{
|
||||
for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
|
||||
{
|
||||
if ((adj->level & level) == 0)
|
||||
continue;
|
||||
if (new_state == ISIS_ADJ_UP)
|
||||
{
|
||||
circuit->upadjcount[level - 1]++;
|
||||
isis_event_adjacency_state_change (adj, new_state);
|
||||
|
||||
/* 7.3.17 - going up on P2P -> send CSNP */
|
||||
/* FIXME: yup, I know its wrong... but i will do it! (for now) */
|
||||
send_csnp (circuit, 1);
|
||||
send_csnp (circuit, 2);
|
||||
}
|
||||
else if (state == ISIS_ADJ_DOWN)
|
||||
{ /* p2p interface */
|
||||
adj->circuit->u.p2p.neighbor = NULL;
|
||||
isis_delete_adj (adj, NULL);
|
||||
if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
|
||||
send_hello (circuit, level);
|
||||
|
||||
/* update counter & timers for debugging purposes */
|
||||
adj->last_flap = time (NULL);
|
||||
adj->flaps++;
|
||||
|
||||
/* 7.3.17 - going up on P2P -> send CSNP */
|
||||
/* FIXME: yup, I know its wrong... but i will do it! (for now) */
|
||||
send_csnp (circuit, level);
|
||||
}
|
||||
else if (new_state == ISIS_ADJ_DOWN)
|
||||
{
|
||||
if (adj->circuit->u.p2p.neighbor == adj)
|
||||
adj->circuit->u.p2p.neighbor = NULL;
|
||||
circuit->upadjcount[level - 1]--;
|
||||
if (circuit->upadjcount[level - 1] == 0)
|
||||
{
|
||||
/* Clean lsp_queue when no adj is up. */
|
||||
if (circuit->lsp_queue)
|
||||
list_delete_all_node (circuit->lsp_queue);
|
||||
}
|
||||
isis_event_adjacency_state_change (adj, new_state);
|
||||
isis_delete_adj (adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -225,7 +318,7 @@ isis_adj_print (struct isis_adjacency *adj)
|
||||
snpa_print (adj->snpa), adj->level, adj->hold_time);
|
||||
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0)
|
||||
{
|
||||
zlog_debug ("IPv4 Addresses:");
|
||||
zlog_debug ("IPv4 Address(es):");
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr))
|
||||
zlog_debug ("%s", inet_ntoa (*ipv4_addr));
|
||||
@ -234,7 +327,7 @@ isis_adj_print (struct isis_adjacency *adj)
|
||||
#ifdef HAVE_IPV6
|
||||
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
|
||||
{
|
||||
zlog_debug ("IPv6 Addresses:");
|
||||
zlog_debug ("IPv6 Address(es):");
|
||||
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
|
||||
{
|
||||
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
|
||||
@ -251,14 +344,12 @@ int
|
||||
isis_adj_expire (struct thread *thread)
|
||||
{
|
||||
struct isis_adjacency *adj;
|
||||
int level;
|
||||
|
||||
/*
|
||||
* Get the adjacency
|
||||
*/
|
||||
adj = THREAD_ARG (thread);
|
||||
assert (adj);
|
||||
level = adj->level;
|
||||
adj->t_expire = NULL;
|
||||
|
||||
/* trigger the adj expire event */
|
||||
@ -267,32 +358,12 @@ isis_adj_expire (struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
adj_state2string (int state)
|
||||
{
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ISIS_ADJ_INITIALIZING:
|
||||
return "Initializing";
|
||||
case ISIS_ADJ_UP:
|
||||
return "Up";
|
||||
case ISIS_ADJ_DOWN:
|
||||
return "Down";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return NULL; /* not reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* show clns/isis neighbor (detail)
|
||||
* show isis neighbor [detail]
|
||||
*/
|
||||
static void
|
||||
isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
|
||||
void
|
||||
isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail)
|
||||
{
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
struct in6_addr *ipv6_addr;
|
||||
u_char ip6[INET6_ADDRSTRLEN];
|
||||
@ -335,10 +406,11 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
|
||||
if (detail == ISIS_UI_LEVEL_DETAIL)
|
||||
{
|
||||
level = adj->level;
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
if (adj->circuit)
|
||||
vty_out (vty, "%s Interface: %s", VTY_NEWLINE, adj->circuit->interface->name); /* interface name */
|
||||
vty_out (vty, " Interface: %s", adj->circuit->interface->name);
|
||||
else
|
||||
vty_out (vty, "NULL circuit!%s", VTY_NEWLINE);
|
||||
vty_out (vty, " Interface: NULL circuit");
|
||||
vty_out (vty, ", Level: %u", adj->level); /* level */
|
||||
vty_out (vty, ", State: %s", adj_state2string (adj->adj_state));
|
||||
now = time (NULL);
|
||||
@ -347,40 +419,54 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
|
||||
time2string (adj->last_upd + adj->hold_time - now));
|
||||
else
|
||||
vty_out (vty, ", Expires in %s", time2string (adj->hold_time));
|
||||
vty_out (vty, "%s Adjacency flaps: %u", VTY_NEWLINE, adj->flaps);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " Adjacency flaps: %u", adj->flaps);
|
||||
vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap));
|
||||
vty_out (vty, "%s Circuit type: %s",
|
||||
VTY_NEWLINE, circuit_t2string (adj->circuit_t));
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t));
|
||||
vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids));
|
||||
vty_out (vty, "%s SNPA: %s", VTY_NEWLINE, snpa_print (adj->snpa));
|
||||
dyn = dynhn_find_by_id (adj->lanid);
|
||||
if (dyn)
|
||||
vty_out (vty, ", LAN id: %s.%02x",
|
||||
dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]);
|
||||
else
|
||||
vty_out (vty, ", LAN id: %s.%02x",
|
||||
sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " SNPA: %s", snpa_print (adj->snpa));
|
||||
if (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
{
|
||||
dyn = dynhn_find_by_id (adj->lanid);
|
||||
if (dyn)
|
||||
vty_out (vty, ", LAN id: %s.%02x",
|
||||
dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]);
|
||||
else
|
||||
vty_out (vty, ", LAN id: %s.%02x",
|
||||
sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]);
|
||||
|
||||
vty_out (vty, "%s Priority: %u",
|
||||
VTY_NEWLINE, adj->prio[adj->level - 1]);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]);
|
||||
|
||||
vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s",
|
||||
isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1].
|
||||
dis), adj->dischanges[level - 1],
|
||||
time2string (now -
|
||||
(adj->dis_record[ISIS_LEVELS + level - 1].
|
||||
last_dis_change)), VTY_NEWLINE);
|
||||
vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago",
|
||||
isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1].
|
||||
dis), adj->dischanges[level - 1],
|
||||
time2string (now -
|
||||
(adj->dis_record[ISIS_LEVELS + level - 1].
|
||||
last_dis_change)));
|
||||
}
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
|
||||
if (adj->area_addrs && listcount (adj->area_addrs) > 0)
|
||||
{
|
||||
struct area_addr *area_addr;
|
||||
vty_out (vty, " Area Address(es):%s", VTY_NEWLINE);
|
||||
for (ALL_LIST_ELEMENTS_RO (adj->area_addrs, node, area_addr))
|
||||
vty_out (vty, " %s%s", isonet_print (area_addr->area_addr,
|
||||
area_addr->addr_len), VTY_NEWLINE);
|
||||
}
|
||||
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0)
|
||||
{
|
||||
vty_out (vty, " IPv4 Addresses:%s", VTY_NEWLINE);
|
||||
vty_out (vty, " IPv4 Address(es):%s", VTY_NEWLINE);
|
||||
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr))
|
||||
vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
|
||||
{
|
||||
vty_out (vty, " IPv6 Addresses:%s", VTY_NEWLINE);
|
||||
vty_out (vty, " IPv6 Address(es):%s", VTY_NEWLINE);
|
||||
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
|
||||
{
|
||||
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
|
||||
@ -393,53 +479,6 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
|
||||
{
|
||||
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adjdb_iterate (struct list *adjdb, void (*func) (struct isis_adjacency *,
|
||||
void *), void *arg)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct isis_adjacency *adj;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (adjdb, node, nnode, adj))
|
||||
(*func) (adj, arg);
|
||||
}
|
||||
|
||||
void
|
||||
isis_adj_build_neigh_list (struct list *adjdb, struct list *list)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ enum isis_system_type
|
||||
|
||||
enum isis_adj_state
|
||||
{
|
||||
ISIS_ADJ_UNKNOWN,
|
||||
ISIS_ADJ_INITIALIZING,
|
||||
ISIS_ADJ_UP,
|
||||
ISIS_ADJ_DOWN
|
||||
@ -83,8 +84,10 @@ struct isis_adjacency
|
||||
struct list *area_addrs; /* areaAdressesOfNeighbour */
|
||||
struct nlpids nlpids; /* protocols spoken ... */
|
||||
struct list *ipv4_addrs;
|
||||
struct in_addr router_address;
|
||||
#ifdef HAVE_IPV6
|
||||
struct list *ipv6_addrs;
|
||||
struct in6_addr router_address6;
|
||||
#endif /* HAVE_IPV6 */
|
||||
u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
|
||||
int circuit_t; /* from hello PDU hdr */
|
||||
@ -103,25 +106,13 @@ struct isis_adjacency *isis_adj_lookup_snpa (u_char * ssnpa,
|
||||
struct list *adjdb);
|
||||
struct isis_adjacency *isis_new_adj (u_char * id, u_char * snpa, int level,
|
||||
struct isis_circuit *circuit);
|
||||
void isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb);
|
||||
void isis_delete_adj (void *adj);
|
||||
void isis_adj_state_change (struct isis_adjacency *adj,
|
||||
enum isis_adj_state state, const char *reason);
|
||||
void isis_adj_print (struct isis_adjacency *adj);
|
||||
int isis_adj_expire (struct thread *thread);
|
||||
void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty);
|
||||
void isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty);
|
||||
void isis_adj_print_vty_extensive (struct isis_adjacency *adj,
|
||||
struct vty *vty);
|
||||
void isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty);
|
||||
void isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj,
|
||||
struct vty *vty);
|
||||
void isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj,
|
||||
struct vty *vty);
|
||||
|
||||
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_up_list (struct list *adjdb, struct list *list);
|
||||
void isis_adjdb_iterate (struct list *adjdb,
|
||||
void (*func) (struct isis_adjacency *,
|
||||
void *), void *arg);
|
||||
|
||||
#endif /* ISIS_ADJACENCY_H */
|
||||
|
@ -301,7 +301,16 @@ int
|
||||
isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
{
|
||||
struct ether_header *eth;
|
||||
int written;
|
||||
int written, buflen;
|
||||
|
||||
buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN;
|
||||
if (buflen > sizeof (sock_buff))
|
||||
{
|
||||
zlog_warn ("isis_send_pdu_bcast: sock_buff size %lu is less than "
|
||||
"output pdu size %d on circuit %s",
|
||||
sizeof (sock_buff), buflen, circuit->interface->name);
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
stream_set_getp (circuit->snd_stream, 0);
|
||||
|
||||
@ -328,9 +337,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
stream_get_endp (circuit->snd_stream));
|
||||
|
||||
/* now we can send this */
|
||||
written = write (circuit->fd, sock_buff,
|
||||
stream_get_endp (circuit->snd_stream)
|
||||
+ LLC_LEN + ETHER_HDR_LEN);
|
||||
written = write (circuit->fd, sock_buff, buflen);
|
||||
|
||||
return ISIS_OK;
|
||||
}
|
||||
|
2639
isisd/isis_circuit.c
2639
isisd/isis_circuit.c
File diff suppressed because it is too large
Load Diff
@ -52,8 +52,6 @@ struct isis_bcast_info
|
||||
u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */
|
||||
u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */
|
||||
struct thread *t_refresh_pseudo_lsp[2]; /* refresh pseudo-node LSPs */
|
||||
int pad_hellos; /* add padding to Hello PDUs ? */
|
||||
u_char priority[2]; /* l1/2 IS Priority */
|
||||
};
|
||||
|
||||
struct isis_p2p_info
|
||||
@ -65,7 +63,6 @@ struct isis_p2p_info
|
||||
struct isis_circuit
|
||||
{
|
||||
int state;
|
||||
int connected;
|
||||
u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */
|
||||
struct isis_area *area; /* back pointer to the area */
|
||||
struct interface *interface; /* interface info from z */
|
||||
@ -79,31 +76,36 @@ struct isis_circuit
|
||||
struct thread *t_send_csnp[2];
|
||||
struct thread *t_send_psnp[2];
|
||||
struct list *lsp_queue; /* LSPs to be txed (both levels) */
|
||||
time_t lsp_queue_last_cleared;/* timestamp used to enforce transmit interval;
|
||||
* for scalability, use one timestamp per
|
||||
* circuit, instead of one per lsp per circuit
|
||||
*/
|
||||
/* there is no real point in two streams, just for programming kicker */
|
||||
int (*rx) (struct isis_circuit * circuit, u_char * ssnpa);
|
||||
struct stream *rcv_stream; /* Stream for receiving */
|
||||
int (*tx) (struct isis_circuit * circuit, int level);
|
||||
struct stream *snd_stream; /* Stream for sending */
|
||||
int idx; /* idx in S[RM|SN] flags */
|
||||
#define CIRCUIT_T_BROADCAST 0
|
||||
#define CIRCUIT_T_P2P 1
|
||||
#define CIRCUIT_T_STATIC_IN 2
|
||||
#define CIRCUIT_T_STATIC_OUT 3
|
||||
#define CIRCUIT_T_DA 4
|
||||
#define CIRCUIT_T_UNKNOWN 0
|
||||
#define CIRCUIT_T_BROADCAST 1
|
||||
#define CIRCUIT_T_P2P 2
|
||||
#define CIRCUIT_T_LOOPBACK 3
|
||||
int circ_type; /* type of the physical interface */
|
||||
int circ_type_config; /* config type of the physical interface */
|
||||
union
|
||||
{
|
||||
struct isis_bcast_info bc;
|
||||
struct isis_p2p_info p2p;
|
||||
} u;
|
||||
u_char priority[2]; /* l1/2 IS configured priority */
|
||||
int pad_hellos; /* add padding to Hello PDUs ? */
|
||||
char ext_domain; /* externalDomain (boolean) */
|
||||
int lsp_regenerate_pending[ISIS_LEVELS];
|
||||
/*
|
||||
* Configurables
|
||||
*/
|
||||
struct isis_passwd passwd; /* Circuit rx/tx password */
|
||||
long lsp_interval;
|
||||
int manual_l2_only; /* manualL2OnlyMode (boolean) */
|
||||
int circuit_is_type; /* circuit is type == level of circuit
|
||||
int is_type; /* circuit is type == level of circuit
|
||||
* diffrenciated from circuit type (media) */
|
||||
u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */
|
||||
u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */
|
||||
@ -111,24 +113,17 @@ struct isis_circuit
|
||||
u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */
|
||||
struct metric metrics[2]; /* l1XxxMetric */
|
||||
u_int32_t te_metric[2];
|
||||
struct password *c_rx_passwds; /* circuitReceivePasswords */
|
||||
struct password *c_tc_passwd; /* circuitTransmitPassword */
|
||||
int ip_router; /* Route IP ? */
|
||||
int is_passive; /* Is Passive ? */
|
||||
struct list *ip_addrs; /* our IP addresses */
|
||||
#ifdef HAVE_IPV6
|
||||
int ipv6_router; /* Route IPv6 ? */
|
||||
struct list *ipv6_link; /* our link local IPv6 addresses */
|
||||
struct list *ipv6_non_link; /* our non-link local IPv6 addresses */
|
||||
#endif /* HAVE_IPV6 */
|
||||
/*
|
||||
* RFC 2973 IS-IS Mesh Groups
|
||||
*/
|
||||
#define MESH_INACTIVE 0
|
||||
#define MESH_BLOCKED 1
|
||||
#define MESH_SET 2
|
||||
int mesh_enabled; /* meshGroupEnabled */
|
||||
u_int16_t mesh_group; /* meshGroup */
|
||||
u_int16_t upadjcount[2];
|
||||
#define ISIS_CIRCUIT_FLAPPED_AFTER_SPF 0x01
|
||||
u_char flags;
|
||||
/*
|
||||
* Counters as in 10589--11.2.5.9
|
||||
*/
|
||||
@ -142,25 +137,30 @@ struct isis_circuit
|
||||
|
||||
void isis_circuit_init (void);
|
||||
struct isis_circuit *isis_circuit_new (void);
|
||||
void isis_circuit_del (struct isis_circuit *circuit);
|
||||
struct isis_circuit *circuit_lookup_by_ifp (struct interface *ifp,
|
||||
struct list *list);
|
||||
struct isis_circuit *circuit_scan_by_ifp (struct interface *ifp);
|
||||
void isis_circuit_del (struct isis_circuit *circuit);
|
||||
void isis_circuit_configure (struct isis_circuit *circuit,
|
||||
struct isis_area *area);
|
||||
void isis_circuit_up (struct isis_circuit *circuit);
|
||||
void isis_circuit_deconfigure (struct isis_circuit *circuit,
|
||||
struct isis_area *area);
|
||||
|
||||
int isis_circuit_destroy (struct isis_circuit *circuit);
|
||||
void isis_circuit_if_add (struct isis_circuit *circuit,
|
||||
struct interface *ifp);
|
||||
void isis_circuit_if_del (struct isis_circuit *circuit);
|
||||
void circuit_update_nlpids (struct isis_circuit *circuit);
|
||||
void isis_circuit_update_params (struct isis_circuit *circuit,
|
||||
struct interface *ifp);
|
||||
void isis_circuit_if_del (struct isis_circuit *circuit,
|
||||
struct interface *ifp);
|
||||
void isis_circuit_if_bind (struct isis_circuit *circuit,
|
||||
struct interface *ifp);
|
||||
void isis_circuit_if_unbind (struct isis_circuit *circuit,
|
||||
struct interface *ifp);
|
||||
void isis_circuit_add_addr (struct isis_circuit *circuit,
|
||||
struct connected *conn);
|
||||
void isis_circuit_del_addr (struct isis_circuit *circuit,
|
||||
struct connected *conn);
|
||||
int isis_circuit_up (struct isis_circuit *circuit);
|
||||
void isis_circuit_down (struct isis_circuit *);
|
||||
void circuit_update_nlpids (struct isis_circuit *circuit);
|
||||
void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
|
||||
char detail);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_CIRCUIT_H */
|
||||
|
@ -21,6 +21,9 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ISIS_COMMON_H
|
||||
#define ISIS_COMMON_H
|
||||
|
||||
/*
|
||||
* Area Address
|
||||
*/
|
||||
@ -65,11 +68,4 @@ struct nlpids
|
||||
u_char nlpids[4]; /* FIXME: enough ? */
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags structure for SSN and SRM flags
|
||||
*/
|
||||
struct flags
|
||||
{
|
||||
int maxindex;
|
||||
struct list *free_idcs;
|
||||
};
|
||||
#endif
|
||||
|
@ -27,8 +27,10 @@
|
||||
* Architectural constant values from p. 35 of ISO/IEC 10589
|
||||
*/
|
||||
|
||||
#define MAX_LINK_METRIC 63
|
||||
#define MAX_PATH_METRIC 1023
|
||||
#define MAX_NARROW_LINK_METRIC 63
|
||||
#define MAX_NARROW_PATH_METRIC 1023
|
||||
#define MAX_WIDE_LINK_METRIC 0x00FFFFFF /* RFC4444 */
|
||||
#define MAX_WIDE_PATH_METRIC 0xFE000000 /* RFC3787 */
|
||||
#define ISO_SAP 0xFE
|
||||
#define INTRADOMAIN_ROUTEING_SELECTOR 0
|
||||
#define SEQUENCE_MODULUS 4294967296
|
||||
@ -38,7 +40,7 @@
|
||||
* implementation specific jitter values
|
||||
*/
|
||||
|
||||
#define IIH_JITTER 25 /* % */
|
||||
#define IIH_JITTER 10 /* % */
|
||||
#define MAX_AGE_JITTER 5 /* % */
|
||||
#define MAX_LSP_GEN_JITTER 5 /* % */
|
||||
#define CSNP_JITTER 10 /* % */
|
||||
@ -46,36 +48,59 @@
|
||||
|
||||
#define RANDOM_SPREAD 100000.0
|
||||
|
||||
/*
|
||||
* Default values
|
||||
* ISO - 10589
|
||||
* Section 7.3.21 - Parameters
|
||||
*/
|
||||
#define MAX_AGE 1200
|
||||
#define ZERO_AGE_LIFETIME 60
|
||||
#define MAX_LSP_GEN_INTERVAL 900
|
||||
#define MIN_LSP_GEN_INTERVAL 30
|
||||
#define MIN_LSP_TRANS_INTERVAL 5
|
||||
#define ISIS_MIN_LSP_LIFETIME 380
|
||||
#define CSNP_INTERVAL 10
|
||||
#define PSNP_INTERVAL 2
|
||||
#define ISIS_MAX_PATH_SPLITS 3
|
||||
|
||||
#define ISIS_LEVELS 2
|
||||
#define ISIS_LEVEL1 1
|
||||
#define ISIS_LEVEL2 2
|
||||
|
||||
#define HELLO_INTERVAL 10
|
||||
#define HELLO_MINIMAL HELLO_INTERVAL
|
||||
#define HELLO_MULTIPLIER 3
|
||||
/*
|
||||
* Default values
|
||||
* ISO - 10589 Section 7.3.21 - Parameters
|
||||
* RFC 4444
|
||||
*/
|
||||
#define MAX_AGE 1200
|
||||
#define ZERO_AGE_LIFETIME 60
|
||||
#define MIN_LSP_LIFETIME 350
|
||||
#define MAX_LSP_LIFETIME 65535
|
||||
#define DEFAULT_LSP_LIFETIME 1200
|
||||
|
||||
#define MIN_MAX_LSP_GEN_INTERVAL 1
|
||||
#define MAX_MAX_LSP_GEN_INTERVAL 65235
|
||||
#define DEFAULT_MAX_LSP_GEN_INTERVAL 900
|
||||
|
||||
#define MIN_MIN_LSP_GEN_INTERVAL 1
|
||||
#define MAX_MIN_LSP_GEN_INTERVAL 120 /* RFC 4444 says 65535 */
|
||||
#define DEFAULT_MIN_LSP_GEN_INTERVAL 30
|
||||
|
||||
#define MIN_LSP_TRANS_INTERVAL 5
|
||||
|
||||
#define MIN_CSNP_INTERVAL 1
|
||||
#define MAX_CSNP_INTERVAL 600
|
||||
#define DEFAULT_CSNP_INTERVAL 10
|
||||
|
||||
#define MIN_PSNP_INTERVAL 1
|
||||
#define MAX_PSNP_INTERVAL 120
|
||||
#define DEFAULT_PSNP_INTERVAL 2
|
||||
|
||||
#define MIN_HELLO_INTERVAL 1
|
||||
#define MAX_HELLO_INTERVAL 600
|
||||
#define DEFAULT_HELLO_INTERVAL 3
|
||||
|
||||
#define MIN_HELLO_MULTIPLIER 2
|
||||
#define MAX_HELLO_MULTIPLIER 100
|
||||
#define DEFAULT_HELLO_MULTIPLIER 10
|
||||
|
||||
#define MIN_PRIORITY 0
|
||||
#define MAX_PRIORITY 127
|
||||
#define DEFAULT_PRIORITY 64
|
||||
/* different vendors implement different values 5-10 on average */
|
||||
#define LSP_GEN_INTERVAL_DEFAULT 10
|
||||
#define LSP_INTERVAL 33 /* msecs */
|
||||
#define DEFAULT_CIRCUIT_METRICS 10
|
||||
#define METRICS_UNSUPPORTED 0x80
|
||||
#define PERIODIC_SPF_INTERVAL 60 /* at the top of my head */
|
||||
#define MINIMUM_SPF_INTERVAL 5 /* .. same here */
|
||||
|
||||
/* min and max metric varies by new vs old metric types */
|
||||
#define DEFAULT_CIRCUIT_METRIC 10
|
||||
|
||||
#define METRICS_UNSUPPORTED 0x80
|
||||
|
||||
#define MINIMUM_SPF_INTERVAL 1
|
||||
|
||||
#define ISIS_MAX_PATH_SPLITS 64
|
||||
|
||||
/*
|
||||
* NLPID values
|
||||
@ -104,6 +129,7 @@
|
||||
|
||||
#define SNPA_ADDRSTRLEN 18
|
||||
#define ISIS_SYS_ID_LEN 6
|
||||
#define ISIS_NSEL_LEN 1
|
||||
#define SYSID_STRLEN 24
|
||||
|
||||
/*
|
||||
@ -136,8 +162,8 @@
|
||||
* packets, using isomtu = mtu - LLC_LEN
|
||||
*/
|
||||
#define ISO_MTU(C) \
|
||||
(C->circ_type==CIRCUIT_T_BROADCAST) ? \
|
||||
(C->interface->mtu - LLC_LEN) : (C->interface->mtu)
|
||||
((if_is_broadcast ((C)->interface)) ? \
|
||||
(C->interface->mtu - LLC_LEN) : (C->interface->mtu))
|
||||
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "isisd/include-netbsd/iso.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_tlv.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
@ -45,7 +46,6 @@
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_dr.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_csm.h"
|
||||
#include "isisd/isis_events.h"
|
||||
@ -85,6 +85,7 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
||||
case C_STATE_NA:
|
||||
if (circuit)
|
||||
zlog_warn ("Non-null circuit while state C_STATE_NA");
|
||||
assert (circuit == NULL);
|
||||
switch (event)
|
||||
{
|
||||
case ISIS_ENABLE:
|
||||
@ -106,24 +107,29 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
||||
}
|
||||
break;
|
||||
case C_STATE_INIT:
|
||||
assert (circuit);
|
||||
switch (event)
|
||||
{
|
||||
case ISIS_ENABLE:
|
||||
isis_circuit_configure (circuit, (struct isis_area *) arg);
|
||||
isis_circuit_up (circuit);
|
||||
if (isis_circuit_up (circuit) != ISIS_OK)
|
||||
{
|
||||
isis_circuit_deconfigure (circuit, (struct isis_area *) arg);
|
||||
break;
|
||||
}
|
||||
circuit->state = C_STATE_UP;
|
||||
circuit->connected = 1;
|
||||
isis_event_circuit_state_change (circuit, 1);
|
||||
isis_event_circuit_state_change (circuit, circuit->area, 1);
|
||||
listnode_delete (isis->init_circ_list, circuit);
|
||||
break;
|
||||
case IF_UP_FROM_Z:
|
||||
assert (circuit);
|
||||
zlog_warn ("circuit already connected");
|
||||
break;
|
||||
case ISIS_DISABLE:
|
||||
zlog_warn ("circuit already disabled");
|
||||
break;
|
||||
case IF_DOWN_FROM_Z:
|
||||
isis_circuit_if_del (circuit);
|
||||
isis_circuit_if_del (circuit, (struct interface *) arg);
|
||||
listnode_delete (isis->init_circ_list, circuit);
|
||||
isis_circuit_del (circuit);
|
||||
circuit = NULL;
|
||||
@ -131,19 +137,21 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
||||
}
|
||||
break;
|
||||
case C_STATE_CONF:
|
||||
assert (circuit);
|
||||
switch (event)
|
||||
{
|
||||
case ISIS_ENABLE:
|
||||
zlog_warn ("circuit already enabled");
|
||||
break;
|
||||
case IF_UP_FROM_Z:
|
||||
if (!circuit->connected) {
|
||||
isis_circuit_if_add (circuit, (struct interface *) arg);
|
||||
isis_circuit_up (circuit);
|
||||
}
|
||||
isis_circuit_if_add (circuit, (struct interface *) arg);
|
||||
if (isis_circuit_up (circuit) != ISIS_OK)
|
||||
{
|
||||
isis_circuit_if_del (circuit, (struct interface *) arg);
|
||||
break;
|
||||
}
|
||||
circuit->state = C_STATE_UP;
|
||||
circuit->connected = 1;
|
||||
isis_event_circuit_state_change (circuit, 1);
|
||||
isis_event_circuit_state_change (circuit, circuit->area, 1);
|
||||
break;
|
||||
case ISIS_DISABLE:
|
||||
isis_circuit_deconfigure (circuit, (struct isis_area *) arg);
|
||||
@ -156,6 +164,7 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
||||
}
|
||||
break;
|
||||
case C_STATE_UP:
|
||||
assert (circuit);
|
||||
switch (event)
|
||||
{
|
||||
case ISIS_ENABLE:
|
||||
@ -165,14 +174,18 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
||||
zlog_warn ("circuit already connected");
|
||||
break;
|
||||
case ISIS_DISABLE:
|
||||
isis_circuit_down (circuit);
|
||||
isis_circuit_deconfigure (circuit, (struct isis_area *) arg);
|
||||
listnode_add (isis->init_circ_list, circuit);
|
||||
circuit->state = C_STATE_INIT;
|
||||
isis_event_circuit_state_change (circuit, 0);
|
||||
isis_event_circuit_state_change (circuit,
|
||||
(struct isis_area *)arg, 0);
|
||||
listnode_add (isis->init_circ_list, circuit);
|
||||
break;
|
||||
case IF_DOWN_FROM_Z:
|
||||
isis_circuit_down (circuit);
|
||||
isis_circuit_if_del (circuit, (struct interface *) arg);
|
||||
circuit->state = C_STATE_CONF;
|
||||
isis_event_circuit_state_change (circuit, 0);
|
||||
isis_event_circuit_state_change (circuit, circuit->area, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -442,12 +442,12 @@ open_dlpi_dev (struct isis_circuit *circuit)
|
||||
* 8.4.2 - Broadcast subnetwork IIH PDUs
|
||||
*/
|
||||
retval = 0;
|
||||
if (circuit->circuit_is_type & IS_LEVEL_1)
|
||||
if (circuit->is_type & IS_LEVEL_1)
|
||||
{
|
||||
retval |= dlpimcast (fd, ALL_L1_ISS);
|
||||
retval |= dlpimcast (fd, ALL_ISS);
|
||||
}
|
||||
if (circuit->circuit_is_type & IS_LEVEL_2)
|
||||
if (circuit->is_type & IS_LEVEL_2)
|
||||
retval |= dlpimcast (fd, ALL_L2_ISS);
|
||||
|
||||
if (retval != 0)
|
||||
@ -589,6 +589,16 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
|
||||
char *dstaddr;
|
||||
u_short *dstsap;
|
||||
int buflen;
|
||||
|
||||
buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN;
|
||||
if (buflen > sizeof (sock_buff))
|
||||
{
|
||||
zlog_warn ("isis_send_pdu_bcast: sock_buff size %lu is less than "
|
||||
"output pdu size %d on circuit %s",
|
||||
sizeof (sock_buff), buflen, circuit->interface->name);
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
stream_set_getp (circuit->snd_stream, 0);
|
||||
|
||||
@ -612,7 +622,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
else
|
||||
memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
|
||||
/* Note: DLPI SAP values are in host byte order */
|
||||
*dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN;
|
||||
*dstsap = buflen;
|
||||
|
||||
sock_buff[0] = ISO_SAP;
|
||||
sock_buff[1] = ISO_SAP;
|
||||
@ -620,7 +630,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
|
||||
stream_get_endp (circuit->snd_stream));
|
||||
dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length,
|
||||
sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0);
|
||||
sock_buff, buflen, 0);
|
||||
return ISIS_OK;
|
||||
}
|
||||
|
||||
|
@ -47,9 +47,6 @@
|
||||
#include "isisd/isis_dr.h"
|
||||
#include "isisd/isis_events.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
extern struct thread_master *master;
|
||||
|
||||
const char *
|
||||
isis_disflag2string (int disflag)
|
||||
{
|
||||
@ -137,15 +134,14 @@ isis_dr_elect (struct isis_circuit *circuit, int level)
|
||||
int biggest_prio = -1;
|
||||
int cmp_res, retval = ISIS_OK;
|
||||
|
||||
own_prio = circuit->u.bc.priority[level - 1];
|
||||
own_prio = circuit->priority[level - 1];
|
||||
adjdb = circuit->u.bc.adjdb[level - 1];
|
||||
|
||||
if (!adjdb)
|
||||
{
|
||||
zlog_warn ("isis_dr_elect() adjdb == NULL");
|
||||
retval = ISIS_WARNING;
|
||||
list_delete (list);
|
||||
goto out;
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
isis_adj_build_up_list (adjdb, list);
|
||||
|
||||
@ -189,42 +185,34 @@ isis_dr_elect (struct isis_circuit *circuit, int level)
|
||||
if (!adj_dr)
|
||||
{
|
||||
/*
|
||||
* Could not find the DR - means we are alone and thus the DR
|
||||
* Could not find the DR - means we are alone. Resign if we were DR.
|
||||
*/
|
||||
if (!circuit->u.bc.is_dr[level - 1])
|
||||
{
|
||||
list_delete (list);
|
||||
list = NULL;
|
||||
return isis_dr_commence (circuit, level);
|
||||
}
|
||||
goto out;
|
||||
if (circuit->u.bc.is_dr[level - 1])
|
||||
retval = isis_dr_resign (circuit, level);
|
||||
list_delete (list);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have the DR adjacency, compare it to self
|
||||
*/
|
||||
if (adj_dr->prio[level - 1] < own_prio
|
||||
|| (adj_dr->prio[level - 1] == own_prio
|
||||
&& memcmp (adj_dr->snpa, circuit->u.bc.snpa, ETH_ALEN) < 0))
|
||||
if (adj_dr->prio[level - 1] < own_prio ||
|
||||
(adj_dr->prio[level - 1] == own_prio &&
|
||||
memcmp (adj_dr->snpa, circuit->u.bc.snpa, ETH_ALEN) < 0))
|
||||
{
|
||||
if (!circuit->u.bc.is_dr[level - 1])
|
||||
{
|
||||
/*
|
||||
* We are the DR
|
||||
*/
|
||||
adj_dr->dis_record[level - 1].dis = ISIS_IS_NOT_DIS;
|
||||
adj_dr->dis_record[level - 1].last_dis_change = time (NULL);
|
||||
|
||||
/* rotate the history log */
|
||||
for (ALL_LIST_ELEMENTS_RO (list, node, adj))
|
||||
isis_check_dr_change (adj, level);
|
||||
/* rotate the history log */
|
||||
for (ALL_LIST_ELEMENTS_RO (list, node, adj))
|
||||
isis_check_dr_change (adj, level);
|
||||
|
||||
/* commence */
|
||||
list_delete (list);
|
||||
return isis_dr_commence (circuit, level);
|
||||
}
|
||||
/* We are the DR, commence DR */
|
||||
if (circuit->u.bc.is_dr[level - 1] == 0 && listcount (list) > 0)
|
||||
retval = isis_dr_commence (circuit, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* ok we have found the DIS - lets mark the adjacency */
|
||||
/* set flag for show output */
|
||||
adj_dr->dis_record[level - 1].dis = ISIS_IS_DIS;
|
||||
@ -240,16 +228,10 @@ isis_dr_elect (struct isis_circuit *circuit, int level)
|
||||
/*
|
||||
* We are not DR - if we were -> resign
|
||||
*/
|
||||
|
||||
if (circuit->u.bc.is_dr[level - 1])
|
||||
{
|
||||
list_delete (list);
|
||||
return isis_dr_resign (circuit, level);
|
||||
}
|
||||
retval = isis_dr_resign (circuit, level);
|
||||
}
|
||||
out:
|
||||
if (list)
|
||||
list_delete (list);
|
||||
list_delete (list);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -264,11 +246,12 @@ isis_dr_resign (struct isis_circuit *circuit, int level)
|
||||
circuit->u.bc.run_dr_elect[level - 1] = 0;
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[level - 1]);
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]);
|
||||
circuit->lsp_regenerate_pending[level - 1] = 0;
|
||||
|
||||
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
|
||||
LSP_PSEUDO_ID (id) = circuit->circuit_id;
|
||||
LSP_FRAGMENT (id) = 0;
|
||||
lsp_purge_dr (id, circuit, level);
|
||||
lsp_purge_pseudo (id, circuit, level);
|
||||
|
||||
if (level == 1)
|
||||
{
|
||||
@ -327,7 +310,7 @@ isis_dr_commence (struct isis_circuit *circuit, int level)
|
||||
if (LSP_PSEUDO_ID (old_dr))
|
||||
{
|
||||
/* there was a dr elected, purge its LSPs from the db */
|
||||
lsp_purge_dr (old_dr, circuit, level);
|
||||
lsp_purge_pseudo (old_dr, circuit, level);
|
||||
}
|
||||
memcpy (circuit->u.bc.l1_desig_is, isis->sysid, ISIS_SYS_ID_LEN);
|
||||
*(circuit->u.bc.l1_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id;
|
||||
@ -335,7 +318,7 @@ isis_dr_commence (struct isis_circuit *circuit, int level)
|
||||
assert (circuit->circuit_id); /* must be non-zero */
|
||||
/* if (circuit->t_send_l1_psnp)
|
||||
thread_cancel (circuit->t_send_l1_psnp); */
|
||||
lsp_l1_pseudo_generate (circuit);
|
||||
lsp_generate_pseudo (circuit, 1);
|
||||
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
|
||||
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
|
||||
@ -353,7 +336,7 @@ isis_dr_commence (struct isis_circuit *circuit, int level)
|
||||
if (LSP_PSEUDO_ID (old_dr))
|
||||
{
|
||||
/* there was a dr elected, purge its LSPs from the db */
|
||||
lsp_purge_dr (old_dr, circuit, level);
|
||||
lsp_purge_pseudo (old_dr, circuit, level);
|
||||
}
|
||||
memcpy (circuit->u.bc.l2_desig_is, isis->sysid, ISIS_SYS_ID_LEN);
|
||||
*(circuit->u.bc.l2_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id;
|
||||
@ -361,7 +344,7 @@ isis_dr_commence (struct isis_circuit *circuit, int level)
|
||||
assert (circuit->circuit_id); /* must be non-zero */
|
||||
/* if (circuit->t_send_l1_psnp)
|
||||
thread_cancel (circuit->t_send_l1_psnp); */
|
||||
lsp_l2_pseudo_generate (circuit);
|
||||
lsp_generate_pseudo (circuit, 2);
|
||||
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
|
||||
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,
|
||||
|
@ -41,8 +41,6 @@
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
extern struct thread_master *master;
|
||||
extern struct host host;
|
||||
|
||||
struct list *dyn_cache = NULL;
|
||||
@ -51,7 +49,8 @@ static int dyn_cache_cleanup (struct thread *);
|
||||
void
|
||||
dyn_cache_init (void)
|
||||
{
|
||||
dyn_cache = list_new ();
|
||||
if (dyn_cache == NULL)
|
||||
dyn_cache = list_new ();
|
||||
THREAD_TIMER_ON (master, isis->t_dync_clean, dyn_cache_cleanup, NULL, 120);
|
||||
return;
|
||||
}
|
||||
@ -67,8 +66,8 @@ dyn_cache_cleanup (struct thread *thread)
|
||||
|
||||
for (ALL_LIST_ELEMENTS (dyn_cache, node, nnode, dyn))
|
||||
{
|
||||
if ((now - dyn->refresh) < (MAX_AGE + 120))
|
||||
continue;
|
||||
if ((now - dyn->refresh) < MAX_LSP_LIFETIME)
|
||||
continue;
|
||||
|
||||
list_delete_node (dyn_cache, node);
|
||||
XFREE (MTYPE_ISIS_DYNHN, dyn);
|
||||
@ -91,6 +90,19 @@ dynhn_find_by_id (u_char * id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct isis_dynhn *
|
||||
dynhn_find_by_name (const char *hostname)
|
||||
{
|
||||
struct listnode *node = NULL;
|
||||
struct isis_dynhn *dyn = NULL;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (dyn_cache, node, dyn))
|
||||
if (strncmp ((char *)dyn->name.name, hostname, 255) == 0)
|
||||
return dyn;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
isis_dynhn_insert (u_char * id, struct hostname *hostname, int level)
|
||||
{
|
||||
@ -122,6 +134,19 @@ isis_dynhn_insert (u_char * id, struct hostname *hostname, int level)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
isis_dynhn_remove (u_char * id)
|
||||
{
|
||||
struct isis_dynhn *dyn;
|
||||
|
||||
dyn = dynhn_find_by_id (id);
|
||||
if (!dyn)
|
||||
return;
|
||||
listnode_delete (dyn_cache, dyn);
|
||||
XFREE (MTYPE_ISIS_DYNHN, dyn);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Level System ID Dynamic Hostname (notag)
|
||||
* 2 0000.0000.0001 foo-gw
|
||||
|
@ -33,7 +33,9 @@ struct isis_dynhn
|
||||
|
||||
void dyn_cache_init (void);
|
||||
void isis_dynhn_insert (u_char * id, struct hostname *hostname, int level);
|
||||
void isis_dynhn_remove (u_char * id);
|
||||
struct isis_dynhn *dynhn_find_by_id (u_char * id);
|
||||
struct isis_dynhn *dynhn_find_by_name (const char *hostname);
|
||||
void dynhn_print_all (struct vty *vty);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_DYNHN_H */
|
||||
|
@ -30,11 +30,13 @@
|
||||
#include "hash.h"
|
||||
#include "prefix.h"
|
||||
#include "stream.h"
|
||||
#include "table.h"
|
||||
|
||||
#include "isisd/dict.h"
|
||||
#include "isisd/include-netbsd/iso.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_tlv.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
@ -44,15 +46,11 @@
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_dr.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_csm.h"
|
||||
#include "isisd/isis_events.h"
|
||||
#include "isisd/isis_spf.h"
|
||||
|
||||
extern struct thread_master *master;
|
||||
extern struct isis *isis;
|
||||
|
||||
/* debug isis-spf spf-events
|
||||
4w4d: ISIS-Spf (tlt): L2 SPF needed, new adjacency, from 0x609229F4
|
||||
4w4d: ISIS-Spf (tlt): L2, 0000.0000.0042.01-00 TLV contents changed, code 0x2
|
||||
@ -62,26 +60,59 @@ extern struct isis *isis;
|
||||
*/
|
||||
|
||||
void
|
||||
isis_event_circuit_state_change (struct isis_circuit *circuit, int up)
|
||||
isis_event_circuit_state_change (struct isis_circuit *circuit,
|
||||
struct isis_area *area, int up)
|
||||
{
|
||||
struct isis_area *area;
|
||||
|
||||
area = circuit->area;
|
||||
assert (area);
|
||||
area->circuit_state_changes++;
|
||||
|
||||
if (isis->debugs & DEBUG_EVENTS)
|
||||
zlog_debug ("ISIS-Evt (%s) circuit %s", circuit->area->area_tag,
|
||||
up ? "up" : "down");
|
||||
zlog_debug ("ISIS-Evt (%s) circuit %s", area->area_tag,
|
||||
up ? "up" : "down");
|
||||
|
||||
/*
|
||||
* Regenerate LSPs this affects
|
||||
*/
|
||||
lsp_regenerate_schedule (area);
|
||||
lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
area_resign_level (struct isis_area *area, int level)
|
||||
{
|
||||
if (area->lspdb[level - 1])
|
||||
{
|
||||
lsp_db_destroy (area->lspdb[level - 1]);
|
||||
area->lspdb[level - 1] = NULL;
|
||||
}
|
||||
if (area->spftree[level - 1])
|
||||
{
|
||||
isis_spftree_del (area->spftree[level - 1]);
|
||||
area->spftree[level - 1] = NULL;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (area->spftree6[level - 1])
|
||||
{
|
||||
isis_spftree_del (area->spftree6[level - 1]);
|
||||
area->spftree6[level - 1] = NULL;
|
||||
}
|
||||
#endif
|
||||
if (area->route_table[level - 1])
|
||||
{
|
||||
route_table_finish (area->route_table[level - 1]);
|
||||
area->route_table[level - 1] = NULL;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (area->route_table6[level - 1])
|
||||
{
|
||||
route_table_finish (area->route_table6[level - 1]);
|
||||
area->route_table6[level - 1] = NULL;
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]);
|
||||
}
|
||||
|
||||
void
|
||||
isis_event_system_type_change (struct isis_area *area, int newtype)
|
||||
{
|
||||
@ -96,59 +127,79 @@ isis_event_system_type_change (struct isis_area *area, int newtype)
|
||||
return; /* No change */
|
||||
|
||||
switch (area->is_type)
|
||||
{
|
||||
{
|
||||
case IS_LEVEL_1:
|
||||
if (newtype == IS_LEVEL_2)
|
||||
area_resign_level (area, IS_LEVEL_1);
|
||||
|
||||
if (area->lspdb[1] == NULL)
|
||||
area->lspdb[1] = lsp_db_init ();
|
||||
lsp_l2_generate (area);
|
||||
area->lspdb[1] = lsp_db_init ();
|
||||
if (area->route_table[1] == NULL)
|
||||
area->route_table[1] = route_table_init ();
|
||||
#ifdef HAVE_IPV6
|
||||
if (area->route_table6[1] == NULL)
|
||||
area->route_table6[1] = route_table_init ();
|
||||
#endif /* HAVE_IPV6 */
|
||||
break;
|
||||
|
||||
case IS_LEVEL_1_AND_2:
|
||||
if (newtype == IS_LEVEL_1)
|
||||
{
|
||||
lsp_db_destroy (area->lspdb[1]);
|
||||
}
|
||||
area_resign_level (area, IS_LEVEL_2);
|
||||
else
|
||||
{
|
||||
lsp_db_destroy (area->lspdb[0]);
|
||||
}
|
||||
area_resign_level (area, IS_LEVEL_1);
|
||||
break;
|
||||
|
||||
case IS_LEVEL_2:
|
||||
if (newtype == IS_LEVEL_1)
|
||||
area_resign_level (area, IS_LEVEL_2);
|
||||
|
||||
if (area->lspdb[0] == NULL)
|
||||
area->lspdb[0] = lsp_db_init ();
|
||||
lsp_l1_generate (area);
|
||||
area->lspdb[0] = lsp_db_init ();
|
||||
if (area->route_table[0] == NULL)
|
||||
area->route_table[0] = route_table_init ();
|
||||
#ifdef HAVE_IPV6
|
||||
if (area->route_table6[0] == NULL)
|
||||
area->route_table6[0] = route_table_init ();
|
||||
#endif /* HAVE_IPV6 */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
area->is_type = newtype;
|
||||
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
|
||||
isis_event_circuit_type_change (circuit, newtype);
|
||||
|
||||
/* override circuit's is_type */
|
||||
if (area->is_type != IS_LEVEL_1_AND_2)
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
|
||||
isis_event_circuit_type_change (circuit, newtype);
|
||||
}
|
||||
|
||||
spftree_area_init (area);
|
||||
lsp_regenerate_schedule (area);
|
||||
|
||||
if (newtype & IS_LEVEL_1)
|
||||
lsp_generate (area, IS_LEVEL_1);
|
||||
if (newtype & IS_LEVEL_2)
|
||||
lsp_generate (area, IS_LEVEL_2);
|
||||
lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
isis_event_area_addr_change (struct isis_area *area)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
circuit_commence_level (struct isis_circuit *circuit, int level)
|
||||
{
|
||||
if (level == 1)
|
||||
{
|
||||
THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
|
||||
isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
|
||||
if (! circuit->is_passive)
|
||||
THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
|
||||
isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
{
|
||||
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
|
||||
circuit, 2 * circuit->hello_interval[1]);
|
||||
circuit, 2 * circuit->hello_interval[0]);
|
||||
|
||||
THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0],
|
||||
send_lan_l1_hello, circuit,
|
||||
@ -160,8 +211,9 @@ circuit_commence_level (struct isis_circuit *circuit, int level)
|
||||
}
|
||||
else
|
||||
{
|
||||
THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
|
||||
isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
|
||||
if (! circuit->is_passive)
|
||||
THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
|
||||
isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
{
|
||||
@ -194,6 +246,8 @@ circuit_resign_level (struct isis_circuit *circuit, int level)
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[idx]);
|
||||
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[idx]);
|
||||
circuit->u.bc.run_dr_elect[idx] = 0;
|
||||
list_delete (circuit->u.bc.lan_neighs[idx]);
|
||||
circuit->u.bc.lan_neighs[idx] = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
@ -202,14 +256,19 @@ circuit_resign_level (struct isis_circuit *circuit, int level)
|
||||
void
|
||||
isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
|
||||
{
|
||||
if (circuit->state != C_STATE_UP)
|
||||
{
|
||||
circuit->is_type = newtype;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_EVENTS)
|
||||
zlog_debug ("ISIS-Evt (%s) circuit type change %s -> %s",
|
||||
circuit->area->area_tag,
|
||||
circuit_t2string (circuit->circuit_is_type),
|
||||
circuit_t2string (circuit->is_type),
|
||||
circuit_t2string (newtype));
|
||||
|
||||
if (circuit->circuit_is_type == newtype)
|
||||
if (circuit->is_type == newtype)
|
||||
return; /* No change */
|
||||
|
||||
if (!(newtype & circuit->area->is_type))
|
||||
@ -221,7 +280,7 @@ isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (circuit->circuit_is_type)
|
||||
switch (circuit->is_type)
|
||||
{
|
||||
case IS_LEVEL_1:
|
||||
if (newtype == IS_LEVEL_2)
|
||||
@ -243,8 +302,8 @@ isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
|
||||
break;
|
||||
}
|
||||
|
||||
circuit->circuit_is_type = newtype;
|
||||
lsp_regenerate_schedule (circuit->area);
|
||||
circuit->is_type = newtype;
|
||||
lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -286,7 +345,7 @@ isis_event_adjacency_state_change (struct isis_adjacency *adj, int newstate)
|
||||
adj->circuit->area->area_tag);
|
||||
|
||||
/* LSP generation again */
|
||||
lsp_regenerate_schedule (adj->circuit->area);
|
||||
lsp_regenerate_schedule (adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -307,7 +366,7 @@ isis_event_dis_status_change (struct thread *thread)
|
||||
zlog_debug ("ISIS-Evt (%s) DIS status change", circuit->area->area_tag);
|
||||
|
||||
/* LSP generation again */
|
||||
lsp_regenerate_schedule (circuit->area);
|
||||
lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,13 +26,12 @@
|
||||
* Events related to area
|
||||
*/
|
||||
void isis_event_system_type_change (struct isis_area *area, int newtype);
|
||||
void isis_event_area_addr_change (struct isis_area *area);
|
||||
|
||||
/*
|
||||
* Events related to circuit
|
||||
*/
|
||||
void isis_event_circuit_state_change (struct isis_circuit *circuit,
|
||||
int state);
|
||||
struct isis_area *area, int state);
|
||||
void isis_event_circuit_type_change (struct isis_circuit *circuit,
|
||||
int newtype);
|
||||
/*
|
||||
|
@ -36,11 +36,11 @@ flags_initialize (struct flags *flags)
|
||||
flags->free_idcs = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
long int
|
||||
flags_get_index (struct flags *flags)
|
||||
{
|
||||
struct listnode *node;
|
||||
int index;
|
||||
long int index;
|
||||
|
||||
if (flags->free_idcs == NULL || flags->free_idcs->count == 0)
|
||||
{
|
||||
@ -49,7 +49,7 @@ flags_get_index (struct flags *flags)
|
||||
else
|
||||
{
|
||||
node = listhead (flags->free_idcs);
|
||||
index = (int) listgetdata (node);
|
||||
index = (long int) listgetdata (node);
|
||||
listnode_delete (flags->free_idcs, (void *) index);
|
||||
index--;
|
||||
}
|
||||
@ -58,7 +58,7 @@ flags_get_index (struct flags *flags)
|
||||
}
|
||||
|
||||
void
|
||||
flags_free_index (struct flags *flags, int index)
|
||||
flags_free_index (struct flags *flags, long int index)
|
||||
{
|
||||
if (index + 1 == flags->maxindex)
|
||||
{
|
||||
|
@ -26,28 +26,43 @@
|
||||
|
||||
/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
|
||||
* the support will be achived using the newest drafts */
|
||||
#define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well */
|
||||
#define ISIS_MAX_CIRCUITS 32 /* = 1024 */
|
||||
|
||||
/*
|
||||
* Flags structure for SSN and SRM flags
|
||||
*/
|
||||
struct flags
|
||||
{
|
||||
int maxindex;
|
||||
struct list *free_idcs;
|
||||
};
|
||||
|
||||
void flags_initialize (struct flags *flags);
|
||||
struct flags *new_flags (int size);
|
||||
int flags_get_index (struct flags *flags);
|
||||
void flags_free_index (struct flags *flags, int index);
|
||||
|
||||
long int flags_get_index (struct flags *flags);
|
||||
void flags_free_index (struct flags *flags, long int index);
|
||||
int flags_any_set (u_int32_t * flags);
|
||||
|
||||
#define ISIS_SET_FLAG(F,C) \
|
||||
F[C->idx>>5] |= (1<<(C->idx & 0x1F));
|
||||
{ \
|
||||
F[C->idx>>5] |= (1<<(C->idx & 0x1F)); \
|
||||
}
|
||||
|
||||
#define ISIS_CLEAR_FLAG(F,C) \
|
||||
F[C->idx>>5] &= ~(1<<(C->idx & 0x1F));
|
||||
{ \
|
||||
F[C->idx>>5] &= ~(1<<(C->idx & 0x1F)); \
|
||||
}
|
||||
|
||||
#define ISIS_CHECK_FLAG(F, C) F[(C)->idx>>5] & (1<<(C->idx & 0x1F))
|
||||
#define ISIS_CHECK_FLAG(F, C) (F[(C)->idx>>5] & (1<<(C->idx & 0x1F)))
|
||||
|
||||
/* sets all u_32int_t flags to 1 */
|
||||
#define ISIS_FLAGS_SET_ALL(FLAGS) \
|
||||
memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4);
|
||||
{ \
|
||||
memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4); \
|
||||
}
|
||||
|
||||
#define ISIS_FLAGS_CLEAR_ALL(FLAGS) \
|
||||
memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4);
|
||||
{ \
|
||||
memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4); \
|
||||
}
|
||||
|
||||
#endif /* _ZEBRA_ISIS_FLAGS_H */
|
||||
|
1558
isisd/isis_lsp.c
1558
isisd/isis_lsp.c
File diff suppressed because it is too large
Load Diff
@ -24,10 +24,6 @@
|
||||
#ifndef _ZEBRA_ISIS_LSP_H
|
||||
#define _ZEBRA_ISIS_LSP_H
|
||||
|
||||
/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
|
||||
* the support will be achived using the newest drafts */
|
||||
#define ISIS_MAX_CIRCUITS 32 /* = 1024 - FIXME:defined in flags.h as well */
|
||||
|
||||
/* Structure for isis_lsp, this structure will only support the fixed
|
||||
* System ID (Currently 6) (atleast for now). In order to support more
|
||||
* We will have to split the header into two parts, and for readability
|
||||
@ -42,15 +38,13 @@ struct isis_lsp
|
||||
struct list *frags;
|
||||
struct isis_lsp *zero_lsp;
|
||||
} lspu;
|
||||
u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */
|
||||
u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
|
||||
u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
|
||||
u_int32_t rexmit_queue[ISIS_MAX_CIRCUITS];
|
||||
int level; /* L1 or L2? */
|
||||
int purged; /* have purged this one */
|
||||
int scheduled; /* scheduled for sending */
|
||||
time_t installed;
|
||||
time_t last_generated;
|
||||
time_t last_sent;
|
||||
int own_lsp;
|
||||
#ifdef TOPOLOGY_GENERATE
|
||||
int from_topology;
|
||||
@ -58,7 +52,6 @@ struct isis_lsp
|
||||
#endif
|
||||
/* used for 60 second counting when rem_lifetime is zero */
|
||||
int age_out;
|
||||
/* FIXME: For now only topology LSP's use this. Is it helpful for others? */
|
||||
struct isis_area *area;
|
||||
struct tlvs tlv_data; /* Simplifies TLV access */
|
||||
};
|
||||
@ -67,37 +60,32 @@ dict_t *lsp_db_init (void);
|
||||
void lsp_db_destroy (dict_t * lspdb);
|
||||
int lsp_tick (struct thread *thread);
|
||||
|
||||
int lsp_l1_generate (struct isis_area *area);
|
||||
int lsp_l2_generate (struct isis_area *area);
|
||||
int lsp_refresh_l1 (struct thread *thread);
|
||||
int lsp_refresh_l2 (struct thread *thread);
|
||||
int lsp_regenerate_schedule (struct isis_area *area);
|
||||
int lsp_generate (struct isis_area *area, int level);
|
||||
int lsp_regenerate_schedule (struct isis_area *area, int level,
|
||||
int all_pseudo);
|
||||
int lsp_generate_pseudo (struct isis_circuit *circuit, int level);
|
||||
int lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level);
|
||||
|
||||
int lsp_l1_pseudo_generate (struct isis_circuit *circuit);
|
||||
int lsp_l2_pseudo_generate (struct isis_circuit *circuit);
|
||||
int lsp_l1_refresh_pseudo (struct thread *thread);
|
||||
int lsp_l2_refresh_pseudo (struct thread *thread);
|
||||
int isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
|
||||
int pdulen, struct isis_passwd *passwd);
|
||||
struct isis_lsp *lsp_new (u_char * lsp_id, u_int16_t rem_lifetime,
|
||||
u_int32_t seq_num, u_int8_t lsp_bits,
|
||||
u_int16_t checksum, int level);
|
||||
struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream,
|
||||
u_int16_t pdu_len,
|
||||
struct isis_lsp *lsp0,
|
||||
struct isis_area *area);
|
||||
struct isis_area *area,
|
||||
int level);
|
||||
void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb);
|
||||
struct isis_lsp *lsp_search (u_char * id, dict_t * lspdb);
|
||||
|
||||
void lsp_build_list (u_char * start_id, u_char * stop_id,
|
||||
void lsp_build_list (u_char * start_id, u_char * stop_id, u_char num_lsps,
|
||||
struct list *list, dict_t * lspdb);
|
||||
void lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
|
||||
struct list *list, dict_t * lspdb);
|
||||
void lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
|
||||
dict_t * lspdb);
|
||||
void lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps,
|
||||
struct list *list, dict_t * lspdb);
|
||||
|
||||
void lsp_search_and_destroy (u_char * id, dict_t * lspdb);
|
||||
void lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level);
|
||||
void lsp_purge_pseudo (u_char * id, struct isis_circuit *circuit, int level);
|
||||
void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
|
||||
struct isis_area *area);
|
||||
|
||||
@ -114,13 +102,18 @@ void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
|
||||
int lsp_id_cmp (u_char * id1, u_char * id2);
|
||||
int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
|
||||
u_int16_t checksum, u_int16_t rem_lifetime);
|
||||
void lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
|
||||
struct stream *stream, struct isis_area *area, int level);
|
||||
void lsp_update (struct isis_lsp *lsp, struct stream *stream,
|
||||
struct isis_area *area, int level);
|
||||
void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num);
|
||||
void lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost);
|
||||
void lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost);
|
||||
int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail,
|
||||
char dynhost);
|
||||
const char *lsp_bits2string (u_char *);
|
||||
|
||||
/* sets SRMflags for all active circuits of an lsp */
|
||||
void lsp_set_all_srmflags (struct isis_lsp *lsp);
|
||||
|
||||
#ifdef TOPOLOGY_GENERATE
|
||||
void generate_topology_lsps (struct isis_area *area);
|
||||
void remove_topology_lsps (struct isis_area *area);
|
||||
|
@ -44,6 +44,9 @@
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_dynhn.h"
|
||||
#include "isisd/isis_spf.h"
|
||||
#include "isisd/isis_route.h"
|
||||
#include "isisd/isis_zebra.h"
|
||||
|
||||
/* Default configuration file name */
|
||||
#define ISISD_DEFAULT_CONFIG "isisd.conf"
|
||||
@ -67,7 +70,7 @@ struct zebra_privs_t isisd_privs = {
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = 2,
|
||||
.cap_num_p = sizeof (_caps_p) / sizeof (*_caps_p),
|
||||
.cap_num_i = 0
|
||||
};
|
||||
|
||||
@ -154,7 +157,10 @@ reload ()
|
||||
zlog_debug ("Reload");
|
||||
/* FIXME: Clean up func call here */
|
||||
vty_reset ();
|
||||
(void) isisd_privs.change (ZPRIVS_RAISE);
|
||||
execve (_progpath, _argv, _envp);
|
||||
zlog_err ("Reload failed: cannot exec %s: %s", _progpath,
|
||||
safe_strerror (errno));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -325,28 +331,31 @@ main (int argc, char **argv, char **envp)
|
||||
memory_init ();
|
||||
access_list_init();
|
||||
isis_init ();
|
||||
dyn_cache_init ();
|
||||
isis_circuit_init ();
|
||||
isis_spf_cmds_init ();
|
||||
|
||||
/* create the global 'isis' instance */
|
||||
isis_new (1);
|
||||
|
||||
isis_zebra_init ();
|
||||
|
||||
sort_node ();
|
||||
|
||||
/* parse config file */
|
||||
/* this is needed three times! because we have interfaces before the areas */
|
||||
vty_read_config (config_file, config_default);
|
||||
vty_read_config (config_file, config_default);
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
/* Start execution only if not in dry-run mode */
|
||||
if (dryrun)
|
||||
return(0);
|
||||
|
||||
/* demonize */
|
||||
if (daemon_mode && daemon (0, 0) < 0)
|
||||
{
|
||||
zlog_err("ISISd daemon failed: %s", strerror(errno));
|
||||
exit (1);
|
||||
}
|
||||
if (daemon_mode)
|
||||
daemon (0, 0);
|
||||
|
||||
/* Process ID file creation. */
|
||||
pid_output (pid_file);
|
||||
if (pid_file[0] != '\0')
|
||||
pid_output (pid_file);
|
||||
|
||||
/* Make isis vty socket. */
|
||||
vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);
|
||||
|
@ -32,7 +32,9 @@
|
||||
#include "isisd/dict.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_csm.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
|
||||
@ -40,6 +42,7 @@
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_dynhn.h"
|
||||
|
||||
/* staticly assigned vars for printing purposes */
|
||||
struct in_addr new_prefix;
|
||||
@ -99,10 +102,10 @@ isonet_print (u_char * from, int len)
|
||||
* extract dot from the dotted str, and insert all the number in a buff
|
||||
*/
|
||||
int
|
||||
dotformat2buff (u_char * buff, const u_char * dotted)
|
||||
dotformat2buff (u_char * buff, const char * dotted)
|
||||
{
|
||||
int dotlen, len = 0;
|
||||
const u_char *pos = dotted;
|
||||
const char *pos = dotted;
|
||||
u_char number[3];
|
||||
int nextdotpos = 2;
|
||||
|
||||
@ -157,10 +160,10 @@ dotformat2buff (u_char * buff, const u_char * dotted)
|
||||
* conversion of XXXX.XXXX.XXXX to memory
|
||||
*/
|
||||
int
|
||||
sysid2buff (u_char * buff, const u_char * dotted)
|
||||
sysid2buff (u_char * buff, const char * dotted)
|
||||
{
|
||||
int len = 0;
|
||||
const u_char *pos = dotted;
|
||||
const char *pos = dotted;
|
||||
u_char number[3];
|
||||
|
||||
number[2] = '\0';
|
||||
@ -271,7 +274,7 @@ speaks (struct nlpids *nlpids, int family)
|
||||
* Returns 0 on error, IS-IS Circuit Type on ok
|
||||
*/
|
||||
int
|
||||
string2circuit_t (const u_char * str)
|
||||
string2circuit_t (const char * str)
|
||||
{
|
||||
|
||||
if (!str)
|
||||
@ -289,6 +292,42 @@ string2circuit_t (const u_char * str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
circuit_state2string (int state)
|
||||
{
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case C_STATE_INIT:
|
||||
return "Init";
|
||||
case C_STATE_CONF:
|
||||
return "Config";
|
||||
case C_STATE_UP:
|
||||
return "Up";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
circuit_type2string (int type)
|
||||
{
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CIRCUIT_T_P2P:
|
||||
return "p2p";
|
||||
case CIRCUIT_T_BROADCAST:
|
||||
return "lan";
|
||||
case CIRCUIT_T_LOOPBACK:
|
||||
return "loopback";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
circuit_t2string (int circuit_t)
|
||||
{
|
||||
@ -498,7 +537,6 @@ unix_hostname (void)
|
||||
{
|
||||
static struct utsname names;
|
||||
const char *hostname;
|
||||
extern struct host host;
|
||||
|
||||
hostname = host.name;
|
||||
if (!hostname)
|
||||
@ -509,3 +547,87 @@ unix_hostname (void)
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the dynamic hostname associated with the passed system ID.
|
||||
* If no dynamic hostname found then returns formatted system ID.
|
||||
*/
|
||||
const char *
|
||||
print_sys_hostname (u_char *sysid)
|
||||
{
|
||||
struct isis_dynhn *dyn;
|
||||
|
||||
if (!sysid)
|
||||
return "nullsysid";
|
||||
|
||||
/* For our system ID return our host name */
|
||||
if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
|
||||
return unix_hostname();
|
||||
|
||||
dyn = dynhn_find_by_id (sysid);
|
||||
if (dyn)
|
||||
return (const char *)dyn->name.name;
|
||||
|
||||
return sysid_print (sysid);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a generic utility that logs data of given length.
|
||||
* Move this to a shared lib so that any protocol can use it.
|
||||
*/
|
||||
void
|
||||
zlog_dump_data (void *data, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
unsigned char c;
|
||||
char bytestr[4];
|
||||
char addrstr[10];
|
||||
char hexstr[ 16*3 + 5];
|
||||
char charstr[16*1 + 5];
|
||||
|
||||
p = data;
|
||||
memset (bytestr, 0, sizeof(bytestr));
|
||||
memset (addrstr, 0, sizeof(addrstr));
|
||||
memset (hexstr, 0, sizeof(hexstr));
|
||||
memset (charstr, 0, sizeof(charstr));
|
||||
|
||||
for (i = 1; i <= len; i++)
|
||||
{
|
||||
c = *p;
|
||||
if (isalnum (c) == 0)
|
||||
c = '.';
|
||||
|
||||
/* store address for this line */
|
||||
if ((i % 16) == 1)
|
||||
snprintf (addrstr, sizeof(addrstr), "%p", p);
|
||||
|
||||
/* store hex str (for left side) */
|
||||
snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
|
||||
strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
|
||||
|
||||
/* store char str (for right side) */
|
||||
snprintf (bytestr, sizeof (bytestr), "%c", c);
|
||||
strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
|
||||
|
||||
if ((i % 16) == 0)
|
||||
{
|
||||
/* line completed */
|
||||
zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
|
||||
hexstr[0] = 0;
|
||||
charstr[0] = 0;
|
||||
}
|
||||
else if ((i % 8) == 0)
|
||||
{
|
||||
/* half line: add whitespaces */
|
||||
strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1);
|
||||
strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
|
||||
}
|
||||
p++; /* next byte */
|
||||
}
|
||||
|
||||
/* print rest of buffer if not empty */
|
||||
if (strlen (hexstr) > 0)
|
||||
zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
|
||||
return;
|
||||
}
|
||||
|
@ -24,8 +24,10 @@
|
||||
#ifndef _ZEBRA_ISIS_MISC_H
|
||||
#define _ZEBRA_ISIS_MISC_H
|
||||
|
||||
int string2circuit_t (const u_char *);
|
||||
int string2circuit_t (const char *);
|
||||
const char *circuit_t2string (int);
|
||||
const char *circuit_state2string (int state);
|
||||
const char *circuit_type2string (int type);
|
||||
const char *syst2string (int);
|
||||
struct in_addr newprefix2inaddr (u_char * prefix_start,
|
||||
u_char prefix_masklen);
|
||||
@ -33,8 +35,8 @@ struct in_addr newprefix2inaddr (u_char * prefix_start,
|
||||
* Converting input to memory stored format
|
||||
* return value of 0 indicates wrong input
|
||||
*/
|
||||
int dotformat2buff (u_char *, const u_char *);
|
||||
int sysid2buff (u_char *, const u_char *);
|
||||
int dotformat2buff (u_char *, const char *);
|
||||
int sysid2buff (u_char *, const char *);
|
||||
|
||||
/*
|
||||
* Printing functions
|
||||
@ -46,6 +48,8 @@ const char *rawlspid_print (u_char *);
|
||||
const char *time2string (u_int32_t);
|
||||
/* typedef struct nlpids nlpids; */
|
||||
char *nlpid2string (struct nlpids *);
|
||||
const char *print_sys_hostname (u_char *sysid);
|
||||
void zlog_dump_data (void *data, int len);
|
||||
|
||||
/*
|
||||
* misc functions
|
||||
@ -57,7 +61,8 @@ const char *unix_hostname (void);
|
||||
/*
|
||||
* macros
|
||||
*/
|
||||
#define GETSYSID(A,L) (A->area_addr + (A->addr_len - (L + 1)))
|
||||
#define GETSYSID(A) (A->area_addr + (A->addr_len - \
|
||||
(ISIS_SYS_ID_LEN + ISIS_NSEL_LEN)))
|
||||
|
||||
/* used for calculating nice string representation instead of plain seconds */
|
||||
|
||||
|
1612
isisd/isis_pdu.c
1612
isisd/isis_pdu.c
File diff suppressed because it is too large
Load Diff
@ -95,7 +95,7 @@ struct isis_fixed_hdr
|
||||
u_char version2;
|
||||
u_char reserved;
|
||||
u_char max_area_addrs;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ISIS_FIXED_HDR_LEN 8
|
||||
|
||||
@ -114,7 +114,7 @@ struct isis_fixed_hdr
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | Holding Time | 2
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | PDU Lenght | 2
|
||||
* | PDU Length | 2
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | R | Priority | 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
@ -142,7 +142,7 @@ struct isis_lan_hello_hdr
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* + Holding Time + 2
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* + PDU Lenght + 2
|
||||
* + PDU Length + 2
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | Local Circuit ID | 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
@ -186,12 +186,23 @@ struct isis_link_state_hdr
|
||||
} __attribute__ ((packed));
|
||||
#define ISIS_LSP_HDR_LEN 19
|
||||
|
||||
/*
|
||||
* Since the length field of LSP Entries TLV is one byte long, and each LSP
|
||||
* entry is LSP_ENTRIES_LEN (16) bytes long, the maximum number of LSP entries
|
||||
* can be accomodated in a TLV is
|
||||
* 255 / 16 = 15.
|
||||
*
|
||||
* Therefore, the maximum length of the LSP Entries TLV is
|
||||
* 16 * 15 + 2 (header) = 242 bytes.
|
||||
*/
|
||||
#define MAX_LSP_ENTRIES_TLV_SIZE 242
|
||||
|
||||
#define L1_COMPLETE_SEQ_NUM 24
|
||||
#define L2_COMPLETE_SEQ_NUM 25
|
||||
/*
|
||||
* L1 and L2 IS to IS complete sequence numbers PDU header
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* + PDU Lenght + 2
|
||||
* + PDU Length + 2
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* + Source ID + id_len + 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
@ -241,6 +252,8 @@ int isis_receive (struct thread *thread);
|
||||
#define ISIS_SNP_PSNP_FLAG 0
|
||||
#define ISIS_SNP_CSNP_FLAG 1
|
||||
|
||||
#define ISIS_AUTH_MD5_SIZE 16U
|
||||
|
||||
/*
|
||||
* Sending functions
|
||||
*/
|
||||
@ -258,7 +271,4 @@ int ack_lsp (struct isis_link_state_hdr *hdr,
|
||||
void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type);
|
||||
int send_hello (struct isis_circuit *circuit, int level);
|
||||
|
||||
#define ISIS_AUTH_MD5_SIZE 16U
|
||||
int authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit *c);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_PDU_H */
|
||||
|
@ -134,7 +134,7 @@ open_packet_socket (struct isis_circuit *circuit)
|
||||
|
||||
circuit->fd = fd;
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
if (if_is_broadcast (circuit->interface))
|
||||
{
|
||||
/*
|
||||
* Join to multicast groups
|
||||
@ -142,24 +142,22 @@ open_packet_socket (struct isis_circuit *circuit)
|
||||
* 8.4.2 - Broadcast subnetwork IIH PDUs
|
||||
* FIXME: is there a case only one will fail??
|
||||
*/
|
||||
if (circuit->circuit_is_type & IS_LEVEL_1)
|
||||
{
|
||||
/* joining ALL_L1_ISS */
|
||||
retval = isis_multicast_join (circuit->fd, 1,
|
||||
circuit->interface->ifindex);
|
||||
/* joining ALL_ISS */
|
||||
retval = isis_multicast_join (circuit->fd, 3,
|
||||
circuit->interface->ifindex);
|
||||
}
|
||||
if (circuit->circuit_is_type & IS_LEVEL_2)
|
||||
/* joining ALL_L2_ISS */
|
||||
retval = isis_multicast_join (circuit->fd, 2,
|
||||
circuit->interface->ifindex);
|
||||
if (circuit->is_type & IS_LEVEL_1)
|
||||
/* joining ALL_L1_ISS */
|
||||
retval = isis_multicast_join (circuit->fd, 1,
|
||||
circuit->interface->ifindex);
|
||||
if (circuit->is_type & IS_LEVEL_2)
|
||||
/* joining ALL_L2_ISS */
|
||||
retval = isis_multicast_join (circuit->fd, 2,
|
||||
circuit->interface->ifindex);
|
||||
/* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */
|
||||
retval = isis_multicast_join (circuit->fd, 3,
|
||||
circuit->interface->ifindex);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval =
|
||||
isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
|
||||
isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -184,12 +182,13 @@ isis_sock_init (struct isis_circuit *circuit)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
||||
/* Assign Rx and Tx callbacks are based on real if type */
|
||||
if (if_is_broadcast (circuit->interface))
|
||||
{
|
||||
circuit->tx = isis_send_pdu_bcast;
|
||||
circuit->rx = isis_recv_pdu_bcast;
|
||||
}
|
||||
else if (circuit->circ_type == CIRCUIT_T_P2P)
|
||||
else if (if_is_pointopoint (circuit->interface))
|
||||
{
|
||||
circuit->tx = isis_send_pdu_p2p;
|
||||
circuit->rx = isis_recv_pdu_p2p;
|
||||
@ -232,19 +231,16 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
LLC_LEN, MSG_PEEK,
|
||||
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
|
||||
|
||||
if (!circuit->area) {
|
||||
return ISIS_OK;
|
||||
}
|
||||
|
||||
if (bytesread < 0)
|
||||
{
|
||||
zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
|
||||
circuit->fd, safe_strerror (errno));
|
||||
zlog_warn ("circuit is %s", circuit->interface->name);
|
||||
zlog_warn ("circuit fd %d", circuit->fd);
|
||||
zlog_warn ("bytesread %d", bytesread);
|
||||
zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, "
|
||||
"recvfrom(): %s",
|
||||
circuit->interface->name, circuit->fd, bytesread,
|
||||
safe_strerror (errno));
|
||||
/* get rid of the packet */
|
||||
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
|
||||
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
|
||||
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
/*
|
||||
@ -253,15 +249,22 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
|
||||
{
|
||||
/* Read the packet into discard buff */
|
||||
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
|
||||
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
|
||||
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
if (bytesread < 0)
|
||||
zlog_warn ("isis_recv_pdu_bcast(): read() failed");
|
||||
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
/* on lan we have to read to the static buff first */
|
||||
bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
|
||||
bytesread = recvfrom (circuit->fd, sock_buff, sizeof (sock_buff), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
|
||||
if (bytesread < 0)
|
||||
{
|
||||
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
/* then we lose the LLC */
|
||||
stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
|
||||
@ -289,9 +292,11 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
if (s_addr.sll_pkttype == PACKET_OUTGOING)
|
||||
{
|
||||
/* Read the packet into discard buff */
|
||||
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
|
||||
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
|
||||
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
if (bytesread < 0)
|
||||
zlog_warn ("isis_recv_pdu_p2p(): read() failed");
|
||||
zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed");
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
@ -313,6 +318,9 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
int
|
||||
isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
/* we need to do the LLC in here because of P2P circuits, which will
|
||||
* not need it
|
||||
*/
|
||||
@ -325,7 +333,10 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
|
||||
sa.sll_ifindex = circuit->interface->ifindex;
|
||||
sa.sll_halen = ETH_ALEN;
|
||||
if (level == 1)
|
||||
/* RFC5309 section 4.1 recommends ALL_ISS */
|
||||
if (circuit->circ_type == CIRCUIT_T_P2P)
|
||||
memcpy (&sa.sll_addr, ALL_ISS, ETH_ALEN);
|
||||
else if (level == 1)
|
||||
memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
|
||||
else
|
||||
memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
|
||||
@ -336,14 +347,17 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
sock_buff[1] = 0xFE;
|
||||
sock_buff[2] = 0x03;
|
||||
|
||||
/* then we copy the data */
|
||||
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
|
||||
stream_get_endp (circuit->snd_stream));
|
||||
memset (&msg, 0, sizeof (msg));
|
||||
msg.msg_name = &sa;
|
||||
msg.msg_namelen = sizeof (struct sockaddr_ll);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
iov[0].iov_base = sock_buff;
|
||||
iov[0].iov_len = LLC_LEN;
|
||||
iov[1].iov_base = circuit->snd_stream->data;
|
||||
iov[1].iov_len = stream_get_endp (circuit->snd_stream);
|
||||
|
||||
/* now we can send this */
|
||||
written = sendto (circuit->fd, sock_buff,
|
||||
stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
|
||||
(struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
|
||||
written = sendmsg (circuit->fd, &msg, 0);
|
||||
|
||||
return ISIS_OK;
|
||||
}
|
||||
@ -351,7 +365,6 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
|
||||
int
|
||||
isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
|
||||
{
|
||||
|
||||
int written = 1;
|
||||
struct sockaddr_ll sa;
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include "isis_constants.h"
|
||||
#include "isis_common.h"
|
||||
#include "isis_flags.h"
|
||||
#include "dict.h"
|
||||
#include "isisd.h"
|
||||
#include "isis_misc.h"
|
||||
@ -48,9 +49,6 @@
|
||||
#include "isis_route.h"
|
||||
#include "isis_zebra.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
extern struct thread_master *master;
|
||||
|
||||
static struct isis_nexthop *
|
||||
isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
|
||||
{
|
||||
@ -246,6 +244,7 @@ adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
|
||||
{
|
||||
nh = isis_nexthop_create (ipv4_addr,
|
||||
adj->circuit->interface->ifindex);
|
||||
nh->router_address = adj->router_address;
|
||||
listnode_add (nexthops, nh);
|
||||
}
|
||||
}
|
||||
@ -269,6 +268,7 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
|
||||
{
|
||||
nh6 = isis_nexthop6_create (ipv6_addr,
|
||||
adj->circuit->interface->ifindex);
|
||||
nh6->router_address6 = adj->router_address6;
|
||||
listnode_add (nexthops6, nh6);
|
||||
}
|
||||
}
|
||||
@ -276,8 +276,8 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
static struct isis_route_info *
|
||||
isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
|
||||
struct list *adjacencies)
|
||||
isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
|
||||
struct list *adjacencies)
|
||||
{
|
||||
struct isis_route_info *rinfo;
|
||||
struct isis_adjacency *adj;
|
||||
@ -290,18 +290,34 @@ isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (family == AF_INET)
|
||||
if (prefix->family == AF_INET)
|
||||
{
|
||||
rinfo->nexthops = list_new ();
|
||||
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
|
||||
adjinfo2nexthop (rinfo->nexthops, adj);
|
||||
{
|
||||
/* check for force resync this route */
|
||||
if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
||||
SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
/* update neighbor router address */
|
||||
if (depth == 2 && prefix->prefixlen == 32)
|
||||
adj->router_address = prefix->u.prefix4;
|
||||
adjinfo2nexthop (rinfo->nexthops, adj);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (family == AF_INET6)
|
||||
if (prefix->family == AF_INET6)
|
||||
{
|
||||
rinfo->nexthops6 = list_new ();
|
||||
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
|
||||
adjinfo2nexthop6 (rinfo->nexthops6, adj);
|
||||
{
|
||||
/* check for force resync this route */
|
||||
if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
||||
SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
/* update neighbor router address */
|
||||
if (depth == 2 && prefix->prefixlen == 128)
|
||||
adj->router_address6 = prefix->u.prefix6;
|
||||
adjinfo2nexthop6 (rinfo->nexthops6, adj);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_IPV6 */
|
||||
@ -353,18 +369,25 @@ isis_route_info_same (struct isis_route_info *new,
|
||||
#ifdef HAVE_IPV6
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return 0;
|
||||
|
||||
if (CHECK_FLAG (new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC))
|
||||
return 0;
|
||||
|
||||
if (!isis_route_info_same_attrib (new, old))
|
||||
return 0;
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop))
|
||||
if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
|
||||
if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
|
||||
== 0)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop))
|
||||
if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
|
||||
if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
|
||||
== 0)
|
||||
return 0;
|
||||
}
|
||||
@ -386,65 +409,6 @@ isis_route_info_same (struct isis_route_info *new,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
isis_nexthops_merge (struct list *new, struct list *old)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_nexthop *nexthop;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (new, node, nexthop))
|
||||
{
|
||||
if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))
|
||||
continue;
|
||||
listnode_add (old, nexthop);
|
||||
nexthop->lock++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
static void
|
||||
isis_nexthops6_merge (struct list *new, struct list *old)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (new, node, nexthop6))
|
||||
{
|
||||
if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))
|
||||
continue;
|
||||
listnode_add (old, nexthop6);
|
||||
nexthop6->lock++;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
static void
|
||||
isis_route_info_merge (struct isis_route_info *new,
|
||||
struct isis_route_info *old, u_char family)
|
||||
{
|
||||
if (family == AF_INET)
|
||||
isis_nexthops_merge (new->nexthops, old->nexthops);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (family == AF_INET6)
|
||||
isis_nexthops6_merge (new->nexthops6, old->nexthops6);
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
isis_route_info_prefer_new (struct isis_route_info *new,
|
||||
struct isis_route_info *old)
|
||||
{
|
||||
if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))
|
||||
return 1;
|
||||
|
||||
if (new->cost < old->cost)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct isis_route_info *
|
||||
isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
|
||||
struct list *adjacencies, struct isis_area *area,
|
||||
@ -459,7 +423,7 @@ isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
|
||||
/* for debugs */
|
||||
prefix2str (prefix, (char *) buff, BUFSIZ);
|
||||
|
||||
rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);
|
||||
rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies);
|
||||
if (!rinfo_new)
|
||||
{
|
||||
zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
|
||||
@ -479,68 +443,32 @@ isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
|
||||
if (!rinfo_old)
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
|
||||
SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
||||
route_node->info = rinfo_new;
|
||||
return rinfo_new;
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
|
||||
buff);
|
||||
|
||||
if (isis_route_info_same (rinfo_new, rinfo_old, family))
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);
|
||||
isis_route_info_delete (rinfo_new);
|
||||
route_info = rinfo_old;
|
||||
}
|
||||
else if (isis_route_info_same_attrib (rinfo_new, rinfo_old))
|
||||
{
|
||||
/* merge the nexthop lists */
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s",
|
||||
area->area_tag, buff);
|
||||
#ifdef EXTREME_DEBUG
|
||||
if (family == AF_INET)
|
||||
{
|
||||
zlog_debug ("Old nexthops");
|
||||
nexthops_print (rinfo_old->nexthops);
|
||||
zlog_debug ("New nexthops");
|
||||
nexthops_print (rinfo_new->nexthops);
|
||||
}
|
||||
else if (family == AF_INET6)
|
||||
{
|
||||
zlog_debug ("Old nexthops");
|
||||
nexthops6_print (rinfo_old->nexthops6);
|
||||
zlog_debug ("New nexthops");
|
||||
nexthops6_print (rinfo_new->nexthops6);
|
||||
}
|
||||
#endif /* EXTREME_DEBUG */
|
||||
isis_route_info_merge (rinfo_new, rinfo_old, family);
|
||||
isis_route_info_delete (rinfo_new);
|
||||
route_info = rinfo_old;
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
|
||||
zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
|
||||
route_info = rinfo_new;
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isis_route_info_prefer_new (rinfo_new, rinfo_old))
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
|
||||
buff);
|
||||
isis_route_info_delete (rinfo_old);
|
||||
route_info = rinfo_new;
|
||||
}
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
|
||||
buff);
|
||||
if (isis_route_info_same (rinfo_new, rinfo_old, family))
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
|
||||
buff);
|
||||
isis_route_info_delete (rinfo_new);
|
||||
route_info = rinfo_old;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,
|
||||
buff);
|
||||
isis_route_info_delete (rinfo_new);
|
||||
route_info = rinfo_old;
|
||||
}
|
||||
{
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
|
||||
buff);
|
||||
isis_route_info_delete (rinfo_old);
|
||||
route_info = rinfo_new;
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
}
|
||||
|
||||
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
||||
@ -570,7 +498,7 @@ isis_route_delete (struct prefix *prefix, struct route_table *table)
|
||||
return;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
|
||||
if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
{
|
||||
UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
@ -600,10 +528,12 @@ isis_route_validate_table (struct isis_area *area, struct route_table *table)
|
||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||
{
|
||||
prefix2str (&rnode->p, (char *) buff, BUFSIZ);
|
||||
zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
|
||||
zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
|
||||
area->area_tag,
|
||||
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
|
||||
"sync'ed" : "nosync"),
|
||||
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
|
||||
"synced" : "not-synced"),
|
||||
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
|
||||
"resync" : "not-resync"),
|
||||
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
|
||||
"active" : "inactive"), buff);
|
||||
}
|
||||
@ -706,41 +636,55 @@ isis_route_validate_merge (struct isis_area *area, int family)
|
||||
|
||||
/* Walk through route tables and propagate necessary changes into RIB. In case
|
||||
* of L1L2 area, level tables have to be merged at first. */
|
||||
int
|
||||
isis_route_validate (struct thread *thread)
|
||||
void
|
||||
isis_route_validate (struct isis_area *area)
|
||||
{
|
||||
struct isis_area *area;
|
||||
|
||||
area = THREAD_ARG (thread);
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
if (area->is_type == IS_LEVEL_1)
|
||||
{
|
||||
isis_route_validate_table (area, area->route_table[0]);
|
||||
goto validate_ipv6;
|
||||
}
|
||||
if (area->is_type == IS_LEVEL_2)
|
||||
{
|
||||
isis_route_validate_table (area, area->route_table[1]);
|
||||
goto validate_ipv6;
|
||||
}
|
||||
isis_route_validate_table (area, area->route_table[0]);
|
||||
else if (area->is_type == IS_LEVEL_2)
|
||||
isis_route_validate_table (area, area->route_table[1]);
|
||||
else
|
||||
isis_route_validate_merge (area, AF_INET);
|
||||
|
||||
isis_route_validate_merge (area, AF_INET);
|
||||
|
||||
validate_ipv6:
|
||||
#ifdef HAVE_IPV6
|
||||
if (area->is_type == IS_LEVEL_1)
|
||||
{
|
||||
isis_route_validate_table (area, area->route_table6[0]);
|
||||
return ISIS_OK;
|
||||
}
|
||||
if (area->is_type == IS_LEVEL_2)
|
||||
{
|
||||
isis_route_validate_table (area, area->route_table6[1]);
|
||||
return ISIS_OK;
|
||||
}
|
||||
|
||||
isis_route_validate_merge (area, AF_INET6);
|
||||
isis_route_validate_table (area, area->route_table6[0]);
|
||||
else if (area->is_type == IS_LEVEL_2)
|
||||
isis_route_validate_table (area, area->route_table6[1]);
|
||||
else
|
||||
isis_route_validate_merge (area, AF_INET6);
|
||||
#endif
|
||||
|
||||
return ISIS_OK;
|
||||
/* walk all circuits and reset any spf specific flags */
|
||||
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
|
||||
UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
isis_route_invalidate_table (struct isis_area *area, struct route_table *table)
|
||||
{
|
||||
struct route_node *rode;
|
||||
struct isis_route_info *rinfo;
|
||||
for (rode = route_top (table); rode; rode = route_next (rode))
|
||||
{
|
||||
if (rode->info == NULL)
|
||||
continue;
|
||||
rinfo = rode->info;
|
||||
|
||||
UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isis_route_invalidate (struct isis_area *area)
|
||||
{
|
||||
if (area->is_type & IS_LEVEL_1)
|
||||
isis_route_invalidate_table (area, area->route_table[0]);
|
||||
if (area->is_type & IS_LEVEL_2)
|
||||
isis_route_invalidate_table (area, area->route_table[1]);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ struct isis_nexthop6
|
||||
{
|
||||
unsigned int ifindex;
|
||||
struct in6_addr ip6;
|
||||
struct in6_addr router_address6;
|
||||
unsigned int lock;
|
||||
};
|
||||
#endif /* HAVE_IPV6 */
|
||||
@ -38,13 +39,15 @@ struct isis_nexthop
|
||||
{
|
||||
unsigned int ifindex;
|
||||
struct in_addr ip;
|
||||
struct in_addr router_address;
|
||||
unsigned int lock;
|
||||
};
|
||||
|
||||
struct isis_route_info
|
||||
{
|
||||
#define ISIS_ROUTE_FLAG_ZEBRA_SYNC 0x01
|
||||
#define ISIS_ROUTE_FLAG_ACTIVE 0x02
|
||||
#define ISIS_ROUTE_FLAG_ACTIVE 0x01 /* active route for the prefix */
|
||||
#define ISIS_ROUTE_FLAG_ZEBRA_SYNCED 0x02 /* set when route synced to zebra */
|
||||
#define ISIS_ROUTE_FLAG_ZEBRA_RESYNC 0x04 /* set when route needs to sync */
|
||||
u_char flag;
|
||||
u_int32_t cost;
|
||||
u_int32_t depth;
|
||||
@ -59,6 +62,9 @@ struct isis_route_info *isis_route_create (struct prefix *prefix,
|
||||
struct list *adjacencies,
|
||||
struct isis_area *area, int level);
|
||||
|
||||
int isis_route_validate (struct thread *thread);
|
||||
void isis_route_validate (struct isis_area *area);
|
||||
void isis_route_invalidate_table (struct isis_area *area,
|
||||
struct route_table *table);
|
||||
void isis_route_invalidate (struct isis_area *area);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_ROUTE_H */
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "isis_constants.h"
|
||||
#include "isis_common.h"
|
||||
#include "isis_flags.h"
|
||||
#include "dict.h"
|
||||
#include "isisd.h"
|
||||
#include "isis_misc.h"
|
||||
|
1158
isisd/isis_spf.c
1158
isisd/isis_spf.c
File diff suppressed because it is too large
Load Diff
@ -54,25 +54,33 @@ struct isis_vertex
|
||||
struct prefix prefix;
|
||||
} N;
|
||||
|
||||
struct isis_lsp *lsp;
|
||||
u_int32_t d_N; /* d(N) Distance from this IS */
|
||||
u_int16_t depth; /* The depth in the imaginary tree */
|
||||
|
||||
struct list *Adj_N; /* {Adj(N)} */
|
||||
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
|
||||
struct list *parents; /* list of parents for ECMP */
|
||||
struct list *children; /* list of children used for tree dump */
|
||||
};
|
||||
|
||||
struct isis_spftree
|
||||
{
|
||||
struct thread *t_spf; /* spf threads */
|
||||
time_t lastrun; /* for scheduling */
|
||||
int pending; /* already scheduled */
|
||||
struct list *paths; /* the SPT */
|
||||
struct list *tents; /* TENT */
|
||||
|
||||
u_int32_t timerun; /* statistics */
|
||||
struct isis_area *area; /* back pointer to area */
|
||||
int pending; /* already scheduled */
|
||||
unsigned int runcount; /* number of runs since uptime */
|
||||
time_t last_run_timestamp; /* last run timestamp for scheduling */
|
||||
time_t last_run_duration; /* last run duration in msec */
|
||||
};
|
||||
|
||||
struct isis_spftree * isis_spftree_new (struct isis_area *area);
|
||||
void isis_spftree_del (struct isis_spftree *spftree);
|
||||
void isis_spftree_adj_del (struct isis_spftree *spftree,
|
||||
struct isis_adjacency *adj);
|
||||
void spftree_area_init (struct isis_area *area);
|
||||
void spftree_area_del (struct isis_area *area);
|
||||
void spftree_area_adj_del (struct isis_area *area,
|
||||
struct isis_adjacency *adj);
|
||||
int isis_spf_schedule (struct isis_area *area, int level);
|
||||
void isis_spf_cmds_init (void);
|
||||
#ifdef HAVE_IPV6
|
||||
|
@ -43,13 +43,6 @@
|
||||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
|
||||
/*
|
||||
* Prototypes.
|
||||
*/
|
||||
int add_tlv (u_char, u_char, u_char *, struct stream *);
|
||||
|
||||
void
|
||||
free_tlv (void *val)
|
||||
{
|
||||
@ -75,10 +68,10 @@ free_tlvs (struct tlvs *tlvs)
|
||||
list_delete (tlvs->es_neighs);
|
||||
if (tlvs->lsp_entries)
|
||||
list_delete (tlvs->lsp_entries);
|
||||
if (tlvs->lan_neighs)
|
||||
list_delete (tlvs->lan_neighs);
|
||||
if (tlvs->prefix_neighs)
|
||||
list_delete (tlvs->prefix_neighs);
|
||||
if (tlvs->lan_neighs)
|
||||
list_delete (tlvs->lan_neighs);
|
||||
if (tlvs->ipv4_addrs)
|
||||
list_delete (tlvs->ipv4_addrs);
|
||||
if (tlvs->ipv4_int_reachs)
|
||||
@ -93,7 +86,9 @@ free_tlvs (struct tlvs *tlvs)
|
||||
if (tlvs->ipv6_reachs)
|
||||
list_delete (tlvs->ipv6_reachs);
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
|
||||
memset (tlvs, 0, sizeof (struct tlvs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,7 +98,7 @@ free_tlvs (struct tlvs *tlvs)
|
||||
*/
|
||||
int
|
||||
parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
|
||||
u_int32_t * found, struct tlvs *tlvs)
|
||||
u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset)
|
||||
{
|
||||
u_char type, length;
|
||||
struct lan_neigh *lan_nei;
|
||||
@ -122,7 +117,7 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
|
||||
#endif /* HAVE_IPV6 */
|
||||
u_char virtual;
|
||||
int value_len, retval = ISIS_OK;
|
||||
u_char *pnt = stream;
|
||||
u_char *start = stream, *pnt = stream;
|
||||
|
||||
*found = 0;
|
||||
memset (tlvs, 0, sizeof (struct tlvs));
|
||||
@ -443,14 +438,22 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
|
||||
if (*expected & TLVFLAG_AUTH_INFO)
|
||||
{
|
||||
tlvs->auth_info.type = *pnt;
|
||||
tlvs->auth_info.len = length-1;
|
||||
if (length == 0)
|
||||
{
|
||||
zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) "
|
||||
"incorrect.", areatag, type, length);
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
--length;
|
||||
tlvs->auth_info.len = length;
|
||||
pnt++;
|
||||
memcpy (tlvs->auth_info.passwd, pnt, length - 1);
|
||||
/* Fill authentication with 0 for later computation
|
||||
* of MD5 (RFC 5304, 2)
|
||||
*/
|
||||
memset (pnt, 0, length - 1);
|
||||
pnt += length - 1;
|
||||
memcpy (tlvs->auth_info.passwd, pnt, length);
|
||||
/* Return the authentication tlv pos for later computation
|
||||
* of MD5 (RFC 5304, 2)
|
||||
*/
|
||||
if (auth_tlv_offset)
|
||||
*auth_tlv_offset += (pnt - start - 3);
|
||||
pnt += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -734,10 +737,14 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
|
||||
int
|
||||
add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
|
||||
{
|
||||
|
||||
if (STREAM_SIZE (stream) - stream_get_endp (stream) < (unsigned) len + 2)
|
||||
if ((stream_get_size (stream) - stream_get_endp (stream)) <
|
||||
(((unsigned)len) + 2))
|
||||
{
|
||||
zlog_warn ("No room for TLV of type %d", tag);
|
||||
zlog_warn ("No room for TLV of type %d "
|
||||
"(total size %d available %d required %d)",
|
||||
tag, (int)stream_get_size (stream),
|
||||
(int)(stream_get_size (stream) - stream_get_endp (stream)),
|
||||
len+2);
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
|
||||
@ -745,7 +752,7 @@ add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
|
||||
stream_putc (stream, len); /* LENGTH */
|
||||
stream_put (stream, value, (int) len); /* VALUE */
|
||||
|
||||
#ifdef EXTREME_TLV_DEBUG
|
||||
#ifdef EXTREME_DEBUG
|
||||
zlog_debug ("Added TLV %d len %d", tag, len);
|
||||
#endif /* EXTREME DEBUG */
|
||||
return ISIS_OK;
|
||||
@ -877,7 +884,7 @@ tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
|
||||
}
|
||||
|
||||
int
|
||||
tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
|
||||
tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value,
|
||||
struct stream *stream)
|
||||
{
|
||||
u_char value[255];
|
||||
@ -1006,7 +1013,6 @@ tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
|
||||
pos += IPV4_MAX_BYTELEN;
|
||||
}
|
||||
|
||||
|
||||
return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
|
||||
}
|
||||
|
||||
@ -1027,7 +1033,7 @@ tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
|
||||
if (pos - value + (5 + prefix_size) > 255)
|
||||
{
|
||||
retval =
|
||||
add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
|
||||
add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
|
||||
if (retval != ISIS_OK)
|
||||
return retval;
|
||||
pos = value;
|
||||
@ -1110,7 +1116,7 @@ tlv_add_padding (struct stream *stream)
|
||||
/*
|
||||
* How many times can we add full padding ?
|
||||
*/
|
||||
fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
|
||||
fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257;
|
||||
for (i = 0; i < fullpads; i++)
|
||||
{
|
||||
if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
|
||||
@ -1120,7 +1126,7 @@ tlv_add_padding (struct stream *stream)
|
||||
stream_put (stream, NULL, 255); /* zero padding */
|
||||
}
|
||||
|
||||
left = STREAM_SIZE (stream) - stream_get_endp (stream);
|
||||
left = stream_get_size (stream) - stream_get_endp (stream);
|
||||
|
||||
if (left < 2)
|
||||
return ISIS_OK;
|
||||
|
@ -30,7 +30,7 @@
|
||||
* Name Value IIH LSP SNP Status
|
||||
* LAN
|
||||
* ____________________________________________________________________________
|
||||
*
|
||||
*
|
||||
* Area Addresses 1 y y n ISO10589
|
||||
* IIS Neighbors 2 n y n ISO10589
|
||||
* ES Neighbors 3 n y n ISO10589
|
||||
@ -39,52 +39,52 @@
|
||||
* LSP Entries 9 n n y ISO10589
|
||||
* Authentication 10 y y y ISO10589, RFC3567
|
||||
* Checksum 12 y n y RFC3358
|
||||
* TE IS Reachability 22 n y n RFC3784
|
||||
* TE IS Reachability 22 n y n RFC5305
|
||||
* IS Alias 24 n y n RFC3786
|
||||
* IP Int. Reachability 128 n y n RFC1195
|
||||
* Protocols Supported 129 y y n RFC1195
|
||||
* IP Ext. Reachability 130 n y n RFC1195
|
||||
* IDRPI 131 n y y RFC1195
|
||||
* IP Interface Address 132 y y n RFC1195
|
||||
* TE Router ID 134 n y n RFC3784
|
||||
* Extended IP Reachability 135 n y n RFC3784
|
||||
* TE Router ID 134 n y n RFC5305
|
||||
* Extended IP Reachability 135 n y n RFC5305
|
||||
* Dynamic Hostname 137 n y n RFC2763
|
||||
* Shared Risk Link Group 138 n y y draft-ietf-isis-gmpls-extensions
|
||||
* Shared Risk Link Group 138 n y y RFC5307
|
||||
* Restart TLV 211 y n n RFC3847
|
||||
* MT IS Reachability 222 n y n draft-ietf-isis-wg-multi-topology
|
||||
* MT Supported 229 y y n draft-ietf-isis-wg-multi-topology
|
||||
* IPv6 Interface Address 232 y y n draft-ietf-isis_ipv6
|
||||
* MT IP Reachability 235 n y n draft-ietf-isis-wg-multi-topology
|
||||
* IPv6 IP Reachability 236 n y n draft-ietf-isis_ipv6
|
||||
* MT IPv6 IP Reachability 237 n y n draft-ietf-isis-wg-multi-topology
|
||||
* MT IS Reachability 222 n y n RFC5120
|
||||
* MT Supported 229 y y n RFC5120
|
||||
* IPv6 Interface Address 232 y y n RFC5308
|
||||
* MT IP Reachability 235 n y n RFC5120
|
||||
* IPv6 IP Reachability 236 n y n RFC5308
|
||||
* MT IPv6 IP Reachability 237 n y n RFC5120
|
||||
* P2P Adjacency State 240 y n n RFC3373
|
||||
* IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence
|
||||
* Router Capability 242 - - - draft-ietf-isis-caps
|
||||
*
|
||||
*
|
||||
*
|
||||
* IS Reachability sub-TLVs we (should) support.
|
||||
* ____________________________________________________________________________
|
||||
* Name Value Status
|
||||
* ____________________________________________________________________________
|
||||
* Administartive group (color) 3 RFC3784
|
||||
* Link Local/Remote Identifiers 4 draft-ietf-isis-gmpls-extensions
|
||||
* IPv4 interface address 6 RFC3784
|
||||
* IPv4 neighbor address 8 RFC3784
|
||||
* Maximum link bandwidth 9 RFC3784
|
||||
* Reservable link bandwidth 10 RFC3784
|
||||
* Unreserved bandwidth 11 RFC3784
|
||||
* TE Default metric 18 RFC3784
|
||||
* Link Protection Type 20 draft-ietf-isis-gmpls-extensions
|
||||
* Interface Switching Capability 21 draft-ietf-isis-gmpls-extensions
|
||||
* Administartive group (color) 3 RFC5305
|
||||
* Link Local/Remote Identifiers 4 RFC5307
|
||||
* IPv4 interface address 6 RFC5305
|
||||
* IPv4 neighbor address 8 RFC5305
|
||||
* Maximum link bandwidth 9 RFC5305
|
||||
* Reservable link bandwidth 10 RFC5305
|
||||
* Unreserved bandwidth 11 RFC5305
|
||||
* TE Default metric 18 RFC5305
|
||||
* Link Protection Type 20 RFC5307
|
||||
* Interface Switching Capability 21 RFC5307
|
||||
*
|
||||
*
|
||||
*
|
||||
* IP Reachability sub-TLVs we (should) support.
|
||||
* ____________________________________________________________________________
|
||||
* Name Value Status
|
||||
* ____________________________________________________________________________
|
||||
* 32bit administrative tag 1 draft-ietf-isis-admin-tags
|
||||
* 64bit administrative tag 2 draft-ietf-isis-admin-tags
|
||||
* Management prefix color 117 draft-ietf-isis-wg-multi-topology
|
||||
* 32bit administrative tag 1 RFC5130
|
||||
* 64bit administrative tag 2 RFC5130
|
||||
* Management prefix color 117 RFC5120
|
||||
*/
|
||||
|
||||
#define AREA_ADDRESSES 1
|
||||
@ -110,11 +110,14 @@
|
||||
#define IPV6_REACHABILITY 236
|
||||
#define WAY3_HELLO 240
|
||||
|
||||
#define AUTH_INFO_HDRLEN 3
|
||||
|
||||
#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5)
|
||||
#define LAN_NEIGHBOURS_LEN 6
|
||||
#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */
|
||||
#define IPV4_REACH_LEN 12
|
||||
#define IPV6_REACH_LEN 22
|
||||
#define TE_IPV4_REACH_LEN 9
|
||||
|
||||
/* struct for neighbor */
|
||||
struct is_neigh
|
||||
@ -131,6 +134,15 @@ struct te_is_neigh
|
||||
u_char sub_tlvs_length;
|
||||
};
|
||||
|
||||
/* Decode and encode three-octet metric into host byte order integer */
|
||||
#define GET_TE_METRIC(t) \
|
||||
(((unsigned)(t)->te_metric[0]<<16) | ((t)->te_metric[1]<<8) | \
|
||||
(t)->te_metric[2])
|
||||
#define SET_TE_METRIC(t, m) \
|
||||
(((t)->te_metric[0] = (m) >> 16), \
|
||||
((t)->te_metric[1] = (m) >> 8), \
|
||||
((t)->te_metric[2] = (m)))
|
||||
|
||||
/* struct for es neighbors */
|
||||
struct es_neigh
|
||||
{
|
||||
@ -213,7 +225,6 @@ struct ipv6_reachability
|
||||
u_char prefix_len;
|
||||
u_char prefix[16];
|
||||
};
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
/* bits in control_info */
|
||||
#define CTRL_INFO_DIRECTION 0x80
|
||||
@ -223,12 +234,17 @@ struct ipv6_reachability
|
||||
#define DISTRIBUTION_INTERNAL 0
|
||||
#define DISTRIBUTION_EXTERNAL 1
|
||||
#define CTRL_INFO_SUBTLVS 0x20
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
/*
|
||||
* Pointer to each tlv type, filled by parse_tlvs()
|
||||
*/
|
||||
struct tlvs
|
||||
{
|
||||
struct checksum *checksum;
|
||||
struct hostname *hostname;
|
||||
struct nlpids *nlpids;
|
||||
struct te_router_id *router_id;
|
||||
struct list *area_addrs;
|
||||
struct list *is_neighs;
|
||||
struct list *te_is_neighs;
|
||||
@ -236,14 +252,10 @@ struct tlvs
|
||||
struct list *lsp_entries;
|
||||
struct list *prefix_neighs;
|
||||
struct list *lan_neighs;
|
||||
struct checksum *checksum;
|
||||
struct nlpids *nlpids;
|
||||
struct list *ipv4_addrs;
|
||||
struct list *ipv4_int_reachs;
|
||||
struct list *ipv4_ext_reachs;
|
||||
struct list *te_ipv4_reachs;
|
||||
struct hostname *hostname;
|
||||
struct te_router_id *router_id;
|
||||
#ifdef HAVE_IPV6
|
||||
struct list *ipv6_addrs;
|
||||
struct list *ipv6_reachs;
|
||||
@ -281,7 +293,9 @@ struct tlvs
|
||||
void init_tlvs (struct tlvs *tlvs, uint32_t expected);
|
||||
void free_tlvs (struct tlvs *tlvs);
|
||||
int parse_tlvs (char *areatag, u_char * stream, int size,
|
||||
u_int32_t * expected, u_int32_t * found, struct tlvs *tlvs);
|
||||
u_int32_t * expected, u_int32_t * found, struct tlvs *tlvs,
|
||||
u_int32_t * auth_tlv_offset);
|
||||
int add_tlv (u_char, u_char, u_char *, struct stream *);
|
||||
void free_tlv (void *val);
|
||||
|
||||
int tlv_add_area_addrs (struct list *area_addrs, struct stream *stream);
|
||||
@ -290,7 +304,7 @@ int tlv_add_te_is_neighs (struct list *te_is_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_checksum (struct checksum *checksum, struct stream *stream);
|
||||
int tlv_add_authinfo (char auth_type, char authlen, u_char *auth_value,
|
||||
int tlv_add_authinfo (u_char auth_type, u_char authlen, u_char *auth_value,
|
||||
struct stream *stream);
|
||||
int tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream);
|
||||
int tlv_add_in_addr (struct in_addr *, struct stream *stream, u_char tag);
|
||||
|
@ -36,30 +36,37 @@
|
||||
#include "isisd/dict.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_tlv.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_csm.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_route.h"
|
||||
#include "isisd/isis_zebra.h"
|
||||
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
extern struct thread_master *master;
|
||||
extern struct isis *isis;
|
||||
|
||||
struct in_addr router_id_zebra;
|
||||
|
||||
/* Router-id update message from zebra. */
|
||||
static int
|
||||
isis_router_id_update_zebra (int command, struct zclient *zclient,
|
||||
zebra_size_t length)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct prefix router_id;
|
||||
|
||||
zebra_router_id_update_read (zclient->ibuf,&router_id);
|
||||
router_id_zebra = router_id.u.prefix4;
|
||||
zebra_router_id_update_read (zclient->ibuf, &router_id);
|
||||
if (isis->router_id == router_id.u.prefix4.s_addr)
|
||||
return 0;
|
||||
|
||||
isis->router_id = router_id.u.prefix4.s_addr;
|
||||
for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
|
||||
if (listcount (area->area_addrs) > 0)
|
||||
lsp_regenerate_schedule (area, area->is_type, 0);
|
||||
|
||||
/* FIXME: Do we react somehow? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -100,53 +107,28 @@ isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
|
||||
zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
|
||||
|
||||
/* Cannot call if_delete because we should retain the pseudo interface
|
||||
in case there is configuration info attached to it. */
|
||||
if_delete_retain(ifp);
|
||||
|
||||
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
|
||||
|
||||
ifp->ifindex = IFINDEX_INTERNAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct interface *
|
||||
zebra_interface_if_lookup (struct stream *s)
|
||||
{
|
||||
char ifname_tmp[INTERFACE_NAMSIZ];
|
||||
|
||||
/* Read interface name. */
|
||||
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
|
||||
|
||||
/* And look it up. */
|
||||
return if_lookup_by_name_len(ifname_tmp,
|
||||
strnlen(ifname_tmp, INTERFACE_NAMSIZ));
|
||||
}
|
||||
|
||||
static int
|
||||
isis_zebra_if_state_up (int command, struct zclient *zclient,
|
||||
zebra_size_t length)
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = zebra_interface_if_lookup (zclient->ibuf);
|
||||
ifp = zebra_interface_state_read (zclient->ibuf);
|
||||
|
||||
if (!ifp)
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
if (if_is_operative (ifp))
|
||||
{
|
||||
zebra_interface_if_set_value (zclient->ibuf, ifp);
|
||||
/* HT: This is wrong actually. We can't assume that circuit exist
|
||||
* if we delete circuit during if_state_down event. Needs rethink.
|
||||
* TODO */
|
||||
isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
zebra_interface_if_set_value (zclient->ibuf, ifp);
|
||||
isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
|
||||
|
||||
return 0;
|
||||
@ -157,17 +139,17 @@ isis_zebra_if_state_down (int command, struct zclient *zclient,
|
||||
zebra_size_t length)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
ifp = zebra_interface_if_lookup (zclient->ibuf);
|
||||
ifp = zebra_interface_state_read (zclient->ibuf);
|
||||
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
if (if_is_operative (ifp))
|
||||
{
|
||||
zebra_interface_if_set_value (zclient->ibuf, ifp);
|
||||
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
|
||||
}
|
||||
circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
|
||||
ifp);
|
||||
if (circuit)
|
||||
SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -251,7 +233,7 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
|
||||
struct isis_nexthop *nexthop;
|
||||
struct listnode *node;
|
||||
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return;
|
||||
|
||||
if (zclient->redist[ZEBRA_ROUTE_ISIS])
|
||||
@ -307,7 +289,8 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
|
||||
|
||||
stream_putw_at (stream, 0, stream_get_endp (stream));
|
||||
zclient_send_message(zclient);
|
||||
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
|
||||
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +312,7 @@ isis_zebra_route_del_ipv4 (struct prefix *prefix,
|
||||
prefix4.prefix = prefix->u.prefix4;
|
||||
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
|
||||
}
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -347,7 +330,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
|
||||
struct listnode *node;
|
||||
struct prefix_ipv6 prefix6;
|
||||
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return;
|
||||
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
@ -410,7 +393,8 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
|
||||
prefix6.prefixlen = prefix->prefixlen;
|
||||
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
|
||||
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
|
||||
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
|
||||
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
}
|
||||
|
||||
XFREE (MTYPE_ISIS_TMP, nexthop_list);
|
||||
@ -431,7 +415,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
|
||||
struct listnode *node;
|
||||
struct prefix_ipv6 prefix6;
|
||||
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
|
||||
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return;
|
||||
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
@ -488,7 +472,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
|
||||
prefix6.prefixlen = prefix->prefixlen;
|
||||
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
|
||||
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
|
||||
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
|
||||
XFREE (MTYPE_ISIS_TMP, nexthop_list);
|
||||
|
1969
isisd/isisd.c
1969
isisd/isisd.c
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,7 @@ struct isis
|
||||
u_long process_id;
|
||||
int sysid_set;
|
||||
u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */
|
||||
u_int32_t router_id; /* Router ID from zebra */
|
||||
struct list *area_list; /* list of IS-IS areas */
|
||||
struct list *init_circ_list;
|
||||
struct list *nexthops; /* IPv4 next hops from this IS */
|
||||
@ -78,6 +79,8 @@ struct isis
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct isis *isis;
|
||||
|
||||
struct isis_area
|
||||
{
|
||||
struct isis *isis; /* back pointer */
|
||||
@ -92,11 +95,8 @@ struct isis_area
|
||||
struct list *circuit_list; /* IS-IS circuits */
|
||||
struct flags flags;
|
||||
struct thread *t_tick; /* LSP walker */
|
||||
struct thread *t_remove_aged;
|
||||
struct thread *t_lsp_l1_regenerate;
|
||||
struct thread *t_lsp_l2_regenerate;
|
||||
int lsp_regenerate_pending[ISIS_LEVELS];
|
||||
struct thread *t_lsp_refresh[ISIS_LEVELS];
|
||||
int lsp_regenerate_pending[ISIS_LEVELS];
|
||||
|
||||
/*
|
||||
* Configurables
|
||||
@ -114,6 +114,8 @@ struct isis_area
|
||||
struct list *area_addrs;
|
||||
u_int16_t max_lsp_lifetime[ISIS_LEVELS];
|
||||
char is_type; /* level-1 level-1-2 or level-2-only */
|
||||
/* are we overloaded? */
|
||||
char overload_bit;
|
||||
u_int16_t lsp_refresh[ISIS_LEVELS];
|
||||
/* minimum time allowed before lsp retransmission */
|
||||
u_int16_t lsp_gen_interval[ISIS_LEVELS];
|
||||
@ -122,6 +124,8 @@ struct isis_area
|
||||
/* the percentage of LSP mtu size used, before generating a new frag */
|
||||
int lsp_frag_threshold;
|
||||
int ip_circuits;
|
||||
/* logging adjacency changes? */
|
||||
u_char log_adj_changes;
|
||||
#ifdef HAVE_IPV6
|
||||
int ipv6_circuits;
|
||||
#endif /* HAVE_IPV6 */
|
||||
@ -130,14 +134,21 @@ struct isis_area
|
||||
|
||||
#ifdef TOPOLOGY_GENERATE
|
||||
struct list *topology;
|
||||
char topology_baseis[ISIS_SYS_ID_LEN]; /* IS for the first IS emulated. */
|
||||
u_char topology_baseis[ISIS_SYS_ID_LEN]; /* IS for the first IS emulated. */
|
||||
char *topology_basedynh; /* Dynamic hostname base. */
|
||||
char top_params[200]; /* FIXME: what is reasonable? */
|
||||
#endif /* TOPOLOGY_GENERATE */
|
||||
};
|
||||
|
||||
void isis_init (void);
|
||||
void isis_new(unsigned long);
|
||||
struct isis_area *isis_area_create(const char *);
|
||||
struct isis_area *isis_area_lookup (const char *);
|
||||
int isis_area_get (struct vty *vty, const char *area_tag);
|
||||
void print_debug(struct vty *, int, int);
|
||||
|
||||
/* Master of threads. */
|
||||
extern struct thread_master *master;
|
||||
|
||||
#define DEBUG_ADJ_PACKETS (1<<0)
|
||||
#define DEBUG_CHECKSUM_ERRORS (1<<1)
|
||||
@ -151,5 +162,6 @@ struct isis_area *isis_area_lookup (const char *);
|
||||
#define DEBUG_RTE_EVENTS (1<<9)
|
||||
#define DEBUG_EVENTS (1<<10)
|
||||
#define DEBUG_ZEBRA (1<<11)
|
||||
#define DEBUG_PACKET_DUMP (1<<12)
|
||||
|
||||
#endif /* ISISD_H */
|
||||
|
4
lib/if.c
4
lib/if.c
@ -146,7 +146,7 @@ if_delete_retain (struct interface *ifp)
|
||||
(*if_master.if_delete_hook) (ifp);
|
||||
|
||||
/* Free connected address list */
|
||||
list_delete (ifp->connected);
|
||||
list_delete_all_node (ifp->connected);
|
||||
}
|
||||
|
||||
/* Delete and free interface structure. */
|
||||
@ -157,6 +157,8 @@ if_delete (struct interface *ifp)
|
||||
|
||||
if_delete_retain(ifp);
|
||||
|
||||
list_free (ifp->connected);
|
||||
|
||||
XFREE (MTYPE_IF, ifp);
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,9 @@ struct list
|
||||
void (*del) (void *val);
|
||||
};
|
||||
|
||||
#define listnextnode(X) ((X)->next)
|
||||
#define listhead(X) ((X)->head)
|
||||
#define listtail(X) ((X)->tail)
|
||||
#define listnextnode(X) ((X) ? ((X)->next) : NULL)
|
||||
#define listhead(X) ((X) ? ((X)->head) : NULL)
|
||||
#define listtail(X) ((X) ? ((X)->tail) : NULL)
|
||||
#define listcount(X) ((X)->count)
|
||||
#define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL)
|
||||
#define listgetdata(X) (assert((X)->data != NULL), (X)->data)
|
||||
@ -88,10 +88,10 @@ extern void list_add_list (struct list *, struct list *);
|
||||
* It is safe to delete the listnode using this macro.
|
||||
*/
|
||||
#define ALL_LIST_ELEMENTS(list,node,nextnode,data) \
|
||||
(node) = listhead(list); \
|
||||
(node) = listhead(list), ((data) = NULL); \
|
||||
(node) != NULL && \
|
||||
((data) = listgetdata(node),(nextnode) = listnextnode(node), 1); \
|
||||
(node) = (nextnode)
|
||||
(node) = (nextnode), ((data) = NULL)
|
||||
|
||||
/* read-only list iteration macro.
|
||||
* Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only
|
||||
@ -100,9 +100,9 @@ extern void list_add_list (struct list *, struct list *);
|
||||
* of previous macro.
|
||||
*/
|
||||
#define ALL_LIST_ELEMENTS_RO(list,node,data) \
|
||||
(node) = listhead(list); \
|
||||
(node) = listhead(list), ((data) = NULL);\
|
||||
(node) != NULL && ((data) = listgetdata(node), 1); \
|
||||
(node) = listnextnode(node)
|
||||
(node) = listnextnode(node), ((data) = NULL)
|
||||
|
||||
/* these *do not* cleanup list nodes and referenced data, as the functions
|
||||
* do - these macros simply {de,at}tach a listnode from/to a list.
|
||||
|
@ -83,6 +83,7 @@ do { \
|
||||
} while (0)
|
||||
|
||||
/* From RFC 2104 */
|
||||
void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, caddr_t digest);
|
||||
void hmac_md5(unsigned char* text, int text_len, unsigned char* key,
|
||||
int key_len, caddr_t digest);
|
||||
|
||||
#endif /* ! _LIBZEBRA_MD5_H_*/
|
||||
|
@ -248,6 +248,8 @@ struct memory_list memory_list_isis[] =
|
||||
{ MTYPE_ISIS_ROUTE_INFO, "ISIS route info" },
|
||||
{ MTYPE_ISIS_NEXTHOP, "ISIS nexthop" },
|
||||
{ MTYPE_ISIS_NEXTHOP6, "ISIS nexthop6" },
|
||||
{ MTYPE_ISIS_DICT, "ISIS dictionary" },
|
||||
{ MTYPE_ISIS_DICT_NODE, "ISIS dictionary node" },
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
|
20
lib/stream.c
20
lib/stream.c
@ -52,7 +52,7 @@
|
||||
* using stream_put..._at() functions.
|
||||
*/
|
||||
#define STREAM_WARN_OFFSETS(S) \
|
||||
zlog_warn ("&(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \
|
||||
zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
|
||||
(S), \
|
||||
(unsigned long) (S)->size, \
|
||||
(unsigned long) (S)->getp, \
|
||||
@ -214,6 +214,20 @@ stream_set_getp (struct stream *s, size_t pos)
|
||||
s->getp = pos;
|
||||
}
|
||||
|
||||
void
|
||||
stream_set_endp (struct stream *s, size_t pos)
|
||||
{
|
||||
STREAM_VERIFY_SANE(s);
|
||||
|
||||
if (!GETP_VALID (s, pos))
|
||||
{
|
||||
STREAM_BOUND_WARN (s, "set endp");
|
||||
pos = s->endp;
|
||||
}
|
||||
|
||||
s->endp = pos;
|
||||
}
|
||||
|
||||
/* Forward pointer. */
|
||||
void
|
||||
stream_forward_getp (struct stream *s, size_t size)
|
||||
@ -934,9 +948,9 @@ stream_fifo_pop (struct stream_fifo *fifo)
|
||||
|
||||
if (fifo->head == NULL)
|
||||
fifo->tail = NULL;
|
||||
}
|
||||
|
||||
fifo->count--;
|
||||
fifo->count--;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ extern size_t stream_get_size (struct stream *);
|
||||
extern u_char *stream_get_data (struct stream *);
|
||||
|
||||
extern void stream_set_getp (struct stream *, size_t);
|
||||
extern void stream_set_endp (struct stream *, size_t);
|
||||
extern void stream_forward_getp (struct stream *, size_t);
|
||||
extern void stream_forward_endp (struct stream *, size_t);
|
||||
|
||||
|
@ -654,24 +654,8 @@ zebra_interface_add_read (struct stream *s)
|
||||
/* Lookup/create interface by name. */
|
||||
ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));
|
||||
|
||||
/* Read interface's index. */
|
||||
ifp->ifindex = stream_getl (s);
|
||||
zebra_interface_if_set_value (s, ifp);
|
||||
|
||||
/* Read interface's value. */
|
||||
ifp->status = stream_getc (s);
|
||||
ifp->flags = stream_getq (s);
|
||||
ifp->metric = stream_getl (s);
|
||||
ifp->mtu = stream_getl (s);
|
||||
ifp->mtu6 = stream_getl (s);
|
||||
ifp->bandwidth = stream_getl (s);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_DL
|
||||
stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
|
||||
#else
|
||||
ifp->hw_addr_len = stream_getl (s);
|
||||
if (ifp->hw_addr_len)
|
||||
stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_DL */
|
||||
|
||||
return ifp;
|
||||
}
|
||||
|
||||
@ -699,16 +683,7 @@ zebra_interface_state_read (struct stream *s)
|
||||
if (! ifp)
|
||||
return NULL;
|
||||
|
||||
/* Read interface's index. */
|
||||
ifp->ifindex = stream_getl (s);
|
||||
|
||||
/* Read interface's value. */
|
||||
ifp->status = stream_getc (s);
|
||||
ifp->flags = stream_getq (s);
|
||||
ifp->metric = stream_getl (s);
|
||||
ifp->mtu = stream_getl (s);
|
||||
ifp->mtu6 = stream_getl (s);
|
||||
ifp->bandwidth = stream_getl (s);
|
||||
zebra_interface_if_set_value (s, ifp);
|
||||
|
||||
return ifp;
|
||||
}
|
||||
@ -758,6 +733,13 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
|
||||
ifp->mtu = stream_getl (s);
|
||||
ifp->mtu6 = stream_getl (s);
|
||||
ifp->bandwidth = stream_getl (s);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_DL
|
||||
stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
|
||||
#else
|
||||
ifp->hw_addr_len = stream_getl (s);
|
||||
if (ifp->hw_addr_len)
|
||||
stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_DL */
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -225,6 +225,10 @@ extern struct nexthop *nexthop_ifname_add (struct rib *, char *);
|
||||
extern struct nexthop *nexthop_blackhole_add (struct rib *);
|
||||
extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
|
||||
struct in_addr *);
|
||||
extern struct nexthop *nexthop_ipv4_ifindex_add (struct rib *,
|
||||
struct in_addr *,
|
||||
struct in_addr *,
|
||||
unsigned int);
|
||||
extern void rib_lookup_and_dump (struct prefix_ipv4 *);
|
||||
extern void rib_lookup_and_pushup (struct prefix_ipv4 *);
|
||||
extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "prefix.h"
|
||||
#include "connected.h"
|
||||
#include "table.h"
|
||||
#include "memory.h"
|
||||
#include "rib.h"
|
||||
#include "thread.h"
|
||||
#include "privs.h"
|
||||
@ -426,6 +427,37 @@ netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility function to parse hardware link-layer address and update ifp */
|
||||
static void
|
||||
netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (tb[IFLA_ADDRESS])
|
||||
{
|
||||
int hw_addr_len;
|
||||
|
||||
hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
|
||||
|
||||
if (hw_addr_len > INTERFACE_HWADDR_MAX)
|
||||
zlog_warn ("Hardware address is too large: %d", hw_addr_len);
|
||||
else
|
||||
{
|
||||
ifp->hw_addr_len = hw_addr_len;
|
||||
memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
|
||||
|
||||
for (i = 0; i < hw_addr_len; i++)
|
||||
if (ifp->hw_addr[i] != 0)
|
||||
break;
|
||||
|
||||
if (i == hw_addr_len)
|
||||
ifp->hw_addr_len = 0;
|
||||
else
|
||||
ifp->hw_addr_len = hw_addr_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from interface_lookup_netlink(). This function is only used
|
||||
during bootstrap. */
|
||||
static int
|
||||
@ -436,7 +468,6 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
struct rtattr *tb[IFLA_MAX + 1];
|
||||
struct interface *ifp;
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
ifi = NLMSG_DATA (h);
|
||||
|
||||
@ -474,30 +505,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
|
||||
/* Hardware type and address. */
|
||||
ifp->hw_type = ifi->ifi_type;
|
||||
|
||||
if (tb[IFLA_ADDRESS])
|
||||
{
|
||||
int hw_addr_len;
|
||||
|
||||
hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
|
||||
|
||||
if (hw_addr_len > INTERFACE_HWADDR_MAX)
|
||||
zlog_warn ("Hardware address is too large: %d", hw_addr_len);
|
||||
else
|
||||
{
|
||||
ifp->hw_addr_len = hw_addr_len;
|
||||
memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
|
||||
|
||||
for (i = 0; i < hw_addr_len; i++)
|
||||
if (ifp->hw_addr[i] != 0)
|
||||
break;
|
||||
|
||||
if (i == hw_addr_len)
|
||||
ifp->hw_addr_len = 0;
|
||||
else
|
||||
ifp->hw_addr_len = hw_addr_len;
|
||||
}
|
||||
}
|
||||
netlink_interface_update_hw_addr (tb, ifp);
|
||||
|
||||
if_add_update (ifp);
|
||||
|
||||
@ -709,7 +717,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
if (tb[RTA_PREFSRC])
|
||||
src = RTA_DATA (tb[RTA_PREFSRC]);
|
||||
|
||||
/* Multipath treatment is needed. */
|
||||
if (tb[RTA_GATEWAY])
|
||||
gate = RTA_DATA (tb[RTA_GATEWAY]);
|
||||
|
||||
@ -723,7 +730,64 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
memcpy (&p.prefix, dest, 4);
|
||||
p.prefixlen = rtm->rtm_dst_len;
|
||||
|
||||
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
|
||||
if (!tb[RTA_MULTIPATH])
|
||||
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
|
||||
table, metric, 0, SAFI_UNICAST);
|
||||
else
|
||||
{
|
||||
/* This is a multipath route */
|
||||
|
||||
struct rib *rib;
|
||||
struct rtnexthop *rtnh =
|
||||
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
|
||||
|
||||
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
|
||||
|
||||
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
|
||||
rib->type = ZEBRA_ROUTE_KERNEL;
|
||||
rib->distance = 0;
|
||||
rib->flags = flags;
|
||||
rib->metric = metric;
|
||||
rib->table = table;
|
||||
rib->nexthop_num = 0;
|
||||
rib->uptime = time (NULL);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
|
||||
break;
|
||||
|
||||
rib->nexthop_num++;
|
||||
index = rtnh->rtnh_ifindex;
|
||||
gate = 0;
|
||||
if (rtnh->rtnh_len > sizeof (*rtnh))
|
||||
{
|
||||
memset (tb, 0, sizeof (tb));
|
||||
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
|
||||
rtnh->rtnh_len - sizeof (*rtnh));
|
||||
if (tb[RTA_GATEWAY])
|
||||
gate = RTA_DATA (tb[RTA_GATEWAY]);
|
||||
}
|
||||
|
||||
if (gate)
|
||||
{
|
||||
if (index)
|
||||
nexthop_ipv4_ifindex_add (rib, gate, src, index);
|
||||
else
|
||||
nexthop_ipv4_add (rib, gate, src);
|
||||
}
|
||||
else
|
||||
nexthop_ifindex_add (rib, index);
|
||||
|
||||
len -= NLMSG_ALIGN(rtnh->rtnh_len);
|
||||
rtnh = RTNH_NEXT(rtnh);
|
||||
}
|
||||
|
||||
if (rib->nexthop_num == 0)
|
||||
XFREE (MTYPE_RIB, rib);
|
||||
else
|
||||
rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (rtm->rtm_family == AF_INET6)
|
||||
@ -867,7 +931,66 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
}
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWROUTE)
|
||||
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
|
||||
{
|
||||
if (!tb[RTA_MULTIPATH])
|
||||
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
|
||||
metric, 0, SAFI_UNICAST);
|
||||
else
|
||||
{
|
||||
/* This is a multipath route */
|
||||
|
||||
struct rib *rib;
|
||||
struct rtnexthop *rtnh =
|
||||
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
|
||||
|
||||
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
|
||||
|
||||
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
|
||||
rib->type = ZEBRA_ROUTE_KERNEL;
|
||||
rib->distance = 0;
|
||||
rib->flags = 0;
|
||||
rib->metric = metric;
|
||||
rib->table = table;
|
||||
rib->nexthop_num = 0;
|
||||
rib->uptime = time (NULL);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
|
||||
break;
|
||||
|
||||
rib->nexthop_num++;
|
||||
index = rtnh->rtnh_ifindex;
|
||||
gate = 0;
|
||||
if (rtnh->rtnh_len > sizeof (*rtnh))
|
||||
{
|
||||
memset (tb, 0, sizeof (tb));
|
||||
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
|
||||
rtnh->rtnh_len - sizeof (*rtnh));
|
||||
if (tb[RTA_GATEWAY])
|
||||
gate = RTA_DATA (tb[RTA_GATEWAY]);
|
||||
}
|
||||
|
||||
if (gate)
|
||||
{
|
||||
if (index)
|
||||
nexthop_ipv4_ifindex_add (rib, gate, src, index);
|
||||
else
|
||||
nexthop_ipv4_add (rib, gate, src);
|
||||
}
|
||||
else
|
||||
nexthop_ifindex_add (rib, index);
|
||||
|
||||
len -= NLMSG_ALIGN(rtnh->rtnh_len);
|
||||
rtnh = RTNH_NEXT(rtnh);
|
||||
}
|
||||
|
||||
if (rib->nexthop_num == 0)
|
||||
XFREE (MTYPE_RIB, rib);
|
||||
else
|
||||
rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
else
|
||||
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
|
||||
}
|
||||
@ -960,6 +1083,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
|
||||
ifp->metric = 1;
|
||||
|
||||
netlink_interface_update_hw_addr (tb, ifp);
|
||||
|
||||
/* If new link is added. */
|
||||
if_add_update (ifp);
|
||||
}
|
||||
@ -970,6 +1095,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
|
||||
ifp->metric = 1;
|
||||
|
||||
netlink_interface_update_hw_addr (tb, ifp);
|
||||
|
||||
if (if_is_operative (ifp))
|
||||
{
|
||||
ifp->flags = ifi->ifi_flags & 0x0000fffff;
|
||||
|
@ -232,7 +232,7 @@ nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
|
||||
return nexthop;
|
||||
}
|
||||
|
||||
static struct nexthop *
|
||||
struct nexthop *
|
||||
nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
|
||||
struct in_addr *src, unsigned int ifindex)
|
||||
{
|
||||
@ -1279,14 +1279,30 @@ rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
|
||||
static void
|
||||
rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
assert (zebra && rn);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB_Q)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
|
||||
|
||||
zlog_info ("%s: %s/%d: work queue added", __func__,
|
||||
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN),
|
||||
rn->p.prefixlen);
|
||||
/* Pointless to queue a route_node with no RIB entries to add or remove */
|
||||
if (!rn->info)
|
||||
{
|
||||
zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
|
||||
__func__, rn, rn->lock);
|
||||
zlog_backtrace(LOG_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB_Q)
|
||||
zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
|
||||
|
||||
assert (zebra);
|
||||
|
||||
if (zebra->ribq == NULL)
|
||||
{
|
||||
zlog_err ("%s: work_queue does not exist!", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1301,6 +1317,11 @@ rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
|
||||
work_queue_add (zebra->ribq, zebra->mq);
|
||||
|
||||
rib_meta_queue_add (zebra->mq, rn);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB_Q)
|
||||
zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create new meta queue.
|
||||
@ -1328,6 +1349,8 @@ meta_queue_new (void)
|
||||
static void
|
||||
rib_queue_init (struct zebra_t *zebra)
|
||||
{
|
||||
assert (zebra);
|
||||
|
||||
if (! (zebra->ribq = work_queue_new (zebra->master,
|
||||
"route_node processing")))
|
||||
{
|
||||
@ -1343,7 +1366,11 @@ rib_queue_init (struct zebra_t *zebra)
|
||||
zebra->ribq->spec.hold = rib_process_hold_time;
|
||||
|
||||
if (!(zebra->mq = meta_queue_new ()))
|
||||
{
|
||||
zlog_err ("%s: could not initialise meta queue!", __func__);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* RIB updates are processed via a queue of pointers to route_nodes.
|
||||
@ -2893,6 +2920,62 @@ rib_sweep_route (void)
|
||||
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
|
||||
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
|
||||
}
|
||||
|
||||
/* Delete routes learned from a given client. */
|
||||
/* TODO(wsun) May need to split the sweep process into multiple batches,
|
||||
* so that the process won't take too long if the table is large. */
|
||||
static void
|
||||
rib_sweep_client_table (struct route_table *table, int rib_type)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct rib *rib;
|
||||
struct rib *next;
|
||||
int ret = 0;
|
||||
|
||||
if (table)
|
||||
for (rn = route_top (table); rn; rn = route_next (rn))
|
||||
for (rib = rn->info; rib; rib = next)
|
||||
{
|
||||
next = rib->next;
|
||||
|
||||
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
||||
continue;
|
||||
|
||||
if (rib->type == rib_type)
|
||||
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
|
||||
{
|
||||
/* TODO(wsun) Is this mandatory? What about graceful restart/
|
||||
* non-stop forwarding */
|
||||
ret = rib_uninstall_kernel (rn, rib);
|
||||
if (! ret)
|
||||
rib_delnode (rn, rib);
|
||||
else
|
||||
zlog_err ("%s: could not delete routes from kernel!",
|
||||
__func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Always delete the node. */
|
||||
rib_delnode (rn, rib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sweep all routes learned from a given client from RIB tables. */
|
||||
void
|
||||
rib_sweep_client_route (struct zserv *client)
|
||||
{
|
||||
assert(client);
|
||||
int route_type = client->route_type;
|
||||
if (route_type != ZEBRA_ROUTE_MAX)
|
||||
{
|
||||
zlog_debug ("%s: Removing existing routes from client type %d",
|
||||
__func__, route_type);
|
||||
rib_sweep_client_table (vrf_table (AFI_IP, SAFI_UNICAST, 0), route_type);
|
||||
rib_sweep_client_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0), route_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Remove specific by protocol routes from 'table'. */
|
||||
static unsigned long
|
||||
|
113
zebra/zserv.c
113
zebra/zserv.c
@ -140,6 +140,30 @@ zserv_create_header (struct stream *s, uint16_t cmd)
|
||||
stream_putw (s, cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
zserv_encode_interface (struct stream *s, struct interface *ifp)
|
||||
{
|
||||
/* Interface information. */
|
||||
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
|
||||
stream_putl (s, ifp->ifindex);
|
||||
stream_putc (s, ifp->status);
|
||||
stream_putq (s, ifp->flags);
|
||||
stream_putl (s, ifp->metric);
|
||||
stream_putl (s, ifp->mtu);
|
||||
stream_putl (s, ifp->mtu6);
|
||||
stream_putl (s, ifp->bandwidth);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_DL
|
||||
stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
|
||||
#else
|
||||
stream_putl (s, ifp->hw_addr_len);
|
||||
if (ifp->hw_addr_len)
|
||||
stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_DL */
|
||||
|
||||
/* Write packet size. */
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
}
|
||||
|
||||
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
|
||||
/*
|
||||
* This function is called in the following situations:
|
||||
@ -163,28 +187,8 @@ zsend_interface_add (struct zserv *client, struct interface *ifp)
|
||||
s = client->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Message type. */
|
||||
zserv_create_header (s, ZEBRA_INTERFACE_ADD);
|
||||
|
||||
/* Interface information. */
|
||||
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
|
||||
stream_putl (s, ifp->ifindex);
|
||||
stream_putc (s, ifp->status);
|
||||
stream_putq (s, ifp->flags);
|
||||
stream_putl (s, ifp->metric);
|
||||
stream_putl (s, ifp->mtu);
|
||||
stream_putl (s, ifp->mtu6);
|
||||
stream_putl (s, ifp->bandwidth);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_DL
|
||||
stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
|
||||
#else
|
||||
stream_putl (s, ifp->hw_addr_len);
|
||||
if (ifp->hw_addr_len)
|
||||
stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_DL */
|
||||
|
||||
/* Write packet size. */
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
zserv_encode_interface (s, ifp);
|
||||
|
||||
return zebra_server_send_message(client);
|
||||
}
|
||||
@ -201,21 +205,9 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp)
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
|
||||
|
||||
/* Interface information. */
|
||||
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
|
||||
stream_putl (s, ifp->ifindex);
|
||||
stream_putc (s, ifp->status);
|
||||
stream_putq (s, ifp->flags);
|
||||
stream_putl (s, ifp->metric);
|
||||
stream_putl (s, ifp->mtu);
|
||||
stream_putl (s, ifp->mtu6);
|
||||
stream_putl (s, ifp->bandwidth);
|
||||
|
||||
/* Write packet length. */
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
|
||||
zserv_encode_interface (s, ifp);
|
||||
|
||||
return zebra_server_send_message (client);
|
||||
}
|
||||
@ -328,19 +320,7 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
|
||||
stream_reset (s);
|
||||
|
||||
zserv_create_header (s, cmd);
|
||||
|
||||
/* Interface information. */
|
||||
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
|
||||
stream_putl (s, ifp->ifindex);
|
||||
stream_putc (s, ifp->status);
|
||||
stream_putq (s, ifp->flags);
|
||||
stream_putl (s, ifp->metric);
|
||||
stream_putl (s, ifp->mtu);
|
||||
stream_putl (s, ifp->mtu6);
|
||||
stream_putl (s, ifp->bandwidth);
|
||||
|
||||
/* Write packet size. */
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
zserv_encode_interface (s, ifp);
|
||||
|
||||
return zebra_server_send_message(client);
|
||||
}
|
||||
@ -761,6 +741,13 @@ zread_ipv4_add (struct zserv *client, u_short length)
|
||||
|
||||
/* Type, flags, message. */
|
||||
rib->type = stream_getc (s);
|
||||
/* Update client's route type if it is not done yet. */
|
||||
/* It is done here since only zread_ipv4/6_add() and
|
||||
* zread_ipv4/6_delete() decode Zebra messages and retrieve
|
||||
* route types. */
|
||||
if (client->route_type == ZEBRA_ROUTE_MAX)
|
||||
client->route_type = rib->type;
|
||||
|
||||
rib->flags = stream_getc (s);
|
||||
message = stream_getc (s);
|
||||
safi = stream_getw (s);
|
||||
@ -798,10 +785,10 @@ zread_ipv4_add (struct zserv *client, u_short length)
|
||||
case ZEBRA_NEXTHOP_IPV6:
|
||||
stream_forward_getp (s, IPV6_MAX_BYTELEN);
|
||||
break;
|
||||
case ZEBRA_NEXTHOP_BLACKHOLE:
|
||||
nexthop_blackhole_add (rib);
|
||||
break;
|
||||
}
|
||||
case ZEBRA_NEXTHOP_BLACKHOLE:
|
||||
nexthop_blackhole_add (rib);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -826,7 +813,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
|
||||
int i;
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct in_addr nexthop;
|
||||
struct in_addr nexthop, *nexthop_p;
|
||||
unsigned long ifindex;
|
||||
struct prefix_ipv4 p;
|
||||
u_char nexthop_num;
|
||||
@ -836,6 +823,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
|
||||
s = client->ibuf;
|
||||
ifindex = 0;
|
||||
nexthop.s_addr = 0;
|
||||
nexthop_p = NULL;
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc (s);
|
||||
@ -869,6 +857,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
|
||||
break;
|
||||
case ZEBRA_NEXTHOP_IPV4:
|
||||
nexthop.s_addr = stream_get_ipv4 (s);
|
||||
nexthop_p = &nexthop;
|
||||
break;
|
||||
case ZEBRA_NEXTHOP_IPV6:
|
||||
stream_forward_getp (s, IPV6_MAX_BYTELEN);
|
||||
@ -889,7 +878,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
|
||||
else
|
||||
api.metric = 0;
|
||||
|
||||
rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
|
||||
rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
|
||||
client->rtm_table, api.safi);
|
||||
return 0;
|
||||
}
|
||||
@ -935,6 +924,11 @@ zread_ipv6_add (struct zserv *client, u_short length)
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc (s);
|
||||
/* Update the route type of the client.
|
||||
* Same as in zread_ipv4_add(). */
|
||||
if (client->route_type == ZEBRA_ROUTE_MAX)
|
||||
client->route_type = api.type;
|
||||
|
||||
api.flags = stream_getc (s);
|
||||
api.message = stream_getc (s);
|
||||
api.safi = stream_getw (s);
|
||||
@ -1133,6 +1127,14 @@ zebra_score_rib (int client_sock)
|
||||
static void
|
||||
zebra_client_close (struct zserv *client)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
/* Sweep all routes learned from the client first. */
|
||||
rib_sweep_client_route(client);
|
||||
/* Reset the route type. It may not be necessary since the
|
||||
* whole client will be freed. */
|
||||
client->route_type = ZEBRA_ROUTE_MAX;
|
||||
|
||||
/* Close file descriptor. */
|
||||
if (client->sock)
|
||||
{
|
||||
@ -1172,6 +1174,9 @@ zebra_client_create (int sock)
|
||||
|
||||
/* Make client input/output buffer. */
|
||||
client->sock = sock;
|
||||
/* Set the default route type to ZEBRA_ROUTE_MAX; it will be updated
|
||||
* once new routes are received. */
|
||||
client->route_type = ZEBRA_ROUTE_MAX;
|
||||
client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
|
||||
client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
|
||||
client->wb = buffer_new(0);
|
||||
|
@ -38,6 +38,10 @@ struct zserv
|
||||
/* Client file descriptor. */
|
||||
int sock;
|
||||
|
||||
/* Client route type. */
|
||||
/* Assuming each client contains only one type of route. */
|
||||
int route_type;
|
||||
|
||||
/* Input/output buffer to the client. */
|
||||
struct stream *ibuf;
|
||||
struct stream *obuf;
|
||||
|
Loading…
Reference in New Issue
Block a user