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>
Ofer Wald <ofersf@islands.co.il>
Hannes Gredler <hannes@gredler.at>
Subbaiah Venkata <svenkata@google.com>

View File

@ -15,17 +15,11 @@
* contain a copyright notice related to this source.
*/
#include <stdlib.h>
#include <stddef.h>
#include "zebra.h"
#include "zassert.h"
#define DICT_IMPLEMENTATION
#include "memory.h"
#include "dict.h"
#ifdef KAZLIB_RCSID
static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
#endif
/*
* These macros provide short convenient names for structure members,
* which are embellished with dict_ prefixes so that they are
@ -243,7 +237,7 @@ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
{
dict_t *new = malloc(sizeof *new);
dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t));
if (new) {
new->compare = comp;
@ -284,7 +278,7 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
void dict_destroy(dict_t *dict)
{
assert (dict_isempty(dict));
free(dict);
XFREE(MTYPE_ISIS_DICT, dict);
}
/*
@ -307,9 +301,6 @@ void dict_free_nodes(dict_t *dict)
void dict_free(dict_t *dict)
{
#ifdef KAZLIB_OBSOLESCENT_DEBUG
assert ("call to obsolescent function dict_free()" && 0);
#endif
dict_free_nodes(dict);
}
@ -810,7 +801,7 @@ dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
int dict_alloc_insert(dict_t *dict, const void *key, void *data)
{
dnode_t *node = dict->allocnode(dict->context);
dnode_t *node = dict->allocnode (dict->context);
if (node) {
dnode_init(node, data);
@ -946,17 +937,17 @@ int dict_contains(dict_t *dict, dnode_t *node)
static dnode_t *dnode_alloc(void *context)
{
return malloc(sizeof *dnode_alloc(NULL));
return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
}
static void dnode_free(dnode_t *node, void *context)
{
free(node);
XFREE(MTYPE_ISIS_DICT_NODE, node);
}
dnode_t *dnode_create(void *data)
{
dnode_t *new = malloc(sizeof *new);
dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
if (new) {
new->data = data;
new->parent = NULL;
@ -978,7 +969,7 @@ dnode_t *dnode_init(dnode_t *dnode, void *data)
void dnode_destroy(dnode_t *dnode)
{
assert (!dnode_is_in_a_dict(dnode));
free(dnode);
XFREE(MTYPE_ISIS_DICT_NODE, dnode);
}
void *dnode_get(dnode_t *dnode)
@ -1232,7 +1223,7 @@ static int comparef(const void *key1, const void *key2)
static char *dupstring(char *str)
{
int sz = strlen(str) + 1;
char *new = malloc(sz);
char *new = XCALLOC(MTYPE_ISIS_TMP, sz);
if (new)
memcpy(new, str, sz);
return new;
@ -1347,7 +1338,7 @@ int main(void)
"s switch to non-functioning allocator\n"
"q quit";
for (i = 0; i < sizeof darray / sizeof *darray; i++)
for (i = 0; i < 10; i++)
dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
for (;;) {

View File

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

View File

@ -36,6 +36,7 @@
#include "isisd/include-netbsd/iso.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isisd.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_adjacency.h"
@ -43,6 +44,10 @@
#include "isisd/isis_dr.h"
#include "isisd/isis_dynhn.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_events.h"
extern struct isis *isis;
@ -73,9 +78,9 @@ isis_new_adj (u_char * id, u_char * snpa, int level,
}
if (snpa) {
memcpy (adj->snpa, snpa, 6);
memcpy (adj->snpa, snpa, ETH_ALEN);
} else {
memset (adj->snpa, ' ', 6);
memset (adj->snpa, ' ', ETH_ALEN);
}
adj->circuit = circuit;
@ -125,16 +130,20 @@ isis_adj_lookup_snpa (u_char * ssnpa, struct list *adjdb)
}
void
isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb)
isis_delete_adj (void *arg)
{
struct isis_adjacency *adj = arg;
if (!adj)
return;
/* When we recieve a NULL list, we will know its p2p. */
if (adjdb)
listnode_delete (adjdb, adj);
THREAD_OFF (adj->t_expire);
THREAD_TIMER_OFF (adj->t_expire);
/* remove from SPF trees */
spftree_area_adj_del (adj->circuit->area, adj);
if (adj->area_addrs)
list_delete (adj->area_addrs);
if (adj->ipv4_addrs)
list_delete (adj->ipv4_addrs);
#ifdef HAVE_IPV6
@ -146,16 +155,35 @@ isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb)
return;
}
static const char *
adj_state2string (int state)
{
switch (state)
{
case ISIS_ADJ_INITIALIZING:
return "Initializing";
case ISIS_ADJ_UP:
return "Up";
case ISIS_ADJ_DOWN:
return "Down";
default:
return "Unknown";
}
return NULL; /* not reached */
}
void
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state,
const char *reason)
{
int old_state;
int level = adj->level;
int level;
struct isis_circuit *circuit;
old_state = adj->adj_state;
adj->adj_state = state;
adj->adj_state = new_state;
circuit = adj->circuit;
@ -163,27 +191,81 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
{
zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
circuit->area->area_tag,
old_state, state, reason ? reason : "unspecified");
old_state, new_state, reason ? reason : "unspecified");
}
if (circuit->area->log_adj_changes)
{
const char *adj_name;
struct isis_dynhn *dyn;
dyn = dynhn_find_by_id (adj->sysid);
if (dyn)
adj_name = (const char *)dyn->name.name;
else
adj_name = adj->sysid ? sysid_print (adj->sysid) : "unknown";
zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s",
adj_name,
adj->circuit ? adj->circuit->interface->name : "no circuit",
adj_state2string (old_state),
adj_state2string (new_state),
reason ? reason : "unspecified");
}
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
{
if (state == ISIS_ADJ_UP)
circuit->upadjcount[level - 1]++;
if (state == ISIS_ADJ_DOWN)
for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
{
listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj);
if ((adj->level & level) == 0)
continue;
if (new_state == ISIS_ADJ_UP)
{
circuit->upadjcount[level - 1]++;
isis_event_adjacency_state_change (adj, new_state);
/* update counter & timers for debugging purposes */
adj->last_flap = time (NULL);
adj->flaps++;
}
else if (new_state == ISIS_ADJ_DOWN)
{
listnode_delete (circuit->u.bc.adjdb[level - 1], adj);
circuit->upadjcount[level - 1]--;
if (circuit->upadjcount[level - 1] == 0)
{
/* Clean lsp_queue when no adj is up. */
if (circuit->lsp_queue)
list_delete_all_node (circuit->lsp_queue);
}
isis_event_adjacency_state_change (adj, new_state);
isis_delete_adj (adj);
}
if (circuit->u.bc.lan_neighs[level - 1])
{
list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
circuit->u.bc.lan_neighs[level - 1]);
}
else if (state == ISIS_ADJ_UP)
{ /* p2p interface */
/* On adjacency state change send new pseudo LSP if we are the DR */
if (circuit->u.bc.is_dr[level - 1])
lsp_regenerate_schedule_pseudo (circuit, level);
}
}
else if (circuit->circ_type == CIRCUIT_T_P2P)
{
for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
{
if ((adj->level & level) == 0)
continue;
if (new_state == ISIS_ADJ_UP)
{
circuit->upadjcount[level - 1]++;
isis_event_adjacency_state_change (adj, new_state);
if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
send_hello (circuit, 1);
send_hello (circuit, level);
/* update counter & timers for debugging purposes */
adj->last_flap = time (NULL);
@ -191,14 +273,25 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
/* 7.3.17 - going up on P2P -> send CSNP */
/* FIXME: yup, I know its wrong... but i will do it! (for now) */
send_csnp (circuit, 1);
send_csnp (circuit, 2);
send_csnp (circuit, level);
}
else if (state == ISIS_ADJ_DOWN)
{ /* p2p interface */
else if (new_state == ISIS_ADJ_DOWN)
{
if (adj->circuit->u.p2p.neighbor == adj)
adj->circuit->u.p2p.neighbor = NULL;
isis_delete_adj (adj, NULL);
circuit->upadjcount[level - 1]--;
if (circuit->upadjcount[level - 1] == 0)
{
/* Clean lsp_queue when no adj is up. */
if (circuit->lsp_queue)
list_delete_all_node (circuit->lsp_queue);
}
isis_event_adjacency_state_change (adj, new_state);
isis_delete_adj (adj);
}
}
}
return;
}
@ -225,7 +318,7 @@ isis_adj_print (struct isis_adjacency *adj)
snpa_print (adj->snpa), adj->level, adj->hold_time);
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0)
{
zlog_debug ("IPv4 Addresses:");
zlog_debug ("IPv4 Address(es):");
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr))
zlog_debug ("%s", inet_ntoa (*ipv4_addr));
@ -234,7 +327,7 @@ isis_adj_print (struct isis_adjacency *adj)
#ifdef HAVE_IPV6
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
{
zlog_debug ("IPv6 Addresses:");
zlog_debug ("IPv6 Address(es):");
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
{
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
@ -251,14 +344,12 @@ int
isis_adj_expire (struct thread *thread)
{
struct isis_adjacency *adj;
int level;
/*
* Get the adjacency
*/
adj = THREAD_ARG (thread);
assert (adj);
level = adj->level;
adj->t_expire = NULL;
/* trigger the adj expire event */
@ -267,32 +358,12 @@ isis_adj_expire (struct thread *thread)
return 0;
}
static const char *
adj_state2string (int state)
{
switch (state)
{
case ISIS_ADJ_INITIALIZING:
return "Initializing";
case ISIS_ADJ_UP:
return "Up";
case ISIS_ADJ_DOWN:
return "Down";
default:
return "Unknown";
}
return NULL; /* not reached */
}
/*
* show clns/isis neighbor (detail)
* show isis neighbor [detail]
*/
static void
isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
void
isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail)
{
#ifdef HAVE_IPV6
struct in6_addr *ipv6_addr;
u_char ip6[INET6_ADDRSTRLEN];
@ -335,10 +406,11 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
if (detail == ISIS_UI_LEVEL_DETAIL)
{
level = adj->level;
vty_out (vty, "%s", VTY_NEWLINE);
if (adj->circuit)
vty_out (vty, "%s Interface: %s", VTY_NEWLINE, adj->circuit->interface->name); /* interface name */
vty_out (vty, " Interface: %s", adj->circuit->interface->name);
else
vty_out (vty, "NULL circuit!%s", VTY_NEWLINE);
vty_out (vty, " Interface: NULL circuit");
vty_out (vty, ", Level: %u", adj->level); /* level */
vty_out (vty, ", State: %s", adj_state2string (adj->adj_state));
now = time (NULL);
@ -347,12 +419,16 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
time2string (adj->last_upd + adj->hold_time - now));
else
vty_out (vty, ", Expires in %s", time2string (adj->hold_time));
vty_out (vty, "%s Adjacency flaps: %u", VTY_NEWLINE, adj->flaps);
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, " Adjacency flaps: %u", adj->flaps);
vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap));
vty_out (vty, "%s Circuit type: %s",
VTY_NEWLINE, circuit_t2string (adj->circuit_t));
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t));
vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids));
vty_out (vty, "%s SNPA: %s", VTY_NEWLINE, snpa_print (adj->snpa));
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, " SNPA: %s", snpa_print (adj->snpa));
if (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)
{
dyn = dynhn_find_by_id (adj->lanid);
if (dyn)
vty_out (vty, ", LAN id: %s.%02x",
@ -361,26 +437,36 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
vty_out (vty, ", LAN id: %s.%02x",
sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]);
vty_out (vty, "%s Priority: %u",
VTY_NEWLINE, adj->prio[adj->level - 1]);
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]);
vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s",
vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago",
isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1].
dis), adj->dischanges[level - 1],
time2string (now -
(adj->dis_record[ISIS_LEVELS + level - 1].
last_dis_change)), VTY_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)
{
vty_out (vty, " IPv4 Addresses:%s", VTY_NEWLINE);
vty_out (vty, " IPv4 Address(es):%s", VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr))
vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE);
}
#ifdef HAVE_IPV6
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
{
vty_out (vty, " IPv6 Addresses:%s", VTY_NEWLINE);
vty_out (vty, " IPv6 Address(es):%s", VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
{
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
@ -393,53 +479,6 @@ isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
return;
}
void
isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
}
void
isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
}
void
isis_adj_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
}
void
isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
}
void
isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
}
void
isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
{
isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
}
void
isis_adjdb_iterate (struct list *adjdb, void (*func) (struct isis_adjacency *,
void *), void *arg)
{
struct listnode *node, *nnode;
struct isis_adjacency *adj;
for (ALL_LIST_ELEMENTS (adjdb, node, nnode, adj))
(*func) (adj, arg);
}
void
isis_adj_build_neigh_list (struct list *adjdb, struct list *list)
{

View File

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

View File

@ -301,7 +301,16 @@ int
isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
{
struct ether_header *eth;
int written;
int written, buflen;
buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN;
if (buflen > sizeof (sock_buff))
{
zlog_warn ("isis_send_pdu_bcast: sock_buff size %lu is less than "
"output pdu size %d on circuit %s",
sizeof (sock_buff), buflen, circuit->interface->name);
return ISIS_WARNING;
}
stream_set_getp (circuit->snd_stream, 0);
@ -328,9 +337,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
stream_get_endp (circuit->snd_stream));
/* now we can send this */
written = write (circuit->fd, sock_buff,
stream_get_endp (circuit->snd_stream)
+ LLC_LEN + ETHER_HDR_LEN);
written = write (circuit->fd, sock_buff, buflen);
return ISIS_OK;
}

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

View File

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

View File

@ -27,8 +27,10 @@
* Architectural constant values from p. 35 of ISO/IEC 10589
*/
#define MAX_LINK_METRIC 63
#define MAX_PATH_METRIC 1023
#define MAX_NARROW_LINK_METRIC 63
#define MAX_NARROW_PATH_METRIC 1023
#define MAX_WIDE_LINK_METRIC 0x00FFFFFF /* RFC4444 */
#define MAX_WIDE_PATH_METRIC 0xFE000000 /* RFC3787 */
#define ISO_SAP 0xFE
#define INTRADOMAIN_ROUTEING_SELECTOR 0
#define SEQUENCE_MODULUS 4294967296
@ -38,7 +40,7 @@
* implementation specific jitter values
*/
#define IIH_JITTER 25 /* % */
#define IIH_JITTER 10 /* % */
#define MAX_AGE_JITTER 5 /* % */
#define MAX_LSP_GEN_JITTER 5 /* % */
#define CSNP_JITTER 10 /* % */
@ -46,36 +48,59 @@
#define RANDOM_SPREAD 100000.0
/*
* Default values
* ISO - 10589
* Section 7.3.21 - Parameters
*/
#define MAX_AGE 1200
#define ZERO_AGE_LIFETIME 60
#define MAX_LSP_GEN_INTERVAL 900
#define MIN_LSP_GEN_INTERVAL 30
#define MIN_LSP_TRANS_INTERVAL 5
#define ISIS_MIN_LSP_LIFETIME 380
#define CSNP_INTERVAL 10
#define PSNP_INTERVAL 2
#define ISIS_MAX_PATH_SPLITS 3
#define ISIS_LEVELS 2
#define ISIS_LEVEL1 1
#define ISIS_LEVEL2 2
#define HELLO_INTERVAL 10
#define HELLO_MINIMAL HELLO_INTERVAL
#define HELLO_MULTIPLIER 3
/*
* Default values
* ISO - 10589 Section 7.3.21 - Parameters
* RFC 4444
*/
#define MAX_AGE 1200
#define ZERO_AGE_LIFETIME 60
#define MIN_LSP_LIFETIME 350
#define MAX_LSP_LIFETIME 65535
#define DEFAULT_LSP_LIFETIME 1200
#define MIN_MAX_LSP_GEN_INTERVAL 1
#define MAX_MAX_LSP_GEN_INTERVAL 65235
#define DEFAULT_MAX_LSP_GEN_INTERVAL 900
#define MIN_MIN_LSP_GEN_INTERVAL 1
#define MAX_MIN_LSP_GEN_INTERVAL 120 /* RFC 4444 says 65535 */
#define DEFAULT_MIN_LSP_GEN_INTERVAL 30
#define MIN_LSP_TRANS_INTERVAL 5
#define MIN_CSNP_INTERVAL 1
#define MAX_CSNP_INTERVAL 600
#define DEFAULT_CSNP_INTERVAL 10
#define MIN_PSNP_INTERVAL 1
#define MAX_PSNP_INTERVAL 120
#define DEFAULT_PSNP_INTERVAL 2
#define MIN_HELLO_INTERVAL 1
#define MAX_HELLO_INTERVAL 600
#define DEFAULT_HELLO_INTERVAL 3
#define MIN_HELLO_MULTIPLIER 2
#define MAX_HELLO_MULTIPLIER 100
#define DEFAULT_HELLO_MULTIPLIER 10
#define MIN_PRIORITY 0
#define MAX_PRIORITY 127
#define DEFAULT_PRIORITY 64
/* different vendors implement different values 5-10 on average */
#define LSP_GEN_INTERVAL_DEFAULT 10
#define LSP_INTERVAL 33 /* msecs */
#define DEFAULT_CIRCUIT_METRICS 10
/* min and max metric varies by new vs old metric types */
#define DEFAULT_CIRCUIT_METRIC 10
#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
@ -104,6 +129,7 @@
#define SNPA_ADDRSTRLEN 18
#define ISIS_SYS_ID_LEN 6
#define ISIS_NSEL_LEN 1
#define SYSID_STRLEN 24
/*
@ -136,8 +162,8 @@
* packets, using isomtu = mtu - LLC_LEN
*/
#define ISO_MTU(C) \
(C->circ_type==CIRCUIT_T_BROADCAST) ? \
(C->interface->mtu - LLC_LEN) : (C->interface->mtu)
((if_is_broadcast ((C)->interface)) ? \
(C->interface->mtu - LLC_LEN) : (C->interface->mtu))
#ifndef ETH_ALEN
#define ETH_ALEN 6

View File

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

View File

@ -442,12 +442,12 @@ open_dlpi_dev (struct isis_circuit *circuit)
* 8.4.2 - Broadcast subnetwork IIH PDUs
*/
retval = 0;
if (circuit->circuit_is_type & IS_LEVEL_1)
if (circuit->is_type & IS_LEVEL_1)
{
retval |= dlpimcast (fd, ALL_L1_ISS);
retval |= dlpimcast (fd, ALL_ISS);
}
if (circuit->circuit_is_type & IS_LEVEL_2)
if (circuit->is_type & IS_LEVEL_2)
retval |= dlpimcast (fd, ALL_L2_ISS);
if (retval != 0)
@ -589,6 +589,16 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
char *dstaddr;
u_short *dstsap;
int buflen;
buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN;
if (buflen > sizeof (sock_buff))
{
zlog_warn ("isis_send_pdu_bcast: sock_buff size %lu is less than "
"output pdu size %d on circuit %s",
sizeof (sock_buff), buflen, circuit->interface->name);
return ISIS_WARNING;
}
stream_set_getp (circuit->snd_stream, 0);
@ -612,7 +622,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
else
memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
/* Note: DLPI SAP values are in host byte order */
*dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN;
*dstsap = buflen;
sock_buff[0] = ISO_SAP;
sock_buff[1] = ISO_SAP;
@ -620,7 +630,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
stream_get_endp (circuit->snd_stream));
dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length,
sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0);
sock_buff, buflen, 0);
return ISIS_OK;
}

View File

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

View File

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

View File

@ -33,7 +33,9 @@ struct isis_dynhn
void dyn_cache_init (void);
void isis_dynhn_insert (u_char * id, struct hostname *hostname, int level);
void isis_dynhn_remove (u_char * id);
struct isis_dynhn *dynhn_find_by_id (u_char * id);
struct isis_dynhn *dynhn_find_by_name (const char *hostname);
void dynhn_print_all (struct vty *vty);
#endif /* _ZEBRA_ISIS_DYNHN_H */

View File

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

View File

@ -26,13 +26,12 @@
* Events related to area
*/
void isis_event_system_type_change (struct isis_area *area, int newtype);
void isis_event_area_addr_change (struct isis_area *area);
/*
* Events related to circuit
*/
void isis_event_circuit_state_change (struct isis_circuit *circuit,
int state);
struct isis_area *area, int state);
void isis_event_circuit_type_change (struct isis_circuit *circuit,
int newtype);
/*

View File

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

View File

@ -26,28 +26,43 @@
/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
* the support will be achived using the newest drafts */
#define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well */
#define ISIS_MAX_CIRCUITS 32 /* = 1024 */
/*
* Flags structure for SSN and SRM flags
*/
struct flags
{
int maxindex;
struct list *free_idcs;
};
void flags_initialize (struct flags *flags);
struct flags *new_flags (int size);
int flags_get_index (struct flags *flags);
void flags_free_index (struct flags *flags, int index);
long int flags_get_index (struct flags *flags);
void flags_free_index (struct flags *flags, long int index);
int flags_any_set (u_int32_t * flags);
#define ISIS_SET_FLAG(F,C) \
F[C->idx>>5] |= (1<<(C->idx & 0x1F));
{ \
F[C->idx>>5] |= (1<<(C->idx & 0x1F)); \
}
#define ISIS_CLEAR_FLAG(F,C) \
F[C->idx>>5] &= ~(1<<(C->idx & 0x1F));
{ \
F[C->idx>>5] &= ~(1<<(C->idx & 0x1F)); \
}
#define ISIS_CHECK_FLAG(F, C) F[(C)->idx>>5] & (1<<(C->idx & 0x1F))
#define ISIS_CHECK_FLAG(F, C) (F[(C)->idx>>5] & (1<<(C->idx & 0x1F)))
/* sets all u_32int_t flags to 1 */
#define ISIS_FLAGS_SET_ALL(FLAGS) \
memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4);
{ \
memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4); \
}
#define ISIS_FLAGS_CLEAR_ALL(FLAGS) \
memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4);
{ \
memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4); \
}
#endif /* _ZEBRA_ISIS_FLAGS_H */

File diff suppressed because it is too large Load Diff

View File

@ -24,10 +24,6 @@
#ifndef _ZEBRA_ISIS_LSP_H
#define _ZEBRA_ISIS_LSP_H
/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
* the support will be achived using the newest drafts */
#define ISIS_MAX_CIRCUITS 32 /* = 1024 - FIXME:defined in flags.h as well */
/* Structure for isis_lsp, this structure will only support the fixed
* System ID (Currently 6) (atleast for now). In order to support more
* We will have to split the header into two parts, and for readability
@ -42,15 +38,13 @@ struct isis_lsp
struct list *frags;
struct isis_lsp *zero_lsp;
} lspu;
u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */
u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
u_int32_t rexmit_queue[ISIS_MAX_CIRCUITS];
int level; /* L1 or L2? */
int purged; /* have purged this one */
int scheduled; /* scheduled for sending */
time_t installed;
time_t last_generated;
time_t last_sent;
int own_lsp;
#ifdef TOPOLOGY_GENERATE
int from_topology;
@ -58,7 +52,6 @@ struct isis_lsp
#endif
/* used for 60 second counting when rem_lifetime is zero */
int age_out;
/* FIXME: For now only topology LSP's use this. Is it helpful for others? */
struct isis_area *area;
struct tlvs tlv_data; /* Simplifies TLV access */
};
@ -67,37 +60,32 @@ dict_t *lsp_db_init (void);
void lsp_db_destroy (dict_t * lspdb);
int lsp_tick (struct thread *thread);
int lsp_l1_generate (struct isis_area *area);
int lsp_l2_generate (struct isis_area *area);
int lsp_refresh_l1 (struct thread *thread);
int lsp_refresh_l2 (struct thread *thread);
int lsp_regenerate_schedule (struct isis_area *area);
int lsp_generate (struct isis_area *area, int level);
int lsp_regenerate_schedule (struct isis_area *area, int level,
int all_pseudo);
int lsp_generate_pseudo (struct isis_circuit *circuit, int level);
int lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level);
int lsp_l1_pseudo_generate (struct isis_circuit *circuit);
int lsp_l2_pseudo_generate (struct isis_circuit *circuit);
int lsp_l1_refresh_pseudo (struct thread *thread);
int lsp_l2_refresh_pseudo (struct thread *thread);
int isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
int pdulen, struct isis_passwd *passwd);
struct isis_lsp *lsp_new (u_char * lsp_id, u_int16_t rem_lifetime,
u_int32_t seq_num, u_int8_t lsp_bits,
u_int16_t checksum, int level);
struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream,
u_int16_t pdu_len,
struct isis_lsp *lsp0,
struct isis_area *area);
struct isis_area *area,
int level);
void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb);
struct isis_lsp *lsp_search (u_char * id, dict_t * lspdb);
void lsp_build_list (u_char * start_id, u_char * stop_id,
void lsp_build_list (u_char * start_id, u_char * stop_id, u_char num_lsps,
struct list *list, dict_t * lspdb);
void lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
struct list *list, dict_t * lspdb);
void lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
dict_t * lspdb);
void lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps,
struct list *list, dict_t * lspdb);
void lsp_search_and_destroy (u_char * id, dict_t * lspdb);
void lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level);
void lsp_purge_pseudo (u_char * id, struct isis_circuit *circuit, int level);
void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
struct isis_area *area);
@ -114,13 +102,18 @@ void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
int lsp_id_cmp (u_char * id1, u_char * id2);
int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
u_int16_t checksum, u_int16_t rem_lifetime);
void lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
struct stream *stream, struct isis_area *area, int level);
void lsp_update (struct isis_lsp *lsp, struct stream *stream,
struct isis_area *area, int level);
void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num);
void lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost);
void lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost);
int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail,
char dynhost);
const char *lsp_bits2string (u_char *);
/* sets SRMflags for all active circuits of an lsp */
void lsp_set_all_srmflags (struct isis_lsp *lsp);
#ifdef TOPOLOGY_GENERATE
void generate_topology_lsps (struct isis_area *area);
void remove_topology_lsps (struct isis_area *area);

View File

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

View File

@ -32,7 +32,9 @@
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"
#include "isisd/isisd.h"
#include "isisd/isis_misc.h"
@ -40,6 +42,7 @@
#include "isisd/isis_lsp.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_dynhn.h"
/* staticly assigned vars for printing purposes */
struct in_addr new_prefix;
@ -99,10 +102,10 @@ isonet_print (u_char * from, int len)
* extract dot from the dotted str, and insert all the number in a buff
*/
int
dotformat2buff (u_char * buff, const u_char * dotted)
dotformat2buff (u_char * buff, const char * dotted)
{
int dotlen, len = 0;
const u_char *pos = dotted;
const char *pos = dotted;
u_char number[3];
int nextdotpos = 2;
@ -157,10 +160,10 @@ dotformat2buff (u_char * buff, const u_char * dotted)
* conversion of XXXX.XXXX.XXXX to memory
*/
int
sysid2buff (u_char * buff, const u_char * dotted)
sysid2buff (u_char * buff, const char * dotted)
{
int len = 0;
const u_char *pos = dotted;
const char *pos = dotted;
u_char number[3];
number[2] = '\0';
@ -271,7 +274,7 @@ speaks (struct nlpids *nlpids, int family)
* Returns 0 on error, IS-IS Circuit Type on ok
*/
int
string2circuit_t (const u_char * str)
string2circuit_t (const char * str)
{
if (!str)
@ -289,6 +292,42 @@ string2circuit_t (const u_char * str)
return 0;
}
const char *
circuit_state2string (int state)
{
switch (state)
{
case C_STATE_INIT:
return "Init";
case C_STATE_CONF:
return "Config";
case C_STATE_UP:
return "Up";
default:
return "Unknown";
}
return NULL;
}
const char *
circuit_type2string (int type)
{
switch (type)
{
case CIRCUIT_T_P2P:
return "p2p";
case CIRCUIT_T_BROADCAST:
return "lan";
case CIRCUIT_T_LOOPBACK:
return "loopback";
default:
return "Unknown";
}
return NULL;
}
const char *
circuit_t2string (int circuit_t)
{
@ -498,7 +537,6 @@ unix_hostname (void)
{
static struct utsname names;
const char *hostname;
extern struct host host;
hostname = host.name;
if (!hostname)
@ -509,3 +547,87 @@ unix_hostname (void)
return hostname;
}
/*
* Returns the dynamic hostname associated with the passed system ID.
* If no dynamic hostname found then returns formatted system ID.
*/
const char *
print_sys_hostname (u_char *sysid)
{
struct isis_dynhn *dyn;
if (!sysid)
return "nullsysid";
/* For our system ID return our host name */
if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
return unix_hostname();
dyn = dynhn_find_by_id (sysid);
if (dyn)
return (const char *)dyn->name.name;
return sysid_print (sysid);
}
/*
* This function is a generic utility that logs data of given length.
* Move this to a shared lib so that any protocol can use it.
*/
void
zlog_dump_data (void *data, int len)
{
int i;
unsigned char *p;
unsigned char c;
char bytestr[4];
char addrstr[10];
char hexstr[ 16*3 + 5];
char charstr[16*1 + 5];
p = data;
memset (bytestr, 0, sizeof(bytestr));
memset (addrstr, 0, sizeof(addrstr));
memset (hexstr, 0, sizeof(hexstr));
memset (charstr, 0, sizeof(charstr));
for (i = 1; i <= len; i++)
{
c = *p;
if (isalnum (c) == 0)
c = '.';
/* store address for this line */
if ((i % 16) == 1)
snprintf (addrstr, sizeof(addrstr), "%p", p);
/* store hex str (for left side) */
snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
/* store char str (for right side) */
snprintf (bytestr, sizeof (bytestr), "%c", c);
strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
if ((i % 16) == 0)
{
/* line completed */
zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
hexstr[0] = 0;
charstr[0] = 0;
}
else if ((i % 8) == 0)
{
/* half line: add whitespaces */
strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1);
strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
}
p++; /* next byte */
}
/* print rest of buffer if not empty */
if (strlen (hexstr) > 0)
zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
return;
}

View File

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

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 reserved;
u_char max_area_addrs;
};
} __attribute__ ((packed));
#define ISIS_FIXED_HDR_LEN 8
@ -114,7 +114,7 @@ struct isis_fixed_hdr
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Holding Time | 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | PDU Lenght | 2
* | PDU Length | 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | R | Priority | 1
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -142,7 +142,7 @@ struct isis_lan_hello_hdr
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + Holding Time + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + PDU Lenght + 2
* + PDU Length + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Local Circuit ID | 1
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -186,12 +186,23 @@ struct isis_link_state_hdr
} __attribute__ ((packed));
#define ISIS_LSP_HDR_LEN 19
/*
* Since the length field of LSP Entries TLV is one byte long, and each LSP
* entry is LSP_ENTRIES_LEN (16) bytes long, the maximum number of LSP entries
* can be accomodated in a TLV is
* 255 / 16 = 15.
*
* Therefore, the maximum length of the LSP Entries TLV is
* 16 * 15 + 2 (header) = 242 bytes.
*/
#define MAX_LSP_ENTRIES_TLV_SIZE 242
#define L1_COMPLETE_SEQ_NUM 24
#define L2_COMPLETE_SEQ_NUM 25
/*
* L1 and L2 IS to IS complete sequence numbers PDU header
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + PDU Lenght + 2
* + PDU Length + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + Source ID + id_len + 1
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -241,6 +252,8 @@ int isis_receive (struct thread *thread);
#define ISIS_SNP_PSNP_FLAG 0
#define ISIS_SNP_CSNP_FLAG 1
#define ISIS_AUTH_MD5_SIZE 16U
/*
* Sending functions
*/
@ -258,7 +271,4 @@ int ack_lsp (struct isis_link_state_hdr *hdr,
void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type);
int send_hello (struct isis_circuit *circuit, int level);
#define ISIS_AUTH_MD5_SIZE 16U
int authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit *c);
#endif /* _ZEBRA_ISIS_PDU_H */

View File

@ -134,7 +134,7 @@ open_packet_socket (struct isis_circuit *circuit)
circuit->fd = fd;
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
if (if_is_broadcast (circuit->interface))
{
/*
* Join to multicast groups
@ -142,19 +142,17 @@ open_packet_socket (struct isis_circuit *circuit)
* 8.4.2 - Broadcast subnetwork IIH PDUs
* FIXME: is there a case only one will fail??
*/
if (circuit->circuit_is_type & IS_LEVEL_1)
{
if (circuit->is_type & IS_LEVEL_1)
/* joining ALL_L1_ISS */
retval = isis_multicast_join (circuit->fd, 1,
circuit->interface->ifindex);
/* joining ALL_ISS */
retval = isis_multicast_join (circuit->fd, 3,
circuit->interface->ifindex);
}
if (circuit->circuit_is_type & IS_LEVEL_2)
if (circuit->is_type & IS_LEVEL_2)
/* joining ALL_L2_ISS */
retval = isis_multicast_join (circuit->fd, 2,
circuit->interface->ifindex);
/* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */
retval = isis_multicast_join (circuit->fd, 3,
circuit->interface->ifindex);
}
else
{
@ -184,12 +182,13 @@ isis_sock_init (struct isis_circuit *circuit)
goto end;
}
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
/* Assign Rx and Tx callbacks are based on real if type */
if (if_is_broadcast (circuit->interface))
{
circuit->tx = isis_send_pdu_bcast;
circuit->rx = isis_recv_pdu_bcast;
}
else if (circuit->circ_type == CIRCUIT_T_P2P)
else if (if_is_pointopoint (circuit->interface))
{
circuit->tx = isis_send_pdu_p2p;
circuit->rx = isis_recv_pdu_p2p;
@ -232,19 +231,16 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
LLC_LEN, MSG_PEEK,
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
if (!circuit->area) {
return ISIS_OK;
}
if (bytesread < 0)
{
zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
circuit->fd, safe_strerror (errno));
zlog_warn ("circuit is %s", circuit->interface->name);
zlog_warn ("circuit fd %d", circuit->fd);
zlog_warn ("bytesread %d", bytesread);
zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, "
"recvfrom(): %s",
circuit->interface->name, circuit->fd, bytesread,
safe_strerror (errno));
/* get rid of the packet */
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
return ISIS_WARNING;
}
/*
@ -253,15 +249,22 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
{
/* Read the packet into discard buff */
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
if (bytesread < 0)
zlog_warn ("isis_recv_pdu_bcast(): read() failed");
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
return ISIS_WARNING;
}
/* on lan we have to read to the static buff first */
bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
bytesread = recvfrom (circuit->fd, sock_buff, sizeof (sock_buff), MSG_DONTWAIT,
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
if (bytesread < 0)
{
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
return ISIS_WARNING;
}
/* then we lose the LLC */
stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
@ -289,9 +292,11 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
if (s_addr.sll_pkttype == PACKET_OUTGOING)
{
/* Read the packet into discard buff */
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
if (bytesread < 0)
zlog_warn ("isis_recv_pdu_p2p(): read() failed");
zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed");
return ISIS_WARNING;
}
@ -313,6 +318,9 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
int
isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
{
struct msghdr msg;
struct iovec iov[2];
/* we need to do the LLC in here because of P2P circuits, which will
* not need it
*/
@ -325,7 +333,10 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
sa.sll_ifindex = circuit->interface->ifindex;
sa.sll_halen = ETH_ALEN;
if (level == 1)
/* RFC5309 section 4.1 recommends ALL_ISS */
if (circuit->circ_type == CIRCUIT_T_P2P)
memcpy (&sa.sll_addr, ALL_ISS, ETH_ALEN);
else if (level == 1)
memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
else
memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
@ -336,14 +347,17 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
sock_buff[1] = 0xFE;
sock_buff[2] = 0x03;
/* then we copy the data */
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
stream_get_endp (circuit->snd_stream));
memset (&msg, 0, sizeof (msg));
msg.msg_name = &sa;
msg.msg_namelen = sizeof (struct sockaddr_ll);
msg.msg_iov = iov;
msg.msg_iovlen = 2;
iov[0].iov_base = sock_buff;
iov[0].iov_len = LLC_LEN;
iov[1].iov_base = circuit->snd_stream->data;
iov[1].iov_len = stream_get_endp (circuit->snd_stream);
/* now we can send this */
written = sendto (circuit->fd, sock_buff,
stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
(struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
written = sendmsg (circuit->fd, &msg, 0);
return ISIS_OK;
}
@ -351,7 +365,6 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
int
isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
{
int written = 1;
struct sockaddr_ll sa;

View File

@ -36,6 +36,7 @@
#include "isis_constants.h"
#include "isis_common.h"
#include "isis_flags.h"
#include "dict.h"
#include "isisd.h"
#include "isis_misc.h"
@ -48,9 +49,6 @@
#include "isis_route.h"
#include "isis_zebra.h"
extern struct isis *isis;
extern struct thread_master *master;
static struct isis_nexthop *
isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
{
@ -246,6 +244,7 @@ adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
{
nh = isis_nexthop_create (ipv4_addr,
adj->circuit->interface->ifindex);
nh->router_address = adj->router_address;
listnode_add (nexthops, nh);
}
}
@ -269,6 +268,7 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
{
nh6 = isis_nexthop6_create (ipv6_addr,
adj->circuit->interface->ifindex);
nh6->router_address6 = adj->router_address6;
listnode_add (nexthops6, nh6);
}
}
@ -276,7 +276,7 @@ adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
#endif /* HAVE_IPV6 */
static struct isis_route_info *
isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
struct list *adjacencies)
{
struct isis_route_info *rinfo;
@ -290,19 +290,35 @@ isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
return NULL;
}
if (family == AF_INET)
if (prefix->family == AF_INET)
{
rinfo->nexthops = list_new ();
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
{
/* check for force resync this route */
if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
/* update neighbor router address */
if (depth == 2 && prefix->prefixlen == 32)
adj->router_address = prefix->u.prefix4;
adjinfo2nexthop (rinfo->nexthops, adj);
}
}
#ifdef HAVE_IPV6
if (family == AF_INET6)
if (prefix->family == AF_INET6)
{
rinfo->nexthops6 = list_new ();
for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
{
/* check for force resync this route */
if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
/* update neighbor router address */
if (depth == 2 && prefix->prefixlen == 128)
adj->router_address6 = prefix->u.prefix6;
adjinfo2nexthop6 (rinfo->nexthops6, adj);
}
}
#endif /* HAVE_IPV6 */
@ -353,6 +369,13 @@ isis_route_info_same (struct isis_route_info *new,
#ifdef HAVE_IPV6
struct isis_nexthop6 *nexthop6;
#endif /* HAVE_IPV6 */
if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return 0;
if (CHECK_FLAG (new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC))
return 0;
if (!isis_route_info_same_attrib (new, old))
return 0;
@ -386,65 +409,6 @@ isis_route_info_same (struct isis_route_info *new,
return 1;
}
static void
isis_nexthops_merge (struct list *new, struct list *old)
{
struct listnode *node;
struct isis_nexthop *nexthop;
for (ALL_LIST_ELEMENTS_RO (new, node, nexthop))
{
if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))
continue;
listnode_add (old, nexthop);
nexthop->lock++;
}
}
#ifdef HAVE_IPV6
static void
isis_nexthops6_merge (struct list *new, struct list *old)
{
struct listnode *node;
struct isis_nexthop6 *nexthop6;
for (ALL_LIST_ELEMENTS_RO (new, node, nexthop6))
{
if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))
continue;
listnode_add (old, nexthop6);
nexthop6->lock++;
}
}
#endif /* HAVE_IPV6 */
static void
isis_route_info_merge (struct isis_route_info *new,
struct isis_route_info *old, u_char family)
{
if (family == AF_INET)
isis_nexthops_merge (new->nexthops, old->nexthops);
#ifdef HAVE_IPV6
else if (family == AF_INET6)
isis_nexthops6_merge (new->nexthops6, old->nexthops6);
#endif /* HAVE_IPV6 */
return;
}
static int
isis_route_info_prefer_new (struct isis_route_info *new,
struct isis_route_info *old)
{
if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))
return 1;
if (new->cost < old->cost)
return 1;
return 0;
}
struct isis_route_info *
isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
struct list *adjacencies, struct isis_area *area,
@ -459,7 +423,7 @@ isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
/* for debugs */
prefix2str (prefix, (char *) buff, BUFSIZ);
rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);
rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies);
if (!rinfo_new)
{
zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
@ -480,66 +444,30 @@ isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
{
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);
route_node->info = rinfo_new;
return rinfo_new;
}
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
buff);
if (isis_route_info_same (rinfo_new, rinfo_old, family))
{
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);
isis_route_info_delete (rinfo_new);
route_info = rinfo_old;
}
else if (isis_route_info_same_attrib (rinfo_new, rinfo_old))
{
/* merge the nexthop lists */
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s",
area->area_tag, buff);
#ifdef EXTREME_DEBUG
if (family == AF_INET)
{
zlog_debug ("Old nexthops");
nexthops_print (rinfo_old->nexthops);
zlog_debug ("New nexthops");
nexthops_print (rinfo_new->nexthops);
}
else if (family == AF_INET6)
{
zlog_debug ("Old nexthops");
nexthops6_print (rinfo_old->nexthops6);
zlog_debug ("New nexthops");
nexthops6_print (rinfo_new->nexthops6);
}
#endif /* EXTREME_DEBUG */
isis_route_info_merge (rinfo_new, rinfo_old, family);
isis_route_info_delete (rinfo_new);
route_info = rinfo_old;
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
route_info = rinfo_new;
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
}
else
{
if (isis_route_info_prefer_new (rinfo_new, rinfo_old))
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
buff);
if (isis_route_info_same (rinfo_new, rinfo_old, family))
{
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
buff);
isis_route_info_delete (rinfo_new);
route_info = rinfo_old;
}
else
{
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
buff);
isis_route_info_delete (rinfo_old);
route_info = rinfo_new;
}
else
{
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,
buff);
isis_route_info_delete (rinfo_new);
route_info = rinfo_old;
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
}
}
@ -570,7 +498,7 @@ isis_route_delete (struct prefix *prefix, struct route_table *table)
return;
}
if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
{
UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
if (isis->debugs & DEBUG_RTE_EVENTS)
@ -600,10 +528,12 @@ isis_route_validate_table (struct isis_area *area, struct route_table *table)
if (isis->debugs & DEBUG_RTE_EVENTS)
{
prefix2str (&rnode->p, (char *) buff, BUFSIZ);
zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
area->area_tag,
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
"sync'ed" : "nosync"),
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
"synced" : "not-synced"),
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
"resync" : "not-resync"),
(CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
"active" : "inactive"), buff);
}
@ -706,41 +636,55 @@ isis_route_validate_merge (struct isis_area *area, int family)
/* Walk through route tables and propagate necessary changes into RIB. In case
* of L1L2 area, level tables have to be merged at first. */
int
isis_route_validate (struct thread *thread)
void
isis_route_validate (struct isis_area *area)
{
struct isis_area *area;
area = THREAD_ARG (thread);
struct listnode *node;
struct isis_circuit *circuit;
if (area->is_type == IS_LEVEL_1)
{
isis_route_validate_table (area, area->route_table[0]);
goto validate_ipv6;
}
if (area->is_type == IS_LEVEL_2)
{
else if (area->is_type == IS_LEVEL_2)
isis_route_validate_table (area, area->route_table[1]);
goto validate_ipv6;
}
else
isis_route_validate_merge (area, AF_INET);
validate_ipv6:
#ifdef HAVE_IPV6
if (area->is_type == IS_LEVEL_1)
{
isis_route_validate_table (area, area->route_table6[0]);
return ISIS_OK;
}
if (area->is_type == IS_LEVEL_2)
{
else if (area->is_type == IS_LEVEL_2)
isis_route_validate_table (area, area->route_table6[1]);
return ISIS_OK;
}
else
isis_route_validate_merge (area, AF_INET6);
#endif
return ISIS_OK;
/* walk all circuits and reset any spf specific flags */
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
return;
}
void
isis_route_invalidate_table (struct isis_area *area, struct route_table *table)
{
struct route_node *rode;
struct isis_route_info *rinfo;
for (rode = route_top (table); rode; rode = route_next (rode))
{
if (rode->info == NULL)
continue;
rinfo = rode->info;
UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
}
}
void
isis_route_invalidate (struct isis_area *area)
{
if (area->is_type & IS_LEVEL_1)
isis_route_invalidate_table (area, area->route_table[0]);
if (area->is_type & IS_LEVEL_2)
isis_route_invalidate_table (area, area->route_table[1]);
}

View File

@ -30,6 +30,7 @@ struct isis_nexthop6
{
unsigned int ifindex;
struct in6_addr ip6;
struct in6_addr router_address6;
unsigned int lock;
};
#endif /* HAVE_IPV6 */
@ -38,13 +39,15 @@ struct isis_nexthop
{
unsigned int ifindex;
struct in_addr ip;
struct in_addr router_address;
unsigned int lock;
};
struct isis_route_info
{
#define ISIS_ROUTE_FLAG_ZEBRA_SYNC 0x01
#define ISIS_ROUTE_FLAG_ACTIVE 0x02
#define ISIS_ROUTE_FLAG_ACTIVE 0x01 /* active route for the prefix */
#define ISIS_ROUTE_FLAG_ZEBRA_SYNCED 0x02 /* set when route synced to zebra */
#define ISIS_ROUTE_FLAG_ZEBRA_RESYNC 0x04 /* set when route needs to sync */
u_char flag;
u_int32_t cost;
u_int32_t depth;
@ -59,6 +62,9 @@ struct isis_route_info *isis_route_create (struct prefix *prefix,
struct list *adjacencies,
struct isis_area *area, int level);
int isis_route_validate (struct thread *thread);
void isis_route_validate (struct isis_area *area);
void isis_route_invalidate_table (struct isis_area *area,
struct route_table *table);
void isis_route_invalidate (struct isis_area *area);
#endif /* _ZEBRA_ISIS_ROUTE_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -54,25 +54,33 @@ struct isis_vertex
struct prefix prefix;
} N;
struct isis_lsp *lsp;
u_int32_t d_N; /* d(N) Distance from this IS */
u_int16_t depth; /* The depth in the imaginary tree */
struct list *Adj_N; /* {Adj(N)} */
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
struct list *parents; /* list of parents for ECMP */
struct list *children; /* list of children used for tree dump */
};
struct isis_spftree
{
struct thread *t_spf; /* spf threads */
time_t lastrun; /* for scheduling */
int pending; /* already scheduled */
struct list *paths; /* the SPT */
struct list *tents; /* TENT */
u_int32_t timerun; /* statistics */
struct isis_area *area; /* back pointer to area */
int pending; /* already scheduled */
unsigned int runcount; /* number of runs since uptime */
time_t last_run_timestamp; /* last run timestamp for scheduling */
time_t last_run_duration; /* last run duration in msec */
};
struct isis_spftree * isis_spftree_new (struct isis_area *area);
void isis_spftree_del (struct isis_spftree *spftree);
void isis_spftree_adj_del (struct isis_spftree *spftree,
struct isis_adjacency *adj);
void spftree_area_init (struct isis_area *area);
void spftree_area_del (struct isis_area *area);
void spftree_area_adj_del (struct isis_area *area,
struct isis_adjacency *adj);
int isis_spf_schedule (struct isis_area *area, int level);
void isis_spf_cmds_init (void);
#ifdef HAVE_IPV6

View File

@ -43,13 +43,6 @@
#include "isisd/isis_pdu.h"
#include "isisd/isis_lsp.h"
extern struct isis *isis;
/*
* Prototypes.
*/
int add_tlv (u_char, u_char, u_char *, struct stream *);
void
free_tlv (void *val)
{
@ -75,10 +68,10 @@ free_tlvs (struct tlvs *tlvs)
list_delete (tlvs->es_neighs);
if (tlvs->lsp_entries)
list_delete (tlvs->lsp_entries);
if (tlvs->lan_neighs)
list_delete (tlvs->lan_neighs);
if (tlvs->prefix_neighs)
list_delete (tlvs->prefix_neighs);
if (tlvs->lan_neighs)
list_delete (tlvs->lan_neighs);
if (tlvs->ipv4_addrs)
list_delete (tlvs->ipv4_addrs);
if (tlvs->ipv4_int_reachs)
@ -94,6 +87,8 @@ free_tlvs (struct tlvs *tlvs)
list_delete (tlvs->ipv6_reachs);
#endif /* HAVE_IPV6 */
memset (tlvs, 0, sizeof (struct tlvs));
return;
}
@ -103,7 +98,7 @@ free_tlvs (struct tlvs *tlvs)
*/
int
parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
u_int32_t * found, struct tlvs *tlvs)
u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset)
{
u_char type, length;
struct lan_neigh *lan_nei;
@ -122,7 +117,7 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
#endif /* HAVE_IPV6 */
u_char virtual;
int value_len, retval = ISIS_OK;
u_char *pnt = stream;
u_char *start = stream, *pnt = stream;
*found = 0;
memset (tlvs, 0, sizeof (struct tlvs));
@ -443,14 +438,22 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
if (*expected & TLVFLAG_AUTH_INFO)
{
tlvs->auth_info.type = *pnt;
tlvs->auth_info.len = length-1;
if (length == 0)
{
zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) "
"incorrect.", areatag, type, length);
return ISIS_WARNING;
}
--length;
tlvs->auth_info.len = length;
pnt++;
memcpy (tlvs->auth_info.passwd, pnt, length - 1);
/* Fill authentication with 0 for later computation
memcpy (tlvs->auth_info.passwd, pnt, length);
/* Return the authentication tlv pos for later computation
* of MD5 (RFC 5304, 2)
*/
memset (pnt, 0, length - 1);
pnt += length - 1;
if (auth_tlv_offset)
*auth_tlv_offset += (pnt - start - 3);
pnt += length;
}
else
{
@ -734,10 +737,14 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
int
add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
{
if (STREAM_SIZE (stream) - stream_get_endp (stream) < (unsigned) len + 2)
if ((stream_get_size (stream) - stream_get_endp (stream)) <
(((unsigned)len) + 2))
{
zlog_warn ("No room for TLV of type %d", tag);
zlog_warn ("No room for TLV of type %d "
"(total size %d available %d required %d)",
tag, (int)stream_get_size (stream),
(int)(stream_get_size (stream) - stream_get_endp (stream)),
len+2);
return ISIS_WARNING;
}
@ -745,7 +752,7 @@ add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
stream_putc (stream, len); /* LENGTH */
stream_put (stream, value, (int) len); /* VALUE */
#ifdef EXTREME_TLV_DEBUG
#ifdef EXTREME_DEBUG
zlog_debug ("Added TLV %d len %d", tag, len);
#endif /* EXTREME DEBUG */
return ISIS_OK;
@ -877,7 +884,7 @@ tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
}
int
tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value,
struct stream *stream)
{
u_char value[255];
@ -1006,7 +1013,6 @@ tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
pos += IPV4_MAX_BYTELEN;
}
return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
}
@ -1027,7 +1033,7 @@ tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
if (pos - value + (5 + prefix_size) > 255)
{
retval =
add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
if (retval != ISIS_OK)
return retval;
pos = value;
@ -1110,7 +1116,7 @@ tlv_add_padding (struct stream *stream)
/*
* How many times can we add full padding ?
*/
fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257;
for (i = 0; i < fullpads; i++)
{
if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
@ -1120,7 +1126,7 @@ tlv_add_padding (struct stream *stream)
stream_put (stream, NULL, 255); /* zero padding */
}
left = STREAM_SIZE (stream) - stream_get_endp (stream);
left = stream_get_size (stream) - stream_get_endp (stream);
if (left < 2)
return ISIS_OK;

View File

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

View File

@ -36,30 +36,37 @@
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h"
#include "isisd/isis_zebra.h"
struct zclient *zclient = NULL;
extern struct thread_master *master;
extern struct isis *isis;
struct in_addr router_id_zebra;
/* Router-id update message from zebra. */
static int
isis_router_id_update_zebra (int command, struct zclient *zclient,
zebra_size_t length)
{
struct isis_area *area;
struct listnode *node;
struct prefix router_id;
zebra_router_id_update_read (zclient->ibuf,&router_id);
router_id_zebra = router_id.u.prefix4;
zebra_router_id_update_read (zclient->ibuf, &router_id);
if (isis->router_id == router_id.u.prefix4.s_addr)
return 0;
isis->router_id = router_id.u.prefix4.s_addr;
for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
if (listcount (area->area_addrs) > 0)
lsp_regenerate_schedule (area, area->is_type, 0);
/* FIXME: Do we react somehow? */
return 0;
}
@ -100,53 +107,28 @@ isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
/* Cannot call if_delete because we should retain the pseudo interface
in case there is configuration info attached to it. */
if_delete_retain(ifp);
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
ifp->ifindex = IFINDEX_INTERNAL;
return 0;
}
static struct interface *
zebra_interface_if_lookup (struct stream *s)
{
char ifname_tmp[INTERFACE_NAMSIZ];
/* Read interface name. */
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
/* And look it up. */
return if_lookup_by_name_len(ifname_tmp,
strnlen(ifname_tmp, INTERFACE_NAMSIZ));
}
static int
isis_zebra_if_state_up (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
ifp = zebra_interface_if_lookup (zclient->ibuf);
ifp = zebra_interface_state_read (zclient->ibuf);
if (!ifp)
if (ifp == NULL)
return 0;
if (if_is_operative (ifp))
{
zebra_interface_if_set_value (zclient->ibuf, ifp);
/* HT: This is wrong actually. We can't assume that circuit exist
* if we delete circuit during if_state_down event. Needs rethink.
* TODO */
isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp);
return 0;
}
zebra_interface_if_set_value (zclient->ibuf, ifp);
isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
return 0;
@ -157,17 +139,17 @@ isis_zebra_if_state_down (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
struct isis_circuit *circuit;
ifp = zebra_interface_if_lookup (zclient->ibuf);
ifp = zebra_interface_state_read (zclient->ibuf);
if (ifp == NULL)
return 0;
if (if_is_operative (ifp))
{
zebra_interface_if_set_value (zclient->ibuf, ifp);
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
}
circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
ifp);
if (circuit)
SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
return 0;
}
@ -251,7 +233,7 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
struct isis_nexthop *nexthop;
struct listnode *node;
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
if (zclient->redist[ZEBRA_ROUTE_ISIS])
@ -307,7 +289,8 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
stream_putw_at (stream, 0, stream_get_endp (stream));
zclient_send_message(zclient);
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
}
@ -329,7 +312,7 @@ isis_zebra_route_del_ipv4 (struct prefix *prefix,
prefix4.prefix = prefix->u.prefix4;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
}
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
return;
}
@ -347,7 +330,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
struct listnode *node;
struct prefix_ipv6 prefix6;
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
api.type = ZEBRA_ROUTE_ISIS;
@ -410,7 +393,8 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
XFREE (MTYPE_ISIS_TMP, nexthop_list);
@ -431,7 +415,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
struct listnode *node;
struct prefix_ipv6 prefix6;
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
api.type = ZEBRA_ROUTE_ISIS;
@ -488,7 +472,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
}
XFREE (MTYPE_ISIS_TMP, nexthop_list);

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@ struct isis
u_long process_id;
int sysid_set;
u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */
u_int32_t router_id; /* Router ID from zebra */
struct list *area_list; /* list of IS-IS areas */
struct list *init_circ_list;
struct list *nexthops; /* IPv4 next hops from this IS */
@ -78,6 +79,8 @@ struct isis
#endif
};
extern struct isis *isis;
struct isis_area
{
struct isis *isis; /* back pointer */
@ -92,11 +95,8 @@ struct isis_area
struct list *circuit_list; /* IS-IS circuits */
struct flags flags;
struct thread *t_tick; /* LSP walker */
struct thread *t_remove_aged;
struct thread *t_lsp_l1_regenerate;
struct thread *t_lsp_l2_regenerate;
int lsp_regenerate_pending[ISIS_LEVELS];
struct thread *t_lsp_refresh[ISIS_LEVELS];
int lsp_regenerate_pending[ISIS_LEVELS];
/*
* Configurables
@ -114,6 +114,8 @@ struct isis_area
struct list *area_addrs;
u_int16_t max_lsp_lifetime[ISIS_LEVELS];
char is_type; /* level-1 level-1-2 or level-2-only */
/* are we overloaded? */
char overload_bit;
u_int16_t lsp_refresh[ISIS_LEVELS];
/* minimum time allowed before lsp retransmission */
u_int16_t lsp_gen_interval[ISIS_LEVELS];
@ -122,6 +124,8 @@ struct isis_area
/* the percentage of LSP mtu size used, before generating a new frag */
int lsp_frag_threshold;
int ip_circuits;
/* logging adjacency changes? */
u_char log_adj_changes;
#ifdef HAVE_IPV6
int ipv6_circuits;
#endif /* HAVE_IPV6 */
@ -130,14 +134,21 @@ struct isis_area
#ifdef TOPOLOGY_GENERATE
struct list *topology;
char topology_baseis[ISIS_SYS_ID_LEN]; /* IS for the first IS emulated. */
u_char topology_baseis[ISIS_SYS_ID_LEN]; /* IS for the first IS emulated. */
char *topology_basedynh; /* Dynamic hostname base. */
char top_params[200]; /* FIXME: what is reasonable? */
#endif /* TOPOLOGY_GENERATE */
};
void isis_init (void);
void isis_new(unsigned long);
struct isis_area *isis_area_create(const char *);
struct isis_area *isis_area_lookup (const char *);
int isis_area_get (struct vty *vty, const char *area_tag);
void print_debug(struct vty *, int, int);
/* Master of threads. */
extern struct thread_master *master;
#define DEBUG_ADJ_PACKETS (1<<0)
#define DEBUG_CHECKSUM_ERRORS (1<<1)
@ -151,5 +162,6 @@ struct isis_area *isis_area_lookup (const char *);
#define DEBUG_RTE_EVENTS (1<<9)
#define DEBUG_EVENTS (1<<10)
#define DEBUG_ZEBRA (1<<11)
#define DEBUG_PACKET_DUMP (1<<12)
#endif /* ISISD_H */

View File

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

View File

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

View File

@ -83,6 +83,7 @@ do { \
} while (0)
/* From RFC 2104 */
void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, caddr_t digest);
void hmac_md5(unsigned char* text, int text_len, unsigned char* key,
int key_len, caddr_t digest);
#endif /* ! _LIBZEBRA_MD5_H_*/

View File

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

View File

@ -52,7 +52,7 @@
* using stream_put..._at() functions.
*/
#define STREAM_WARN_OFFSETS(S) \
zlog_warn ("&(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \
zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
(S), \
(unsigned long) (S)->size, \
(unsigned long) (S)->getp, \
@ -214,6 +214,20 @@ stream_set_getp (struct stream *s, size_t pos)
s->getp = pos;
}
void
stream_set_endp (struct stream *s, size_t pos)
{
STREAM_VERIFY_SANE(s);
if (!GETP_VALID (s, pos))
{
STREAM_BOUND_WARN (s, "set endp");
pos = s->endp;
}
s->endp = pos;
}
/* Forward pointer. */
void
stream_forward_getp (struct stream *s, size_t size)
@ -934,9 +948,9 @@ stream_fifo_pop (struct stream_fifo *fifo)
if (fifo->head == NULL)
fifo->tail = NULL;
}
fifo->count--;
}
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 void stream_set_getp (struct stream *, size_t);
extern void stream_set_endp (struct stream *, size_t);
extern void stream_forward_getp (struct stream *, size_t);
extern void stream_forward_endp (struct stream *, size_t);

View File

@ -654,23 +654,7 @@ zebra_interface_add_read (struct stream *s)
/* Lookup/create interface by name. */
ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));
/* Read interface's index. */
ifp->ifindex = stream_getl (s);
/* 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 */
zebra_interface_if_set_value (s, ifp);
return ifp;
}
@ -699,16 +683,7 @@ zebra_interface_state_read (struct stream *s)
if (! ifp)
return NULL;
/* Read interface's index. */
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
ifp->status = stream_getc (s);
ifp->flags = stream_getq (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
ifp->mtu6 = stream_getl (s);
ifp->bandwidth = stream_getl (s);
zebra_interface_if_set_value (s, ifp);
return ifp;
}
@ -758,6 +733,13 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
ifp->mtu = stream_getl (s);
ifp->mtu6 = stream_getl (s);
ifp->bandwidth = stream_getl (s);
#ifdef HAVE_STRUCT_SOCKADDR_DL
stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
#else
ifp->hw_addr_len = stream_getl (s);
if (ifp->hw_addr_len)
stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_STRUCT_SOCKADDR_DL */
}
static int

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_ipv4_add (struct rib *, struct in_addr *,
struct in_addr *);
extern struct nexthop *nexthop_ipv4_ifindex_add (struct rib *,
struct in_addr *,
struct in_addr *,
unsigned int);
extern void rib_lookup_and_dump (struct prefix_ipv4 *);
extern void rib_lookup_and_pushup (struct prefix_ipv4 *);
extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *);

View File

@ -32,6 +32,7 @@
#include "prefix.h"
#include "connected.h"
#include "table.h"
#include "memory.h"
#include "rib.h"
#include "thread.h"
#include "privs.h"
@ -426,6 +427,37 @@ netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
}
}
/* Utility function to parse hardware link-layer address and update ifp */
static void
netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
{
int i;
if (tb[IFLA_ADDRESS])
{
int hw_addr_len;
hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
if (hw_addr_len > INTERFACE_HWADDR_MAX)
zlog_warn ("Hardware address is too large: %d", hw_addr_len);
else
{
ifp->hw_addr_len = hw_addr_len;
memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
for (i = 0; i < hw_addr_len; i++)
if (ifp->hw_addr[i] != 0)
break;
if (i == hw_addr_len)
ifp->hw_addr_len = 0;
else
ifp->hw_addr_len = hw_addr_len;
}
}
}
/* Called from interface_lookup_netlink(). This function is only used
during bootstrap. */
static int
@ -436,7 +468,6 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
struct rtattr *tb[IFLA_MAX + 1];
struct interface *ifp;
char *name;
int i;
ifi = NLMSG_DATA (h);
@ -474,30 +505,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Hardware type and address. */
ifp->hw_type = ifi->ifi_type;
if (tb[IFLA_ADDRESS])
{
int hw_addr_len;
hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
if (hw_addr_len > INTERFACE_HWADDR_MAX)
zlog_warn ("Hardware address is too large: %d", hw_addr_len);
else
{
ifp->hw_addr_len = hw_addr_len;
memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
for (i = 0; i < hw_addr_len; i++)
if (ifp->hw_addr[i] != 0)
break;
if (i == hw_addr_len)
ifp->hw_addr_len = 0;
else
ifp->hw_addr_len = hw_addr_len;
}
}
netlink_interface_update_hw_addr (tb, ifp);
if_add_update (ifp);
@ -709,7 +717,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (tb[RTA_PREFSRC])
src = RTA_DATA (tb[RTA_PREFSRC]);
/* Multipath treatment is needed. */
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
@ -723,7 +730,64 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
memcpy (&p.prefix, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
table, metric, 0, SAFI_UNICAST);
else
{
/* This is a multipath route */
struct rib *rib;
struct rtnexthop *rtnh =
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
rib->type = ZEBRA_ROUTE_KERNEL;
rib->distance = 0;
rib->flags = flags;
rib->metric = metric;
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
for (;;)
{
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
break;
rib->nexthop_num++;
index = rtnh->rtnh_ifindex;
gate = 0;
if (rtnh->rtnh_len > sizeof (*rtnh))
{
memset (tb, 0, sizeof (tb));
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
rtnh->rtnh_len - sizeof (*rtnh));
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
}
if (gate)
{
if (index)
nexthop_ipv4_ifindex_add (rib, gate, src, index);
else
nexthop_ipv4_add (rib, gate, src);
}
else
nexthop_ifindex_add (rib, index);
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
}
}
#ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6)
@ -867,7 +931,66 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
}
if (h->nlmsg_type == RTM_NEWROUTE)
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
{
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
metric, 0, SAFI_UNICAST);
else
{
/* This is a multipath route */
struct rib *rib;
struct rtnexthop *rtnh =
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
rib->type = ZEBRA_ROUTE_KERNEL;
rib->distance = 0;
rib->flags = 0;
rib->metric = metric;
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
for (;;)
{
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
break;
rib->nexthop_num++;
index = rtnh->rtnh_ifindex;
gate = 0;
if (rtnh->rtnh_len > sizeof (*rtnh))
{
memset (tb, 0, sizeof (tb));
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
rtnh->rtnh_len - sizeof (*rtnh));
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
}
if (gate)
{
if (index)
nexthop_ipv4_ifindex_add (rib, gate, src, index);
else
nexthop_ipv4_add (rib, gate, src);
}
else
nexthop_ifindex_add (rib, index);
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
}
}
else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
}
@ -960,6 +1083,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1;
netlink_interface_update_hw_addr (tb, ifp);
/* If new link is added. */
if_add_update (ifp);
}
@ -970,6 +1095,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1;
netlink_interface_update_hw_addr (tb, ifp);
if (if_is_operative (ifp))
{
ifp->flags = ifi->ifi_flags & 0x0000fffff;

View File

@ -232,7 +232,7 @@ nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
return nexthop;
}
static struct nexthop *
struct nexthop *
nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
struct in_addr *src, unsigned int ifindex)
{
@ -1279,14 +1279,30 @@ rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
static void
rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
{
char buf[INET_ADDRSTRLEN];
assert (zebra && rn);
if (IS_ZEBRA_DEBUG_RIB_Q)
{
char buf[INET6_ADDRSTRLEN];
inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
zlog_info ("%s: %s/%d: work queue added", __func__,
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN),
rn->p.prefixlen);
/* Pointless to queue a route_node with no RIB entries to add or remove */
if (!rn->info)
{
zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
__func__, rn, rn->lock);
zlog_backtrace(LOG_DEBUG);
return;
}
if (IS_ZEBRA_DEBUG_RIB_Q)
zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
assert (zebra);
if (zebra->ribq == NULL)
{
zlog_err ("%s: work_queue does not exist!", __func__);
return;
}
/*
@ -1301,6 +1317,11 @@ rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
work_queue_add (zebra->ribq, zebra->mq);
rib_meta_queue_add (zebra->mq, rn);
if (IS_ZEBRA_DEBUG_RIB_Q)
zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
return;
}
/* Create new meta queue.
@ -1328,6 +1349,8 @@ meta_queue_new (void)
static void
rib_queue_init (struct zebra_t *zebra)
{
assert (zebra);
if (! (zebra->ribq = work_queue_new (zebra->master,
"route_node processing")))
{
@ -1343,7 +1366,11 @@ rib_queue_init (struct zebra_t *zebra)
zebra->ribq->spec.hold = rib_process_hold_time;
if (!(zebra->mq = meta_queue_new ()))
{
zlog_err ("%s: could not initialise meta queue!", __func__);
return;
}
return;
}
/* RIB updates are processed via a queue of pointers to route_nodes.
@ -2893,6 +2920,62 @@ rib_sweep_route (void)
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
}
/* Delete routes learned from a given client. */
/* TODO(wsun) May need to split the sweep process into multiple batches,
* so that the process won't take too long if the table is large. */
static void
rib_sweep_client_table (struct route_table *table, int rib_type)
{
struct route_node *rn;
struct rib *rib;
struct rib *next;
int ret = 0;
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
for (rib = rn->info; rib; rib = next)
{
next = rib->next;
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
if (rib->type == rib_type)
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
{
/* TODO(wsun) Is this mandatory? What about graceful restart/
* non-stop forwarding */
ret = rib_uninstall_kernel (rn, rib);
if (! ret)
rib_delnode (rn, rib);
else
zlog_err ("%s: could not delete routes from kernel!",
__func__);
}
else
{
/* Always delete the node. */
rib_delnode (rn, rib);
}
}
}
/* Sweep all routes learned from a given client from RIB tables. */
void
rib_sweep_client_route (struct zserv *client)
{
assert(client);
int route_type = client->route_type;
if (route_type != ZEBRA_ROUTE_MAX)
{
zlog_debug ("%s: Removing existing routes from client type %d",
__func__, route_type);
rib_sweep_client_table (vrf_table (AFI_IP, SAFI_UNICAST, 0), route_type);
rib_sweep_client_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0), route_type);
}
}
/* Remove specific by protocol routes from 'table'. */
static unsigned long

View File

@ -140,6 +140,30 @@ zserv_create_header (struct stream *s, uint16_t cmd)
stream_putw (s, cmd);
}
static void
zserv_encode_interface (struct stream *s, struct interface *ifp)
{
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
stream_putl (s, ifp->bandwidth);
#ifdef HAVE_STRUCT_SOCKADDR_DL
stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
#else
stream_putl (s, ifp->hw_addr_len);
if (ifp->hw_addr_len)
stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
#endif /* HAVE_STRUCT_SOCKADDR_DL */
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
}
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
/*
* This function is called in the following situations:
@ -163,28 +187,8 @@ zsend_interface_add (struct zserv *client, struct interface *ifp)
s = client->obuf;
stream_reset (s);
/* Message type. */
zserv_create_header (s, ZEBRA_INTERFACE_ADD);
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
stream_putl (s, ifp->bandwidth);
#ifdef HAVE_STRUCT_SOCKADDR_DL
stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
#else
stream_putl (s, ifp->hw_addr_len);
if (ifp->hw_addr_len)
stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
#endif /* HAVE_STRUCT_SOCKADDR_DL */
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
zserv_encode_interface (s, ifp);
return zebra_server_send_message(client);
}
@ -203,19 +207,7 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp)
stream_reset (s);
zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
stream_putl (s, ifp->bandwidth);
/* Write packet length. */
stream_putw_at (s, 0, stream_get_endp (s));
zserv_encode_interface (s, ifp);
return zebra_server_send_message (client);
}
@ -328,19 +320,7 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
stream_reset (s);
zserv_create_header (s, cmd);
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
stream_putl (s, ifp->bandwidth);
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
zserv_encode_interface (s, ifp);
return zebra_server_send_message(client);
}
@ -761,6 +741,13 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* Type, flags, message. */
rib->type = stream_getc (s);
/* Update client's route type if it is not done yet. */
/* It is done here since only zread_ipv4/6_add() and
* zread_ipv4/6_delete() decode Zebra messages and retrieve
* route types. */
if (client->route_type == ZEBRA_ROUTE_MAX)
client->route_type = rib->type;
rib->flags = stream_getc (s);
message = stream_getc (s);
safi = stream_getw (s);
@ -826,7 +813,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
int i;
struct stream *s;
struct zapi_ipv4 api;
struct in_addr nexthop;
struct in_addr nexthop, *nexthop_p;
unsigned long ifindex;
struct prefix_ipv4 p;
u_char nexthop_num;
@ -836,6 +823,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
s = client->ibuf;
ifindex = 0;
nexthop.s_addr = 0;
nexthop_p = NULL;
/* Type, flags, message. */
api.type = stream_getc (s);
@ -869,6 +857,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
break;
case ZEBRA_NEXTHOP_IPV4:
nexthop.s_addr = stream_get_ipv4 (s);
nexthop_p = &nexthop;
break;
case ZEBRA_NEXTHOP_IPV6:
stream_forward_getp (s, IPV6_MAX_BYTELEN);
@ -889,7 +878,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
else
api.metric = 0;
rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
client->rtm_table, api.safi);
return 0;
}
@ -935,6 +924,11 @@ zread_ipv6_add (struct zserv *client, u_short length)
/* Type, flags, message. */
api.type = stream_getc (s);
/* Update the route type of the client.
* Same as in zread_ipv4_add(). */
if (client->route_type == ZEBRA_ROUTE_MAX)
client->route_type = api.type;
api.flags = stream_getc (s);
api.message = stream_getc (s);
api.safi = stream_getw (s);
@ -1133,6 +1127,14 @@ zebra_score_rib (int client_sock)
static void
zebra_client_close (struct zserv *client)
{
struct stream *s;
/* Sweep all routes learned from the client first. */
rib_sweep_client_route(client);
/* Reset the route type. It may not be necessary since the
* whole client will be freed. */
client->route_type = ZEBRA_ROUTE_MAX;
/* Close file descriptor. */
if (client->sock)
{
@ -1172,6 +1174,9 @@ zebra_client_create (int sock)
/* Make client input/output buffer. */
client->sock = sock;
/* Set the default route type to ZEBRA_ROUTE_MAX; it will be updated
* once new routes are received. */
client->route_type = ZEBRA_ROUTE_MAX;
client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
client->wb = buffer_new(0);

View File

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