lib: Add new if_link_params structure
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
* lib/memtypes.c: Add new memory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
diff --git a/lib/command.c b/lib/command.c
index fa2ef11..ab46fc4 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2632,8 +2632,12 @@
case KEYCHAIN_KEY_NODE:
ret = KEYCHAIN_NODE;
break;
+ case LINK_PARAMS_NODE:
+ ret = INTERFACE_NODE;
+ break;
default:
ret = CONFIG_NODE;
+ break;
}
return ret;
@@ -3003,6 +3007,9 @@
case KEYCHAIN_KEY_NODE:
vty->node = KEYCHAIN_NODE;
break;
+ case LINK_PARAMS_NODE:
+ vty->node = INTERFACE_NODE;
+ break;
default:
break;
}
@@ -3052,6 +3059,7 @@
case MASC_NODE:
case PIM_NODE:
case VTY_NODE:
+ case LINK_PARAMS_NODE:
vty_config_unlock (vty);
vty->node = ENABLE_NODE;
break;
diff --git a/lib/command.h b/lib/command.h
index 214b1d5..d8029fb 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -109,6 +109,7 @@
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
@@ -509,6 +510,10 @@
"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
#define ISIS_STR "IS-IS information\n"
#define AREA_TAG_STR "[area tag]\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"
diff --git a/lib/if.c b/lib/if.c
index 44b8586..45c1acc 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -168,6 +168,8 @@
list_free (ifp->connected);
+ if_link_params_free (ifp);
+
XFREE (MTYPE_IF, ifp);
}
@@ -1125,3 +1127,43 @@
}
return NULL;
}
+
+struct if_link_params *
+if_link_params_get (struct interface *ifp)
+{
+ 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 (int 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;
+}
diff --git a/lib/if.h b/lib/if.h
index b3d14ba..9796a4d 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -131,6 +131,63 @@
};
#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
{
@@ -172,6 +229,9 @@
/* interface bandwidth, kbits */
unsigned int bandwidth;
+ /* Link parameters for Traffic Engineering */
+ struct if_link_params *link_params;
+
/* description of the interface. */
char *desc;
@@ -389,6 +449,10 @@
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 list *iflist;
extern struct cmd_element interface_desc_cmd;
diff --git a/lib/memtypes.c b/lib/memtypes.c
index 3b9345d..f464c4b 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -72,6 +72,7 @@
{ MTYPE_VRF, "VRF" },
{ MTYPE_VRF_NAME, "VRF name" },
{ MTYPE_VRF_BITMAP, "VRF bit-map" },
+ { MTYPE_IF_LINK_PARAMS, "Informational Link Parameters" },
{ -1, NULL },
};
@@ -214,6 +215,8 @@
{ 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 },
};
@@ -256,6 +259,7 @@
{ 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 },
};
diff --git a/lib/zclient.c b/lib/zclient.c
index 208ea5c..c2e1333 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -707,8 +707,6 @@
* 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 |
* | |
@@ -716,20 +714,32 @@
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | ifindex |
+ * | ifindex |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | if_flags |
+ * | status |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | if_flags |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | metric |
+ * | metric |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | ifmtu |
+ * | ifmtu |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | ifmtu6 |
+ * | ifmtu6 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | bandwidth |
+ * | bandwidth |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | sockaddr_dl |
+ * | Link Layer Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Harware Address Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Hardware Address if HW lenght different from 0 |
+ * | ... max INTERFACE_HWADDR_MAX |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Link_params? | Whether a link-params follows: 1 or 0.
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Link_params 0 or 1 INTERFACE_LINK_PARAMS_SIZE sized |
+ * | .... (struct if_link_params). |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
@@ -782,7 +792,135 @@
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->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;
+
+ 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 (int 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
@@ -811,28 +949,8 @@
* : :
* | |
* +-+-+-+-+-+-+-+-+
- *
*/
-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->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)
{
@@ -1059,6 +1177,10 @@
if (zclient->ipv6_route_delete)
(*zclient->ipv6_route_delete) (command, zclient, length, vrf_id);
break;
+ case ZEBRA_INTERFACE_LINK_PARAMS:
+ if (zclient->interface_link_params)
+ (*zclient->interface_link_params) (command, zclient, length);
+ break;
default:
break;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index d069eb2..1513492 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -85,6 +85,7 @@
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 (*ipv4_route_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*ipv4_route_delete) (int, struct zclient *, uint16_t, vrf_id_t);
int (*ipv6_route_add) (int, struct zclient *, uint16_t, vrf_id_t);
@@ -184,6 +185,9 @@
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. */
diff --git a/lib/zebra.h b/lib/zebra.h
index 7c4adf1..cb83a11 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -425,7 +425,8 @@
#define ZEBRA_HELLO 23
#define ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB 24
#define ZEBRA_VRF_UNREGISTER 25
-#define ZEBRA_MESSAGE_MAX 26
+#define ZEBRA_INTERFACE_LINK_PARAMS 26
+#define ZEBRA_MESSAGE_MAX 27
/* Marker value used in new Zserv, in the byte location corresponding
* the command value in the old zserv header. To allow old and new