]> git.proxmox.com Git - mirror_frr.git/commitdiff
Update Traffic Engineering Support for OSPFD
authorOlivier Dugeon <olivier.dugeon@orange.com>
Tue, 19 Apr 2016 14:21:46 +0000 (16:21 +0200)
committerDonald Sharp <sharpd@cumulusnetwroks.com>
Sat, 3 Sep 2016 15:05:50 +0000 (11:05 -0400)
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches.  Since this
series builds together I am doing this. -DBS

This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering

* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format

* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
  safely convert between big-endian IEEE-754 single and double binary
  format, as used in IETF RFCs, and C99.  Implementation depends on host
  using __STDC_IEC_559__, which should be everything we care about.  Should
  correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra

* zebra/interface.c:
   - Add new link-params CLI commands
   - Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh

In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD

These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).

* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp

32 files changed:
lib/command.c
lib/command.h
lib/if.c
lib/if.h
lib/memtypes.c
lib/network.c
lib/network.h
lib/stream.c
lib/stream.h
lib/zclient.c
lib/zclient.h
lib/zebra.h
ospfd/ospf_dump.c
ospfd/ospf_dump.h
ospfd/ospf_opaque.c
ospfd/ospf_opaque.h
ospfd/ospf_packet.c
ospfd/ospf_te.c
ospfd/ospf_te.h
ospfd/ospf_vty.c
ospfd/ospf_vty.h
ospfd/ospf_zebra.c
ospfd/ospfd.c
ospfd/ospfd.h
vtysh/extract.pl.in
vtysh/vtysh.c
zebra/interface.c
zebra/redistribute.c
zebra/redistribute.h
zebra/redistribute_null.c
zebra/zserv.c
zebra/zserv.h

index 10ab066bfb3537ea083da2b3cecfc7f01039e531..0e921bd6360760d92f1755227a2862c1736ea581 100644 (file)
@@ -2537,8 +2537,12 @@ node_parent ( enum node_type node )
     case KEYCHAIN_KEY_NODE:
       ret = KEYCHAIN_NODE;
       break;
+    case LINK_PARAMS_NODE:
+      ret = INTERFACE_NODE;
+      break;
     default:
       ret = CONFIG_NODE;
+      break;
     }
 
   return ret;
@@ -2926,6 +2930,9 @@ DEFUN (config_exit,
     case KEYCHAIN_KEY_NODE:
       vty->node = KEYCHAIN_NODE;
       break;
+    case LINK_PARAMS_NODE:
+      vty->node = INTERFACE_NODE;
+      break;
     default:
       break;
     }
@@ -2975,6 +2982,7 @@ DEFUN (config_end,
     case MASC_NODE:
     case PIM_NODE:
     case VTY_NODE:
+    case LINK_PARAMS_NODE:
       vty_config_unlock (vty);
       vty->node = ENABLE_NODE;
       break;
index c1ef0e55bd110ce5bb2f1781911b0b9378b27aa5..8f20a928077dadebf3811ea142860224e756be63 100644 (file)
@@ -108,6 +108,7 @@ enum node_type
   FORWARDING_NODE,             /* IP forwarding node. */
   PROTOCOL_NODE,                /* protocol filtering node */
   VTY_NODE,                    /* Vty node. */
+  LINK_PARAMS_NODE,            /* Link-parameters node */
 };
 
 /* Node which has some commands and prompt string and configuration
@@ -516,6 +517,10 @@ struct cmd_token
 #define AREA_TAG_STR "[area tag]\n"
 #define COMMUNITY_AANN_STR "Community number where AA and NN are <0-65535>\n"
 #define COMMUNITY_VAL_STR  "Community number in AA:NN format (where AA and NN are <0-65535>) or local-AS|no-advertise|no-export|internet or additive\n"
+#define MPLS_TE_STR "MPLS-TE specific commands\n"
+#define LINK_PARAMS_STR "Configure interface link parameters\n"
+#define OSPF_RI_STR "OSPF Router Information specific commands\n"
+#define PCE_STR "PCE Router Information specific commands\n"
 
 #define CONF_BACKUP_EXT ".sav"
 
index 11d339ffb705579f091faa8065aa3c152bbb9475..e44882a43e9a203456004ef32d79ace25544483d 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -205,6 +205,8 @@ if_delete (struct interface *ifp)
   list_free (ifp->connected);
   list_free (ifp->nbr_connected);
 
+  if_link_params_free (ifp);
+
   XFREE (MTYPE_IF, ifp);
 }
 
@@ -1364,3 +1366,45 @@ if_link_type_str (enum zebra_link_type llt)
     }
   return NULL;
 }
+
+struct if_link_params *
+if_link_params_get (struct interface *ifp)
+{
+  int i;
+
+  if (ifp->link_params != NULL)
+    return ifp->link_params;
+
+  struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS,
+                                      sizeof (struct if_link_params));
+  if (iflp == NULL) return NULL;
+
+  /* Set TE metric == standard metric */
+  iflp->te_metric = ifp->metric;
+
+  /* Compute default bandwidth based on interface */
+  int bw = (float)((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
+                   * TE_KILO_BIT / TE_BYTE);
+
+  /* Set Max, Reservable and Unreserved Bandwidth */
+  iflp->max_bw = bw;
+  iflp->max_rsv_bw = bw;
+  for (i = 0; i < MAX_CLASS_TYPE; i++)
+    iflp->unrsv_bw[i] = bw;
+
+  /* Update Link parameters status */
+  iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
+
+  /* Finally attach newly created Link Parameters */
+  ifp->link_params = iflp;
+
+  return iflp;
+}
+
+void
+if_link_params_free (struct interface *ifp)
+{
+  if (ifp->link_params == NULL) return;
+  XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
+  ifp->link_params = NULL;
+}
index 63e50f48bb17044a5108d77f6fb175dda7b2c3ae..17f8565595797d4a171a16c5bb7d4cbabeb559c3 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -131,6 +131,63 @@ struct if_stats
 };
 #endif /* HAVE_PROC_NET_DEV */
 
+/* Here are "non-official" architectural constants. */
+#define TE_EXT_MASK             0x0FFFFFFF
+#define TE_EXT_ANORMAL          0x80000000
+#define LOSS_PRECISION          0.000003
+#define TE_KILO_BIT             1000
+#define TE_BYTE                 8
+#define DEFAULT_BANDWIDTH       10000
+#define MAX_CLASS_TYPE          8
+#define MAX_PKT_LOSS            50.331642
+
+/* Link Parameters Status: 0: unset, 1: set, */
+#define LP_UNSET                0x0000
+#define LP_TE                   0x0001
+#define LP_MAX_BW               0x0002
+#define LP_MAX_RSV_BW           0x0004
+#define LP_UNRSV_BW             0x0008
+#define LP_ADM_GRP              0x0010
+#define LP_RMT_AS               0x0020
+#define LP_DELAY                0x0040
+#define LP_MM_DELAY             0x0080
+#define LP_DELAY_VAR            0x0100
+#define LP_PKT_LOSS             0x0200
+#define LP_RES_BW               0x0400
+#define LP_AVA_BW               0x0800
+#define LP_USE_BW               0x1000
+
+#define IS_PARAM_UNSET(lp, st) !(lp->lp_status & st)
+#define IS_PARAM_SET(lp, st) (lp->lp_status & st)
+#define IS_LINK_PARAMS_SET(lp) (lp->lp_status != LP_UNSET)
+
+#define SET_PARAM(lp, st) (lp->lp_status) |= (st)
+#define UNSET_PARAM(lp, st) (lp->lp_status) &= ~(st)
+#define RESET_LINK_PARAM(lp) (lp->lp_status = LP_UNSET)
+
+/* Link Parameters for Traffic Engineering */
+struct if_link_params {
+  u_int32_t lp_status;   /* Status of Link Parameters: */
+  u_int32_t te_metric;   /* Traffic Engineering metric */
+  float max_bw;          /* Maximum Bandwidth */
+  float max_rsv_bw;      /* Maximum Reservable Bandwidth */
+  float unrsv_bw[MAX_CLASS_TYPE];     /* Unreserved Bandwidth per Class Type (8) */
+  u_int32_t admin_grp;   /* Administrative group */
+  u_int32_t rmt_as;      /* Remote AS number */
+  struct in_addr rmt_ip; /* Remote IP address */
+  u_int32_t av_delay;    /* Link Average Delay */
+  u_int32_t min_delay;   /* Link Min Delay */
+  u_int32_t max_delay;   /* Link Max Delay */
+  u_int32_t delay_var;   /* Link Delay Variation */
+  float pkt_loss;        /* Link Packet Loss */
+  float res_bw;          /* Residual Bandwidth */
+  float ava_bw;          /* Available Bandwidth */
+  float use_bw;          /* Utilized Bandwidth */
+};
+
+#define INTERFACE_LINK_PARAMS_SIZE   sizeof(struct if_link_params)
+#define HAS_LINK_PARAMS(ifp)  ((ifp)->link_params != NULL)
+
 /* Interface structure */
 struct interface 
 {
@@ -174,6 +231,9 @@ struct interface
   /* interface bandwidth, kbits */
   unsigned int bandwidth;
   
+  /* Link parameters for Traffic Engineering */
+  struct if_link_params *link_params;
+
   /* description of the interface. */
   char *desc;                  
 
@@ -418,6 +478,10 @@ extern ifindex_t if_nametoindex (const char *);
 extern char *if_indextoname (ifindex_t, char *);
 #endif
 
+/* link parameters */
+struct if_link_params *if_link_params_get (struct interface *);
+void if_link_params_free (struct interface *);
+
 /* Exported variables. */
 extern struct cmd_element interface_desc_cmd;
 extern struct cmd_element no_interface_desc_cmd;
index d0faecb640ffc07aebd60120793055d32ed0e3ca..56d4faead5ae34dec1712dde7e3ca3f23b527b04 100644 (file)
@@ -77,6 +77,7 @@ struct memory_list memory_list_lib[] =
   { MTYPE_VRF,                 "VRF"                           },
   { MTYPE_VRF_NAME,            "VRF name"                      },
   { MTYPE_VRF_BITMAP,          "VRF bit-map"                   },
+  { MTYPE_IF_LINK_PARAMS,      "Informational Link Parameters" },
   { -1, NULL },
 };
 
@@ -228,6 +229,8 @@ struct memory_list memory_list_ospf[] =
   { MTYPE_OSPF_IF_INFO,       "OSPF if info"                   },
   { MTYPE_OSPF_IF_PARAMS,     "OSPF if params"                 },
   { MTYPE_OSPF_MESSAGE,                "OSPF message"                  },
+  { MTYPE_OSPF_MPLS_TE,       "OSPF MPLS parameters"            },
+  { MTYPE_OSPF_PCE_PARAMS,    "OSPF PCE parameters"             },
   { -1, NULL },
 };
 
@@ -269,6 +272,7 @@ struct memory_list memory_list_isis[] =
   { MTYPE_ISIS_NEXTHOP6,      "ISIS nexthop6"                  },
   { MTYPE_ISIS_DICT,          "ISIS dictionary"                        },
   { MTYPE_ISIS_DICT_NODE,     "ISIS dictionary node"           },
+  { MTYPE_ISIS_MPLS_TE,       "ISIS MPLS_TE parameters"         },
   { -1, NULL },
 };
 
index 3373983b3cb83b5f6f8278bdd91f4ce6bee02727..5379ecb5a68d5102f745588d51ac2512969893bb 100644 (file)
@@ -93,3 +93,21 @@ set_nonblocking(int fd)
     }
   return 0;
 }
+
+float
+htonf (float host)
+{
+  u_int32_t lu1, lu2;
+  float convert;
+
+  memcpy (&lu1, &host, sizeof (u_int32_t));
+  lu2 = htonl (lu1);
+  memcpy (&convert, &lu2, sizeof (u_int32_t));
+  return convert;
+}
+
+float
+ntohf (float net)
+{
+  return htonf (net);
+}
index 4d9c2284bf74a6920a674b030246d994cc56e3f1..0fcb575d1cea7af6d2ef8d21dfa4f33e8d87bb01 100644 (file)
@@ -37,4 +37,7 @@ extern int set_nonblocking(int fd);
 #define ERRNO_IO_RETRY(EN) \
        (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
 
+extern float htonf (float);
+extern float ntohf (float);
+
 #endif /* _ZEBRA_NETWORK_H */
index fe77e2a2adadf7d492a456fce1e8e0349320fc6b..809e749fb90af3b59802f7c4307b07ff7df7caf9 100644 (file)
@@ -543,6 +543,28 @@ stream_get_ipv4 (struct stream *s)
   return l;
 }
 
+float
+stream_getf (struct stream *s)
+{
+  union {
+    float r;
+    uint32_t d;
+  } u;
+  u.d = stream_getl (s);
+  return u.r;
+}
+
+double
+stream_getd (struct stream *s)
+{
+  union {
+    double r;
+    uint64_t d;
+  } u;
+  u.d = stream_getq (s);
+  return u.r;
+}
+
 /* Copy to source to stream.
  *
  * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
@@ -670,6 +692,28 @@ stream_putq (struct stream *s, uint64_t q)
   return 8;
 }
 
+int
+stream_putf (struct stream *s, float f)
+{
+  union {
+    float i;
+    uint32_t o;
+  } u;
+  u.i = f;
+  return stream_putl (s, u.o);
+}
+
+int
+stream_putd (struct stream *s, double d)
+{
+  union {
+    double i;
+    uint64_t o;
+  } u;
+  u.i = d;
+  return stream_putq (s, u.o);
+}
+
 int
 stream_putc_at (struct stream *s, size_t putp, u_char c)
 {
index 4e9b21df5f1cbe54662b4e8883e2e86e92405d4e..1e2bc89b32d63a26f74217d0dce4d325265e5928 100644 (file)
@@ -196,6 +196,12 @@ extern uint64_t stream_getq (struct stream *);
 extern uint64_t stream_getq_from (struct stream *, size_t);
 extern u_int32_t stream_get_ipv4 (struct stream *);
 
+/* IEEE-754 floats */
+extern float stream_getf (struct stream *);
+extern double stream_getd (struct stream *);
+extern int stream_putf (struct stream *, float);
+extern int stream_putd (struct stream *, double);
+
 #undef stream_read
 #undef stream_write
 
index a49403d31423d43b0e6f7d9aee449d6534dcbaa7..753954fd848dba26830cf5bf5bf975b98082c122 100644 (file)
@@ -960,8 +960,6 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid)
  * ZEBRA_INTERFACE_DELETE from zebra to the client is:
  *     0                   1                   2                   3
  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+
- * |   type        |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |  ifname                                                       |
  * |                                                               |
@@ -969,20 +967,32 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid)
  * |                                                               |
  * |                                                               |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         ifindex                                               |
+ * |  ifindex                                                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  status       |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         if_flags                                              |
+ * |  if_flags                                                     |
  * |                                                               |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         metric                                                |
+ * |  metric                                                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  ifmtu                                                        |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  ifmtu6                                                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  bandwidth                                                    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  Link Layer Type                                              |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         ifmtu                                                 |
+ * |  Harware Address Length                                       |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         ifmtu6                                                |
+ * |  Hardware Address      if HW lenght different from 0          |
+ * |   ...                  max INTERFACE_HWADDR_MAX               |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         bandwidth                                             |
+ * |  Link_params? |  Whether a link-params follows: 1 or 0.
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         sockaddr_dl                                           |
+ * |  Link_params    0 or 1 INTERFACE_LINK_PARAMS_SIZE sized       |
+ * |   ....          (struct if_link_params).                      |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
@@ -1071,7 +1081,138 @@ zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id)
   return ifp;
 }
 
-/* 
+static void
+link_params_set_value(struct stream *s, struct if_link_params *iflp)
+{
+
+  if (iflp == NULL)
+    return;
+
+  iflp->lp_status = stream_getl (s);
+  iflp->te_metric = stream_getl (s);
+  iflp->max_bw = stream_getf (s);
+  iflp->max_rsv_bw = stream_getf (s);
+  uint32_t bwclassnum = stream_getl (s);
+  {
+    unsigned int i;
+    for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
+      iflp->unrsv_bw[i] = stream_getf (s);
+    if (i < bwclassnum)
+      zlog_err ("%s: received %d > %d (MAX_CLASS_TYPE) bw entries"
+                " - outdated library?",
+                __func__, bwclassnum, MAX_CLASS_TYPE);
+  }
+  iflp->admin_grp = stream_getl (s);
+  iflp->rmt_as = stream_getl (s);
+  iflp->rmt_ip.s_addr = stream_get_ipv4 (s);
+
+  iflp->av_delay = stream_getl (s);
+  iflp->min_delay = stream_getl (s);
+  iflp->max_delay = stream_getl (s);
+  iflp->delay_var = stream_getl (s);
+
+  iflp->pkt_loss = stream_getf (s);
+  iflp->res_bw = stream_getf (s);
+  iflp->ava_bw = stream_getf (s);
+  iflp->use_bw = stream_getf (s);
+}
+
+struct interface *
+zebra_interface_link_params_read (struct stream *s)
+{
+  struct if_link_params *iflp;
+  uint32_t ifindex = stream_getl (s);
+
+  struct interface *ifp = if_lookup_by_index (ifindex);
+
+  if (ifp == NULL || s == NULL)
+    {
+      zlog_err ("%s: unknown ifindex %u, shouldn't happen",
+                __func__, ifindex);
+      return NULL;
+    }
+
+  if ((iflp = if_link_params_get (ifp)) == NULL)
+    return NULL;
+
+  link_params_set_value(s, iflp);
+
+  return ifp;
+}
+
+void
+zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
+{
+  u_char link_params_status = 0;
+
+  /* Read interface's index. */
+  ifp->ifindex = stream_getl (s);
+  ifp->status = stream_getc (s);
+
+  /* Read interface's value. */
+  ifp->flags = stream_getq (s);
+  ifp->ptm_enable = stream_getc (s);
+  ifp->ptm_status = stream_getc (s);
+  ifp->metric = stream_getl (s);
+  ifp->mtu = stream_getl (s);
+  ifp->mtu6 = stream_getl (s);
+  ifp->bandwidth = stream_getl (s);
+  ifp->ll_type = stream_getl (s);
+  ifp->hw_addr_len = stream_getl (s);
+  if (ifp->hw_addr_len)
+    stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
+
+  /* Read Traffic Engineering status */
+  link_params_status = stream_getc (s);
+  /* Then, Traffic Engineering parameters if any */
+  if (link_params_status)
+    {
+      struct if_link_params *iflp = if_link_params_get (ifp);
+      link_params_set_value(s, iflp);
+    }
+}
+
+size_t
+zebra_interface_link_params_write (struct stream *s, struct interface *ifp)
+{
+  size_t w;
+  struct if_link_params *iflp;
+  int i;
+
+  if (s == NULL || ifp == NULL || ifp->link_params == NULL)
+    return 0;
+
+  iflp = ifp->link_params;
+  w = 0;
+
+  w += stream_putl (s, iflp->lp_status);
+
+  w += stream_putl (s, iflp->te_metric);
+  w += stream_putf (s, iflp->max_bw);
+  w += stream_putf (s, iflp->max_rsv_bw);
+
+  w += stream_putl (s, MAX_CLASS_TYPE);
+  for (i = 0; i < MAX_CLASS_TYPE; i++)
+    w += stream_putf (s, iflp->unrsv_bw[i]);
+
+  w += stream_putl (s, iflp->admin_grp);
+  w += stream_putl (s, iflp->rmt_as);
+  w += stream_put_in_addr (s, &iflp->rmt_ip);
+
+  w += stream_putl (s, iflp->av_delay);
+  w += stream_putl (s, iflp->min_delay);
+  w += stream_putl (s, iflp->max_delay);
+  w += stream_putl (s, iflp->delay_var);
+
+  w += stream_putf (s, iflp->pkt_loss);
+  w += stream_putf (s, iflp->res_bw);
+  w += stream_putf (s, iflp->ava_bw);
+  w += stream_putf (s, iflp->use_bw);
+
+  return w;
+}
+
+/*
  * format of message for address additon is:
  *    0
  *  0 1 2 3 4 5 6 7
@@ -1100,30 +1241,8 @@ zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id)
  * :               :
  * |               |
  * +-+-+-+-+-+-+-+-+
- *
  */
 
-void
-zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
-{
-  /* Read interface's index. */
-  ifp->ifindex = stream_getl (s);
-  ifp->status = stream_getc (s);
-
-  /* Read interface's value. */
-  ifp->flags = stream_getq (s);
-  ifp->ptm_enable = stream_getc (s);
-  ifp->ptm_status = stream_getc (s);
-  ifp->metric = stream_getl (s);
-  ifp->mtu = stream_getl (s);
-  ifp->mtu6 = stream_getl (s);
-  ifp->bandwidth = stream_getl (s);
-  ifp->ll_type = stream_getl (s);
-  ifp->hw_addr_len = stream_getl (s);
-  if (ifp->hw_addr_len)
-    stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
-}
-
 static int
 memconstant(const void *s, int c, size_t n)
 {
@@ -1509,6 +1628,9 @@ zclient_read (struct thread *thread)
     case ZEBRA_REDISTRIBUTE_IPV6_DEL:
       if (zclient->redistribute_route_ipv6_del)
        (*zclient->redistribute_route_ipv6_del) (command, zclient, length, vrf_id);
+    case ZEBRA_INTERFACE_LINK_PARAMS:
+      if (zclient->interface_link_params)
+        (*zclient->interface_link_params) (command, zclient, length);
       break;
     default:
       break;
index c42d8c9aa3e7e12045b3cc88bb895824fd699b05..b95d18ec1abf59a29dcafe5a8962967e109d8ed7 100644 (file)
@@ -93,6 +93,7 @@ struct zclient
   int (*interface_down) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_address_add) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_address_delete) (int, struct zclient *, uint16_t, vrf_id_t);
+  int (*interface_link_params) (int, struct zclient *, uint16_t);
   int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_nbr_address_add) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t, vrf_id_t);
@@ -214,6 +215,9 @@ extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid);
 extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, 
                             struct zapi_ipv4 *);
 
+extern struct interface *zebra_interface_link_params_read (struct stream *);
+extern size_t zebra_interface_link_params_write (struct stream *,
+                                                 struct interface *);
 #ifdef HAVE_IPV6
 /* IPv6 prefix add and delete function prototype. */
 
index 546f0dd3d75a00e208169cd5537d694bb01c7f21..94158013ec32174ad4976c2c52212ccd2a3825ff 100644 (file)
@@ -445,7 +445,8 @@ struct in_pktinfo
 #define ZEBRA_INTERFACE_ENABLE_RADV       47
 #define ZEBRA_INTERFACE_DISABLE_RADV      48
 #define ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB    49
-#define ZEBRA_MESSAGE_MAX                 50
+#define ZEBRA_INTERFACE_LINK_PARAMS       50
+#define ZEBRA_MESSAGE_MAX                 51
 
 /* Marker value used in new Zserv, in the byte location corresponding
  * the command value in the old zserv header. To allow old and new
index ed279f38ff4b720102b84e87de7ec0219c3c1b73..a53c72685387d520c229e52a99aeb13e23caf79c 100644 (file)
@@ -133,6 +133,7 @@ unsigned long conf_debug_ospf_nsm = 0;
 unsigned long conf_debug_ospf_lsa = 0;
 unsigned long conf_debug_ospf_zebra = 0;
 unsigned long conf_debug_ospf_nssa = 0;
+unsigned long conf_debug_ospf_te = 0;
 
 /* Enable debug option variables -- valid only session. */
 unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
@@ -142,7 +143,7 @@ unsigned long term_debug_ospf_nsm = 0;
 unsigned long term_debug_ospf_lsa = 0;
 unsigned long term_debug_ospf_zebra = 0;
 unsigned long term_debug_ospf_nssa = 0;
-
+unsigned long term_debug_ospf_te = 0;
 
 
 const char *
@@ -328,13 +329,14 @@ ospf_options_dump (u_char options)
 {
   static char buf[OSPF_OPTION_STR_MAXLEN];
 
-  snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|*",
+  snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|%s",
            (options & OSPF_OPTION_O) ? "O" : "-",
            (options & OSPF_OPTION_DC) ? "DC" : "-",
            (options & OSPF_OPTION_EA) ? "EA" : "-",
            (options & OSPF_OPTION_NP) ? "N/P" : "-",
            (options & OSPF_OPTION_MC) ? "MC" : "-",
-           (options & OSPF_OPTION_E) ? "E" : "-");
+           (options & OSPF_OPTION_E) ? "E" : "-",
+           (options & OSPF_OPTION_MT) ? "M/T" : "-");
 
   return buf;
 }
@@ -1920,6 +1922,33 @@ DEFUN (no_debug_ospf_instance_nssa,
   return CMD_SUCCESS;
 }
 
+DEFUN (debug_ospf_te,
+       debug_ospf_te_cmd,
+       "debug ospf te",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF-TE information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_ON (te, TE);
+  TERM_DEBUG_ON (te, TE);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf_te,
+       no_debug_ospf_te_cmd,
+       "no debug ospf te",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF-TE information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_OFF (te, TE);
+  TERM_DEBUG_OFF (te, TE);
+  return CMD_SUCCESS;
+}
+
 DEFUN (no_debug_ospf,
        no_debug_ospf_cmd,
        "no debug ospf",
@@ -2270,6 +2299,7 @@ debug_init ()
   install_element (ENABLE_NODE, &debug_ospf_zebra_cmd);
   install_element (ENABLE_NODE, &debug_ospf_event_cmd);
   install_element (ENABLE_NODE, &debug_ospf_nssa_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_te_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_detail_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf_packet_all_cmd);
@@ -2283,6 +2313,7 @@ debug_init ()
   install_element (ENABLE_NODE, &no_debug_ospf_zebra_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf_event_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf_nssa_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_te_cmd);
 
   install_element (ENABLE_NODE, &show_debugging_ospf_instance_cmd);
   install_element (ENABLE_NODE, &debug_ospf_instance_packet_send_recv_detail_cmd);
@@ -2326,6 +2357,7 @@ debug_init ()
   install_element (CONFIG_NODE, &debug_ospf_zebra_cmd);
   install_element (CONFIG_NODE, &debug_ospf_event_cmd);
   install_element (CONFIG_NODE, &debug_ospf_nssa_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_te_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_detail_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf_packet_all_cmd);
@@ -2339,6 +2371,7 @@ debug_init ()
   install_element (CONFIG_NODE, &no_debug_ospf_zebra_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf_event_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf_nssa_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_te_cmd);
 
   install_element (CONFIG_NODE, &debug_ospf_instance_packet_send_recv_detail_cmd);
   install_element (CONFIG_NODE, &debug_ospf_instance_packet_send_recv_cmd);
index a2d5e8ba196150cf8bcd55711d6e5d1a983c88ea..f843df03ae7398698beca040716c21d36f917fd9 100644 (file)
@@ -57,6 +57,7 @@
 
 #define OSPF_DEBUG_EVENT        0x01
 #define OSPF_DEBUG_NSSA                0x02
+#define OSPF_DEBUG_TE          0x04
 
 /* Macro for setting debug option. */
 #define CONF_DEBUG_PACKET_ON(a, b)         conf_debug_ospf_packet[a] |= (b)
@@ -98,6 +99,8 @@
 
 #define IS_DEBUG_OSPF_NSSA  IS_DEBUG_OSPF(nssa,NSSA)
 
+#define IS_DEBUG_OSPF_TE  IS_DEBUG_OSPF(te,TE)
+
 #define IS_CONF_DEBUG_OSPF_PACKET(a, b) \
        (conf_debug_ospf_packet[a] & OSPF_DEBUG_ ## b)
 #define IS_CONF_DEBUG_OSPF(a, b) \
@@ -119,6 +122,7 @@ extern unsigned long term_debug_ospf_nsm;
 extern unsigned long term_debug_ospf_lsa;
 extern unsigned long term_debug_ospf_zebra;
 extern unsigned long term_debug_ospf_nssa;
+extern unsigned long term_debug_ospf_te;
 
 /* Message Strings. */
 extern char *ospf_lsa_type_str[];
index ee2608b05b3ff7d177cb7369b1289b1a5e12ba6e..8c6ec892c498303dac3d11bd4356abfbca889c1f 100644 (file)
@@ -213,6 +213,9 @@ ospf_opaque_type_name (u_char opaque_type)
     case OPAQUE_TYPE_GRACE_LSA:
       name = "Grace-LSA";
       break;
+    case OPAQUE_TYPE_INTER_AS_LSA:
+      name = "Inter-AS TE-v2 LSA";
+      break;
     default:
       if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
         name = "Unassigned";
@@ -1979,6 +1982,7 @@ ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
   struct opaque_info_per_type *oipt;
   struct opaque_info_per_id *oipi;
   struct ospf_lsa *lsa;
+  struct ospf *top;
   int delay;
 
   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
@@ -2010,7 +2014,10 @@ ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
       break;
     case OSPF_OPAQUE_AS_LSA:
-      ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
+      top = ospf_lookup ();
+      if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
+        top = lsa0->area->ospf;
+      ospf_ls_retransmit_delete_nbr_as (top, lsa);
       break;
     default:
       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
@@ -2055,6 +2062,9 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
   struct opaque_info_per_type *oipt;
   struct opaque_info_per_id *oipi;
   struct ospf_lsa *lsa;
+  struct ospf *top;
+
+  top = ospf_lookup ();
 
   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
   ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
@@ -2078,7 +2088,9 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
       break;
     case OSPF_OPAQUE_AS_LSA:
-      ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
+      if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
+        top = lsa0->area->ospf;
+      ospf_ls_retransmit_delete_nbr_as (top, lsa);
       break;
     default:
       zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
@@ -2102,7 +2114,7 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
     zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
   /* This lsa will be flushed and removed eventually. */
-  ospf_lsa_flush (lsa0->area->ospf, lsa);
+  ospf_lsa_flush (top, lsa);
 
 out:
   return;
@@ -2144,28 +2156,6 @@ ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr,
  * Followings are util functions; probably be used by Opaque-LSAs only...
  *------------------------------------------------------------------------*/
 
-void
-htonf (float *src, float *dst)
-{
-  u_int32_t lu1, lu2;
-
-  memcpy (&lu1, src, sizeof (u_int32_t));
-  lu2 = htonl (lu1);
-  memcpy (dst, &lu2, sizeof (u_int32_t));
-  return;
-}
-
-void
-ntohf (float *src, float *dst)
-{
-  u_int32_t lu1, lu2;
-
-  memcpy (&lu1, src, sizeof (u_int32_t));
-  lu2 = ntohl (lu1);
-  memcpy (dst, &lu2, sizeof (u_int32_t));
-  return;
-}
-
 struct ospf *
 oi_to_top (struct ospf_interface *oi)
 {
index b9490a0ff2aea764e38047d6823332f9ce4199f7..2ac9b41efc8dec53b616a1553f24f29b2ee911e3 100644 (file)
 #define OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA            1
 #define OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC     2
 #define OPAQUE_TYPE_GRACE_LSA                          3
+#define OPAQUE_TYPE_L1VPN_LSA                          5
+#define OPAQUE_TYPE_ROUTER_INFORMATION_LSA             4
+#define OPAQUE_TYPE_INTER_AS_LSA                       6
+#define OPAQUE_TYPE_MAX                                6
 
 /* Followings types are proposed in internet-draft documents. */
 #define OPAQUE_TYPE_8021_QOSPF                         129
@@ -70,7 +74,7 @@
 #define OPAQUE_TYPE_WILDCARD                           0
 
 #define OPAQUE_TYPE_RANGE_UNASSIGNED(type) \
-       (  4 <= (type) && (type) <= 127)
+       ( OPAQUE_TYPE_MAX  <= (type) && (type) <= 127)
 
 #define OPAQUE_TYPE_RANGE_RESERVED(type) \
        (127 <  (type) && (type) <= 255)
@@ -137,8 +141,6 @@ extern void ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa);
 extern void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor
                                                      *nbr,
                                                      struct ospf_lsa *lsa);
-extern void htonf (float *src, float *dst);
-extern void ntohf (float *src, float *dst);
 extern struct ospf *oi_to_top (struct ospf_interface *oi);
 
 #endif /* _ZEBRA_OSPF_OPAQUE_H */
index e6014a14c6d4bd1936888d6756c2e1ab662344c4..399a558a0d10a8e2102574911a67abfc9e19cd24 100644 (file)
@@ -913,7 +913,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   /* Compare options. */
 #define REJECT_IF_TBIT_ON      1 /* XXX */
 #ifdef REJECT_IF_TBIT_ON
-  if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
+  if (CHECK_FLAG (hello->options, OSPF_OPTION_MT))
     {
       /*
        * This router does not support non-zero TOS.
@@ -1265,7 +1265,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
     }
 
 #ifdef REJECT_IF_TBIT_ON
-  if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
+  if (CHECK_FLAG (dd->options, OSPF_OPTION_MT))
     {
       /*
        * In Hello protocol, optional capability must have checked
index 6dba2d3beea1eb22feeed72a9bc8af5648b21717..b55105ac8f5cdbcaa2501031431f9a86c960fb02 100644 (file)
@@ -1,8 +1,11 @@
 /*
- * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
+ * This is an implementation of RFC3630
  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
  * http://www.kddlabs.co.jp/
  *
+ * Copyright (C) 2012 Orange Labs
+ * http://www.orange.com
+ *
  * This file is part of GNU Zebra.
  *
  * GNU Zebra is free software; you can redistribute it and/or modify it
  * 02111-1307, USA.
  */
 
-/***** MTYPE definition is not reflected to "memory.h" yet. *****/
-#define MTYPE_OSPF_MPLS_TE_LINKPARAMS  MTYPE_TMP
+/* Add support of RFC7471 */
+/* Add support of RFC5392, RFC6827 */
 
 #include <zebra.h>
+#include <math.h>
 
 #include "linklist.h"
 #include "prefix.h"
@@ -39,6 +43,7 @@
 #include "thread.h"
 #include "hash.h"
 #include "sockunion.h"         /* for inet_aton() */
+#include "network.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_interface.h"
 #include "ospfd/ospf_ase.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_te.h"
-
-/* Following structure are internal use only. */
-struct ospf_mpls_te
-{
-  enum { disabled, enabled } status;
-
-  /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
-  struct list *iflist;
-
-  /* Store Router-TLV in network byte order. */
-  struct te_tlv_router_addr router_addr;
-};
-
-struct mpls_te_link
-{
-  /*
-   * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
-   * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
-   * In this implementation, each Link-TLV has its own instance.
-   */
-  u_int32_t instance;
-
-  /* Reference pointer to a Zebra-interface. */
-  struct interface *ifp;
-
-  /* Area info in which this MPLS-TE link belongs to. */
-  struct ospf_area *area;
-
-  /* Flags to manage this link parameters. */
-  u_int32_t flags;
-#define LPFLG_LOOKUP_DONE              0x1
-#define LPFLG_LSA_ENGAGED              0x2
-#define LPFLG_LSA_FORCED_REFRESH       0x4
-
-  /* Store Link-TLV in network byte order. */
-  struct te_tlv_link link_header;
-  struct te_link_subtlv_link_type link_type;
-  struct te_link_subtlv_link_id link_id;
-  struct te_link_subtlv_lclif_ipaddr *lclif_ipaddr;
-  struct te_link_subtlv_rmtif_ipaddr *rmtif_ipaddr;
-  struct te_link_subtlv_te_metric te_metric;
-  struct te_link_subtlv_max_bw max_bw;
-  struct te_link_subtlv_max_rsv_bw max_rsv_bw;
-  struct te_link_subtlv_unrsv_bw unrsv_bw;
-  struct te_link_subtlv_rsc_clsclr rsc_clsclr;
-};
+#include "ospfd/ospf_vty.h"
 
 /*
  * Global variable to manage Opaque-LSA/MPLS-TE on this node.
  * Note that all parameter values are stored in network byte order.
  */
-static struct ospf_mpls_te OspfMplsTE;
+struct ospf_mpls_te OspfMplsTE;
 
-enum oifstate {
-  OI_ANY, OI_DOWN, OI_UP
-};
+const char *mode2text[] = { "Disable", "AS", "Area", "Emulate" };
 
-enum sched_opcode {
-  REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA
+enum oifstate
+{
+  OI_ANY, OI_DOWN, OI_UP
 };
 
 /*------------------------------------------------------------------------*
@@ -123,14 +82,14 @@ enum sched_opcode {
 
 static int ospf_mpls_te_new_if (struct interface *ifp);
 static int ospf_mpls_te_del_if (struct interface *ifp);
-static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);
+static void ospf_mpls_te_ism_change (struct ospf_interface *oi,
+                                     int old_status);
 static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
 static void ospf_mpls_te_config_write_router (struct vty *vty);
-static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
 static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
-static int ospf_mpls_te_lsa_originate (void *arg);
+static int ospf_mpls_te_lsa_originate_area (void *arg);
+static int ospf_mpls_te_lsa_originate_as (void *arg);
 static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
-static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
 
 static void del_mpls_te_link (void *val);
 static void ospf_mpls_te_register_vty (void);
@@ -148,21 +107,22 @@ ospf_mpls_te_init (void)
                ospf_mpls_te_ism_change,
                ospf_mpls_te_nsm_change,
                ospf_mpls_te_config_write_router,
-               ospf_mpls_te_config_write_if,
+               NULL,/*ospf_mpls_te_config_write_if */
                NULL,/* ospf_mpls_te_config_write_debug */
                 ospf_mpls_te_show_info,
-                ospf_mpls_te_lsa_originate,
+                ospf_mpls_te_lsa_originate_area,
                 ospf_mpls_te_lsa_refresh,
                NULL,/* ospf_mpls_te_new_lsa_hook */
                NULL /* ospf_mpls_te_del_lsa_hook */);
   if (rc != 0)
     {
-      zlog_warn ("ospf_mpls_te_init: Failed to register functions");
+      zlog_warn ("ospf_mpls_te_init: Failed to register Traffic Engineering functions");
       goto out;
     }
 
   memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te));
   OspfMplsTE.status = disabled;
+  OspfMplsTE.inter_as = Disable;
   OspfMplsTE.iflist = list_new ();
   OspfMplsTE.iflist->del = del_mpls_te_link;
 
@@ -172,16 +132,75 @@ out:
   return rc;
 }
 
+/* Additional register for RFC5392 support */
+static int
+ospf_mpls_te_register (enum inter_as_mode mode)
+{
+  int rc;
+  u_int8_t scope;
+
+  if (OspfMplsTE.inter_as != Disable)
+    return 0;
+
+  if (mode == AS)
+    scope = OSPF_OPAQUE_AS_LSA;
+  else
+    scope = OSPF_OPAQUE_AREA_LSA;
+
+  rc = ospf_register_opaque_functab (scope,
+                                     OPAQUE_TYPE_INTER_AS_LSA,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     ospf_mpls_te_show_info,
+                                     ospf_mpls_te_lsa_originate_as,
+                                     ospf_mpls_te_lsa_refresh, NULL, NULL);
+
+  if (rc != 0)
+    {
+      zlog_warn ("ospf_router_info_init: Failed to register Inter-AS functions");
+      return rc;
+    }
+
+  return 0;
+}
+
+static int
+ospf_mpls_te_unregister ()
+{
+  u_int8_t scope;
+
+  if (OspfMplsTE.inter_as == Disable)
+    return 0;
+
+  if (OspfMplsTE.inter_as == AS)
+    scope = OSPF_OPAQUE_AS_LSA;
+  else
+    scope = OSPF_OPAQUE_AREA_LSA;
+
+  ospf_delete_opaque_functab (scope, OPAQUE_TYPE_INTER_AS_LSA);
+
+  return 0;
+
+}
+
 void
 ospf_mpls_te_term (void)
 {
   list_delete (OspfMplsTE.iflist);
-
   OspfMplsTE.iflist = NULL;
-  OspfMplsTE.status = disabled;
 
   ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
                               OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
+  OspfMplsTE.status = disabled;
+
+  ospf_mpls_te_unregister ();
+  OspfMplsTE.inter_as = Disable;
+
   return;
 }
 
@@ -192,11 +211,11 @@ ospf_mpls_te_term (void)
 static void
 del_mpls_te_link (void *val)
 {
-  XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val);
+  XFREE (MTYPE_OSPF_MPLS_TE, val);
   return;
 }
 
-static u_int32_t
+u_int32_t
 get_mpls_te_instance_value (void)
 {
   static u_int32_t seqno = 0;
@@ -274,9 +293,9 @@ lookup_linkparams_by_instance (struct ospf_lsa *lsa)
 }
 
 static void
-ospf_mpls_te_foreach_area (
-  void (*func)(struct mpls_te_link *lp, enum sched_opcode),
-  enum sched_opcode sched_opcode)
+ospf_mpls_te_foreach_area (void (*func)
+                           (struct mpls_te_link * lp, opcode_t sched_opcode),
+                           opcode_t sched_opcode)
 {
   struct listnode *node, *nnode; 
   struct listnode *node2;
@@ -285,10 +304,12 @@ ospf_mpls_te_foreach_area (
 
   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
     {
-      if ((area = lp->area) == NULL)
+      /* Skip Inter-AS TEv2 Links */
+      if (IS_INTER_AS (lp->type))
         continue;
-      if (lp->flags & LPFLG_LOOKUP_DONE)
+      if ((area = lp->area) == NULL)
         continue;
+      if CHECK_FLAG (lp->flags, LPFLG_LOOKUP_DONE) continue;
 
       if (func != NULL)
         (* func)(lp, sched_opcode);
@@ -297,12 +318,12 @@ ospf_mpls_te_foreach_area (
         if ((lp = listgetdata (node2)) != NULL)
           if (lp->area != NULL)
             if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
-              lp->flags |= LPFLG_LOOKUP_DONE;
+              SET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
     }
 
   for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
     if (lp->area != NULL)
-      lp->flags &= ~LPFLG_LOOKUP_DONE;
+      UNSET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
 
   return;
 }
@@ -311,7 +332,7 @@ static void
 set_mpls_te_router_addr (struct in_addr ipv4)
 {
   OspfMplsTE.router_addr.header.type   = htons (TE_TLV_ROUTER_ADDR);
-  OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4));
+  OspfMplsTE.router_addr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
   OspfMplsTE.router_addr.value = ipv4;
   return;
 }
@@ -319,7 +340,6 @@ set_mpls_te_router_addr (struct in_addr ipv4)
 static void
 set_linkparams_link_header (struct mpls_te_link *lp)
 {
-  struct te_tlv_header *tlvh;
   u_int16_t length = 0;
 
   /* TE_LINK_SUBTLV_LINK_TYPE */
@@ -331,14 +351,12 @@ set_linkparams_link_header (struct mpls_te_link *lp)
     length += TLV_SIZE (&lp->link_id.header);
 
   /* TE_LINK_SUBTLV_LCLIF_IPADDR */
-  if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL
-  &&  ntohs (tlvh->type) != 0)
-    length += TLV_SIZE (tlvh);
+  if (lp->lclif_ipaddr.header.type != 0)
+    length += TLV_SIZE (&lp->lclif_ipaddr.header);
 
   /* TE_LINK_SUBTLV_RMTIF_IPADDR */
-  if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL
-  &&  ntohs (tlvh->type) != 0)
-    length += TLV_SIZE (tlvh);
+  if (lp->rmtif_ipaddr.header.type != 0)
+    length += TLV_SIZE (&lp->rmtif_ipaddr.header);
 
   /* TE_LINK_SUBTLV_TE_METRIC */
   if (ntohs (lp->te_metric.header.type) != 0)
@@ -360,6 +378,50 @@ set_linkparams_link_header (struct mpls_te_link *lp)
   if (ntohs (lp->rsc_clsclr.header.type) != 0)
     length += TLV_SIZE (&lp->rsc_clsclr.header);
 
+  /* TE_LINK_SUBTLV_LLRI */
+  if (ntohs (lp->llri.header.type) != 0)
+    length += TLV_SIZE (&lp->llri.header);
+
+  /* TE_LINK_SUBTLV_RIP */
+  if (ntohs (lp->rip.header.type) != 0)
+    length += TLV_SIZE (&lp->rip.header);
+
+  /* TE_LINK_SUBTLV_RAS */
+  if (ntohs (lp->ras.header.type) != 0)
+    length += TLV_SIZE (&lp->ras.header);
+
+  /* TE_LINK_SUBTLV_LRRID */
+  if (ntohs (lp->lrrid.header.type) != 0)
+    length += TLV_SIZE (&lp->lrrid.header);
+
+  /* TE_LINK_SUBTLV_AV_DELAY */
+  if (ntohs (lp->av_delay.header.type) != 0)
+    length += TLV_SIZE (&lp->av_delay.header);
+
+  /* TE_LINK_SUBTLV_MM_DELAY */
+  if (ntohs (lp->mm_delay.header.type) != 0)
+    length += TLV_SIZE (&lp->mm_delay.header);
+
+  /* TE_LINK_SUBTLV_DELAY_VAR */
+  if (ntohs (lp->delay_var.header.type) != 0)
+    length += TLV_SIZE (&lp->delay_var.header);
+
+  /* TE_LINK_SUBTLV_PKT_LOSS */
+  if (ntohs (lp->pkt_loss.header.type) != 0)
+    length += TLV_SIZE (&lp->pkt_loss.header);
+
+  /* TE_LINK_SUBTLV_RES_BW */
+  if (ntohs (lp->res_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->res_bw.header);
+
+  /* TE_LINK_SUBTLV_AVA_BW */
+  if (ntohs (lp->ava_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->ava_bw.header);
+
+  /* TE_LINK_SUBTLV_USE_BW */
+  if (ntohs (lp->use_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->use_bw.header);
+
   lp->link_header.header.type   = htons (TE_TLV_LINK);
   lp->link_header.header.length = htons (length);
 
@@ -370,7 +432,7 @@ static void
 set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
 {
   lp->link_type.header.type   = htons (TE_LINK_SUBTLV_LINK_TYPE);
-  lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value));
+  lp->link_type.header.length = htons (TE_LINK_SUBTLV_TYPE_SIZE);
 
   switch (oi->type)
     {
@@ -396,7 +458,7 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
   int done = 0;
 
   lp->link_id.header.type   = htons (TE_LINK_SUBTLV_LINK_ID);
-  lp->link_id.header.length = htons (sizeof (lp->link_id.value));
+  lp->link_id.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
 
   /*
    * The Link ID is identical to the contents of the Link ID field
@@ -406,8 +468,7 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
     {
     case OSPF_IFTYPE_POINTOPOINT:
       /* Take the router ID of the neighbor. */
-      if ((nbr = ospf_nbr_lookup_ptop (oi))
-         && nbr->state == NSM_Full)
+      if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full)
         {
           lp->link_id.value = nbr->router_id;
           done = 1;
@@ -442,40 +503,60 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
   return;
 }
 
+static void
+set_linkparams_lclif_ipaddr (struct mpls_te_link *lp, struct in_addr lclif)
+{
+
+  lp->lclif_ipaddr.header.type = htons (TE_LINK_SUBTLV_LCLIF_IPADDR);
+  lp->lclif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->lclif_ipaddr.value[0] = lclif;
+  return;
+}
+
+static void
+set_linkparams_rmtif_ipaddr (struct mpls_te_link *lp, struct in_addr rmtif)
+{
+
+  lp->rmtif_ipaddr.header.type = htons (TE_LINK_SUBTLV_RMTIF_IPADDR);
+  lp->rmtif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->rmtif_ipaddr.value[0] = rmtif;
+  return;
+}
+
 static void
 set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
 {
   lp->te_metric.header.type   = htons (TE_LINK_SUBTLV_TE_METRIC);
-  lp->te_metric.header.length = htons (sizeof (lp->te_metric.value));
+  lp->te_metric.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
   lp->te_metric.value = htonl (te_metric);
   return;
 }
 
 static void
-set_linkparams_max_bw (struct mpls_te_link *lp, float *fp)
+set_linkparams_max_bw (struct mpls_te_link *lp, float fp)
 {
   lp->max_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_BW);
-  lp->max_bw.header.length = htons (sizeof (lp->max_bw.value));
-  htonf (fp, &lp->max_bw.value);
+  lp->max_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->max_bw.value = htonf (fp);
   return;
 }
 
 static void
-set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp)
+set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float fp)
 {
   lp->max_rsv_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
-  lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value));
-  htonf (fp, &lp->max_rsv_bw.value);
+  lp->max_rsv_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->max_rsv_bw.value = htonf (fp);
   return;
 }
 
 static void
-set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
+set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float fp)
 {
   /* Note that TLV-length field is the size of array. */
   lp->unrsv_bw.header.type   = htons (TE_LINK_SUBTLV_UNRSV_BW);
-  lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value));
-  htonf (fp, &lp->unrsv_bw.value [priority]);
+  lp->unrsv_bw.header.length = htons (TE_LINK_SUBTLV_UNRSV_SIZE);
+  lp->unrsv_bw.value [priority] = htonf (fp);
   return;
 }
 
@@ -483,21 +564,283 @@ static void
 set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
 {
   lp->rsc_clsclr.header.type   = htons (TE_LINK_SUBTLV_RSC_CLSCLR);
-  lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value));
+  lp->rsc_clsclr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
   lp->rsc_clsclr.value = htonl (classcolor);
   return;
 }
 
+static void
+set_linkparams_inter_as (struct mpls_te_link *lp, struct in_addr addr,
+                         u_int32_t as)
+{
+
+  /* Set the Remote ASBR IP address and then the associated AS number */
+  lp->rip.header.type = htons (TE_LINK_SUBTLV_RIP);
+  lp->rip.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->rip.value = addr;
+
+  lp->ras.header.type = htons (TE_LINK_SUBTLV_RAS);
+  lp->ras.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->ras.value = htonl (as);
+}
+
+static void
+unset_linkparams_inter_as (struct mpls_te_link *lp)
+{
+
+  /* Reset the Remote ASBR IP address and then the associated AS number */
+  lp->rip.header.type = htons (0);
+  lp->rip.header.length = htons (0);
+  lp->rip.value.s_addr = htonl (0);
+
+  lp->ras.header.type = htons (0);
+  lp->ras.header.length = htons (0);
+  lp->ras.value = htonl (0);
+}
+
+void
+set_linkparams_llri (struct mpls_te_link *lp, u_int32_t local,
+                     u_int32_t remote)
+{
+
+  lp->llri.header.type = htons (TE_LINK_SUBTLV_LLRI);
+  lp->llri.header.length = htons (TE_LINK_SUBTLV_LLRI_SIZE);
+  lp->llri.local = htonl (local);
+  lp->llri.remote = htonl (remote);
+}
+
+void
+set_linkparams_lrrid (struct mpls_te_link *lp, struct in_addr local,
+                           struct in_addr remote)
+{
+
+  lp->lrrid.header.type = htons (TE_LINK_SUBTLV_LRRID);
+  lp->lrrid.header.length = htons (TE_LINK_SUBTLV_LRRID_SIZE);
+  lp->lrrid.local.s_addr = local.s_addr;
+  lp->lrrid.remote.s_addr = remote.s_addr;
+}
+
+static void
+set_linkparams_av_delay (struct mpls_te_link *lp, u_int32_t delay, u_char anormal)
+{
+  u_int32_t tmp;
+  /* Note that TLV-length field is the size of array. */
+  lp->av_delay.header.type = htons (TE_LINK_SUBTLV_AV_DELAY);
+  lp->av_delay.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  tmp = delay & TE_EXT_MASK;
+  if (anormal)
+    tmp |= TE_EXT_ANORMAL;
+  lp->av_delay.value = htonl (tmp);
+  return;
+}
+
+static void
+set_linkparams_mm_delay (struct mpls_te_link *lp, u_int32_t low, u_int32_t high, u_char anormal)
+{
+  u_int32_t tmp;
+  /* Note that TLV-length field is the size of array. */
+  lp->mm_delay.header.type = htons (TE_LINK_SUBTLV_MM_DELAY);
+  lp->mm_delay.header.length = htons (TE_LINK_SUBTLV_MM_DELAY_SIZE);
+  tmp = low & TE_EXT_MASK;
+  if (anormal)
+    tmp |= TE_EXT_ANORMAL;
+  lp->mm_delay.low = htonl (tmp);
+  lp->mm_delay.high = htonl (high);
+  return;
+}
+
+static void
+set_linkparams_delay_var (struct mpls_te_link *lp, u_int32_t jitter)
+{
+  /* Note that TLV-length field is the size of array. */
+  lp->delay_var.header.type = htons (TE_LINK_SUBTLV_DELAY_VAR);
+  lp->delay_var.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->delay_var.value = htonl (jitter & TE_EXT_MASK);
+  return;
+}
+
+static void
+set_linkparams_pkt_loss (struct mpls_te_link *lp, u_int32_t loss, u_char anormal)
+{
+  u_int32_t tmp;
+  /* Note that TLV-length field is the size of array. */
+  lp->pkt_loss.header.type = htons (TE_LINK_SUBTLV_PKT_LOSS);
+  lp->pkt_loss.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  tmp = loss & TE_EXT_MASK;
+  if (anormal)
+    tmp |= TE_EXT_ANORMAL;
+  lp->pkt_loss.value = htonl (tmp);
+  return;
+}
+
+static void
+set_linkparams_res_bw (struct mpls_te_link *lp, float fp)
+{
+  /* Note that TLV-length field is the size of array. */
+  lp->res_bw.header.type = htons (TE_LINK_SUBTLV_RES_BW);
+  lp->res_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->res_bw.value = htonf (fp);
+  return;
+}
+
+static void
+set_linkparams_ava_bw (struct mpls_te_link *lp, float fp)
+{
+  /* Note that TLV-length field is the size of array. */
+  lp->ava_bw.header.type = htons (TE_LINK_SUBTLV_AVA_BW);
+  lp->ava_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->ava_bw.value = htonf (fp);
+  return;
+}
+
+static void
+set_linkparams_use_bw (struct mpls_te_link *lp, float fp)
+{
+  /* Note that TLV-length field is the size of array. */
+  lp->use_bw.header.type = htons (TE_LINK_SUBTLV_USE_BW);
+  lp->use_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
+  lp->use_bw.value = htonf (fp);
+  return;
+}
+
+/* Update TE parameters from Interface */
+static void
+update_linkparams(struct mpls_te_link *lp)
+{
+  int i;
+  struct interface *ifp;
+
+  /* Get the Interface structure */
+  if ((ifp = lp->ifp) == NULL)
+    {
+      zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters");
+      return;
+    }
+  if (!HAS_LINK_PARAMS(ifp))
+    {
+      zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface");
+      return;
+    }
+
+  /* RFC3630 metrics */
+  if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
+    set_linkparams_rsc_clsclr (lp, ifp->link_params->admin_grp);
+  else
+    TLV_TYPE(lp->rsc_clsclr) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
+    set_linkparams_max_bw (lp, ifp->link_params->max_bw);
+  else
+    TLV_TYPE(lp->max_bw) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
+    set_linkparams_max_rsv_bw (lp, ifp->link_params->max_rsv_bw);
+  else
+    TLV_TYPE(lp->max_rsv_bw) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
+    for (i = 0; i < MAX_CLASS_TYPE; i++)
+      set_linkparams_unrsv_bw (lp, i, ifp->link_params->unrsv_bw[i]);
+  else
+    TLV_TYPE(lp->unrsv_bw) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_TE))
+    set_linkparams_te_metric(lp, ifp->link_params->te_metric);
+  else
+    TLV_TYPE(lp->te_metric) = 0;
+
+  /* TE metric Extensions */
+  if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
+    set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
+  else
+    TLV_TYPE(lp->av_delay) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
+    set_linkparams_mm_delay(lp, ifp->link_params->min_delay, ifp->link_params->max_delay, 0);
+  else
+    TLV_TYPE(lp->mm_delay) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
+    set_linkparams_delay_var(lp, ifp->link_params->delay_var);
+  else
+    TLV_TYPE(lp->delay_var) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
+    set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
+  else
+    TLV_TYPE(lp->pkt_loss) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
+    set_linkparams_res_bw(lp, ifp->link_params->res_bw);
+  else
+    TLV_TYPE(lp->res_bw) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
+    set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
+  else
+    TLV_TYPE(lp->ava_bw) = 0;
+
+  if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
+    set_linkparams_use_bw(lp, ifp->link_params->use_bw);
+  else
+    TLV_TYPE(lp->use_bw) = 0;
+
+  /* RFC5392 */
+  if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS))
+    {
+      /* Flush LSA if it engaged and was previously a STD_TE one */
+      if (IS_STD_TE(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
+        {
+          if (IS_DEBUG_OSPF_TE)
+            zlog_debug("OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
+              ifp->name, lp->flags, lp->type);
+
+          ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+          /* Then, switch it to INTER-AS */
+          if (OspfMplsTE.inter_as == AS)
+            lp->flags = INTER_AS | FLOOD_AS;
+          else
+            {
+              lp->flags = INTER_AS | FLOOD_AREA;
+              lp->area = ospf_area_lookup_by_area_id (ospf_lookup(), OspfMplsTE.interas_areaid);
+            }
+        }
+      set_linkparams_inter_as(lp, ifp->link_params->rmt_ip, ifp->link_params->rmt_as);
+    }
+  else
+    {
+      if (IS_DEBUG_OSPF_TE)
+        zlog_debug("OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
+          ifp->name, lp->flags, lp->type);
+
+      /* reset inter-as TE params */
+      /* Flush LSA if it engaged and was previously an INTER_AS one */
+      if (IS_INTER_AS(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
+        {
+          ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+          /* Then, switch it to Standard TE */
+          lp->flags = STD_TE | FLOOD_AREA;
+        }
+      unset_linkparams_inter_as (lp);
+    }
+}
+
 static void
 initialize_linkparams (struct mpls_te_link *lp)
 {
   struct interface *ifp = lp->ifp;
   struct ospf_interface *oi;
-  float fval;
-  int i;
+
+  if (IS_DEBUG_OSPF_TE)
+    zlog_debug("MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
+                ifp->name);
 
   if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
-    return;
+    {
+      zlog_warn("MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
+                 ifp->name);
+      return;
+    }
 
   /*
    * Try to set initial values those can be derived from
@@ -505,18 +848,19 @@ initialize_linkparams (struct mpls_te_link *lp)
    */
   set_linkparams_link_type (oi, lp);
 
-  /*
-   * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
-   * We may have to reconsider, if "ifp->bandwidth" type changes to float.
-   */
-  fval = (float)((ifp->bandwidth ? ifp->bandwidth
-                                 : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8);
+  /* Set local IP addr */
+  set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
 
-  set_linkparams_max_bw (lp, &fval);
-  set_linkparams_max_rsv_bw (lp, &fval);
+  /* Set Remote IP addr if Point to Point Interface */
+  if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP)
+    {
+      struct prefix *pref = CONNECTED_PREFIX(oi->connected);
+      if (pref != NULL)
+        set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
+    }
 
-  for (i = 0; i < 8; i++)
-    set_linkparams_unrsv_bw (lp, i, &fval);
+  /* Keep Area information in combination with link parameters. */
+  lp->area = oi->area;
 
   return;
 }
@@ -527,13 +871,22 @@ is_mandated_params_set (struct mpls_te_link *lp)
   int rc = 0;
 
   if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
+    {
+      zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Router Address");
     goto out;
+    }
 
   if (ntohs (lp->link_type.header.type) == 0)
+    {
+      zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link Type");
     goto out;
+    }
 
-  if (ntohs (lp->link_id.header.type) == 0)
+  if (!IS_INTER_AS (lp->type) && (ntohs (lp->link_id.header.type) == 0))
+    {
+      zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link ID");
     goto out;
+    }
 
   rc = 1;
 out:
@@ -550,6 +903,10 @@ ospf_mpls_te_new_if (struct interface *ifp)
   struct mpls_te_link *new;
   int rc = -1;
 
+  if (IS_DEBUG_OSPF_TE)
+    zlog_debug ("MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list",
+                 ifp->link_params ? "Active" : "Inactive", ifp->name);
+
   if (lookup_linkparams_by_ifp (ifp) != NULL)
     {
       zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp);
@@ -557,23 +914,33 @@ ospf_mpls_te_new_if (struct interface *ifp)
       goto out;
     }
 
-  new = XCALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
-                  sizeof (struct mpls_te_link));
+  new = XCALLOC (MTYPE_OSPF_MPLS_TE, sizeof (struct mpls_te_link));
   if (new == NULL)
     {
       zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
       goto out;
     }
 
-  new->area = NULL;
-  new->flags = 0;
   new->instance = get_mpls_te_instance_value ();
   new->ifp = ifp;
+  /* By default TE-Link is RFC3630 compatible flooding in Area and not active */
+  /* This default behavior will be adapted with call to ospf_mpls_te_update_if() */
+  new->type = STD_TE | FLOOD_AREA;
+  new->flags = LPFLG_LSA_INACTIVE;
+
+  /* Initialize Link Parameters from Interface */
+  initialize_linkparams(new);
 
-  initialize_linkparams (new);
+  /* Set TE Parameters from Interface */
+  update_linkparams(new);
 
+  /* Add Link Parameters structure to the list */
   listnode_add (OspfMplsTE.iflist, new);
 
+  if (IS_DEBUG_OSPF_TE)
+    zlog_debug("OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]",
+      ifp->name, new->flags, new->type);
+
   /* Schedule Opaque-LSA refresh. *//* XXX */
 
   rc = 0;
@@ -598,7 +965,7 @@ ospf_mpls_te_del_if (struct interface *ifp)
       if (listcount (iflist) == 0)
         iflist->head = iflist->tail = NULL;
 
-      XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp);
+      XFREE (MTYPE_OSPF_MPLS_TE, lp);
     }
 
   /* Schedule Opaque-LSA refresh. *//* XXX */
@@ -608,6 +975,56 @@ ospf_mpls_te_del_if (struct interface *ifp)
   return rc;
 }
 
+/* Main initialization / update function of the MPLS TE Link context */
+
+/* Call when interface TE Link parameters are modified */
+void
+ospf_mpls_te_update_if (struct interface *ifp)
+{
+  struct mpls_te_link *lp;
+
+  if (IS_DEBUG_OSPF_TE)
+    zlog_debug ("OSPF MPLS-TE: Update LSA parameters for interface %s [%s]",
+        ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
+
+  /* Get Link context from interface */
+  if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL)
+    {
+      zlog_warn ("OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s", ifp->name);
+      return;
+    }
+
+  /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
+  if (HAS_LINK_PARAMS(ifp))
+    {
+      SET_FLAG (lp->flags, LPFLG_LSA_ACTIVE);
+
+      /* Update TE parameters */
+      update_linkparams(lp);
+
+      /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is enabled */
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
+                ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+                ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
+          }
+    }
+  else
+    {
+      /* If MPLS TE is disable on this interface, flush LSA if it is already engaged */
+      if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
+          ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+      else
+        /* Reset Activity flag */
+        lp->flags = LPFLG_LSA_INACTIVE;
+    }
+
+  return;
+}
+
 static void
 ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
 {
@@ -620,10 +1037,10 @@ ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
       zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
       goto out;
     }
+
   if (oi->area == NULL || oi->area->ospf == NULL)
     {
-      zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
-IF_NAME (oi));
+      zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi));
       goto out;
     }
 #ifdef notyet
@@ -632,13 +1049,17 @@ IF_NAME (oi));
   || (lp->area != NULL && oi->area == NULL))
     {
       /* How should we consider this case? */
-      zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
+      zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs",
+         IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
       ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
     }
 #endif
-  /* Keep Area information in conbination with linkparams. */
+  /* Keep Area information in combination with linkparams. */
   lp->area = oi->area;
 
+  /* Keep interface MPLS-TE status */
+  lp->flags = HAS_LINK_PARAMS(oi->ifp);
+
   switch (oi->state)
     {
     case ISM_PointToPoint:
@@ -648,37 +1069,53 @@ IF_NAME (oi));
       old_type = lp->link_type;
       old_id   = lp->link_id;
 
+      /* Set Link type, Link ID, Local and Remote IP addr */
       set_linkparams_link_type (oi, lp);
       set_linkparams_link_id (oi, lp);
+      set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
+
+      if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP)
+        {
+          struct prefix *pref = CONNECTED_PREFIX(oi->connected);
+          if (pref != NULL)
+            set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
+        }
 
+      /* Update TE parameters */
+      update_linkparams(lp);
+
+      /* Try to Schedule LSA */
       if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type)
       ||   old_type.link_type.value     != lp->link_type.link_type.value)
       ||  (ntohs (old_id.header.type)   != ntohs (lp->link_id.header.type)
-      ||   ntohl (old_id.value.s_addr)  != ntohl (lp->link_id.value.s_addr)))
+              || ntohl (old_id.value.s_addr) !=
+              ntohl (lp->link_id.value.s_addr)))
         {
-          if (lp->flags & LPFLG_LSA_ENGAGED)
+          if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
           else
-            ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+            ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
+
         }
       break;
     default:
       lp->link_type.header.type = htons (0);
       lp->link_id.header.type   = htons (0);
 
-      if (lp->flags & LPFLG_LSA_ENGAGED)
+      if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
         ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
       break;
     }
 
 out:
   return;
+
 }
 
 static void
 ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
 {
-  /* So far, nothing to do here. */
+  /* Nothing to do here */
   return;
 }
 
@@ -706,22 +1143,10 @@ build_router_tlv (struct stream *s)
 }
 
 static void
-build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->link_type.header;
-  if (ntohs (tlvh->type) != 0)
+build_link_subtlv (struct stream *s, struct te_tlv_header *tlvh)
     {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
 
-static void
-build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->link_id.header;
-  if (ntohs (tlvh->type) != 0)
+  if ((tlvh != NULL) && (ntohs (tlvh->type) != 0))
     {
       build_tlv_header (s, tlvh);
       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
@@ -730,104 +1155,32 @@ build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
 }
 
 static void
-build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr;
-  if (tlvh != NULL && ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr;
-  if (tlvh != NULL && ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->te_metric.header;
-  if (ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->max_bw.header;
-  if (ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->max_rsv_bw.header;
-  if (ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->unrsv_bw.header;
-  if (ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp)
-{
-  struct te_tlv_header *tlvh = &lp->rsc_clsclr.header;
-  if (ntohs (tlvh->type) != 0)
-    {
-      build_tlv_header (s, tlvh);
-      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
-    }
-  return;
-}
-
-static void
-build_link_tlv (struct stream *s, struct mpls_te_link *lp)
+build_link_tlv (struct stream *s, struct mpls_te_link *lp)
 {
   set_linkparams_link_header (lp);
   build_tlv_header (s, &lp->link_header.header);
 
-  build_link_subtlv_link_type (s, lp);
-  build_link_subtlv_link_id (s, lp);
-  build_link_subtlv_lclif_ipaddr (s, lp);
-  build_link_subtlv_rmtif_ipaddr (s, lp);
-  build_link_subtlv_te_metric (s, lp);
-  build_link_subtlv_max_bw (s, lp);
-  build_link_subtlv_max_rsv_bw (s, lp);
-  build_link_subtlv_unrsv_bw (s, lp);
-  build_link_subtlv_rsc_clsclr (s, lp);
+  build_link_subtlv (s, &lp->link_type.header);
+  build_link_subtlv (s, &lp->link_id.header);
+  build_link_subtlv (s, &lp->lclif_ipaddr.header);
+  build_link_subtlv (s, &lp->rmtif_ipaddr.header);
+  build_link_subtlv (s, &lp->te_metric.header);
+  build_link_subtlv (s, &lp->max_bw.header);
+  build_link_subtlv (s, &lp->max_rsv_bw.header);
+  build_link_subtlv (s, &lp->unrsv_bw.header);
+  build_link_subtlv (s, &lp->rsc_clsclr.header);
+  build_link_subtlv (s, &lp->lrrid.header);
+  build_link_subtlv (s, &lp->llri.header);
+  build_link_subtlv (s, &lp->rip.header);
+  build_link_subtlv (s, &lp->ras.header);
+  build_link_subtlv (s, &lp->av_delay.header);
+  build_link_subtlv (s, &lp->mm_delay.header);
+  build_link_subtlv (s, &lp->delay_var.header);
+  build_link_subtlv (s, &lp->pkt_loss.header);
+  build_link_subtlv (s, &lp->res_bw.header);
+  build_link_subtlv (s, &lp->ava_bw.header);
+  build_link_subtlv (s, &lp->res_bw.header);
+
   return;
 }
 
@@ -856,7 +1209,7 @@ ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
   struct stream *s;
   struct lsa_header *lsah;
   struct ospf_lsa *new = NULL;
-  u_char options, lsa_type;
+  u_char options, lsa_type = 0;
   struct in_addr lsa_id;
   u_int32_t tmp;
   u_int16_t length;
@@ -869,19 +1222,42 @@ ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
     }
   lsah = (struct lsa_header *) STREAM_DATA (s);
 
-  options  = LSA_OPTIONS_GET (area);
-  options |= LSA_OPTIONS_NSSA_GET (area);
-  options |= OSPF_OPTION_O; /* Don't forget this :-) */
+  options = OSPF_OPTION_O;      /* Don't forget this :-) */
 
-  lsa_type = OSPF_OPAQUE_AREA_LSA;
-  tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
-  lsa_id.s_addr = htonl (tmp);
+  /* Set opaque-LSA header fields depending of the type of RFC */
+  if (IS_INTER_AS (lp->type))
+    {
+      if IS_FLOOD_AS (lp->type)
+        {
+          options |= OSPF_OPTION_E;     /* Enable AS external as we flood Inter-AS with Opaque Type 11 */
+          lsa_type = OSPF_OPAQUE_AS_LSA;
+        }
+      else
+        {
+          options |= LSA_OPTIONS_GET (area);    /* Get area default option */
+          options |= LSA_OPTIONS_NSSA_GET (area);
+          lsa_type = OSPF_OPAQUE_AREA_LSA;
+        }
+      tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
+      lsa_id.s_addr = htonl (tmp);
 
-  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
-    zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id));
+      struct ospf *top = ospf_lookup ();
 
-  /* Set opaque-LSA header fields. */
-  lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
+      lsa_header_set (s, options, lsa_type, lsa_id, top->router_id);
+    }
+  else
+    {
+      options |= LSA_OPTIONS_GET (area);        /* Get area default option */
+      options |= LSA_OPTIONS_NSSA_GET (area);
+      lsa_type = OSPF_OPAQUE_AREA_LSA;
+      tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
+      lsa_id.s_addr = htonl (tmp);
+      lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance",
+                lsa_type, inet_ntoa (lsa_id));
 
   /* Set opaque-LSA body fields. */
   ospf_mpls_te_lsa_body_set (s, lp);
@@ -936,9 +1312,8 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
       goto out;
     }
 
-  /* Now this linkparameter entry has associated LSA. */
-  lp->flags |= LPFLG_LSA_ENGAGED;
-
+  /* Now this link-parameter entry has associated LSA. */
+  SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
   /* Update new LSA origination count. */
   area->ospf->lsa_originate_count++;
 
@@ -949,7 +1324,8 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
     {
       char area_id[INET_ADDRSTRLEN];
       strcpy (area_id, inet_ntoa (area->area_id));
-      zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
+      zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)",
+                   new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
       ospf_lsa_header_dump (new->data);
     }
 
@@ -959,7 +1335,7 @@ out:
 }
 
 static int
-ospf_mpls_te_lsa_originate (void *arg)
+ospf_mpls_te_lsa_originate_area (void *arg)
 {
   struct ospf_area *area = (struct ospf_area *) arg;
   struct listnode *node, *nnode;
@@ -968,34 +1344,44 @@ ospf_mpls_te_lsa_originate (void *arg)
 
   if (OspfMplsTE.status == disabled)
     {
-      zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
+      zlog_info ("ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
       rc = 0; /* This is not an error case. */
       goto out;
     }
 
   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
     {
+      /* Process only enabled LSA with area scope flooding */
+      if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || IS_FLOOD_AS (lp->type))
+        continue;
+
       if (lp->area == NULL)
         continue;
+
       if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
         continue;
 
-      if (lp->flags & LPFLG_LSA_ENGAGED)
+      if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
         {
-          if (lp->flags & LPFLG_LSA_FORCED_REFRESH)
+          if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH)
             {
-              lp->flags &= ~LPFLG_LSA_FORCED_REFRESH;
+              UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
+              zlog_warn ("OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
             }
           continue;
         }
       if (! is_mandated_params_set (lp))
         {
-          zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?");
+          zlog_warn ("ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
+              lp->ifp ? lp->ifp->name : "?");
           continue;
         }
 
       /* Ok, let's try to originate an LSA for this area and Link. */
+      if (IS_DEBUG_OSPF_TE)
+        zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s",
+                     lp->instance, inet_ntoa (area->area_id), lp->ifp ? lp->ifp->name : "?");
       if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
         goto out;
     }
@@ -1005,11 +1391,112 @@ out:
   return rc;
 }
 
+static int
+ospf_mpls_te_lsa_originate2 (struct ospf *top, struct mpls_te_link *lp)
+{
+  struct ospf_lsa *new;
+  int rc = -1;
+
+  /* Create new Opaque-LSA/Inter-AS instance. */
+  if ((new = ospf_mpls_te_lsa_new (NULL, lp)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
+      goto out;
+    }
+
+  /* Install this LSA into LSDB. */
+  if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?");
+      ospf_lsa_unlock (&new);
+      goto out;
+    }
+
+  /* Now this Router Info parameter entry has associated LSA. */
+  SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
+  /* Update new LSA origination count. */
+  top->lsa_originate_count++;
+
+  /* Flood new LSA through AS. */
+  ospf_flood_through_as (top, NULL /*nbr */ , new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS",
+                  new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+  rc = 0;
+out:return rc;
+}
+
+static int
+ospf_mpls_te_lsa_originate_as (void *arg)
+{
+  struct ospf *top;
+  struct ospf_area *area;
+  struct listnode *node, *nnode;
+  struct mpls_te_link *lp;
+  int rc = -1;
+
+  if ((OspfMplsTE.status == disabled) || (OspfMplsTE.inter_as == Disable))
+    {
+      zlog_info
+        ("ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now.");
+      rc = 0;                   /* This is not an error case. */
+      goto out;
+    }
+
+  for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
+    {
+      /* Process only enabled INTER_AS Links or Pseudo-Links */
+      if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || !IS_INTER_AS (lp->type))
+        continue;
+
+      if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
+        {
+          if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH)
+            {
+              UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            }
+          continue;
+        }
+      if (!is_mandated_params_set (lp))
+        {
+          zlog_warn ("ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.",
+             lp->ifp ? lp->ifp->name : "?");
+          continue;
+        }
+
+      /* Ok, let's try to originate an LSA for this AS and Link. */
+      if (IS_DEBUG_OSPF_TE)
+        zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
+                    lp->instance, IS_FLOOD_AS (lp->type) ? "AS" : "Area", lp->ifp ? lp->ifp->name : "Unknown");
+
+      if (IS_FLOOD_AS (lp->type))
+        {
+          top = (struct ospf *) arg;
+          rc = ospf_mpls_te_lsa_originate2 (top, lp);
+        }
+      else
+        {
+          area = (struct ospf_area *) arg;
+          rc = ospf_mpls_te_lsa_originate1 (area, lp);
+        }
+    }
+
+  rc = 0;
+out:return rc;
+}
+
 static struct ospf_lsa *
 ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
 {
   struct mpls_te_link *lp;
   struct ospf_area *area = lsa->area;
+  struct ospf *top;
   struct ospf_lsa *new = NULL;
 
   if (OspfMplsTE.status == disabled)
@@ -1029,11 +1516,18 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
     }
 
+  /* Check if lp was not disable in the interval */
+  if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE))
+    {
+      zlog_warn ("ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!");
+      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
+    }
+
   /* If the lsa's age reached to MaxAge, start flushing procedure. */
   if (IS_LSA_MAXAGE (lsa))
     {
       if (lp)
-        lp->flags &= ~LPFLG_LSA_ENGAGED;
+        UNSET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
       ospf_opaque_lsa_flush_schedule (lsa);
       goto out;
     }
@@ -1048,15 +1542,24 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
 
   /* Install this LSA into LSDB. */
   /* Given "lsa" will be freed in the next function. */
-  if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
+  /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use ospf_lookup() to get ospf instance */
+  if (area)
+    top = area->ospf;
+  else
+    top = ospf_lookup ();
+
+  if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
     {
       zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
       ospf_lsa_unlock (&new);
       goto out;
     }
 
-  /* Flood updated LSA through area. */
-  ospf_flood_through_area (area, NULL/*nbr*/, new);
+  /* Flood updated LSA through AS or Area depending of the RFC of the link */
+  if (IS_FLOOD_AS (lp->type))
+    ospf_flood_through_as (top, NULL, new);
+  else
+    ospf_flood_through_area (area, NULL/*nbr*/, new);
 
   /* Debug logging. */
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
@@ -1070,34 +1573,80 @@ out:
   return new;
 }
 
-static void
-ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
-                           enum sched_opcode opcode)
+void
+ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode)
 {
   struct ospf_lsa lsa;
   struct lsa_header lsah;
+  struct ospf *top;
   u_int32_t tmp;
 
   memset (&lsa, 0, sizeof (lsa));
   memset (&lsah, 0, sizeof (lsah));
+  top = ospf_lookup ();
+
+  /* Check if the pseudo link is ready to flood */
+  if (!(CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE))
+      || !(IS_FLOOD_AREA (lp->type) || IS_FLOOD_AS (lp->type))) {
+    return;
+  }
 
   lsa.area = lp->area;
   lsa.data = &lsah;
-  lsah.type = OSPF_OPAQUE_AREA_LSA;
-  tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
-  lsah.id.s_addr = htonl (tmp);
+  if (IS_FLOOD_AS (lp->type))
+    {
+      lsah.type = OSPF_OPAQUE_AS_LSA;
+      tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
+      lsah.id.s_addr = htonl (tmp);
+    }
+  else
+    {
+      lsah.type = OSPF_OPAQUE_AREA_LSA;
+      if (IS_INTER_AS (lp->type))
+        {
+          /* Set the area context if not know */
+          if (lp->area == NULL)
+            lp->area = ospf_area_lookup_by_area_id (top, OspfMplsTE.interas_areaid);
+          /* Unable to set the area context. Abort! */
+          if (lp->area == NULL)
+            {
+              zlog_warn ("MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !");
+              return;
+            }
+          tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
+        }
+      else
+        tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
+      lsah.id.s_addr = htonl (tmp);
+    }
 
   switch (opcode)
     {
-    case REORIGINATE_PER_AREA:
-      ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area,
-          OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
+    case REORIGINATE_THIS_LSA:
+      if (IS_FLOOD_AS (lp->type))
+        {
+          ospf_opaque_lsa_reoriginate_schedule ((void *) top, OSPF_OPAQUE_AS_LSA,
+              OPAQUE_TYPE_INTER_AS_LSA);
+          break;
+        }
+
+      if (IS_FLOOD_AREA (lp->type))
+        {
+          if (IS_INTER_AS (lp->type))
+            ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA,
+                OPAQUE_TYPE_INTER_AS_LSA);
+          else
+            ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA,
+                OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
+          break;
+        }
       break;
     case REFRESH_THIS_LSA:
       ospf_opaque_lsa_refresh_schedule (&lsa);
       break;
     case FLUSH_THIS_LSA:
-      lp->flags &= ~LPFLG_LSA_ENGAGED;
+      /* Reset Activity flag */
+      lp->flags = LPFLG_LSA_INACTIVE;
       ospf_opaque_lsa_flush_schedule (&lsa);
       break;
     default:
@@ -1108,6 +1657,7 @@ ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
   return;
 }
 
+
 /*------------------------------------------------------------------------*
  * Followings are vty session control functions.
  *------------------------------------------------------------------------*/
@@ -1118,7 +1668,8 @@ show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
   struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
 
   if (vty != NULL)
-    vty_out (vty, "  Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
+    vty_out (vty, "  Router-Address: %s%s", inet_ntoa (top->value),
+             VTY_NEWLINE);
   else
     zlog_debug ("    Router-Address: %s", inet_ntoa (top->value));
 
@@ -1131,7 +1682,8 @@ show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
   struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
 
   if (vty != NULL)
-    vty_out (vty, "  Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE);
+    vty_out (vty, "  Link: %u octets of data%s", ntohs (top->header.length),
+             VTY_NEWLINE);
   else
     zlog_debug ("    Link: %u octets of data", ntohs (top->header.length));
 
@@ -1158,7 +1710,8 @@ show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
     }
 
   if (vty != NULL)
-    vty_out (vty, "  Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE);
+    vty_out (vty, "  Link-Type: %s (%u)%s", cp, top->link_type.value,
+             VTY_NEWLINE);
   else
     zlog_debug ("    Link-Type: %s (%u)", cp, top->link_type.value);
 
@@ -1180,7 +1733,8 @@ show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
 }
 
 static u_int16_t
-show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
+show_vty_link_subtlv_lclif_ipaddr (struct vty *vty,
+                                   struct te_tlv_header *tlvh)
 {
   struct te_link_subtlv_lclif_ipaddr *top;
   int i, n;
@@ -1196,7 +1750,8 @@ show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
   for (i = 0; i < n; i++)
     {
       if (vty != NULL)
-        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
+        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]),
+                 VTY_NEWLINE);
       else
         zlog_debug ("      #%d: %s", i, inet_ntoa (top->value[i]));
     }
@@ -1204,7 +1759,8 @@ show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
 }
 
 static u_int16_t
-show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
+show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty,
+                                   struct te_tlv_header *tlvh)
 {
   struct te_link_subtlv_rmtif_ipaddr *top;
   int i, n;
@@ -1219,7 +1775,8 @@ show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
   for (i = 0; i < n; i++)
     {
       if (vty != NULL)
-        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
+        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]),
+                 VTY_NEWLINE);
       else
         zlog_debug ("      #%d: %s", i, inet_ntoa (top->value[i]));
     }
@@ -1233,9 +1790,11 @@ show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
 
   top = (struct te_link_subtlv_te_metric *) tlvh;
   if (vty != NULL)
-    vty_out (vty, "  Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
+    vty_out (vty, "  Traffic Engineering Metric: %u%s",
+             (u_int32_t) ntohl (top->value), VTY_NEWLINE);
   else
-    zlog_debug ("    Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
+    zlog_debug ("    Traffic Engineering Metric: %u",
+                (u_int32_t) ntohl (top->value));
 
   return TLV_SIZE (tlvh);
 }
@@ -1247,7 +1806,7 @@ show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
   float fval;
 
   top = (struct te_link_subtlv_max_bw *) tlvh;
-  ntohf (&top->value, &fval);
+  fval = ntohf (top->value);
 
   if (vty != NULL)
     vty_out (vty, "  Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
@@ -1264,10 +1823,11 @@ show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
   float fval;
 
   top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
-  ntohf (&top->value, &fval);
+  fval = ntohf (top->value);
 
   if (vty != NULL)
-    vty_out (vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
+    vty_out (vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval,
+             VTY_NEWLINE);
   else
     zlog_debug ("    Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
 
@@ -1278,17 +1838,25 @@ static u_int16_t
 show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
 {
   struct te_link_subtlv_unrsv_bw *top;
-  float fval;
+  float fval1, fval2;
   int i;
 
   top = (struct te_link_subtlv_unrsv_bw *) tlvh;
-  for (i = 0; i < 8; i++)
+  if (vty != NULL)
+    vty_out (vty, "  Unreserved Bandwidth per Class Type in Byte/s:%s", VTY_NEWLINE);
+  else
+    zlog_debug ("    Unreserved Bandwidth per Class Type in Byte/s:");
+  for (i = 0; i < MAX_CLASS_TYPE; i+=2)
     {
-      ntohf (&top->value[i], &fval);
+      fval1 = ntohf (top->value[i]);
+      fval2 = ntohf (top->value[i+1]);
+
       if (vty != NULL)
-        vty_out (vty, "  Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE);
+        vty_out(vty, "    [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s",
+                i, fval1, i+1, fval2, VTY_NEWLINE);
       else
-        zlog_debug ("    Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
+        zlog_debug ("      [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)",
+                    i, fval1, i+1, fval2);
     }
 
   return TLV_SIZE (tlvh);
@@ -1301,9 +1869,230 @@ show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
 
   top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
   if (vty != NULL)
-    vty_out (vty, "  Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
+    vty_out (vty, "  Resource class/color: 0x%x%s",
+             (u_int32_t) ntohl (top->value), VTY_NEWLINE);
+  else
+    zlog_debug ("    Resource Class/Color: 0x%x",
+                (u_int32_t) ntohl (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_lrrid (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_lrrid *top;
+
+  top = (struct te_link_subtlv_lrrid *) tlvh;
+
+  if (vty != NULL)
+    {
+      vty_out (vty, "  Local  TE Router ID: %s%s", inet_ntoa (top->local),
+               VTY_NEWLINE);
+      vty_out (vty, "  Remote TE Router ID: %s%s", inet_ntoa (top->remote),
+               VTY_NEWLINE);
+    }
+  else
+    {
+      zlog_debug ("    Local  TE Router ID: %s", inet_ntoa (top->local));
+      zlog_debug ("    Remote TE Router ID: %s", inet_ntoa (top->remote));
+    }
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_llri (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_llri *top;
+
+  top = (struct te_link_subtlv_llri *) tlvh;
+
+  if (vty != NULL)
+    {
+      vty_out (vty, "  Link Local  ID: %d%s", (u_int32_t) ntohl (top->local),
+               VTY_NEWLINE);
+      vty_out (vty, "  Link Remote ID: %d%s", (u_int32_t) ntohl (top->remote),
+               VTY_NEWLINE);
+    }
+  else
+    {
+      zlog_debug ("    Link Local  ID: %d", (u_int32_t) ntohl (top->local));
+      zlog_debug ("    Link Remote ID: %d", (u_int32_t) ntohl (top->remote));
+    }
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_rip (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_rip *top;
+
+  top = (struct te_link_subtlv_rip *) tlvh;
+
+  if (vty != NULL)
+    vty_out (vty, "  Inter-AS TE Remote ASBR IP address: %s%s",
+             inet_ntoa (top->value), VTY_NEWLINE);
+  else
+    zlog_debug ("    Inter-AS TE Remote ASBR IP address: %s",
+                inet_ntoa (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_ras (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_ras *top;
+
+  top = (struct te_link_subtlv_ras *) tlvh;
+
+  if (vty != NULL)
+    vty_out (vty, "  Inter-AS TE Remote AS number: %u%s", ntohl (top->value),
+             VTY_NEWLINE);
+  else
+    zlog_debug ("    Inter-AS TE Remote AS number: %u", ntohl (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_av_delay (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_av_delay *top;
+  u_int32_t delay;
+  u_int32_t anomalous;
+
+  top = (struct te_link_subtlv_av_delay *) tlvh;
+  delay = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
+  anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL;
+
+  if (vty != NULL)
+    vty_out (vty, "  %s Average Link Delay: %d (micro-sec)%s",
+             anomalous ? "Anomalous" : "Normal", delay, VTY_NEWLINE);
+  else
+    zlog_debug ("    %s Average Link Delay: %d (micro-sec)",
+                anomalous ? "Anomalous" : "Normal", delay);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_mm_delay (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_mm_delay *top;
+  u_int32_t low, high;
+  u_int32_t anomalous;
+
+  top = (struct te_link_subtlv_mm_delay *) tlvh;
+  low = (u_int32_t) ntohl (top->low) & TE_EXT_MASK;
+  anomalous = (u_int32_t) ntohl (top->low) & TE_EXT_ANORMAL;
+  high = (u_int32_t) ntohl (top->high);
+
+  if (vty != NULL)
+    vty_out (vty, "  %s Min/Max Link Delay: %d/%d (micro-sec)%s",
+             anomalous ? "Anomalous" : "Normal", low, high, VTY_NEWLINE);
+  else
+    zlog_debug ("    %s Min/Max Link Delay: %d/%d (micro-sec)",
+                anomalous ? "Anomalous" : "Normal", low, high);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_delay_var (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_delay_var *top;
+  u_int32_t jitter;
+
+  top = (struct te_link_subtlv_delay_var *) tlvh;
+  jitter = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
+
+  if (vty != NULL)
+    vty_out (vty, "  Delay Variation: %d (micro-sec)%s", jitter, VTY_NEWLINE);
+  else
+    zlog_debug ("    Delay Variation: %d (micro-sec)", jitter);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_pkt_loss (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_pkt_loss *top;
+  u_int32_t loss;
+  u_int32_t anomalous;
+  float fval;
+
+  top = (struct te_link_subtlv_pkt_loss *) tlvh;
+  loss = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
+  fval = (float) (loss * LOSS_PRECISION);
+  anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL;
+
+  if (vty != NULL)
+    vty_out (vty, "  %s Link Loss: %g (%%)%s", anomalous ? "Anomalous" : "Normal",
+             fval, VTY_NEWLINE);
+  else
+    zlog_debug ("    %s Link Loss: %g (%%)", anomalous ? "Anomalous" : "Normal",
+                fval);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_res_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_res_bw *top;
+  float fval;
+
+  top = (struct te_link_subtlv_res_bw *) tlvh;
+  fval = ntohf (top->value);
+
+  if (vty != NULL)
+    vty_out (vty, "  Unidirectional Residual Bandwidth: %g (Bytes/sec)%s",
+             fval, VTY_NEWLINE);
+  else
+    zlog_debug ("    Unidirectional Residual Bandwidth: %g (Bytes/sec)",
+                fval);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_ava_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_ava_bw *top;
+  float fval;
+
+  top = (struct te_link_subtlv_ava_bw *) tlvh;
+  fval = ntohf (top->value);
+
+  if (vty != NULL)
+    vty_out (vty, "  Unidirectional Available Bandwidth: %g (Bytes/sec)%s",
+             fval, VTY_NEWLINE);
   else
-    zlog_debug ("    Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
+    zlog_debug ("    Unidirectional Available Bandwidth: %g (Bytes/sec)",
+                fval);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_use_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_use_bw *top;
+  float fval;
+
+  top = (struct te_link_subtlv_use_bw *) tlvh;
+  fval = ntohf (top->value);
+
+  if (vty != NULL)
+    vty_out (vty, "  Unidirectional Utilized Bandwidth: %g (Bytes/sec)%s",
+             fval, VTY_NEWLINE);
+  else
+    zlog_debug ("    Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
+                fval);
 
   return TLV_SIZE (tlvh);
 }
@@ -1312,9 +2101,11 @@ static u_int16_t
 show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
 {
   if (vty != NULL)
-    vty_out (vty, "  Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
+    vty_out (vty, "  Unknown TLV: [type(0x%x), length(0x%x)]%s",
+             ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
   else
-    zlog_debug ("    Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
+    zlog_debug ("    Unknown TLV: [type(0x%x), length(0x%x)]",
+                ntohs (tlvh->type), ntohs (tlvh->length));
 
   return TLV_SIZE (tlvh);
 }
@@ -1358,6 +2149,39 @@ ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
         case TE_LINK_SUBTLV_RSC_CLSCLR:
           sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
           break;
+        case TE_LINK_SUBTLV_LRRID:
+          sum += show_vty_link_subtlv_lrrid (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_LLRI:
+          sum += show_vty_link_subtlv_llri (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_RIP:
+          sum += show_vty_link_subtlv_rip (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_RAS:
+          sum += show_vty_link_subtlv_ras (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_AV_DELAY:
+          sum += show_vty_link_subtlv_av_delay (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_MM_DELAY:
+          sum += show_vty_link_subtlv_mm_delay (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_DELAY_VAR:
+          sum += show_vty_link_subtlv_delay_var (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_PKT_LOSS:
+          sum += show_vty_link_subtlv_pkt_loss (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_RES_BW:
+          sum += show_vty_link_subtlv_res_bw (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_AVA_BW:
+          sum += show_vty_link_subtlv_ava_bw (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_USE_BW:
+          sum += show_vty_link_subtlv_use_bw (vty, tlvh);
+          break;
         default:
           sum += show_vty_unknown_tlv (vty, tlvh);
           break;
@@ -1411,49 +2235,20 @@ ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
 static void
 ospf_mpls_te_config_write_router (struct vty *vty)
 {
+
   if (OspfMplsTE.status == enabled)
     {
-      vty_out (vty, " mpls-te%s", VTY_NEWLINE);
+      vty_out (vty, " mpls-te on%s", VTY_NEWLINE);
       vty_out (vty, " mpls-te router-address %s%s",
                inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
     }
-  return;
-}
-
-static void
-ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
-{
-  struct mpls_te_link *lp;
-
-  if ((OspfMplsTE.status == enabled)
-  &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
-  &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
-    {
-      float fval;
-      int i;
-
-      vty_out (vty, " mpls-te link metric %u%s",
-               (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE);
-
-      ntohf (&lp->max_bw.value, &fval);
-      if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
-        vty_out (vty, " mpls-te link max-bw %g%s", fval, VTY_NEWLINE);
 
-      ntohf (&lp->max_rsv_bw.value, &fval);
-      if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
-        vty_out (vty, " mpls-te link max-rsv-bw %g%s", fval, VTY_NEWLINE);
+  if (OspfMplsTE.inter_as == AS)
+    vty_out (vty, "  mpls-te inter-as as%s", VTY_NEWLINE);
+  if (OspfMplsTE.inter_as == Area)
+    vty_out (vty, "  mpls-te inter-as area %s %s",
+             inet_ntoa (OspfMplsTE.interas_areaid), VTY_NEWLINE);
 
-      for (i = 0; i < 8; i++)
-        {
-          ntohf (&lp->unrsv_bw.value[i], &fval);
-          if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
-            vty_out (vty, " mpls-te link unrsv-bw %d %g%s",
-                     i, fval, VTY_NEWLINE);
-        }
-
-      vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s",
-               (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE);
-    }
   return;
 }
 
@@ -1461,13 +2256,13 @@ ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
  * Followings are vty command functions.
  *------------------------------------------------------------------------*/
 
-DEFUN (mpls_te,
-       mpls_te_cmd,
-       "mpls-te",
-       "Configure MPLS-TE parameters\n"
+DEFUN (ospf_mpls_te_on,
+       ospf_mpls_te_on_cmd,
+       "mpls-te on",
+       MPLS_TE_STR
        "Enable the MPLS-TE functionality\n")
 {
-  struct listnode *node, *nnode;
+  struct listnode *node;
   struct mpls_te_link *lp;
   struct ospf *ospf = vty->index;
 
@@ -1482,31 +2277,28 @@ DEFUN (mpls_te,
 
   OspfMplsTE.status = enabled;
 
-  /*
-   * Following code is intended to handle two cases;
-   *
-   * 1) MPLS-TE was disabled at startup time, but now become enabled.
-   * 2) MPLS-TE was once enabled then disabled, and now enabled again.
-   */
-  for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
-    initialize_linkparams (lp);
+  /* Reoriginate RFC3630 & RFC6827 Links */
+  ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
 
-  ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
+  /* Reoriginate LSA if INTER-AS is always on */
+  if (OspfMplsTE.inter_as != Disable)
+    {
+      for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
+        {
+          if (IS_INTER_AS (lp->type))
+            {
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
+            }
+        }
+    }
 
   return CMD_SUCCESS;
 }
 
-ALIAS (mpls_te,
-       mpls_te_on_cmd,
-       "mpls-te on",
-       "Configure MPLS-TE parameters\n"
-       "Enable the MPLS-TE functionality\n")
-
-DEFUN (no_mpls_te,
-       no_mpls_te_cmd,
+DEFUN (no_ospf_mpls_te,
+       no_ospf_mpls_te_cmd,
        "no mpls-te",
        NO_STR
-       "Configure MPLS-TE parameters\n"
        "Disable the MPLS-TE functionality\n")
 {
   struct listnode *node, *nnode;
@@ -1525,24 +2317,23 @@ DEFUN (no_mpls_te,
   OspfMplsTE.status = disabled;
 
   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
-    if (lp->area != NULL)
-      if (lp->flags & LPFLG_LSA_ENGAGED)
+    if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
         ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
 
   return CMD_SUCCESS;
 }
 
-ALIAS (no_mpls_te,
-       no_mpls_te_val_cmd,
+ALIAS (no_ospf_mpls_te,
+       no_ospf_mpls_te_val_cmd,
        "no mpls-te on",
        NO_STR
-       "Configure MPLS-TE parameters\n"
+       MPLS_TE_STR
        "Disable the MPLS-TE functionality\n")
 
-DEFUN (mpls_te_router_addr,
-       mpls_te_router_addr_cmd,
+DEFUN (ospf_mpls_te_router_addr,
+       ospf_mpls_te_router_addr_cmd,
        "mpls-te router-address A.B.C.D",
-       "MPLS-TE specific commands\n"
+       MPLS_TE_STR
        "Stable IP address of the advertising router\n"
        "MPLS-TE router address in IPv4 address format\n")
 {
@@ -1573,10 +2364,10 @@ DEFUN (mpls_te_router_addr,
 
       for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
         {
-          if (lp->area == NULL)
+          if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
             continue;
 
-          if ((lp->flags & LPFLG_LSA_ENGAGED) == 0)
+          if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
             {
               need_to_reoriginate = 1;
               break;
@@ -1585,247 +2376,152 @@ DEFUN (mpls_te_router_addr,
       
       for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
         {
-          if (lp->area == NULL)
+          if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
             continue;
 
           if (need_to_reoriginate)
-            lp->flags |= LPFLG_LSA_FORCED_REFRESH;
+            SET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
           else
             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
         }
 
       if (need_to_reoriginate)
-        ospf_mpls_te_foreach_area (
-            ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
+        ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
     }
 out:
   return CMD_SUCCESS;
 }
 
-DEFUN (mpls_te_link_metric,
-       mpls_te_link_metric_cmd,
-       "mpls-te link metric <0-4294967295>",
-       "MPLS-TE specific commands\n"
-       "Configure MPLS-TE link parameters\n"
-       "Link metric for MPLS-TE purpose\n"
-       "Metric\n")
+static int
+set_inter_as_mode (struct vty *vty, const char *mode_name,
+                   const char *area_id)
 {
-  struct interface *ifp = (struct interface *) vty->index;
+  enum inter_as_mode mode;
+  struct listnode *node;
   struct mpls_te_link *lp;
-  u_int32_t value;
-
-  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
-    {
-      vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  int format;
 
-  value = strtoul (argv[0], NULL, 10);
-
-  if (ntohs (lp->te_metric.header.type) == 0
-  ||  ntohl (lp->te_metric.value) != value)
+  if (OspfMplsTE.status == enabled)
     {
-      set_linkparams_te_metric (lp, value);
-
-      if (OspfMplsTE.status == enabled)
-        if (lp->area != NULL)
-          {
-            if (lp->flags & LPFLG_LSA_ENGAGED)
-              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
-            else
-              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
-          }
-    }
-  return CMD_SUCCESS;
-}
-
-DEFUN (mpls_te_link_maxbw,
-       mpls_te_link_maxbw_cmd,
-       "mpls-te link max-bw BANDWIDTH",
-       "MPLS-TE specific commands\n"
-       "Configure MPLS-TE link parameters\n"
-       "Maximum bandwidth that can be used\n"
-       "Bytes/second (IEEE floating point format)\n")
-{
-  struct interface *ifp = (struct interface *) vty->index;
-  struct mpls_te_link *lp;
-  float f1, f2;
 
-  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
-    {
-      vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+      /* Read and Check inter_as mode */
+      if (strcmp (mode_name, "as") == 0)
+        mode = AS;
+      else if (strcmp (mode_name, "area") == 0)
+        {
+          mode = Area;
+          VTY_GET_OSPF_AREA_ID (OspfMplsTE.interas_areaid, format, area_id);
+        }
+      else
+        {
+          vty_out (vty, "Unknown mode. Please choose between as or area%s",
+                   VTY_NEWLINE);
+          return CMD_WARNING;
+        }
 
-  ntohf (&lp->max_bw.value, &f1);
-  if (sscanf (argv[0], "%g", &f2) != 1)
-    {
-      vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_debug ("MPLS-TE: Inter-AS enable with %s flooding support",
+                    mode2text[mode]);
 
-  if (ntohs (lp->max_bw.header.type) == 0
-  ||  f1 != f2)
-    {
-      set_linkparams_max_bw (lp, &f2);
+      /* Register new callbacks regarding the flooding scope (AS or Area) */
+      if (ospf_mpls_te_register (mode) < 0)
+        {
+          vty_out (vty, "Internal error: Unable to register Inter-AS functions%s",
+                   VTY_NEWLINE);
+          return CMD_WARNING;
+        }
 
-      if (OspfMplsTE.status == enabled)
-        if (lp->area != NULL)
-          {
-            if (lp->flags & LPFLG_LSA_ENGAGED)
-              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
-            else
-              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
-          }
+      /* Enable mode and re-originate LSA if needed */
+      if ((OspfMplsTE.inter_as == Disable) && (mode != OspfMplsTE.inter_as))
+        {
+          OspfMplsTE.inter_as = mode;
+          /* Re-originate all InterAS-TEv2 LSA */
+          for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
+            {
+              if (IS_INTER_AS (lp->type))
+                {
+                  if (mode == AS)
+                    lp->type |= FLOOD_AS;
+                  else
+                    lp->type |= FLOOD_AREA;
+                  ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
+                }
+            }
+        }
+      else
+        {
+          vty_out (vty, "Please change Inter-AS support to disable first before going to mode %s%s",
+                   mode2text[mode], VTY_NEWLINE);
+          return CMD_WARNING;
+        }
     }
   return CMD_SUCCESS;
 }
 
-DEFUN (mpls_te_link_max_rsv_bw,
-       mpls_te_link_max_rsv_bw_cmd,
-       "mpls-te link max-rsv-bw BANDWIDTH",
-       "MPLS-TE specific commands\n"
-       "Configure MPLS-TE link parameters\n"
-       "Maximum bandwidth that may be reserved\n"
-       "Bytes/second (IEEE floating point format)\n")
-{
-  struct interface *ifp = (struct interface *) vty->index;
-  struct mpls_te_link *lp;
-  float f1, f2;
-
-  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
-    {
-      vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
 
-  ntohf (&lp->max_rsv_bw.value, &f1);
-  if (sscanf (argv[0], "%g", &f2) != 1)
-    {
-      vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
-  if (ntohs (lp->max_rsv_bw.header.type) == 0
-  ||  f1 != f2)
-    {
-      set_linkparams_max_rsv_bw (lp, &f2);
-
-      if (OspfMplsTE.status == enabled)
-        if (lp->area != NULL)
-          {
-            if (lp->flags & LPFLG_LSA_ENGAGED)
-              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
-            else
-              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
-          }
-    }
-  return CMD_SUCCESS;
+DEFUN (ospf_mpls_te_inter_as_as,
+       ospf_mpls_te_inter_as_cmd,
+       "mpls-te inter-as as",
+       MPLS_TE_STR
+       "Configure MPLS-TE Inter-AS support\n"
+       "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
+{
+  return set_inter_as_mode (vty, "as", "");
 }
 
-DEFUN (mpls_te_link_unrsv_bw,
-       mpls_te_link_unrsv_bw_cmd,
-       "mpls-te link unrsv-bw <0-7> BANDWIDTH",
-       "MPLS-TE specific commands\n"
-       "Configure MPLS-TE link parameters\n"
-       "Unreserved bandwidth at each priority level\n"
-       "Priority\n"
-       "Bytes/second (IEEE floating point format)\n")
+DEFUN (ospf_mpls_te_inter_as_area,
+       ospf_mpls_te_inter_as_area_cmd,
+       "mpls-te inter-as area (A.B.C.D|<0-4294967295>)",
+       MPLS_TE_STR
+       "Configure MPLS-TE Inter-AS support\n"
+       "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
+       "OSPF area ID in IP format\n"
+       "OSPF area ID as decimal value\n")
 {
-  struct interface *ifp = (struct interface *) vty->index;
-  struct mpls_te_link *lp;
-  int priority;
-  float f1, f2;
-
-  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
-    {
-      vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
-  /* We don't have to consider about range check here. */
-  if (sscanf (argv[0], "%d", &priority) != 1)
-    {
-      vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
-  ntohf (&lp->unrsv_bw.value [priority], &f1);
-  if (sscanf (argv[1], "%g", &f2) != 1)
-    {
-      vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
-  if (ntohs (lp->unrsv_bw.header.type) == 0
-  ||  f1 != f2)
-    {
-      set_linkparams_unrsv_bw (lp, priority, &f2);
-
-      if (OspfMplsTE.status == enabled)
-        if (lp->area != NULL)
-          {
-            if (lp->flags & LPFLG_LSA_ENGAGED)
-              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
-            else
-              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
-          }
-    }
-  return CMD_SUCCESS;
+  return set_inter_as_mode (vty, "area", argv[0]);
 }
 
-DEFUN (mpls_te_link_rsc_clsclr,
-       mpls_te_link_rsc_clsclr_cmd,
-       "mpls-te link rsc-clsclr BITPATTERN",
-       "MPLS-TE specific commands\n"
-       "Configure MPLS-TE link parameters\n"
-       "Administrative group membership\n"
-       "32-bit Hexadecimal value (ex. 0xa1)\n")
+DEFUN (no_ospf_mpls_te_inter_as,
+       no_ospf_mpls_te_inter_as_cmd,
+       "no mpls-te inter-as",
+       NO_STR
+       MPLS_TE_STR
+       "Disable MPLS-TE Inter-AS support\n")
 {
-  struct interface *ifp = (struct interface *) vty->index;
+
+  struct listnode *node, *nnode;
   struct mpls_te_link *lp;
-  unsigned long value;
 
-  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
-    {
-      vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_debug ("MPLS-TE: Inter-AS support OFF");
 
-  if (sscanf (argv[0], "0x%lx", &value) != 1)
+  if ((OspfMplsTE.status == enabled) && (OspfMplsTE.inter_as != Disable))
     {
-      vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
-      return CMD_WARNING;
+      OspfMplsTE.inter_as = Disable;
+      /* Flush all Inter-AS LSA */
+      for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
+        if (IS_INTER_AS (lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
+          ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
     }
 
-  if (ntohs (lp->rsc_clsclr.header.type) == 0
-  ||  ntohl (lp->rsc_clsclr.value) != value)
-    {
-      set_linkparams_rsc_clsclr (lp, value);
+  /* Deregister the Callbacks for Inter-AS suport */
+  ospf_mpls_te_unregister ();
 
-      if (OspfMplsTE.status == enabled)
-        if (lp->area != NULL)
-          {
-            if (lp->flags & LPFLG_LSA_ENGAGED)
-              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
-            else
-              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
-          }
-    }
   return CMD_SUCCESS;
 }
 
-DEFUN (show_mpls_te_router,
-       show_mpls_te_router_cmd,
-       "show mpls-te router",
+DEFUN (show_ip_ospf_mpls_te_router,
+       show_ip_ospf_mpls_te_router_cmd,
+       "show ip ospf mpls-te router",
        SHOW_STR
+       IP_STR
+       OSPF_STR
        "MPLS-TE information\n"
-       "Router information\n")
+       "MPLS-TE Router parameters\n")
 {
   if (OspfMplsTE.status == enabled)
     {
-      vty_out (vty, "--- MPLS-TE router parameters ---%s",
-               VTY_NEWLINE);
+      vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE);
 
       if (ntohs (OspfMplsTE.router_addr.header.type) != 0)
         show_vty_router_addr (vty, &OspfMplsTE.router_addr.header);
@@ -1839,29 +2535,73 @@ static void
 show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
 {
   struct mpls_te_link *lp;
-  struct te_tlv_header *tlvh;
 
   if ((OspfMplsTE.status == enabled)
-  &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
-  &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
+      && HAS_LINK_PARAMS(ifp)
+      && !if_is_loopback (ifp)
+      && if_is_up (ifp)
+      && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
     {
+      /* Continue only if interface is not passive or support Inter-AS TEv2 */
+      if (!(ospf_oi_count (ifp) > 0))
+        {
+          if (IS_INTER_AS (lp->type))
+            {
+              vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --%s",
+                       ifp->name, VTY_NEWLINE);
+            }
+          else
+            {
+              /* MPLS-TE is not activate on this interface */
+              /* or this interface is passive and Inter-AS TEv2 is not activate */
+              vty_out (vty, "  %s: MPLS-TE is disabled on this interface%s",
+                       ifp->name, VTY_NEWLINE);
+              return;
+            }
+        }
+      else
+        {
       vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
                ifp->name, VTY_NEWLINE);
+        }
 
-      show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
-      show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
-
-      if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL)
-        show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
-      if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL)
-        show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
-
-      show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
-
-      show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
-      show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
-      show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
-      show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
+      if (TLV_TYPE(lp->link_type) != 0)
+        show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
+      if (TLV_TYPE(lp->link_id) != 0)
+        show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
+      if (TLV_TYPE(lp->lclif_ipaddr) != 0)
+        show_vty_link_subtlv_lclif_ipaddr (vty, &lp->lclif_ipaddr.header);
+      if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
+        show_vty_link_subtlv_rmtif_ipaddr (vty, &lp->rmtif_ipaddr.header);
+      if (TLV_TYPE(lp->rip) != 0)
+        show_vty_link_subtlv_rip (vty, &lp->rip.header);
+      if (TLV_TYPE(lp->ras) != 0)
+        show_vty_link_subtlv_ras (vty, &lp->ras.header);
+      if (TLV_TYPE(lp->te_metric) != 0)
+        show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
+      if (TLV_TYPE(lp->max_bw) != 0)
+        show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
+      if (TLV_TYPE(lp->max_rsv_bw) != 0)
+        show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
+      if (TLV_TYPE(lp->unrsv_bw) != 0)
+        show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
+      if (TLV_TYPE(lp->rsc_clsclr) != 0)
+        show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
+      if (TLV_TYPE(lp->av_delay) != 0)
+        show_vty_link_subtlv_av_delay (vty, &lp->av_delay.header);
+      if (TLV_TYPE(lp->mm_delay) != 0)
+        show_vty_link_subtlv_mm_delay (vty, &lp->mm_delay.header);
+      if (TLV_TYPE(lp->delay_var) != 0)
+        show_vty_link_subtlv_delay_var (vty, &lp->delay_var.header);
+      if (TLV_TYPE(lp->pkt_loss) != 0)
+        show_vty_link_subtlv_pkt_loss (vty, &lp->pkt_loss.header);
+      if (TLV_TYPE(lp->res_bw) != 0)
+        show_vty_link_subtlv_res_bw (vty, &lp->res_bw.header);
+      if (TLV_TYPE(lp->ava_bw) != 0)
+        show_vty_link_subtlv_ava_bw (vty, &lp->ava_bw.header);
+      if (TLV_TYPE(lp->use_bw) != 0)
+        show_vty_link_subtlv_use_bw (vty, &lp->use_bw.header);
+      vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE);
     }
   else
     {
@@ -1872,10 +2612,12 @@ show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
   return;
 }
 
-DEFUN (show_mpls_te_link,
-       show_mpls_te_link_cmd,
-       "show mpls-te interface [INTERFACE]",
+DEFUN (show_ip_ospf_mpls_te_link,
+       show_ip_ospf_mpls_te_link_cmd,
+       "show ip ospf mpls-te interface [INTERFACE]",
        SHOW_STR
+       IP_STR
+       OSPF_STR
        "MPLS-TE information\n"
        "Interface information\n"
        "Interface name\n")
@@ -1904,22 +2646,18 @@ DEFUN (show_mpls_te_link,
 static void
 ospf_mpls_te_register_vty (void)
 {
-  install_element (VIEW_NODE, &show_mpls_te_router_cmd);
-  install_element (VIEW_NODE, &show_mpls_te_link_cmd);
-  install_element (ENABLE_NODE, &show_mpls_te_router_cmd);
-  install_element (ENABLE_NODE, &show_mpls_te_link_cmd);
-
-  install_element (OSPF_NODE, &mpls_te_cmd);
-  install_element (OSPF_NODE, &no_mpls_te_cmd);
-  install_element (OSPF_NODE, &no_mpls_te_val_cmd);
-  install_element (OSPF_NODE, &mpls_te_on_cmd);
-  install_element (OSPF_NODE, &mpls_te_router_addr_cmd);
-
-  install_element (INTERFACE_NODE, &mpls_te_link_metric_cmd);
-  install_element (INTERFACE_NODE, &mpls_te_link_maxbw_cmd);
-  install_element (INTERFACE_NODE, &mpls_te_link_max_rsv_bw_cmd);
-  install_element (INTERFACE_NODE, &mpls_te_link_unrsv_bw_cmd);
-  install_element (INTERFACE_NODE, &mpls_te_link_rsc_clsclr_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_mpls_te_router_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_mpls_te_link_cmd);
+
+  install_element (OSPF_NODE, &ospf_mpls_te_on_cmd);
+  install_element (OSPF_NODE, &no_ospf_mpls_te_cmd);
+  install_element (OSPF_NODE, &no_ospf_mpls_te_val_cmd);
+  install_element (OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
+  install_element (OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
+  install_element (OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
+  install_element (OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
 
   return;
 }
index 863d8ba8f29f04a2d5133b0ddbf3709c8ea76830..8bb77c40c578336f6caf80e95a2a40a5cc90096e 100644 (file)
@@ -1,8 +1,11 @@
 /*
- * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
+ * This is an implementation of RFC3630, RFC5392 & RFC6827
  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
  * http://www.kddlabs.co.jp/
  *
+ * Copyright (C) 2012 Orange Labs
+ * http://www.orange.com
+ *
  * This file is part of GNU Zebra.
  *
  * GNU Zebra is free software; you can redistribute it and/or modify it
  * 02111-1307, USA.
  */
 
+/* Add support of RFC7471 */
+/* Add support of RFC5392 */
+/* Add support of RFC6827 (partial) */
+
 #ifndef _ZEBRA_OSPF_MPLS_TE_H
 #define _ZEBRA_OSPF_MPLS_TE_H
 
@@ -42,6 +49,7 @@
  */
 
 #define        MAX_LEGAL_TE_INSTANCE_NUM (0xffff)
+#define LEGAL_TE_INSTANCE_RANGE(i)  (0 <= (i) && (i) <= 0xffff)
 
 /*
  *        24       16        8        0
  * +--------+--------+--------+--------+ ---
  */
 
+/* Following define the type of TE link regarding the various RFC */
+#define STD_TE         0x01
+#define GMPLS          0x02
+#define INTER_AS       0x04
+#define PSEUDO_TE      0x08
+#define FLOOD_AREA     0x10
+#define FLOOD_AS       0x20
+#define EMULATED       0x80
+
+#define IS_STD_TE(x)           (x & STD_TE)
+#define IS_PSEUDO_TE(x)                (x & PSEUDO_TE)
+#define IS_INTER_AS(x)                 (x & INTER_AS)
+#define IS_EMULATED(x)         (x & EMULATED)
+#define IS_FLOOD_AREA(x)       (x & FLOOD_AREA)
+#define IS_FLOOD_AS(x)         (x & FLOOD_AS)
+#define IS_INTER_AS_EMU(x)     (x & INTER_AS & EMULATED)
+#define IS_INTER_AS_AS(x)      (x & INTER_AS & FLOOD_AS)
+
+/* Flags to manage TE Link LSA */
+#define LPFLG_LSA_INACTIVE             0x0
+#define LPFLG_LSA_ACTIVE               0x1
+#define LPFLG_LSA_ENGAGED              0x2
+#define LPFLG_LOOKUP_DONE              0x4
+#define LPFLG_LSA_FORCED_REFRESH       0x8
+
 /*
  * Following section defines TLV (tag, length, value) structures,
  * used for Traffic Engineering.
@@ -87,10 +120,18 @@ struct te_tlv_header
 #define TLV_HDR_NEXT(tlvh) \
        (struct te_tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
 
+#define TLV_HDR_SUBTLV(tlvh) \
+       (struct te_tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE)
+
+#define TLV_TYPE(tlvh)     tlvh.header.type
+#define TLV_LEN(tlvh)      tlvh.header.length
+#define TLV_HDR(tlvh)      tlvh.header
+
+
 /*
  * Following section defines TLV body parts.
  */
-/* Router Address TLV *//* Mandatory */
+/* Router Address TLV */ /* Mandatory */
 #define        TE_TLV_ROUTER_ADDR              1
 struct te_tlv_router_addr
 {
@@ -106,12 +147,16 @@ struct te_tlv_link
   /* A set of link-sub-TLVs will follow. */
 };
 
-/* Link Type Sub-TLV *//* Mandatory */
-#define        TE_LINK_SUBTLV_LINK_TYPE                1
+#define TE_LINK_SUBTLV_DEF_SIZE                4
+
+/* Link Type Sub-TLV */ /* Mandatory */
+#define        TE_LINK_SUBTLV_LINK_TYPE        1
+#define TE_LINK_SUBTLV_TYPE_SIZE       1
 struct te_link_subtlv_link_type
 {
   struct te_tlv_header header;         /* Value length is 1 octet. */
-  struct {
+  struct
+  {
 #define        LINK_TYPE_SUBTLV_VALUE_PTP      1
 #define        LINK_TYPE_SUBTLV_VALUE_MA       2
       u_char   value;
@@ -119,75 +164,303 @@ struct te_link_subtlv_link_type
   } link_type;
 };
 
-/* Link Sub-TLV: Link ID *//* Mandatory */
-#define        TE_LINK_SUBTLV_LINK_ID                  2
+/* Link Sub-TLV: Link ID */ /* Mandatory */
+#define        TE_LINK_SUBTLV_LINK_ID          2
 struct te_link_subtlv_link_id
 {
   struct te_tlv_header header;         /* Value length is 4 octets. */
   struct in_addr       value;          /* Same as router-lsa's link-id. */
 };
 
-/* Link Sub-TLV: Local Interface IP Address *//* Optional */
-#define        TE_LINK_SUBTLV_LCLIF_IPADDR             3
+/* Link Sub-TLV: Local Interface IP Address */ /* Optional */
+#define        TE_LINK_SUBTLV_LCLIF_IPADDR     3
 struct te_link_subtlv_lclif_ipaddr
 {
   struct te_tlv_header header;         /* Value length is 4 x N octets. */
   struct in_addr       value[1];       /* Local IP address(es). */
 };
 
-/* Link Sub-TLV: Remote Interface IP Address *//* Optional */
-#define        TE_LINK_SUBTLV_RMTIF_IPADDR             4
+/* Link Sub-TLV: Remote Interface IP Address */ /* Optional */
+#define        TE_LINK_SUBTLV_RMTIF_IPADDR     4
 struct te_link_subtlv_rmtif_ipaddr
 {
   struct te_tlv_header header;         /* Value length is 4 x N octets. */
   struct in_addr       value[1];       /* Neighbor's IP address(es). */
 };
 
-/* Link Sub-TLV: Traffic Engineering Metric *//* Optional */
-#define        TE_LINK_SUBTLV_TE_METRIC                5
+/* Link Sub-TLV: Traffic Engineering Metric */ /* Optional */
+#define        TE_LINK_SUBTLV_TE_METRIC        5
 struct te_link_subtlv_te_metric
 {
   struct te_tlv_header header;         /* Value length is 4 octets. */
   u_int32_t            value;          /* Link metric for TE purpose. */
 };
 
-/* Link Sub-TLV: Maximum Bandwidth *//* Optional */
-#define        TE_LINK_SUBTLV_MAX_BW                   6
+/* Link Sub-TLV: Maximum Bandwidth */ /* Optional */
+#define        TE_LINK_SUBTLV_MAX_BW           6
 struct te_link_subtlv_max_bw
 {
   struct te_tlv_header header;         /* Value length is 4 octets. */
   float                        value;          /* bytes/sec */
 };
 
-/* Link Sub-TLV: Maximum Reservable Bandwidth *//* Optional */
-#define        TE_LINK_SUBTLV_MAX_RSV_BW               7
+/* Link Sub-TLV: Maximum Reservable Bandwidth */ /* Optional */
+#define        TE_LINK_SUBTLV_MAX_RSV_BW       7
 struct te_link_subtlv_max_rsv_bw
 {
   struct te_tlv_header header;         /* Value length is 4 octets. */
   float                        value;          /* bytes/sec */
 };
 
-/* Link Sub-TLV: Unreserved Bandwidth *//* Optional */
-#define        TE_LINK_SUBTLV_UNRSV_BW                 8
+/* Link Sub-TLV: Unreserved Bandwidth */ /* Optional */
+#define        TE_LINK_SUBTLV_UNRSV_BW         8
+#define TE_LINK_SUBTLV_UNRSV_SIZE      32
 struct te_link_subtlv_unrsv_bw
 {
   struct te_tlv_header header;         /* Value length is 32 octets. */
-  float                        value[8];       /* One for each priority level. */
+  float                        value[MAX_CLASS_TYPE];  /* One for each priority level. */
 };
 
-/* Link Sub-TLV: Resource Class/Color *//* Optional */
-#define        TE_LINK_SUBTLV_RSC_CLSCLR               9
+/* Link Sub-TLV: Resource Class/Color */ /* Optional */
+#define        TE_LINK_SUBTLV_RSC_CLSCLR       9
 struct te_link_subtlv_rsc_clsclr
 {
   struct te_tlv_header header;         /* Value length is 4 octets. */
   u_int32_t            value;          /* Admin. group membership. */
 };
 
-/* Here are "non-official" architechtual constants. */
+/* For RFC6827 */
+/* Local and Remote TE Router ID */
+#define TE_LINK_SUBTLV_LRRID           10
+#define TE_LINK_SUBTLV_LRRID_SIZE      8
+struct te_link_subtlv_lrrid
+{
+  struct te_tlv_header header;  /* Value length is 8 octets. */
+  struct in_addr local;         /* Local TE Router Identifier */
+  struct in_addr remote;        /* Remote TE Router Identifier */
+};
+
+/* RFC4203: Link Local/Remote Identifiers */
+#define TE_LINK_SUBTLV_LLRI            11
+#define TE_LINK_SUBTLV_LLRI_SIZE       8
+struct te_link_subtlv_llri
+{
+  struct te_tlv_header header;  /* Value length is 8 octets. */
+  u_int32_t local;              /* Link Local Identifier */
+  u_int32_t remote;             /* Link Remote Identifier */
+};
+
+/* Inter-RA Export Upward sub-TLV (12) and Inter-RA Export Downward sub-TLV (13) (RFC6827bis) are not yet supported */
+/* SUBTLV 14-16 (RFC4203) are not yet supported */
+/* Bandwidth Constraints sub-TLV (17) (RFC4124) is not yet supported */
+/* SUBLV 18-20 are for OSPFv6 TE (RFC5329). see ospf6d */
+
+/* For RFC 5392 */
+/* Remote AS Number sub-TLV */
+#define TE_LINK_SUBTLV_RAS             21
+struct te_link_subtlv_ras
+{
+  struct te_tlv_header header;  /* Value length is 4 octets. */
+  u_int32_t value;              /* Remote AS number */
+};
+
+/* IPv4 Remote ASBR ID Sub-TLV */
+#define TE_LINK_SUBTLV_RIP             22
+struct te_link_subtlv_rip
+{
+  struct te_tlv_header header;  /* Value length is 4 octets. */
+  struct in_addr value;         /* Remote ASBR IP address */
+};
+
+/* SUBTLV 24 is IPv6 Remote ASBR ID (RFC5392). see ospf6d */
+
+/* SUBTLV 23 (RFC5330) and 25 (RFC6001) are not yet supported */
+
+/* SUBTLV 26 (RFC7308) is not yet supported */
+
+/* RFC7471 */
+/* Link Sub-TLV: Average Link Delay */ /* Optional */
+#define TE_LINK_SUBTLV_AV_DELAY                27
+struct te_link_subtlv_av_delay
+{
+  struct te_tlv_header header;  /* Value length is 4 bytes. */
+  u_int32_t            value;   /* delay in micro-seconds only 24 bits => 0 ... 16777215
+                                   with Anomalous Bit as Upper most bit */
+};
+
+/* Link Sub-TLV: Low/High Link Delay */
+#define TE_LINK_SUBTLV_MM_DELAY         28
+#define TE_LINK_SUBTLV_MM_DELAY_SIZE    8
+struct te_link_subtlv_mm_delay
+{
+  struct te_tlv_header header;  /* Value length is 8 bytes. */
+  u_int32_t            low;     /* low delay in micro-seconds only 24 bits => 0 ... 16777215
+                                   with Anomalous Bit (A) as Upper most bit */
+  u_int32_t            high;    /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */
+};
+
+/* Link Sub-TLV: Link Delay Variation i.e. Jitter */
+#define TE_LINK_SUBTLV_DELAY_VAR       29
+struct te_link_subtlv_delay_var
+{
+  struct te_tlv_header header;  /* Value length is 4 bytes. */
+  u_int32_t            value;   /* interval in micro-seconds only 24 bits => 0 ... 16777215 */
+};
+
+/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */
+#define TE_LINK_SUBTLV_PKT_LOSS                30
+struct te_link_subtlv_pkt_loss
+{
+  struct te_tlv_header header;  /* Value length is 4 bytes. */
+  u_int32_t            value;   /* in percentage of total traffic only 24 bits (2^24 - 2)
+                                   with Anomalous Bit as Upper most bit */
+};
+
+/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */
+#define TE_LINK_SUBTLV_RES_BW          31
+struct te_link_subtlv_res_bw
+{
+  struct te_tlv_header header;  /* Value length is 4 bytes. */
+  float                value;   /* bandwidth in IEEE floating point format with units in bytes per second */
+};
+
+/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */
+#define TE_LINK_SUBTLV_AVA_BW          32
+struct te_link_subtlv_ava_bw
+{
+  struct te_tlv_header header;  /* Value length is 4 octets. */
+  float                value;   /* bandwidth in IEEE floating point format with units in bytes per second */
+};
+
+/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */
+#define TE_LINK_SUBTLV_USE_BW           33
+struct te_link_subtlv_use_bw
+{
+  struct te_tlv_header header;  /* Value length is 4 octets. */
+  float                value;   /* bandwidth in IEEE floating point format with units in bytes per second */
+};
+
+#define TE_LINK_SUBTLV_MAX             34      /* Last SUBTLV + 1 */
+
+/* Here are "non-official" architectural constants. */
 #define MPLS_TE_MINIMUM_BANDWIDTH      1.0     /* Reasonable? *//* XXX */
 
+/* Following declaration concerns the MPLS-TE and LINk-TE management */
+typedef enum _opcode_t
+{ REORIGINATE_THIS_LSA, REFRESH_THIS_LSA, FLUSH_THIS_LSA } opcode_t;
+
+typedef enum _status_t
+{ disabled, enabled } status_t;
+
+/* Mode for Inter-AS Opaque-LSA */
+enum inter_as_mode { Disable, AS, Area };
+
+struct te_link_subtlv
+{
+  struct te_tlv_header header;
+  union
+  {
+    u_int32_t link_type;
+    struct in_addr link_id;
+    struct in_addr lclif;
+    struct in_addr rmtif;
+    u_int32_t te_metric;
+    float max_bw;
+    float max_rsv_bw;
+    float unrsv[8];
+    u_int32_t rsc_clsclr;
+    u_int32_t llri[2];
+    u_int32_t ras;
+    struct in_addr rip;
+    struct in_addr lrrid[2];
+    u_int32_t av_delay;
+    u_int32_t mm_delay;
+    u_int32_t delay_var;
+    u_int32_t pkt_loss;
+    float res_bw;
+    float ava_bw;
+    float use_bw;
+  } value;
+};
+
+/* Following structure are internal use only. */
+struct ospf_mpls_te
+{
+  /* Status of MPLS-TE: enable or disbale */
+  status_t status;
+
+  /* RFC5392 */
+  enum inter_as_mode inter_as;
+  struct in_addr interas_areaid;
+
+  /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
+  struct list *iflist;
+
+  /* Store Router-TLV in network byte order. */
+  struct te_tlv_router_addr router_addr;
+};
+
+struct mpls_te_link
+{
+  /*
+   * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
+   * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
+   * In this implementation, each Link-TLV has its own instance.
+   */
+  u_int32_t instance;
+
+  /* Reference pointer to a Zebra-interface. */
+  struct interface *ifp;
+
+  /* Area info in which this MPLS-TE link belongs to. */
+  struct ospf_area *area;
+
+  /* Flags to manage this link parameters. */
+  u_int32_t flags;
+
+  /* Type of MPLS-TE link: RFC3630, RFC5392, RFC5392 emulated, RFC6827 */
+  u_int8_t type;
+
+  /* Store Link-TLV in network byte order. */
+  /* RFC3630 & RFC6827 / RFC 6827 */
+  struct te_tlv_link link_header;
+  struct te_link_subtlv_link_type link_type;
+  struct te_link_subtlv_link_id link_id;
+  struct te_link_subtlv_lclif_ipaddr lclif_ipaddr;
+  struct te_link_subtlv_rmtif_ipaddr rmtif_ipaddr;
+  struct te_link_subtlv_te_metric te_metric;
+  struct te_link_subtlv_max_bw max_bw;
+  struct te_link_subtlv_max_rsv_bw max_rsv_bw;
+  struct te_link_subtlv_unrsv_bw unrsv_bw;
+  struct te_link_subtlv_rsc_clsclr rsc_clsclr;
+  /* RFC4203 */
+  struct te_link_subtlv_llri llri;
+  /* RFC5392 */
+  struct te_link_subtlv_ras ras;
+  struct te_link_subtlv_rip rip;
+  /* RFC6827 */
+  struct te_link_subtlv_lrrid lrrid;
+  /* RFC7471 */
+  struct te_link_subtlv_av_delay av_delay;
+  struct te_link_subtlv_mm_delay mm_delay;
+  struct te_link_subtlv_delay_var delay_var;
+  struct te_link_subtlv_pkt_loss pkt_loss;
+  struct te_link_subtlv_res_bw res_bw;
+  struct te_link_subtlv_ava_bw ava_bw;
+  struct te_link_subtlv_use_bw use_bw;
+
+  struct in_addr adv_router;
+  struct in_addr id;
+};
+
 /* Prototypes. */
 extern int ospf_mpls_te_init (void);
 extern void ospf_mpls_te_term (void);
+extern struct ospf_mpls_te *get_ospf_mpls_te (void);
+extern void ospf_mpls_te_update_if (struct interface *);
+extern void ospf_mpls_te_lsa_schedule (struct mpls_te_link *, opcode_t);
+extern u_int32_t get_mpls_te_instance_value (void);
+extern void set_linkparams_llri (struct mpls_te_link *, u_int32_t, u_int32_t);
+extern void set_linkparams_lrrid (struct mpls_te_link *, struct in_addr, struct in_addr);
 
 #endif /* _ZEBRA_OSPF_MPLS_TE_H */
index 3022a316c68ea13032f77efa2d7b4160a82e8f8c..264249b4c0f571c337b39fdbce40f0fc35f41c6b 100644 (file)
@@ -64,7 +64,7 @@ static const char *ospf_network_type_str[] =
 };
 
 /* Utility functions. */
-static int
+int
 ospf_str2area_id (const char *str, struct in_addr *area_id, int *format)
 {
   char *endptr = NULL;
index 28bb419af841fa0881d79f80e6dd7c3d7b8a3092..429ac318f7ad9aea5a1992a7c7557fdcd5951e87 100644 (file)
@@ -54,5 +54,6 @@
 extern void ospf_vty_init (void);
 extern void ospf_vty_show_init (void);
 extern void ospf_vty_clear_init (void);
+extern int ospf_str2area_id (const char *, struct in_addr *, int *);
 
 #endif /* _QUAGGA_OSPF_VTY_H */
index a31ef5f7071d323e66e6e29fd2d7320c41edcaab..c0b94a33604c5420f06438544aa1469a32f003cb 100644 (file)
@@ -53,6 +53,7 @@
 #ifdef HAVE_SNMP
 #include "ospfd/ospf_snmp.h"
 #endif /* HAVE_SNMP */
+#include "ospfd/ospf_te.h"
 
 /* Zebra structure to hold current status. */
 struct zclient *zclient = NULL;
@@ -331,6 +332,24 @@ ospf_interface_address_delete (int command, struct zclient *zclient,
   return 0;
 }
 
+static int
+ospf_interface_link_params (int command, struct zclient *zclient,
+                        zebra_size_t length)
+{
+  struct interface *ifp;
+
+  ifp = zebra_interface_link_params_read (zclient->ibuf);
+
+  if (ifp == NULL)
+    return 0;
+
+  /* Update TE TLV */
+  ospf_mpls_te_update_if (ifp);
+
+  return 0;
+}
+
+
 void
 ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
 {
@@ -1580,6 +1599,8 @@ ospf_zebra_init (struct thread_master *master, u_short instance)
   zclient->interface_down = ospf_interface_state_down;
   zclient->interface_address_add = ospf_interface_address_add;
   zclient->interface_address_delete = ospf_interface_address_delete;
+  zclient->interface_link_params = ospf_interface_link_params;
+
   zclient->ipv4_route_add = ospf_zebra_read_ipv4;
   zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
   zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
index 9d0e4b9e87a2185553208400a838a0ab9db3ae20..7156c1edac62f64063291e60799300b9d089e932 100644 (file)
@@ -305,7 +305,7 @@ ospf_lookup ()
   if (listcount (om->ospf) == 0)
     return NULL;
 
-  return listgetdata (listhead (om->ospf));
+  return listgetdata ((struct listnode *)listhead (om->ospf));
 }
 
 struct ospf *
index 5f0a7bf1130eeca95b6754781e20febe067347d4..af238c53aefb410161042210495f82de45cfe2f3 100644 (file)
 #define OSPF_AUTH_CMD_NOTSEEN              -2
 
 /* OSPF options. */
-#define OSPF_OPTION_T                    0x01  /* TOS. */
+#define OSPF_OPTION_MT                   0x01  /* M/T */
 #define OSPF_OPTION_E                    0x02
 #define OSPF_OPTION_MC                   0x04
 #define OSPF_OPTION_NP                   0x08
 #define OSPF_OPTION_EA                   0x10
 #define OSPF_OPTION_DC                   0x20
 #define OSPF_OPTION_O                    0x40
+#define OSPF_OPTION_DN                   0x80
 
 /* OSPF Database Description flags. */
 #define OSPF_DD_FLAG_MS                  0x01
index a7b78bd7b90733756d06b98f7b1f045655ee407e..4ead72221341e378c619cbe71d871183eb55115e 100755 (executable)
@@ -36,6 +36,7 @@ EOF
 $ignore{'"interface IFNAME"'} = "ignore";
 $ignore{'"interface IFNAME " "vrf <0-65535>"'} = "ignore";
 $ignore{'"interface IFNAME " "vrf NAME"'} = "ignore";
+$ignore{'"link-params"'} = "ignore";
 $ignore{'"vrf NAME"'} = "ignore";
 $ignore{'"ip vrf NAME"'} = "ignore";
 $ignore{'"router rip"'} = "ignore";
index 7241455cd1d9e84f1bd469fd9e96481b7974ea70..5cf27facb87405f588e26b1aef158cecb84c674b 100644 (file)
@@ -1032,6 +1032,12 @@ static struct cmd_node keychain_key_node =
   "%s(config-keychain-key)# "
 };
 
+struct cmd_node link_params_node =
+{
+  LINK_PARAMS_NODE,
+  "%s(config-link-params)# ",
+};
+
 /* Defined in lib/vty.c */
 extern struct cmd_node vty_node;
 
@@ -1414,6 +1420,9 @@ vtysh_exit (struct vty *vty)
     case KEYCHAIN_KEY_NODE:
       vty->node = KEYCHAIN_NODE;
       break;
+    case LINK_PARAMS_NODE:
+      vty->node = INTERFACE_NODE;
+      break;
     default:
       break;
     }
@@ -1746,6 +1755,17 @@ DEFUN (vtysh_show_work_queues_daemon,
   return ret;
 }
 
+DEFUNSH (VTYSH_ZEBRA,
+         vtysh_link_params,
+         vtysh_link_params_cmd,
+         "link-params",
+         LINK_PARAMS_STR
+         )
+{
+  vty->node = LINK_PARAMS_NODE;
+  return CMD_SUCCESS;
+}
+
 /* Memory */
 DEFUN (vtysh_show_memory,
        vtysh_show_memory_cmd,
@@ -2843,6 +2863,7 @@ vtysh_init_vty (void)
   install_node (&bgp_node, NULL);
   install_node (&rip_node, NULL);
   install_node (&interface_node, NULL);
+  install_node (&link_params_node, NULL);
   install_node (&vrf_node, NULL);
   install_node (&rmap_node, NULL);
   install_node (&zebra_node, NULL);
@@ -2872,6 +2893,7 @@ vtysh_init_vty (void)
   vtysh_install_default (BGP_NODE);
   vtysh_install_default (RIP_NODE);
   vtysh_install_default (INTERFACE_NODE);
+  vtysh_install_default (LINK_PARAMS_NODE);
   vtysh_install_default (VRF_NODE);
   vtysh_install_default (RMAP_NODE);
   vtysh_install_default (ZEBRA_NODE);
@@ -2965,6 +2987,8 @@ vtysh_init_vty (void)
   install_element (INTERFACE_NODE, &no_interface_desc_cmd);
   install_element (INTERFACE_NODE, &vtysh_end_all_cmd);
   install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd);
+  install_element (LINK_PARAMS_NODE, &vtysh_end_all_cmd);
+  install_element (LINK_PARAMS_NODE, &vtysh_exit_interface_cmd);
   install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd);
 
   install_element (VRF_NODE, &vtysh_end_all_cmd);
@@ -3015,6 +3039,7 @@ vtysh_init_vty (void)
   install_element (CONFIG_NODE, &vtysh_no_interface_cmd);
   install_element (CONFIG_NODE, &vtysh_interface_vrf_cmd);
   install_element (CONFIG_NODE, &vtysh_no_interface_vrf_cmd);
+  install_element (INTERFACE_NODE, &vtysh_link_params_cmd);
   install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
   install_element (ENABLE_NODE, &vtysh_show_running_config_daemon_cmd);
   install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
index 36270ac42550ca0b7d4cea77723076f38e768fac..2b1e6f4ac624c62f5ce206ef1242963b2011d7a5 100644 (file)
@@ -281,7 +281,7 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)
       /* If deleted address is primary, mark subsequent one as such and distribute. */
       if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
        {
-         ifc = listgetdata (listhead (addr_list));
+         ifc = listgetdata ((struct listnode *)listhead (addr_list));
          zebra_interface_address_delete_update (ifp, ifc);
          UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
          /* XXX: Linux kernel removes all the secondary addresses when the primary
@@ -1074,7 +1074,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp)
     {
       if (! rn->info)
        continue;
-      
+
       for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
         connected_dump_vty (vty, connected);
     }
@@ -1086,6 +1086,53 @@ if_dump_vty (struct vty *vty, struct interface *ifp)
        connected_dump_vty (vty, connected);
     }
 
+  if (HAS_LINK_PARAMS(ifp))
+    {
+      int i;
+      struct if_link_params *iflp = ifp->link_params;
+      vty_out(vty, "  Traffic Engineering Link Parameters:%s", VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_TE))
+        vty_out(vty, "    TE metric %u%s",iflp->te_metric, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_MAX_BW))
+        vty_out(vty, "    Maximum Bandwidth %g (Byte/s)%s", iflp->max_bw, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
+        vty_out(vty, "    Maximum Reservable Bandwidth %g (Byte/s)%s", iflp->max_rsv_bw, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
+        vty_out(vty, "    Unreserved Bandwidth per Class Type in Byte/s:%s", VTY_NEWLINE);
+        for (i = 0; i < MAX_CLASS_TYPE; i+=2)
+          vty_out(vty, "      [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s",
+                  i, iflp->unrsv_bw[i], i+1, iflp->unrsv_bw[i+1], VTY_NEWLINE);
+      }
+
+      if (IS_PARAM_SET(iflp, LP_ADM_GRP))
+        vty_out(vty, "    Administrative Group:%u%s", iflp->admin_grp, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_DELAY))
+        {
+          vty_out(vty, "    Link Delay Average: %u (micro-sec.)", iflp->av_delay);
+          if (IS_PARAM_SET(iflp, LP_MM_DELAY))
+            {
+              vty_out(vty, " Min:  %u (micro-sec.)", iflp->min_delay);
+              vty_out(vty, " Max:  %u (micro-sec.)", iflp->max_delay);
+            }
+          vty_out(vty, "%s", VTY_NEWLINE);
+        }
+      if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
+        vty_out(vty, "    Link Delay Variation %u (micro-sec.)%s", iflp->delay_var, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
+        vty_out(vty, "    Link Packet Loss %g (in %%)%s", iflp->pkt_loss, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_AVA_BW))
+        vty_out(vty, "    Available Bandwidth %g (Byte/s)%s", iflp->ava_bw, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_RES_BW))
+        vty_out(vty, "    Residual Bandwidth %g (Byte/s)%s", iflp->res_bw, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_USE_BW))
+        vty_out(vty, "    Utilized Bandwidth %g (Byte/s)%s", iflp->use_bw, VTY_NEWLINE);
+      if (IS_PARAM_SET(iflp, LP_RMT_AS))
+        vty_out(vty, "    Neighbor ASBR IP: %s AS: %u %s", inet_ntoa(iflp->rmt_ip), iflp->rmt_as, VTY_NEWLINE);
+    }
+
+ #ifdef RTADV
+   nd_dump_vty (vty, ifp);
+ #endif /* RTADV */
 #if defined (HAVE_RTADV)
   nd_dump_vty (vty, ifp);
 #endif /* HAVE_RTADV */
@@ -1185,13 +1232,13 @@ DEFUN_NOSH (zebra_interface,
            "Interface's name\n")
 {
   int ret;
-  struct interface * ifp;
+  struct interface *ifp;
   
   /* Call lib interface() */
   if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
     return ret;
 
-  ifp = vty->index;  
+  ifp = vty->index;
 
   if (ifp->ifindex == IFINDEX_INTERNAL)
     /* Is this really necessary?  Shouldn't status be initialized to 0
@@ -1690,6 +1737,692 @@ ALIAS (no_bandwidth_if,
        "Set bandwidth informational parameter\n"
        "Bandwidth in megabits\n")
 
+struct cmd_node link_params_node =
+{
+  LINK_PARAMS_NODE,
+  "%s(config-link-params)# ",
+  1,
+};
+
+static void
+link_param_cmd_set_uint32 (struct interface *ifp, uint32_t *field,
+                           uint32_t type, uint32_t value)
+{
+  /* Update field as needed */
+  if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value)
+    {
+      *field = value;
+      SET_PARAM(ifp->link_params, type);
+
+      /* force protocols to update LINK STATE due to parameters change */
+      if (if_is_operative (ifp))
+        zebra_interface_parameters_update (ifp);
+    }
+}
+static void
+link_param_cmd_set_float (struct interface *ifp, float *field,
+                          uint32_t type, float value)
+{
+
+  /* Update field as needed */
+  if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value)
+    {
+      *field = value;
+      SET_PARAM(ifp->link_params, type);
+
+      /* force protocols to update LINK STATE due to parameters change */
+      if (if_is_operative (ifp))
+        zebra_interface_parameters_update (ifp);
+    }
+}
+
+static void
+link_param_cmd_unset (struct interface *ifp, uint32_t type)
+{
+
+  /* Unset field */
+  UNSET_PARAM(ifp->link_params, type);
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+}
+
+DEFUN (link_params,
+       link_params_cmd,
+       "link-params",
+       LINK_PARAMS_STR)
+{
+  vty->node = LINK_PARAMS_NODE;
+
+  return CMD_SUCCESS;
+}
+
+/* Specific Traffic Engineering parameters commands */
+DEFUN (link_params_enable,
+       link_params_enable_cmd,
+       "enable",
+       "Activate link parameters on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* This command could be issue at startup, when activate MPLS TE */
+  /* on a new interface or after a ON / OFF / ON toggle */
+  /* In all case, TE parameters are reset to their default factory */
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug ("Link-params: enable TE link parameters on interface %s", ifp->name);
+
+  if (!if_link_params_get (ifp))
+    {
+      if (IS_ZEBRA_DEBUG_EVENT)
+        zlog_debug ("Link-params: failed to init TE link parameters  %s", ifp->name);
+
+      return CMD_WARNING;
+    }
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_enable,
+       no_link_params_enable_cmd,
+       "no enable",
+       NO_STR
+       "Disable link parameters on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  zlog_debug ("MPLS-TE: disable TE link parameters on interface %s", ifp->name);
+
+  if_link_params_free (ifp);
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+
+  return CMD_SUCCESS;
+}
+
+/* STANDARD TE metrics */
+DEFUN (link_params_metric,
+       link_params_metric_cmd,
+       "metric <0-4294967295>",
+       "Link metric for MPLS-TE purpose\n"
+       "Metric value in decimal\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  u_int32_t metric;
+
+  VTY_GET_ULONG("metric", metric, argv[0]);
+
+  /* Update TE metric if needed */
+  link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE, metric);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_metric,
+       no_link_params_metric_cmd,
+       "no metric",
+       NO_STR
+       "Disbale Link Metric on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset TE Metric */
+  link_param_cmd_unset(ifp, LP_TE);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_maxbw,
+       link_params_maxbw_cmd,
+       "max-bw BANDWIDTH",
+       "Maximum bandwidth that can be used\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+
+  float bw;
+
+  if (sscanf (argv[0], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_maxbw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that Maximum bandwidth is not lower than other bandwidth parameters */
+  if ((bw <= iflp->max_rsv_bw)
+      || (bw <= iflp->unrsv_bw[0])
+      || (bw <= iflp->unrsv_bw[1])
+      || (bw <= iflp->unrsv_bw[2])
+      || (bw <= iflp->unrsv_bw[3])
+      || (bw <= iflp->unrsv_bw[4])
+      || (bw <= iflp->unrsv_bw[5])
+      || (bw <= iflp->unrsv_bw[6])
+      || (bw <= iflp->unrsv_bw[7])
+      || (bw <= iflp->ava_bw)
+      || (bw <= iflp->res_bw)
+      || (bw <= iflp->use_bw))
+    {
+      vty_out (vty,
+               "Maximum Bandwidth could not be lower than others bandwidth%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Maximum Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->max_bw, LP_MAX_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_max_rsv_bw,
+       link_params_max_rsv_bw_cmd,
+       "max-rsv-bw BANDWIDTH",
+       "Maximum bandwidth that may be reserved\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  float bw;
+
+  if (sscanf (argv[0], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_max_rsv_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that bandwidth is not greater than maximum bandwidth parameter */
+  if (bw > iflp->max_bw)
+    {
+      vty_out (vty,
+               "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)%s",
+               iflp->max_bw, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Maximum Reservable Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_unrsv_bw,
+       link_params_unrsv_bw_cmd,
+       "unrsv-bw <0-7> BANDWIDTH",
+       "Unreserved bandwidth at each priority level\n"
+       "Priority\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  int priority;
+  float bw;
+
+  /* We don't have to consider about range check here. */
+  if (sscanf (argv[0], "%d", &priority) != 1)
+    {
+      vty_out (vty, "link_params_unrsv_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (sscanf (argv[1], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_unrsv_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that bandwidth is not greater than maximum bandwidth parameter */
+  if (bw > iflp->max_bw)
+    {
+      vty_out (vty,
+               "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)%s",
+               iflp->max_bw, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Unreserved Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_admin_grp,
+       link_params_admin_grp_cmd,
+       "admin-grp BITPATTERN",
+       "Administrative group membership\n"
+       "32-bit Hexadecimal value (e.g. 0xa1)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  unsigned long value;
+
+  if (sscanf (argv[0], "0x%lx", &value) != 1)
+    {
+      vty_out (vty, "link_params_admin_grp: fscanf: %s%s",
+               safe_strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Administrative Group if needed */
+  link_param_cmd_set_uint32 (ifp, &iflp->admin_grp, LP_ADM_GRP, value);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_admin_grp,
+       no_link_params_admin_grp_cmd,
+       "no admin-grp",
+       NO_STR
+       "Disbale Administrative group membership on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Admin Group */
+  link_param_cmd_unset(ifp, LP_ADM_GRP);
+
+  return CMD_SUCCESS;
+}
+
+/* RFC5392 & RFC5316: INTER-AS */
+DEFUN (link_params_inter_as,
+       link_params_inter_as_cmd,
+       "neighbor A.B.C.D as <1-4294967295>",
+       "Configure remote ASBR information (Neighbor IP address and AS number)\n"
+       "Remote IP address in dot decimal A.B.C.D\n"
+       "Remote AS number\n"
+       "AS number in the range <1-4294967295>\n")
+{
+
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  struct in_addr addr;
+  u_int32_t as;
+
+  if (!inet_aton (argv[0], &addr))
+    {
+      vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  VTY_GET_ULONG("AS number", as, argv[1]);
+
+  /* Update Remote IP and Remote AS fields if needed */
+  if (IS_PARAM_UNSET(iflp, LP_RMT_AS)
+      || iflp->rmt_as != as
+      || iflp->rmt_ip.s_addr != addr.s_addr)
+    {
+
+      iflp->rmt_as = as;
+      iflp->rmt_ip.s_addr = addr.s_addr;
+      SET_PARAM(iflp, LP_RMT_AS);
+
+      /* force protocols to update LINK STATE due to parameters change */
+      if (if_is_operative (ifp))
+        zebra_interface_parameters_update (ifp);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_inter_as,
+       no_link_params_inter_as_cmd,
+       "no neighbor",
+       NO_STR
+       "Remove Neighbor IP address and AS number for Inter-AS TE\n")
+{
+
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+
+  /* Reset Remote IP and AS neighbor */
+  iflp->rmt_as = 0;
+  iflp->rmt_ip.s_addr = 0;
+  UNSET_PARAM(iflp, LP_RMT_AS);
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+
+  return CMD_SUCCESS;
+}
+
+/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & draft-ietf-isis-metric-extensions-07.txt */
+DEFUN (link_params_delay,
+       link_params_delay_cmd,
+       "delay <0-16777215>",
+       "Unidirectional Average Link Delay\n"
+       "Average delay in micro-second as decimal (0...16777215)\n")
+{
+
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  u_int32_t delay = 0, low = 0, high = 0;
+  u_int8_t update = 0;
+
+  /* Get and Check new delay values */
+  VTY_GET_ULONG("delay", delay, argv[0]);
+  switch (argc)
+    {
+    case 1:
+      /* Check new delay value against old Min and Max delays if set */
+      if (IS_PARAM_SET(iflp, LP_MM_DELAY)
+          && (delay <= iflp->min_delay || delay >= iflp->max_delay))
+        {
+          vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay%s",
+                   iflp->min_delay, iflp->max_delay, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+      /* Update delay if value is not set or change */
+      if (IS_PARAM_UNSET(iflp, LP_DELAY)|| iflp->av_delay != delay)
+        {
+          iflp->av_delay = delay;
+          SET_PARAM(iflp, LP_DELAY);
+          update = 1;
+        }
+      /* Unset Min and Max delays if already set */
+      if (IS_PARAM_SET(iflp, LP_MM_DELAY))
+        {
+          iflp->min_delay = 0;
+          iflp->max_delay = 0;
+          UNSET_PARAM(iflp, LP_MM_DELAY);
+          update = 1;
+        }
+      break;
+    case 2:
+      vty_out (vty, "You should specify both Minimum and Maximum delay with Average delay%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    break;
+    case 3:
+      VTY_GET_ULONG("minimum delay", low, argv[1]);
+      VTY_GET_ULONG("maximum delay", high, argv[2]);
+      /* Check new delays value coherency */
+      if (delay <= low || delay >= high)
+        {
+          vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay%s",
+                   low, high, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+      /* Update Delays if needed */
+      if (IS_PARAM_UNSET(iflp, LP_DELAY)
+          || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
+          || iflp->av_delay != delay
+          || iflp->min_delay != low
+          || iflp->max_delay != high)
+        {
+          iflp->av_delay = delay;
+          SET_PARAM(iflp, LP_DELAY);
+          iflp->min_delay = low;
+          iflp->max_delay = high;
+          SET_PARAM(iflp, LP_MM_DELAY);
+          update = 1;
+        }
+      break;
+    default:
+      return CMD_WARNING;
+      break;
+    }
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (update == 1 && if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (link_params_delay,
+       link_params_delay_mm_cmd,
+       "delay <0-16777215> min <0-16777215> max <0-16777215>",
+       "Unidirectional Average Link Delay (optionally Minimum and Maximum delays)\n"
+       "Average delay in micro-second as decimal (0...16777215)\n"
+       "Minimum delay\n"
+       "Minimum delay in micro-second as decimal (0...16777215)\n"
+       "Maximum delay\n"
+       "Maximum delay in micro-second as decimal (0...16777215)\n")
+
+DEFUN (no_link_params_delay,
+       no_link_params_delay_cmd,
+       "no delay",
+       NO_STR
+       "Disbale Unidirectional Average, Min & Max Link Delay on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+
+  /* Unset Delays */
+  iflp->av_delay = 0;
+  UNSET_PARAM(iflp, LP_DELAY);
+  iflp->min_delay = 0;
+  iflp->max_delay = 0;
+  UNSET_PARAM(iflp, LP_MM_DELAY);
+
+  /* force protocols to update LINK STATE due to parameters change */
+  if (if_is_operative (ifp))
+    zebra_interface_parameters_update (ifp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_delay_var,
+       link_params_delay_var_cmd,
+       "delay-variation <0-16777215>",
+       "Unidirectional Link Delay Variation\n"
+       "delay variation in micro-second as decimal (0...16777215)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  u_int32_t value;
+
+  VTY_GET_ULONG("delay variation", value, argv[0]);
+
+  /* Update Delay Variation if needed */
+  link_param_cmd_set_uint32 (ifp, &iflp->delay_var, LP_DELAY_VAR, value);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_delay_var,
+       no_link_params_delay_var_cmd,
+       "no delay-variation",
+       NO_STR
+       "Disbale Unidirectional Delay Variation on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Delay Variation */
+  link_param_cmd_unset(ifp, LP_DELAY_VAR);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_pkt_loss,
+       link_params_pkt_loss_cmd,
+       "packet-loss PERCENTAGE",
+       "Unidirectional Link Packet Loss\n"
+       "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  float fval;
+
+  if (sscanf (argv[0], "%g", &fval) != 1)
+    {
+      vty_out (vty, "link_params_pkt_loss: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (fval > MAX_PKT_LOSS)
+    fval = MAX_PKT_LOSS;
+
+  /* Update Packet Loss if needed */
+  link_param_cmd_set_float (ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_pkt_loss,
+       no_link_params_pkt_loss_cmd,
+       "no packet-loss",
+       NO_STR
+       "Disbale Unidirectional Link Packet Loss on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Packet Loss */
+  link_param_cmd_unset(ifp, LP_PKT_LOSS);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_res_bw,
+       link_params_res_bw_cmd,
+       "res-bw BANDWIDTH",
+       "Unidirectional Residual Bandwidth\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  float bw;
+
+  if (sscanf (argv[0], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_res_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that bandwidth is not greater than maximum bandwidth parameter */
+  if (bw > iflp->max_bw)
+    {
+      vty_out (vty,
+               "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)%s",
+               iflp->max_bw, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Residual Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->res_bw, LP_RES_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_res_bw,
+       no_link_params_res_bw_cmd,
+       "no res-bw",
+       NO_STR
+       "Disbale Unidirectional Residual Bandwidth on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Residual Bandwidth */
+  link_param_cmd_unset(ifp, LP_RES_BW);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_ava_bw,
+       link_params_ava_bw_cmd,
+       "ava-bw BANDWIDTH",
+       "Unidirectional Available Bandwidth\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  float bw;
+
+  if (sscanf (argv[0], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_ava_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that bandwidth is not greater than maximum bandwidth parameter */
+  if (bw > iflp->max_bw)
+    {
+      vty_out (vty,
+               "Available Bandwidth could not be greater than Maximum Bandwidth (%g)%s",
+               iflp->max_bw, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Residual Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->ava_bw, LP_AVA_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_ava_bw,
+       no_link_params_ava_bw_cmd,
+       "no ava-bw",
+       NO_STR
+       "Disbale Unidirectional Available Bandwidth on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Available Bandwidth */
+  link_param_cmd_unset(ifp, LP_AVA_BW);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (link_params_use_bw,
+       link_params_use_bw_cmd,
+       "use-bw BANDWIDTH",
+       "Unidirectional Utilised Bandwidth\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct if_link_params *iflp = if_link_params_get (ifp);
+  float bw;
+
+  if (sscanf (argv[0], "%g", &bw) != 1)
+    {
+      vty_out (vty, "link_params_use_bw: fscanf: %s%s", safe_strerror (errno),
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check that bandwidth is not greater than maximum bandwidth parameter */
+  if (bw > iflp->max_bw)
+    {
+      vty_out (vty,
+               "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)%s",
+               iflp->max_bw, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Update Utilized Bandwidth if needed */
+  link_param_cmd_set_float (ifp, &iflp->use_bw, LP_USE_BW, bw);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_link_params_use_bw,
+       no_link_params_use_bw_cmd,
+       "no use-bw",
+       NO_STR
+       "Disbale Unidirectional Utilised Bandwidth on this interface\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  /* Unset Utilised Bandwidth */
+  link_param_cmd_unset(ifp, LP_USE_BW);
+
+  return CMD_SUCCESS;
+}
+
 static int
 ip_address_install (struct vty *vty, struct interface *ifp,
                    const char *addr_str, const char *peer_str,
@@ -2054,6 +2787,58 @@ DEFUN (no_ipv6_address,
 }
 #endif /* HAVE_IPV6 */
 
+static int
+link_params_config_write (struct vty *vty, struct interface *ifp)
+{
+  int i;
+
+  if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
+    return -1;
+
+  struct if_link_params *iflp = ifp->link_params;
+
+  vty_out (vty, " link-params%s", VTY_NEWLINE);
+  vty_out(vty, "  enable%s", VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_TE))
+    vty_out(vty, "  metric %u%s",iflp->te_metric, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_MAX_BW))
+    vty_out(vty, "  max-bw %g%s", iflp->max_bw, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
+    vty_out(vty, "  max-rsv-bw %g%s", iflp->max_rsv_bw, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_UNRSV_BW))
+    {
+      for (i = 0; i < 8; i++)
+        vty_out(vty, "  unrsv-bw %d %g%s",
+            i, iflp->unrsv_bw[i], VTY_NEWLINE);
+    }
+  if (IS_PARAM_SET(iflp, LP_ADM_GRP))
+    vty_out(vty, "  admin-grp %u%s", iflp->admin_grp, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_DELAY))
+    {
+      vty_out(vty, "  delay %u", iflp->av_delay);
+      if (IS_PARAM_SET(iflp, LP_MM_DELAY))
+        {
+          vty_out(vty, " min %u", iflp->min_delay);
+          vty_out(vty, " max %u", iflp->max_delay);
+        }
+      vty_out(vty, "%s", VTY_NEWLINE);
+    }
+  if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
+    vty_out(vty, "  delay-variation %u%s", iflp->delay_var, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
+    vty_out(vty, "  packet-loss %g%s", iflp->pkt_loss, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_AVA_BW))
+    vty_out(vty, "  ava-bw %g%s", iflp->ava_bw, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_RES_BW))
+    vty_out(vty, "  res-bw %g%s", iflp->res_bw, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_USE_BW))
+    vty_out(vty, "  use-bw %g%s", iflp->use_bw, VTY_NEWLINE);
+  if (IS_PARAM_SET(iflp, LP_RMT_AS))
+    vty_out(vty, "  neighbor %s as %u%s", inet_ntoa(iflp->rmt_ip),
+        iflp->rmt_as, VTY_NEWLINE);
+  return 0;
+}
+
 static int
 if_config_write (struct vty *vty)
 {
@@ -2134,6 +2919,8 @@ if_config_write (struct vty *vty)
       irdp_config_write (vty, ifp);
 #endif /* IRDP */
 
+      link_params_config_write (vty, ifp);
+
       vty_out (vty, "!%s", VTY_NEWLINE);
     }
   return 0;
@@ -2166,6 +2953,7 @@ zebra_if_init (void)
   
   /* Install configuration write function. */
   install_node (&interface_node, if_config_write);
+  install_node (&link_params_node, NULL);
   install_node (&vrf_node, vrf_config_write);
 
   install_element (VIEW_NODE, &show_interface_cmd);
@@ -2209,9 +2997,26 @@ zebra_if_init (void)
   install_element (INTERFACE_NODE, &ip_address_label_cmd);
   install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
 #endif /* HAVE_NETLINK */
-  
+  install_element(INTERFACE_NODE, &link_params_cmd);
+  install_default(LINK_PARAMS_NODE);
+  install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
+  install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
+  install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_delay_mm_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
+  install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
+
   install_element (CONFIG_NODE, &zebra_vrf_cmd);
   install_element (CONFIG_NODE, &no_vrf_cmd);
   install_default (VRF_NODE);
-
 }
index 2864e0b8a50d195eb1839906b20de0b35cb8bfa7..fb9fa0216abdf8ba50e2c13edfc95dedf0ef33ad 100644 (file)
@@ -385,9 +385,11 @@ zebra_interface_up_update (struct interface *ifp)
 
   if (ifp->ptm_status || !ifp->ptm_enable) {
     for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
-      {
-       zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
-      }
+      if (client->ifinfo)
+       {
+         zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
+         zsend_interface_link_params (client, ifp);
+       }
   }
 }
 
@@ -418,10 +420,12 @@ zebra_interface_add_update (struct interface *ifp)
     zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, ifp->vrf_id);
     
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
-    {
-      client->ifadd_cnt++;
-       zsend_interface_add (client, ifp);
-    }
+    if (client->ifinfo)
+      {
+       client->ifadd_cnt++;
+       zsend_interface_add (client, ifp);
+        zsend_interface_link_params (client, ifp);
+      }
 }
 
 void
@@ -797,3 +801,18 @@ zebra_import_table_rm_update ()
 
   return;
 }
+
+/* Interface parameters update */
+void
+zebra_interface_parameters_update (struct interface *ifp)
+{
+  struct listnode *node, *nnode;
+  struct zserv *client;
+
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug ("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", ifp->name);
+
+  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+    if (client->ifinfo)
+      zsend_interface_link_params (client, ifp);
+}
index 5e3cf1bfd3fc2b305d428b69210f1a701129e9bf..e3bce7af4665ef3678d847c31f6c96904522d5d8 100644 (file)
@@ -49,6 +49,7 @@ extern void zebra_interface_address_add_update (struct interface *,
                                                struct connected *);
 extern void zebra_interface_address_delete_update (struct interface *,
                                                   struct connected *c);
+extern void zebra_interface_parameters_update (struct interface *);
 extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id);
 extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id);
 
index c21ee44702ec57f52fb0ea694b093f3016083ff8..85d3bd2f1b0fd63ce32a0779656ffc5401095822 100644 (file)
@@ -60,6 +60,10 @@ void zebra_interface_address_delete_update (struct interface *a,
                                                 struct connected *b)
 { return; }
 
+/* Interface parameters update */
+void zebra_interface_parameters_update (struct interface *ifp)
+{ return; };
+
 void zebra_interface_vrf_update_del (struct interface *a, vrf_id_t new_vrf_id)
 { return; }
 
index 989bca0788d04e71d329f1bf5e08171981d3b03f..d8579a2d06b56dee7af4fc04fc9dd9f38bafd7f0 100644 (file)
@@ -165,6 +165,16 @@ zserv_encode_interface (struct stream *s, struct interface *ifp)
   if (ifp->hw_addr_len)
     stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
 
+  zlog_info("Try to set TE Link Param");
+  /* Then, Traffic Engineering parameters if any */
+  if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params))
+    {
+      stream_putc (s, 1);
+      zebra_interface_link_params_write (s, ifp);
+    }
+  else
+    stream_putc (s, 0);
+
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 }
@@ -252,6 +262,35 @@ zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf)
   return zebra_server_send_message (client);
 }
 
+int
+zsend_interface_link_params (struct zserv *client, struct interface *ifp)
+{
+  struct stream *s;
+
+  /* Check this client need interface information. */
+  if (! client->ifinfo)
+    return 0;
+
+  if (!ifp->link_params)
+    return 0;
+  s = client->obuf;
+  stream_reset (s);
+
+  zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
+
+  /* Add Interface Index */
+  stream_putl (s, ifp->ifindex);
+
+  /* Then TE Link Parameters */
+  if (zebra_interface_link_params_write (s, ifp) == 0)
+    return 0;
+
+  /* Write packet size. */
+  stream_putw_at (s, 0, stream_get_endp (s));
+
+  return zebra_server_send_message (client);
+}
+
 /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
  * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. 
  *
index 737795ad5419761198a406d1651e7f97afc17a84..3667f5b2b6442706b142570ae7c1509c5297a23b 100644 (file)
@@ -165,6 +165,8 @@ extern int zsend_router_id_update (struct zserv *, struct prefix *,
 extern int zsend_interface_vrf_update (struct zserv *, struct interface *,
                                        vrf_id_t);
 
+extern int zsend_interface_link_params (struct zserv *, struct interface *);
+
 extern pid_t pid;
 
 extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id);