diff options
Diffstat (limited to 'isisd/isis_adjacency.c')
| -rw-r--r-- | isisd/isis_adjacency.c | 882 | 
1 files changed, 434 insertions, 448 deletions
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index e4a4e0c426..d8cb32375b 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -1,19 +1,19 @@  /* - * IS-IS Rout(e)ing protocol - isis_adjacency.c    + * IS-IS Rout(e)ing protocol - isis_adjacency.c   *                             handling of IS-IS adjacencies   *   * Copyright (C) 2001,2002   Sampo Saaristo - *                           Tampere University of Technology       + *                           Tampere University of Technology   *                           Institute of Communications Engineering   * - * This program is free software; you can redistribute it and/or modify it  - * under the terms of the GNU General Public Licenseas published by the Free  - * Software Foundation; either version 2 of the License, or (at your option)  + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option)   * any later version.   * - * This program is distributed in the hope that it will be useful,but WITHOUT  - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   * more details.   *   * You should have received a copy of the GNU General Public License along @@ -51,512 +51,498 @@  extern struct isis *isis; -static struct isis_adjacency * -adj_alloc (const u_char *id) +static struct isis_adjacency *adj_alloc(const u_char *id)  { -  struct isis_adjacency *adj; +	struct isis_adjacency *adj; -  adj = XCALLOC (MTYPE_ISIS_ADJACENCY, sizeof (struct isis_adjacency)); -  memcpy (adj->sysid, id, ISIS_SYS_ID_LEN); +	adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency)); +	memcpy(adj->sysid, id, ISIS_SYS_ID_LEN); -  return adj; +	return adj;  } -struct isis_adjacency * -isis_new_adj (const u_char * id, const u_char * snpa, int level, -	      struct isis_circuit *circuit) +struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa, +				    int level, struct isis_circuit *circuit)  { -  struct isis_adjacency *adj; -  int i; - -  adj = adj_alloc (id);		/* P2P kludge */ - -  if (adj == NULL) -    { -      zlog_err ("Out of memory!"); -      return NULL; -    } - -  if (snpa) { -    memcpy (adj->snpa, snpa, ETH_ALEN); -  } else { -    memset (adj->snpa, ' ', ETH_ALEN); -  } - -  adj->circuit = circuit; -  adj->level = level; -  adj->flaps = 0; -  adj->last_flap = time (NULL); -  if (circuit->circ_type == CIRCUIT_T_BROADCAST) -    { -      listnode_add (circuit->u.bc.adjdb[level - 1], adj); -      adj->dischanges[level - 1] = 0; -      for (i = 0; i < DIS_RECORDS; i++)	/* clear N DIS state change records */ -	{ -	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis -	    = ISIS_UNKNOWN_DIS; -	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change -	    = time (NULL); +	struct isis_adjacency *adj; +	int i; + +	adj = adj_alloc(id); /* P2P kludge */ + +	if (adj == NULL) { +		zlog_err("Out of memory!"); +		return NULL; +	} + +	if (snpa) { +		memcpy(adj->snpa, snpa, ETH_ALEN); +	} else { +		memset(adj->snpa, ' ', ETH_ALEN);  	} -    } -  return adj; +	adj->circuit = circuit; +	adj->level = level; +	adj->flaps = 0; +	adj->last_flap = time(NULL); +	if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +		listnode_add(circuit->u.bc.adjdb[level - 1], adj); +		adj->dischanges[level - 1] = 0; +		for (i = 0; i < DIS_RECORDS; +		     i++) /* clear N DIS state change records */ +		{ +			adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis = +				ISIS_UNKNOWN_DIS; +			adj->dis_record[(i * ISIS_LEVELS) + level - 1] +				.last_dis_change = time(NULL); +		} +	} + +	return adj;  } -struct isis_adjacency * -isis_adj_lookup (const u_char * sysid, struct list *adjdb) +struct isis_adjacency *isis_adj_lookup(const u_char *sysid, struct list *adjdb)  { -  struct isis_adjacency *adj; -  struct listnode *node; +	struct isis_adjacency *adj; +	struct listnode *node; -  for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) -    if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) -      return adj; +	for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) +		if (memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) +			return adj; -  return NULL; +	return NULL;  } -struct isis_adjacency * -isis_adj_lookup_snpa (const u_char * ssnpa, struct list *adjdb) +struct isis_adjacency *isis_adj_lookup_snpa(const u_char *ssnpa, +					    struct list *adjdb)  { -  struct listnode *node; -  struct isis_adjacency *adj; +	struct listnode *node; +	struct isis_adjacency *adj; -  for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) -    if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0) -      return adj; +	for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) +		if (memcmp(adj->snpa, ssnpa, ETH_ALEN) == 0) +			return adj; -  return NULL; +	return NULL;  } -void -isis_delete_adj (void *arg) +void isis_delete_adj(void *arg)  { -  struct isis_adjacency *adj = arg; +	struct isis_adjacency *adj = arg; -  if (!adj) -    return; +	if (!adj) +		return; -  THREAD_TIMER_OFF (adj->t_expire); +	THREAD_TIMER_OFF(adj->t_expire); -  /* remove from SPF trees */ -  spftree_area_adj_del (adj->circuit->area, adj); +	/* 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); -  if (adj->ipv6_addrs) -    list_delete (adj->ipv6_addrs); +	if (adj->area_addrs) +		list_delete(adj->area_addrs); +	if (adj->ipv4_addrs) +		list_delete(adj->ipv4_addrs); +	if (adj->ipv6_addrs) +		list_delete(adj->ipv6_addrs); -  adj_mt_finish(adj); +	adj_mt_finish(adj); -  XFREE (MTYPE_ISIS_ADJACENCY, adj); -  return; +	XFREE(MTYPE_ISIS_ADJACENCY, adj); +	return;  } -static const char * -adj_state2string (int state) +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 */ +	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 new_state, -		       const char *reason) +void isis_adj_state_change(struct isis_adjacency *adj, +			   enum isis_adj_state new_state, const char *reason)  { -  int old_state; -  int level; -  struct isis_circuit *circuit; -  bool del; - -  old_state = adj->adj_state; -  adj->adj_state = new_state; - -  circuit = adj->circuit; - -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", -		 circuit->area->area_tag, -		 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 = sysid_print (adj->sysid); - -      zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", -		 adj_name, -		 adj->circuit->interface->name, -		 adj_state2string (old_state), -		 adj_state2string (new_state), -		 reason ? reason : "unspecified"); -    } - -  if (circuit->circ_type == CIRCUIT_T_BROADCAST) -    { -      del = false; -      for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) -      { -        if ((adj->level & level) == 0) -          continue; -        if (new_state == ISIS_ADJ_UP) -        { -          circuit->upadjcount[level - 1]++; -          isis_event_adjacency_state_change (adj, new_state); -          /* update counter & timers for debugging purposes */ -          adj->last_flap = time (NULL); -          adj->flaps++; -        } -        else if (new_state == ISIS_ADJ_DOWN) -        { -          listnode_delete (circuit->u.bc.adjdb[level - 1], adj); -          circuit->upadjcount[level - 1]--; -          if (circuit->upadjcount[level - 1] == 0) -            { -              /* Clean lsp_queue when no adj is up. */ -              if (circuit->lsp_queue) -                list_delete_all_node (circuit->lsp_queue); -            } -          isis_event_adjacency_state_change (adj, new_state); -          del = true; -        } - -        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]); -          } - -        /* 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); -      } - -      if (del) -        isis_delete_adj (adj); - -      adj = NULL; -    } -  else if (circuit->circ_type == CIRCUIT_T_P2P) -    { -      del = false; -      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, level); - -          /* update counter & timers for debugging purposes */ -          adj->last_flap = time (NULL); -          adj->flaps++; - -          /* 7.3.17 - going up on P2P -> send CSNP */ -          /* FIXME: yup, I know its wrong... but i will do it! (for now) */ -          send_csnp (circuit, level); -        } -        else if (new_state == ISIS_ADJ_DOWN) -        { -          if (adj->circuit->u.p2p.neighbor == adj) -            adj->circuit->u.p2p.neighbor = NULL; -          circuit->upadjcount[level - 1]--; -          if (circuit->upadjcount[level - 1] == 0) -            { -              /* Clean lsp_queue when no adj is up. */ -              if (circuit->lsp_queue) -                list_delete_all_node (circuit->lsp_queue); -            } -          isis_event_adjacency_state_change (adj, new_state); -          del = true; -        } -      } - -      if (del) -        isis_delete_adj (adj); - -      adj = NULL; -    } - -  return; +	int old_state; +	int level; +	struct isis_circuit *circuit; +	bool del; + +	old_state = adj->adj_state; +	adj->adj_state = new_state; + +	circuit = adj->circuit; + +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		zlog_debug("ISIS-Adj (%s): Adjacency state change %d->%d: %s", +			   circuit->area->area_tag, 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 = sysid_print(adj->sysid); + +		zlog_info( +			"%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", +			adj_name, adj->circuit->interface->name, +			adj_state2string(old_state), +			adj_state2string(new_state), +			reason ? reason : "unspecified"); +	} + +	if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +		del = false; +		for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { +			if ((adj->level & level) == 0) +				continue; +			if (new_state == ISIS_ADJ_UP) { +				circuit->upadjcount[level - 1]++; +				isis_event_adjacency_state_change(adj, +								  new_state); +				/* update counter & timers for debugging +				 * purposes */ +				adj->last_flap = time(NULL); +				adj->flaps++; +			} else if (new_state == ISIS_ADJ_DOWN) { +				listnode_delete(circuit->u.bc.adjdb[level - 1], +						adj); +				circuit->upadjcount[level - 1]--; +				if (circuit->upadjcount[level - 1] == 0) { +					/* Clean lsp_queue when no adj is up. */ +					if (circuit->lsp_queue) +						list_delete_all_node( +							circuit->lsp_queue); +				} +				isis_event_adjacency_state_change(adj, +								  new_state); +				del = true; +			} + +			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]); +			} + +			/* 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); +		} + +		if (del) +			isis_delete_adj(adj); + +		adj = NULL; +	} else if (circuit->circ_type == CIRCUIT_T_P2P) { +		del = false; +		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, level); + +				/* update counter & timers for debugging +				 * purposes */ +				adj->last_flap = time(NULL); +				adj->flaps++; + +				/* 7.3.17 - going up on P2P -> send CSNP */ +				/* FIXME: yup, I know its wrong... but i will do +				 * it! (for now) */ +				send_csnp(circuit, level); +			} else if (new_state == ISIS_ADJ_DOWN) { +				if (adj->circuit->u.p2p.neighbor == adj) +					adj->circuit->u.p2p.neighbor = NULL; +				circuit->upadjcount[level - 1]--; +				if (circuit->upadjcount[level - 1] == 0) { +					/* Clean lsp_queue when no adj is up. */ +					if (circuit->lsp_queue) +						list_delete_all_node( +							circuit->lsp_queue); +				} +				isis_event_adjacency_state_change(adj, +								  new_state); +				del = true; +			} +		} + +		if (del) +			isis_delete_adj(adj); + +		adj = NULL; +	} + +	return;  } -void -isis_adj_print (struct isis_adjacency *adj) +void isis_adj_print(struct isis_adjacency *adj)  { -  struct isis_dynhn *dyn; -  struct listnode *node; -  struct in_addr *ipv4_addr; -  struct in6_addr *ipv6_addr; -  u_char ip6[INET6_ADDRSTRLEN]; - -  if (!adj) -    return; -  dyn = dynhn_find_by_id (adj->sysid); -  if (dyn) -    zlog_debug ("%s", dyn->name.name); - -  zlog_debug ("SystemId %20s SNPA %s, level %d\nHolding Time %d", -              sysid_print (adj->sysid), snpa_print (adj->snpa), -              adj->level, adj->hold_time); -  if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) -    { -      zlog_debug ("IPv4 Address(es):"); - -      for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) -        zlog_debug ("%s", inet_ntoa (*ipv4_addr)); -    } - -  if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) -    { -      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); -	  zlog_debug ("%s", ip6); +	struct isis_dynhn *dyn; +	struct listnode *node; +	struct in_addr *ipv4_addr; +	struct in6_addr *ipv6_addr; +	u_char ip6[INET6_ADDRSTRLEN]; + +	if (!adj) +		return; +	dyn = dynhn_find_by_id(adj->sysid); +	if (dyn) +		zlog_debug("%s", dyn->name.name); + +	zlog_debug("SystemId %20s SNPA %s, level %d\nHolding Time %d", +		   sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level, +		   adj->hold_time); +	if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) { +		zlog_debug("IPv4 Address(es):"); + +		for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr)) +			zlog_debug("%s", inet_ntoa(*ipv4_addr)); +	} + +	if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) { +		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); +			zlog_debug("%s", ip6); +		}  	} -    } -  zlog_debug ("Speaks: %s", nlpid2string (&adj->nlpids)); +	zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids)); -  return; +	return;  } -int -isis_adj_expire (struct thread *thread) +int isis_adj_expire(struct thread *thread)  { -  struct isis_adjacency *adj; +	struct isis_adjacency *adj; -  /* -   * Get the adjacency -   */ -  adj = THREAD_ARG (thread); -  assert (adj); -  adj->t_expire = NULL; +	/* +	 * Get the adjacency +	 */ +	adj = THREAD_ARG(thread); +	assert(adj); +	adj->t_expire = NULL; -  /* trigger the adj expire event */ -  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired"); +	/* trigger the adj expire event */ +	isis_adj_state_change(adj, ISIS_ADJ_DOWN, "holding time expired"); -  return 0; +	return 0;  }  /*   * show isis neighbor [detail]   */ -void -isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) +void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, +			char detail)  { -  struct in6_addr *ipv6_addr; -  u_char ip6[INET6_ADDRSTRLEN]; -  struct in_addr *ip_addr; -  time_t now; -  struct isis_dynhn *dyn; -  int level; -  struct listnode *node; - -  dyn = dynhn_find_by_id (adj->sysid); -  if (dyn) -    vty_out (vty, "  %-20s", dyn->name.name); -  else -    vty_out (vty, "  %-20s", sysid_print (adj->sysid)); - -  if (detail == ISIS_UI_LEVEL_BRIEF) -    { -      if (adj->circuit) -	vty_out (vty, "%-12s", adj->circuit->interface->name); -      else -	vty_out (vty, "NULL circuit!"); -      vty_out (vty, "%-3u", adj->level);	/* level */ -      vty_out (vty, "%-13s", adj_state2string (adj->adj_state)); -      now = time (NULL); -      if (adj->last_upd) -        vty_out (vty, "%-9llu", -                 (unsigned long long)adj->last_upd + adj->hold_time - now); -      else -	vty_out (vty, "-        "); -      vty_out (vty, "%-10s", snpa_print (adj->snpa)); -      vty_out (vty, "\n"); -    } - -  if (detail == ISIS_UI_LEVEL_DETAIL) -    { -      level = adj->level; -      vty_out (vty, "\n"); -      if (adj->circuit) -	vty_out (vty, "    Interface: %s", adj->circuit->interface->name); -      else -	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); -      if (adj->last_upd) -	vty_out (vty, ", Expires in %s", -		 time2string (adj->last_upd + adj->hold_time - now)); -      else -	vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); -      vty_out (vty, "\n"); -      vty_out (vty, "    Adjacency flaps: %u", adj->flaps); -      vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap)); -      vty_out (vty, "\n"); -      vty_out (vty, "    Circuit type: %s", circuit_t2string (adj->circuit_t)); -      vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); -      vty_out (vty, "\n"); -      if (adj->mt_count != 1 || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) -        { -          vty_out (vty, "    Topologies:\n"); -          for (unsigned int i = 0; i < adj->mt_count; i++) -            vty_out (vty, "      %s\n", isis_mtid2str(adj->mt_set[i])); -        } -      vty_out (vty, "    SNPA: %s", snpa_print (adj->snpa)); -      if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) -      { -        dyn = dynhn_find_by_id (adj->lanid); -        if (dyn) -          vty_out (vty, ", LAN id: %s.%02x", -              dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); -        else -          vty_out (vty, ", LAN id: %s.%02x", -              sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); - -        vty_out (vty, "\n"); -        vty_out (vty, "    LAN Priority: %u", adj->prio[adj->level - 1]); - -        vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago", -            isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. -              dis), adj->dischanges[level - 1], -            time2string (now - -              (adj->dis_record[ISIS_LEVELS + level - 1]. -               last_dis_change))); -      } -      vty_out (vty, "\n"); - -      if (adj->area_addrs && listcount (adj->area_addrs) > 0) -        { -          struct area_addr *area_addr; -          vty_out (vty, "    Area Address(es):\n"); -          for (ALL_LIST_ELEMENTS_RO (adj->area_addrs, node, area_addr)) -            vty_out (vty, "      %s\n", -                       isonet_print(area_addr->area_addr, area_addr->addr_len)); -        } -      if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) -	{ -	  vty_out (vty, "    IPv4 Address(es):\n"); -	  for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr)) -            vty_out (vty, "      %s\n", inet_ntoa(*ip_addr)); +	struct in6_addr *ipv6_addr; +	u_char ip6[INET6_ADDRSTRLEN]; +	struct in_addr *ip_addr; +	time_t now; +	struct isis_dynhn *dyn; +	int level; +	struct listnode *node; + +	dyn = dynhn_find_by_id(adj->sysid); +	if (dyn) +		vty_out(vty, "  %-20s", dyn->name.name); +	else +		vty_out(vty, "  %-20s", sysid_print(adj->sysid)); + +	if (detail == ISIS_UI_LEVEL_BRIEF) { +		if (adj->circuit) +			vty_out(vty, "%-12s", adj->circuit->interface->name); +		else +			vty_out(vty, "NULL circuit!"); +		vty_out(vty, "%-3u", adj->level); /* level */ +		vty_out(vty, "%-13s", adj_state2string(adj->adj_state)); +		now = time(NULL); +		if (adj->last_upd) +			vty_out(vty, "%-9llu", +				(unsigned long long)adj->last_upd +					+ adj->hold_time - now); +		else +			vty_out(vty, "-        "); +		vty_out(vty, "%-10s", snpa_print(adj->snpa)); +		vty_out(vty, "\n");  	} -      if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) -	{ -	  vty_out (vty, "    IPv6 Address(es):\n"); -	  for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) -	    { -	      inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); -	      vty_out (vty, "      %s\n", ip6); -	    } + +	if (detail == ISIS_UI_LEVEL_DETAIL) { +		level = adj->level; +		vty_out(vty, "\n"); +		if (adj->circuit) +			vty_out(vty, "    Interface: %s", +				adj->circuit->interface->name); +		else +			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); +		if (adj->last_upd) +			vty_out(vty, ", Expires in %s", +				time2string(adj->last_upd + adj->hold_time +					    - now)); +		else +			vty_out(vty, ", Expires in %s", +				time2string(adj->hold_time)); +		vty_out(vty, "\n"); +		vty_out(vty, "    Adjacency flaps: %u", adj->flaps); +		vty_out(vty, ", Last: %s ago", +			time2string(now - adj->last_flap)); +		vty_out(vty, "\n"); +		vty_out(vty, "    Circuit type: %s", +			circuit_t2string(adj->circuit_t)); +		vty_out(vty, ", Speaks: %s", nlpid2string(&adj->nlpids)); +		vty_out(vty, "\n"); +		if (adj->mt_count != 1 +		    || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) { +			vty_out(vty, "    Topologies:\n"); +			for (unsigned int i = 0; i < adj->mt_count; i++) +				vty_out(vty, "      %s\n", +					isis_mtid2str(adj->mt_set[i])); +		} +		vty_out(vty, "    SNPA: %s", snpa_print(adj->snpa)); +		if (adj->circuit +		    && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { +			dyn = dynhn_find_by_id(adj->lanid); +			if (dyn) +				vty_out(vty, ", LAN id: %s.%02x", +					dyn->name.name, +					adj->lanid[ISIS_SYS_ID_LEN]); +			else +				vty_out(vty, ", LAN id: %s.%02x", +					sysid_print(adj->lanid), +					adj->lanid[ISIS_SYS_ID_LEN]); + +			vty_out(vty, "\n"); +			vty_out(vty, "    LAN Priority: %u", +				adj->prio[adj->level - 1]); + +			vty_out(vty, ", %s, DIS flaps: %u, Last: %s ago", +				isis_disflag2string( +					adj->dis_record[ISIS_LEVELS + level - 1] +						.dis), +				adj->dischanges[level - 1], +				time2string(now - (adj->dis_record[ISIS_LEVELS +								   + level - 1] +							   .last_dis_change))); +		} +		vty_out(vty, "\n"); + +		if (adj->area_addrs && listcount(adj->area_addrs) > 0) { +			struct area_addr *area_addr; +			vty_out(vty, "    Area Address(es):\n"); +			for (ALL_LIST_ELEMENTS_RO(adj->area_addrs, node, +						  area_addr)) +				vty_out(vty, "      %s\n", +					isonet_print(area_addr->area_addr, +						     area_addr->addr_len)); +		} +		if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) { +			vty_out(vty, "    IPv4 Address(es):\n"); +			for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, +						  ip_addr)) +				vty_out(vty, "      %s\n", inet_ntoa(*ip_addr)); +		} +		if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) { +			vty_out(vty, "    IPv6 Address(es):\n"); +			for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, +						  ipv6_addr)) { +				inet_ntop(AF_INET6, ipv6_addr, (char *)ip6, +					  INET6_ADDRSTRLEN); +				vty_out(vty, "      %s\n", ip6); +			} +		} +		vty_out(vty, "\n");  	} -      vty_out (vty, "\n"); -    } -  return; +	return;  } -void -isis_adj_build_neigh_list (struct list *adjdb, struct list *list) +void isis_adj_build_neigh_list(struct list *adjdb, struct list *list)  { -  struct isis_adjacency *adj; -  struct listnode *node; - -  if (!list) -    { -      zlog_warn ("isis_adj_build_neigh_list(): NULL list"); -      return; -    } - -  for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) -    { -      if (!adj) -	{ -	  zlog_warn ("isis_adj_build_neigh_list(): NULL adj"); -	  return; +	struct isis_adjacency *adj; +	struct listnode *node; + +	if (!list) { +		zlog_warn("isis_adj_build_neigh_list(): NULL list"); +		return;  	} -      if ((adj->adj_state == ISIS_ADJ_UP || -	   adj->adj_state == ISIS_ADJ_INITIALIZING)) -	listnode_add (list, adj->snpa); -    } -  return; +	for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { +		if (!adj) { +			zlog_warn("isis_adj_build_neigh_list(): NULL adj"); +			return; +		} + +		if ((adj->adj_state == ISIS_ADJ_UP +		     || adj->adj_state == ISIS_ADJ_INITIALIZING)) +			listnode_add(list, adj->snpa); +	} +	return;  } -void -isis_adj_build_up_list (struct list *adjdb, struct list *list) +void isis_adj_build_up_list(struct list *adjdb, struct list *list)  { -  struct isis_adjacency *adj; -  struct listnode *node; - -  if (adjdb == NULL) { -    zlog_warn ("isis_adj_build_up_list(): adjacency DB is empty"); -    return; -  } - -  if (!list) -    { -      zlog_warn ("isis_adj_build_up_list(): NULL list"); -      return; -    } - -  for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) -    { -      if (!adj) -	{ -	  zlog_warn ("isis_adj_build_up_list(): NULL adj"); -	  return; +	struct isis_adjacency *adj; +	struct listnode *node; + +	if (adjdb == NULL) { +		zlog_warn("isis_adj_build_up_list(): adjacency DB is empty"); +		return; +	} + +	if (!list) { +		zlog_warn("isis_adj_build_up_list(): NULL list"); +		return;  	} -      if (adj->adj_state == ISIS_ADJ_UP) -	listnode_add (list, adj); -    } +	for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { +		if (!adj) { +			zlog_warn("isis_adj_build_up_list(): NULL adj"); +			return; +		} -  return; +		if (adj->adj_state == ISIS_ADJ_UP) +			listnode_add(list, adj); +	} + +	return;  } -int -isis_adj_usage2levels(enum isis_adj_usage usage) +int isis_adj_usage2levels(enum isis_adj_usage usage)  { -  switch (usage) -    { -    case ISIS_ADJ_LEVEL1: -      return IS_LEVEL_1; -    case ISIS_ADJ_LEVEL2: -      return IS_LEVEL_2; -    case ISIS_ADJ_LEVEL1AND2: -      return IS_LEVEL_1 | IS_LEVEL_2; -    default: -      break; -    } -  return 0; +	switch (usage) { +	case ISIS_ADJ_LEVEL1: +		return IS_LEVEL_1; +	case ISIS_ADJ_LEVEL2: +		return IS_LEVEL_2; +	case ISIS_ADJ_LEVEL1AND2: +		return IS_LEVEL_1 | IS_LEVEL_2; +	default: +		break; +	} +	return 0;  }  | 
