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:
David Lamparter 2012-04-16 18:24:40 +02:00
commit d75318cc8d
49 changed files with 7147 additions and 4075 deletions

View File

@ -1,3 +1,4 @@
Sampo Saaristo <sambo@cs.tut.fi> Sampo Saaristo <sambo@cs.tut.fi>
Ofer Wald <ofersf@islands.co.il> Ofer Wald <ofersf@islands.co.il>
Hannes Gredler <hannes@gredler.at> Hannes Gredler <hannes@gredler.at>
Subbaiah Venkata <svenkata@google.com>

View File

@ -15,17 +15,11 @@
* contain a copyright notice related to this source. * contain a copyright notice related to this source.
*/ */
#include <stdlib.h>
#include <stddef.h>
#include "zebra.h" #include "zebra.h"
#include "zassert.h" #include "zassert.h"
#define DICT_IMPLEMENTATION #include "memory.h"
#include "dict.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, * These macros provide short convenient names for structure members,
* which are embellished with dict_ prefixes so that they are * 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 *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) { if (new) {
new->compare = comp; new->compare = comp;
@ -284,7 +278,7 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
void dict_destroy(dict_t *dict) void dict_destroy(dict_t *dict)
{ {
assert (dict_isempty(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) void dict_free(dict_t *dict)
{ {
#ifdef KAZLIB_OBSOLESCENT_DEBUG
assert ("call to obsolescent function dict_free()" && 0);
#endif
dict_free_nodes(dict); 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) 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) { if (node) {
dnode_init(node, data); dnode_init(node, data);
@ -946,17 +937,17 @@ int dict_contains(dict_t *dict, dnode_t *node)
static dnode_t *dnode_alloc(void *context) 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) 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 *dnode_create(void *data)
{ {
dnode_t *new = malloc(sizeof *new); dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
if (new) { if (new) {
new->data = data; new->data = data;
new->parent = NULL; new->parent = NULL;
@ -978,7 +969,7 @@ dnode_t *dnode_init(dnode_t *dnode, void *data)
void dnode_destroy(dnode_t *dnode) void dnode_destroy(dnode_t *dnode)
{ {
assert (!dnode_is_in_a_dict(dnode)); assert (!dnode_is_in_a_dict(dnode));
free(dnode); XFREE(MTYPE_ISIS_DICT_NODE, dnode);
} }
void *dnode_get(dnode_t *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) static char *dupstring(char *str)
{ {
int sz = strlen(str) + 1; int sz = strlen(str) + 1;
char *new = malloc(sz); char *new = XCALLOC(MTYPE_ISIS_TMP, sz);
if (new) if (new)
memcpy(new, str, sz); memcpy(new, str, sz);
return new; return new;
@ -1347,7 +1338,7 @@ int main(void)
"s switch to non-functioning allocator\n" "s switch to non-functioning allocator\n"
"q quit"; "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); dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
for (;;) { for (;;) {

View File

@ -22,9 +22,6 @@
#define DICT_H #define DICT_H
#include <limits.h> #include <limits.h>
#ifdef KAZLIB_SIDEEFFECT_DEBUG
#include "sfx.h"
#endif
/* /*
* Blurb for inclusion into C++ translation units * 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 enum { dnode_red, dnode_black } dnode_color_t;
typedef struct dnode_t { typedef struct dnode_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
struct dnode_t *dict_left; struct dnode_t *dict_left;
struct dnode_t *dict_right; struct dnode_t *dict_right;
struct dnode_t *dict_parent; struct dnode_t *dict_parent;
dnode_color_t dict_color; dnode_color_t dict_color;
const void *dict_key; const void *dict_key;
void *dict_data; void *dict_data;
#else
int dict_dummy;
#endif
} dnode_t; } dnode_t;
typedef int (*dict_comp_t)(const void *, const void *); 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 void (*dnode_free_t)(dnode_t *, void *);
typedef struct dict_t { typedef struct dict_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
dnode_t dict_nilnode; dnode_t dict_nilnode;
dictcount_t dict_nodecount; dictcount_t dict_nodecount;
dictcount_t dict_maxcount; dictcount_t dict_maxcount;
@ -70,20 +62,13 @@ typedef struct dict_t {
dnode_free_t dict_freenode; dnode_free_t dict_freenode;
void *dict_context; void *dict_context;
int dict_dupes; int dict_dupes;
#else
int dict_dummmy;
#endif
} dict_t; } dict_t;
typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
typedef struct dict_load_t { typedef struct dict_load_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
dict_t *dict_dictptr; dict_t *dict_dictptr;
dnode_t dict_nilnode; dnode_t dict_nilnode;
#else
int dict_dummmy;
#endif
} dict_load_t; } dict_load_t;
extern dict_t *dict_create(dictcount_t, dict_comp_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_load_end(dict_load_t *);
extern void dict_merge(dict_t *, dict_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) #define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
#endif
#define dict_count(D) ((D)->dict_nodecount) #define dict_count(D) ((D)->dict_nodecount)
#define dict_isempty(D) ((D)->dict_nodecount == 0) #define dict_isempty(D) ((D)->dict_nodecount == 0)
#define dnode_get(N) ((N)->dict_data) #define dnode_get(N) ((N)->dict_data)
#define dnode_getkey(N) ((N)->dict_key) #define dnode_getkey(N) ((N)->dict_key)
#define dnode_put(N, X) ((N)->dict_data = (X)) #define dnode_put(N, X) ((N)->dict_data = (X))
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -36,6 +36,7 @@
#include "isisd/include-netbsd/iso.h" #include "isisd/include-netbsd/iso.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_common.h" #include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isisd.h" #include "isisd/isisd.h"
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isis_adjacency.h" #include "isisd/isis_adjacency.h"
@ -43,6 +44,10 @@
#include "isisd/isis_dr.h" #include "isisd/isis_dr.h"
#include "isisd/isis_dynhn.h" #include "isisd/isis_dynhn.h"
#include "isisd/isis_pdu.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; extern struct isis *isis;
@ -73,9 +78,9 @@ isis_new_adj (u_char * id, u_char * snpa, int level,
} }
if (snpa) { if (snpa) {
memcpy (adj->snpa, snpa, 6); memcpy (adj->snpa, snpa, ETH_ALEN);
} else { } else {
memset (adj->snpa, ' ', 6); memset (adj->snpa, ' ', ETH_ALEN);
} }
adj->circuit = circuit; adj->circuit = circuit;
@ -125,37 +130,60 @@ isis_adj_lookup_snpa (u_char * ssnpa, struct list *adjdb)
} }
void void
isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb) isis_delete_adj (void *arg)
{ {
struct isis_adjacency *adj = arg;
if (!adj) if (!adj)
return; 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) if (adj->ipv4_addrs)
list_delete (adj->ipv4_addrs); list_delete (adj->ipv4_addrs);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (adj->ipv6_addrs) if (adj->ipv6_addrs)
list_delete (adj->ipv6_addrs); list_delete (adj->ipv6_addrs);
#endif #endif
XFREE (MTYPE_ISIS_ADJACENCY, adj); XFREE (MTYPE_ISIS_ADJACENCY, adj);
return; 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 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) const char *reason)
{ {
int old_state; int old_state;
int level = adj->level; int level;
struct isis_circuit *circuit; struct isis_circuit *circuit;
old_state = adj->adj_state; old_state = adj->adj_state;
adj->adj_state = state; adj->adj_state = new_state;
circuit = adj->circuit; 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", zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
circuit->area->area_tag, 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 (circuit->circ_type == CIRCUIT_T_BROADCAST)
{ {
if (state == ISIS_ADJ_UP) for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
circuit->upadjcount[level - 1]++; {
if (state == ISIS_ADJ_DOWN) if ((adj->level & level) == 0)
{ continue;
listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj); if (new_state == ISIS_ADJ_UP)
circuit->upadjcount[level - 1]--; {
} 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]); if (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]); list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
} isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
else if (state == ISIS_ADJ_UP) circuit->u.bc.lan_neighs[level - 1]);
{ /* p2p interface */ }
if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
send_hello (circuit, 1);
/* update counter & timers for debugging purposes */ /* On adjacency state change send new pseudo LSP if we are the DR */
adj->last_flap = time (NULL); if (circuit->u.bc.is_dr[level - 1])
adj->flaps++; 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 */ if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
/* FIXME: yup, I know its wrong... but i will do it! (for now) */ send_hello (circuit, level);
send_csnp (circuit, 1);
send_csnp (circuit, 2); /* update counter & timers for debugging purposes */
} adj->last_flap = time (NULL);
else if (state == ISIS_ADJ_DOWN) adj->flaps++;
{ /* p2p interface */
adj->circuit->u.p2p.neighbor = NULL; /* 7.3.17 - going up on P2P -> send CSNP */
isis_delete_adj (adj, NULL); /* 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; return;
} }
@ -225,7 +318,7 @@ isis_adj_print (struct isis_adjacency *adj)
snpa_print (adj->snpa), adj->level, adj->hold_time); snpa_print (adj->snpa), adj->level, adj->hold_time);
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) 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)) for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr))
zlog_debug ("%s", inet_ntoa (*ipv4_addr)); zlog_debug ("%s", inet_ntoa (*ipv4_addr));
@ -234,7 +327,7 @@ isis_adj_print (struct isis_adjacency *adj)
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) 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)) for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
{ {
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
@ -251,14 +344,12 @@ int
isis_adj_expire (struct thread *thread) isis_adj_expire (struct thread *thread)
{ {
struct isis_adjacency *adj; struct isis_adjacency *adj;
int level;
/* /*
* Get the adjacency * Get the adjacency
*/ */
adj = THREAD_ARG (thread); adj = THREAD_ARG (thread);
assert (adj); assert (adj);
level = adj->level;
adj->t_expire = NULL; adj->t_expire = NULL;
/* trigger the adj expire event */ /* trigger the adj expire event */
@ -267,32 +358,12 @@ isis_adj_expire (struct thread *thread)
return 0; 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 void
isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail) isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail)
{ {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct in6_addr *ipv6_addr; struct in6_addr *ipv6_addr;
u_char ip6[INET6_ADDRSTRLEN]; 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) if (detail == ISIS_UI_LEVEL_DETAIL)
{ {
level = adj->level; level = adj->level;
vty_out (vty, "%s", VTY_NEWLINE);
if (adj->circuit) 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 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, ", Level: %u", adj->level); /* level */
vty_out (vty, ", State: %s", adj_state2string (adj->adj_state)); vty_out (vty, ", State: %s", adj_state2string (adj->adj_state));
now = time (NULL); 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)); time2string (adj->last_upd + adj->hold_time - now));
else else
vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); 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, ", Last: %s ago", time2string (now - adj->last_flap));
vty_out (vty, "%s Circuit type: %s", vty_out (vty, "%s", VTY_NEWLINE);
VTY_NEWLINE, circuit_t2string (adj->circuit_t)); vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t));
vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids));
vty_out (vty, "%s SNPA: %s", VTY_NEWLINE, snpa_print (adj->snpa)); vty_out (vty, "%s", VTY_NEWLINE);
dyn = dynhn_find_by_id (adj->lanid); vty_out (vty, " SNPA: %s", snpa_print (adj->snpa));
if (dyn) if (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)
vty_out (vty, ", LAN id: %s.%02x", {
dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); dyn = dynhn_find_by_id (adj->lanid);
else if (dyn)
vty_out (vty, ", LAN id: %s.%02x", vty_out (vty, ", LAN id: %s.%02x",
sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); 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_out (vty, "%s", VTY_NEWLINE);
VTY_NEWLINE, adj->prio[adj->level - 1]); vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]);
vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s", vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago",
isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1].
dis), adj->dischanges[level - 1], dis), adj->dischanges[level - 1],
time2string (now - time2string (now -
(adj->dis_record[ISIS_LEVELS + level - 1]. (adj->dis_record[ISIS_LEVELS + level - 1].
last_dis_change)), VTY_NEWLINE); 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) 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)) for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr))
vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE); vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE);
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) 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)) for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
{ {
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); 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; 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 void
isis_adj_build_neigh_list (struct list *adjdb, struct list *list) isis_adj_build_neigh_list (struct list *adjdb, struct list *list)
{ {

View File

@ -44,6 +44,7 @@ enum isis_system_type
enum isis_adj_state enum isis_adj_state
{ {
ISIS_ADJ_UNKNOWN,
ISIS_ADJ_INITIALIZING, ISIS_ADJ_INITIALIZING,
ISIS_ADJ_UP, ISIS_ADJ_UP,
ISIS_ADJ_DOWN ISIS_ADJ_DOWN
@ -83,8 +84,10 @@ struct isis_adjacency
struct list *area_addrs; /* areaAdressesOfNeighbour */ struct list *area_addrs; /* areaAdressesOfNeighbour */
struct nlpids nlpids; /* protocols spoken ... */ struct nlpids nlpids; /* protocols spoken ... */
struct list *ipv4_addrs; struct list *ipv4_addrs;
struct in_addr router_address;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct list *ipv6_addrs; struct list *ipv6_addrs;
struct in6_addr router_address6;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */ u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
int circuit_t; /* from hello PDU hdr */ 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 list *adjdb);
struct isis_adjacency *isis_new_adj (u_char * id, u_char * snpa, int level, struct isis_adjacency *isis_new_adj (u_char * id, u_char * snpa, int level,
struct isis_circuit *circuit); 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, void isis_adj_state_change (struct isis_adjacency *adj,
enum isis_adj_state state, const char *reason); enum isis_adj_state state, const char *reason);
void isis_adj_print (struct isis_adjacency *adj); void isis_adj_print (struct isis_adjacency *adj);
int isis_adj_expire (struct thread *thread); int isis_adj_expire (struct thread *thread);
void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty); void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail);
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_build_neigh_list (struct list *adjdb, struct list *list); void isis_adj_build_neigh_list (struct list *adjdb, struct list *list);
void isis_adj_build_up_list (struct list *adjdb, struct list *list); void isis_adj_build_up_list (struct list *adjdb, struct list *list);
void isis_adjdb_iterate (struct list *adjdb,
void (*func) (struct isis_adjacency *,
void *), void *arg);
#endif /* ISIS_ADJACENCY_H */ #endif /* ISIS_ADJACENCY_H */

View File

@ -301,7 +301,16 @@ int
isis_send_pdu_bcast (struct isis_circuit *circuit, int level) isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
{ {
struct ether_header *eth; 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); 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)); stream_get_endp (circuit->snd_stream));
/* now we can send this */ /* now we can send this */
written = write (circuit->fd, sock_buff, written = write (circuit->fd, sock_buff, buflen);
stream_get_endp (circuit->snd_stream)
+ LLC_LEN + ETHER_HDR_LEN);
return ISIS_OK; return ISIS_OK;
} }

File diff suppressed because it is too large Load Diff

View File

@ -52,8 +52,6 @@ struct isis_bcast_info
u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */ 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 */ u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */
struct thread *t_refresh_pseudo_lsp[2]; /* refresh pseudo-node LSPs */ 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 struct isis_p2p_info
@ -65,7 +63,6 @@ struct isis_p2p_info
struct isis_circuit struct isis_circuit
{ {
int state; int state;
int connected;
u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */
struct isis_area *area; /* back pointer to the area */ struct isis_area *area; /* back pointer to the area */
struct interface *interface; /* interface info from z */ struct interface *interface; /* interface info from z */
@ -79,31 +76,36 @@ struct isis_circuit
struct thread *t_send_csnp[2]; struct thread *t_send_csnp[2];
struct thread *t_send_psnp[2]; struct thread *t_send_psnp[2];
struct list *lsp_queue; /* LSPs to be txed (both levels) */ 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 */ /* there is no real point in two streams, just for programming kicker */
int (*rx) (struct isis_circuit * circuit, u_char * ssnpa); int (*rx) (struct isis_circuit * circuit, u_char * ssnpa);
struct stream *rcv_stream; /* Stream for receiving */ struct stream *rcv_stream; /* Stream for receiving */
int (*tx) (struct isis_circuit * circuit, int level); int (*tx) (struct isis_circuit * circuit, int level);
struct stream *snd_stream; /* Stream for sending */ struct stream *snd_stream; /* Stream for sending */
int idx; /* idx in S[RM|SN] flags */ int idx; /* idx in S[RM|SN] flags */
#define CIRCUIT_T_BROADCAST 0 #define CIRCUIT_T_UNKNOWN 0
#define CIRCUIT_T_P2P 1 #define CIRCUIT_T_BROADCAST 1
#define CIRCUIT_T_STATIC_IN 2 #define CIRCUIT_T_P2P 2
#define CIRCUIT_T_STATIC_OUT 3 #define CIRCUIT_T_LOOPBACK 3
#define CIRCUIT_T_DA 4
int circ_type; /* type of the physical interface */ int circ_type; /* type of the physical interface */
int circ_type_config; /* config type of the physical interface */
union union
{ {
struct isis_bcast_info bc; struct isis_bcast_info bc;
struct isis_p2p_info p2p; struct isis_p2p_info p2p;
} u; } u;
u_char priority[2]; /* l1/2 IS configured priority */
int pad_hellos; /* add padding to Hello PDUs ? */
char ext_domain; /* externalDomain (boolean) */ char ext_domain; /* externalDomain (boolean) */
int lsp_regenerate_pending[ISIS_LEVELS];
/* /*
* Configurables * Configurables
*/ */
struct isis_passwd passwd; /* Circuit rx/tx password */ struct isis_passwd passwd; /* Circuit rx/tx password */
long lsp_interval; int is_type; /* circuit is type == level of circuit
int manual_l2_only; /* manualL2OnlyMode (boolean) */
int circuit_is_type; /* circuit is type == level of circuit
* diffrenciated from circuit type (media) */ * diffrenciated from circuit type (media) */
u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */
u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ 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 */ u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */
struct metric metrics[2]; /* l1XxxMetric */ struct metric metrics[2]; /* l1XxxMetric */
u_int32_t te_metric[2]; u_int32_t te_metric[2];
struct password *c_rx_passwds; /* circuitReceivePasswords */
struct password *c_tc_passwd; /* circuitTransmitPassword */
int ip_router; /* Route IP ? */ int ip_router; /* Route IP ? */
int is_passive; /* Is Passive ? */
struct list *ip_addrs; /* our IP addresses */ struct list *ip_addrs; /* our IP addresses */
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int ipv6_router; /* Route IPv6 ? */ int ipv6_router; /* Route IPv6 ? */
struct list *ipv6_link; /* our link local IPv6 addresses */ struct list *ipv6_link; /* our link local IPv6 addresses */
struct list *ipv6_non_link; /* our non-link local IPv6 addresses */ struct list *ipv6_non_link; /* our non-link local IPv6 addresses */
#endif /* HAVE_IPV6 */ #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]; u_int16_t upadjcount[2];
#define ISIS_CIRCUIT_FLAPPED_AFTER_SPF 0x01
u_char flags;
/* /*
* Counters as in 10589--11.2.5.9 * Counters as in 10589--11.2.5.9
*/ */
@ -142,25 +137,30 @@ struct isis_circuit
void isis_circuit_init (void); void isis_circuit_init (void);
struct isis_circuit *isis_circuit_new (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 isis_circuit *circuit_lookup_by_ifp (struct interface *ifp,
struct list *list); struct list *list);
struct isis_circuit *circuit_scan_by_ifp (struct interface *ifp); 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, void isis_circuit_configure (struct isis_circuit *circuit,
struct isis_area *area); struct isis_area *area);
void isis_circuit_up (struct isis_circuit *circuit);
void isis_circuit_deconfigure (struct isis_circuit *circuit, void isis_circuit_deconfigure (struct isis_circuit *circuit,
struct isis_area *area); struct isis_area *area);
int isis_circuit_destroy (struct isis_circuit *circuit);
void isis_circuit_if_add (struct isis_circuit *circuit, void isis_circuit_if_add (struct isis_circuit *circuit,
struct interface *ifp); struct interface *ifp);
void isis_circuit_if_del (struct isis_circuit *circuit); void isis_circuit_if_del (struct isis_circuit *circuit,
void circuit_update_nlpids (struct isis_circuit *circuit); struct interface *ifp);
void isis_circuit_update_params (struct isis_circuit *circuit, void isis_circuit_if_bind (struct isis_circuit *circuit,
struct interface *ifp); struct interface *ifp);
void isis_circuit_if_unbind (struct isis_circuit *circuit,
struct interface *ifp);
void isis_circuit_add_addr (struct isis_circuit *circuit, void isis_circuit_add_addr (struct isis_circuit *circuit,
struct connected *conn); struct connected *conn);
void isis_circuit_del_addr (struct isis_circuit *circuit, void isis_circuit_del_addr (struct isis_circuit *circuit,
struct connected *conn); 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 */ #endif /* _ZEBRA_ISIS_CIRCUIT_H */

View File

@ -21,6 +21,9 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef ISIS_COMMON_H
#define ISIS_COMMON_H
/* /*
* Area Address * Area Address
*/ */
@ -65,11 +68,4 @@ struct nlpids
u_char nlpids[4]; /* FIXME: enough ? */ u_char nlpids[4]; /* FIXME: enough ? */
}; };
/* #endif
* Flags structure for SSN and SRM flags
*/
struct flags
{
int maxindex;
struct list *free_idcs;
};

View File

@ -27,8 +27,10 @@
* Architectural constant values from p. 35 of ISO/IEC 10589 * Architectural constant values from p. 35 of ISO/IEC 10589
*/ */
#define MAX_LINK_METRIC 63 #define MAX_NARROW_LINK_METRIC 63
#define MAX_PATH_METRIC 1023 #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 ISO_SAP 0xFE
#define INTRADOMAIN_ROUTEING_SELECTOR 0 #define INTRADOMAIN_ROUTEING_SELECTOR 0
#define SEQUENCE_MODULUS 4294967296 #define SEQUENCE_MODULUS 4294967296
@ -38,7 +40,7 @@
* implementation specific jitter values * implementation specific jitter values
*/ */
#define IIH_JITTER 25 /* % */ #define IIH_JITTER 10 /* % */
#define MAX_AGE_JITTER 5 /* % */ #define MAX_AGE_JITTER 5 /* % */
#define MAX_LSP_GEN_JITTER 5 /* % */ #define MAX_LSP_GEN_JITTER 5 /* % */
#define CSNP_JITTER 10 /* % */ #define CSNP_JITTER 10 /* % */
@ -46,36 +48,59 @@
#define RANDOM_SPREAD 100000.0 #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_LEVELS 2
#define ISIS_LEVEL1 1 #define ISIS_LEVEL1 1
#define ISIS_LEVEL2 2 #define ISIS_LEVEL2 2
#define HELLO_INTERVAL 10 /*
#define HELLO_MINIMAL HELLO_INTERVAL * Default values
#define HELLO_MULTIPLIER 3 * 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 #define DEFAULT_PRIORITY 64
/* different vendors implement different values 5-10 on average */
#define LSP_GEN_INTERVAL_DEFAULT 10 /* min and max metric varies by new vs old metric types */
#define LSP_INTERVAL 33 /* msecs */ #define DEFAULT_CIRCUIT_METRIC 10
#define DEFAULT_CIRCUIT_METRICS 10
#define METRICS_UNSUPPORTED 0x80 #define METRICS_UNSUPPORTED 0x80
#define PERIODIC_SPF_INTERVAL 60 /* at the top of my head */
#define MINIMUM_SPF_INTERVAL 5 /* .. same here */ #define MINIMUM_SPF_INTERVAL 1
#define ISIS_MAX_PATH_SPLITS 64
/* /*
* NLPID values * NLPID values
@ -104,6 +129,7 @@
#define SNPA_ADDRSTRLEN 18 #define SNPA_ADDRSTRLEN 18
#define ISIS_SYS_ID_LEN 6 #define ISIS_SYS_ID_LEN 6
#define ISIS_NSEL_LEN 1
#define SYSID_STRLEN 24 #define SYSID_STRLEN 24
/* /*
@ -136,8 +162,8 @@
* packets, using isomtu = mtu - LLC_LEN * packets, using isomtu = mtu - LLC_LEN
*/ */
#define ISO_MTU(C) \ #define ISO_MTU(C) \
(C->circ_type==CIRCUIT_T_BROADCAST) ? \ ((if_is_broadcast ((C)->interface)) ? \
(C->interface->mtu - LLC_LEN) : (C->interface->mtu) (C->interface->mtu - LLC_LEN) : (C->interface->mtu))
#ifndef ETH_ALEN #ifndef ETH_ALEN
#define ETH_ALEN 6 #define ETH_ALEN 6

View File

@ -36,6 +36,7 @@
#include "isisd/include-netbsd/iso.h" #include "isisd/include-netbsd/iso.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_common.h" #include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h" #include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h" #include "isisd/isis_lsp.h"
@ -45,7 +46,6 @@
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h" #include "isisd/isis_adjacency.h"
#include "isisd/isis_dr.h" #include "isisd/isis_dr.h"
#include "isisd/isis_flags.h"
#include "isisd/isisd.h" #include "isisd/isisd.h"
#include "isisd/isis_csm.h" #include "isisd/isis_csm.h"
#include "isisd/isis_events.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: case C_STATE_NA:
if (circuit) if (circuit)
zlog_warn ("Non-null circuit while state C_STATE_NA"); zlog_warn ("Non-null circuit while state C_STATE_NA");
assert (circuit == NULL);
switch (event) switch (event)
{ {
case ISIS_ENABLE: case ISIS_ENABLE:
@ -106,24 +107,29 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
} }
break; break;
case C_STATE_INIT: case C_STATE_INIT:
assert (circuit);
switch (event) switch (event)
{ {
case ISIS_ENABLE: case ISIS_ENABLE:
isis_circuit_configure (circuit, (struct isis_area *) arg); 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->state = C_STATE_UP;
circuit->connected = 1; isis_event_circuit_state_change (circuit, circuit->area, 1);
isis_event_circuit_state_change (circuit, 1);
listnode_delete (isis->init_circ_list, circuit); listnode_delete (isis->init_circ_list, circuit);
break; break;
case IF_UP_FROM_Z: case IF_UP_FROM_Z:
assert (circuit);
zlog_warn ("circuit already connected"); zlog_warn ("circuit already connected");
break; break;
case ISIS_DISABLE: case ISIS_DISABLE:
zlog_warn ("circuit already disabled"); zlog_warn ("circuit already disabled");
break; break;
case IF_DOWN_FROM_Z: 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); listnode_delete (isis->init_circ_list, circuit);
isis_circuit_del (circuit); isis_circuit_del (circuit);
circuit = NULL; circuit = NULL;
@ -131,19 +137,21 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
} }
break; break;
case C_STATE_CONF: case C_STATE_CONF:
assert (circuit);
switch (event) switch (event)
{ {
case ISIS_ENABLE: case ISIS_ENABLE:
zlog_warn ("circuit already enabled"); zlog_warn ("circuit already enabled");
break; break;
case IF_UP_FROM_Z: case IF_UP_FROM_Z:
if (!circuit->connected) { isis_circuit_if_add (circuit, (struct interface *) arg);
isis_circuit_if_add (circuit, (struct interface *) arg); if (isis_circuit_up (circuit) != ISIS_OK)
isis_circuit_up (circuit); {
} isis_circuit_if_del (circuit, (struct interface *) arg);
break;
}
circuit->state = C_STATE_UP; circuit->state = C_STATE_UP;
circuit->connected = 1; isis_event_circuit_state_change (circuit, circuit->area, 1);
isis_event_circuit_state_change (circuit, 1);
break; break;
case ISIS_DISABLE: case ISIS_DISABLE:
isis_circuit_deconfigure (circuit, (struct isis_area *) arg); 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; break;
case C_STATE_UP: case C_STATE_UP:
assert (circuit);
switch (event) switch (event)
{ {
case ISIS_ENABLE: case ISIS_ENABLE:
@ -165,14 +174,18 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
zlog_warn ("circuit already connected"); zlog_warn ("circuit already connected");
break; break;
case ISIS_DISABLE: case ISIS_DISABLE:
isis_circuit_down (circuit);
isis_circuit_deconfigure (circuit, (struct isis_area *) arg); isis_circuit_deconfigure (circuit, (struct isis_area *) arg);
listnode_add (isis->init_circ_list, circuit);
circuit->state = C_STATE_INIT; 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; break;
case IF_DOWN_FROM_Z: case IF_DOWN_FROM_Z:
isis_circuit_down (circuit);
isis_circuit_if_del (circuit, (struct interface *) arg);
circuit->state = C_STATE_CONF; circuit->state = C_STATE_CONF;
isis_event_circuit_state_change (circuit, 0); isis_event_circuit_state_change (circuit, circuit->area, 0);
break; break;
} }
break; break;

View File

@ -442,12 +442,12 @@ open_dlpi_dev (struct isis_circuit *circuit)
* 8.4.2 - Broadcast subnetwork IIH PDUs * 8.4.2 - Broadcast subnetwork IIH PDUs
*/ */
retval = 0; 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_L1_ISS);
retval |= dlpimcast (fd, ALL_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); retval |= dlpimcast (fd, ALL_L2_ISS);
if (retval != 0) 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; dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
char *dstaddr; char *dstaddr;
u_short *dstsap; 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); stream_set_getp (circuit->snd_stream, 0);
@ -612,7 +622,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
else else
memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL); memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
/* Note: DLPI SAP values are in host byte order */ /* 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[0] = ISO_SAP;
sock_buff[1] = 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, memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
stream_get_endp (circuit->snd_stream)); stream_get_endp (circuit->snd_stream));
dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length, 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; return ISIS_OK;
} }

View File

@ -47,9 +47,6 @@
#include "isisd/isis_dr.h" #include "isisd/isis_dr.h"
#include "isisd/isis_events.h" #include "isisd/isis_events.h"
extern struct isis *isis;
extern struct thread_master *master;
const char * const char *
isis_disflag2string (int disflag) isis_disflag2string (int disflag)
{ {
@ -137,15 +134,14 @@ isis_dr_elect (struct isis_circuit *circuit, int level)
int biggest_prio = -1; int biggest_prio = -1;
int cmp_res, retval = ISIS_OK; 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]; adjdb = circuit->u.bc.adjdb[level - 1];
if (!adjdb) if (!adjdb)
{ {
zlog_warn ("isis_dr_elect() adjdb == NULL"); zlog_warn ("isis_dr_elect() adjdb == NULL");
retval = ISIS_WARNING;
list_delete (list); list_delete (list);
goto out; return ISIS_WARNING;
} }
isis_adj_build_up_list (adjdb, list); isis_adj_build_up_list (adjdb, list);
@ -189,42 +185,34 @@ isis_dr_elect (struct isis_circuit *circuit, int level)
if (!adj_dr) 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]) if (circuit->u.bc.is_dr[level - 1])
{ retval = isis_dr_resign (circuit, level);
list_delete (list); list_delete (list);
list = NULL; return retval;
return isis_dr_commence (circuit, level);
}
goto out;
} }
/* /*
* Now we have the DR adjacency, compare it to self * Now we have the DR adjacency, compare it to self
*/ */
if (adj_dr->prio[level - 1] < own_prio if (adj_dr->prio[level - 1] < own_prio ||
|| (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)) memcmp (adj_dr->snpa, circuit->u.bc.snpa, ETH_ALEN) < 0))
{ {
if (!circuit->u.bc.is_dr[level - 1]) adj_dr->dis_record[level - 1].dis = ISIS_IS_NOT_DIS;
{ adj_dr->dis_record[level - 1].last_dis_change = time (NULL);
/*
* We are the DR
*/
/* rotate the history log */ /* rotate the history log */
for (ALL_LIST_ELEMENTS_RO (list, node, adj)) for (ALL_LIST_ELEMENTS_RO (list, node, adj))
isis_check_dr_change (adj, level); isis_check_dr_change (adj, level);
/* commence */ /* We are the DR, commence DR */
list_delete (list); if (circuit->u.bc.is_dr[level - 1] == 0 && listcount (list) > 0)
return isis_dr_commence (circuit, level); retval = isis_dr_commence (circuit, level);
}
} }
else else
{ {
/* ok we have found the DIS - lets mark the adjacency */ /* ok we have found the DIS - lets mark the adjacency */
/* set flag for show output */ /* set flag for show output */
adj_dr->dis_record[level - 1].dis = ISIS_IS_DIS; 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 * We are not DR - if we were -> resign
*/ */
if (circuit->u.bc.is_dr[level - 1]) if (circuit->u.bc.is_dr[level - 1])
{ retval = isis_dr_resign (circuit, level);
list_delete (list);
return isis_dr_resign (circuit, level);
}
} }
out: list_delete (list);
if (list)
list_delete (list);
return retval; return retval;
} }
@ -264,11 +246,12 @@ isis_dr_resign (struct isis_circuit *circuit, int level)
circuit->u.bc.run_dr_elect[level - 1] = 0; 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_run_dr[level - 1]);
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[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); memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
LSP_PSEUDO_ID (id) = circuit->circuit_id; LSP_PSEUDO_ID (id) = circuit->circuit_id;
LSP_FRAGMENT (id) = 0; LSP_FRAGMENT (id) = 0;
lsp_purge_dr (id, circuit, level); lsp_purge_pseudo (id, circuit, level);
if (level == 1) if (level == 1)
{ {
@ -327,7 +310,7 @@ isis_dr_commence (struct isis_circuit *circuit, int level)
if (LSP_PSEUDO_ID (old_dr)) if (LSP_PSEUDO_ID (old_dr))
{ {
/* there was a dr elected, purge its LSPs from the db */ /* 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); 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; *(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 */ assert (circuit->circuit_id); /* must be non-zero */
/* if (circuit->t_send_l1_psnp) /* if (circuit->t_send_l1_psnp)
thread_cancel (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_OFF (circuit->u.bc.t_run_dr[0]);
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1, 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)) if (LSP_PSEUDO_ID (old_dr))
{ {
/* there was a dr elected, purge its LSPs from the db */ /* 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); 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; *(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 */ assert (circuit->circuit_id); /* must be non-zero */
/* if (circuit->t_send_l1_psnp) /* if (circuit->t_send_l1_psnp)
thread_cancel (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_OFF (circuit->u.bc.t_run_dr[1]);
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2, THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,

View File

@ -41,8 +41,6 @@
#include "isisd/isis_misc.h" #include "isisd/isis_misc.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
extern struct isis *isis;
extern struct thread_master *master;
extern struct host host; extern struct host host;
struct list *dyn_cache = NULL; struct list *dyn_cache = NULL;
@ -51,7 +49,8 @@ static int dyn_cache_cleanup (struct thread *);
void void
dyn_cache_init (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); THREAD_TIMER_ON (master, isis->t_dync_clean, dyn_cache_cleanup, NULL, 120);
return; return;
} }
@ -67,8 +66,8 @@ dyn_cache_cleanup (struct thread *thread)
for (ALL_LIST_ELEMENTS (dyn_cache, node, nnode, dyn)) for (ALL_LIST_ELEMENTS (dyn_cache, node, nnode, dyn))
{ {
if ((now - dyn->refresh) < (MAX_AGE + 120)) if ((now - dyn->refresh) < MAX_LSP_LIFETIME)
continue; continue;
list_delete_node (dyn_cache, node); list_delete_node (dyn_cache, node);
XFREE (MTYPE_ISIS_DYNHN, dyn); XFREE (MTYPE_ISIS_DYNHN, dyn);
@ -91,6 +90,19 @@ dynhn_find_by_id (u_char * id)
return NULL; 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 void
isis_dynhn_insert (u_char * id, struct hostname *hostname, int level) 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; 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) * Level System ID Dynamic Hostname (notag)
* 2 0000.0000.0001 foo-gw * 2 0000.0000.0001 foo-gw

View File

@ -33,7 +33,9 @@ struct isis_dynhn
void dyn_cache_init (void); void dyn_cache_init (void);
void isis_dynhn_insert (u_char * id, struct hostname *hostname, int level); 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_id (u_char * id);
struct isis_dynhn *dynhn_find_by_name (const char *hostname);
void dynhn_print_all (struct vty *vty); void dynhn_print_all (struct vty *vty);
#endif /* _ZEBRA_ISIS_DYNHN_H */ #endif /* _ZEBRA_ISIS_DYNHN_H */

View File

@ -30,11 +30,13 @@
#include "hash.h" #include "hash.h"
#include "prefix.h" #include "prefix.h"
#include "stream.h" #include "stream.h"
#include "table.h"
#include "isisd/dict.h" #include "isisd/dict.h"
#include "isisd/include-netbsd/iso.h" #include "isisd/include-netbsd/iso.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_common.h" #include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h" #include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h" #include "isisd/isis_lsp.h"
@ -44,15 +46,11 @@
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h" #include "isisd/isis_adjacency.h"
#include "isisd/isis_dr.h" #include "isisd/isis_dr.h"
#include "isisd/isis_flags.h"
#include "isisd/isisd.h" #include "isisd/isisd.h"
#include "isisd/isis_csm.h" #include "isisd/isis_csm.h"
#include "isisd/isis_events.h" #include "isisd/isis_events.h"
#include "isisd/isis_spf.h" #include "isisd/isis_spf.h"
extern struct thread_master *master;
extern struct isis *isis;
/* debug isis-spf spf-events /* debug isis-spf spf-events
4w4d: ISIS-Spf (tlt): L2 SPF needed, new adjacency, from 0x609229F4 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 4w4d: ISIS-Spf (tlt): L2, 0000.0000.0042.01-00 TLV contents changed, code 0x2
@ -62,26 +60,59 @@ extern struct isis *isis;
*/ */
void 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++; area->circuit_state_changes++;
if (isis->debugs & DEBUG_EVENTS) if (isis->debugs & DEBUG_EVENTS)
zlog_debug ("ISIS-Evt (%s) circuit %s", circuit->area->area_tag, zlog_debug ("ISIS-Evt (%s) circuit %s", area->area_tag,
up ? "up" : "down"); up ? "up" : "down");
/* /*
* Regenerate LSPs this affects * Regenerate LSPs this affects
*/ */
lsp_regenerate_schedule (area); lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0);
return; 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 void
isis_event_system_type_change (struct isis_area *area, int newtype) 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 */ return; /* No change */
switch (area->is_type) switch (area->is_type)
{ {
case IS_LEVEL_1: case IS_LEVEL_1:
if (newtype == IS_LEVEL_2)
area_resign_level (area, IS_LEVEL_1);
if (area->lspdb[1] == NULL) if (area->lspdb[1] == NULL)
area->lspdb[1] = lsp_db_init (); area->lspdb[1] = lsp_db_init ();
lsp_l2_generate (area); 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; break;
case IS_LEVEL_1_AND_2: case IS_LEVEL_1_AND_2:
if (newtype == IS_LEVEL_1) if (newtype == IS_LEVEL_1)
{ area_resign_level (area, IS_LEVEL_2);
lsp_db_destroy (area->lspdb[1]);
}
else else
{ area_resign_level (area, IS_LEVEL_1);
lsp_db_destroy (area->lspdb[0]);
}
break; break;
case IS_LEVEL_2: case IS_LEVEL_2:
if (newtype == IS_LEVEL_1)
area_resign_level (area, IS_LEVEL_2);
if (area->lspdb[0] == NULL) if (area->lspdb[0] == NULL)
area->lspdb[0] = lsp_db_init (); area->lspdb[0] = lsp_db_init ();
lsp_l1_generate (area); 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; break;
default: default:
break; break;
} }
area->is_type = newtype; 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); 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; return;
} }
void
isis_event_area_addr_change (struct isis_area *area)
{
}
static void static void
circuit_commence_level (struct isis_circuit *circuit, int level) circuit_commence_level (struct isis_circuit *circuit, int level)
{ {
if (level == 1) if (level == 1)
{ {
THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit, if (! circuit->is_passive)
isis_jitter (circuit->psnp_interval[0], PSNP_JITTER)); 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) if (circuit->circ_type == CIRCUIT_T_BROADCAST)
{ {
THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1, 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], THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0],
send_lan_l1_hello, circuit, send_lan_l1_hello, circuit,
@ -160,8 +211,9 @@ circuit_commence_level (struct isis_circuit *circuit, int level)
} }
else else
{ {
THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit, if (! circuit->is_passive)
isis_jitter (circuit->psnp_interval[1], PSNP_JITTER)); 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) 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_run_dr[idx]);
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[idx]); THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[idx]);
circuit->u.bc.run_dr_elect[idx] = 0; circuit->u.bc.run_dr_elect[idx] = 0;
list_delete (circuit->u.bc.lan_neighs[idx]);
circuit->u.bc.lan_neighs[idx] = NULL;
} }
return; return;
@ -202,14 +256,19 @@ circuit_resign_level (struct isis_circuit *circuit, int level)
void void
isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype) 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) if (isis->debugs & DEBUG_EVENTS)
zlog_debug ("ISIS-Evt (%s) circuit type change %s -> %s", zlog_debug ("ISIS-Evt (%s) circuit type change %s -> %s",
circuit->area->area_tag, circuit->area->area_tag,
circuit_t2string (circuit->circuit_is_type), circuit_t2string (circuit->is_type),
circuit_t2string (newtype)); circuit_t2string (newtype));
if (circuit->circuit_is_type == newtype) if (circuit->is_type == newtype)
return; /* No change */ return; /* No change */
if (!(newtype & circuit->area->is_type)) if (!(newtype & circuit->area->is_type))
@ -221,7 +280,7 @@ isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
return; return;
} }
switch (circuit->circuit_is_type) switch (circuit->is_type)
{ {
case IS_LEVEL_1: case IS_LEVEL_1:
if (newtype == IS_LEVEL_2) if (newtype == IS_LEVEL_2)
@ -243,8 +302,8 @@ isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
break; break;
} }
circuit->circuit_is_type = newtype; circuit->is_type = newtype;
lsp_regenerate_schedule (circuit->area); lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
return; return;
} }
@ -286,7 +345,7 @@ isis_event_adjacency_state_change (struct isis_adjacency *adj, int newstate)
adj->circuit->area->area_tag); adj->circuit->area->area_tag);
/* LSP generation again */ /* LSP generation again */
lsp_regenerate_schedule (adj->circuit->area); lsp_regenerate_schedule (adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
return; 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); zlog_debug ("ISIS-Evt (%s) DIS status change", circuit->area->area_tag);
/* LSP generation again */ /* LSP generation again */
lsp_regenerate_schedule (circuit->area); lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
return 0; return 0;
} }

View File

@ -26,13 +26,12 @@
* Events related to area * Events related to area
*/ */
void isis_event_system_type_change (struct isis_area *area, int newtype); 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 * Events related to circuit
*/ */
void isis_event_circuit_state_change (struct isis_circuit *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, void isis_event_circuit_type_change (struct isis_circuit *circuit,
int newtype); int newtype);
/* /*

View File

@ -36,11 +36,11 @@ flags_initialize (struct flags *flags)
flags->free_idcs = NULL; flags->free_idcs = NULL;
} }
int long int
flags_get_index (struct flags *flags) flags_get_index (struct flags *flags)
{ {
struct listnode *node; struct listnode *node;
int index; long int index;
if (flags->free_idcs == NULL || flags->free_idcs->count == 0) if (flags->free_idcs == NULL || flags->free_idcs->count == 0)
{ {
@ -49,7 +49,7 @@ flags_get_index (struct flags *flags)
else else
{ {
node = listhead (flags->free_idcs); node = listhead (flags->free_idcs);
index = (int) listgetdata (node); index = (long int) listgetdata (node);
listnode_delete (flags->free_idcs, (void *) index); listnode_delete (flags->free_idcs, (void *) index);
index--; index--;
} }
@ -58,7 +58,7 @@ flags_get_index (struct flags *flags)
} }
void void
flags_free_index (struct flags *flags, int index) flags_free_index (struct flags *flags, long int index)
{ {
if (index + 1 == flags->maxindex) if (index + 1 == flags->maxindex)
{ {

View File

@ -26,28 +26,43 @@
/* The grand plan is to support 1024 circuits so we have 32*32 bit flags /* The grand plan is to support 1024 circuits so we have 32*32 bit flags
* the support will be achived using the newest drafts */ * 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); void flags_initialize (struct flags *flags);
struct flags *new_flags (int size); long int flags_get_index (struct flags *flags);
int flags_get_index (struct flags *flags); void flags_free_index (struct flags *flags, long int index);
void flags_free_index (struct flags *flags, int index);
int flags_any_set (u_int32_t * flags); int flags_any_set (u_int32_t * flags);
#define ISIS_SET_FLAG(F,C) \ #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) \ #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 */ /* sets all u_32int_t flags to 1 */
#define ISIS_FLAGS_SET_ALL(FLAGS) \ #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) \ #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 */ #endif /* _ZEBRA_ISIS_FLAGS_H */

File diff suppressed because it is too large Load Diff

View File

@ -24,10 +24,6 @@
#ifndef _ZEBRA_ISIS_LSP_H #ifndef _ZEBRA_ISIS_LSP_H
#define _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 /* Structure for isis_lsp, this structure will only support the fixed
* System ID (Currently 6) (atleast for now). In order to support more * 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 * We will have to split the header into two parts, and for readability
@ -42,15 +38,13 @@ struct isis_lsp
struct list *frags; struct list *frags;
struct isis_lsp *zero_lsp; struct isis_lsp *zero_lsp;
} lspu; } lspu;
u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */
u_int32_t SRMflags[ISIS_MAX_CIRCUITS]; u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
u_int32_t SSNflags[ISIS_MAX_CIRCUITS]; u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
u_int32_t rexmit_queue[ISIS_MAX_CIRCUITS];
int level; /* L1 or L2? */ int level; /* L1 or L2? */
int purged; /* have purged this one */
int scheduled; /* scheduled for sending */ int scheduled; /* scheduled for sending */
time_t installed; time_t installed;
time_t last_generated; time_t last_generated;
time_t last_sent;
int own_lsp; int own_lsp;
#ifdef TOPOLOGY_GENERATE #ifdef TOPOLOGY_GENERATE
int from_topology; int from_topology;
@ -58,7 +52,6 @@ struct isis_lsp
#endif #endif
/* used for 60 second counting when rem_lifetime is zero */ /* used for 60 second counting when rem_lifetime is zero */
int age_out; int age_out;
/* FIXME: For now only topology LSP's use this. Is it helpful for others? */
struct isis_area *area; struct isis_area *area;
struct tlvs tlv_data; /* Simplifies TLV access */ struct tlvs tlv_data; /* Simplifies TLV access */
}; };
@ -67,37 +60,32 @@ dict_t *lsp_db_init (void);
void lsp_db_destroy (dict_t * lspdb); void lsp_db_destroy (dict_t * lspdb);
int lsp_tick (struct thread *thread); int lsp_tick (struct thread *thread);
int lsp_l1_generate (struct isis_area *area); int lsp_generate (struct isis_area *area, int level);
int lsp_l2_generate (struct isis_area *area); int lsp_regenerate_schedule (struct isis_area *area, int level,
int lsp_refresh_l1 (struct thread *thread); int all_pseudo);
int lsp_refresh_l2 (struct thread *thread); int lsp_generate_pseudo (struct isis_circuit *circuit, int level);
int lsp_regenerate_schedule (struct isis_area *area); 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, 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_int32_t seq_num, u_int8_t lsp_bits,
u_int16_t checksum, int level); u_int16_t checksum, int level);
struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream, struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream,
u_int16_t pdu_len, u_int16_t pdu_len,
struct isis_lsp *lsp0, struct isis_lsp *lsp0,
struct isis_area *area); struct isis_area *area,
int level);
void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb); void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb);
struct isis_lsp *lsp_search (u_char * id, 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); struct list *list, dict_t * lspdb);
void lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id, void lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
struct list *list, dict_t * lspdb); struct list *list, dict_t * lspdb);
void lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list, void lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps,
dict_t * lspdb); struct list *list, dict_t * lspdb);
void lsp_search_and_destroy (u_char * id, 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, void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
struct isis_area *area); 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_id_cmp (u_char * id1, u_char * id2);
int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
u_int16_t checksum, u_int16_t rem_lifetime); u_int16_t checksum, u_int16_t rem_lifetime);
void lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr, void lsp_update (struct isis_lsp *lsp, struct stream *stream,
struct stream *stream, struct isis_area *area, int level); struct isis_area *area, int level);
void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num); 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, int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail,
char dynhost); char dynhost);
const char *lsp_bits2string (u_char *); 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 #ifdef TOPOLOGY_GENERATE
void generate_topology_lsps (struct isis_area *area); void generate_topology_lsps (struct isis_area *area);
void remove_topology_lsps (struct isis_area *area); void remove_topology_lsps (struct isis_area *area);

View File

@ -44,6 +44,9 @@
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isisd.h" #include "isisd/isisd.h"
#include "isisd/isis_dynhn.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 */ /* Default configuration file name */
#define ISISD_DEFAULT_CONFIG "isisd.conf" #define ISISD_DEFAULT_CONFIG "isisd.conf"
@ -67,7 +70,7 @@ struct zebra_privs_t isisd_privs = {
.vty_group = VTY_GROUP, .vty_group = VTY_GROUP,
#endif #endif
.caps_p = _caps_p, .caps_p = _caps_p,
.cap_num_p = 2, .cap_num_p = sizeof (_caps_p) / sizeof (*_caps_p),
.cap_num_i = 0 .cap_num_i = 0
}; };
@ -154,7 +157,10 @@ reload ()
zlog_debug ("Reload"); zlog_debug ("Reload");
/* FIXME: Clean up func call here */ /* FIXME: Clean up func call here */
vty_reset (); vty_reset ();
(void) isisd_privs.change (ZPRIVS_RAISE);
execve (_progpath, _argv, _envp); execve (_progpath, _argv, _envp);
zlog_err ("Reload failed: cannot exec %s: %s", _progpath,
safe_strerror (errno));
} }
static void static void
@ -325,28 +331,31 @@ main (int argc, char **argv, char **envp)
memory_init (); memory_init ();
access_list_init(); access_list_init();
isis_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 (); sort_node ();
/* parse config file */ /* parse config file */
/* this is needed three times! because we have interfaces before the areas */ /* 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);
vty_read_config (config_file, config_default);
/* Start execution only if not in dry-run mode */ /* Start execution only if not in dry-run mode */
if (dryrun) if (dryrun)
return(0); return(0);
/* demonize */ /* demonize */
if (daemon_mode && daemon (0, 0) < 0) if (daemon_mode)
{ daemon (0, 0);
zlog_err("ISISd daemon failed: %s", strerror(errno));
exit (1);
}
/* Process ID file creation. */ /* Process ID file creation. */
pid_output (pid_file); if (pid_file[0] != '\0')
pid_output (pid_file);
/* Make isis vty socket. */ /* Make isis vty socket. */
vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH); vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);

View File

@ -32,7 +32,9 @@
#include "isisd/dict.h" #include "isisd/dict.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_common.h" #include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"
#include "isisd/isisd.h" #include "isisd/isisd.h"
#include "isisd/isis_misc.h" #include "isisd/isis_misc.h"
@ -40,6 +42,7 @@
#include "isisd/isis_lsp.h" #include "isisd/isis_lsp.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h" #include "isisd/isis_adjacency.h"
#include "isisd/isis_dynhn.h"
/* staticly assigned vars for printing purposes */ /* staticly assigned vars for printing purposes */
struct in_addr new_prefix; 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 * extract dot from the dotted str, and insert all the number in a buff
*/ */
int int
dotformat2buff (u_char * buff, const u_char * dotted) dotformat2buff (u_char * buff, const char * dotted)
{ {
int dotlen, len = 0; int dotlen, len = 0;
const u_char *pos = dotted; const char *pos = dotted;
u_char number[3]; u_char number[3];
int nextdotpos = 2; int nextdotpos = 2;
@ -157,10 +160,10 @@ dotformat2buff (u_char * buff, const u_char * dotted)
* conversion of XXXX.XXXX.XXXX to memory * conversion of XXXX.XXXX.XXXX to memory
*/ */
int int
sysid2buff (u_char * buff, const u_char * dotted) sysid2buff (u_char * buff, const char * dotted)
{ {
int len = 0; int len = 0;
const u_char *pos = dotted; const char *pos = dotted;
u_char number[3]; u_char number[3];
number[2] = '\0'; number[2] = '\0';
@ -271,7 +274,7 @@ speaks (struct nlpids *nlpids, int family)
* Returns 0 on error, IS-IS Circuit Type on ok * Returns 0 on error, IS-IS Circuit Type on ok
*/ */
int int
string2circuit_t (const u_char * str) string2circuit_t (const char * str)
{ {
if (!str) if (!str)
@ -289,6 +292,42 @@ string2circuit_t (const u_char * str)
return 0; 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 * const char *
circuit_t2string (int circuit_t) circuit_t2string (int circuit_t)
{ {
@ -498,7 +537,6 @@ unix_hostname (void)
{ {
static struct utsname names; static struct utsname names;
const char *hostname; const char *hostname;
extern struct host host;
hostname = host.name; hostname = host.name;
if (!hostname) if (!hostname)
@ -509,3 +547,87 @@ unix_hostname (void)
return hostname; 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;
}

View File

@ -24,8 +24,10 @@
#ifndef _ZEBRA_ISIS_MISC_H #ifndef _ZEBRA_ISIS_MISC_H
#define _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_t2string (int);
const char *circuit_state2string (int state);
const char *circuit_type2string (int type);
const char *syst2string (int); const char *syst2string (int);
struct in_addr newprefix2inaddr (u_char * prefix_start, struct in_addr newprefix2inaddr (u_char * prefix_start,
u_char prefix_masklen); u_char prefix_masklen);
@ -33,8 +35,8 @@ struct in_addr newprefix2inaddr (u_char * prefix_start,
* Converting input to memory stored format * Converting input to memory stored format
* return value of 0 indicates wrong input * return value of 0 indicates wrong input
*/ */
int dotformat2buff (u_char *, const u_char *); int dotformat2buff (u_char *, const char *);
int sysid2buff (u_char *, const u_char *); int sysid2buff (u_char *, const char *);
/* /*
* Printing functions * Printing functions
@ -46,6 +48,8 @@ const char *rawlspid_print (u_char *);
const char *time2string (u_int32_t); const char *time2string (u_int32_t);
/* typedef struct nlpids nlpids; */ /* typedef struct nlpids nlpids; */
char *nlpid2string (struct nlpids *); char *nlpid2string (struct nlpids *);
const char *print_sys_hostname (u_char *sysid);
void zlog_dump_data (void *data, int len);
/* /*
* misc functions * misc functions
@ -57,7 +61,8 @@ const char *unix_hostname (void);
/* /*
* macros * 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 */ /* used for calculating nice string representation instead of plain seconds */

File diff suppressed because it is too large Load Diff

View File

@ -95,7 +95,7 @@ struct isis_fixed_hdr
u_char version2; u_char version2;
u_char reserved; u_char reserved;
u_char max_area_addrs; u_char max_area_addrs;
}; } __attribute__ ((packed));
#define ISIS_FIXED_HDR_LEN 8 #define ISIS_FIXED_HDR_LEN 8
@ -114,7 +114,7 @@ struct isis_fixed_hdr
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* | Holding Time | 2 * | Holding Time | 2
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* | PDU Lenght | 2 * | PDU Length | 2
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* | R | Priority | 1 * | R | Priority | 1
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
@ -142,7 +142,7 @@ struct isis_lan_hello_hdr
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* + Holding Time + 2 * + Holding Time + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* + PDU Lenght + 2 * + PDU Length + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* | Local Circuit ID | 1 * | Local Circuit ID | 1
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
@ -186,12 +186,23 @@ struct isis_link_state_hdr
} __attribute__ ((packed)); } __attribute__ ((packed));
#define ISIS_LSP_HDR_LEN 19 #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 L1_COMPLETE_SEQ_NUM 24
#define L2_COMPLETE_SEQ_NUM 25 #define L2_COMPLETE_SEQ_NUM 25
/* /*
* L1 and L2 IS to IS complete sequence numbers PDU header * L1 and L2 IS to IS complete sequence numbers PDU header
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* + PDU Lenght + 2 * + PDU Length + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* + Source ID + id_len + 1 * + Source ID + id_len + 1
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
@ -241,6 +252,8 @@ int isis_receive (struct thread *thread);
#define ISIS_SNP_PSNP_FLAG 0 #define ISIS_SNP_PSNP_FLAG 0
#define ISIS_SNP_CSNP_FLAG 1 #define ISIS_SNP_CSNP_FLAG 1
#define ISIS_AUTH_MD5_SIZE 16U
/* /*
* Sending functions * 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); void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type);
int send_hello (struct isis_circuit *circuit, int level); 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 */ #endif /* _ZEBRA_ISIS_PDU_H */

View File

@ -134,7 +134,7 @@ open_packet_socket (struct isis_circuit *circuit)
circuit->fd = fd; circuit->fd = fd;
if (circuit->circ_type == CIRCUIT_T_BROADCAST) if (if_is_broadcast (circuit->interface))
{ {
/* /*
* Join to multicast groups * Join to multicast groups
@ -142,24 +142,22 @@ open_packet_socket (struct isis_circuit *circuit)
* 8.4.2 - Broadcast subnetwork IIH PDUs * 8.4.2 - Broadcast subnetwork IIH PDUs
* FIXME: is there a case only one will fail?? * FIXME: is there a case only one will fail??
*/ */
if (circuit->circuit_is_type & IS_LEVEL_1) if (circuit->is_type & IS_LEVEL_1)
{ /* joining ALL_L1_ISS */
/* joining ALL_L1_ISS */ retval = isis_multicast_join (circuit->fd, 1,
retval = isis_multicast_join (circuit->fd, 1, circuit->interface->ifindex);
circuit->interface->ifindex); if (circuit->is_type & IS_LEVEL_2)
/* joining ALL_ISS */ /* joining ALL_L2_ISS */
retval = isis_multicast_join (circuit->fd, 3, retval = isis_multicast_join (circuit->fd, 2,
circuit->interface->ifindex); circuit->interface->ifindex);
} /* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */
if (circuit->circuit_is_type & IS_LEVEL_2) retval = isis_multicast_join (circuit->fd, 3,
/* joining ALL_L2_ISS */ circuit->interface->ifindex);
retval = isis_multicast_join (circuit->fd, 2,
circuit->interface->ifindex);
} }
else else
{ {
retval = retval =
isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
} }
return retval; return retval;
@ -184,12 +182,13 @@ isis_sock_init (struct isis_circuit *circuit)
goto end; 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->tx = isis_send_pdu_bcast;
circuit->rx = isis_recv_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->tx = isis_send_pdu_p2p;
circuit->rx = isis_recv_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, LLC_LEN, MSG_PEEK,
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len); (struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
if (!circuit->area) {
return ISIS_OK;
}
if (bytesread < 0) if (bytesread < 0)
{ {
zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, "
circuit->fd, safe_strerror (errno)); "recvfrom(): %s",
zlog_warn ("circuit is %s", circuit->interface->name); circuit->interface->name, circuit->fd, bytesread,
zlog_warn ("circuit fd %d", circuit->fd); safe_strerror (errno));
zlog_warn ("bytesread %d", bytesread);
/* get rid of the packet */ /* 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; 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) if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
{ {
/* Read the packet into discard buff */ /* 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) if (bytesread < 0)
zlog_warn ("isis_recv_pdu_bcast(): read() failed"); zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
return ISIS_WARNING; return ISIS_WARNING;
} }
/* on lan we have to read to the static buff first */ /* 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); (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 */ /* then we lose the LLC */
stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN); 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) if (s_addr.sll_pkttype == PACKET_OUTGOING)
{ {
/* Read the packet into discard buff */ /* 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) if (bytesread < 0)
zlog_warn ("isis_recv_pdu_p2p(): read() failed"); zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed");
return ISIS_WARNING; return ISIS_WARNING;
} }
@ -313,6 +318,9 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
int int
isis_send_pdu_bcast (struct isis_circuit *circuit, int level) 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 /* we need to do the LLC in here because of P2P circuits, which will
* not need it * 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_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
sa.sll_ifindex = circuit->interface->ifindex; sa.sll_ifindex = circuit->interface->ifindex;
sa.sll_halen = ETH_ALEN; 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); memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
else else
memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); 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[1] = 0xFE;
sock_buff[2] = 0x03; sock_buff[2] = 0x03;
/* then we copy the data */ memset (&msg, 0, sizeof (msg));
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, msg.msg_name = &sa;
stream_get_endp (circuit->snd_stream)); 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 = sendmsg (circuit->fd, &msg, 0);
written = sendto (circuit->fd, sock_buff,
stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
(struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
return ISIS_OK; return ISIS_OK;
} }
@ -351,7 +365,6 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
int int
isis_send_pdu_p2p (struct isis_circuit *circuit, int level) isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
{ {
int written = 1; int written = 1;
struct sockaddr_ll sa; struct sockaddr_ll sa;

View File

@ -36,6 +36,7 @@
#include "isis_constants.h" #include "isis_constants.h"
#include "isis_common.h" #include "isis_common.h"
#include "isis_flags.h"
#include "dict.h" #include "dict.h"
#include "isisd.h" #include "isisd.h"
#include "isis_misc.h" #include "isis_misc.h"
@ -48,9 +49,6 @@
#include "isis_route.h" #include "isis_route.h"
#include "isis_zebra.h" #include "isis_zebra.h"
extern struct isis *isis;
extern struct thread_master *master;
static struct isis_nexthop * static struct isis_nexthop *
isis_nexthop_create (struct in_addr *ip, unsigned int ifindex) 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, nh = isis_nexthop_create (ipv4_addr,
adj->circuit->interface->ifindex); adj->circuit->interface->ifindex);
nh->router_address = adj->router_address;
listnode_add (nexthops, nh); listnode_add (nexthops, nh);
} }
} }
@ -269,6 +268,7 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
{ {
nh6 = isis_nexthop6_create (ipv6_addr, nh6 = isis_nexthop6_create (ipv6_addr,
adj->circuit->interface->ifindex); adj->circuit->interface->ifindex);
nh6->router_address6 = adj->router_address6;
listnode_add (nexthops6, nh6); listnode_add (nexthops6, nh6);
} }
} }
@ -276,8 +276,8 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
static struct isis_route_info * static struct isis_route_info *
isis_route_info_new (uint32_t cost, uint32_t depth, u_char family, isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
struct list *adjacencies) struct list *adjacencies)
{ {
struct isis_route_info *rinfo; struct isis_route_info *rinfo;
struct isis_adjacency *adj; struct isis_adjacency *adj;
@ -290,18 +290,34 @@ isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
return NULL; return NULL;
} }
if (family == AF_INET) if (prefix->family == AF_INET)
{ {
rinfo->nexthops = list_new (); rinfo->nexthops = list_new ();
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) 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 #ifdef HAVE_IPV6
if (family == AF_INET6) if (prefix->family == AF_INET6)
{ {
rinfo->nexthops6 = list_new (); rinfo->nexthops6 = list_new ();
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) 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 */ #endif /* HAVE_IPV6 */
@ -353,18 +369,25 @@ isis_route_info_same (struct isis_route_info *new,
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct isis_nexthop6 *nexthop6; struct isis_nexthop6 *nexthop6;
#endif /* HAVE_IPV6 */ #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)) if (!isis_route_info_same_attrib (new, old))
return 0; return 0;
if (family == AF_INET) if (family == AF_INET)
{ {
for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop)) 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) == 0)
return 0; return 0;
for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop)) 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) == 0)
return 0; return 0;
} }
@ -386,65 +409,6 @@ isis_route_info_same (struct isis_route_info *new,
return 1; 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 * struct isis_route_info *
isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth, isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
struct list *adjacencies, struct isis_area *area, 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 */ /* for debugs */
prefix2str (prefix, (char *) buff, BUFSIZ); 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) if (!rinfo_new)
{ {
zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!", 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 (!rinfo_old)
{ {
if (isis->debugs & DEBUG_RTE_EVENTS) if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff); zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE); route_info = rinfo_new;
route_node->info = rinfo_new; UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
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);
} }
else else
{ {
if (isis_route_info_prefer_new (rinfo_new, rinfo_old)) if (isis->debugs & DEBUG_RTE_EVENTS)
{ zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
if (isis->debugs & DEBUG_RTE_EVENTS) buff);
zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag, if (isis_route_info_same (rinfo_new, rinfo_old, family))
buff); {
isis_route_info_delete (rinfo_old); if (isis->debugs & DEBUG_RTE_EVENTS)
route_info = rinfo_new; zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
} buff);
isis_route_info_delete (rinfo_new);
route_info = rinfo_old;
}
else else
{ {
if (isis->debugs & DEBUG_RTE_EVENTS) if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag, zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
buff); buff);
isis_route_info_delete (rinfo_new); isis_route_info_delete (rinfo_old);
route_info = 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); SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
@ -570,7 +498,7 @@ isis_route_delete (struct prefix *prefix, struct route_table *table)
return; 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); UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
if (isis->debugs & DEBUG_RTE_EVENTS) 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) if (isis->debugs & DEBUG_RTE_EVENTS)
{ {
prefix2str (&rnode->p, (char *) buff, BUFSIZ); 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, area->area_tag,
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ? (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
"sync'ed" : "nosync"), "synced" : "not-synced"),
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
"resync" : "not-resync"),
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ? (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
"active" : "inactive"), buff); "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 /* Walk through route tables and propagate necessary changes into RIB. In case
* of L1L2 area, level tables have to be merged at first. */ * of L1L2 area, level tables have to be merged at first. */
int void
isis_route_validate (struct thread *thread) isis_route_validate (struct isis_area *area)
{ {
struct isis_area *area; struct listnode *node;
struct isis_circuit *circuit;
area = THREAD_ARG (thread);
if (area->is_type == IS_LEVEL_1) if (area->is_type == IS_LEVEL_1)
{ isis_route_validate_table (area, area->route_table[0]);
isis_route_validate_table (area, area->route_table[0]); else if (area->is_type == IS_LEVEL_2)
goto validate_ipv6; isis_route_validate_table (area, area->route_table[1]);
} else
if (area->is_type == IS_LEVEL_2) isis_route_validate_merge (area, AF_INET);
{
isis_route_validate_table (area, area->route_table[1]);
goto validate_ipv6;
}
isis_route_validate_merge (area, AF_INET);
validate_ipv6:
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (area->is_type == IS_LEVEL_1) if (area->is_type == IS_LEVEL_1)
{ isis_route_validate_table (area, area->route_table6[0]);
isis_route_validate_table (area, area->route_table6[0]); else if (area->is_type == IS_LEVEL_2)
return ISIS_OK; isis_route_validate_table (area, area->route_table6[1]);
} else
if (area->is_type == IS_LEVEL_2) isis_route_validate_merge (area, AF_INET6);
{
isis_route_validate_table (area, area->route_table6[1]);
return ISIS_OK;
}
isis_route_validate_merge (area, AF_INET6);
#endif #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]);
} }

View File

@ -30,6 +30,7 @@ struct isis_nexthop6
{ {
unsigned int ifindex; unsigned int ifindex;
struct in6_addr ip6; struct in6_addr ip6;
struct in6_addr router_address6;
unsigned int lock; unsigned int lock;
}; };
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -38,13 +39,15 @@ struct isis_nexthop
{ {
unsigned int ifindex; unsigned int ifindex;
struct in_addr ip; struct in_addr ip;
struct in_addr router_address;
unsigned int lock; unsigned int lock;
}; };
struct isis_route_info struct isis_route_info
{ {
#define ISIS_ROUTE_FLAG_ZEBRA_SYNC 0x01 #define ISIS_ROUTE_FLAG_ACTIVE 0x01 /* active route for the prefix */
#define ISIS_ROUTE_FLAG_ACTIVE 0x02 #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_char flag;
u_int32_t cost; u_int32_t cost;
u_int32_t depth; u_int32_t depth;
@ -59,6 +62,9 @@ struct isis_route_info *isis_route_create (struct prefix *prefix,
struct list *adjacencies, struct list *adjacencies,
struct isis_area *area, int level); 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 */ #endif /* _ZEBRA_ISIS_ROUTE_H */

View File

@ -35,6 +35,7 @@
#include "isis_constants.h" #include "isis_constants.h"
#include "isis_common.h" #include "isis_common.h"
#include "isis_flags.h"
#include "dict.h" #include "dict.h"
#include "isisd.h" #include "isisd.h"
#include "isis_misc.h" #include "isis_misc.h"

File diff suppressed because it is too large Load Diff

View File

@ -54,25 +54,33 @@ struct isis_vertex
struct prefix prefix; struct prefix prefix;
} N; } N;
struct isis_lsp *lsp;
u_int32_t d_N; /* d(N) Distance from this IS */ u_int32_t d_N; /* d(N) Distance from this IS */
u_int16_t depth; /* The depth in the imaginary tree */ u_int16_t depth; /* The depth in the imaginary tree */
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
struct list *Adj_N; /* {Adj(N)} */ struct list *parents; /* list of parents for ECMP */
struct list *children; /* list of children used for tree dump */
}; };
struct isis_spftree struct isis_spftree
{ {
struct thread *t_spf; /* spf threads */ struct thread *t_spf; /* spf threads */
time_t lastrun; /* for scheduling */
int pending; /* already scheduled */
struct list *paths; /* the SPT */ struct list *paths; /* the SPT */
struct list *tents; /* TENT */ struct list *tents; /* TENT */
struct isis_area *area; /* back pointer to area */
u_int32_t timerun; /* statistics */ 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_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); int isis_spf_schedule (struct isis_area *area, int level);
void isis_spf_cmds_init (void); void isis_spf_cmds_init (void);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6

View File

@ -43,13 +43,6 @@
#include "isisd/isis_pdu.h" #include "isisd/isis_pdu.h"
#include "isisd/isis_lsp.h" #include "isisd/isis_lsp.h"
extern struct isis *isis;
/*
* Prototypes.
*/
int add_tlv (u_char, u_char, u_char *, struct stream *);
void void
free_tlv (void *val) free_tlv (void *val)
{ {
@ -75,10 +68,10 @@ free_tlvs (struct tlvs *tlvs)
list_delete (tlvs->es_neighs); list_delete (tlvs->es_neighs);
if (tlvs->lsp_entries) if (tlvs->lsp_entries)
list_delete (tlvs->lsp_entries); list_delete (tlvs->lsp_entries);
if (tlvs->lan_neighs)
list_delete (tlvs->lan_neighs);
if (tlvs->prefix_neighs) if (tlvs->prefix_neighs)
list_delete (tlvs->prefix_neighs); list_delete (tlvs->prefix_neighs);
if (tlvs->lan_neighs)
list_delete (tlvs->lan_neighs);
if (tlvs->ipv4_addrs) if (tlvs->ipv4_addrs)
list_delete (tlvs->ipv4_addrs); list_delete (tlvs->ipv4_addrs);
if (tlvs->ipv4_int_reachs) if (tlvs->ipv4_int_reachs)
@ -93,7 +86,9 @@ free_tlvs (struct tlvs *tlvs)
if (tlvs->ipv6_reachs) if (tlvs->ipv6_reachs)
list_delete (tlvs->ipv6_reachs); list_delete (tlvs->ipv6_reachs);
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
memset (tlvs, 0, sizeof (struct tlvs));
return; return;
} }
@ -103,7 +98,7 @@ free_tlvs (struct tlvs *tlvs)
*/ */
int int
parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, 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; u_char type, length;
struct lan_neigh *lan_nei; 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 */ #endif /* HAVE_IPV6 */
u_char virtual; u_char virtual;
int value_len, retval = ISIS_OK; int value_len, retval = ISIS_OK;
u_char *pnt = stream; u_char *start = stream, *pnt = stream;
*found = 0; *found = 0;
memset (tlvs, 0, sizeof (struct tlvs)); 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) if (*expected & TLVFLAG_AUTH_INFO)
{ {
tlvs->auth_info.type = *pnt; 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++; pnt++;
memcpy (tlvs->auth_info.passwd, pnt, length - 1); memcpy (tlvs->auth_info.passwd, pnt, length);
/* Fill authentication with 0 for later computation /* Return the authentication tlv pos for later computation
* of MD5 (RFC 5304, 2) * of MD5 (RFC 5304, 2)
*/ */
memset (pnt, 0, length - 1); if (auth_tlv_offset)
pnt += length - 1; *auth_tlv_offset += (pnt - start - 3);
pnt += length;
} }
else else
{ {
@ -734,10 +737,14 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
int int
add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream) add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
{ {
if ((stream_get_size (stream) - stream_get_endp (stream)) <
if (STREAM_SIZE (stream) - stream_get_endp (stream) < (unsigned) len + 2) (((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; 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_putc (stream, len); /* LENGTH */
stream_put (stream, value, (int) len); /* VALUE */ stream_put (stream, value, (int) len); /* VALUE */
#ifdef EXTREME_TLV_DEBUG #ifdef EXTREME_DEBUG
zlog_debug ("Added TLV %d len %d", tag, len); zlog_debug ("Added TLV %d len %d", tag, len);
#endif /* EXTREME DEBUG */ #endif /* EXTREME DEBUG */
return ISIS_OK; return ISIS_OK;
@ -877,7 +884,7 @@ tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
} }
int 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) struct stream *stream)
{ {
u_char value[255]; u_char value[255];
@ -1006,7 +1013,6 @@ tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
pos += IPV4_MAX_BYTELEN; pos += IPV4_MAX_BYTELEN;
} }
return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream); 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) if (pos - value + (5 + prefix_size) > 255)
{ {
retval = retval =
add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream); add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
if (retval != ISIS_OK) if (retval != ISIS_OK)
return retval; return retval;
pos = value; pos = value;
@ -1110,7 +1116,7 @@ tlv_add_padding (struct stream *stream)
/* /*
* How many times can we add full padding ? * 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++) for (i = 0; i < fullpads; i++)
{ {
if (!stream_putc (stream, (u_char) PADDING)) /* TAG */ 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 */ 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) if (left < 2)
return ISIS_OK; return ISIS_OK;

View File

@ -30,7 +30,7 @@
* Name Value IIH LSP SNP Status * Name Value IIH LSP SNP Status
* LAN * LAN
* ____________________________________________________________________________ * ____________________________________________________________________________
* *
* Area Addresses 1 y y n ISO10589 * Area Addresses 1 y y n ISO10589
* IIS Neighbors 2 n y n ISO10589 * IIS Neighbors 2 n y n ISO10589
* ES Neighbors 3 n y n ISO10589 * ES Neighbors 3 n y n ISO10589
@ -39,52 +39,52 @@
* LSP Entries 9 n n y ISO10589 * LSP Entries 9 n n y ISO10589
* Authentication 10 y y y ISO10589, RFC3567 * Authentication 10 y y y ISO10589, RFC3567
* Checksum 12 y n y RFC3358 * 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 * IS Alias 24 n y n RFC3786
* IP Int. Reachability 128 n y n RFC1195 * IP Int. Reachability 128 n y n RFC1195
* Protocols Supported 129 y y n RFC1195 * Protocols Supported 129 y y n RFC1195
* IP Ext. Reachability 130 n y n RFC1195 * IP Ext. Reachability 130 n y n RFC1195
* IDRPI 131 n y y RFC1195 * IDRPI 131 n y y RFC1195
* IP Interface Address 132 y y n RFC1195 * IP Interface Address 132 y y n RFC1195
* TE Router ID 134 n y n RFC3784 * TE Router ID 134 n y n RFC5305
* Extended IP Reachability 135 n y n RFC3784 * Extended IP Reachability 135 n y n RFC5305
* Dynamic Hostname 137 n y n RFC2763 * 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 * Restart TLV 211 y n n RFC3847
* MT IS Reachability 222 n y n draft-ietf-isis-wg-multi-topology * MT IS Reachability 222 n y n RFC5120
* MT Supported 229 y y n draft-ietf-isis-wg-multi-topology * MT Supported 229 y y n RFC5120
* IPv6 Interface Address 232 y y n draft-ietf-isis_ipv6 * IPv6 Interface Address 232 y y n RFC5308
* MT IP Reachability 235 n y n draft-ietf-isis-wg-multi-topology * MT IP Reachability 235 n y n RFC5120
* IPv6 IP Reachability 236 n y n draft-ietf-isis_ipv6 * IPv6 IP Reachability 236 n y n RFC5308
* MT IPv6 IP Reachability 237 n y n draft-ietf-isis-wg-multi-topology * MT IPv6 IP Reachability 237 n y n RFC5120
* P2P Adjacency State 240 y n n RFC3373 * P2P Adjacency State 240 y n n RFC3373
* IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence * IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence
* Router Capability 242 - - - draft-ietf-isis-caps * Router Capability 242 - - - draft-ietf-isis-caps
* *
* *
* IS Reachability sub-TLVs we (should) support. * IS Reachability sub-TLVs we (should) support.
* ____________________________________________________________________________ * ____________________________________________________________________________
* Name Value Status * Name Value Status
* ____________________________________________________________________________ * ____________________________________________________________________________
* Administartive group (color) 3 RFC3784 * Administartive group (color) 3 RFC5305
* Link Local/Remote Identifiers 4 draft-ietf-isis-gmpls-extensions * Link Local/Remote Identifiers 4 RFC5307
* IPv4 interface address 6 RFC3784 * IPv4 interface address 6 RFC5305
* IPv4 neighbor address 8 RFC3784 * IPv4 neighbor address 8 RFC5305
* Maximum link bandwidth 9 RFC3784 * Maximum link bandwidth 9 RFC5305
* Reservable link bandwidth 10 RFC3784 * Reservable link bandwidth 10 RFC5305
* Unreserved bandwidth 11 RFC3784 * Unreserved bandwidth 11 RFC5305
* TE Default metric 18 RFC3784 * TE Default metric 18 RFC5305
* Link Protection Type 20 draft-ietf-isis-gmpls-extensions * Link Protection Type 20 RFC5307
* Interface Switching Capability 21 draft-ietf-isis-gmpls-extensions * Interface Switching Capability 21 RFC5307
*
* *
*
* IP Reachability sub-TLVs we (should) support. * IP Reachability sub-TLVs we (should) support.
* ____________________________________________________________________________ * ____________________________________________________________________________
* Name Value Status * Name Value Status
* ____________________________________________________________________________ * ____________________________________________________________________________
* 32bit administrative tag 1 draft-ietf-isis-admin-tags * 32bit administrative tag 1 RFC5130
* 64bit administrative tag 2 draft-ietf-isis-admin-tags * 64bit administrative tag 2 RFC5130
* Management prefix color 117 draft-ietf-isis-wg-multi-topology * Management prefix color 117 RFC5120
*/ */
#define AREA_ADDRESSES 1 #define AREA_ADDRESSES 1
@ -110,11 +110,14 @@
#define IPV6_REACHABILITY 236 #define IPV6_REACHABILITY 236
#define WAY3_HELLO 240 #define WAY3_HELLO 240
#define AUTH_INFO_HDRLEN 3
#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5) #define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5)
#define LAN_NEIGHBOURS_LEN 6 #define LAN_NEIGHBOURS_LEN 6
#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */ #define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */
#define IPV4_REACH_LEN 12 #define IPV4_REACH_LEN 12
#define IPV6_REACH_LEN 22 #define IPV6_REACH_LEN 22
#define TE_IPV4_REACH_LEN 9
/* struct for neighbor */ /* struct for neighbor */
struct is_neigh struct is_neigh
@ -131,6 +134,15 @@ struct te_is_neigh
u_char sub_tlvs_length; 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 for es neighbors */
struct es_neigh struct es_neigh
{ {
@ -213,7 +225,6 @@ struct ipv6_reachability
u_char prefix_len; u_char prefix_len;
u_char prefix[16]; u_char prefix[16];
}; };
#endif /* HAVE_IPV6 */
/* bits in control_info */ /* bits in control_info */
#define CTRL_INFO_DIRECTION 0x80 #define CTRL_INFO_DIRECTION 0x80
@ -223,12 +234,17 @@ struct ipv6_reachability
#define DISTRIBUTION_INTERNAL 0 #define DISTRIBUTION_INTERNAL 0
#define DISTRIBUTION_EXTERNAL 1 #define DISTRIBUTION_EXTERNAL 1
#define CTRL_INFO_SUBTLVS 0x20 #define CTRL_INFO_SUBTLVS 0x20
#endif /* HAVE_IPV6 */
/* /*
* Pointer to each tlv type, filled by parse_tlvs() * Pointer to each tlv type, filled by parse_tlvs()
*/ */
struct tlvs struct tlvs
{ {
struct checksum *checksum;
struct hostname *hostname;
struct nlpids *nlpids;
struct te_router_id *router_id;
struct list *area_addrs; struct list *area_addrs;
struct list *is_neighs; struct list *is_neighs;
struct list *te_is_neighs; struct list *te_is_neighs;
@ -236,14 +252,10 @@ struct tlvs
struct list *lsp_entries; struct list *lsp_entries;
struct list *prefix_neighs; struct list *prefix_neighs;
struct list *lan_neighs; struct list *lan_neighs;
struct checksum *checksum;
struct nlpids *nlpids;
struct list *ipv4_addrs; struct list *ipv4_addrs;
struct list *ipv4_int_reachs; struct list *ipv4_int_reachs;
struct list *ipv4_ext_reachs; struct list *ipv4_ext_reachs;
struct list *te_ipv4_reachs; struct list *te_ipv4_reachs;
struct hostname *hostname;
struct te_router_id *router_id;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct list *ipv6_addrs; struct list *ipv6_addrs;
struct list *ipv6_reachs; struct list *ipv6_reachs;
@ -281,7 +293,9 @@ struct tlvs
void init_tlvs (struct tlvs *tlvs, uint32_t expected); void init_tlvs (struct tlvs *tlvs, uint32_t expected);
void free_tlvs (struct tlvs *tlvs); void free_tlvs (struct tlvs *tlvs);
int parse_tlvs (char *areatag, u_char * stream, int size, 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); void free_tlv (void *val);
int tlv_add_area_addrs (struct list *area_addrs, struct stream *stream); 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_lan_neighs (struct list *lan_neighs, struct stream *stream);
int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream); int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream);
int tlv_add_checksum (struct checksum *checksum, struct stream *stream); int tlv_add_checksum (struct checksum *checksum, struct stream *stream);
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); struct stream *stream);
int tlv_add_ip_addrs (struct list *ip_addrs, 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); int tlv_add_in_addr (struct in_addr *, struct stream *stream, u_char tag);

View File

@ -36,30 +36,37 @@
#include "isisd/dict.h" #include "isisd/dict.h"
#include "isisd/isis_constants.h" #include "isisd/isis_constants.h"
#include "isisd/isis_common.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/isisd.h"
#include "isisd/isis_circuit.h" #include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h" #include "isisd/isis_csm.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h" #include "isisd/isis_route.h"
#include "isisd/isis_zebra.h" #include "isisd/isis_zebra.h"
struct zclient *zclient = NULL; 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. */ /* Router-id update message from zebra. */
static int static int
isis_router_id_update_zebra (int command, struct zclient *zclient, isis_router_id_update_zebra (int command, struct zclient *zclient,
zebra_size_t length) zebra_size_t length)
{ {
struct isis_area *area;
struct listnode *node;
struct prefix router_id; struct prefix router_id;
zebra_router_id_update_read (zclient->ibuf,&router_id); zebra_router_id_update_read (zclient->ibuf, &router_id);
router_id_zebra = router_id.u.prefix4; 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; 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", 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); 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 /* Cannot call if_delete because we should retain the pseudo interface
in case there is configuration info attached to it. */ in case there is configuration info attached to it. */
if_delete_retain(ifp); if_delete_retain(ifp);
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
ifp->ifindex = IFINDEX_INTERNAL; ifp->ifindex = IFINDEX_INTERNAL;
return 0; 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 static int
isis_zebra_if_state_up (int command, struct zclient *zclient, isis_zebra_if_state_up (int command, struct zclient *zclient,
zebra_size_t length) zebra_size_t length)
{ {
struct interface *ifp; struct interface *ifp;
ifp = zebra_interface_if_lookup (zclient->ibuf); ifp = zebra_interface_state_read (zclient->ibuf);
if (!ifp) if (ifp == NULL)
return 0; 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); isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
return 0; return 0;
@ -157,17 +139,17 @@ isis_zebra_if_state_down (int command, struct zclient *zclient,
zebra_size_t length) zebra_size_t length)
{ {
struct interface *ifp; struct interface *ifp;
struct isis_circuit *circuit;
ifp = zebra_interface_if_lookup (zclient->ibuf); ifp = zebra_interface_state_read (zclient->ibuf);
if (ifp == NULL) if (ifp == NULL)
return 0; return 0;
if (if_is_operative (ifp)) circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
{ ifp);
zebra_interface_if_set_value (zclient->ibuf, ifp); if (circuit)
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp); SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
}
return 0; return 0;
} }
@ -251,7 +233,7 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
struct listnode *node; 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; return;
if (zclient->redist[ZEBRA_ROUTE_ISIS]) 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)); stream_putw_at (stream, 0, stream_get_endp (stream));
zclient_send_message(zclient); 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; prefix4.prefix = prefix->u.prefix4;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api); 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; return;
} }
@ -347,7 +330,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
struct listnode *node; struct listnode *node;
struct prefix_ipv6 prefix6; 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; return;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
@ -410,7 +393,8 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
prefix6.prefixlen = prefix->prefixlen; prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr)); memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api); 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); XFREE (MTYPE_ISIS_TMP, nexthop_list);
@ -431,7 +415,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
struct listnode *node; struct listnode *node;
struct prefix_ipv6 prefix6; 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; return;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
@ -488,7 +472,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
prefix6.prefixlen = prefix->prefixlen; prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr)); memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api); 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); XFREE (MTYPE_ISIS_TMP, nexthop_list);

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@ struct isis
u_long process_id; u_long process_id;
int sysid_set; int sysid_set;
u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ 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 *area_list; /* list of IS-IS areas */
struct list *init_circ_list; struct list *init_circ_list;
struct list *nexthops; /* IPv4 next hops from this IS */ struct list *nexthops; /* IPv4 next hops from this IS */
@ -78,6 +79,8 @@ struct isis
#endif #endif
}; };
extern struct isis *isis;
struct isis_area struct isis_area
{ {
struct isis *isis; /* back pointer */ struct isis *isis; /* back pointer */
@ -92,11 +95,8 @@ struct isis_area
struct list *circuit_list; /* IS-IS circuits */ struct list *circuit_list; /* IS-IS circuits */
struct flags flags; struct flags flags;
struct thread *t_tick; /* LSP walker */ 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]; struct thread *t_lsp_refresh[ISIS_LEVELS];
int lsp_regenerate_pending[ISIS_LEVELS];
/* /*
* Configurables * Configurables
@ -114,6 +114,8 @@ struct isis_area
struct list *area_addrs; struct list *area_addrs;
u_int16_t max_lsp_lifetime[ISIS_LEVELS]; u_int16_t max_lsp_lifetime[ISIS_LEVELS];
char is_type; /* level-1 level-1-2 or level-2-only */ 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]; u_int16_t lsp_refresh[ISIS_LEVELS];
/* minimum time allowed before lsp retransmission */ /* minimum time allowed before lsp retransmission */
u_int16_t lsp_gen_interval[ISIS_LEVELS]; 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 */ /* the percentage of LSP mtu size used, before generating a new frag */
int lsp_frag_threshold; int lsp_frag_threshold;
int ip_circuits; int ip_circuits;
/* logging adjacency changes? */
u_char log_adj_changes;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int ipv6_circuits; int ipv6_circuits;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -130,14 +134,21 @@ struct isis_area
#ifdef TOPOLOGY_GENERATE #ifdef TOPOLOGY_GENERATE
struct list *topology; 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 *topology_basedynh; /* Dynamic hostname base. */
char top_params[200]; /* FIXME: what is reasonable? */ char top_params[200]; /* FIXME: what is reasonable? */
#endif /* TOPOLOGY_GENERATE */ #endif /* TOPOLOGY_GENERATE */
}; };
void isis_init (void); 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 *); 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_ADJ_PACKETS (1<<0)
#define DEBUG_CHECKSUM_ERRORS (1<<1) #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_RTE_EVENTS (1<<9)
#define DEBUG_EVENTS (1<<10) #define DEBUG_EVENTS (1<<10)
#define DEBUG_ZEBRA (1<<11) #define DEBUG_ZEBRA (1<<11)
#define DEBUG_PACKET_DUMP (1<<12)
#endif /* ISISD_H */ #endif /* ISISD_H */

View File

@ -146,7 +146,7 @@ if_delete_retain (struct interface *ifp)
(*if_master.if_delete_hook) (ifp); (*if_master.if_delete_hook) (ifp);
/* Free connected address list */ /* Free connected address list */
list_delete (ifp->connected); list_delete_all_node (ifp->connected);
} }
/* Delete and free interface structure. */ /* Delete and free interface structure. */
@ -157,6 +157,8 @@ if_delete (struct interface *ifp)
if_delete_retain(ifp); if_delete_retain(ifp);
list_free (ifp->connected);
XFREE (MTYPE_IF, ifp); XFREE (MTYPE_IF, ifp);
} }

View File

@ -54,9 +54,9 @@ struct list
void (*del) (void *val); void (*del) (void *val);
}; };
#define listnextnode(X) ((X)->next) #define listnextnode(X) ((X) ? ((X)->next) : NULL)
#define listhead(X) ((X)->head) #define listhead(X) ((X) ? ((X)->head) : NULL)
#define listtail(X) ((X)->tail) #define listtail(X) ((X) ? ((X)->tail) : NULL)
#define listcount(X) ((X)->count) #define listcount(X) ((X)->count)
#define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) #define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL)
#define listgetdata(X) (assert((X)->data != NULL), (X)->data) #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. * It is safe to delete the listnode using this macro.
*/ */
#define ALL_LIST_ELEMENTS(list,node,nextnode,data) \ #define ALL_LIST_ELEMENTS(list,node,nextnode,data) \
(node) = listhead(list); \ (node) = listhead(list), ((data) = NULL); \
(node) != NULL && \ (node) != NULL && \
((data) = listgetdata(node),(nextnode) = listnextnode(node), 1); \ ((data) = listgetdata(node),(nextnode) = listnextnode(node), 1); \
(node) = (nextnode) (node) = (nextnode), ((data) = NULL)
/* read-only list iteration macro. /* read-only list iteration macro.
* Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only * 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. * of previous macro.
*/ */
#define ALL_LIST_ELEMENTS_RO(list,node,data) \ #define ALL_LIST_ELEMENTS_RO(list,node,data) \
(node) = listhead(list); \ (node) = listhead(list), ((data) = NULL);\
(node) != NULL && ((data) = listgetdata(node), 1); \ (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 /* 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. * do - these macros simply {de,at}tach a listnode from/to a list.

View File

@ -83,6 +83,7 @@ do { \
} while (0) } while (0)
/* From RFC 2104 */ /* 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_*/ #endif /* ! _LIBZEBRA_MD5_H_*/

View File

@ -248,6 +248,8 @@ struct memory_list memory_list_isis[] =
{ MTYPE_ISIS_ROUTE_INFO, "ISIS route info" }, { MTYPE_ISIS_ROUTE_INFO, "ISIS route info" },
{ MTYPE_ISIS_NEXTHOP, "ISIS nexthop" }, { MTYPE_ISIS_NEXTHOP, "ISIS nexthop" },
{ MTYPE_ISIS_NEXTHOP6, "ISIS nexthop6" }, { MTYPE_ISIS_NEXTHOP6, "ISIS nexthop6" },
{ MTYPE_ISIS_DICT, "ISIS dictionary" },
{ MTYPE_ISIS_DICT_NODE, "ISIS dictionary node" },
{ -1, NULL }, { -1, NULL },
}; };

View File

@ -52,7 +52,7 @@
* using stream_put..._at() functions. * using stream_put..._at() functions.
*/ */
#define STREAM_WARN_OFFSETS(S) \ #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), \ (S), \
(unsigned long) (S)->size, \ (unsigned long) (S)->size, \
(unsigned long) (S)->getp, \ (unsigned long) (S)->getp, \
@ -214,6 +214,20 @@ stream_set_getp (struct stream *s, size_t pos)
s->getp = 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. */ /* Forward pointer. */
void void
stream_forward_getp (struct stream *s, size_t size) stream_forward_getp (struct stream *s, size_t size)
@ -934,9 +948,9 @@ stream_fifo_pop (struct stream_fifo *fifo)
if (fifo->head == NULL) if (fifo->head == NULL)
fifo->tail = NULL; fifo->tail = NULL;
}
fifo->count--; fifo->count--;
}
return s; return s;
} }

View File

@ -146,6 +146,7 @@ extern size_t stream_get_size (struct stream *);
extern u_char *stream_get_data (struct stream *); extern u_char *stream_get_data (struct stream *);
extern void stream_set_getp (struct stream *, size_t); 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_getp (struct stream *, size_t);
extern void stream_forward_endp (struct stream *, size_t); extern void stream_forward_endp (struct stream *, size_t);

View File

@ -654,24 +654,8 @@ zebra_interface_add_read (struct stream *s)
/* Lookup/create interface by name. */ /* Lookup/create interface by name. */
ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ)); ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));
/* Read interface's index. */ zebra_interface_if_set_value (s, ifp);
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);
#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; return ifp;
} }
@ -699,16 +683,7 @@ zebra_interface_state_read (struct stream *s)
if (! ifp) if (! ifp)
return NULL; return NULL;
/* Read interface's index. */ zebra_interface_if_set_value (s, ifp);
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);
return ifp; return ifp;
} }
@ -758,6 +733,13 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
ifp->mtu = stream_getl (s); ifp->mtu = stream_getl (s);
ifp->mtu6 = stream_getl (s); ifp->mtu6 = stream_getl (s);
ifp->bandwidth = 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 static int

View File

@ -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_blackhole_add (struct rib *);
extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *, extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
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_dump (struct prefix_ipv4 *);
extern void rib_lookup_and_pushup (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 *); extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *);

View File

@ -32,6 +32,7 @@
#include "prefix.h" #include "prefix.h"
#include "connected.h" #include "connected.h"
#include "table.h" #include "table.h"
#include "memory.h"
#include "rib.h" #include "rib.h"
#include "thread.h" #include "thread.h"
#include "privs.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 /* Called from interface_lookup_netlink(). This function is only used
during bootstrap. */ during bootstrap. */
static int static int
@ -436,7 +468,6 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *tb[IFLA_MAX + 1];
struct interface *ifp; struct interface *ifp;
char *name; char *name;
int i;
ifi = NLMSG_DATA (h); ifi = NLMSG_DATA (h);
@ -474,30 +505,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Hardware type and address. */ /* Hardware type and address. */
ifp->hw_type = ifi->ifi_type; ifp->hw_type = ifi->ifi_type;
netlink_interface_update_hw_addr (tb, ifp);
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;
}
}
if_add_update (ifp); if_add_update (ifp);
@ -709,7 +717,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (tb[RTA_PREFSRC]) if (tb[RTA_PREFSRC])
src = RTA_DATA (tb[RTA_PREFSRC]); src = RTA_DATA (tb[RTA_PREFSRC]);
/* Multipath treatment is needed. */
if (tb[RTA_GATEWAY]) if (tb[RTA_GATEWAY])
gate = RTA_DATA (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); memcpy (&p.prefix, dest, 4);
p.prefixlen = rtm->rtm_dst_len; 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 #ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6) 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) 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 else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST); 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->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1; ifp->metric = 1;
netlink_interface_update_hw_addr (tb, ifp);
/* If new link is added. */ /* If new link is added. */
if_add_update (ifp); 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->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1; ifp->metric = 1;
netlink_interface_update_hw_addr (tb, ifp);
if (if_is_operative (ifp)) if (if_is_operative (ifp))
{ {
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;

View File

@ -232,7 +232,7 @@ nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
return nexthop; return nexthop;
} }
static struct nexthop * struct nexthop *
nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
struct in_addr *src, unsigned int ifindex) 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 static void
rib_queue_add (struct zebra_t *zebra, struct route_node *rn) rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
{ {
char buf[INET_ADDRSTRLEN];
assert (zebra && rn);
if (IS_ZEBRA_DEBUG_RIB_Q) if (IS_ZEBRA_DEBUG_RIB_Q)
{ inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
char buf[INET6_ADDRSTRLEN];
zlog_info ("%s: %s/%d: work queue added", __func__, /* Pointless to queue a route_node with no RIB entries to add or remove */
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN), if (!rn->info)
rn->p.prefixlen); {
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); work_queue_add (zebra->ribq, zebra->mq);
rib_meta_queue_add (zebra->mq, rn); 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. /* Create new meta queue.
@ -1328,6 +1349,8 @@ meta_queue_new (void)
static void static void
rib_queue_init (struct zebra_t *zebra) rib_queue_init (struct zebra_t *zebra)
{ {
assert (zebra);
if (! (zebra->ribq = work_queue_new (zebra->master, if (! (zebra->ribq = work_queue_new (zebra->master,
"route_node processing"))) "route_node processing")))
{ {
@ -1343,7 +1366,11 @@ rib_queue_init (struct zebra_t *zebra)
zebra->ribq->spec.hold = rib_process_hold_time; zebra->ribq->spec.hold = rib_process_hold_time;
if (!(zebra->mq = meta_queue_new ())) if (!(zebra->mq = meta_queue_new ()))
{
zlog_err ("%s: could not initialise meta queue!", __func__); zlog_err ("%s: could not initialise meta queue!", __func__);
return;
}
return;
} }
/* RIB updates are processed via a queue of pointers to route_nodes. /* 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_IP, SAFI_UNICAST, 0));
rib_sweep_table (vrf_table (AFI_IP6, 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'. */ /* Remove specific by protocol routes from 'table'. */
static unsigned long static unsigned long

View File

@ -140,6 +140,30 @@ zserv_create_header (struct stream *s, uint16_t cmd)
stream_putw (s, 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. */ /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
/* /*
* This function is called in the following situations: * This function is called in the following situations:
@ -163,28 +187,8 @@ zsend_interface_add (struct zserv *client, struct interface *ifp)
s = client->obuf; s = client->obuf;
stream_reset (s); stream_reset (s);
/* Message type. */
zserv_create_header (s, ZEBRA_INTERFACE_ADD); zserv_create_header (s, ZEBRA_INTERFACE_ADD);
zserv_encode_interface (s, 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));
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
@ -201,21 +205,9 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp)
s = client->obuf; s = client->obuf;
stream_reset (s); 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. */ zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
stream_putw_at (s, 0, stream_get_endp (s)); zserv_encode_interface (s, ifp);
return zebra_server_send_message (client); return zebra_server_send_message (client);
} }
@ -328,19 +320,7 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
stream_reset (s); stream_reset (s);
zserv_create_header (s, cmd); zserv_create_header (s, cmd);
zserv_encode_interface (s, 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);
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
@ -761,6 +741,13 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* Type, flags, message. */ /* Type, flags, message. */
rib->type = stream_getc (s); 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); rib->flags = stream_getc (s);
message = stream_getc (s); message = stream_getc (s);
safi = stream_getw (s); safi = stream_getw (s);
@ -798,10 +785,10 @@ zread_ipv4_add (struct zserv *client, u_short length)
case ZEBRA_NEXTHOP_IPV6: case ZEBRA_NEXTHOP_IPV6:
stream_forward_getp (s, IPV6_MAX_BYTELEN); stream_forward_getp (s, IPV6_MAX_BYTELEN);
break; break;
case ZEBRA_NEXTHOP_BLACKHOLE: case ZEBRA_NEXTHOP_BLACKHOLE:
nexthop_blackhole_add (rib); nexthop_blackhole_add (rib);
break; break;
} }
} }
} }
@ -826,7 +813,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
int i; int i;
struct stream *s; struct stream *s;
struct zapi_ipv4 api; struct zapi_ipv4 api;
struct in_addr nexthop; struct in_addr nexthop, *nexthop_p;
unsigned long ifindex; unsigned long ifindex;
struct prefix_ipv4 p; struct prefix_ipv4 p;
u_char nexthop_num; u_char nexthop_num;
@ -836,6 +823,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
s = client->ibuf; s = client->ibuf;
ifindex = 0; ifindex = 0;
nexthop.s_addr = 0; nexthop.s_addr = 0;
nexthop_p = NULL;
/* Type, flags, message. */ /* Type, flags, message. */
api.type = stream_getc (s); api.type = stream_getc (s);
@ -869,6 +857,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
break; break;
case ZEBRA_NEXTHOP_IPV4: case ZEBRA_NEXTHOP_IPV4:
nexthop.s_addr = stream_get_ipv4 (s); nexthop.s_addr = stream_get_ipv4 (s);
nexthop_p = &nexthop;
break; break;
case ZEBRA_NEXTHOP_IPV6: case ZEBRA_NEXTHOP_IPV6:
stream_forward_getp (s, IPV6_MAX_BYTELEN); stream_forward_getp (s, IPV6_MAX_BYTELEN);
@ -889,7 +878,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
else else
api.metric = 0; 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); client->rtm_table, api.safi);
return 0; return 0;
} }
@ -935,6 +924,11 @@ zread_ipv6_add (struct zserv *client, u_short length)
/* Type, flags, message. */ /* Type, flags, message. */
api.type = stream_getc (s); 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.flags = stream_getc (s);
api.message = stream_getc (s); api.message = stream_getc (s);
api.safi = stream_getw (s); api.safi = stream_getw (s);
@ -1133,6 +1127,14 @@ zebra_score_rib (int client_sock)
static void static void
zebra_client_close (struct zserv *client) 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. */ /* Close file descriptor. */
if (client->sock) if (client->sock)
{ {
@ -1172,6 +1174,9 @@ zebra_client_create (int sock)
/* Make client input/output buffer. */ /* Make client input/output buffer. */
client->sock = sock; 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->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
client->wb = buffer_new(0); client->wb = buffer_new(0);

View File

@ -38,6 +38,10 @@ struct zserv
/* Client file descriptor. */ /* Client file descriptor. */
int sock; int sock;
/* Client route type. */
/* Assuming each client contains only one type of route. */
int route_type;
/* Input/output buffer to the client. */ /* Input/output buffer to the client. */
struct stream *ibuf; struct stream *ibuf;
struct stream *obuf; struct stream *obuf;