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_tlv.c b/isisd/isis_tlv.c
index 8d4ea0e..1d29d78 100644
--- a/isisd/isis_tlv.c
+++ b/isisd/isis_tlv.c
@@ -42,6 +42,7 @@
 #include "isisd/isis_misc.h"
 #include "isisd/isis_pdu.h"
 #include "isisd/isis_lsp.h"
+#include "isisd/isis_te.h"
 
 void
 free_tlv (void *val)
@@ -178,7 +179,6 @@
 	       * |                        Virtual Flag                           | 
 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
 	       */
-	      /* virtual = *pnt; FIXME: what is the use for this? */
 	      pnt++;
 	      value_len++;
 	      /* +-------+-------+-------+-------+-------+-------+-------+-------+
@@ -230,9 +230,23 @@
 	      while (length > value_len)
 		{
 		  te_is_nei = (struct te_is_neigh *) pnt;
-		  value_len += 11;
-		  pnt += 11;
-		  /* FIXME - subtlvs are handled here, for now we skip */
+		  value_len += IS_NEIGHBOURS_LEN;
+		  pnt += IS_NEIGHBOURS_LEN;
+                  /* FIXME - subtlvs are handled here, for now we skip */
+		  /* FIXME: All TE SubTLVs are not necessary present in LSP PDU. */
+		  /* So, it must be copied in a new te_is_neigh structure        */
+		  /* rather than just initialize pointer to the original LSP PDU */
+		  /* to avoid consider the rest of lspdu as subTLVs or buffer overflow */
+		  if (IS_MPLS_TE(isisMplsTE))
+		    {
+		      struct te_is_neigh *new = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh));
+		      memcpy(new->neigh_id, te_is_nei->neigh_id, ISIS_SYS_ID_LEN + 1);
+		      memcpy(new->te_metric, te_is_nei->te_metric, 3);
+		      new->sub_tlvs_length = te_is_nei->sub_tlvs_length;
+		      memcpy(new->sub_tlvs, pnt, te_is_nei->sub_tlvs_length);
+                      te_is_nei = new;
+                    }
+		  /* Skip SUB TLVs payload */
 		  value_len += te_is_nei->sub_tlvs_length;
 		  pnt += te_is_nei->sub_tlvs_length;
 
@@ -846,8 +860,8 @@
 
   for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
     {
-      /* FIXME: This will be wrong if we are going to add TE sub TLVs. */
-      if (pos - value + IS_NEIGHBOURS_LEN > 255)
+      /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
+      if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255)
         {
           retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
           if (retval != ISIS_OK)
@@ -859,9 +873,15 @@
       pos += ISIS_SYS_ID_LEN + 1;
       memcpy (pos, te_is_neigh->te_metric, 3);
       pos += 3;
-      /* Sub TLVs length. */
-      *pos = 0;
+      /* Set the total size of Sub TLVs */
+      *pos = te_is_neigh->sub_tlvs_length;
       pos++;
+      /* Copy Sub TLVs if any */
+      if (te_is_neigh->sub_tlvs_length > 0)
+        {
+          memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length);
+          pos += te_is_neigh->sub_tlvs_length;
+        }
     }
 
   return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);