zebra: 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>
diff --git a/zebra/interface.c b/zebra/interface.c
index 14dc589..6fa097f 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -192,7 +192,7 @@
/* 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
@@ -831,7 +831,7 @@
{
if (! rn->info)
continue;
-
+
for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
connected_dump_vty (vty, connected);
}
@@ -843,6 +843,53 @@
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 */
@@ -938,13 +985,13 @@
"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
@@ -1414,6 +1461,692 @@
"Set bandwidth informational parameter\n"
"Bandwidth in kilobits\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,
@@ -1752,6 +2485,56 @@
#endif /* HAVE_IPV6 */
static int
+link_params_config_write (struct vty *vty, struct interface *ifp)
+{
+ 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 (int 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)
{
struct listnode *node;
@@ -1788,7 +2571,6 @@
while processing config script */
if (ifp->bandwidth != 0)
vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
-
if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
vty_out(vty, " link-detect%s", VTY_NEWLINE);
else
@@ -1827,11 +2609,14 @@
irdp_config_write (vty, ifp);
#endif /* IRDP */
+ link_params_config_write (vty, ifp);
+
vty_out (vty, "!%s", VTY_NEWLINE);
}
return 0;
}
+
/* Allocate and initialize interface vector. */
void
zebra_if_init (void)
@@ -1843,6 +2628,8 @@
/* Install configuration write function. */
install_node (&interface_node, if_config_write);
+ install_node (&link_params_node, NULL);
+
install_element (VIEW_NODE, &show_interface_cmd);
install_element (VIEW_NODE, &show_interface_vrf_cmd);
install_element (VIEW_NODE, &show_interface_vrf_all_cmd);
@@ -1875,4 +2662,22 @@
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);
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 57b515e..6c54917 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -281,7 +281,11 @@
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
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);
+ }
}
/* Interface down information. */
@@ -310,7 +314,10 @@
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
if (client->ifinfo)
- zsend_interface_add (client, ifp);
+ {
+ zsend_interface_add (client, ifp);
+ zsend_interface_link_params (client, ifp);
+ }
}
void
@@ -381,3 +388,18 @@
if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
}
+
+/* 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);
+}
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 6a36f4d..ce84009 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -48,6 +48,8 @@
extern void zebra_interface_address_delete_update (struct interface *,
struct connected *c);
+extern void zebra_interface_parameters_update (struct interface *);
+
extern int zebra_check_addr (struct prefix *);
extern int is_default (struct prefix *);
diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c
index c68cec6..5584d12 100644
--- a/zebra/redistribute_null.c
+++ b/zebra/redistribute_null.c
@@ -78,3 +78,7 @@
struct connected *b)
{ return; }
#endif
+
+/* Interface parameters update */
+void zebra_interface_parameters_update (struct interface *ifp)
+{ return; };
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 054cdb3..d4c5db9 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -159,6 +159,16 @@
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));
}
@@ -211,6 +221,35 @@
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.
*
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 413cd6a..9d65998 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -108,6 +108,8 @@
extern int zsend_router_id_update (struct zserv *, struct prefix *,
vrf_id_t);
+extern int zsend_interface_link_params (struct zserv *, struct interface *);
+
extern pid_t pid;
#endif /* _ZEBRA_ZEBRA_H */