isisd: Add support of Traffic Engineering
These patches is an implementation of RFC5305 that enable the
support of Traffic Engineering in IS-IS
* isisd/Makefile.am: Add new files isis_te.c and isis_te.h
* isisd/isis_circuit.[c,h]: Add new mpls_te_circuit structure to
isis_circuit structure to handle new Traffic Engineering TLVs
* isisd/isis_lsp.c: Update LSP handler to mux/demux Traffic Engineering TLVs
* isisd/isis_main.c: Add initialisation of ISIS TE
* isisd/isis_pdu.c: Update function process_p2p_hello() to retrieve remote
IP address to populate Traffic Engineering TLV.
* isisd/isis_te.[c,]: Implementation of RFC5305
* isisd/isis_tlv.[c,h]: Update TLV definition and function to handle
Traffic Engineering ones
* isisd/isis_zebra.c: Add new function isis_zebra_link_params() to retrieve
the link parameters of interfaces from ZBus to populate the Traffic
Engineering TLVs
* isisd/isisd.[c,h]: Add Traffic Engineering support with new debug command
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 4665490..9032de4 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -52,6 +52,7 @@
#include "isisd/isis_csm.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_spf.h"
+#include "isisd/isis_te.h"
#ifdef TOPOLOGY_GENERATE
#include "spgrid.h"
@@ -983,6 +984,8 @@
lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
vty_out (vty, " Metric : %-8d IS-Extended : %s%s",
GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE);
+ if (IS_MPLS_TE(isisMplsTE))
+ mpls_te_print_detail(vty, te_is_neigh);
}
/* TE IPv4 tlv */
@@ -1093,6 +1096,64 @@
return;
}
+/* Process IS_NEIGHBOURS TLV with TE subTLVs */
+static void
+lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, int frag_thold)
+{
+ int count, size = 0;
+ struct listnode *node, *nextnode;
+ struct te_is_neigh *elem;
+
+ /* Start computing real size of TLVs */
+ for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem))
+ size = size + elem->sub_tlvs_length + IS_NEIGHBOURS_LEN;
+
+ /* can we fit all ? */
+ if (!FRAG_NEEDED (lsp->pdu, frag_thold, size))
+ {
+ tlv_add_te_is_neighs (*from, lsp->pdu);
+ if (listcount (*to) != 0)
+ {
+ for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem))
+ {
+ listnode_add (*to, elem);
+ list_delete_node (*from, node);
+ }
+ }
+ else
+ {
+ list_free (*to);
+ *to = *from;
+ *from = NULL;
+ }
+ }
+ else
+ {
+ /* fit all we can */
+ /* Compute remaining place in LSP PDU */
+ count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
+ (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
+ /* Determine size of TE SubTLVs */
+ elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from));
+ count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN;
+ if (count > 0)
+ {
+ while (count > 0)
+ {
+ listnode_add (*to, listgetdata ((struct listnode *)listhead (*from)));
+ listnode_delete (*from, listgetdata ((struct listnode *)listhead (*from)));
+
+ elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from));
+ count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN;
+ }
+
+ tlv_add_te_is_neighs (*to, lsp->pdu);
+ }
+ }
+ lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
+ return;
+}
+
static u_int16_t
lsp_rem_lifetime (struct isis_area *area, int level)
{
@@ -1627,6 +1688,14 @@
}
else
{
+ /* Check if MPLS_TE is activate */
+ if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface))
+ /* Add SubTLVs & Adjust real size of SubTLVs */
+ te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc);
+ else
+ /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
+ te_is_neigh->sub_tlvs_length = 0;
+
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor",
area->area_tag, sysid_print(te_is_neigh->neigh_id),
@@ -1672,6 +1741,18 @@
memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
metric = circuit->te_metric[level - 1];
SET_TE_METRIC(te_is_neigh, metric);
+ /* Check if MPLS_TE is activate */
+ if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface))
+ /* Update Local and Remote IP address for MPLS TE circuit parameters */
+ /* NOTE sure that it is the pertinent place for that updates */
+ /* Local IP address could be updated in isis_circuit.c - isis_circuit_add_addr() */
+ /* But, where update remote IP address ? in isis_pdu.c - process_p2p_hello() ? */
+
+ /* Add SubTLVs & Adjust real size of SubTLVs */
+ te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc);
+ else
+ /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
+ te_is_neigh->sub_tlvs_length = 0;
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag,
sysid_print(te_is_neigh->neigh_id));