* isis_lsp.h: Added backpointer to the area from LSP. For now it's used
only in generated topology LSPs.
* isisd.[ch]: Cleanup CLI commands related to topology generation and
added command to specify base fo dynamic hostname for topology LSPs.
* isis_lsp.c: Rewrite almost all code related to generation topology
LSPs (top_lsp_refresh(), generate_topology_lsps() and
build_topology_lsp_data() functions). Topology is connected to own
LSP now (lsp_build_nonpseudo). Commented out lsppdu_realloc
functions, it's not used any more hopefully.
Topology generation feature is actually useful now.
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index a294bc8..26c46a2 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -914,6 +914,7 @@
return lsp_count;
}
+#if 0
/* this function reallocate memory to an lsp pdu, with an additional
* size of memory, it scans the lsp and moves all pointers the
* way they should */
@@ -939,6 +940,7 @@
return STREAM_DATA (lsp->pdu) + (lsp->lsp_header->pdu_len - size);
#endif /* LSP_MEMORY_PREASSIGN */
}
+#endif
#if 0 /* Saving the old one just in case :) */
/*
@@ -1356,6 +1358,28 @@
add_tlv (IPV4_ADDR, IPV4_MAX_BYTELEN, (u_char *) &routerid->s_addr,
lsp->pdu);
}
+
+#ifdef TOPOLOGY_GENERATE
+ /* If topology exists (and we create topology for level 1 only), create
+ * (hardcoded) link to topology. */
+ if (area->topology && level == 1)
+ {
+ if (tlv_data.is_neighs == NULL)
+ tlv_data.is_neighs = list_new ();
+ is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+ memset (is_neigh, 0, sizeof (struct is_neigh));
+
+ memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
+ is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (1 & 0xFF);
+ is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((1 >> 8) & 0xFF);
+ is_neigh->metrics.metric_default = 0x01;
+ is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+ listnode_add (tlv_data.is_neighs, is_neigh);
+ }
+#endif /* TOPOLOGY_GENERATE */
+
/*
* Then build lists of tlvs related to circuits
*/
@@ -2156,7 +2180,10 @@
lsp->level,
rawlspid_print (lsp->lsp_header->lsp_id),
ntohl (lsp->lsp_header->seq_num));
-
+#ifdef TOPOLOGY_GENERATE
+ if (lsp->from_topology)
+ THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
+#endif /* TOPOLOGY_GENERATE */
lsp_destroy (lsp);
dict_delete (area->lspdb[level], dnode);
}
@@ -2266,15 +2293,14 @@
top_lsp_refresh (struct thread *thread)
{
struct isis_lsp *lsp;
+ unsigned long ref_time;
lsp = THREAD_ARG (thread);
assert (lsp);
lsp->t_lsp_top_ref = NULL;
- lsp->lsp_header->rem_lifetime =
- htons (isis_jitter (MAX_AGE, MAX_AGE_JITTER));
- lsp->lsp_header->seq_num = htonl (ntohl (lsp->lsp_header->seq_num) + 1);
+ lsp_seqnum_update (lsp);
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
if (isis->debugs & DEBUG_UPDATE_PACKETS)
@@ -2282,12 +2308,14 @@
zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
rawlspid_print (lsp->lsp_header->lsp_id));
}
+ lsp->lsp_header->rem_lifetime =
+ htons (isis_jitter (lsp->area->max_lsp_lifetime[0], MAX_AGE_JITTER));
- /* time to calculate our checksum */
- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
- ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+ ref_time = lsp->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
+ MAX_LSP_GEN_INTERVAL : lsp->area->lsp_refresh[0];
+
THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
- isis_jitter (MAX_LSP_GEN_INTERVAL, MAX_LSP_GEN_JITTER));
+ isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
return ISIS_OK;
}
@@ -2300,6 +2328,7 @@
struct arc *arc;
u_char lspid[ISIS_SYS_ID_LEN + 2];
struct isis_lsp *lsp;
+ unsigned long ref_time;
/* first we find the maximal node */
for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
@@ -2319,21 +2348,24 @@
lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
- MAX_AGE_JITTER), 1, IS_LEVEL_1, 0,
- 1);
+ MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
+ if (!lsp)
+ return;
lsp->from_topology = 1;
- /* creating data based on topology */
- build_topology_lsp_data (lsp, area, i);
- /* time to calculate our checksum */
- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
- ntohs (lsp->lsp_header->pdu_len) - 12, 12);
- THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
- isis_jitter (MAX_LSP_GEN_INTERVAL,
- MAX_LSP_GEN_JITTER));
+ lsp->area = area;
+ /* Creating LSP data based on topology info. */
+ build_topology_lsp_data (lsp, area, i);
+ /* Checksum is also calculated here. */
+ lsp_seqnum_update (lsp);
+
+ ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
+ MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
+
+ THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
+ isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
lsp_insert (lsp, area->lspdb[0]);
-
}
}
@@ -2364,100 +2396,99 @@
{
struct listnode *node, *nnode;
struct arc *arc;
- u_char *tlv_ptr;
struct is_neigh *is_neigh;
- int to_lsp = 0;
char buff[200];
+ struct tlvs tlv_data;
+ struct isis_lsp *lsp0 = lsp;
- /* add our nlpids */
- /* the 2 is for the TL plus 1 for the nlpid */
- tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
- *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
- *(tlv_ptr + 1) = 1; /* one protocol */
- *(tlv_ptr + 2) = NLPID_IP;
- lsp->tlv_data.nlpids = (struct nlpids *) (tlv_ptr + 1);
+ /* Add area addresses. FIXME: Is it needed at all? */
+ if (lsp->tlv_data.area_addrs == NULL)
+ lsp->tlv_data.area_addrs = list_new ();
+ list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
- /* first, lets add the tops */
- /* the 2 is for the TL plus 1 for the virtual field */
- tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
- *tlv_ptr = IS_NEIGHBOURS; /* Type */
- *(tlv_ptr + 1) = 1; /* this is the virtual char len */
- *(tlv_ptr + 2) = 0; /* virtual is zero */
- lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
+ if (lsp->tlv_data.nlpids == NULL)
+ lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
+ lsp->tlv_data.nlpids->count = 1;
+ lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
- /* add reachability for this IS for simulated 1 */
+ if (area->dynhostname)
+ {
+ lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
+ sizeof (struct hostname));
+ memset (buff, 0x00, 200);
+ sprintf (buff, "%s%d", area->topology_basedynh ? area->topology_basedynh :
+ "feedme", lsp_top_num);
+ memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
+ lsp->tlv_data.hostname->namelen = strlen (buff);
+ }
+
+ if (lsp->tlv_data.nlpids)
+ tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
+ if (lsp->tlv_data.hostname)
+ tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
+ if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
+ tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
+
+ memset (&tlv_data, 0, sizeof (struct tlvs));
+ if (tlv_data.is_neighs == NULL)
+ tlv_data.is_neighs = list_new ();
+
+ /* Add reachability for this IS for simulated 1. */
if (lsp_top_num == 1)
{
- /* assign space for the is_neigh at the pdu end */
- is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
- sizeof (struct
- is_neigh));
- /* add this node to our list */
- listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+ is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+ memset (is_neigh, 0, sizeof (struct is_neigh));
+
memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
- is_neigh->metrics.metric_default = 0x00; /* no special reason */
+ /* Metric MUST NOT be 0, unless it's not alias TLV. */
+ is_neigh->metrics.metric_default = 0x01;
is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
- /* don't forget the length */
- *(tlv_ptr + 1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
- /* no need to check for fragging here, it is a lonely is_reach */
+ listnode_add (tlv_data.is_neighs, is_neigh);
}
- /* addding is reachabilities */
+ /* Add IS reachabilities. */
for (ALL_LIST_ELEMENTS (area->topology, node, nnode, arc))
- {
- if ((arc->from_node == lsp_top_num) || (arc->to_node == lsp_top_num))
- {
- if (arc->to_node == lsp_top_num)
- to_lsp = arc->from_node;
- if (arc->from_node == lsp_top_num)
- to_lsp = arc->to_node;
-
- /* if the length here is about to cross the FF limit, we reTLV */
- if (*(tlv_ptr + 1) >= (0xFF - IS_NEIGHBOURS_LEN))
- {
- /* retlv */
- /* the 2 is for the TL plus 1 for the virtual field */
- tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
- *tlv_ptr = IS_NEIGHBOURS; /* Type */
- *(tlv_ptr + 1) = 1; /* this is the virtual char len */
- *(tlv_ptr + 2) = 0; /* virtual is zero */
- }
- /* doing this here assures us that we won't add an "empty" tlv */
- /* assign space for the is_neigh at the pdu end */
- is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
- sizeof (struct
- is_neigh));
- /* add this node to our list */
- listnode_add (lsp->tlv_data.is_neighs, is_neigh);
- memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
- is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
- is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
- is_neigh->metrics.metric_default = arc->distance;
- is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
- /* don't forget the length */
- *(tlv_ptr + 1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
- }
- }
-
- /* adding dynamic hostname if needed */
- if (area->dynhostname)
{
- memset (buff, 0x00, 200);
- sprintf (buff, "feedme%d", lsp_top_num);
- /* the 2 is for the TL */
- tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 2);
- *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
- *(tlv_ptr + 1) = strlen (buff); /* Length */
- /* the -1 is to fit the length in the struct */
- lsp->tlv_data.hostname = (struct hostname *)
- (lsppdu_realloc (lsp, MTYPE_ISIS_TLV, strlen (buff)) - 1);
- memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
+ int to_lsp = 0;
+
+ if ((lsp_top_num != arc->from_node) && (lsp_top_num != arc->to_node))
+ continue;
+
+ if (lsp_top_num == arc->from_node)
+ to_lsp = arc->to_node;
+ else
+ to_lsp = arc->from_node;
+
+ is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+ memset (is_neigh, 0, sizeof (struct is_neigh));
+
+ memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
+ is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
+ is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
+ is_neigh->metrics.metric_default = arc->distance;
+ is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+ listnode_add (tlv_data.is_neighs, is_neigh);
}
+
+ while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
+ {
+ if (lsp->tlv_data.is_neighs == NULL)
+ lsp->tlv_data.is_neighs = list_new ();
+ lsp_tlv_fit (lsp, &tlv_data.is_neighs,
+ &lsp->tlv_data.is_neighs,
+ IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
+ tlv_add_is_neighs);
+ if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
+ lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
+ lsp0, area, IS_LEVEL_1);
+ }
+
+ free_tlvs (&tlv_data);
+ return;
}
#endif /* TOPOLOGY_GENERATE */