diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 8 | ||||
| -rw-r--r-- | lib/command.h | 5 | ||||
| -rw-r--r-- | lib/if.c | 44 | ||||
| -rw-r--r-- | lib/if.h | 64 | ||||
| -rw-r--r-- | lib/memtypes.c | 4 | ||||
| -rw-r--r-- | lib/network.c | 18 | ||||
| -rw-r--r-- | lib/network.h | 3 | ||||
| -rw-r--r-- | lib/stream.c | 44 | ||||
| -rw-r--r-- | lib/stream.h | 6 | ||||
| -rw-r--r-- | lib/zclient.c | 186 | ||||
| -rw-r--r-- | lib/zclient.h | 4 | ||||
| -rw-r--r-- | lib/zebra.h | 3 |
12 files changed, 356 insertions, 33 deletions
diff --git a/lib/command.c b/lib/command.c index 10ab066bfb..0e921bd636 100644 --- a/lib/command.c +++ b/lib/command.c @@ -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; diff --git a/lib/command.h b/lib/command.h index c1ef0e55bd..8f20a92807 100644 --- a/lib/command.h +++ b/lib/command.h @@ -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" @@ -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; +} @@ -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; diff --git a/lib/memtypes.c b/lib/memtypes.c index d0faecb640..56d4faead5 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -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 }, }; diff --git a/lib/network.c b/lib/network.c index 3373983b3c..5379ecb5a6 100644 --- a/lib/network.c +++ b/lib/network.c @@ -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); +} diff --git a/lib/network.h b/lib/network.h index 4d9c2284bf..0fcb575d1c 100644 --- a/lib/network.h +++ b/lib/network.h @@ -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 */ diff --git a/lib/stream.c b/lib/stream.c index fe77e2a2ad..809e749fb9 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -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 @@ -671,6 +693,28 @@ stream_putq (struct stream *s, uint64_t q) } 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) { STREAM_VERIFY_SANE(s); diff --git a/lib/stream.h b/lib/stream.h index 4e9b21df5f..1e2bc89b32 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -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 diff --git a/lib/zclient.c b/lib/zclient.c index a49403d314..753954fd84 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -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; diff --git a/lib/zclient.h b/lib/zclient.h index c42d8c9aa3..b95d18ec1a 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -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. */ diff --git a/lib/zebra.h b/lib/zebra.h index 546f0dd3d7..94158013ec 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -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 |
