diff options
197 files changed, 9692 insertions, 2926 deletions
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index de27513a42..da5ab94e97 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "hash.h" #include "thread.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 4161d149fa..eca4441010 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "jhash.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index eefdd9e8ec..3cb52ef911 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "jhash.h" #include "queue.h" #include "table.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" @@ -1314,7 +1315,8 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) gets ignored in any of these cases. */ nexthop_n = stream_get_ipv4 (peer->ibuf); nexthop_h = ntohl (nexthop_n); - if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) + if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) + && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */ { char buf[INET_ADDRSTRLEN]; inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); @@ -1946,7 +1948,7 @@ bgp_attr_encap( } while (length >= 4) { - uint16_t subtype; + uint16_t subtype = 0; uint16_t sublength = 0; struct bgp_attr_encap_subtlv *tlv; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 9a8e2a75e2..0bf8c897de 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -131,7 +131,7 @@ struct attr struct in_addr nexthop; u_int32_t med; u_int32_t local_pref; - u_int32_t nh_ifindex; + ifindex_t nh_ifindex; /* Path origin attribute */ u_char origin; diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index aeac93e7b3..ad221d922d 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -34,6 +34,8 @@ #include "vty.h" #include "bfd.h" #include "lib/json.h" +#include "filter.h" + #include "bgpd/bgpd.h" #include "bgp_fsm.h" #include "bgpd/bgp_bfd.h" diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index a6c16d8c2d..cd52c94b1f 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "privs.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_dump.h" @@ -143,7 +144,7 @@ main (int argc, char **argv) size_t len; int source_as; int dest_as; - int ifindex; + ifindex_t ifindex; int family; struct in_addr sip; struct in_addr dip; diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 4beae4391e..12c936b190 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 2e2dc42ad1..f4a83d720b 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "thread.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_damp.h" diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 5b6ee0e070..dc0f539847 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -48,6 +49,7 @@ unsigned long conf_bgp_debug_keepalive; unsigned long conf_bgp_debug_update; unsigned long conf_bgp_debug_bestpath; unsigned long conf_bgp_debug_zebra; +unsigned long conf_bgp_debug_allow_martians; unsigned long conf_bgp_debug_nht; unsigned long conf_bgp_debug_update_groups; @@ -60,6 +62,7 @@ unsigned long term_bgp_debug_keepalive; unsigned long term_bgp_debug_update; unsigned long term_bgp_debug_bestpath; unsigned long term_bgp_debug_zebra; +unsigned long term_bgp_debug_allow_martians; unsigned long term_bgp_debug_nht; unsigned long term_bgp_debug_update_groups; @@ -1518,6 +1521,48 @@ DEFUN (no_debug_bgp_zebra_prefix, return CMD_SUCCESS; } +DEFUN (debug_bgp_allow_martians, + debug_bgp_allow_martians_cmd, + "debug bgp allow-martians", + DEBUG_STR + BGP_STR + "BGP allow martian next hops\n") +{ + if (vty->node == CONFIG_NODE) + DEBUG_ON (allow_martians, ALLOW_MARTIANS); + else + { + TERM_DEBUG_ON (allow_martians, ALLOW_MARTIANS); + vty_out (vty, "BGP allow_martian next hop debugging is on%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +DEFUN (no_debug_bgp_allow_martians, + no_debug_bgp_allow_martians_cmd, + "no debug bgp allow-martians", + NO_STR + DEBUG_STR + BGP_STR + "BGP allow martian next hops\n") +{ + if (vty->node == CONFIG_NODE) + DEBUG_OFF (allow_martians, ALLOW_MARTIANS); + else + { + TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); + vty_out (vty, "BGP allow martian next hop debugging is off%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +ALIAS (no_debug_bgp_allow_martians, + undebug_bgp_allow_martians_cmd, + "undebug bgp allow-martians", + UNDEBUG_STR + BGP_STR + "BGP allow martian next hops\n") + /* debug bgp update-groups */ DEFUN (debug_bgp_update_groups, debug_bgp_update_groups_cmd, @@ -1580,6 +1625,7 @@ DEFUN (no_debug_bgp, TERM_DEBUG_OFF (as4, AS4_SEGMENT); TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); TERM_DEBUG_OFF (zebra, ZEBRA); + TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE); return CMD_SUCCESS; @@ -1634,6 +1680,8 @@ DEFUN (show_debugging_bgp, bgp_debug_list_print (vty, " BGP zebra debugging is on", bgp_debug_zebra_prefixes); + if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) + vty_out (vty, " BGP allow martian next hop debugging is on%s", VTY_NEWLINE); vty_out (vty, "%s", VTY_NEWLINE); return CMD_SUCCESS; } @@ -1717,6 +1765,12 @@ bgp_config_write_debug (struct vty *vty) } } + if (CONF_BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) + { + vty_out (vty, "debug bgp allow-martians%s", VTY_NEWLINE); + write++; + } + return write; } @@ -1749,6 +1803,8 @@ bgp_debug_init (void) install_element (CONFIG_NODE, &debug_bgp_update_cmd); install_element (ENABLE_NODE, &debug_bgp_zebra_cmd); install_element (CONFIG_NODE, &debug_bgp_zebra_cmd); + install_element (ENABLE_NODE, &debug_bgp_allow_martians_cmd); + install_element (CONFIG_NODE, &debug_bgp_allow_martians_cmd); install_element (ENABLE_NODE, &debug_bgp_update_groups_cmd); install_element (CONFIG_NODE, &debug_bgp_update_groups_cmd); install_element (ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd); @@ -1805,6 +1861,9 @@ bgp_debug_init (void) install_element (CONFIG_NODE, &no_debug_bgp_update_cmd); install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd); install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_allow_martians_cmd); + install_element (ENABLE_NODE, &undebug_bgp_allow_martians_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_allow_martians_cmd); install_element (ENABLE_NODE, &no_debug_bgp_update_groups_cmd); install_element (CONFIG_NODE, &no_debug_bgp_update_groups_cmd); install_element (ENABLE_NODE, &no_debug_bgp_cmd); diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 8372c7e3f5..835d585735 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -66,6 +66,7 @@ extern unsigned long conf_bgp_debug_keepalive; extern unsigned long conf_bgp_debug_update; extern unsigned long conf_bgp_debug_bestpath; extern unsigned long conf_bgp_debug_zebra; +extern unsigned long conf_bgp_debug_allow_martians; extern unsigned long conf_bgp_debug_nht; extern unsigned long conf_bgp_debug_update_groups; @@ -76,6 +77,7 @@ extern unsigned long term_bgp_debug_keepalive; extern unsigned long term_bgp_debug_update; extern unsigned long term_bgp_debug_bestpath; extern unsigned long term_bgp_debug_zebra; +extern unsigned long term_bgp_debug_allow_martians; extern unsigned long term_bgp_debug_nht; extern unsigned long term_bgp_debug_update_groups; @@ -104,6 +106,7 @@ struct bgp_debug_filter #define BGP_DEBUG_UPDATE_OUT 0x02 #define BGP_DEBUG_UPDATE_PREFIX 0x04 #define BGP_DEBUG_ZEBRA 0x01 +#define BGP_DEBUG_ALLOW_MARTIANS 0x01 #define BGP_DEBUG_NHT 0x01 #define BGP_DEBUG_UPDATE_GROUPS 0x01 diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 59bb2f8a13..e219d5248e 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -29,9 +29,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "linklist.h" #include "queue.h" #include "memory.h" +#include "filter.h" #include "bgpd/bgp_table.h" - #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index dc0137fd19..926e2650a2 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "command.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" @@ -769,7 +770,9 @@ ecommunity_match (const struct ecommunity *ecom1, /* Every community on com2 needs to be on com1 for this to match */ while (i < ecom1->size && j < ecom2->size) { - if (memcmp (ecom1->val + i, ecom2->val + j, ECOMMUNITY_SIZE) == 0) + if (memcmp (ecom1->val + i * ECOMMUNITY_SIZE, + ecom2->val + j * ECOMMUNITY_SIZE, + ECOMMUNITY_SIZE) == 0) j++; i++; } @@ -779,4 +782,3 @@ ecommunity_match (const struct ecommunity *ecom1, else return 0; } - diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 693c639f75..33877e7258 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "buffer.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -66,18 +67,12 @@ struct as_filter char *reg_str; }; -enum as_list_type -{ - ACCESS_TYPE_STRING, - ACCESS_TYPE_NUMBER -}; - /* AS path filter list. */ struct as_list { char *name; - enum as_list_type type; + enum access_type type; struct as_list *next; struct as_list *prev; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9da21fdffd..046767177b 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "workqueue.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" @@ -1331,8 +1332,10 @@ bgp_start (struct peer *peer) if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s [FSM] Waiting for NHT", peer->host); +#if !defined (HAVE_BGP_STANDALONE) BGP_EVENT_ADD(peer, TCP_connection_open_failed); return 0; +#endif } status = bgp_connect (peer); diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 0d24c9c294..20fa138ce8 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -227,7 +227,6 @@ bgp_exit (int status) { struct bgp *bgp; struct listnode *node, *nnode; - extern struct zclient *zclient; /* it only makes sense for this to be called on a clean exit */ assert (status == 0); @@ -277,8 +276,8 @@ bgp_exit (int status) bgp_vrf_terminate (); cmd_terminate (); vty_terminate (); - if (zclient) - zclient_free (zclient); + + bgp_zebra_destroy(); if (bgp_nexthop_buf) stream_free (bgp_nexthop_buf); if (bgp_ifindices_buf) diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 2395a66689..e7272cc0aa 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -29,6 +29,7 @@ #include "sockunion.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 00f8221bcb..c22dbb05a9 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "stream.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" @@ -481,7 +482,7 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u { u_int16_t type; struct rd_as rd_as; - struct rd_ip rd_ip = { 0, { 0 }, 0}; + struct rd_ip rd_ip = {0}; u_char *pnt; pnt = rn->p.u.val; @@ -671,7 +672,7 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty { u_int16_t type; struct rd_as rd_as; - struct rd_ip rd_ip = { 0, { 0 }, 0}; + struct rd_ip rd_ip = {0}; u_char *pnt; pnt = rn->p.u.val; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 61972aabf1..ecfc3f9fe8 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -33,6 +33,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "network.h" #include "queue.h" #include "hash.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_open.h" @@ -62,7 +63,9 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password) { int ret = -1; int en = ENOSYS; +#if HAVE_DECL_TCP_MD5SIG union sockunion su2; +#endif /* HAVE_TCP_MD5SIG */ assert (socket >= 0); @@ -228,6 +231,17 @@ bgp_set_socket_ttl (struct peer *peer, int bgp_sock) static int bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) { +#ifndef SO_BINDTODEVICE + /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here + * anyway since the assumption is that the interface name returned by + * getsockopt() is useful in identifying the VRF, particularly with Linux's + * VRF l3master device. The whole mechanism is specific to Linux, so... + * when other platforms add VRF support, this will need handling here as + * well. (or, some restructuring) */ + *bgp_inst = bgp_get_default (); + return !*bgp_inst; + +#else char name[VRF_NAMSIZ + 1]; socklen_t name_len = VRF_NAMSIZ; struct bgp *bgp; @@ -239,9 +253,13 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len); if (rc != 0) { +#if !defined (HAVE_BGP_STANDALONE) zlog_err ("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", safe_strerror (errno), sock); return -1; +#else + strcpy (name, VRF_DEFAULT_NAME); +#endif } if (!strlen(name)) @@ -275,6 +293,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) /* We didn't match to either an instance or an interface. */ return -1; +#endif } /* Accept bgp connection. */ @@ -566,7 +585,7 @@ bgp_update_source (struct peer *peer) int bgp_connect (struct peer *peer) { - unsigned int ifindex = 0; + ifindex_t ifindex = 0; if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) { @@ -656,7 +675,9 @@ bgp_getsockname (struct peer *peer) { zlog_err ("%s: nexthop_set failed, resetting connection - intf %p", peer->host, peer->nexthop.ifp); +#if !defined (HAVE_BGP_STANDALONE) return -1; +#endif } return 0; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index a58b73e9f3..1e5c4cf8b0 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "jhash.h" #include "nexthop.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -563,12 +564,13 @@ bgp_scan_init (struct bgp *bgp) bgp->connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); bgp->import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); -#ifdef HAVE_IPV6 bgp->nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp->connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp->import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); -#endif /* HAVE_IPV6 */ + bgp->nexthop_cache_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); + bgp->connected_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); + bgp->import_check_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); } void diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index caf6fc2b41..ef70d0e4f9 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -31,6 +31,7 @@ #include "memory.h" #include "nexthop.h" #include "vrf.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -396,25 +397,23 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id) nexthop->type = stream_getc (s); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: nexthop->ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); nexthop->ifindex = stream_getl (s); break; -#ifdef HAVE_IPV6 - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop->gate.ipv6, s, 16); break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: stream_get (&nexthop->gate.ipv6, s, 16); nexthop->ifindex = stream_getl (s); break; -#endif default: /* do nothing */ break; diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 947f5c09d4..6001092ce2 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" @@ -195,6 +196,9 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) return 1; } break; + case AFI_ETHER: + default: + break; } zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); @@ -1473,7 +1477,7 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc(s, len); stream_put(s, names.nodename, len); -#ifdef _GNU_SOURCE +#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME if ((names.domainname[0] != '\0') && (strcmp(names.domainname, "(none)") != 0)) { @@ -1497,8 +1501,13 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc_at(s, capp, len); if (bgp_debug_neighbor_events(peer)) +#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME zlog_debug("%s Sending hostname cap with hn = %s, dn = %s", peer->host, names.nodename, names.domainname); +#else + zlog_debug("%s Sending hostname cap with hn = %s", peer->host, + names.nodename); +#endif } /* Sending base graceful-restart capability irrespective of the config */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 0236f6777a..937623a30b 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "linklist.h" #include "plist.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c index 15c23c9ff9..ea87633dc0 100644 --- a/bgpd/bgp_regex.c +++ b/bgpd/bgp_regex.c @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd.h" #include "bgp_aspath.h" diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f767fae1a9..7295ff147f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9382,6 +9382,66 @@ DEFUN (show_ip_bgp_dampening_info, return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); } + +DEFUN (show_ip_bgp_ipv4_dampening_parameters, + show_ip_bgp_ipv4_dampening_parameters_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening parameters", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display detail of configured dampening parameters\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_MULTICAST); + + return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); +} + + +DEFUN (show_ip_bgp_ipv4_dampening_flap_stats, + show_ip_bgp_ipv4_dampening_flap_stats_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening flap-statistics", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display flap statistics of routes\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_flap_statistics, NULL, 0); + + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_flap_statistics, NULL, 0); +} + +DEFUN (show_ip_bgp_ipv4_dampening_dampd_paths, + show_ip_bgp_ipv4_dampening_dampd_paths_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening dampened-paths", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display paths suppressed due to dampening\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_dampend_paths, NULL, 0); + + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_dampend_paths, NULL, 0); +} + static int bgp_show_route_map (struct vty *vty, const char *name, const char *rmap_str, afi_t afi, @@ -14516,7 +14576,10 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd); install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_dampd_paths_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_flap_stats_cmd); install_element (VIEW_NODE, &show_ip_bgp_damp_dampened_paths_cmd); install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd); install_element (VIEW_NODE, &show_ip_bgp_damp_flap_statistics_cmd); @@ -14669,6 +14732,9 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); install_element (ENABLE_NODE, &show_ip_bgp_dampening_params_cmd); install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_dampd_paths_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_flap_stats_cmd); install_element (ENABLE_NODE, &show_ip_bgp_damp_dampened_paths_cmd); install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd); install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_statistics_cmd); @@ -15078,6 +15144,13 @@ bgp_route_init (void) install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset3_cmd); + + /* IPv4 Multicast Mode */ + install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_set2_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_set3_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_unset2_cmd); } void diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index e4fd730cf0..fea9ae6b18 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2997,8 +2997,8 @@ DEFUN (match_peer, "match peer (A.B.C.D|X:X::X:X)", MATCH_STR "Match peer address\n" - "IPv6 address of peer\n" - "IP address of peer\n") + "IP address of peer\n" + "IPv6 address of peer\n") { return bgp_route_match_add (vty, vty->index, "peer", argv[0], RMAP_EVENT_MATCH_ADDED); @@ -3036,8 +3036,8 @@ ALIAS (no_match_peer, NO_STR MATCH_STR "Match peer address\n" - "IPv6 address of peer\n" - "IP address of peer\n") + "IP address of peer\n" + "IPv6 address of peer\n") ALIAS (no_match_peer, no_match_peer_local_cmd, diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index fc5a0eb59c..5e6218e8a3 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "thread.h" #include "smux.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 1df24859f5..114c6ef013 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "vty.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 1114c37010..2f839c4af7 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -35,7 +35,7 @@ struct bgp_table struct peer *owner; struct route_table *route_table; - u_int64_t version; + uint64_t version; }; struct bgp_node @@ -56,7 +56,7 @@ struct bgp_node struct bgp_node *prn; - u_int64_t version; + uint64_t version; u_char flags; #define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_USER_CLEAR (1 << 1) @@ -311,13 +311,13 @@ bgp_table_iter_started (bgp_table_iter_t * iter) /* This would benefit from a real atomic operation... * until then. */ -static inline u_int64_t +static inline uint64_t bgp_table_next_version (struct bgp_table *table) { return ++table->version; } -static inline u_int64_t +static inline uint64_t bgp_table_version (struct bgp_table *table) { return table->version; diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index cd7710b501..29e6243a1a 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -668,7 +668,7 @@ updgrp_show_packet_queue_walkcb (struct update_group *updgrp, void *arg) */ void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { struct updwalk_context ctx; @@ -1587,7 +1587,7 @@ update_bgp_group_free (struct bgp *bgp) void update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t subgrp_id) + uint64_t subgrp_id) { struct updwalk_context ctx; memset (&ctx, 0, sizeof (ctx)); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index aab2458b30..6ab384369c 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -133,7 +133,7 @@ struct update_group safi_t safi; int afid; - u_int64_t id; + uint64_t id; time_t uptime; u_int32_t join_events; @@ -231,8 +231,8 @@ struct update_subgroup */ struct { - u_int64_t update_group_id; - u_int64_t subgroup_id; + uint64_t update_group_id; + uint64_t subgroup_id; } split_from; u_int32_t join_events; @@ -248,7 +248,7 @@ struct update_subgroup u_int32_t split_events; u_int32_t merge_checks_triggered; - u_int64_t id; + uint64_t id; struct zlog *log; u_int16_t sflags; @@ -297,8 +297,8 @@ struct updwalk_context struct vty *vty; struct bgp_node *rn; struct bgp_info *ri; - u_int64_t updgrp_id; - u_int64_t subgrp_id; + uint64_t updgrp_id; + uint64_t subgrp_id; bgp_policy_type_e policy_type; const char *policy_name; int policy_event_start_flag; @@ -367,7 +367,7 @@ extern void update_bgp_group_init (struct bgp *); extern void udpate_bgp_group_free (struct bgp *); extern void -update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, u_int64_t subgrp_id); +update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id); extern void update_group_show_stats (struct bgp *bgp, struct vty *vty); extern void update_group_adjust_peer (struct peer_af *paf); extern int update_group_adjust_soloness (struct peer *peer, int set); @@ -439,13 +439,13 @@ extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct *adj); extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void subgroup_announce_route (struct update_subgroup *subgrp); extern void subgroup_announce_all (struct update_subgroup *subgrp); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 4b684be1bb..c485e61e5c 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -36,6 +36,7 @@ #include "thread.h" #include "queue.h" #include "routemap.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -276,7 +277,7 @@ updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg) static void updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id, u_int8_t flags) + struct vty *vty, uint64_t id, u_int8_t flags) { struct updwalk_context ctx; memset (&ctx, 0, sizeof (ctx)); @@ -849,14 +850,14 @@ group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi, void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE); } void update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED); } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f16cf53cbe..c83d751743 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "hash.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_advertise.h" @@ -62,12 +63,20 @@ listen_range_exists (struct bgp *bgp, struct prefix *range, int exact); afi_t bgp_node_afi (struct vty *vty) { - if (vty->node == BGP_IPV6_NODE || - vty->node == BGP_IPV6M_NODE || - vty->node == BGP_VPNV6_NODE || - vty->node == BGP_ENCAPV6_NODE) - return AFI_IP6; - return AFI_IP; + afi_t afi; + switch (vty->node) + { + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_VPNV6_NODE: + case BGP_ENCAPV6_NODE: + afi = AFI_IP6; + break; + default: + afi = AFI_IP; + break; + } + return afi; } /* Utility function to get subsequent address family from current @@ -75,13 +84,26 @@ bgp_node_afi (struct vty *vty) safi_t bgp_node_safi (struct vty *vty) { - if (vty->node == BGP_VPNV4_NODE || vty->node == BGP_VPNV6_NODE) - return SAFI_MPLS_VPN; - if (vty->node == BGP_ENCAP_NODE || vty->node == BGP_ENCAPV6_NODE) - return SAFI_ENCAP; - if (vty->node == BGP_IPV4M_NODE || vty->node == BGP_IPV6M_NODE) - return SAFI_MULTICAST; - return SAFI_UNICAST; + safi_t safi; + switch (vty->node) + { + case BGP_ENCAP_NODE: + case BGP_ENCAPV6_NODE: + safi = SAFI_ENCAP; + break; + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + safi = SAFI_MPLS_VPN; + break; + case BGP_IPV4M_NODE: + case BGP_IPV6M_NODE: + safi = SAFI_MULTICAST; + break; + default: + safi = SAFI_UNICAST; + break; + } + return safi; } int @@ -1794,6 +1816,26 @@ DEFUN (bgp_graceful_restart_stalepath_time, return CMD_SUCCESS; } +DEFUN (bgp_graceful_restart_restart_time, + bgp_graceful_restart_restart_time_cmd, + "bgp graceful-restart restart-time <1-3600>", + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n" + "Delay value (seconds)\n") +{ + struct bgp *bgp; + u_int32_t restart; + + bgp = vty->index; + if (! bgp) + return CMD_WARNING; + + VTY_GET_INTEGER_RANGE ("restart-time", restart, argv[0], 1, 3600); + bgp->restart_time = restart; + return CMD_SUCCESS; +} + DEFUN (no_bgp_graceful_restart_stalepath_time, no_bgp_graceful_restart_stalepath_time_cmd, "no bgp graceful-restart stalepath-time", @@ -1812,6 +1854,24 @@ DEFUN (no_bgp_graceful_restart_stalepath_time, return CMD_SUCCESS; } +DEFUN (no_bgp_graceful_restart_restart_time, + no_bgp_graceful_restart_restart_time_cmd, + "no bgp graceful-restart restart-time", + NO_STR + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n") +{ + struct bgp *bgp; + + bgp = vty->index; + if (! bgp) + return CMD_WARNING; + + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + return CMD_SUCCESS; +} + ALIAS (no_bgp_graceful_restart_stalepath_time, no_bgp_graceful_restart_stalepath_time_val_cmd, "no bgp graceful-restart stalepath-time <1-3600>", @@ -1821,6 +1881,15 @@ ALIAS (no_bgp_graceful_restart_stalepath_time, "Set the max time to hold onto restarting peer's stale paths\n" "Delay value (seconds)\n") +ALIAS (no_bgp_graceful_restart_restart_time, + no_bgp_graceful_restart_restart_time_val_cmd, + "no bgp graceful-restart restart-time <1-3600>", + NO_STR + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n" + "Delay value (seconds)\n") + /* "bgp fast-external-failover" configuration. */ DEFUN (bgp_fast_external_failover, bgp_fast_external_failover_cmd, @@ -13012,7 +13081,7 @@ DEFUN (show_ip_bgp_attr_info, static int bgp_show_update_groups(struct vty *vty, const char *name, int afi, int safi, - u_int64_t subgrp_id) + uint64_t subgrp_id) { struct bgp *bgp; @@ -13139,7 +13208,7 @@ DEFUN (show_ip_bgp_updgrps_s, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); return (bgp_show_update_groups(vty, NULL, AFI_IP, SAFI_UNICAST, subgrp_id)); @@ -13155,7 +13224,7 @@ DEFUN (show_ip_bgp_instance_updgrps_s, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); return (bgp_show_update_groups(vty, argv[1], AFI_IP, SAFI_UNICAST, subgrp_id)); @@ -13169,7 +13238,7 @@ DEFUN (show_bgp_ipv6_updgrps_s, "Detailed info about v6 dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); return(bgp_show_update_groups(vty, NULL, AFI_IP6, SAFI_UNICAST, subgrp_id)); @@ -13183,7 +13252,7 @@ DEFUN (show_bgp_instance_ipv6_updgrps_s, "Detailed info about v6 dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); return(bgp_show_update_groups(vty, argv[1], AFI_IP6, SAFI_UNICAST, subgrp_id)); @@ -13203,7 +13272,7 @@ DEFUN (show_bgp_updgrps_s, { afi_t afi; safi_t safi; - u_int64_t subgrp_id; + uint64_t subgrp_id; afi = (strcmp(argv[0], "ipv4") == 0) ? AFI_IP : AFI_IP6; safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; @@ -13250,7 +13319,7 @@ DEFUN (show_bgp_instance_updgrps_stats, static void show_bgp_updgrps_adj_info_aux (struct vty *vty, const char *name, afi_t afi, safi_t safi, - const char *what, u_int64_t subgrp_id) + const char *what, uint64_t subgrp_id) { struct bgp *bgp; @@ -13369,7 +13438,7 @@ DEFUN (show_ip_bgp_updgrps_adj_s, "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); @@ -13391,7 +13460,7 @@ DEFUN (show_ip_bgp_instance_updgrps_adj_s, "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); @@ -13417,7 +13486,7 @@ DEFUN (show_bgp_updgrps_afi_adj_s, { afi_t afi; safi_t safi; - u_int64_t subgrp_id; + uint64_t subgrp_id; afi = (strcmp(argv[0], "ipv4") == 0) ? AFI_IP : AFI_IP6; safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; @@ -13438,7 +13507,7 @@ DEFUN (show_bgp_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); @@ -13458,7 +13527,7 @@ DEFUN (show_bgp_instance_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); @@ -14510,6 +14579,9 @@ bgp_vty_init (void) install_element (BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd); install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd); install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_val_cmd); + install_element (BGP_NODE, &bgp_graceful_restart_restart_time_cmd); + install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd); + install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_val_cmd); /* "bgp fast-external-failover" commands */ install_element (BGP_NODE, &bgp_fast_external_failover_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 6e17d778ab..c2df521e79 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "memory.h" #include "lib/json.h" #include "lib/bfd.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" @@ -865,7 +866,7 @@ if_lookup_by_ipv4_exact (struct in_addr *addr, vrf_id_t vrf_id) #ifdef HAVE_IPV6 struct interface * -if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) +if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *ifnode; struct listnode *cnode; @@ -887,7 +888,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) if (cp->family == AF_INET6) if (prefix_match (cp, (struct prefix *)&p)) { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6.s6_addr32[0])) + if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { if (ifindex == ifp->ifindex) return ifp; @@ -901,7 +902,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) } struct interface * -if_lookup_by_ipv6_exact (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) +if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *ifnode; struct listnode *cnode; @@ -1390,7 +1391,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (p->family == AF_INET6 || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { - unsigned int ifindex; + ifindex_t ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; int valid_nh_count = 0; @@ -1536,7 +1537,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = valid_nh_count; - api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf); + api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; api.tag = 0; diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 1f845bd918..af921af82f 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -58,8 +58,8 @@ extern int bgp_redistribute_unreg (struct bgp *, afi_t, int, u_short); extern struct interface *if_lookup_by_ipv4 (struct in_addr *, vrf_id_t); extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t); #ifdef HAVE_IPV6 -extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, unsigned int, vrf_id_t); -extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, unsigned int, vrf_id_t); +extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t); +extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t); #endif /* HAVE_IPV6 */ #endif /* _QUAGGA_BGP_ZEBRA_H */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a6265ad8ba..87e5c54ea2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1295,7 +1295,7 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) { struct connected *ifc; struct prefix p; - u_int32_t s_addr; + u_int32_t addr; struct listnode *node; /* If our IPv4 address on the interface is /30 or /31, we can derive the @@ -1309,26 +1309,26 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) if (p.prefixlen == 30) { peer->su.sa.sa_family = AF_INET; - s_addr = ntohl(p.u.prefix4.s_addr); - if (s_addr % 4 == 1) - peer->su.sin.sin_addr.s_addr = htonl(s_addr+1); - else if (s_addr % 4 == 2) - peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 4 == 1) + peer->su.sin.sin_addr.s_addr = htonl(addr+1); + else if (addr % 4 == 2) + peer->su.sin.sin_addr.s_addr = htonl(addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su->sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return 1; } else if (p.prefixlen == 31) { peer->su.sa.sa_family = AF_INET; - s_addr = ntohl(p.u.prefix4.s_addr); - if (s_addr % 2 == 0) - peer->su.sin.sin_addr.s_addr = htonl(s_addr+1); + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 2 == 0) + peer->su.sin.sin_addr.s_addr = htonl(addr+1); else - peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); + peer->su.sin.sin_addr.s_addr = htonl(addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su->sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return 1; } @@ -3227,6 +3227,8 @@ bgp_free (struct bgp *bgp) bgp_table_finish (&bgp->rib[afi][safi]); } + bgp_address_destroy (bgp); + /* If Default instance or VRF, unlink from the VRF structure. */ vrf = bgp_vrf_lookup_by_instance_type (bgp); if (vrf) @@ -7219,6 +7221,9 @@ bgp_config_write (struct vty *vty) if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) vty_out (vty, " bgp graceful-restart stalepath-time %d%s", bgp->stalepath_time, VTY_NEWLINE); + if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) + vty_out (vty, " bgp graceful-restart restart-time %d%s", + bgp->restart_time, VTY_NEWLINE); if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART)) vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 991afdf7cc..e8827ca91f 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -112,8 +112,8 @@ struct bgp_master #define BGP_OPT_CONFIG_CISCO (1 << 2) #define BGP_OPT_NO_LISTEN (1 << 3) - u_int64_t updgrp_idspace; - u_int64_t subgrp_idspace; + uint64_t updgrp_idspace; + uint64_t subgrp_idspace; /* timer to dampen route map changes */ struct thread *t_rmap_update; /* Handle route map updates */ @@ -518,7 +518,7 @@ struct peer /* BGP peer group. */ struct peer_group *group; - u_int64_t version[AFI_MAX][SAFI_MAX]; + uint64_t version[AFI_MAX][SAFI_MAX]; /* BGP peer_af structures, per configured AF on this peer */ struct peer_af *peer_af_array[BGP_AF_MAX]; @@ -583,7 +583,7 @@ struct peer time_t readtime; /* Last read time */ time_t resettime; /* Last reset time */ - unsigned int ifindex; /* ifindex of the BGP connection. */ + ifindex_t ifindex; /* ifindex of the BGP connection. */ char *conf_if; /* neighbor interface config name. */ struct interface *ifp; /* corresponding interface */ char *ifname; /* bind interface name. */ diff --git a/configure.ac b/configure.ac index 8fcafbb0f0..b1ea4821e2 100755 --- a/configure.ac +++ b/configure.ac @@ -21,6 +21,7 @@ AC_CANONICAL_HOST() AC_CANONICAL_TARGET() AM_INIT_AUTOMAKE(1.6) +m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])]) AM_SILENT_RULES([yes]) AC_CONFIG_HEADERS(config.h) @@ -265,15 +266,11 @@ AC_ARG_WITH(libpam, AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh])) AC_ARG_ENABLE(tcp-zebra, AS_HELP_STRING([--enable-tcp-zebra], [enable TCP/IP socket connection between zebra and protocol daemon])) -AC_ARG_ENABLE(opaque-lsa, - AS_HELP_STRING([--disable-opaque-lsa],[do not build OSPF Opaque-LSA with OSPFAPI support (RFC2370)])) AC_ARG_ENABLE(ospfapi, AS_HELP_STRING([--disable-ospfapi], [do not build OSPFAPI to access the OSPF LSA Database])) AC_ARG_ENABLE(ospfclient, AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI, (this is the default if --disable-ospfapi is set)])) -AC_ARG_ENABLE(ospf-te, - AS_HELP_STRING([--disable-ospf-te],[disable Traffic Engineering Extension to OSPF])) AC_ARG_ENABLE(multipath, AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit])) AC_ARG_ENABLE(user, @@ -320,19 +317,18 @@ AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)])) AC_ARG_ENABLE(cumulus, AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions])) +AC_ARG_ENABLE(bgp-standalone, + AS_HELP_STRING([--enable-bgp-standalone], [Modify code to allow BGP to work without Zebra])) AC_ARG_ENABLE(rr-semantics, AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics])) AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c") if test $ac_cv_lib_json_c_json_object_get = no; then - AC_MSG_ERROR([lib json is needed to compile]) -fi - -AC_CHECK_HEADERS(json-c/json.h) -AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c") -if test $ac_cv_lib_json_c_json_object_get = no; then - AC_MSG_ERROR([lib json is needed to compile]) + AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson") + if test $ac_cv_lib_json_json_object_get = no; then + AC_MSG_ERROR([lib json is needed to compile]) + fi fi if test x"${enable_gcc_rdynamic}" != x"no" ; then @@ -374,6 +370,10 @@ if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) fi +if test "${enable_bgp_standalone}" = "yes" ; then + AC_DEFINE(HAVE_BGP_STANDALONE,,Allow BGP to work without Zebra) +fi + if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) fi @@ -386,15 +386,6 @@ if test "${enable_tcp_zebra}" = "yes"; then AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication) fi -if test "${enable_opaque_lsa}" != "no"; then - AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA) -fi - -if test "${enable_ospf_te}" != "no"; then - AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA) - AC_DEFINE(HAVE_OSPF_TE,,OSPF TE) -fi - if test "${enable_linux24_tcp_md5}" = "yes"; then AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch) fi @@ -422,16 +413,22 @@ AC_SUBST(ISIS_TOPOLOGY_INCLUDES) AC_SUBST(ISIS_TOPOLOGY_DIR) AC_SUBST(ISIS_TOPOLOGY_LIB) -if test "${enable_user}" = "yes" || test x"${enable_user}" = x""; then - enable_user="quagga" -elif test "${enable_user}" = "no"; then - enable_user="root" +if test x"${enable_user}" = x"no"; then + enable_user="" +else + if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then + enable_user="quagga" + fi + AC_DEFINE_UNQUOTED(QUAGGA_USER, "${enable_user}", Quagga User) fi -if test "${enable_group}" = "yes" || test x"${enable_group}" = x""; then - enable_group="quagga" -elif test "${enable_group}" = "no"; then - enable_group="root" +if test x"${enable_group}" = x"no"; then + enable_group="" +else + if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then + enable_group="quagga" + fi + AC_DEFINE_UNQUOTED(QUAGGA_GROUP, "${enable_group}", Quagga Group) fi if test x"${enable_vty_group}" = x"yes" ; then @@ -444,8 +441,6 @@ fi AC_SUBST([enable_user]) AC_SUBST([enable_group]) AC_SUBST([enable_vty_group]) -AC_DEFINE_UNQUOTED(QUAGGA_USER, "${enable_user}", Quagga User) -AC_DEFINE_UNQUOTED(QUAGGA_GROUP, "${enable_group}", Quagga Group) enable_configfile_mask=${enable_configfile_mask:-0600} AC_DEFINE_UNQUOTED(CONFIGFILE_MASK, ${enable_configfile_mask}, Mask for config files) @@ -716,7 +711,7 @@ dnl [TODO] on Linux, and in [TODO] on Solaris. )] )] ) - AC_CHECK_LIB(readline, main, LIBREADLINE="$LIBREADLINE -lreadline",, + AC_CHECK_LIB(readline, main, LIBREADLINE="-lreadline $LIBREADLINE",, "$LIBREADLINE") if test $ac_cv_lib_readline_main = no; then AC_MSG_ERROR([vtysh needs libreadline but was not found and usable on your system.]) @@ -999,11 +994,46 @@ dnl figure out how to specify an interface in multicast sockets API dnl --------------------------------------------------------------- AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], QUAGGA_INCLUDES) -AC_CHECK_HEADERS([linux/mroute.h], [], [], -[ -#if HAVE_NETINET_IN_H -#include<netinet/in.h> -#endif]) +AC_CHECK_HEADERS([linux/mroute.h], [], [],[ + #ifdef HAVE_SYS_SOCKET_H + # include <sys/socket.h> + #endif + #ifdef HAVE_NETINET_IN_H + # include <netinet/in.h> + #endif + #define _LINUX_IN_H /* For Linux <= 2.6.25 */ + #include <linux/types.h> +]) + +m4_define([QUAGGA_INCLUDES], +QUAGGA_INCLUDES +[#if HAVE_LINUX_MROUTE_H +# include <linux/mroute.h> +#endif +])dnl + +AC_CHECK_HEADERS([netinet/ip_mroute.h], [], [],[ + #ifdef HAVE_SYS_SOCKET_H + # include <sys/socket.h> + #endif + #ifdef HAVE_SYS_TYPES_H + # include <sys/types.h> + #endif + #ifdef HAVE_NETINET_IN_H + # include <netinet/in.h> + #endif + #ifdef HAVE_NET_ROUTE_H + # include <net/route.h> + #endif +]) + +m4_define([QUAGGA_INCLUDES], +QUAGGA_INCLUDES +[#if HAVE_NETINET_IP_MROUTE_H +# include <netinet/ip_mroute.h> +#endif +])dnl + AC_MSG_CHECKING([for BSD struct ip_mreq hack]) AC_TRY_COMPILE([#ifdef HAVE_SYS_PARAM_H #include <sys/param.h> @@ -1101,6 +1131,11 @@ AC_SUBST(IPFORWARD) AC_CHECK_FUNCS(getaddrinfo, [have_getaddrinfo=yes], [have_getaddrinfo=no]) +dnl ---------------------------------------------------------------------------- +dnl figure out if domainname is available in the utsname struct (GNU extension). +dnl ---------------------------------------------------------------------------- +AC_CHECK_MEMBERS([struct utsname.domainname], [], [], [#include <sys/utsname.h>]) + dnl ---------- dnl IPv6 check dnl ---------- @@ -1208,16 +1243,14 @@ fi AM_CONDITIONAL(WATCHQUAGGA, test "x$WATCHQUAGGA" = "xwatchquagga") OSPFCLIENT="" -if test "${enable_opaque_lsa}" != "no"; then - if test "${enable_ospfapi}" != "no";then +if test "${enable_ospfapi}" != "no";then AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI) - if test "${enable_ospfclient}" != "no";then + if test "${enable_ospfclient}" != "no";then OSPFCLIENT="ospfclient" - fi fi - fi + AM_CONDITIONAL(OSPFCLIENT, test "x$OSPFCLIENT" = "xospfclient") case "${enable_ripngd}" in diff --git a/cumulus/start-stop-daemon.c b/cumulus/start-stop-daemon.c index ea63fbc217..4d447d9051 100644 --- a/cumulus/start-stop-daemon.c +++ b/cumulus/start-stop-daemon.c @@ -56,8 +56,9 @@ #include <limits.h> #include <assert.h> #include <ctype.h> -#include <error.h> +#ifdef linux #include <linux/sched.h> +#endif static int testmode = 0; static int quietmode = 0; @@ -241,6 +242,7 @@ next_dirname(const char *s) return cur; } +#ifdef linux static void add_namespace(const char *path) { @@ -270,6 +272,7 @@ add_namespace(const char *path) namespace->nstype = nstype; LIST_INSERT_HEAD(&namespace_head, namespace, list); } +#endif #ifdef HAVE_LXC static void @@ -567,7 +570,9 @@ parse_options(int argc, char * const *argv) changeroot = optarg; break; case 'd': /* --namespace /.../<ipcns>|<netns>|<utsns>/name */ +#ifdef linux add_namespace(optarg); +#endif break; case 'N': /* --nice */ nicelevel = atoi(optarg); diff --git a/doc/install.texi b/doc/install.texi index 7349e92cbe..811ad9ae89 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -83,8 +83,17 @@ OSPF-API is enabled if --enable-opaque-lsa is set. @item --disable-ospfclient Disable building of the example OSPF-API client. @item --disable-ospf-te -Disable support for OSPF Traffic Engineering Extension (internet-draft) this +Disable support for OSPF Traffic Engineering Extension (RFC3630) this requires support for Opaque LSAs. +@item --disable-ospf-ri +Disable support for OSPF Router Information (RFC4970 & RFC5088) this +requires support for Opaque LSAs and Traffic Engineering. +@item --enable-isisd +Build isisd. +@item --enable-isis-topology +Enable IS-IS topology generator. +@item --enable-isis-te +Enable Traffic Engineering Extension for ISIS (RFC5305) @item --enable-multipath=@var{ARG} Enable support for Equal Cost Multipath. @var{ARG} is the maximum number of ECMP paths to allow, set to 0 to allow unlimited number of paths. diff --git a/doc/isisd.texi b/doc/isisd.texi new file mode 100644 index 0000000000..bbc2896755 --- /dev/null +++ b/doc/isisd.texi @@ -0,0 +1,432 @@ +@cindex ISIS +@node ISIS +@chapter ISIS + +@acronym{ISIS,Intermediate System to Intermediate System} is a routing protocol +which is described in @cite{ISO10589, RFC1195, RFC5308}. ISIS is an +@acronym{IGP,Interior Gateway Protocol}. Compared with @acronym{RIP}, +@acronym{ISIS} can provide scalable network support and faster +convergence times like @acronym{OSPF}. ISIS is widely used in large networks such as +@acronym{ISP,Internet Service Provider} and carrier backbone networks. + +@menu +* Configuring isisd:: +* ISIS router:: +* ISIS Timer:: +* ISIS region:: +* ISIS interface:: +* Showing ISIS information:: +* ISIS Traffic Engineering:: +* Debugging ISIS:: +* ISIS Configuration Examples:: +@end menu + +@node Configuring isisd +@section Configuring isisd + +There are no @command{isisd} specific options. Common options can be +specified (@pxref{Common Invocation Options}) to @command{isisd}. +@command{isisd} needs to acquire interface information from +@command{zebra} in order to function. Therefore @command{zebra} must be +running before invoking @command{isisd}. Also, if @command{zebra} is +restarted then @command{isisd} must be too. + +Like other daemons, @command{isisd} configuration is done in @acronym{ISIS} +specific configuration file @file{isisd.conf}. + +@node ISIS router +@section ISIS router + +To start ISIS process you have to specify the ISIS router. As of this +writing, @command{isisd} does not support multiple ISIS processes. + +@deffn Command {router isis WORD} {} +@deffnx Command {no router isis WORD} {} +@anchor{router isis WORD}Enable or disable the ISIS process by specifying the ISIS domain with 'WORD'. +@command{isisd} does not yet support multiple ISIS processes but you must specify +the name of ISIS process. The ISIS process name 'WORD' is then used for interface +(see command @ref{ip router isis WORD}). +@end deffn + +@deffn {ISIS Command} {net XX.XXXX. ... .XXX.XX} {} +@deffnx {ISIS Command} {no net XX.XXXX. ... .XXX.XX} {} +Set/Unset network entity title (NET) provided in ISO format. +@end deffn + +@deffn {ISIS Command} {hostname dynamic} {} +@deffnx {ISIS Command} {no hostname dynamic} {} +Enable support for dynamic hostname. +@end deffn + +@deffn {ISIS Command} {area-password [clear | md5] <password>} {} +@deffnx {ISIS Command} {domain-password [clear | md5] <password>} {} +@deffnx {ISIS Command} {no area-password} {} +@deffnx {ISIS Command} {no domain-password} {} +Configure the authentication password for an area, respectively a domain, +as clear text or md5 one. +@end deffn + +@deffn {ISIS Command} {log-adjacency-changes} {} +@deffnx {ISIS Command} {no log-adjacency-changes} {} +Log changes in adjacency state. +@end deffn + +@deffn {ISIS Command} {metric-style [narrow | transition | wide]} {} +@deffnx {ISIS Command} {no metric-style} {} +@anchor{metric-style}Set old-style (ISO 10589) or new-style packet formats: + - narrow Use old style of TLVs with narrow metric + - transition Send and accept both styles of TLVs during transition + - wide Use new style of TLVs to carry wider metric +@end deffn + +@deffn {ISIS Command} {set-overload-bit} {} +@deffnx {ISIS Command} {no set-overload-bit} {} +Set overload bit to avoid any transit traffic. +@end deffn + +@node ISIS Timer +@section ISIS Timer + +@deffn {ISIS Command} {lsp-gen-interval <1-120>} {} +@deffnx {ISIS Command} {lsp-gen-interval [level-1 | level-2] <1-120>} {} +@deffnx {ISIS Command} {no lsp-gen-interval} {} +@deffnx {ISIS Command} {no lsp-gen-interval [level-1 | level-2]} {} +Set minimum interval in seconds between regenerating same LSP, +globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {lsp-refresh-interval <1-65235>} {} +@deffnx {ISIS Command} {lsp-refresh-interval [level-1 | level-2] <1-65235>} {} +@deffnx {ISIS Command} {no lsp-refresh-interval} {} +@deffnx {ISIS Command} {no lsp-refresh-interval [level-1 | level-2]} {} +Set LSP refresh interval in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {lsp-refresh-interval <1-65235>} {} +@deffnx {ISIS Command} {lsp-refresh-interval [level-1 | level-2] <1-65235>} {} +@deffnx {ISIS Command} {no lsp-refresh-interval} {} +@deffnx {ISIS Command} {no lsp-refresh-interval [level-1 | level-2]} {} +Set LSP refresh interval in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {max-lsp-lifetime <360-65535>} {} +@deffnx {ISIS Command} {max-lsp-lifetime [level-1 | level-2] <360-65535>} {} +@deffnx {ISIS Command} {no max-lsp-lifetime} {} +@deffnx {ISIS Command} {no max-lsp-lifetime [level-1 | level-2]} {} +Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {spf-interval <1-120>} {} +@deffnx {ISIS Command} {spf-interval [level-1 | level-2] <1-120>} {} +@deffnx {ISIS Command} {no spf-interval} {} +@deffnx {ISIS Command} {no spf-interval [level-1 | level-2]} {} +Set minimum interval between consecutive SPF calculations in seconds. +@end deffn + +@node ISIS region +@section ISIS region + +@deffn {ISIS Command} {is-type [level-1 | level-1-2 | level-2-only]} {} +@deffnx {ISIS Command} {no is-type} {} +Define the ISIS router behavior: + - level-1 Act as a station router only + - level-1-2 Act as both a station router and an area router + - level-2-only Act as an area router only +@end deffn + +@node ISIS interface +@section ISIS interface + +@deffn {Interface Command} {ip router isis WORD} {} +@deffnx {Interface Command} {no ip router isis WORD} {} +@anchor{ip router isis WORD}Activate ISIS adjacency on this interface. Note that the name +of ISIS instance must be the same as the one used to configure the ISIS process +(see command @ref{router isis WORD}). +@end deffn + +@deffn {Interface Command} {isis circuit-type [level-1 | level-1-2 | level-2]} {} +@deffnx {Interface Command} {no isis circuit-type} {} +Configure circuit type for interface: + - level-1 Level-1 only adjacencies are formed + - level-1-2 Level-1-2 adjacencies are formed + - level-2-only Level-2 only adjacencies are formed +@end deffn + +@deffn {Interface Command} {isis csnp-interval <1-600>} {} +@deffnx {Interface Command} {isis csnp-interval <1-600> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis csnp-interval} {} +@deffnx {Interface Command} {no isis csnp-interval [level-1 | level-2]} {} +Set CSNP interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis hello padding} {} +Add padding to IS-IS hello packets. +@end deffn + +@deffn {Interface Command} {isis hello-interval <1-600>} {} +@deffnx {Interface Command} {isis hello-interval <1-600> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis hello-interval} {} +@deffnx {Interface Command} {no isis hello-interval [level-1 | level-2]} {} +Set Hello interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis hello-multiplier <2-100>} {} +@deffnx {Interface Command} {isis hello-multiplier <2-100> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis hello-multiplier} {} +@deffnx {Interface Command} {no isis hello-multiplier [level-1 | level-2]} {} +Set multiplier for Hello holding time globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis metric [<0-255> | <0-16777215>]} {} +@deffnx {Interface Command} {isis metric [<0-255> | <0-16777215>] [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis metric} {} +@deffnx {Interface Command} {no isis metric [level-1 | level-2]} {} +Set default metric value globally, for an area (level-1) or a domain (level-2). +Max value depend if metric support narrow or wide value (see command @ref{metric-style}). +@end deffn + +@deffn {Interface Command} {isis network point-to-point} {} +@deffnx {Interface Command} {no isis network point-to-point} {} +Set network type to 'Point-to-Point' (broadcast by default). +@end deffn + +@deffn {Interface Command} {isis passive} {} +@deffnx {Interface Command} {no isis passive} {} +Configure the passive mode for this interface. +@end deffn + +@deffn {Interface Command} {isis password [clear | md5] <password>} {} +@deffnx {Interface Command} {no isis password} {} +Configure the authentication password (clear or encoded text) for the interface. +@end deffn + +@deffn {Interface Command} {isis priority <0-127>} {} +@deffnx {Interface Command} {isis priority <0-127> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis priority} {} +@deffnx {Interface Command} {no isis priority [level-1 | level-2]} {} +Set priority for Designated Router election, globally, for the area (level-1) +or the domain (level-2). +@end deffn + +@deffn {Interface Command} {isis psnp-interval <1-120>} {} +@deffnx {Interface Command} {isis psnp-interval <1-120> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis psnp-interval} {} +@deffnx {Interface Command} {no isis psnp-interval [level-1 | level-2]} {} +Set PSNP interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@node Showing ISIS information +@section Showing ISIS information + +@deffn {Command} {show isis summary} {} +Show summary information about ISIS. +@end deffn + +@deffn {Command} {show isis hostname} {} +Show information about ISIS node. +@end deffn + +@deffn {Command} {show isis interface} {} +@deffnx {Command} {show isis interface detail} {} +@deffnx {Command} {show isis interface <interface name>} {} +Show state and configuration of ISIS specified interface, or all +interfaces if no interface is given with or without details. +@end deffn + +@deffn {Command} {show isis neighbor} {} +@deffnx {Command} {show isis neighbor <System Id>} {} +@deffnx {Command} {show isis neighbor detail} {} +Show state and information of ISIS specified neighbor, or all +neighbors if no system id is given with or without details. +@end deffn + +@deffn {Command} {show isis database} {} +@deffnx {Command} {show isis database [detail]} {} +@deffnx {Command} {show isis database <LSP id> [detail]} {} +@deffnx {Command} {show isis database detail <LSP id>} {} +Show the ISIS database globally, for a specific LSP id without or with details. +@end deffn + +@deffn {Command} {show isis topology} {} +@deffnx {Command} {show isis topology [level-1|level-2]} {} +Show topology IS-IS paths to Intermediate Systems, globally, +in area (level-1) or domain (level-2). +@end deffn + +@deffn {Command} {show ip route isis} {} +Show the ISIS routing table, as determined by the most recent SPF calculation. +@end deffn + +@node ISIS Traffic Engineering +@section Traffic Engineering + +@deffn {ISIS Command} {mpls-te on} {} +@deffnx {ISIS Command} {no mpls-te} {} +Enable Traffic Engineering LSP flooding. +@end deffn + +@deffn {ISIS Command} {mpls-te router-address <A.B.C.D>} {} +@deffnx {ISIS Command} {no mpls-te router-address} {} +Configure stable IP address for MPLS-TE. +@end deffn + +@deffn {Command} {show isis mpls-te interface} {} +@deffnx {Command} {show isis mpls-te interface @var{interface}} {} +Show MPLS Traffic Engineering parameters for all or specified interface. +@end deffn + +@deffn {Command} {show isis mpls-te router} {} +Show Traffic Engineering router parameters. +@end deffn + +@node Debugging ISIS +@section Debugging ISIS + +@deffn {Command} {debug isis adj-packets} {} +@deffnx {Command} {no debug isis adj-packets} {} +IS-IS Adjacency related packets. +@end deffn + +@deffn {Command} {debug isis checksum-errors} {} +@deffnx {Command} {no debug isis checksum-errors} {} +IS-IS LSP checksum errors. +@end deffn + +@deffn {Command} {debug isis events} {} +@deffnx {Command} {no debug isis events} {} +IS-IS Events. +@end deffn + +@deffn {Command} {debug isis local-updates} {} +@deffnx {Command} {no debug isis local-updates} {} +IS-IS local update packets. +@end deffn + +@deffn {Command} {debug isis packet-dump} {} +@deffnx {Command} {no debug isis packet-dump} {} +IS-IS packet dump. +@end deffn + +@deffn {Command} {debug isis protocol-errors} {} +@deffnx {Command} {no debug isis protocol-errors} {} +IS-IS LSP protocol errors. +@end deffn + +@deffn {Command} {debug isis route-events} {} +@deffnx {Command} {no debug isis route-events} {} +IS-IS Route related events. +@end deffn + +@deffn {Command} {debug isis snp-packets} {} +@deffnx {Command} {no debug isis snp-packets} {} +IS-IS CSNP/PSNP packets. +@end deffn + +@deffn {Command} {debug isis spf-events} {} +@deffnx {Command} {debug isis spf-statistics} {} +@deffnx {Command} {debug isis spf-triggers} {} +@deffnx {Command} {no debug isis spf-events} {} +@deffnx {Command} {no debug isis spf-statistics} {} +@deffnx {Command} {no debug isis spf-triggers} {} +IS-IS Shortest Path First Events, Timing and Statistic Data +and triggering events. +@end deffn + +@deffn {Command} {debug isis update-packets} {} +@deffnx {Command} {no debug isis update-packets} {} +Update related packets. +@end deffn + +@deffn {Command} {show debugging isis} {} +Print which ISIS debug level is activate. +@end deffn + +@node ISIS Configuration Examples +@section ISIS Configuration Examples +A simple example, with MD5 authentication enabled: + +@example +@group +! +interface eth0 + ip router isis FOO + isis network point-to-point + isis circuit-type level-2-only +! +router isis FOO +net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00 + metric-style wide + is-type level-2-only +@end group +@end example + + +A Traffic Engineering configuration, with Inter-ASv2 support. + + - First, the 'zebra.conf' part: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/zebra.log +! +interface eth0 + ip address 10.2.2.2/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab +! +interface eth1 + ip address 10.1.1.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab + mpls-te neighbor 10.1.1.2 as 65000 +@end group +@end example + + - Then the 'isisd.conf' itself: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/isisd.log +! +! +interface eth0 + ip router isis FOO +! +interface eth1 + ip router isis FOO +! +! +router isis FOO + isis net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00 + mpls-te on + mpls-te router-address 10.1.1.1 +! +line vty +@end group +@end example diff --git a/doc/main.texi b/doc/main.texi index 4c11d2440d..29ed17c82b 100644 --- a/doc/main.texi +++ b/doc/main.texi @@ -42,6 +42,14 @@ When program terminates, retain routes added by zebra. @node Interface Commands @section Interface Commands +@menu +* Standard Commands:: +* Link Parameters Commands:: +@end menu + +@node Standard Commands +@subsection Standard Commands + @deffn Command {interface @var{ifname}} {} @end deffn @@ -74,18 +82,71 @@ Enable or disables multicast flag for the interface. @deffn {Interface Command} {bandwidth <1-10000000>} {} @deffnx {Interface Command} {no bandwidth <1-10000000>} {} -Set bandwidth value of the interface in kilobits/sec. This is for -calculating OSPF cost. This command does not affect the actual device +Set bandwidth value of the interface in kilobits/sec. This is for +calculating OSPF cost. This command does not affect the actual device configuration. @end deffn @deffn {Interface Command} {link-detect} {} @deffnx {Interface Command} {no link-detect} {} -Enable/disable link-detect on platforms which support this. Currently +Enable/disable link-detect on platforms which support this. Currently only Linux and Solaris, and only where network interface drivers support reporting link-state via the IFF_RUNNING flag. @end deffn +@node Link Parameters Commands +@subsection Link Parameters Commands + +@deffn {Interface Command} {link-params} {} +@deffnx {Interface Command} {no link-param} {} +Enter into the link parameters sub node. At least 'enable' must be set to activate the link parameters, +and consequently Traffic Engineering on this interface. MPLS-TE must be enable at the OSPF (@ref{OSPF Traffic Engineering}) +or ISIS (@ref{ISIS Traffic Engineering}) router level in complement to this. +Disable link parameters for this interface. +@end deffn + +Under link parameter statement, the following commands set the different TE values: + +@deffn link-params {enable} +Enable link parameters for this interface. +@end deffn + +@deffn link-params {metric <0-4294967295>} {} +@deffnx link-params {max-bw @var{bandwidth}} {} +@deffnx link-params {max-rsv-bw @var{bandwidth}} {} +@deffnx link-params {unrsv-bw <0-7> @var{bandwidth}} {} +@deffnx link-params {admin-grp @var{bandwidth}} {} +These commands specifies the Traffic Engineering parameters of the interface in conformity to RFC3630 (OSPF) +or RFC5305 (ISIS). +There are respectively the TE Metric (different from the OSPF or ISIS metric), Maximum Bandwidth (interface speed +by default), Maximum Reservable Bandwidth, Unreserved Bandwidth for each 0-7 priority and Admin Group (ISIS) or +Resource Class/Color (OSPF). + +Note that @var{bandwidth} are specified in IEEE floating point format and express in Bytes/second. +@end deffn + +@deffn link-param {delay <0-16777215> [min <0-16777215> | max <0-16777215>]} {} +@deffnx link-param {delay-variation <0-16777215>} {} +@deffnx link-param {packet-loss @var{percentage}} {} +@deffnx link-param {res-bw @var{bandwidth}} {} +@deffnx link-param {ava-bw @var{bandwidth}} {} +@deffnx link-param {use-bw @var{bandwidth}} {} +These command specifies additionnal Traffic Engineering parameters of the interface in conformity to +draft-ietf-ospf-te-metrics-extension-05.txt and draft-ietf-isis-te-metrics-extension-03.txt. There are +respectively the delay, jitter, loss, available bandwidth, reservable bandwidth and utilized bandwidth. + +Note that @var{bandwidth} are specified in IEEE floating point format and express in Bytes/second. +Delays and delay variation are express in micro-second (µs). Loss is specified in @var{percentage} ranging +from 0 to 50.331642% by step of 0.000003. +@end deffn + +@deffn link-param {neighbor <A.B.C.D> as <0-65535>} {} +@deffnx link-param {no neighbor} {} +Specifies the remote ASBR IP address and Autonomous System (AS) number for InterASv2 link in OSPF (RFC5392). +Note that this option is not yet supported for ISIS (RFC5316). +@end deffn + + @node Static Route Commands @section Static Route Commands @@ -162,7 +223,7 @@ prevent traffic destined for a prefix to match less-specific routes (eg default) should the specified gateways not be reachable. Eg: @example -zebra> show ip route 10.0.0.0/8 +zebra> show ip route 10.0.0.0/8 Routing entry for 10.0.0.0/8 Known via "static", distance 1, metric 0 10.0.0.2 inactive @@ -182,7 +243,7 @@ These behave similarly to their ipv4 counterparts. @deffn Command {table @var{tableno}} {} Select the primary kernel routing table to be used. This only works for kernels supporting multiple routing tables (like GNU/Linux 2.2.x -and later). After setting @var{tableno} with this command, +and later). After setting @var{tableno} with this command, static routes defined after this are added to the specified table. @end deffn @@ -365,8 +426,8 @@ Display current routes which zebra holds in its database. @example @group -Router# show ip route -Codes: K - kernel route, C - connected, S - static, R - RIP, +Router# show ip route +Codes: K - kernel route, C - connected, S - static, R - RIP, B - BGP * - FIB route. K* 0.0.0.0/0 203.181.89.241 diff --git a/doc/mpls/ChangeLog.opaque.txt b/doc/mpls/ChangeLog.opaque.txt index 68ddf4c817..afcfaa3590 100644 --- a/doc/mpls/ChangeLog.opaque.txt +++ b/doc/mpls/ChangeLog.opaque.txt @@ -1,4 +1,17 @@ ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- +Changes 2013.07.01 + +1. Feature enhancements + + 1.1 Update ospf_te.[c,h] in conformance to RFC3630 and clean the code. + Add new directive to enable MPLS-TE per interface instead of globally + + 1.2 Add support for RFC4970 "Router Information" and RFC5088 "PCE + Capabilities announcement". + + 1.3 Incorporate the mpls documentation into the main stream doc. + +----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- Changes 2001.12.03 1. Bug fixes diff --git a/doc/mpls/ospfd.conf b/doc/mpls/ospfd.conf index 6be11f9120..2b15fa4d00 100644 --- a/doc/mpls/ospfd.conf +++ b/doc/mpls/ospfd.conf @@ -17,6 +17,7 @@ debug ospf packet all detail interface fxp0 ip ospf hello-interval 60 ip ospf dead-interval 240 + mpls-te on mpls-te link metric 999 mpls-te link max-bw 1.25e+06 mpls-te link max-rsv-bw 1.25e+06 diff --git a/doc/ospfd.texi b/doc/ospfd.texi index 45d1ad7cd2..96dffe0000 100644 --- a/doc/ospfd.texi +++ b/doc/ospfd.texi @@ -1,3 +1,4 @@ + @cindex OSPFv2 @node OSPFv2 @chapter OSPFv2 @@ -18,6 +19,9 @@ networks. * OSPF interface:: * Redistribute routes to OSPF:: * Showing OSPF information:: +* Opaque LSA:: +* OSPF Traffic Engineering:: +* Router Information:: * Debugging OSPF:: * OSPF Configuration Examples:: @end menu @@ -616,35 +620,137 @@ interfaces if no interface is given. Show the OSPF routing table, as determined by the most recent SPF calculation. @end deffn +@node Opaque LSA +@section Opaque LSA + +@deffn {OSPF Command} {ospf opaque-lsa} {} +@deffnx {OSPF Command} {capability opaque} {} +@deffnx {OSPF Command} {no ospf opaque-lsa} {} +@deffnx {OSPF Command} {no capability opaque} {} +@command{ospfd} support Opaque LSA (RFC2370) as fondment for MPLS Traffic Engineering LSA. Prior to used MPLS TE, opaque-lsa must be enable in the configuration file. Alternate command could be "mpls-te on" (@ref{OSPF Traffic Engineering}). +@end deffn + +@deffn {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external)} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id} adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id} self-originate} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) self-originate} {} +Show Opaque LSA from the database. +@end deffn + +@node OSPF Traffic Engineering +@section Traffic Engineering + +@deffn {OSPF Command} {mpls-te on} {} +@deffnx {OSPF Command} {no mpls-te} {} +Enable Traffic Engineering LSA flooding. +@end deffn + +@deffn {OSPF Command} {mpls-te router-address <A.B.C.D>} {} +@deffnx {OSPF Command} {no mpls-te} {} +Configure stable IP address for MPLS-TE. This IP address is then advertise in Opaque LSA Type-10 TLV=1 (TE) +option 1 (Router-Address). +@end deffn + +@deffn {OSPF Command} {mpls-te inter-as area <area-id>|as} {} +@deffnx {OSPF Command} {no mpls-te inter-as} {} +Enable RFC5392 suuport - Inter-AS TE v2 - to flood Traffic Engineering parameters of Inter-AS link. +2 modes are supported: AREA and AS; LSA are flood in AREA <area-id> with Opaque Type-10, +respectively in AS with Opaque Type-11. In all case, Opaque-LSA TLV=6. +@end deffn + +@deffn {Command} {show ip ospf mpls-te interface} {} +@deffnx {Command} {show ip ospf mpls-te interface @var{interface}} {} +Show MPLS Traffic Engineering parameters for all or specified interface. +@end deffn + +@deffn {Command} {show ip ospf mpls-te router} {} +Show Traffic Engineering router parameters. +@end deffn + +@node Router Information +@section Router Information + +@deffn {OSPF Command} {router-info [as | area <A.B.C.D>]} {} +@deffnx {OSPF Command} {no router-info} {} +Enable Router Information (RFC4970) LSA advertisement with AS scope (default) or Area scope flooding +when area is specified. +@end deffn + +@deffn {OSPF Command} {pce address <A.B.C.D>} {} +@deffnx {OSPF Command} {no pce address} {} +@deffnx {OSPF Command} {pce domain as <0-65535>} {} +@deffnx {OSPF Command} {no pce domain as <0-65535>} {} +@deffnx {OSPF Command} {pce neighbor as <0-65535>} {} +@deffnx {OSPF Command} {no pce neighbor as <0-65535>} {} +@deffnx {OSPF Command} {pce flag BITPATTERN} {} +@deffnx {OSPF Command} {no pce flag} {} +@deffnx {OSPF Command} {pce scope BITPATTERN} {} +@deffnx {OSPF Command} {no pce scope} {} +The commands are conform to RFC 5088 and allow OSPF router announce Path Compuatation Elemenent (PCE) capabilities +through the Router Information (RI) LSA. Router Information must be enable prior to this. The command set/unset +respectively the PCE IP adress, Autonomous System (AS) numbers of controlled domains, neighbor ASs, flag and scope. +For flag and scope, please refer to RFC5088 for the BITPATTERN recognition. Multiple 'pce neighbor' command could +be specified in order to specify all PCE neighbours. +@end deffn + +@deffn {Command} {show ip ospf router-info} {} +Show Router Capabilities flag. +@end deffn +@deffn {Command} {show ip ospf router-info pce} {} +Show Router Capabilities PCE parameters. +@end deffn + @node Debugging OSPF @section Debugging OSPF @deffn {Command} {debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} @deffnx {Command} {no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} +Dump Packet for debugging @end deffn @deffn {Command} {debug ospf ism} {} @deffnx {Command} {debug ospf ism (status|events|timers)} {} @deffnx {Command} {no debug ospf ism} {} @deffnx {Command} {no debug ospf ism (status|events|timers)} {} +Show debug information of Interface State Machine @end deffn @deffn {Command} {debug ospf nsm} {} @deffnx {Command} {debug ospf nsm (status|events|timers)} {} @deffnx {Command} {no debug ospf nsm} {} @deffnx {Command} {no debug ospf nsm (status|events|timers)} {} +Show debug information of Network State Machine +@end deffn + +@deffn {Command} {debug ospf event} {} +@deffnx {Command} {no debug ospf event} {} +Show debug information of OSPF event +@end deffn + +@deffn {Command} {debug ospf nssa} {} +@deffnx {Command} {no debug ospf nssa} {} +Show debug information about Not So Stub Area @end deffn @deffn {Command} {debug ospf lsa} {} @deffnx {Command} {debug ospf lsa (generate|flooding|refresh)} {} @deffnx {Command} {no debug ospf lsa} {} @deffnx {Command} {no debug ospf lsa (generate|flooding|refresh)} {} +Show debug detail of Link State messages +@end deffn + +@deffn {Command} {debug ospf te} {} +@deffnx {Command} {no debug ospf te} {} +Show debug information about Traffic Engineering LSA @end deffn @deffn {Command} {debug ospf zebra} {} @deffnx {Command} {debug ospf zebra (interface|redistribute)} {} @deffnx {Command} {no debug ospf zebra} {} @deffnx {Command} {no debug ospf zebra (interface|redistribute)} {} +Show debug information of ZEBRA API @end deffn @deffn {Command} {show debugging ospf} {} @@ -702,3 +808,100 @@ router ospf ! @end group @end example + +A Traffic Engineering configuration, with Inter-ASv2 support. + + - First, the 'zebra.conf' part: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/zebra.log +! +interface eth0 + ip address 198.168.1.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab +! +interface eth1 + ip address 192.168.2.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab + mpls-te neighbor 192.168.2.2 as 65000 +@end group +@end example + + - Then the 'ospfd.conf' itself: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/ospfd.log +! +! +interface eth0 + ip ospf hello-interval 60 + ip ospf dead-interval 240 +! +interface eth1 + ip ospf hello-interval 60 + ip ospf dead-interval 240 +! +! +router ospf + ospf router-id 192.168.1.1 + network 192.168.0.0/16 area 1 + ospf opaque-lsa + mpls-te + mpls-te router-address 192.168.1.1 + mpls-te inter-as area 1 +! +line vty +@end group +@end example + +A router information example with PCE advsertisement: + +@example +@group +! +router ospf + ospf router-id 192.168.1.1 + network 192.168.0.0/16 area 1 + capability opaque + mpls-te + mpls-te router-address 192.168.1.1 + router-info area 0.0.0.1 + pce address 192.168.1.1 + pce flag 0x80 + pce domain as 65400 + pce neighbor as 65500 + pce neighbor as 65200 + pce scope 0x80 +! +@end group +@end example diff --git a/doc/quagga.texi b/doc/quagga.texi index 65089621a3..6831b30cdf 100644 --- a/doc/quagga.texi +++ b/doc/quagga.texi @@ -85,6 +85,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of * RIPng:: * OSPFv2:: * OSPFv3:: +* ISIS:: * BGP:: * Configuring Quagga as a Route Server:: * VTY shell:: @@ -109,6 +110,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of @include ripngd.texi @include ospfd.texi @include ospf6d.texi +@include isisd.texi @include bgpd.texi @include routeserver.texi @include vtysh.texi diff --git a/isisd/AUTHORS b/isisd/AUTHORS index 05fc0a5073..80b3a28e19 100644 --- a/isisd/AUTHORS +++ b/isisd/AUTHORS @@ -2,3 +2,4 @@ Sampo Saaristo <sambo@cs.tut.fi> Ofer Wald <ofersf@islands.co.il> Hannes Gredler <hannes@gredler.at> Subbaiah Venkata <svenkata@google.com> +Olivier Dugeon <olivier.dugeon@orange.com> diff --git a/isisd/Makefile.am b/isisd/Makefile.am index 6dd132d49a..bfe2e94779 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -16,7 +16,7 @@ libisis_a_SOURCES = \ isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ - isis_spf.c isis_redist.c isis_route.c isis_routemap.c \ + isis_spf.c isis_redist.c isis_route.c isis_routemap.c isis_te.c \ isis_vty.c @@ -25,7 +25,7 @@ noinst_HEADERS = \ isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \ isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \ iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \ - isis_route.h isis_routemap.h \ + isis_route.h isis_routemap.h isis_te.h \ include-netbsd/clnp.h include-netbsd/esis.h include-netbsd/iso.h isisd_SOURCES = \ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 728cbdc67d..4f22a5e558 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -37,6 +37,7 @@ #include "linklist.h" #include "command.h" #include "thread.h" +#include "vty.h" #include "hash.h" #include "prefix.h" #include "stream.h" @@ -58,6 +59,7 @@ #include "isisd/isisd.h" #include "isisd/isis_csm.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" /* * Prototypes. @@ -96,6 +98,8 @@ isis_circuit_new () circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC; } + circuit->mtc = mpls_te_circuit_new(); + return circuit; } @@ -222,6 +226,10 @@ isis_circuit_add_addr (struct isis_circuit *circuit, ipv4->prefixlen = connected->address->prefixlen; ipv4->prefix = connected->address->u.prefix4; listnode_add (circuit->ip_addrs, ipv4); + + /* Update MPLS TE Local IP address parameter */ + set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix); + if (circuit->area) lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); @@ -518,6 +526,7 @@ isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp) assert (ifp->info == circuit); else ifp->info = circuit; + isis_link_params_update (circuit, ifp); } void @@ -619,15 +628,6 @@ isis_circuit_up (struct isis_circuit *circuit) /* * Get the Hardware Address */ -#ifdef HAVE_STRUCT_SOCKADDR_DL -#ifndef SUNOS_5 - if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN) - zlog_warn ("unsupported link layer"); - else - memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl), - ETH_ALEN); -#endif -#else if (circuit->interface->hw_addr_len != ETH_ALEN) { zlog_warn ("unsupported link layer"); @@ -641,7 +641,6 @@ isis_circuit_up (struct isis_circuit *circuit) circuit->interface->ifindex, ISO_MTU (circuit), snpa_print (circuit->u.bc.snpa)); #endif /* EXTREME_DEBUG */ -#endif /* HAVE_STRUCT_SOCKADDR_DL */ circuit->u.bc.adjdb[0] = list_new (); circuit->u.bc.adjdb[1] = list_new (); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 9d6e426d41..9ada1e26a3 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -112,13 +112,14 @@ struct isis_circuit */ struct isis_passwd passwd; /* Circuit rx/tx password */ int is_type; /* circuit is type == level of circuit - * diffrenciated from circuit type (media) */ + * differentiated from circuit type (media) */ u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ u_int8_t metric[2]; u_int32_t te_metric[2]; + struct mpls_te_circuit *mtc; /* Support for MPLS-TE parameters - see isis_te.[c,h] */ int ip_router; /* Route IP ? */ int is_passive; /* Is Passive ? */ struct list *ip_addrs; /* our IP addresses */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 81f1958e63..0177a9423a 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -52,6 +52,7 @@ #include "isisd/isis_csm.h" #include "isisd/isis_adjacency.h" #include "isisd/isis_spf.h" +#include "isisd/isis_te.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -981,6 +982,8 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost) lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0); vty_out (vty, " Metric : %-8d IS-Extended : %s%s", GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE); + if (IS_MPLS_TE(isisMplsTE)) + mpls_te_print_detail(vty, te_is_neigh); } /* TE IPv4 tlv */ @@ -1091,6 +1094,64 @@ lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, return; } +/* Process IS_NEIGHBOURS TLV with TE subTLVs */ +void +lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, int frag_thold) +{ + int count, size = 0; + struct listnode *node, *nextnode; + struct te_is_neigh *elem; + + /* Start computing real size of TLVs */ + for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem)) + size = size + elem->sub_tlvs_length + IS_NEIGHBOURS_LEN; + + /* can we fit all ? */ + if (!FRAG_NEEDED (lsp->pdu, frag_thold, size)) + { + tlv_add_te_is_neighs (*from, lsp->pdu); + if (listcount (*to) != 0) + { + for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem)) + { + listnode_add (*to, elem); + list_delete_node (*from, node); + } + } + else + { + list_free (*to); + *to = *from; + *from = NULL; + } + } + else + { + /* fit all we can */ + /* Compute remaining place in LSP PDU */ + count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 - + (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu)); + /* Determine size of TE SubTLVs */ + elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from)); + count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN; + if (count > 0) + { + while (count > 0) + { + listnode_add (*to, listgetdata ((struct listnode *)listhead (*from))); + listnode_delete (*from, listgetdata ((struct listnode *)listhead (*from))); + + elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from)); + count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN; + } + + tlv_add_te_is_neighs (*to, lsp->pdu); + } + } + lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); + return; +} + static u_int16_t lsp_rem_lifetime (struct isis_area *area, int level) { @@ -1631,6 +1692,14 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) } else { + /* Check if MPLS_TE is activate */ + if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) + /* Add SubTLVs & Adjust real size of SubTLVs */ + te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); + else + /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ + te_is_neigh->sub_tlvs_length = 0; + listnode_add (tlv_data.te_is_neighs, te_is_neigh); lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor", area->area_tag, sysid_print(te_is_neigh->neigh_id), @@ -1679,6 +1748,18 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); metric = circuit->te_metric[level - 1]; SET_TE_METRIC(te_is_neigh, metric); + /* Check if MPLS_TE is activate */ + if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) + /* Update Local and Remote IP address for MPLS TE circuit parameters */ + /* NOTE sure that it is the pertinent place for that updates */ + /* Local IP address could be updated in isis_circuit.c - isis_circuit_add_addr() */ + /* But, where update remote IP address ? in isis_pdu.c - process_p2p_hello() ? */ + + /* Add SubTLVs & Adjust real size of SubTLVs */ + te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); + else + /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ + te_is_neigh->sub_tlvs_length = 0; listnode_add (tlv_data.te_is_neighs, te_is_neigh); lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag, sysid_print(te_is_neigh->neigh_id)); diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index a35bfa7622..7b2286b189 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -112,6 +112,8 @@ void lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost); int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost); const char *lsp_bits2string (u_char *); +void lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, + struct list **to, int frag_thold); /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags (struct isis_lsp *lsp); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 234e516db5..81ca1e20c6 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -50,6 +50,8 @@ #include "isisd/isis_route.h" #include "isisd/isis_routemap.h" #include "isisd/isis_zebra.h" +#include "isisd/isis_tlv.h" +#include "isisd/isis_te.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" @@ -348,6 +350,7 @@ main (int argc, char **argv, char **envp) isis_spf_cmds_init (); isis_redist_init (); isis_route_map_init(); + isis_mpls_te_init(); /* create the global 'isis' instance */ isis_new (1); diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 0401e44a9a..1dfb4623f6 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -53,6 +53,7 @@ #include "isisd/iso_checksum.h" #include "isisd/isis_csm.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" #define ISIS_MINIMUM_FIXED_HDR_LEN 15 #define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */ @@ -630,6 +631,15 @@ process_p2p_hello (struct isis_circuit *circuit) if (found & TLVFLAG_IPV4_ADDR) tlvs_to_adj_ipv4_addrs (&tlvs, adj); + /* Update MPLS TE Remote IP address parameter if possible */ + if (IS_MPLS_TE(isisMplsTE) && circuit->mtc && IS_CIRCUIT_TE(circuit->mtc)) + if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) + { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr (circuit->mtc, *ip_addr); + } + #ifdef HAVE_IPV6 if (found & TLVFLAG_IPV6_ADDR) tlvs_to_adj_ipv6_addrs (&tlvs, adj); diff --git a/isisd/isis_route.c b/isisd/isis_route.c index e72e0cac7a..67d45c8f10 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -50,7 +50,7 @@ #include "isis_zebra.h" static struct isis_nexthop * -isis_nexthop_create (struct in_addr *ip, unsigned int ifindex) +isis_nexthop_create (struct in_addr *ip, ifindex_t ifindex) { struct listnode *node; struct isis_nexthop *nexthop; @@ -91,7 +91,7 @@ isis_nexthop_delete (struct isis_nexthop *nexthop) static int nexthoplookup (struct list *nexthops, struct in_addr *ip, - unsigned int ifindex) + ifindex_t ifindex) { struct listnode *node; struct isis_nexthop *nh; @@ -130,7 +130,7 @@ nexthops_print (struct list *nhs) #ifdef HAVE_IPV6 static struct isis_nexthop6 * -isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) +isis_nexthop6_new (struct in6_addr *ip6, ifindex_t ifindex) { struct isis_nexthop6 *nexthop6; @@ -144,7 +144,7 @@ isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) } static struct isis_nexthop6 * -isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex) +isis_nexthop6_create (struct in6_addr *ip6, ifindex_t ifindex) { struct listnode *node; struct isis_nexthop6 *nexthop6; @@ -181,7 +181,7 @@ isis_nexthop6_delete (struct isis_nexthop6 *nexthop6) static int nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6, - unsigned int ifindex) + ifindex_t ifindex) { struct listnode *node; struct isis_nexthop6 *nh6; diff --git a/isisd/isis_route.h b/isisd/isis_route.h index 5adea2293b..0d2379cbe8 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -28,7 +28,7 @@ #ifdef HAVE_IPV6 struct isis_nexthop6 { - unsigned int ifindex; + ifindex_t ifindex; struct in6_addr ip6; struct in6_addr router_address6; unsigned int lock; @@ -37,7 +37,7 @@ struct isis_nexthop6 struct isis_nexthop { - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ip; struct in_addr router_address; unsigned int lock; diff --git a/isisd/isis_te.c b/isisd/isis_te.c new file mode 100644 index 0000000000..deaaa7104b --- /dev/null +++ b/isisd/isis_te.c @@ -0,0 +1,1369 @@ +/* + * IS-IS Rout(e)ing protocol - isis_te.c + * + * This is an implementation of RFC5305 + * + * Copyright (C) 2014 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 + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> +#include <math.h> + +#include "linklist.h" +#include "thread.h" +#include "vty.h" +#include "stream.h" +#include "memory.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "hash.h" +#include "if.h" +#include "vrf.h" +#include "checksum.h" +#include "md5.h" +#include "sockunion.h" +#include "network.h" + +#include "isisd/dict.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_common.h" +#include "isisd/isis_flags.h" +#include "isisd/isis_circuit.h" +#include "isisd/isisd.h" +#include "isisd/isis_tlv.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_pdu.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_csm.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_te.h" + +/* Global varial for MPLS TE management */ +struct isis_mpls_te isisMplsTE; + +const char *mode2text[] = { "Disable", "Area", "AS", "Emulate" }; + +/*------------------------------------------------------------------------* + * Followings are control functions for MPLS-TE parameters management. + *------------------------------------------------------------------------*/ + +/* Search MPLS TE Circuit context from Interface */ +static struct mpls_te_circuit * +lookup_mpls_params_by_ifp (struct interface *ifp) +{ + struct isis_circuit *circuit; + + if ((circuit = circuit_scan_by_ifp (ifp)) == NULL) + return NULL; + + return circuit->mtc; +} + +/* Create new MPLS TE Circuit context */ +struct mpls_te_circuit * +mpls_te_circuit_new() +{ + struct mpls_te_circuit *mtc; + + zlog_debug ("ISIS MPLS-TE: Create new MPLS TE Circuit context"); + + mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof (struct mpls_te_circuit)); + + if (mtc == NULL) + return NULL; + + mtc->status = disable; + mtc->type = STD_TE; + mtc->length = 0; + + return mtc; + +} + +/* Copy SUB TLVs parameters into a buffer - No space verification are performed */ +/* Caller must verify before that there is enough free space in the buffer */ +u_char +add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) +{ + u_char size, *tlvs = buf; + + zlog_debug ("ISIS MPLS-TE: Add TE Sub TLVs to buffer"); + + if (mtc == NULL) + { + zlog_debug("ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified"); + return 0; + } + + /* Create buffer if not provided */ + if (buf == NULL) + { + zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified"); + return 0; + } + + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) + { + size = SUBTLV_SIZE (&(mtc->admin_grp.header)); + memcpy(tlvs, &(mtc->admin_grp), size); + tlvs += size; + } + + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) + { + size = SUBTLV_SIZE (&(mtc->llri.header)); + memcpy(tlvs, &(mtc->llri), size); + tlvs += size; + } + + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + { + size = SUBTLV_SIZE (&(mtc->local_ipaddr.header)); + memcpy(tlvs, &(mtc->local_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + { + size = SUBTLV_SIZE (&(mtc->rmt_ipaddr.header)); + memcpy(tlvs, &(mtc->rmt_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->max_bw.header)); + memcpy(tlvs, &(mtc->max_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->max_rsv_bw.header)); + memcpy(tlvs, &(mtc->max_rsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->unrsv_bw.header)); + memcpy(tlvs, &(mtc->unrsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) + { + size = SUBTLV_SIZE (&(mtc->te_metric.header)); + memcpy(tlvs, &(mtc->te_metric), size); + tlvs += size; + } + + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) + { + size = SUBTLV_SIZE (&(mtc->av_delay.header)); + memcpy(tlvs, &(mtc->av_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) + { + size = SUBTLV_SIZE (&(mtc->mm_delay.header)); + memcpy(tlvs, &(mtc->mm_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) + { + size = SUBTLV_SIZE (&(mtc->delay_var.header)); + memcpy(tlvs, &(mtc->delay_var), size); + tlvs += size; + } + + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) + { + size = SUBTLV_SIZE (&(mtc->pkt_loss.header)); + memcpy(tlvs, &(mtc->pkt_loss), size); + tlvs += size; + } + + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->res_bw.header)); + memcpy(tlvs, &(mtc->res_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->ava_bw.header)); + memcpy(tlvs, &(mtc->ava_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->use_bw.header)); + memcpy(tlvs, &(mtc->use_bw), size); + tlvs += size; + } + + /* Update SubTLVs length */ + mtc->length = subtlvs_len(mtc); + + zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length); + + return mtc->length; +} + +/* Compute total Sub-TLVs size */ +u_char +subtlvs_len (struct mpls_te_circuit *mtc) +{ + int length = 0; + + /* Sanity Check */ + if (mtc == NULL) + return 0; + + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) + length += SUBTLV_SIZE (&(mtc->admin_grp.header)); + + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) + length += SUBTLV_SIZE (&mtc->llri.header); + + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + length += SUBTLV_SIZE (&mtc->local_ipaddr.header); + + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + length += SUBTLV_SIZE (&mtc->rmt_ipaddr.header); + + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) + length += SUBTLV_SIZE (&mtc->max_bw.header); + + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) + length += SUBTLV_SIZE (&mtc->max_rsv_bw.header); + + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) + length += SUBTLV_SIZE (&mtc->unrsv_bw.header); + + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) + length += SUBTLV_SIZE (&mtc->te_metric.header); + + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) + length += SUBTLV_SIZE (&mtc->av_delay.header); + + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) + length += SUBTLV_SIZE (&mtc->mm_delay.header); + + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) + length += SUBTLV_SIZE (&mtc->delay_var.header); + + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) + length += SUBTLV_SIZE (&mtc->pkt_loss.header); + + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) + length += SUBTLV_SIZE (&mtc->res_bw.header); + + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) + length += SUBTLV_SIZE (&mtc->ava_bw.header); + + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) + length += SUBTLV_SIZE (&mtc->use_bw.header); + + /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */ + if (length > MAX_SUBTLV_SIZE) + { + mtc->length = 0; + return 0; + } + + mtc->length = (u_char)length; + + return mtc->length; +} + +/* Following are various functions to set MPLS TE parameters */ +static void +set_circuitparams_admin_grp (struct mpls_te_circuit *mtc, u_int32_t admingrp) +{ + SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP; + SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE; + mtc->admin_grp.value = htonl(admingrp); + return; +} + +static void __attribute__ ((unused)) +set_circuitparams_llri (struct mpls_te_circuit *mtc, u_int32_t local, u_int32_t remote) +{ + SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI; + SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE; + mtc->llri.local = htonl(local); + mtc->llri.remote = htonl(remote); +} + +void +set_circuitparams_local_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +{ + + SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR; + SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE; + mtc->local_ipaddr.value.s_addr = addr.s_addr; + return; +} + +void +set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +{ + + SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR; + SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE; + mtc->rmt_ipaddr.value.s_addr = addr.s_addr; + return; +} + +static void +set_circuitparams_max_bw (struct mpls_te_circuit *mtc, float fp) +{ + SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW; + SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE; + mtc->max_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_max_rsv_bw (struct mpls_te_circuit *mtc, float fp) +{ + SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW; + SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE; + mtc->max_rsv_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_unrsv_bw (struct mpls_te_circuit *mtc, int priority, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW; + SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE; + mtc->unrsv_bw.value[priority] = htonf(fp); + return; +} + +static void +set_circuitparams_te_metric (struct mpls_te_circuit *mtc, u_int32_t te_metric) +{ + SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC; + SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE; + mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF; + mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF; + mtc->te_metric.value[2] = te_metric & 0xFF; + return; +} + +static void +set_circuitparams_inter_as (struct mpls_te_circuit *mtc, struct in_addr addr, u_int32_t as) +{ + + /* Set the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP; + SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE; + mtc->rip.value.s_addr = addr.s_addr; + + SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS; + SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE; + mtc->ras.value = htonl(as); +} + +static void +unset_circuitparams_inter_as (struct mpls_te_circuit *mtc) +{ + + /* Reset the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = 0; + SUBTLV_LEN(mtc->rip) = 0; + mtc->rip.value.s_addr = 0; + + SUBTLV_TYPE(mtc->ras) = 0; + SUBTLV_LEN(mtc->ras) = 0; + mtc->ras.value = 0; +} + +static void +set_circuitparams_av_delay (struct mpls_te_circuit *mtc, u_int32_t delay, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY; + SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE; + tmp = delay & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->av_delay.value = htonl(tmp); + return; +} + +static void +set_circuitparams_mm_delay (struct mpls_te_circuit *mtc, 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. */ + SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY; + SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE; + tmp = low & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->mm_delay.low = htonl(tmp); + mtc->mm_delay.high = htonl(high); + return; +} + +static void +set_circuitparams_delay_var (struct mpls_te_circuit *mtc, u_int32_t jitter) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR; + SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE; + mtc->delay_var.value = htonl(jitter & TE_EXT_MASK); + return; +} + +static void +set_circuitparams_pkt_loss (struct mpls_te_circuit *mtc, u_int32_t loss, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS; + SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE; + tmp = loss & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->pkt_loss.value = htonl(tmp); + return; +} + +static void +set_circuitparams_res_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW; + SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE; + mtc->res_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_ava_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW; + SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE; + mtc->ava_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_use_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW; + SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE; + mtc->use_bw.value = htonf(fp); + return; +} + +/* Main initialization / update function of the MPLS TE Circuit context */ +/* Call when interface TE Link parameters are modified */ +void +isis_link_params_update (struct isis_circuit *circuit, struct interface *ifp) +{ + int i; + struct prefix_ipv4 *addr; + struct mpls_te_circuit *mtc; + + /* Sanity Check */ + if ((circuit == NULL) || (ifp == NULL)) + return; + + zlog_info ("MPLS-TE: Initialize circuit parameters for interface %s", ifp->name); + + /* Check if MPLS TE Circuit context has not been already created */ + if (circuit->mtc == NULL) + circuit->mtc = mpls_te_circuit_new(); + + mtc = circuit->mtc; + + /* Fulfil MTC TLV from ifp TE Link parameters */ + if (HAS_LINK_PARAMS(ifp)) + { + mtc->status = enable; + /* STD_TE metrics */ + if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) + set_circuitparams_admin_grp (mtc, ifp->link_params->admin_grp); + else + SUBTLV_TYPE(mtc->admin_grp) = 0; + + /* If not already set, register local IP addr from ip_addr list if it exists */ + if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) + { + if (circuit->ip_addrs != NULL && listcount(circuit->ip_addrs) != 0) + { + addr = (struct prefix_ipv4 *)listgetdata ((struct listnode *)listhead (circuit->ip_addrs)); + set_circuitparams_local_ipaddr (mtc, addr->prefix); + } + } + + /* If not already set, try to determine Remote IP addr if circuit is P2P */ + if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0) && (circuit->circ_type == CIRCUIT_T_P2P)) + { + struct isis_adjacency *adj = circuit->u.p2p.neighbor; + if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) + { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr (mtc, *ip_addr); + } + } + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) + set_circuitparams_max_bw (mtc, ifp->link_params->max_bw); + else + SUBTLV_TYPE(mtc->max_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) + set_circuitparams_max_rsv_bw (mtc, ifp->link_params->max_rsv_bw); + else + SUBTLV_TYPE(mtc->max_rsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) + for (i = 0; i < MAX_CLASS_TYPE; i++) + set_circuitparams_unrsv_bw (mtc, i, ifp->link_params->unrsv_bw[i]); + else + SUBTLV_TYPE(mtc->unrsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_TE)) + set_circuitparams_te_metric(mtc, ifp->link_params->te_metric); + else + SUBTLV_TYPE(mtc->te_metric) = 0; + + /* TE metric Extensions */ + if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) + set_circuitparams_av_delay(mtc, ifp->link_params->av_delay, 0); + else + SUBTLV_TYPE(mtc->av_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) + set_circuitparams_mm_delay(mtc, ifp->link_params->min_delay, ifp->link_params->max_delay, 0); + else + SUBTLV_TYPE(mtc->mm_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) + set_circuitparams_delay_var(mtc, ifp->link_params->delay_var); + else + SUBTLV_TYPE(mtc->delay_var) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) + set_circuitparams_pkt_loss(mtc, ifp->link_params->pkt_loss, 0); + else + SUBTLV_TYPE(mtc->pkt_loss) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) + set_circuitparams_res_bw(mtc, ifp->link_params->res_bw); + else + SUBTLV_TYPE(mtc->res_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) + set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw); + else + SUBTLV_TYPE(mtc->ava_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) + set_circuitparams_use_bw(mtc, ifp->link_params->use_bw); + else + SUBTLV_TYPE(mtc->use_bw) = 0; + + /* INTER_AS */ + if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) + set_circuitparams_inter_as(mtc, ifp->link_params->rmt_ip, ifp->link_params->rmt_as); + else + /* reset inter-as TE params */ + unset_circuitparams_inter_as (mtc); + + /* Compute total length of SUB TLVs */ + mtc->length = subtlvs_len(mtc); + + } + else + mtc->status = disable; + + /* Finally Update LSP */ +#if 0 + if (IS_MPLS_TE(isisMplsTE) && circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); +#endif + return; +} + +void +isis_mpls_te_update (struct interface *ifp) +{ + struct isis_circuit *circuit; + + /* Sanity Check */ + if (ifp == NULL) + return; + + /* Get circuit context from interface */ + if ((circuit = circuit_scan_by_ifp(ifp)) == NULL) + return; + + /* Update TE TLVs ... */ + isis_link_params_update(circuit, ifp); + + /* ... and LSP */ + if (IS_MPLS_TE(isisMplsTE) && circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty session control functions. + *------------------------------------------------------------------------*/ + +static u_char +show_vty_subtlv_admin_grp (struct vty *vty, struct te_subtlv_admin_grp *tlv) +{ + + if (vty != NULL) + vty_out (vty, " Administrative Group: 0x%x%s", + (u_int32_t) ntohl (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Administrative Group: 0x%x", + (u_int32_t) ntohl (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_llri (struct vty *vty, struct te_subtlv_llri *tlv) +{ + if (vty != NULL) + { + vty_out (vty, " Link Local ID: %d%s", (u_int32_t) ntohl (tlv->local), + VTY_NEWLINE); + vty_out (vty, " Link Remote ID: %d%s", (u_int32_t) ntohl (tlv->remote), + VTY_NEWLINE); + } + else + { + zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (tlv->local)); + zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (tlv->remote)); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE); +} + +static u_char +show_vty_subtlv_local_ipaddr (struct vty *vty, struct te_subtlv_local_ipaddr *tlv) +{ + if (vty != NULL) + vty_out (vty, " Local Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Local Interface IP Address(es): %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_rmt_ipaddr (struct vty *vty, struct te_subtlv_rmt_ipaddr *tlv) +{ + if (vty != NULL) + vty_out (vty, " Remote Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Remote Interface IP Address(es): %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_max_bw (struct vty *vty, struct te_subtlv_max_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_max_rsv_bw (struct vty *vty, struct te_subtlv_max_rsv_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, + VTY_NEWLINE); + else + zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_unrsv_bw (struct vty *vty, struct te_subtlv_unrsv_bw *tlv) +{ + float fval1, fval2; + int i; + + if (vty != NULL) + vty_out (vty, " Unreserved Bandwidth:%s",VTY_NEWLINE); + else + zlog_debug (" Unreserved Bandwidth:"); + + for (i = 0; i < MAX_CLASS_TYPE; i+=2) + { + fval1 = ntohf (tlv->value[i]); + fval2 = ntohf (tlv->value[i+1]); + if (vty != NULL) + vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s", i, fval1, i+1, fval2, VTY_NEWLINE); + else + zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", i, fval1, i+1, fval2); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE); +} + +static u_char +show_vty_subtlv_te_metric (struct vty *vty, struct te_subtlv_te_metric *tlv) +{ + u_int32_t te_metric; + + te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16; + if (vty != NULL) + vty_out (vty, " Traffic Engineering Metric: %u%s", te_metric, VTY_NEWLINE); + else + zlog_debug (" Traffic Engineering Metric: %u", te_metric); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_ras (struct vty *vty, struct te_subtlv_ras *tlv) +{ + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote AS number: %u%s", ntohl (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_rip (struct vty *vty, struct te_subtlv_rip *tlv) +{ + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote ASBR IP address: %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_av_delay (struct vty *vty, struct te_subtlv_av_delay *tlv) +{ + u_int32_t delay; + u_int32_t A; + + delay = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Average Link Delay: %d (micro-sec)%s", A ? "Anomalous" : "Normal", delay, VTY_NEWLINE); + else + zlog_debug (" %s Average Link Delay: %d (micro-sec)", A ? "Anomalous" : "Normal", delay); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_mm_delay (struct vty *vty, struct te_subtlv_mm_delay *tlv) +{ + u_int32_t low, high; + u_int32_t A; + + low = (u_int32_t) ntohl (tlv->low) & TE_EXT_MASK; + A = (u_int32_t) ntohl (tlv->low) & TE_EXT_ANORMAL; + high = (u_int32_t) ntohl (tlv->high) & TE_EXT_MASK; + + if (vty != NULL) + vty_out (vty, " %s Min/Max Link Delay: %d / %d (micro-sec)%s", A ? "Anomalous" : "Normal", low, high, VTY_NEWLINE); + else + zlog_debug (" %s Min/Max Link Delay: %d / %d (micro-sec)", A ? "Anomalous" : "Normal", low, high); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_delay_var (struct vty *vty, struct te_subtlv_delay_var *tlv) +{ + u_int32_t jitter; + + jitter = (u_int32_t) ntohl (tlv->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 (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_pkt_loss (struct vty *vty, struct te_subtlv_pkt_loss *tlv) +{ + u_int32_t loss; + u_int32_t A; + float fval; + + loss = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + fval = (float) (loss * LOSS_PRECISION); + A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Link Packet Loss: %g (%%)%s", A ? "Anomalous" : "Normal", fval, VTY_NEWLINE); + else + zlog_debug (" %s Link Packet Loss: %g (%%)", A ? "Anomalous" : "Normal", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_res_bw (struct vty *vty, struct te_subtlv_res_bw *tlv) +{ + float fval; + + fval = ntohf(tlv->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 (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_ava_bw (struct vty *vty, struct te_subtlv_ava_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_use_bw (struct vty *vty, struct te_subtlv_use_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->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 (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_unknown_tlv (struct vty *vty, struct subtlv_header *tlvh) +{ + int i, rtn = 1; + u_char *v = (u_char *)tlvh; + + if (vty != NULL) + { + if (tlvh->length != 0) + { + vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]%s", + tlvh->type, tlvh->length, VTY_NEWLINE); + vty_out(vty, " Dump: [00]"); + rtn = 1; /* initialize end of line counter */ + for (i = 0; i < tlvh->length; i++) + { + vty_out (vty, " %#.2x", v[i]); + if (rtn == 8) + { + vty_out (vty, "%s [%.2x]", VTY_NEWLINE, i + 1); + rtn = 1; + } + else + rtn++; + } + vty_out (vty, "%s", VTY_NEWLINE); + } + else + vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]%s", + tlvh->type, tlvh->length, VTY_NEWLINE); + } + else + { + zlog_debug (" Unknown TLV: [type(%#.2x), length(%#.2x)]", + tlvh->type, tlvh->length); + } + + return SUBTLV_SIZE(tlvh); +} + +/* Main Show function */ +void +mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) +{ + struct subtlv_header *tlvh, *next; + u_int16_t sum = 0; + + zlog_debug ("ISIS MPLS-TE: Show database TE detail"); + + tlvh = (struct subtlv_header *)te->sub_tlvs; + + for (; sum < te->sub_tlvs_length; tlvh = (next ? next : SUBTLV_HDR_NEXT (tlvh))) + { + next = NULL; + + switch (tlvh->type) + { + case TE_SUBTLV_ADMIN_GRP: + sum += show_vty_subtlv_admin_grp (vty, (struct te_subtlv_admin_grp *)tlvh); + break; + case TE_SUBTLV_LLRI: + sum += show_vty_subtlv_llri (vty, (struct te_subtlv_llri *)tlvh); + break; + case TE_SUBTLV_LOCAL_IPADDR: + sum += show_vty_subtlv_local_ipaddr (vty, (struct te_subtlv_local_ipaddr *)tlvh); + break; + case TE_SUBTLV_RMT_IPADDR: + sum += show_vty_subtlv_rmt_ipaddr (vty, (struct te_subtlv_rmt_ipaddr *)tlvh); + break; + case TE_SUBTLV_MAX_BW: + sum += show_vty_subtlv_max_bw (vty, (struct te_subtlv_max_bw *)tlvh); + break; + case TE_SUBTLV_MAX_RSV_BW: + sum += show_vty_subtlv_max_rsv_bw (vty, (struct te_subtlv_max_rsv_bw *)tlvh); + break; + case TE_SUBTLV_UNRSV_BW: + sum += show_vty_subtlv_unrsv_bw (vty, (struct te_subtlv_unrsv_bw *)tlvh); + break; + case TE_SUBTLV_TE_METRIC: + sum += show_vty_subtlv_te_metric (vty, (struct te_subtlv_te_metric *)tlvh); + break; + case TE_SUBTLV_RAS: + sum += show_vty_subtlv_ras (vty, (struct te_subtlv_ras *)tlvh); + break; + case TE_SUBTLV_RIP: + sum += show_vty_subtlv_rip (vty, (struct te_subtlv_rip *)tlvh); + break; + case TE_SUBTLV_AV_DELAY: + sum += show_vty_subtlv_av_delay (vty, (struct te_subtlv_av_delay *)tlvh); + break; + case TE_SUBTLV_MM_DELAY: + sum += show_vty_subtlv_mm_delay (vty, (struct te_subtlv_mm_delay *)tlvh); + break; + case TE_SUBTLV_DELAY_VAR: + sum += show_vty_subtlv_delay_var (vty, (struct te_subtlv_delay_var *)tlvh); + break; + case TE_SUBTLV_PKT_LOSS: + sum += show_vty_subtlv_pkt_loss (vty, (struct te_subtlv_pkt_loss *)tlvh); + break; + case TE_SUBTLV_RES_BW: + sum += show_vty_subtlv_res_bw (vty, (struct te_subtlv_res_bw *)tlvh); + break; + case TE_SUBTLV_AVA_BW: + sum += show_vty_subtlv_ava_bw (vty, (struct te_subtlv_ava_bw *)tlvh); + break; + case TE_SUBTLV_USE_BW: + sum += show_vty_subtlv_use_bw (vty, (struct te_subtlv_use_bw *)tlvh); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + return; +} + +/* Specific MPLS TE router parameters write function */ +void +isis_mpls_te_config_write_router (struct vty *vty) +{ + + zlog_debug ("ISIS MPLS-TE: Write ISIS router configuration"); + + if (IS_MPLS_TE(isisMplsTE)) + { + vty_out (vty, " mpls-te on%s", VTY_NEWLINE); + vty_out (vty, " mpls-te router-address %s%s", + inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE); + } + + return; +} + + +/*------------------------------------------------------------------------* + * Followings are vty command functions. + *------------------------------------------------------------------------*/ + +DEFUN (isis_mpls_te_on, + isis_mpls_te_on_cmd, + "mpls-te on", + MPLS_TE_STR + "Enable MPLS-TE functionality\n") +{ + struct listnode *node; + struct isis_circuit *circuit; + + if (IS_MPLS_TE(isisMplsTE)) + return CMD_SUCCESS; + + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug ("ISIS MPLS-TE: OFF -> ON"); + + isisMplsTE.status = enable; + + /* + * Following code is intended to handle two cases; + * + * 1) MPLS-TE was disabled at startup time, but now become enabled. + * In this case, we must enable MPLS-TE Circuit regarding interface MPLS_TE flag + * 2) MPLS-TE was once enabled then disabled, and now enabled again. + */ + for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) + { + if (circuit->mtc == NULL || IS_FLOOD_AS (circuit->mtc->type)) + continue; + + if ((circuit->mtc->status == disable) + && HAS_LINK_PARAMS(circuit->interface)) + circuit->mtc->status = enable; + else + continue; + + /* Reoriginate STD_TE & GMPLS circuits */ + if (circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + } + + return CMD_SUCCESS; +} + +DEFUN (no_isis_mpls_te_on, + no_isis_mpls_te_on_cmd, + "no mpls-te", + NO_STR + "Disable the MPLS-TE functionality\n") +{ + struct listnode *node; + struct isis_circuit *circuit; + + if (isisMplsTE.status == disable) + return CMD_SUCCESS; + + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug ("ISIS MPLS-TE: ON -> OFF"); + + isisMplsTE.status = disable; + + /* Flush LSP if circuit engage */ + for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) + { + if (circuit->mtc == NULL || (circuit->mtc->status == disable)) + continue; + + /* disable MPLS_TE Circuit */ + circuit->mtc->status = disable; + + /* Re-originate circuit without STD_TE & GMPLS parameters */ + if (circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + } + + return CMD_SUCCESS; +} + +DEFUN (isis_mpls_te_router_addr, + isis_mpls_te_router_addr_cmd, + "mpls-te router-address A.B.C.D", + MPLS_TE_STR + "Stable IP address of the advertising router\n" + "MPLS-TE router address in IPv4 address format\n") +{ + struct in_addr value; + struct listnode *node; + struct isis_area *area; + + if (! inet_aton (argv[0], &value)) + { + vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + isisMplsTE.router_id.s_addr = value.s_addr; + + if (isisMplsTE.status == disable) + return CMD_SUCCESS; + + /* Update main Router ID in isis global structure */ + isis->router_id = value.s_addr; + /* And re-schedule LSP update */ + for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) + if (listcount (area->area_addrs) > 0) + lsp_regenerate_schedule (area, area->is_type, 0); + + return CMD_SUCCESS; +} + +DEFUN (isis_mpls_te_inter_as, + isis_mpls_te_inter_as_cmd, + "mpls-te inter-as (level-1|level-1-2|level-2-only)", + MPLS_TE_STR + "Configure MPLS-TE Inter-AS support\n" + "AREA native mode self originate INTER-AS LSP with L1 only flooding scope)\n" + "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n" + "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n") +{ + vty_out (vty, "Not yet supported%s", VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (no_isis_mpls_te_inter_as, + no_isis_mpls_te_inter_as_cmd, + "no mpls-te inter-as", + NO_STR + "Disable the MPLS-TE functionality\n" + "Disable MPLS-TE Inter-AS support\n") +{ + + vty_out (vty, "Not yet supported%s", VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (show_isis_mpls_te_router, + show_isis_mpls_te_router_cmd, + "show isis mpls-te router", + SHOW_STR + ISIS_STR + MPLS_TE_STR + "Router information\n") +{ + if (IS_MPLS_TE(isisMplsTE)) + { + vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE); + + if (vty != NULL) + { + if (ntohs (isisMplsTE.router_id.s_addr) != 0) + vty_out (vty, " Router-Address: %s%s", inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE); + else + vty_out (vty, " N/A%s", VTY_NEWLINE); + } + } + else + vty_out (vty, " MPLS-TE is disable on this router%s", VTY_NEWLINE); + + return CMD_SUCCESS; +} + +static void +show_mpls_te_sub (struct vty *vty, struct interface *ifp) +{ + struct mpls_te_circuit *mtc; + + if ((IS_MPLS_TE(isisMplsTE)) + && ((mtc = lookup_mpls_params_by_ifp (ifp)) != NULL)) + { + /* Continue only if interface is not passive or support Inter-AS TEv2 */ + if (mtc->status != enable) + { + if (IS_INTER_AS(mtc->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_subtlv_admin_grp (vty, &mtc->admin_grp); + + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + show_vty_subtlv_local_ipaddr (vty, &mtc->local_ipaddr); + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + show_vty_subtlv_rmt_ipaddr (vty, &mtc->rmt_ipaddr); + + show_vty_subtlv_max_bw (vty, &mtc->max_bw); + show_vty_subtlv_max_rsv_bw (vty, &mtc->max_rsv_bw); + show_vty_subtlv_unrsv_bw (vty, &mtc->unrsv_bw); + show_vty_subtlv_te_metric (vty, &mtc->te_metric); + + if (IS_INTER_AS(mtc->type)) + { + if (SUBTLV_TYPE(mtc->ras) != 0) + show_vty_subtlv_ras (vty, &mtc->ras); + if (SUBTLV_TYPE(mtc->rip) != 0) + show_vty_subtlv_rip (vty, &mtc->rip); + } + + show_vty_subtlv_av_delay (vty, &mtc->av_delay); + show_vty_subtlv_mm_delay (vty, &mtc->mm_delay); + show_vty_subtlv_delay_var (vty, &mtc->delay_var); + show_vty_subtlv_pkt_loss (vty, &mtc->pkt_loss); + show_vty_subtlv_res_bw (vty, &mtc->res_bw); + show_vty_subtlv_ava_bw (vty, &mtc->ava_bw); + show_vty_subtlv_use_bw (vty, &mtc->use_bw); + vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE); + } + else + { + vty_out (vty, " %s: MPLS-TE is disabled on this interface%s", + ifp->name, VTY_NEWLINE); + } + + return; +} + +DEFUN (show_isis_mpls_te_interface, + show_isis_mpls_te_interface_cmd, + "show isis mpls-te interface [INTERFACE]", + SHOW_STR + ISIS_STR + MPLS_TE_STR + "Interface information\n" + "Interface name\n") +{ + struct interface *ifp; + struct listnode *node; + + /* Show All Interfaces. */ + if (argc == 0) + { + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + show_mpls_te_sub (vty, ifp); + } + /* Interface name is specified. */ + else + { + if ((ifp = if_lookup_by_name (argv[0])) == NULL) + vty_out (vty, "No such interface name%s", VTY_NEWLINE); + else + show_mpls_te_sub (vty, ifp); + } + + return CMD_SUCCESS; +} + +/* Initialize MPLS_TE */ +void +isis_mpls_te_init (void) +{ + + zlog_debug("ISIS MPLS-TE: Initialize"); + + /* Initialize MPLS_TE structure */ + isisMplsTE.status = disable; + isisMplsTE.level = 0; + isisMplsTE.inter_as = off; + isisMplsTE.interas_areaid.s_addr = 0; + isisMplsTE.cir_list = list_new(); + isisMplsTE.router_id.s_addr = 0; + + /* Register new VTY commands */ + install_element (VIEW_NODE, &show_isis_mpls_te_router_cmd); + install_element (VIEW_NODE, &show_isis_mpls_te_interface_cmd); + install_element (ENABLE_NODE, &show_isis_mpls_te_router_cmd); + install_element (ENABLE_NODE, &show_isis_mpls_te_interface_cmd); + + install_element (ISIS_NODE, &isis_mpls_te_on_cmd); + install_element (ISIS_NODE, &no_isis_mpls_te_on_cmd); + install_element (ISIS_NODE, &isis_mpls_te_router_addr_cmd); + install_element (ISIS_NODE, &isis_mpls_te_inter_as_cmd); + install_element (ISIS_NODE, &no_isis_mpls_te_inter_as_cmd); + + return; +} diff --git a/isisd/isis_te.h b/isisd/isis_te.h new file mode 100644 index 0000000000..4cec1735ae --- /dev/null +++ b/isisd/isis_te.h @@ -0,0 +1,331 @@ +/* + * IS-IS Rout(e)ing protocol - isis_te.c + * + * This is an implementation of RFC5305, RFC 5307 and draft-ietf-isis-te-metric-extensions-11 + * + * Copyright (C) 2014 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 + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_ISIS_MPLS_TE_H +#define _ZEBRA_ISIS_MPLS_TE_H + +/* + * Traffic Engineering information are transport through LSP: + * - Extended IS Reachability TLV = 22 + * - Traffic Engineering Router ID TLV = 134 + * - Extended IP Reachability TLV = 135 + * - Inter-AS Reachability Information TLV = 141 + * + * and support following sub-TLV: + * + * Name Value Status + * _________________________________________________ + * Administartive group (color) 3 RFC5305 + * Link Local/Remote Identifiers 4 RFC5307 + * IPv4 interface address 6 RFC5305 + * IPv4 neighbor address 8 RFC5305 + * Maximum link bandwidth 9 RFC5305 + * Reservable link bandwidth 10 RFC5305 + * Unreserved bandwidth 11 RFC5305 + * TE Default metric 18 RFC5305 + * Link Protection Type 20 RFC5307 + * Interface Switching Capability 21 RFC5307 + * Remote AS number 24 RFC5316 + * IPv4 Remote ASBR identifier 25 RFC5316 + * + */ + +/* NOTE: RFC5316 is not yet supported in this version */ + +/* Following define the type of TE link regarding the various RFC */ +#define STD_TE 0x01 +#define GMPLS 0x02 +#define INTER_AS 0x04 +#define FLOOD_L1 0x10 +#define FLOOD_L2 0x20 +#define FLOOD_AS 0x40 +#define EMULATED 0x80 + +#define IS_STD_TE(x) (x & STD_TE) +#define IS_INTER_AS(x) (x & INTER_AS) +#define IS_EMULATED(x) (x & EMULATED) +#define IS_FLOOD_L1(x) (x & FLOOD_L1) +#define IS_FLOOD_L2(x) (x & FLOOD_L2) +#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) + +/* + * Following section defines subTLV (tag, length, value) structures, + * used for Traffic Engineering. + */ +struct subtlv_header +{ + u_char type; /* sub_TLV_XXX type (see above) */ + u_char length; /* Value portion only, in byte */ +}; + +#define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */ + +#define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length) + +#define SUBTLV_HDR_TOP(lsph) (struct subtlv_header *)((char *)(lsph) + ISIS_LSP_HEADER_SIZE) + +#define SUBTLV_HDR_NEXT(stlvh) (struct subtlv_header *)((char *)(stlvh) + SUBTLV_SIZE(stlvh)) + +#define SUBTLV_TYPE(stlvh) stlvh.header.type +#define SUBTLV_LEN(stlvh) stlvh.header.length +#define SUBTLV_VAL(stlvh) stlvh.value +#define SUBTLV_DATA(stlvh) stlvh + SUBTLV_HDR_SIZE + +#define SUBTLV_DEF_SIZE 4 + +/* Link Sub-TLV: Resource Class/Color - RFC 5305 */ +#define TE_SUBTLV_ADMIN_GRP 3 +struct te_subtlv_admin_grp +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Admin. group membership. */ +} __attribute__((__packed__)); + +/* Link Local/Remote Identifiers - RFC 5307 */ +#define TE_SUBTLV_LLRI 4 +#define TE_SUBTLV_LLRI_SIZE 8 +struct te_subtlv_llri +{ + struct subtlv_header header; /* Value length is 8 octets. */ + u_int32_t local; /* Link Local Identifier */ + u_int32_t remote; /* Link Remote Identifier */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Local Interface IP Address - RFC 5305 */ +#define TE_SUBTLV_LOCAL_IPADDR 6 +struct te_subtlv_local_ipaddr +{ + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Local IP address(es). */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Neighbor Interface IP Address - RFC 5305 */ +#define TE_SUBTLV_RMT_IPADDR 8 +struct te_subtlv_rmt_ipaddr +{ + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Neighbor's IP address(es). */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Maximum Bandwidth - RFC 5305 */ +#define TE_SUBTLV_MAX_BW 9 +struct te_subtlv_max_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Maximum Reservable Bandwidth - RFC 5305 */ +#define TE_SUBTLV_MAX_RSV_BW 10 +struct te_subtlv_max_rsv_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unreserved Bandwidth - RFC 5305 */ +#define TE_SUBTLV_UNRSV_BW 11 +#define TE_SUBTLV_UNRSV_SIZE 32 +struct te_subtlv_unrsv_bw +{ + struct subtlv_header header; /* Value length is 32 octets. */ + float value[8]; /* One for each priority level. */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Traffic Engineering Metric - RFC 5305 */ +#define TE_SUBTLV_TE_METRIC 18 +#define TE_SUBTLV_TE_METRIC_SIZE 3 +struct te_subtlv_te_metric +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_char value[3]; /* Link metric for TE purpose. */ +} __attribute__((__packed__)); + +/* Remote AS Number sub-TLV - RFC5316 */ +#define TE_SUBTLV_RAS 24 +struct te_subtlv_ras +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Remote AS number */ +} __attribute__((__packed__)); + +/* IPv4 Remote ASBR ID Sub-TLV - RFC5316 */ +#define TE_SUBTLV_RIP 25 +struct te_subtlv_rip +{ + struct subtlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Remote ASBR IP address */ +} __attribute__((__packed__)); + + +/* draft-ietf-isis-te-metric-extensions-11.txt */ +/* Link Sub-TLV: Average Link Delay */ +#define TE_SUBTLV_AV_DELAY 33 +struct te_subtlv_av_delay +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* Average delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit (A) as Upper most bit */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Low/High Link Delay */ +#define TE_SUBTLV_MM_DELAY 34 +#define TE_SUBTLV_MM_DELAY_SIZE 8 +struct te_subtlv_mm_delay +{ + struct subtlv_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 */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Link Delay Variation i.e. Jitter */ +#define TE_SUBTLV_DELAY_VAR 35 +struct te_subtlv_delay_var +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... 16777215 */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */ +#define TE_SUBTLV_PKT_LOSS 36 +struct te_subtlv_pkt_loss +{ + struct subtlv_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 (A) as Upper most bit */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */ +#define TE_SUBTLV_RES_BW 37 +struct te_subtlv_res_bw +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */ +#define TE_SUBTLV_AVA_BW 38 +struct te_subtlv_ava_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */ +#define TE_SUBTLV_USE_BW 39 +struct te_subtlv_use_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +#define TE_SUBTLV_MAX 40 /* Last SUBTLV + 1 */ + +/* Following declaration concerns the MPLS-TE and LINk-TE management */ +typedef enum _status_t { disable, enable, learn } status_t; + +/* Mode for Inter-AS LSP */ /* TODO: Check how if LSP is flooded in RFC5316 */ +typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t; + +#define IS_MPLS_TE(m) (m.status == enable) +#define IS_CIRCUIT_TE(c) (c->status == enable) + +/* Following structure are internal use only. */ +struct isis_mpls_te +{ + /* Status of MPLS-TE: enable or disable */ + status_t status; + + /* L1, L1-L2, L2-Only */ + u_int8_t level; + + /* RFC5316 */ + interas_mode_t inter_as; + struct in_addr interas_areaid; + + /* Circuit list on which TE are enable */ + struct list *cir_list; + + /* MPLS_TE router ID */ + struct in_addr router_id; +}; + +extern struct isis_mpls_te isisMplsTE; + +struct mpls_te_circuit +{ + + /* Status of MPLS-TE on this interface */ + status_t status; + + /* Type of MPLS-TE circuit: STD_TE(RFC5305), INTER_AS(RFC5316), INTER_AS_EMU(RFC5316 emulated) */ + u_int8_t type; + + /* Total size of sub_tlvs */ + u_char length; + + /* Store subTLV in network byte order. */ + /* RFC5305 */ + struct te_subtlv_admin_grp admin_grp; + /* RFC5307 */ + struct te_subtlv_llri llri; + /* RFC5305 */ + struct te_subtlv_local_ipaddr local_ipaddr; + struct te_subtlv_rmt_ipaddr rmt_ipaddr; + struct te_subtlv_max_bw max_bw; + struct te_subtlv_max_rsv_bw max_rsv_bw; + struct te_subtlv_unrsv_bw unrsv_bw; + struct te_subtlv_te_metric te_metric; + /* RFC5316 */ + struct te_subtlv_ras ras; + struct te_subtlv_rip rip; + /* draft-ietf-isis-te-metric-extension */ + struct te_subtlv_av_delay av_delay; + struct te_subtlv_mm_delay mm_delay; + struct te_subtlv_delay_var delay_var; + struct te_subtlv_pkt_loss pkt_loss; + struct te_subtlv_res_bw res_bw; + struct te_subtlv_ava_bw ava_bw; + struct te_subtlv_use_bw use_bw; +}; + +/* Prototypes. */ +void isis_mpls_te_init (void); +struct mpls_te_circuit *mpls_te_circuit_new(void); +void mpls_te_print_detail(struct vty *, struct te_is_neigh *); +void set_circuitparams_local_ipaddr (struct mpls_te_circuit *, struct in_addr); +void set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *, struct in_addr); +u_char subtlvs_len (struct mpls_te_circuit *); +u_char add_te_subtlvs(u_char *, struct mpls_te_circuit *); +u_char build_te_subtlvs(u_char *, struct isis_circuit *); +void isis_link_params_update(struct isis_circuit *, struct interface *); +void isis_mpls_te_update(struct interface *); +void isis_mpls_te_config_write_router (struct vty *); + +#endif /* _ZEBRA_ISIS_MPLS_TE_H */ diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c index b4017b5f45..1d29d78287 100644 --- a/isisd/isis_tlv.c +++ b/isisd/isis_tlv.c @@ -42,6 +42,7 @@ #include "isisd/isis_misc.h" #include "isisd/isis_pdu.h" #include "isisd/isis_lsp.h" +#include "isisd/isis_te.h" void free_tlv (void *val) @@ -229,9 +230,23 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, while (length > value_len) { te_is_nei = (struct te_is_neigh *) pnt; - value_len += 11; - pnt += 11; - /* FIXME - subtlvs are handled here, for now we skip */ + value_len += IS_NEIGHBOURS_LEN; + pnt += IS_NEIGHBOURS_LEN; + /* FIXME - subtlvs are handled here, for now we skip */ + /* FIXME: All TE SubTLVs are not necessary present in LSP PDU. */ + /* So, it must be copied in a new te_is_neigh structure */ + /* rather than just initialize pointer to the original LSP PDU */ + /* to avoid consider the rest of lspdu as subTLVs or buffer overflow */ + if (IS_MPLS_TE(isisMplsTE)) + { + struct te_is_neigh *new = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh)); + memcpy(new->neigh_id, te_is_nei->neigh_id, ISIS_SYS_ID_LEN + 1); + memcpy(new->te_metric, te_is_nei->te_metric, 3); + new->sub_tlvs_length = te_is_nei->sub_tlvs_length; + memcpy(new->sub_tlvs, pnt, te_is_nei->sub_tlvs_length); + te_is_nei = new; + } + /* Skip SUB TLVs payload */ value_len += te_is_nei->sub_tlvs_length; pnt += te_is_nei->sub_tlvs_length; @@ -845,8 +860,8 @@ tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream) for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh)) { - /* FIXME: This will be wrong if we are going to add TE sub TLVs. */ - if (pos - value + IS_NEIGHBOURS_LEN > 255) + /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */ + if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255) { retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); if (retval != ISIS_OK) @@ -858,9 +873,15 @@ tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream) pos += ISIS_SYS_ID_LEN + 1; memcpy (pos, te_is_neigh->te_metric, 3); pos += 3; - /* Sub TLVs length. */ - *pos = 0; + /* Set the total size of Sub TLVs */ + *pos = te_is_neigh->sub_tlvs_length; pos++; + /* Copy Sub TLVs if any */ + if (te_is_neigh->sub_tlvs_length > 0) + { + memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length); + pos += te_is_neigh->sub_tlvs_length; + } } return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h index 619003a0e3..5a39d564dc 100644 --- a/isisd/isis_tlv.h +++ b/isisd/isis_tlv.h @@ -39,7 +39,7 @@ * LSP Entries 9 n n y ISO10589 * Authentication 10 y y y ISO10589, RFC3567 * Checksum 12 y n y RFC3358 - * TE IS Reachability 22 n y n RFC5305 + * Extended IS Reachability 22 n y n RFC5305 * IS Alias 24 n y n RFC3786 * IP Int. Reachability 128 n y n RFC1195 * Protocols Supported 129 y y n RFC1195 @@ -50,6 +50,7 @@ * Extended IP Reachability 135 n y n RFC5305 * Dynamic Hostname 137 n y n RFC2763 * Shared Risk Link Group 138 n y y RFC5307 + * Inter-AS Reachability 141 n y n RFC5316 * Restart TLV 211 y n n RFC3847 * MT IS Reachability 222 n y n RFC5120 * MT Supported 229 y y n RFC5120 @@ -59,10 +60,10 @@ * MT IPv6 IP Reachability 237 n y n RFC5120 * P2P Adjacency State 240 y n n RFC3373 * IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence - * Router Capability 242 - - - draft-ietf-isis-caps + * Router Capability 242 n y n RFC4971 * * - * IS Reachability sub-TLVs we (should) support. + * IS Reachability sub-TLVs we support (See isis_te.[c,h]) * ____________________________________________________________________________ * Name Value Status * ____________________________________________________________________________ @@ -76,6 +77,8 @@ * TE Default metric 18 RFC5305 * Link Protection Type 20 RFC5307 * Interface Switching Capability 21 RFC5307 + * Remote AS number 24 RFC5316 + * IPv4 Remote ASBR identifier 25 RFC5316 * * * IP Reachability sub-TLVs we (should) support. @@ -109,6 +112,7 @@ #define IPV6_ADDR 232 #define IPV6_REACHABILITY 236 #define WAY3_HELLO 240 +#define ROUTER_INFORMATION 242 #define AUTH_INFO_HDRLEN 3 @@ -121,6 +125,8 @@ #define IPV6_REACH_LEN 22 #define TE_IPV4_REACH_LEN 9 +#define MAX_SUBTLV_SIZE 256 + /* struct for neighbor */ struct is_neigh { @@ -128,12 +134,18 @@ struct is_neigh u_char neigh_id[ISIS_SYS_ID_LEN + 1]; }; -/* struct for te is neighbor */ +/* struct for te metric */ struct te_is_neigh { u_char neigh_id[ISIS_SYS_ID_LEN + 1]; u_char te_metric[3]; u_char sub_tlvs_length; + /* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8 bits */ + /* Practically, 118 bytes are necessary to store all supported TE parameters */ + /* FIXME: A pointer will use less memory, but need to be free */ + /* which is hard to fix, especially within free_tlvs() function */ + /* and malloc() / free() as a CPU cost compared to the memory usage */ + u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */ }; /* Decode and encode three-octet metric into host byte order integer */ diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 125a2f63d3..569ff70d8d 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -49,6 +49,7 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" +#include "isisd/isis_te.h" struct zclient *zclient = NULL; @@ -61,6 +62,13 @@ isis_router_id_update_zebra (int command, struct zclient *zclient, struct listnode *node; struct prefix router_id; + /* + * If ISIS TE is enable, TE Router ID is set through specific command. + * See mpls_te_router_addr() command in isis_te.c + */ + if (IS_MPLS_TE(isisMplsTE)) + return 0; + zebra_router_id_update_read (zclient->ibuf, &router_id); if (isis->router_id == router_id.u.prefix4.s_addr) return 0; @@ -228,6 +236,23 @@ isis_zebra_if_address_del (int command, struct zclient *client, return 0; } +static int +isis_zebra_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 */ + isis_mpls_te_update(ifp); + + return 0; +} + static void isis_zebra_route_add_ipv4 (struct prefix *prefix, struct isis_route_info *route_info) @@ -278,12 +303,12 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix, /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc (stream, ZEBRA_NEXTHOP_IPV4); + stream_putc (stream, NEXTHOP_TYPE_IPV4); stream_put_in_addr (stream, &nexthop->ip); } else { - stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (stream, NEXTHOP_TYPE_IFINDEX); stream_putl (stream, nexthop->ifindex); } } @@ -333,7 +358,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix, { struct zapi_ipv6 api; struct in6_addr **nexthop_list; - unsigned int *ifindex_list; + ifindex_t *ifindex_list; struct isis_nexthop6 *nexthop6; int i, size; struct listnode *node; @@ -370,7 +395,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix, /* allocate memory for ifindex_list */ size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size); + ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); if (!ifindex_list) { zlog_err ("isis_zebra_add_route_ipv6: out of memory!"); @@ -420,7 +445,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix, { struct zapi_ipv6 api; struct in6_addr **nexthop_list; - unsigned int *ifindex_list; + ifindex_t *ifindex_list; struct isis_nexthop6 *nexthop6; int i, size; struct listnode *node; @@ -451,7 +476,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix, /* allocate memory for ifindex_list */ size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size); + ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); if (!ifindex_list) { zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); @@ -680,6 +705,7 @@ isis_zebra_init (struct thread_master *master) zclient->interface_down = isis_zebra_if_state_down; zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_delete = isis_zebra_if_address_del; + zclient->interface_link_params = isis_zebra_link_params; zclient->ipv4_route_add = isis_zebra_read_ipv4; zclient->ipv4_route_delete = isis_zebra_read_ipv4; zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; diff --git a/isisd/isisd.c b/isisd/isisd.c index 0d0b805a20..5a90115127 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -54,6 +54,7 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -98,6 +99,7 @@ isis_new (unsigned long process_id) * uncomment the next line for full debugs */ /* isis->debugs = 0xFFFF; */ + isisMplsTE.status = disable; /* Only support TE metric */ } struct isis_area * @@ -781,14 +783,16 @@ print_debug (struct vty *vty, int flags, int onoff) } DEFUN (show_debugging, - show_debugging_cmd, + show_debugging_isis_cmd, "show debugging isis", SHOW_STR "State of each debugging option\n" ISIS_STR) { - vty_out (vty, "IS-IS:%s", VTY_NEWLINE); - print_debug (vty, isis->debugs, 1); + if (isis->debugs) { + vty_out (vty, "IS-IS:%s", VTY_NEWLINE); + print_debug (vty, isis->debugs, 1); + } return CMD_SUCCESS; } @@ -2282,6 +2286,7 @@ isis_config_write (struct vty *vty) #endif /* TOPOLOGY_GENERATE */ } + isis_mpls_te_config_write_router(vty); } return write; @@ -2336,7 +2341,7 @@ isis_init () install_element (ENABLE_NODE, &show_database_arg_detail_cmd); install_element (ENABLE_NODE, &show_database_detail_cmd); install_element (ENABLE_NODE, &show_database_detail_arg_cmd); - install_element (ENABLE_NODE, &show_debugging_cmd); + install_element (ENABLE_NODE, &show_debugging_isis_cmd); install_node (&debug_node, config_write_debug); diff --git a/isisd/isisd.h b/isisd/isisd.h index 69a0100d50..9a4f360a2b 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -197,4 +197,8 @@ extern struct thread_master *master; } \ while (0) +#define DEBUG_TE (1<<13) + +#define IS_DEBUG_ISIS(x) (isis->debugs & x) + #endif /* ISISD_H */ @@ -504,8 +504,8 @@ bfd_client_sendmsg (struct zclient *zclient, int command) if (ret < 0) { if (bfd_debug) - zlog_debug ("bfd_client_sendmsg %d: zclient_send_message() failed", - getpid()); + zlog_debug ("bfd_client_sendmsg %ld: zclient_send_message() failed", + (long) getpid()); return; } 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" diff --git a/lib/filter.h b/lib/filter.h index 37535cb13b..e6ccd33b3a 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -25,6 +25,11 @@ #include "if.h" +/* Filter direction. */ +#define FILTER_IN 0 +#define FILTER_OUT 1 +#define FILTER_MAX 2 + /* Filter type is made by `permit', `deny' and `dynamic'. */ enum filter_type { @@ -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); } @@ -226,41 +228,41 @@ if_add_hook (int type, int (*func)(struct interface *ifp)) /* Interface existance check by index. */ struct interface * -if_lookup_by_index_vrf (unsigned int index, vrf_id_t vrf_id) +if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { - if (ifp->ifindex == index) + if (ifp->ifindex == ifindex) return ifp; } return NULL; } struct interface * -if_lookup_by_index (unsigned int index) +if_lookup_by_index (ifindex_t ifindex) { - return if_lookup_by_index_vrf (index, VRF_DEFAULT); + return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); } const char * -ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id) +ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_index_vrf (index, vrf_id)) != NULL) ? + return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ? ifp->name : "unknown"; } const char * -ifindex2ifname (unsigned int index) +ifindex2ifname (ifindex_t ifindex) { - return ifindex2ifname_vrf (index, VRF_DEFAULT); + return ifindex2ifname_vrf (ifindex, VRF_DEFAULT); } -unsigned int +ifindex_t ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) { struct interface *ifp; @@ -269,7 +271,7 @@ ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -unsigned int +ifindex_t ifname2ifindex (const char *name) { return ifname2ifindex_vrf (name, VRF_DEFAULT); @@ -1167,7 +1169,7 @@ connected_add_by_prefix (struct interface *ifp, struct prefix *p, } #ifndef HAVE_IF_NAMETOINDEX -unsigned int +ifindex_t if_nametoindex (const char *name) { struct interface *ifp; @@ -1179,7 +1181,7 @@ if_nametoindex (const char *name) #ifndef HAVE_IF_INDEXTONAME char * -if_indextoname (unsigned int ifindex, char *name) +if_indextoname (ifindex_t ifindex, char *name) { struct interface *ifp; @@ -1244,7 +1246,7 @@ ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) /* Lookup interface by interface's IP address or interface index. */ static struct interface * -ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) +ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) { struct prefix_ipv4 p; struct route_node *rn; @@ -1304,3 +1306,105 @@ if_terminate (struct list **intf_list) list_delete (*intf_list); *intf_list = NULL; } + +const char * +if_link_type_str (enum zebra_link_type llt) +{ + switch (llt) + { +#define llts(T,S) case (T): return (S) + llts(ZEBRA_LLT_UNKNOWN, "Unknown"); + llts(ZEBRA_LLT_ETHER, "Ethernet"); + llts(ZEBRA_LLT_EETHER, "Experimental Ethernet"); + llts(ZEBRA_LLT_AX25, "AX.25 Level 2"); + llts(ZEBRA_LLT_PRONET, "PROnet token ring"); + llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB"); + llts(ZEBRA_LLT_ARCNET, "ARCnet"); + llts(ZEBRA_LLT_APPLETLK, "AppleTalk"); + llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI"); + llts(ZEBRA_LLT_ATM, "ATM"); + llts(ZEBRA_LLT_METRICOM, "Metricom STRIP"); + llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4"); + llts(ZEBRA_LLT_EUI64, "EUI-64"); + llts(ZEBRA_LLT_INFINIBAND, "InfiniBand"); + llts(ZEBRA_LLT_SLIP, "SLIP"); + llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); + llts(ZEBRA_LLT_SLIP6, "SLIPv6"); + llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); + llts(ZEBRA_LLT_X25, "CCITT X.25"); + llts(ZEBRA_LLT_PPP, "PPP"); + llts(ZEBRA_LLT_CHDLC, "Cisco HDLC"); + llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC"); + llts(ZEBRA_LLT_LAPB, "LAPB"); + llts(ZEBRA_LLT_IPIP, "IPIP Tunnel"); + llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel"); + llts(ZEBRA_LLT_FRAD, "FRAD"); + llts(ZEBRA_LLT_SKIP, "SKIP vif"); + llts(ZEBRA_LLT_LOOPBACK, "Loopback"); + llts(ZEBRA_LLT_LOCALTLK, "Localtalk"); + llts(ZEBRA_LLT_FDDI, "FDDI"); + llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); + llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); + llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); + llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_IRDA, "IrDA"); + llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); + llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); + llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop"); + llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric"); + llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring"); + llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11"); + llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); + llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); + llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); + default: + zlog_warn ("Unknown value %d", llt); + return "Unknown type!"; +#undef llts + } + 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; +} @@ -21,8 +21,69 @@ Boston, MA 02111-1307, USA. */ #ifndef _ZEBRA_IF_H #define _ZEBRA_IF_H +#include "zebra.h" #include "linklist.h" +/* Interface link-layer type, if known. Derived from: + * + * net/if_arp.h on various platforms - Linux especially. + * http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml + * + * Some of the more obviously defunct technologies left out. + */ +enum zebra_link_type { + ZEBRA_LLT_UNKNOWN = 0, + ZEBRA_LLT_ETHER, + ZEBRA_LLT_EETHER, + ZEBRA_LLT_AX25, + ZEBRA_LLT_PRONET, + ZEBRA_LLT_IEEE802, + ZEBRA_LLT_ARCNET, + ZEBRA_LLT_APPLETLK, + ZEBRA_LLT_DLCI, + ZEBRA_LLT_ATM, + ZEBRA_LLT_METRICOM, + ZEBRA_LLT_IEEE1394, + ZEBRA_LLT_EUI64, + ZEBRA_LLT_INFINIBAND, + ZEBRA_LLT_SLIP, + ZEBRA_LLT_CSLIP, + ZEBRA_LLT_SLIP6, + ZEBRA_LLT_CSLIP6, + ZEBRA_LLT_RSRVD, + ZEBRA_LLT_ADAPT, + ZEBRA_LLT_ROSE, + ZEBRA_LLT_X25, + ZEBRA_LLT_PPP, + ZEBRA_LLT_CHDLC, + ZEBRA_LLT_LAPB, + ZEBRA_LLT_RAWHDLC, + ZEBRA_LLT_IPIP, + ZEBRA_LLT_IPIP6, + ZEBRA_LLT_FRAD, + ZEBRA_LLT_SKIP, + ZEBRA_LLT_LOOPBACK, + ZEBRA_LLT_LOCALTLK, + ZEBRA_LLT_FDDI, + ZEBRA_LLT_SIT, + ZEBRA_LLT_IPDDP, + ZEBRA_LLT_IPGRE, + ZEBRA_LLT_IP6GRE, + ZEBRA_LLT_PIMREG, + ZEBRA_LLT_HIPPI, + ZEBRA_LLT_ECONET, + ZEBRA_LLT_IRDA, + ZEBRA_LLT_FCPP, + ZEBRA_LLT_FCAL, + ZEBRA_LLT_FCPL, + ZEBRA_LLT_FCFABRIC, + ZEBRA_LLT_IEEE802_TR, + ZEBRA_LLT_IEEE80211, + ZEBRA_LLT_IEEE80211_RADIOTAP, + ZEBRA_LLT_IEEE802154, + ZEBRA_LLT_IEEE802154_PHY, +}; + /* Interface name length. @@ -36,6 +97,8 @@ Boston, MA 02111-1307, USA. */ #define INTERFACE_NAMSIZ 20 #define INTERFACE_HWADDR_MAX 20 +typedef signed int ifindex_t; + #ifdef HAVE_PROC_NET_DEV struct if_stats { @@ -68,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 { @@ -82,9 +202,9 @@ struct interface /* Interface index (should be IFINDEX_INTERNAL for non-kernel or deleted interfaces). */ - unsigned int ifindex; + ifindex_t ifindex; #define IFINDEX_INTERNAL 0 -#define IFINDEX_DELETED UINT_MAX +#define IFINDEX_DELETED INT_MAX /* Zebra internal interface status */ u_char status; @@ -103,24 +223,17 @@ struct interface unsigned int mtu; /* IPv4 MTU */ unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ - /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - union { - /* note that sdl_storage is never accessed, it only exists to make space. - * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits - * best with C aliasing rules. */ - struct sockaddr_dl sdl; - struct sockaddr_storage sdl_storage; - }; -#else - unsigned short hw_type; + /* Link-layer information and hardware address */ + enum zebra_link_type ll_type; u_char hw_addr[INTERFACE_HWADDR_MAX]; int hw_addr_len; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* interface bandwidth, kbits */ unsigned int bandwidth; + /* Link parameters for Traffic Engineering */ + struct if_link_params *link_params; + /* description of the interface. */ char *desc; @@ -264,7 +377,7 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); extern struct interface *if_create (const char *name, int namelen); -extern struct interface *if_lookup_by_index (unsigned int); +extern struct interface *if_lookup_by_index (ifindex_t); extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct interface *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); @@ -273,8 +386,7 @@ extern void if_update_vrf (struct interface *, const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id); -extern struct interface *if_lookup_by_index_vrf (unsigned int, - vrf_id_t vrf_id); +extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id); extern struct interface *if_lookup_address_vrf (void *matchaddr, int family, @@ -328,18 +440,19 @@ extern void if_init (struct list **); extern void if_terminate (struct list **); extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); +extern const char *if_link_type_str (enum zebra_link_type); /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ -extern const char *ifindex2ifname (unsigned int); -extern const char *ifindex2ifname_vrf (unsigned int, vrf_id_t vrf_id); +extern const char *ifindex2ifname (ifindex_t); +extern const char *ifindex2ifname_vrf (ifindex_t, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must make a system call. */ -extern unsigned int ifname2ifindex(const char *ifname); -extern unsigned int ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); +extern ifindex_t ifname2ifindex(const char *ifname); +extern ifindex_t ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new (void); @@ -359,12 +472,16 @@ extern void nbr_connected_free (struct nbr_connected *); struct nbr_connected *nbr_connected_check (struct interface *, struct prefix *); #ifndef HAVE_IF_NAMETOINDEX -extern unsigned int if_nametoindex (const char *); +extern ifindex_t if_nametoindex (const char *); #endif #ifndef HAVE_IF_INDEXTONAME -extern char *if_indextoname (unsigned int, 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; @@ -179,6 +179,7 @@ static void vzlog (struct zlog *zl, int priority, const char *format, va_list args) { char proto_str[32]; + int original_errno = errno; struct timestamp_control tsctl; tsctl.already_rendered = 0; @@ -197,6 +198,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) fflush (stderr); /* In this case we return at here. */ + errno = original_errno; return; } tsctl.precision = zl->timestamp_precision; @@ -249,6 +251,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), proto_str, format, &tsctl, args); + + errno = original_errno; } static char * diff --git a/lib/memory.c b/lib/memory.c index 290b999bb8..8d1a03743e 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -80,9 +80,11 @@ zmalloc (int type, size_t size) /* * Allocate memory as in zmalloc, and also clear the memory. + * Add an extra 'z' prefix to function name to avoid collision when linking + * statically with zlib that exports the 'zcalloc' symbol. */ void * -zcalloc (int type, size_t size) +zzcalloc (int type, size_t size) { void *memory; @@ -97,9 +99,9 @@ zcalloc (int type, size_t size) } /* - * Given a pointer returned by zmalloc or zcalloc, free it and + * Given a pointer returned by zmalloc or zzcalloc, free it and * return a pointer to a new size, basically acting like realloc(). - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * Requires: ptr was returned by zmalloc, zzcalloc, or zrealloc with the * same type. * Effects: Returns a pointer to the new memory, or aborts. */ @@ -109,7 +111,7 @@ zrealloc (int type, void *ptr, size_t size) void *memory; if (ptr == NULL) /* is really alloc */ - return zcalloc(type, size); + return zzcalloc(type, size); memory = realloc (ptr, size); if (memory == NULL) @@ -122,7 +124,7 @@ zrealloc (int type, void *ptr, size_t size) /* * Free memory allocated by z*alloc or zstrdup. - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * Requires: ptr was returned by zmalloc, zzcalloc, or zrealloc with the * same type. * Effects: The memory is freed and may no longer be referenced. */ @@ -196,7 +198,7 @@ mtype_zcalloc (const char *file, int line, int type, size_t size) mstat[type].c_calloc++; mstat[type].t_calloc++; - memory = zcalloc (type, size); + memory = zzcalloc (type, size); mtype_log ("xcalloc", memory, file, line, type); return memory; diff --git a/lib/memory.h b/lib/memory.h index 23962235db..501352993d 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -56,7 +56,7 @@ extern struct mlist mlists[]; mtype_zstrdup (__FILE__, __LINE__, (mtype), (str)) #else #define XMALLOC(mtype, size) zmalloc ((mtype), (size)) -#define XCALLOC(mtype, size) zcalloc ((mtype), (size)) +#define XCALLOC(mtype, size) zzcalloc ((mtype), (size)) #define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size)) #define XFREE(mtype, ptr) do { \ zfree ((mtype), (ptr)); \ @@ -67,7 +67,7 @@ extern struct mlist mlists[]; /* Prototypes of memory function. */ extern void *zmalloc (int type, size_t size); -extern void *zcalloc (int type, size_t size); +extern void *zzcalloc (int type, size_t size); extern void *zrealloc (int type, void *ptr, size_t size); extern void zfree (int type, void *ptr); extern char *zstrdup (int type, const char *str); 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/nexthop.h b/lib/nexthop.h index 725eb537af..39e8b5425f 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -51,7 +51,7 @@ struct nexthop struct nexthop *prev; /* Interface index. */ - unsigned int ifindex; + ifindex_t ifindex; enum nexthop_types_t type; diff --git a/lib/plist.c b/lib/plist.c index a1289801c4..7bb80fa2a4 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -958,6 +958,11 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, return CMD_WARNING; } break; + case AFI_ETHER: + default: + vty_out (vty, "%% Unrecognized AFI (%d)%s", afi, VTY_NEWLINE); + return CMD_WARNING; + break; } /* ge and le check. */ diff --git a/lib/prefix.c b/lib/prefix.c index c311b94eef..d2bb028315 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -194,8 +194,9 @@ str2family(const char *string) return AF_INET; else if (!strcmp("ipv6", string)) return AF_INET6; - else - return -1; + else if (!strcmp("ethernet", string)) + return AF_ETHERNET; + return -1; } /* Address Famiy Identifier to Address Family converter. */ @@ -208,6 +209,8 @@ afi2family (afi_t afi) else if (afi == AFI_IP6) return AF_INET6; #endif /* HAVE_IPV6 */ + else if (afi == AFI_ETHER) + return AF_ETHERNET; return 0; } @@ -220,10 +223,28 @@ family2afi (int family) else if (family == AF_INET6) return AFI_IP6; #endif /* HAVE_IPV6 */ + else if (family == AF_ETHERNET) + return AFI_ETHER; return 0; } const char * +afi2str(afi_t afi) +{ + switch (afi) { + case AFI_IP: + return "IPv4"; + case AFI_IP6: + return "IPv6"; + case AFI_ETHER: + return "ethernet"; + default: + break; + } + return NULL; +} + +const char * safi2str(safi_t safi) { switch (safi) { @@ -286,6 +307,10 @@ prefix_copy (struct prefix *dest, const struct prefix *src) dest->u.lp.id = src->u.lp.id; dest->u.lp.adv_router = src->u.lp.adv_router; } + else if (src->family == AF_ETHERNET) + { + dest->u.prefix_eth = src->u.prefix_eth; + } else { zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d", @@ -321,6 +346,10 @@ prefix_same (const struct prefix *p1, const struct prefix *p2) if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr)) return 1; #endif /* HAVE_IPV6 */ + if (p1->family == AF_ETHERNET) { + if (!memcmp(p1->u.prefix_eth.octet, p2->u.prefix_eth.octet, ETHER_ADDR_LEN)) + return 1; + } } return 0; } @@ -412,6 +441,8 @@ prefix_family_str (const struct prefix *p) if (p->family == AF_INET6) return "inet6"; #endif /* HAVE_IPV6 */ + if (p->family == AF_ETHERNET) + return "ether"; return "unspec"; } @@ -482,6 +513,60 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) return ret; } +/* When string format is invalid return 0. */ +int +str2prefix_eth (const char *str, struct prefix_eth *p) +{ + int ret = 0; + int plen = 48; + char *pnt; + char *cp = NULL; + const char *str_addr = str; + unsigned int a[6]; + int i; + + /* Find slash inside string. */ + pnt = strchr (str, '/'); + + if (pnt) + { + /* Get prefix length. */ + plen = (u_char) atoi (++pnt); + if (plen > 48) + { + ret = 0; + goto done; + } + + cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); + strncpy (cp, str, pnt - str); + *(cp + (pnt - str)) = '\0'; + + str_addr = cp; + } + + /* Convert string to prefix. */ + if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x", + a+0, a+1, a+2, a+3, a+4, a+5) != 6) + { + ret = 0; + goto done; + } + for (i = 0; i < 6; ++i) + { + p->eth_addr.octet[i] = a[i] & 0xff; + } + p->prefixlen = plen; + p->family = AF_ETHERNET; + ret = 1; + +done: + if (cp) + XFREE (MTYPE_TMP, cp); + + return ret; +} + /* Convert masklen into IP address's netmask (network byte order). */ void masklen2ip (const int masklen, struct in_addr *netmask) @@ -768,6 +853,8 @@ prefix_blen (const struct prefix *p) return IPV6_MAX_BYTELEN; break; #endif /* HAVE_IPV6 */ + case AF_ETHERNET: + return ETHER_ADDR_LEN; } return 0; } @@ -790,6 +877,11 @@ str2prefix (const char *str, struct prefix *p) return ret; #endif /* HAVE_IPV6 */ + /* Next we try to convert string to struct prefix_eth. */ + ret = str2prefix_eth (str, (struct prefix_eth *) p); + if (ret) + return ret; + return 0; } @@ -799,6 +891,24 @@ prefix2str (union prefix46constptr pu, char *str, int size) const struct prefix *p = pu.p; char buf[PREFIX2STR_BUFFER]; + if (p->family == AF_ETHERNET) { + int i; + char *s = str; + + assert(size > (3*ETHER_ADDR_LEN) + 1 /* slash */ + 3 /* plen */ ); + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + sprintf(s, "%02x", p->u.prefix_eth.octet[i]); + if (i < (ETHER_ADDR_LEN - 1)) { + *(s+2) = ':'; + s += 3; + } else { + s += 2; + } + } + sprintf(s, "/%d", p->prefixlen); + return 0; + } + snprintf (str, size, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER), p->prefixlen); diff --git a/lib/prefix.h b/lib/prefix.h index 39c2b62019..85488ccea7 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -23,8 +23,30 @@ #ifndef _ZEBRA_PREFIX_H #define _ZEBRA_PREFIX_H +#ifdef SUNOS_5 +# include <sys/ethernet.h> +#else +# ifdef GNU_LINUX +# include <net/ethernet.h> +# else +# include <netinet/if_ether.h> +# endif +#endif #include "sockunion.h" +#ifndef ETHER_ADDR_LEN +#define ETHER_ADDR_LEN ETHERADDRL +#endif + +/* + * there isn't a portable ethernet address type. We define our + * own to simplify internal handling + */ +struct ethaddr { + u_char octet[ETHER_ADDR_LEN]; +} __packed; + + /* * A struct prefix contains an address family, a prefix length, and an * address. This can represent either a 'network prefix' as defined @@ -34,6 +56,15 @@ * interface. */ +/* different OSes use different names */ +#if defined(AF_PACKET) +#define AF_ETHERNET AF_PACKET +#else +#if defined(AF_LINK) +#define AF_ETHERNET AF_LINK +#endif +#endif + /* IPv4 and IPv6 unified prefix structure. */ struct prefix { @@ -51,6 +82,7 @@ struct prefix struct in_addr id; struct in_addr adv_router; } lp; + struct ethaddr prefix_eth; /* AF_ETHERNET */ u_char val[8]; uintptr_t ptr; } u __attribute__ ((aligned (8))); @@ -90,6 +122,14 @@ struct prefix_rd u_char val[8] __attribute__ ((aligned (8))); }; +/* Prefix for ethernet. */ +struct prefix_eth +{ + u_char family; + u_char prefixlen; + struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */ +}; + /* Prefix for a generic pointer */ struct prefix_ptr { @@ -174,6 +214,7 @@ extern int str2family(const char *); extern int afi2family (afi_t); extern afi_t family2afi (int); extern const char *safi2str(safi_t safi); +extern const char *afi2str(afi_t afi); /* Check bit of the prefix. */ extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen); @@ -205,6 +246,8 @@ extern struct prefix *sockunion2prefix (const union sockunion *dest, extern struct prefix *sockunion2hostprefix (const union sockunion *, struct prefix *p); extern void prefix2sockunion (const struct prefix *, union sockunion *); +extern int str2prefix_eth (const char *, struct prefix_eth *); + extern struct prefix_ipv4 *prefix_ipv4_new (void); extern void prefix_ipv4_free (struct prefix_ipv4 *); extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *); diff --git a/lib/privs.c b/lib/privs.c index e6d76b600b..3fb96aed12 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -307,11 +307,18 @@ zprivs_caps_init (struct zebra_privs_t *zprivs) current_caps = cap_get_proc(); if (current_caps) + { current_caps_text = cap_to_text(current_caps, NULL); + cap_free(current_caps); + } wanted_caps_text = cap_to_text(zprivs_state.caps, NULL); fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???"); fprintf(stderr, "Have caps: %s\n", current_caps_text ? current_caps_text : "???"); + if (current_caps_text) + cap_free(current_caps_text); + if (wanted_caps_text) + cap_free(wanted_caps_text); exit (1); } diff --git a/lib/routemap.c b/lib/routemap.c index d8d1872d65..9267056df6 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1591,7 +1591,7 @@ DEFUN (rmap_onmatch_goto, } if (argc == 1 && argv[0]) - VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 65536); + VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 65535); else d = index->pref + 1; @@ -1669,7 +1669,7 @@ DEFUN (rmap_show_name, ALIAS (rmap_onmatch_goto, rmap_continue_index_cmd, - "continue <1-65536>", + "continue <1-65535>", "Exit policy on matches\n" "Goto Clause number\n") diff --git a/lib/sigevent.c b/lib/sigevent.c index c80a729012..a120028d81 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -237,6 +237,8 @@ core_handler(int signo , siginfo, program_counter(context) #endif ); + /* dump memory stats on core */ + log_memstats_stderr ("core_handler"); abort(); } diff --git a/lib/sockopt.c b/lib/sockopt.c index 257271bc0b..31b2edbacf 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -219,8 +219,9 @@ setsockopt_ipv6_tclass(int sock, int tclass) int setsockopt_ipv4_multicast(int sock, int optname, + struct in_addr if_addr, unsigned int mcast_addr, - unsigned int ifindex) + ifindex_t ifindex) { #ifdef HAVE_RFC3678 struct group_req gr; @@ -279,18 +280,20 @@ setsockopt_ipv4_multicast(int sock, #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ /* standard BSD API */ - struct in_addr m; struct ip_mreq mreq; int ret; assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); - m.s_addr = htonl(ifindex); memset (&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr.s_addr = mcast_addr; - mreq.imr_interface = m; - +#if !defined __OpenBSD__ + mreq.imr_interface.s_addr = htonl (ifindex); +#else + mreq.imr_interface.s_addr = if_addr.s_addr; +#endif + ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) { @@ -318,8 +321,8 @@ setsockopt_ipv4_multicast(int sock, * Set IP_MULTICAST_IF socket option in an OS-dependent manner. */ int -setsockopt_ipv4_multicast_if(int sock, - unsigned int ifindex) +setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, + ifindex_t ifindex) { #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX @@ -336,7 +339,11 @@ setsockopt_ipv4_multicast_if(int sock, #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) struct in_addr m; - m.s_addr = htonl(ifindex); +#if !defined __OpenBSD__ + m.s_addr = htonl (ifindex); +#else + m.s_addr = if_addr.s_addr; +#endif return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); #else @@ -345,7 +352,7 @@ setsockopt_ipv4_multicast_if(int sock, } static int -setsockopt_ipv4_ifindex (int sock, int val) +setsockopt_ipv4_ifindex (int sock, ifindex_t val) { int ret; @@ -381,7 +388,7 @@ setsockopt_ipv4_tos(int sock, int tos) int -setsockopt_ifindex (int af, int sock, int val) +setsockopt_ifindex (int af, int sock, ifindex_t val) { int ret = -1; @@ -408,11 +415,11 @@ setsockopt_ifindex (int af, int sock, int val) * Returns the interface index (small integer >= 1) if it can be * determined, or else 0. */ -static int +static ifindex_t getsockopt_ipv4_ifindex (struct msghdr *msgh) { /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ - int ifindex = -1; + ifindex_t ifindex = -1; #if defined(IP_PKTINFO) /* Linux pktinfo based ifindex retrieval */ @@ -432,7 +439,7 @@ getsockopt_ipv4_ifindex (struct msghdr *msgh) struct sockaddr_dl *sdl; #else /* SUNOS_5 uses an integer with the index. */ - int *ifindex_p; + ifindex_t *ifindex_p; #endif /* SUNOS_5 */ #ifndef SUNOS_5 @@ -473,7 +480,7 @@ getsockopt_ipv4_ifindex (struct msghdr *msgh) } /* return ifindex, 0 if none found */ -int +ifindex_t getsockopt_ifindex (int af, struct msghdr *msgh) { switch (af) diff --git a/lib/sockopt.h b/lib/sockopt.h index cb14efc7ba..d67b510b66 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -83,16 +83,17 @@ extern int setsockopt_ipv6_tclass (int, int); (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \ ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) -extern int setsockopt_ipv4_multicast_if(int sock, - unsigned int ifindex); +extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, + ifindex_t ifindex); extern int setsockopt_ipv4_multicast(int sock, int optname, + struct in_addr if_addr, unsigned int mcast_addr, - unsigned int ifindex); + ifindex_t ifindex); extern int setsockopt_ipv4_tos(int sock, int tos); /* Ask for, and get, ifindex, by whatever method is supported. */ -extern int setsockopt_ifindex (int, int, int); -extern int getsockopt_ifindex (int, struct msghdr *); +extern int setsockopt_ifindex (int, int, ifindex_t); +extern ifindex_t getsockopt_ifindex (int, struct msghdr *); /* swab the fields in iph between the host order and system order expected * for IP_HDRINCL. diff --git a/lib/sockunion.c b/lib/sockunion.c index b5a2eb954a..9184e500fc 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -291,7 +291,7 @@ sockunion_sizeof (const union sockunion *su) 1 : connect is in progress */ enum connect_result sockunion_connect (int fd, const union sockunion *peersu, unsigned short port, - unsigned int ifindex) + ifindex_t ifindex) { int ret; int val; diff --git a/lib/sockunion.h b/lib/sockunion.h index a33051ae57..105b11a24c 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -24,6 +24,7 @@ #define _ZEBRA_SOCKUNION_H #include "privs.h" +#include "if.h" union sockunion { @@ -95,7 +96,7 @@ extern int sockunion_socket (const union sockunion *su); extern const char *inet_sutop (const union sockunion *su, char *str); extern enum connect_result sockunion_connect (int fd, const union sockunion *su, unsigned short port, - unsigned int); + ifindex_t); extern union sockunion *sockunion_getsockname (int); extern union sockunion *sockunion_getpeername (int); extern union sockunion *sockunion_dup (const union sockunion *); @@ -54,26 +54,34 @@ snprintf(char *str, size_t size, const char *format, ...) #endif #ifndef HAVE_STRLCPY -/** - * Like strncpy but does not 0 fill the buffer and always null - * terminates. - * - * @param bufsize is the size of the destination buffer. - * - * @return index of the terminating byte. - **/ +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ size_t -strlcpy(char *d, const char *s, size_t bufsize) +strlcpy(char *dst, const char *src, size_t dsize) { - size_t len = strlen(s); - size_t ret = len; - if (bufsize > 0) { - if (len >= bufsize) - len = bufsize-1; - memcpy(d, s, len); - d[len] = 0; + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } } - return ret; + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ } #endif 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 ef9516c912..753954fd84 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -32,6 +32,7 @@ #include "zclient.h" #include "memory.h" #include "table.h" +#include "nexthop.h" /* Zebra client events. */ enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; @@ -709,6 +710,8 @@ zclient_connect (struct thread *t) * * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 2 byte value * + * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value + * * XXX: No attention paid to alignment. */ int @@ -744,7 +747,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -753,12 +756,12 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, api->nexthop[i]); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } @@ -769,6 +772,8 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -809,7 +814,7 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -818,12 +823,12 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV6); + stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } @@ -834,6 +839,8 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -873,7 +880,7 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -882,12 +889,12 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV6); + stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } @@ -898,6 +905,8 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -951,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 | * | | @@ -960,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 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ifmtu | + * | Link Layer Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ifmtu6 | + * | Harware Address Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | bandwidth | + * | Hardware Address if HW lenght different from 0 | + * | ... max INTERFACE_HWADDR_MAX | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | sockaddr_dl | + * | Link_params? | Whether a link-params follows: 1 or 0. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Link_params 0 or 1 INTERFACE_LINK_PARAMS_SIZE sized | + * | .... (struct if_link_params). | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ @@ -1062,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 @@ -1091,33 +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); -#ifdef HAVE_STRUCT_SOCKADDR_DL - stream_get (&ifp->sdl, s, sizeof (ifp->sdl_storage)); -#else - 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)); -#endif /* HAVE_STRUCT_SOCKADDR_DL */ -} - static int memconstant(const void *s, int c, size_t n) { @@ -1133,7 +1258,7 @@ memconstant(const void *s, int c, size_t n) struct connected * zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) { - unsigned int ifindex; + ifindex_t ifindex; struct interface *ifp; struct connected *ifc; struct prefix p, d; @@ -1503,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 f30190c1b4..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); @@ -116,6 +117,7 @@ struct zclient #define ZAPI_MESSAGE_DISTANCE 0x04 #define ZAPI_MESSAGE_METRIC 0x08 #define ZAPI_MESSAGE_TAG 0x10 +#define ZAPI_MESSAGE_MTU 0x20 /* Zserv protocol message header */ struct zserv_header @@ -146,7 +148,7 @@ struct zapi_ipv4 struct in_addr **nexthop; u_char ifindex_num; - unsigned int *ifindex; + ifindex_t *ifindex; u_char distance; @@ -154,6 +156,8 @@ struct zapi_ipv4 u_short tag; + u_int32_t mtu; + vrf_id_t vrf_id; }; @@ -211,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. */ @@ -229,7 +236,7 @@ struct zapi_ipv6 struct in6_addr **nexthop; u_char ifindex_num; - unsigned int *ifindex; + ifindex_t *ifindex; u_char distance; @@ -237,6 +244,8 @@ struct zapi_ipv6 u_short tag; + u_int32_t mtu; + vrf_id_t vrf_id; }; diff --git a/lib/zebra.h b/lib/zebra.h index 59c154ba46..fdfd471825 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 @@ -489,20 +490,10 @@ extern const char *zserv_command_string (unsigned int command); #define ZEBRA_FLAG_BLACKHOLE 0x04 #define ZEBRA_FLAG_IBGP 0x08 #define ZEBRA_FLAG_SELECTED 0x10 -#define ZEBRA_FLAG_CHANGED 0x20 #define ZEBRA_FLAG_STATIC 0x40 #define ZEBRA_FLAG_REJECT 0x80 #define ZEBRA_FLAG_SCOPE_LINK 0x100 -/* Zebra nexthop flags. */ -#define ZEBRA_NEXTHOP_IFINDEX 1 -#define ZEBRA_NEXTHOP_IPV4 2 -#define ZEBRA_NEXTHOP_IPV4_IFINDEX 3 -#define ZEBRA_NEXTHOP_IPV6 4 -#define ZEBRA_NEXTHOP_IPV6_IFINDEX 5 -#define ZEBRA_NEXTHOP_BLACKHOLE 6 -#define ZEBRA_NEXTHOP_IPV4_ONLINK 7 - #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */ #endif @@ -511,7 +502,8 @@ extern const char *zserv_command_string (unsigned int command); typedef enum { AFI_IP = 1, AFI_IP6 = 2, -#define AFI_MAX 3 + AFI_ETHER = 3, /* RFC 1700 has "6" for 802.* */ + AFI_MAX = 4 } afi_t; /* Subsequent Address Family Identifier. */ @@ -522,11 +514,6 @@ typedef enum { #define SAFI_ENCAP 7 /* per IANA */ #define SAFI_MAX 8 -/* Filter direction. */ -#define FILTER_IN 0 -#define FILTER_OUT 1 -#define FILTER_MAX 2 - /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_CONNECT_DISTANCE_DEFAULT 0 diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 1207419e58..208d3b8c4c 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -426,7 +426,7 @@ ospf6_asbr_send_externals_to_area (struct ospf6_area *oa) } void -ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, +ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix, u_int nexthop_num, struct in6_addr *nexthop) { int ret; @@ -575,7 +575,8 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, } void -ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix) +ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, + struct prefix *prefix) { struct ospf6_route *match; struct ospf6_external_info *info = NULL; diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index 90befdc0dd..645e8fd9cf 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -49,7 +49,7 @@ struct ospf6_external_info struct in6_addr forwarding; /* u_int32_t tag; */ - unsigned int ifindex; + ifindex_t ifindex; }; /* AS-External-LSA */ @@ -79,11 +79,11 @@ extern void ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry); extern void ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry); extern int ospf6_asbr_is_asbr (struct ospf6 *o); -extern void ospf6_asbr_redistribute_add (int type, int ifindex, +extern void ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix, u_int nexthop_num, struct in6_addr *nexthop); -extern void ospf6_asbr_redistribute_remove (int type, int ifindex, +extern void ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, struct prefix *prefix); extern int ospf6_redistribute_config_write (struct vty *vty); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 720a3e0e69..f24ec46da7 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -61,7 +61,7 @@ const char *ospf6_interface_state_str[] = }; struct ospf6_interface * -ospf6_interface_lookup_by_ifindex (int ifindex) +ospf6_interface_lookup_by_ifindex (ifindex_t ifindex) { struct ospf6_interface *oi; struct interface *ifp; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 5e6b455682..3e09bfb930 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -152,7 +152,7 @@ extern const char *ospf6_interface_state_str[]; /* Function Prototypes */ -extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex (int); +extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex (ifindex_t); extern struct ospf6_interface *ospf6_interface_create (struct interface *); extern void ospf6_interface_delete (struct ospf6_interface *); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index fe57f2f423..b0e94288b4 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -290,7 +290,7 @@ ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); /* Neighbor ifindex check */ - if (on->ifindex != ntohl (hello->interface_id)) + if (on->ifindex != (ifindex_t)ntohl (hello->interface_id)) { on->ifindex = ntohl (hello->interface_id); neighbor_ifindex_change++; @@ -1525,7 +1525,7 @@ ospf6_receive (struct thread *thread) unsigned int len; char srcname[64], dstname[64]; struct in6_addr src, dst; - unsigned int ifindex; + ifindex_t ifindex; struct iovec iovector[2]; struct ospf6_interface *oi; struct ospf6_header *oh; diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index b085a9673b..4a9e0c7a66 100644 --- a/ospf6d/ospf6_message.h +++ b/ospf6d/ospf6_message.h @@ -64,7 +64,7 @@ struct ospf6_header #define OSPF6_HELLO_MIN_SIZE 20U struct ospf6_hello { - u_int32_t interface_id; + ifindex_t interface_id; u_char priority; u_char options[3]; u_int16_t hello_interval; diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index fad7fd578a..f9e197e99b 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -53,7 +53,7 @@ struct ospf6_neighbor u_int32_t router_id; /* Neighbor Interface ID */ - u_int32_t ifindex; + ifindex_t ifindex; /* Router Priority of this neighbor */ u_char priority; diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 7b1cf91932..2227d03477 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -113,7 +113,7 @@ ospf6_serv_sock (void) /* ospf6 set socket option */ int -ospf6_sso (u_int ifindex, struct in6_addr *group, int option) +ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option) { struct ipv6_mreq mreq6; int ret; @@ -193,19 +193,23 @@ iov_totallen (struct iovec *iov) int ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, - unsigned int *ifindex, struct iovec *message) + ifindex_t *ifindex, struct iovec *message) { int retval; struct msghdr smsghdr; struct cmsghdr *scmsgp; - u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; + union + { + struct cmsghdr hdr; + u_char buf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; + } cmsgbuf; struct in6_pktinfo *pktinfo; struct sockaddr_in6 dst_sin6; assert (dst); assert (*ifindex); - scmsgp = (struct cmsghdr *)cmsgbuf; + scmsgp = (struct cmsghdr *)&cmsgbuf; pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); memset (&dst_sin6, 0, sizeof (struct sockaddr_in6)); @@ -222,7 +226,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, dst_sin6.sin6_len = sizeof (struct sockaddr_in6); #endif /*SIN6_LEN*/ memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr)); -#ifdef HAVE_SIN6_SCOPE_ID +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID dst_sin6.sin6_scope_id = *ifindex; #endif @@ -238,8 +242,8 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, smsghdr.msg_iovlen = iov_count (message); smsghdr.msg_name = (caddr_t) &dst_sin6; smsghdr.msg_namelen = sizeof (struct sockaddr_in6); - smsghdr.msg_control = (caddr_t) cmsgbuf; - smsghdr.msg_controllen = scmsgp->cmsg_len; + smsghdr.msg_control = (caddr_t) &cmsgbuf.buf; + smsghdr.msg_controllen = sizeof(cmsgbuf.buf); retval = sendmsg (ospf6_sock, &smsghdr, 0); if (retval != iov_totallen (message)) @@ -251,7 +255,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, int ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst, - unsigned int *ifindex, struct iovec *message) + ifindex_t *ifindex, struct iovec *message) { int retval; struct msghdr rmsghdr; diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h index 2aeafe5041..4fa2839519 100644 --- a/ospf6d/ospf6_network.h +++ b/ospf6d/ospf6_network.h @@ -29,12 +29,12 @@ extern struct in6_addr allspfrouters6; extern struct in6_addr alldrouters6; extern int ospf6_serv_sock (void); -extern int ospf6_sso (u_int ifindex, struct in6_addr *group, int option); +extern int ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option); extern int ospf6_sendmsg (struct in6_addr *, struct in6_addr *, - unsigned int *, struct iovec *); + ifindex_t *, struct iovec *); extern int ospf6_recvmsg (struct in6_addr *, struct in6_addr *, - unsigned int *, struct iovec *); + ifindex_t *, struct iovec *); #endif /* OSPF6_NETWORK_H */ diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 0a98c8f082..5172eee48d 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -331,7 +331,7 @@ ospf6_add_nexthop (struct list *nh_list, int ifindex, void ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - unsigned int *ifindexes, + ifindex_t *ifindexes, struct in6_addr **nexthop_addr, int entries) { diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e783b72d8e..610b0970b0 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -41,7 +41,7 @@ extern unsigned char conf_debug_ospf6_route; struct ospf6_nexthop { /* Interface index */ - unsigned int ifindex; + ifindex_t ifindex; /* IP address, if any */ struct in6_addr address; @@ -278,7 +278,7 @@ extern int ospf6_num_nexthops (struct list *nh_list); extern int ospf6_route_cmp_nexthops (struct ospf6_route *a, struct ospf6_route *b); extern void ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - unsigned int *ifindices, + ifindex_t *ifindices, struct in6_addr **addr, int entries); extern int ospf6_route_get_first_nh_index (struct ospf6_route *route); diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index cf1630bbc9..382cf62f72 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -625,7 +625,7 @@ ospfv3WwLsdbEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct ospf6_lsa *lsa = NULL; - u_int32_t ifindex, area_id, id, instid, adv_router; + ifindex_t ifindex, area_id, id, instid, adv_router; u_int16_t type; int len; oid *offset; @@ -837,7 +837,8 @@ static u_char * ospfv3IfEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex, instid; + ifindex_t ifindex = 0; + unsigned int instid = 0; struct ospf6_interface *oi = NULL; struct ospf6_lsa *lsa = NULL; struct interface *iif; @@ -851,8 +852,6 @@ ospfv3IfEntry (struct variable *v, oid *name, size_t *length, == MATCH_FAILED) return NULL; - ifindex = instid = 0; - /* Check OSPFv3 instance. */ if (ospf6 == NULL) return NULL; @@ -990,7 +989,8 @@ static u_char * ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex, instid, rtrid; + ifindex_t ifindex = 0; + unsigned int instid, rtrid; struct ospf6_interface *oi = NULL; struct ospf6_neighbor *on = NULL; struct interface *iif; @@ -1003,7 +1003,7 @@ ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, == MATCH_FAILED) return NULL; - ifindex = instid = rtrid = 0; + instid = rtrid = 0; /* Check OSPFv3 instance. */ if (ospf6 == NULL) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index ab1213ebb6..957988b53d 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -266,7 +266,7 @@ ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, caddr_t lsdesc) { int i; - unsigned int ifindex; + ifindex_t ifindex; struct ospf6_interface *oi; u_int16_t type; u_int32_t adv_router; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 0395b082da..77ea01e53d 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -377,7 +377,7 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request) char buf[PREFIX2STR_BUFFER]; int nhcount; struct in6_addr **nexthops; - unsigned int *ifindexes; + ifindex_t *ifindexes; int ret = 0; struct prefix_ipv6 *dest; @@ -443,7 +443,7 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request) /* allocate memory for ifindex_list */ ifindexes = XCALLOC (MTYPE_OSPF6_OTHER, - nhcount * sizeof (unsigned int)); + nhcount * sizeof (ifindex_t)); if (ifindexes == NULL) { zlog_warn ("Can't send route to zebra: malloc failed"); diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 9eb166a3d6..55f9bf2d8e 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -16,7 +16,7 @@ libospf_la_SOURCES = \ ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ - ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c \ + ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \ ospf_bfd.c ospfdheaderdir = $(pkgincludedir)/ospfd @@ -28,12 +28,12 @@ ospfdheader_HEADERS = \ noinst_HEADERS = \ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h \ + ospf_flood.h ospf_snmp.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ ospf_bfd.h ospfd_SOURCES = ospf_main.c -ospfd_LDADD = libospf.la ../lib/libzebra.la @LIBCAP@ +ospfd_LDADD = libospf.la ../lib/libzebra.la @LIBCAP@ @LIBM@ EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index 45525f4a2c..9f90f671ce 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -23,9 +23,6 @@ #include <zebra.h> #ifdef SUPPORT_OSPF_API -#ifndef HAVE_OPAQUE_LSA -#error "Core Opaque-LSA module must be configured." -#endif /* HAVE_OPAQUE_LSA */ #include "linklist.h" #include "prefix.h" diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 92f68f75f8..aac8ef4b8b 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -23,9 +23,6 @@ #include <zebra.h> #ifdef SUPPORT_OSPF_API -#ifndef HAVE_OPAQUE_LSA -#error "Core Opaque-LSA module must be configured." -#endif /* HAVE_OPAQUE_LSA */ #include "linklist.h" #include "prefix.h" diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index ddb26dd543..21f99af128 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -136,7 +136,7 @@ ospf_route_map_set_compare (struct route_map_set_values *values1, /* Add an External info for AS-external-LSA. */ struct external_info * ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, - unsigned int ifindex, struct in_addr nexthop, + ifindex_t ifindex, struct in_addr nexthop, u_short tag) { struct external_info *new; diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index ade671013a..25a53aad4f 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -41,7 +41,7 @@ struct external_info struct prefix_ipv4 p; /* Interface index. */ - unsigned int ifindex; + ifindex_t ifindex; /* Nexthop address. */ struct in_addr nexthop; @@ -63,7 +63,7 @@ extern int ospf_route_map_set_compare (struct route_map_set_values *, struct route_map_set_values *); extern struct external_info *ospf_external_info_add (u_char, u_short, struct prefix_ipv4, - unsigned int, + ifindex_t, struct in_addr, u_short); extern void ospf_external_info_delete (u_char, u_short, struct prefix_ipv4); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 65d6e09b6d..a53c726853 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -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; } @@ -619,13 +621,11 @@ ospf_packet_ls_upd_dump (struct stream *s, u_int16_t length) case OSPF_AS_NSSA_LSA: ospf_as_external_lsa_dump (s, length); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_dump (s, length); break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -1922,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", @@ -2272,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); @@ -2285,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); @@ -2328,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); @@ -2341,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); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index a2d5e8ba19..f843df03ae 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -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[]; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index e9f443111a..7f83ddeaae 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -156,9 +156,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf, ospf_router_lsa_update_area (area); return; case OSPF_NETWORK_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: -#endif /* HAVE_OPAQUE_LSA */ /* We must find the interface the LSA could belong to. If the interface is no more a broadcast type or we are no more the DR, we flush the LSA otherwise -- create the new instance and @@ -178,13 +176,11 @@ ospf_process_self_originated_lsa (struct ospf *ospf, return; } -#ifdef HAVE_OPAQUE_LSA if (new->data->type == OSPF_OPAQUE_LINK_LSA) { ospf_opaque_lsa_refresh (new); return; } -#endif /* HAVE_OPAQUE_LSA */ if (oi->network_lsa_self) oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum; @@ -211,14 +207,12 @@ ospf_process_self_originated_lsa (struct ospf *ospf, else ospf_lsa_flush_as (ospf, new); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AREA_LSA: ospf_opaque_lsa_refresh (new); break; case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */ break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -299,25 +293,17 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, interface. */ lsa_ack_flag = ospf_flood_through (ospf, nbr, new); -#ifdef HAVE_OPAQUE_LSA /* Remove the current database copy from all neighbors' Link state retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does ^^^^^^^^^^^^^^^^^^^^^^^ not have area ID. All other (even NSSA's) do have area ID. */ -#else /* HAVE_OPAQUE_LSA */ - /* Remove the current database copy from all neighbors' Link state - retransmission lists. Only AS_EXTERNAL does not have area ID. - All other (even NSSA's) do have area ID. */ -#endif /* HAVE_OPAQUE_LSA */ if (current) { switch (current->data->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_ls_retransmit_delete_nbr_as (ospf, current); break; default: @@ -439,7 +425,6 @@ ospf_flood_through_interface (struct ospf_interface *oi, } } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type)) { if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O)) @@ -449,7 +434,6 @@ ospf_flood_through_interface (struct ospf_interface *oi, continue; } } -#endif /* HAVE_OPAQUE_LSA */ /* If the new LSA was received from this neighbor, examine the next neighbor. */ @@ -584,7 +568,6 @@ ospf_flood_through_area (struct ospf_area *area, oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; -#ifdef HAVE_OPAQUE_LSA if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi)) { /* @@ -596,7 +579,6 @@ ospf_flood_through_area (struct ospf_area *area, (void *)lsa->oi, (void *)oi); continue; } -#endif /* HAVE_OPAQUE_LSA */ if (ospf_flood_through_interface (oi, inbr, lsa)) lsa_ack_flag = 1; @@ -706,16 +688,12 @@ ospf_flood_through (struct ospf *ospf, case OSPF_NETWORK_LSA: case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); break; case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); break; /* Type-7 Only received within NSSA, then flooded */ @@ -745,9 +723,7 @@ ospf_flood_through (struct ospf *ospf, switch (lsa->data->type) { case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); break; /* Type-7 Only received within NSSA, then flooded */ @@ -1024,16 +1000,12 @@ ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa) case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_lsa_flush_area (lsa, lsa->area); break; case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_lsa_flush_as (ospf, lsa); break; default: diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 5602ebe897..2c8124b93d 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -243,9 +243,7 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) oi->crypt_seqnum = time (NULL); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type9_lsa_init (oi); -#endif /* HAVE_OPAQUE_LSA */ oi->ospf = ospf; @@ -307,9 +305,7 @@ ospf_if_free (struct ospf_interface *oi) assert (oi->state == ISM_Down); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type9_lsa_term (oi); -#endif /* HAVE_OPAQUE_LSA */ /* Free Pseudo Neighbour */ ospf_nbr_delete (oi->nbr_self); @@ -696,9 +692,7 @@ ospf_if_new_hook (struct interface *ifp) SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET; -#ifdef HAVE_OPAQUE_LSA rc = ospf_opaque_new_if (ifp); -#endif /* HAVE_OPAQUE_LSA */ return rc; } @@ -707,9 +701,7 @@ ospf_if_delete_hook (struct interface *ifp) { int rc = 0; struct route_node *rn; -#ifdef HAVE_OPAQUE_LSA rc = ospf_opaque_del_if (ifp); -#endif /* HAVE_OPAQUE_LSA */ route_table_finish (IF_OIFS (ifp)); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 68dbf186d2..7a74288bff 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -188,9 +188,7 @@ struct ospf_interface /* self-originated LSAs. */ struct ospf_lsa *network_lsa_self; /* network-LSA. */ -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-9 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ struct route_table *ls_upd_queue; @@ -211,9 +209,7 @@ struct ospf_interface struct thread *t_ls_ack; /* timer */ struct thread *t_ls_ack_direct; /* event */ struct thread *t_ls_upd_event; /* event */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-9 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ int on_write_q; diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 9649df8dc0..ae6d0cdbc5 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -593,9 +593,7 @@ ism_change_state (struct ospf_interface *oi, int state) oi->network_lsa_self = NULL; } -#ifdef HAVE_OPAQUE_LSA ospf_opaque_ism_change (oi, old_state); -#endif /* HAVE_OPAQUE_LSA */ /* Check area border status. */ ospf_check_abr_status (oi->ospf); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 7e34e5dd9e..b96ed452c1 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2251,7 +2251,7 @@ ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p) void ospf_external_lsa_flush (struct ospf *ospf, u_char type, struct prefix_ipv4 *p, - unsigned int ifindex /*, struct in_addr nexthop */) + ifindex_t ifindex /*, struct in_addr nexthop */) { struct ospf_lsa *lsa; @@ -2642,11 +2642,9 @@ ospf_discard_from_db (struct ospf *ospf, ospf_ase_unregister_external_lsa (old, ospf); ospf_ls_retransmit_delete_nbr_as (ospf, old); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: ospf_ls_retransmit_delete_nbr_as (ospf, old); break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: ospf_ls_retransmit_delete_nbr_area (old->area, old); ospf_ase_unregister_external_lsa (old, ospf); @@ -2680,9 +2678,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, lsdb = ospf->lsdb; break; case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsdb = ospf->lsdb; break; default: @@ -2794,7 +2790,6 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, case OSPF_AS_EXTERNAL_LSA: new = ospf_external_lsa_install (ospf, lsa, rt_recalc); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: if (IS_LSA_SELF (lsa)) lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */ @@ -2807,7 +2802,6 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, case OSPF_OPAQUE_AS_LSA: new = ospf_opaque_lsa_install (lsa, rt_recalc); break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: new = ospf_external_lsa_install (ospf, lsa, rt_recalc); default: /* type-6,8,9....nothing special */ @@ -2825,9 +2819,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, switch (lsa->data->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: zlog_debug ("LSA[%s]: Install %s", dump_lsa_key (new), @@ -3061,7 +3053,6 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) switch (lsa->data->type) { -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -3074,7 +3065,6 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) * topology, and thus, routing recalculation is not needed here. */ break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_NSSA_LSA: ospf_ase_incremental_update (ospf, lsa); @@ -3115,12 +3105,10 @@ ospf_lsa_maxage_walker (struct thread *thread) ospf_lsa_maxage_walker_remover (ospf, lsa); LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ LSDB_LOOP (NSSA_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); } @@ -3130,10 +3118,8 @@ ospf_lsa_maxage_walker (struct thread *thread) { LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker, @@ -3186,15 +3172,11 @@ ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router); case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router); default: break; @@ -3230,13 +3212,11 @@ ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type, return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: /* Currently not used. */ break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -3249,14 +3229,12 @@ ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah) { struct ospf_lsa *match; -#ifdef HAVE_OPAQUE_LSA /* * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) * is redefined to have two subfields; opaque-type and opaque-id. * However, it is harmless to treat the two sub fields together, as if * they two were forming a unique LSA-ID. */ -#endif /* HAVE_OPAQUE_LSA */ match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router); @@ -3407,14 +3385,12 @@ ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa) switch (lsa->data->type) { -#ifdef HAVE_OPAQUE_LSA /* Opaque wants to be notified of flushes */ case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_refresh (lsa); break; -#endif /* HAVE_OPAQUE_LSA */ default: ospf_refresher_unregister_lsa (ospf, lsa); ospf_lsa_flush (ospf, lsa); @@ -3474,22 +3450,18 @@ ospf_flush_self_originated_lsas_now (struct ospf *ospf) ospf_lsa_flush_schedule (ospf, lsa); LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } if (need_to_flush_ase) { LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } /* @@ -3698,13 +3670,11 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) else ospf_lsa_flush_as (ospf, lsa); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: new = ospf_opaque_lsa_refresh (lsa); break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index f2c08b1b93..28ecc9d4d6 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -27,11 +27,7 @@ /* OSPF LSA Range definition. */ #define OSPF_MIN_LSA 1 /* begin range here */ -#if defined (HAVE_OPAQUE_LSA) #define OSPF_MAX_LSA 12 -#else -#define OSPF_MAX_LSA 8 -#endif /* OSPF LSA Type definition. */ #define OSPF_UNKNOWN_LSA 0 @@ -211,9 +207,7 @@ struct as_external_lsa } e[1]; }; -#ifdef HAVE_OPAQUE_LSA #include "ospfd/ospf_opaque.h" -#endif /* HAVE_OPAQUE_LSA */ /* Macros. */ #define GET_METRIC(x) get_metric(x) @@ -283,7 +277,7 @@ extern struct ospf_lsa *ospf_lsa_install (struct ospf *, extern void ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p); extern void ospf_external_lsa_flush (struct ospf *, u_char, struct prefix_ipv4 *, - unsigned int /* , struct in_addr nexthop */); + ifindex_t /* , struct in_addr nexthop */); extern struct in_addr ospf_get_ip_from_ifp (struct ospf_interface *); diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 48f39d0099..55ec2a306c 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -325,9 +325,7 @@ main (int argc, char **argv) #ifdef HAVE_SNMP ospf_snmp_init (); #endif /* HAVE_SNMP */ -#ifdef HAVE_OPAQUE_LSA ospf_opaque_init (); -#endif /* HAVE_OPAQUE_LSA */ /* Need to initialize the default ospf structure, so the interface mode commands can be duly processed if they are received before 'router ospf', diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 1954447b64..a573936c18 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -310,7 +310,6 @@ ospf_nbr_count (struct ospf_interface *oi, int state) return count; } -#ifdef HAVE_OPAQUE_LSA int ospf_nbr_count_opaque_capable (struct ospf_interface *oi) { @@ -327,7 +326,6 @@ ospf_nbr_count_opaque_capable (struct ospf_interface *oi) return count; } -#endif /* HAVE_OPAQUE_LSA */ /* lookup nbr by address - use this only if you know you must * otherwise use the ospf_nbr_lookup() wrapper, which deals diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 0e209d2117..d62de44b5e 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -105,9 +105,7 @@ extern int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int); extern void ospf_nbr_self_reset (struct ospf_interface *, struct in_addr); extern void ospf_nbr_add_self (struct ospf_interface *, struct in_addr); extern int ospf_nbr_count (struct ospf_interface *, int); -#ifdef HAVE_OPAQUE_LSA extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); -#endif /* HAVE_OPAQUE_LSA */ extern struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, struct ospf_header *, struct ip *, struct prefix *); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 2f167a50a5..6caa38d68b 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -48,12 +48,12 @@ extern struct zebra_privs_t ospfd_privs; /* Join to the OSPF ALL SPF ROUTERS multicast group. */ int ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - htonl (OSPF_ALLSPFROUTERS), + p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -69,12 +69,12 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, int ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - htonl (OSPF_ALLSPFROUTERS), + p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -89,13 +89,12 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, /* Join to the OSPF ALL Designated ROUTERS multicast group. */ int -ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int - ifindex) +ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - htonl (OSPF_ALLDROUTERS), + p->u.prefix4, htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -110,13 +109,12 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int } int -ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int - ifindex) +ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - htonl (OSPF_ALLDROUTERS), + p->u.prefix4, htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -130,7 +128,7 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int } int -ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex) +ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) { u_char val; int ret, len; @@ -151,7 +149,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex) zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", top->fd, safe_strerror (errno)); - ret = setsockopt_ipv4_multicast_if (top->fd, ifindex); + ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex); if (ret < 0) zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " "ifindex %u): %s", diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index e0a5c69d5c..8257adb4af 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -25,14 +25,14 @@ /* Prototypes. */ extern int ospf_if_add_allspfrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_add_alldrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, - unsigned int); -extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, unsigned int); + ifindex_t); +extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, ifindex_t); extern int ospf_sock_init (void); extern void ospf_adjust_sndbuflen (struct ospf *, unsigned int); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 6fc7c266ac..c6b55b0746 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -222,7 +222,6 @@ ospf_db_summary_isempty (struct ospf_neighbor *nbr) static int ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { -#ifdef HAVE_OPAQUE_LSA switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: @@ -240,7 +239,6 @@ ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) default: break; } -#endif /* HAVE_OPAQUE_LSA */ /* Stay away from any Local Translated Type-7 LSAs */ if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) @@ -299,7 +297,6 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_db_summary_add (nbr, lsa); -#ifdef HAVE_OPAQUE_LSA /* Process only if the neighbor is opaque capable. */ if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { @@ -308,7 +305,6 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_db_summary_add (nbr, lsa); } -#endif /* HAVE_OPAQUE_LSA */ if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP)) { @@ -321,13 +317,11 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa) ospf_db_summary_add (nbr, lsa); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O) && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK && area->external_routing == OSPF_AREA_DEFAULT)) LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa) ospf_db_summary_add (nbr, lsa); -#endif /* HAVE_OPAQUE_LSA */ return 0; } @@ -383,10 +377,8 @@ nsm_clear_adj (struct ospf_neighbor *nbr) if (!ospf_ls_retransmit_isempty (nbr)) ospf_ls_retransmit_clear (nbr); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) UNSET_FLAG (nbr->options, OSPF_OPTION_O); -#endif /* HAVE_OPAQUE_LSA */ } static int @@ -768,9 +760,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state) } } -#ifdef HAVE_OPAQUE_LSA ospf_opaque_nsm_change (nbr, old_state); -#endif /* HAVE_OPAQUE_LSA */ /* State changes from > ExStart to <= ExStart should clear any Exchange * or Full/LSA Update related lists and state. diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index ff505b6bd3..9b395b3e8e 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -27,7 +27,6 @@ #define MTYPE_OPAQUE_INFO_PER_ID MTYPE_TMP #include <zebra.h> -#ifdef HAVE_OPAQUE_LSA #include "linklist.h" #include "prefix.h" @@ -62,9 +61,8 @@ * Followings are initialize/terminate functions for Opaque-LSAs handling. *------------------------------------------------------------------------*/ -#ifdef HAVE_OSPF_TE #include "ospfd/ospf_te.h" -#endif /* HAVE_OSPF_TE */ +#include "ospfd/ospf_ri.h" #ifdef SUPPORT_OSPF_API int ospf_apiserver_init (void); @@ -87,10 +85,11 @@ ospf_opaque_init (void) ospf_opaque_register_vty (); ospf_opaque_funclist_init (); -#ifdef HAVE_OSPF_TE if (ospf_mpls_te_init () != 0) exit (1); -#endif /* HAVE_OSPF_TE */ + + if (ospf_router_info_init () != 0) + exit (1); #ifdef SUPPORT_OSPF_API if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0)) @@ -103,9 +102,9 @@ ospf_opaque_init (void) void ospf_opaque_term (void) { -#ifdef HAVE_OSPF_TE ospf_mpls_te_term (); -#endif /* HAVE_OSPF_TE */ + + ospf_router_info_term (); #ifdef SUPPORT_OSPF_API ospf_apiserver_term (); @@ -220,6 +219,12 @@ 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; + case OPAQUE_TYPE_ROUTER_INFORMATION_LSA: + name = "Router Information LSA"; + break; default: if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type)) name = "Unassigned"; @@ -1986,6 +1991,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 @@ -2017,7 +2023,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); @@ -2062,6 +2071,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) @@ -2085,7 +2097,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); @@ -2109,7 +2123,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; @@ -2151,28 +2165,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) { @@ -2185,4 +2177,3 @@ oi_to_top (struct ospf_interface *oi) return top; } -#endif /* HAVE_OPAQUE_LSA */ diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index b9490a0ff2..2ac9b41efc 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -60,6 +60,10 @@ #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 */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 3f80bf214b..399a558a0d 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -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. @@ -925,7 +925,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE) && CHECK_FLAG (hello->options, OSPF_OPTION_O)) { @@ -941,7 +940,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */ #endif /* STRICT_OBIT_USAGE_CHECK */ } -#endif /* HAVE_OPAQUE_LSA */ /* new for NSSA is to ensure that NP is on and E is off */ @@ -1093,7 +1091,6 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, return; } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsah->type) && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { @@ -1101,14 +1098,11 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); return; } -#endif /* HAVE_OPAQUE_LSA */ switch (lsah->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ /* Check for stub area. Reject if AS-External from stub but allow if from NSSA. */ if (oi->area->external_routing == OSPF_AREA_STUB) @@ -1271,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 @@ -1282,7 +1276,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (dd->options, OSPF_OPTION_O) && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { @@ -1292,7 +1285,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, */ UNSET_FLAG (dd->options, OSPF_OPTION_O); } -#endif /* HAVE_OPAQUE_LSA */ /* Add event to thread. */ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); @@ -1357,7 +1349,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, /* This is where the real Options are saved */ nbr->options = dd->options; -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) @@ -1375,7 +1366,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, /* This situation is undesirable, but not a real error. */ } } -#endif /* HAVE_OPAQUE_LSA */ OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone); @@ -1653,7 +1643,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE) lsah->ls_age = htons (OSPF_LSA_MAXAGE); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { #ifdef STRICT_OBIT_USAGE_CHECK @@ -1685,7 +1674,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id)); continue; } -#endif /* HAVE_OPAQUE_LSA */ /* Create OSPF LSA instance. */ lsa = ospf_lsa_new (); @@ -1695,16 +1683,12 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, switch (lsah->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa->area = NULL; break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: lsa->oi = oi; /* Remember incoming interface for flooding control. */ /* Fallthrough */ -#endif /* HAVE_OPAQUE_LSA */ default: lsa->area = oi->area; break; @@ -1892,7 +1876,6 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, DISCARD_LSA (lsa, 3); } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type) && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id)) { @@ -1940,7 +1923,6 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, continue; } } -#endif /* HAVE_OPAQUE_LSA */ /* It might be happen that received LSA is self-originated network LSA, but * router ID is changed. So, we should check if LSA is a network-LSA whose @@ -2161,7 +2143,7 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) int ret; struct ip *iph; u_int16_t ip_len; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; struct iovec iov; /* Header and data both require alignment. */ char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; @@ -2517,7 +2499,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -2525,7 +2506,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char * data) padded to 32-bit alignment." This is considered equivalent * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt * file for the detailed analysis of this passage. */ -#endif ret = lsalen % 4 ? MSG_NG : MSG_OK; break; default: @@ -3157,10 +3137,8 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, /* Set Options. */ options = OPTIONS (oi); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) SET_FLAG (options, OSPF_OPTION_O); -#endif /* HAVE_OPAQUE_LSA */ stream_putc (s, options); /* DD flags */ @@ -3185,7 +3163,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, for (rn = route_top (table); rn; rn = route_next (rn)) if ((lsa = rn->info) != NULL) { -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type) && (! CHECK_FLAG (options, OSPF_OPTION_O))) { @@ -3194,7 +3171,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, ospf_lsdb_delete (lsdb, lsa); continue; } -#endif /* HAVE_OPAQUE_LSA */ if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) { diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c new file mode 100644 index 0000000000..8fefd2bdb8 --- /dev/null +++ b/ospfd/ospf_ri.c @@ -0,0 +1,1639 @@ +/* + * This is an implementation of RFC4970 Router Information + * with support of RFC5088 PCE Capabilites announcement + * + * Module name: Router Information + * Version: 0.99.22 + * Created: 2012-02-01 by Olivier Dugeon + * Copyright (C) 2012 Orange Labs http://www.orange.com/ + * + * This file is part of GNU Quagga. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> +#include <math.h> + +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "memory.h" +#include "command.h" +#include "vty.h" +#include "stream.h" +#include "log.h" +#include "thread.h" +#include "hash.h" +#include "sockunion.h" /* for inet_aton() */ + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_spf.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" +#include "ospfd/ospf_ase.h" +#include "ospfd/ospf_zebra.h" +#include "ospfd/ospf_ri.h" +#include "ospfd/ospf_te.h" + +struct ospf_pce_info +{ + + /* Store Router Information PCE TLV and SubTLV in network byte order. */ + struct ri_tlv_pce pce_header; + struct ri_pce_subtlv_address pce_address; + struct ri_pce_subtlv_path_scope pce_scope; + struct list *pce_domain; + struct list *pce_neighbor; + struct ri_pce_subtlv_cap_flag pce_cap_flag; +}; + +/* Following structure are internal use only. */ +struct ospf_router_info +{ + status_t status; + + u_int8_t registered; + u_int8_t scope; + + /* Flags to manage this router information. */ +#define RIFLG_LOOKUP_DONE 0x1 +#define RIFLG_LSA_ENGAGED 0x2 +#define RIFLG_LSA_FORCED_REFRESH 0x4 + u_int32_t flags; + + /* area pointer if flooding is Type 10 Null if flooding is AS scope */ + struct ospf_area *area; + struct in_addr area_id; + + /* Store Router Information Capabilities LSA */ + struct ri_tlv_router_cap router_cap; + + /* Store PCE capability LSA */ + struct ospf_pce_info pce_info; +}; + +/* + * Global variable to manage Opaque-LSA/Router Information on this node. + * Note that all parameter values are stored in network byte order. + */ +static struct ospf_router_info OspfRI; + +/*------------------------------------------------------------------------------* + * Followings are initialize/terminate functions for Router Information handling. + *------------------------------------------------------------------------------*/ + +static void ospf_router_info_ism_change (struct ospf_interface *oi, + int old_status); +static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr, + int old_status); +static void ospf_router_info_config_write_router (struct vty *vty); +static void ospf_router_info_show_info (struct vty *vty, + struct ospf_lsa *lsa); +static int ospf_router_info_lsa_originate (void *arg); +static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa); +static void ospf_router_info_lsa_schedule (opcode_t opcode); +static void ospf_router_info_register_vty (void); +static void del_pce_info (void *val); + +int +ospf_router_info_init (void) +{ + + memset (&OspfRI, 0, sizeof (struct ospf_router_info)); + OspfRI.status = disabled; + OspfRI.registered = 0; + OspfRI.scope = OSPF_OPAQUE_AS_LSA; + OspfRI.flags = 0; + + /* Initialize pce domain and neighbor list */ + OspfRI.pce_info.pce_domain = list_new (); + OspfRI.pce_info.pce_domain->del = del_pce_info; + OspfRI.pce_info.pce_neighbor = list_new (); + OspfRI.pce_info.pce_neighbor->del = del_pce_info; + + ospf_router_info_register_vty (); + + return 0; +} + +static int +ospf_router_info_register (u_int8_t scope) +{ + int rc = 0; + + if (OspfRI.registered) + return 0; + + zlog_info ("Register Router Information with scope %s(%d)", + scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope); + rc = ospf_register_opaque_functab (scope, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA, + NULL, /* new interface */ + NULL, /* del interface */ + ospf_router_info_ism_change, + ospf_router_info_nsm_change, + ospf_router_info_config_write_router, + NULL, /* Config. write interface */ + NULL, /* Config. write debug */ + ospf_router_info_show_info, + ospf_router_info_lsa_originate, + ospf_router_info_lsa_refresh, + NULL, /* new_lsa_hook */ + NULL); /* del_lsa_hook */ + + if (rc != 0) + { + zlog_warn ("ospf_router_info_init: Failed to register functions"); + return rc; + } + + OspfRI.registered = 1; + OspfRI.scope = scope; + return 0; +} + +static int +ospf_router_info_unregister () +{ + + if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA) + && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) + { + zlog_warn ("Unable to unregister Router Info functions: Wrong scope!"); + return -1; + } + + ospf_delete_opaque_functab (OspfRI.scope, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + + OspfRI.registered = 0; + return 0; + +} + +void +ospf_router_info_term (void) +{ + + list_delete (OspfRI.pce_info.pce_domain); + list_delete (OspfRI.pce_info.pce_neighbor); + + OspfRI.pce_info.pce_domain = NULL; + OspfRI.pce_info.pce_neighbor = NULL; + OspfRI.status = disabled; + + ospf_router_info_unregister (); + + return; +} + +static void +del_pce_info (void *val) +{ + XFREE (MTYPE_OSPF_PCE_PARAMS, val); + return; +} + +/*------------------------------------------------------------------------* + * Followings are control functions for ROUTER INFORMATION parameters management. + *------------------------------------------------------------------------*/ + +static void +set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap) +{ + ric->header.type = htons (RI_TLV_CAPABILITIES); + ric->header.length = htons (RI_TLV_LENGTH); + ric->value = htonl (cap); + return; +} + +static int +set_pce_header (struct ospf_pce_info *pce) +{ + u_int16_t length = 0; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + /* PCE Address */ + if (ntohs (pce->pce_address.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_address.header); + + /* PCE Path Scope */ + if (ntohs (pce->pce_scope.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_scope.header); + + /* PCE Domain */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (ntohs (domain->header.type) != 0) + length += RI_TLV_SIZE (&domain->header); + } + + /* PCE Neighbor */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (ntohs (neighbor->header.type) != 0) + length += RI_TLV_SIZE (&neighbor->header); + } + + /* PCE Capabilities */ + if (ntohs (pce->pce_cap_flag.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_cap_flag.header); + + if (length != 0) + { + pce->pce_header.header.type = htons (RI_TLV_PCE); + pce->pce_header.header.length = htons (length); + } + else + { + pce->pce_header.header.type = 0; + pce->pce_header.header.length = 0; + } + + return length; +} + +static void +set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Address */ + pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS); + pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4); + pce->pce_address.address.value = ipv4; + + return; +} + +static void +set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Scope */ + pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE); + pce->pce_scope.header.length = htons (RI_TLV_LENGTH); + pce->pce_scope.value = htonl (scope); + + return; +} + +static void +set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + + struct ri_pce_subtlv_domain *new; + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + + /* Create new domain info */ + new = + XCALLOC (MTYPE_OSPF_PCE_PARAMS, + sizeof (struct ri_pce_subtlv_domain)); + + new->header.type = htons (RI_PCE_SUBTLV_DOMAIN); + new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + new->type = htons (type); + new->value = htonl (domain); + + /* Add new domain to the list */ + listnode_add (pce->pce_domain, new); + + return; +} + +static void +unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + struct listnode *node; + struct ri_pce_subtlv_domain *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old)) + { + if ((old->type == htons (type)) && (old->value == htonl (domain))) + { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) + { + listnode_delete (pce->pce_domain, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount (pce->pce_domain) == 0) + pce->pce_domain->head = pce->pce_domain->tail = NULL; + + /* Finally free the old domain */ + XFREE (MTYPE_OSPF_PCE_PARAMS, old); + } +} + +static void +set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + + struct ri_pce_subtlv_neighbor *new; + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + + /* Create new neighbor info */ + new = + XCALLOC (MTYPE_OSPF_PCE_PARAMS, + sizeof (struct ri_pce_subtlv_neighbor)); + + new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR); + new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + new->type = htons (type); + new->value = htonl (domain); + + /* Add new domain to the list */ + listnode_add (pce->pce_neighbor, new); + + return; +} + +static void +unset_pce_neighbor (u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) +{ + struct listnode *node; + struct ri_pce_subtlv_neighbor *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old)) + { + if ((old->type == htons (type)) && (old->value == htonl (domain))) + { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) + { + listnode_delete (pce->pce_neighbor, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount (pce->pce_neighbor) == 0) + pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL; + + /* Finally free the old domain */ + XFREE (MTYPE_OSPF_PCE_PARAMS, old); + } +} + +static void +set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Capabilities flag */ + pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG); + pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH); + pce->pce_cap_flag.value = htonl (cap); + + return; +} + + +static void +unset_param (struct ri_tlv_header *tlv) +{ + + tlv->type = 0; + /* Fill the Value to 0 */ + memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv)); + tlv->length = 0; + + return; +} + +static void +initialize_params (struct ospf_router_info *ori) +{ + u_int32_t cap; + struct ospf *top; + + /* + * Initialize default Router Information Capabilities. + */ + cap = 0; + cap = cap | RI_TE_SUPPORT; + + set_router_info_capabilities (&ori->router_cap, cap); + + /* If Area address is not null and exist, retrieve corresponding structure */ + top = ospf_lookup (); + zlog_info ("RI-> Initialize Router Info for %s scope within area %s", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", + inet_ntoa (OspfRI.area_id)); + + /* Try to get the Area context at this step. Do it latter if not available */ + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) + OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); + + /* + * Initialize default PCE Information values + */ + /* PCE address == OSPF Router ID */ + set_pce_address (top->router_id, &ori->pce_info); + + /* PCE scope */ + cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */ + set_pce_path_scope (cap, &ori->pce_info); + + /* PCE Capabilities */ + cap = + PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES | + PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ; + set_pce_cap_flag (cap, &ori->pce_info); + + /* Finally compute PCE header */ + set_pce_header (&ori->pce_info); + + return; +} + +static int +is_mandated_params_set (struct ospf_router_info ori) +{ + int rc = 0; + + if (ntohs (ori.router_cap.header.type) == 0) + goto out; + + if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE) + && (ntohs (ori.pce_info.pce_address.header.type) == 0) + && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0)) + goto out; + + rc = 1; + +out: + return rc; +} + +/*------------------------------------------------------------------------* + * Followings are callback functions against generic Opaque-LSAs handling. + *------------------------------------------------------------------------*/ +static void +ospf_router_info_ism_change (struct ospf_interface *oi, int old_state) +{ + /* So far, nothing to do here. */ + return; + +} + +static void +ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state) +{ + + /* So far, nothing to do here. */ + return; +} + +/*------------------------------------------------------------------------* + * Followings are OSPF protocol processing functions for ROUTER INFORMATION + *------------------------------------------------------------------------*/ + +static void +build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh) +{ + + stream_put (s, tlvh, sizeof (struct ri_tlv_header)); + return; +} + +static void +build_tlv (struct stream *s, struct ri_tlv_header *tlvh) +{ + + if (ntohs (tlvh->type) != 0) + { + build_tlv_header (s, tlvh); + stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh)); + } + return; +} + +static void +ospf_router_info_lsa_body_set (struct stream *s) +{ + + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + /* Build Router Information TLV */ + build_tlv (s, &OspfRI.router_cap.header); + + /* Add RI PCE TLV if it is set */ + /* Compute PCE Info header first */ + if ((set_pce_header (&OspfRI.pce_info)) != 0) + { + + /* Build PCE TLV */ + build_tlv_header (s, &OspfRI.pce_info.pce_header.header); + + /* Build PCE address sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_address.header); + + /* Build PCE path scope sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_scope.header); + + /* Build PCE domain sub-tlv */ + for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain)) + build_tlv (s, &domain->header); + + /* Build PCE neighbor sub-tlv */ + for (ALL_LIST_ELEMENTS_RO + (OspfRI.pce_info.pce_neighbor, node, neighbor)) + build_tlv (s, &neighbor->header); + + /* Build PCE cap flag sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header); + } + + return; +} + +/* Create new opaque-LSA. */ +static struct ospf_lsa * +ospf_router_info_lsa_new () +{ + struct ospf *top; + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new = NULL; + u_char options, lsa_type; + struct in_addr lsa_id; + u_int32_t tmp; + u_int16_t length; + + /* Create a stream for LSA. */ + if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: stream_new() ?"); + goto out; + } + lsah = (struct lsa_header *) STREAM_DATA (s); + + options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */ + options |= OSPF_OPTION_O; /* Don't forget this :-) */ + + lsa_type = OspfRI.scope; + /* LSA ID == 0 for Router Information see RFC 4970 */ + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsa_id.s_addr = htonl (tmp); + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_debug + ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance", + lsa_type, inet_ntoa (lsa_id)); + + top = ospf_lookup (); + + /* Set opaque-LSA header fields. */ + lsa_header_set (s, options, lsa_type, lsa_id, top->router_id); + + /* Set opaque-LSA body fields. */ + ospf_router_info_lsa_body_set (s); + + /* Set length. */ + length = stream_get_endp (s); + lsah->length = htons (length); + + /* Now, create an OSPF LSA instance. */ + if ((new = ospf_lsa_new ()) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?"); + stream_free (s); + goto out; + } + if ((new->data = ospf_lsa_data_new (length)) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_unlock (&new); + new = NULL; + stream_free (s); + goto out; + } + + new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */ + + SET_FLAG (new->flags, OSPF_LSA_SELF); + memcpy (new->data, lsah, length); + stream_free (s); + +out:return new; +} + +static int +ospf_router_info_lsa_originate1 (void *arg) +{ + struct ospf_lsa *new; + struct ospf *top; + struct ospf_area *area; + int rc = -1; + + /* First check if the area is known if flooding scope is Area */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + { + area = (struct ospf_area *) arg; + if (area->area_id.s_addr != OspfRI.area_id.s_addr) + { + zlog_debug + ("RI -> This is not the Router Information Area. Stop processing"); + goto out; + } + OspfRI.area = area; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new ()) == NULL) + { + zlog_warn + ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?"); + goto out; + } + + /* Get ospf info */ + top = ospf_lookup (); + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) + { + zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?"); + ospf_lsa_unlock (&new); + goto out; + } + + /* Now this Router Info parameter entry has associated LSA. */ + SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED); + + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AS. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as (top, NULL /*nbr */ , new); + else + ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + + rc = 0; +out:return rc; +} + +static int +ospf_router_info_lsa_originate (void *arg) +{ + + int rc = -1; + + if (OspfRI.status == disabled) + { + zlog_info + ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + /* Check if Router Information LSA is already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + { + if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH) + { + OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH; + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + } + else + { + if (!is_mandated_params_set (OspfRI)) + zlog_warn + ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters"); + + /* Ok, let's try to originate an LSA */ + if (ospf_router_info_lsa_originate1 (arg) != 0) + goto out; + } + + rc = 0; +out:return rc; +} + +static struct ospf_lsa * +ospf_router_info_lsa_refresh (struct ospf_lsa *lsa) +{ + struct ospf_lsa *new = NULL; + struct ospf *top; + + if (OspfRI.status == disabled) + { + /* + * This LSA must have flushed before due to ROUTER INFORMATION status change. + * It seems a slip among routers in the routing domain. + */ + zlog_info + ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now."); + lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* Verify that the Router Information ID is supported */ + if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0) + { + zlog_warn + ("ospf_router_info_lsa_refresh: Unsupported Router Information ID"); + goto out; + } + + /* If the lsa's age reached to MaxAge, start flushing procedure. */ + if (IS_LSA_MAXAGE (lsa)) + { + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule (lsa); + goto out; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new ()) == NULL) + { + zlog_warn + ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?"); + goto out; + } + new->data->ls_seqnum = lsa_seqnum_increment (lsa); + + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + top = ospf_lookup (); + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) + { + zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); + ospf_lsa_unlock (&new); + goto out; + } + + /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as (top, NULL /*nbr */ , new); + else + ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + +out:return new; +} + +static void +ospf_router_info_lsa_schedule (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)); + + zlog_debug ("RI-> LSA schedule %s%s%s", + opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "", + opcode == REFRESH_THIS_LSA ? "Refresh" : "", + opcode == FLUSH_THIS_LSA ? "Flush" : ""); + + top = ospf_lookup (); + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) + { + zlog_warn + ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); + OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); + } + lsa.area = OspfRI.area; + lsa.data = &lsah; + lsah.type = OspfRI.scope; + + /* LSA ID is set to 0 for the Router Information. See RFC 4970 */ + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsah.id.s_addr = htonl (tmp); + + switch (opcode) + { + case REORIGINATE_THIS_LSA: + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area, + OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + else + ospf_opaque_lsa_reoriginate_schedule ((void *) top, + OSPF_OPAQUE_AS_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + break; + case REFRESH_THIS_LSA: + ospf_opaque_lsa_refresh_schedule (&lsa); + break; + case FLUSH_THIS_LSA: + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule (&lsa); + break; + default: + zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)", + opcode); + break; + } + + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty session control functions. + *------------------------------------------------------------------------*/ + +static u_int16_t +show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh; + + if (vty != NULL) + vty_out (vty, " Router Capabilities: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh; + + if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4) + { + if (vty != NULL) + vty_out (vty, " PCE Address: %s%s", inet_ntoa (top->address.value), + VTY_NEWLINE); + else + zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value)); + } + else + { + /* TODO: Add support to IPv6 with inet_ntop() */ + if (vty != NULL) + vty_out (vty, " PCE Address: 0x%x%s", + ntohl (top->address.value.s_addr), VTY_NEWLINE); + else + zlog_debug (" PCE Address: 0x%x", + ntohl (top->address.value.s_addr)); + } + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_path_scope *top = + (struct ri_pce_subtlv_path_scope *) tlvh; + + if (vty != NULL) + vty_out (vty, " PCE Path Scope: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh; + struct in_addr tmp; + + if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out (vty, " PCE domain Area: %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + else + zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp)); + } + else + { + if (vty != NULL) + vty_out (vty, " PCE domain AS: %d%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE domain AS: %d", ntohl (top->value)); + } + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh) +{ + + struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh; + struct in_addr tmp; + + if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out (vty, " PCE neighbor Area: %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + else + zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp)); + } + else + { + if (vty != NULL) + vty_out (vty, " PCE neighbor AS: %d%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE neighbor AS: %d", ntohl (top->value)); + } + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh; + + if (vty != NULL) + vty_out (vty, " PCE Capabilities Flag: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_unknown_tlv (struct vty *vty, struct ri_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); + else + zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", + ntohs (tlvh->type), ntohs (tlvh->length)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total) +{ + struct ri_tlv_header *tlvh; + u_int16_t sum = 0; + + for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh)) + { + switch (ntohs (tlvh->type)) + { + case RI_PCE_SUBTLV_ADDRESS: + sum += show_vty_pce_subtlv_address (vty, tlvh); + break; + case RI_PCE_SUBTLV_PATH_SCOPE: + sum += show_vty_pce_subtlv_path_scope (vty, tlvh); + break; + case RI_PCE_SUBTLV_DOMAIN: + sum += show_vty_pce_subtlv_domain (vty, tlvh); + break; + case RI_PCE_SUBTLV_NEIGHBOR: + sum += show_vty_pce_subtlv_neighbor (vty, tlvh); + break; + case RI_PCE_SUBTLV_CAP_FLAG: + sum += show_vty_pce_subtlv_cap_flag (vty, tlvh); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + return sum; +} + +static void +ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa) +{ + struct lsa_header *lsah = (struct lsa_header *) lsa->data; + struct ri_tlv_header *tlvh; + u_int16_t length = 0, sum = 0; + + /* Initialize TLV browsing */ + length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE; + + for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length; + tlvh = RI_TLV_HDR_NEXT (tlvh)) + { + switch (ntohs (tlvh->type)) + { + case RI_TLV_CAPABILITIES: + sum += show_vty_router_cap (vty, tlvh); + break; + case RI_TLV_PCE: + tlvh++; + sum += RI_TLV_HDR_SIZE; + sum += show_vty_pce_info (vty, tlvh, length - sum); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + + return; +} + +static void +ospf_router_info_config_write_router (struct vty *vty) +{ + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + struct in_addr tmp; + + if (OspfRI.status == enabled) + { + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + vty_out (vty, " router-info as%s", VTY_NEWLINE); + else + vty_out (vty, " router-info area %s%s", inet_ntoa (OspfRI.area_id), + VTY_NEWLINE); + + if (pce->pce_address.header.type != 0) + vty_out (vty, " pce address %s%s", + inet_ntoa (pce->pce_address.address.value), VTY_NEWLINE); + + if (pce->pce_cap_flag.header.type != 0) + vty_out (vty, " pce flag 0x%x%s", ntohl (pce->pce_cap_flag.value), + VTY_NEWLINE); + + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (domain->header.type != 0) + { + if (domain->type == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = domain->value; + vty_out (vty, " pce domain area %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + } + else + { + vty_out (vty, " pce domain as %d%s", ntohl (domain->value), + VTY_NEWLINE); + } + } + } + + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (neighbor->header.type != 0) + { + if (neighbor->type == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = neighbor->value; + vty_out (vty, " pce neighbor area %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + } + else + { + vty_out (vty, " pce neighbor as %d%s", + ntohl (neighbor->value), VTY_NEWLINE); + } + } + } + + if (pce->pce_scope.header.type != 0) + vty_out (vty, " pce scope 0x%x%s", + ntohl (OspfRI.pce_info.pce_scope.value), VTY_NEWLINE); + } + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty command functions. + *------------------------------------------------------------------------*/ + +DEFUN (router_info, + router_info_area_cmd, + "router-info area A.B.C.D", + OSPF_RI_STR + "Enable the Router Information functionality with Area flooding scope\n" + "OSPF area ID in IP format") +{ + + u_int8_t scope; + + if (OspfRI.status == enabled) + return CMD_SUCCESS; + + /* Check and get Area value if present */ + if (argc == 1) + { + if (!inet_aton (argv[0], &OspfRI.area_id)) + { + vty_out (vty, "Please specify Router Info Area by A.B.C.D%s", + VTY_NEWLINE); + return CMD_WARNING; + } + scope = OSPF_OPAQUE_AREA_LSA; + } + else + { + OspfRI.area_id.s_addr = 0; + scope = OSPF_OPAQUE_AS_LSA; + } + + /* First start to register Router Information callbacks */ + if ((ospf_router_info_register (scope)) != 0) + { + zlog_warn ("Enable to register Router Information callbacks. Abort!"); + return CMD_WARNING; + } + + OspfRI.status = enabled; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS"); + + /* + * Following code is intended to handle two cases; + * + * 1) Router Information was disabled at startup time, but now become enabled. + * 2) Router Information was once enabled then disabled, and now enabled again. + */ + + initialize_params (&OspfRI); + + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + { + zlog_debug ("RI-> Initial origination following configuration"); + ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA); + } + return CMD_SUCCESS; + +} + +ALIAS (router_info, + router_info_as_cmd, + "router-info as", + OSPF_RI_STR + "Enable the Router Information functionality with AS flooding scope\n") + +DEFUN (no_router_info, + no_router_info_cmd, + "no router-info", + NO_STR + "Disable the Router Information functionality\n") +{ + + if (OspfRI.status == disabled) + return CMD_SUCCESS; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("RI-> Router Information: ON -> OFF"); + + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule (FLUSH_THIS_LSA); + + /* Unregister the callbacks */ + ospf_router_info_unregister (); + + OspfRI.status = disabled; + + return CMD_SUCCESS; +} + +DEFUN (pce_address, + pce_address_cmd, + "pce address A.B.C.D", + PCE_STR + "Stable IP address of the PCE\n" + "PCE address in IPv4 address format\n") +{ + struct in_addr value; + struct ospf_pce_info *pi = &OspfRI.pce_info; + + if (!inet_aton (argv[0], &value)) + { + vty_out (vty, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohs (pi->pce_address.header.type) == 0 + || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr)) + { + + set_pce_address (value, pi); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_address, + no_pce_address_cmd, + "no pce address", + NO_STR + PCE_STR + "Disable PCE address\n") +{ + + unset_param (&OspfRI.pce_info.pce_address.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_path_scope, + pce_path_scope_cmd, + "pce scope BITPATTERN", + PCE_STR + "Path scope visibilities of the PCE for path computation\n" + "32-bit Hexadecimal value\n") +{ + uint32_t scope; + struct ospf_pce_info *pi = &OspfRI.pce_info; + + if (sscanf (argv[0], "0x%x", &scope) != 1) + { + vty_out (vty, "pce_path_scope: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value) + { + set_pce_path_scope (scope, pi); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_path_scope, + no_pce_path_scope_cmd, + "no pce scope", + NO_STR + PCE_STR + "Disable PCE path scope\n") +{ + + unset_param (&OspfRI.pce_info.pce_address.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_domain, + pce_domain_cmd, + "pce domain as <0-65535>", + PCE_STR + "Configure PCE domain AS number\n" + "AS number where the PCE as visibilities for path computation\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "pce_domain: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (ntohl (domain->header.type) == 0 && as == domain->value) + goto out; + } + + /* Create new domain if not found */ + set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + +out:return CMD_SUCCESS; +} + +DEFUN (no_pce_domain, + no_pce_domain_cmd, + "no pce domain as <0-65535>", + NO_STR + PCE_STR + "Disable PCE domain AS number\n" + "AS number where the PCE as visibilities for path computation\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "no_pce_domain: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Unset corresponding PCE domain */ + unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_neigbhor, + pce_neighbor_cmd, + "pce neighbor as <0-65535>", + PCE_STR + "Configure PCE neighbor domain AS number\n" + "AS number of PCE neighbors\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_neighbor *neighbor; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "pce_neighbor: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (ntohl (neighbor->header.type) == 0 && as == neighbor->value) + goto out; + } + + /* Create new domain if not found */ + set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + +out:return CMD_SUCCESS; +} + +DEFUN (no_pce_neighbor, + no_pce_neighbor_cmd, + "no pce neighbor as <0-65535>", + NO_STR + PCE_STR + "Disable PCE neighbor AS number\n" + "AS number of PCE neighbor\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Unset corresponding PCE domain */ + unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_cap_flag, + pce_cap_flag_cmd, + "pce flag BITPATTERN", + PCE_STR + "Capabilities of the PCE for path computation\n" + "32-bit Hexadecimal value\n") +{ + + uint32_t cap; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "0x%x", &cap) != 1) + { + vty_out (vty, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohl (pce->pce_cap_flag.header.type) == 0 + || cap != pce->pce_cap_flag.value) + { + set_pce_cap_flag (cap, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_cap_flag, + no_pce_cap_flag_cmd, + "no pce flag", + NO_STR + PCE_STR + "Disable PCE capabilities\n") +{ + + unset_param (&OspfRI.pce_info.pce_cap_flag.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_router_info, + show_ip_ospf_router_info_cmd, + "show ip ospf router-info", + SHOW_STR + IP_STR + OSPF_STR + "Router Information\n") +{ + + if (OspfRI.status == enabled) + { + vty_out (vty, "--- Router Information parameters ---%s", VTY_NEWLINE); + show_vty_router_cap (vty, &OspfRI.router_cap.header); + } + else + { + if (vty != NULL) + vty_out (vty, " Router Information is disabled on this router%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +DEFUN (show_ip_opsf_router_info_pce, + show_ip_ospf_router_info_pce_cmd, + "show ip ospf router-info pce", + SHOW_STR + IP_STR + OSPF_STR + "Router Information\n" + "PCE information\n") +{ + + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + if (OspfRI.status == enabled) + { + vty_out (vty, "--- PCE parameters ---%s", VTY_NEWLINE); + + if (pce->pce_address.header.type != 0) + show_vty_pce_subtlv_address (vty, &pce->pce_address.header); + + if (pce->pce_scope.header.type != 0) + show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header); + + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (domain->header.type != 0) + show_vty_pce_subtlv_domain (vty, &domain->header); + } + + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (neighbor->header.type != 0) + show_vty_pce_subtlv_neighbor (vty, &neighbor->header); + } + + if (pce->pce_cap_flag.header.type != 0) + show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header); + + } + else + { + vty_out (vty, " Router Information is disabled on this router%s", + VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + +/* Install new CLI commands */ +static void +ospf_router_info_register_vty (void) +{ + install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd); + install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_router_info_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_router_info_pce_cmd); + + install_element (OSPF_NODE, &router_info_area_cmd); + install_element (OSPF_NODE, &router_info_as_cmd); + install_element (OSPF_NODE, &no_router_info_cmd); + install_element (OSPF_NODE, &pce_address_cmd); + install_element (OSPF_NODE, &pce_path_scope_cmd); + install_element (OSPF_NODE, &pce_domain_cmd); + install_element (OSPF_NODE, &no_pce_domain_cmd); + install_element (OSPF_NODE, &pce_neighbor_cmd); + install_element (OSPF_NODE, &no_pce_neighbor_cmd); + install_element (OSPF_NODE, &pce_cap_flag_cmd); + + return; +} diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h new file mode 100644 index 0000000000..3f898ac598 --- /dev/null +++ b/ospfd/ospf_ri.h @@ -0,0 +1,191 @@ +/* + * This is an implementation of RFC4970 Router Information + * with support of RFC5088 PCE Capabilites announcement + * + * Module name: Router Information + * Version: 0.99.22 + * Created: 2012-02-01 by Olivier Dugeon + * 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 + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_OSPF_ROUTER_INFO_H +#define _ZEBRA_OSPF_ROUTER_INFO_H + +/* + * Opaque LSA's link state ID for Router Information is + * structured as follows. + * + * 24 16 8 0 + * +--------+--------+--------+--------+ + * | 1 | MBZ |........|........| + * +--------+--------+--------+--------+ + * |<-Type->|<Resv'd>|<-- Instance --->| + * + * + * Type: IANA has assigned '4' for Router Information. + * MBZ: Reserved, must be set to zero. + * Instance: User may select an arbitrary 16-bit value. + * + */ + +/* + * 24 16 8 0 + * +--------+--------+--------+--------+ --- + * | LS age |Options | 9,10,11| A + * +--------+--------+--------+--------+ | + * | 4 | 0 | Instance | | + * +--------+--------+--------+--------+ | + * | Advertising router | | Standard (Opaque) LSA header; + * +--------+--------+--------+--------+ | Type 9,10 or 11 are used. + * | LS sequence number | | + * +--------+--------+--------+--------+ | + * | LS checksum | Length | V + * +--------+--------+--------+--------+ --- + * | Type | Length | A + * +--------+--------+--------+--------+ | TLV part for Router Information; Values might be + * | Values ... | V structured as a set of sub-TLVs. + * +--------+--------+--------+--------+ --- + */ + +/* + * Following section defines TLV (tag, length, value) structures, + * used for Router Information. + */ +struct ri_tlv_header +{ + u_int16_t type; /* RI_TLV_XXX (see below) */ + u_int16_t length; /* Value portion only, in byte */ +}; + +#define RI_TLV_HDR_SIZE (sizeof (struct ri_tlv_header)) +#define RI_TLV_BODY_SIZE(tlvh) (ROUNDUP (ntohs ((tlvh)->length), sizeof (u_int32_t))) +#define RI_TLV_SIZE(tlvh) (RI_TLV_HDR_SIZE + RI_TLV_BODY_SIZE(tlvh)) +#define RI_TLV_HDR_TOP(lsah) (struct ri_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE) +#define RI_TLV_HDR_NEXT(tlvh) (struct ri_tlv_header *)((char *)(tlvh) + RI_TLV_SIZE(tlvh)) + +/* + * Following section defines TLV body parts. + */ + +/* Up to now, 8 code point have been assigned to Router Information */ +/* Only type 1 Router Capabilities and 6 PCE are supported with this code */ +#define RI_IANA_MAX_TYPE 8 + +/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */ +#define RI_TLV_CAPABILITIES 1 + +struct ri_tlv_router_cap +{ + struct ri_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; +}; + +#define RI_GRACE_RESTART 0x01 +#define RI_GRACE_HELPER 0x02 +#define RI_STUB_SUPPORT 0x04 +#define RI_TE_SUPPORT 0x08 +#define RI_P2P_OVER_LAN 0x10 +#define RI_TE_EXPERIMENTAL 0x20 + +#define RI_TLV_LENGTH 4 + +/* RFC5088: PCE Capabilities TLV */ /* Optional */ +/* RI PCE TLV */ +#define RI_TLV_PCE 6 + +struct ri_tlv_pce +{ + struct ri_tlv_header header; +/* A set of PCE-sub-TLVs will follow. */ +}; + +/* PCE Address Sub-TLV */ /* Mandatory */ +#define RI_PCE_SUBTLV_ADDRESS 1 +struct ri_pce_subtlv_address +{ + struct ri_tlv_header header; /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ +#define PCE_ADDRESS_LENGTH_IPV4 8 +#define PCE_ADDRESS_LENGTH_IPV6 20 + struct + { + u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ +#define PCE_ADDRESS_TYPE_IPV4 1 +#define PCE_ADDRESS_TYPE_IPV6 2 + u_int16_t reserved; + struct in_addr value; /* PCE address */ + } address; +}; + +/* PCE Path-Scope Sub-TLV */ /* Mandatory */ +#define RI_PCE_SUBTLV_PATH_SCOPE 2 +struct ri_pce_subtlv_path_scope +{ + struct ri_tlv_header header; /* Type = 2; Length = 4 bytes. */ + u_int32_t value; /* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY bits see RFC5088 page 9 */ +}; + +/* PCE Domain Sub-TLV */ /* Optional */ +#define RI_PCE_SUBTLV_DOMAIN 3 + +#define PCE_DOMAIN_TYPE_AREA 1 +#define PCE_DOMAIN_TYPE_AS 2 + +struct ri_pce_subtlv_domain +{ + struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; +}; + +/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */ +#define RI_PCE_SUBTLV_NEIGHBOR 4 +struct ri_pce_subtlv_neighbor +{ + struct ri_tlv_header header; /* Type = 4; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; +}; + +/* PCE Capabilities Flags Sub-TLV */ /* Optional */ +#define RI_PCE_SUBTLV_CAP_FLAG 5 + +#define PCE_CAP_GMPLS_LINK 0x0001 +#define PCE_CAP_BIDIRECTIONAL 0x0002 +#define PCE_CAP_DIVERSE_PATH 0x0004 +#define PCE_CAP_LOAD_BALANCE 0x0008 +#define PCE_CAP_SYNCHRONIZED 0x0010 +#define PCE_CAP_OBJECTIVES 0x0020 +#define PCE_CAP_ADDITIVE 0x0040 +#define PCE_CAP_PRIORIZATION 0x0080 +#define PCE_CAP_MULTIPLE_REQ 0x0100 + +struct ri_pce_subtlv_cap_flag +{ + struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */ + u_int32_t value; +}; + +/* Prototypes. */ +extern int ospf_router_info_init (void); +extern void ospf_router_info_term (void); + +#endif /* _ZEBRA_OSPF_ROUTER_INFO_H */ diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index d0b121db38..6b6d9f1fab 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -39,7 +39,7 @@ struct ospf_path { struct in_addr nexthop; struct in_addr adv_router; - unsigned int ifindex; + ifindex_t ifindex; unsigned char unnumbered; }; diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index bedcb559bf..676756d6d9 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -1413,7 +1413,7 @@ static struct list *ospf_snmp_iflist; struct ospf_snmp_if { struct in_addr addr; - unsigned int ifindex; + ifindex_t ifindex; struct interface *ifp; }; @@ -1455,7 +1455,7 @@ ospf_snmp_if_update (struct interface *ifp) struct prefix *p; struct ospf_snmp_if *osif; struct in_addr *addr; - unsigned int ifindex; + ifindex_t ifindex; ospf_snmp_if_delete (ifp); @@ -1530,7 +1530,7 @@ ospf_snmp_is_if_have_addr (struct interface *ifp) } static struct ospf_interface * -ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex) +ospf_snmp_if_lookup (struct in_addr *ifaddr, ifindex_t *ifindex) { struct listnode *node; struct ospf_snmp_if *osif; @@ -1554,8 +1554,8 @@ ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex) } static struct ospf_interface * -ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex, - int ifaddr_next, int ifindex_next) +ospf_snmp_if_lookup_next (struct in_addr *ifaddr, ifindex_t *ifindex, + int ifaddr_next, ifindex_t ifindex_next) { struct ospf_snmp_if *osif; struct listnode *nn; @@ -1638,11 +1638,11 @@ ospf_snmp_iftype (struct interface *ifp) static struct ospf_interface * ospfIfLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, unsigned int *ifindex, int exact) + struct in_addr *ifaddr, ifindex_t *ifindex, int exact) { unsigned int len; int ifaddr_next = 0; - int ifindex_next = 0; + ifindex_t ifindex_next = 0; struct ospf_interface *oi; oid *offset; @@ -1694,7 +1694,7 @@ static u_char * ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ifaddr; struct ospf_interface *oi; struct ospf *ospf; @@ -1802,11 +1802,11 @@ ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact, static struct ospf_interface * ospfIfMetricLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, unsigned int *ifindex, int exact) + struct in_addr *ifaddr, ifindex_t *ifindex, int exact) { unsigned int len; int ifaddr_next = 0; - int ifindex_next = 0; + ifindex_t ifindex_next = 0; struct ospf_interface *oi; oid *offset; int metric; @@ -1866,7 +1866,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { /* Currently we support metric 1 only. */ - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ifaddr; struct ospf_interface *oi; struct ospf *ospf; @@ -2133,7 +2133,7 @@ ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact, static struct ospf_neighbor * ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, - unsigned int *ifindex) + ifindex_t *ifindex) { struct listnode *node, *nnode; struct ospf_interface *oi; @@ -2161,7 +2161,7 @@ ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, } static struct ospf_neighbor * -ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, +ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, ifindex_t *ifindex, int first) { struct listnode *nn; @@ -2208,7 +2208,7 @@ ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, static struct ospf_neighbor * ospfNbrLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *nbr_addr, unsigned int *ifindex, int exact) + struct in_addr *nbr_addr, ifindex_t *ifindex, int exact) { unsigned int len; int first; @@ -2303,7 +2303,7 @@ ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct in_addr nbr_addr; - unsigned int ifindex; + ifindex_t ifindex; struct ospf_neighbor *nbr; struct ospf_interface *oi; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 155a773b33..b55105ac8f 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -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 @@ -21,15 +24,11 @@ * 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> - -#ifdef HAVE_OSPF_TE -#ifndef HAVE_OPAQUE_LSA -#error "Wrong configure option" -#endif /* HAVE_OPAQUE_LSA */ +#include <math.h> #include "linklist.h" #include "prefix.h" @@ -44,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" @@ -61,65 +61,19 @@ #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 }; /*------------------------------------------------------------------------* @@ -128,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); @@ -153,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; @@ -177,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; } @@ -197,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; @@ -279,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; @@ -290,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); @@ -302,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; } @@ -316,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; } @@ -324,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 */ @@ -336,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) @@ -365,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); @@ -375,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) { @@ -401,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 @@ -411,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; @@ -448,39 +504,59 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) } 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; } @@ -488,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 @@ -510,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; } @@ -532,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: @@ -555,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); @@ -562,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_linkparams (new); + /* Initialize Link Parameters from Interface */ + 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; @@ -603,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 */ @@ -613,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) { @@ -625,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 @@ -637,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: @@ -653,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; } @@ -711,106 +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_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) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -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_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_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) + if ((tlvh != NULL) && (ntohs (tlvh->type) != 0)) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); @@ -824,15 +1160,27 @@ 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; } @@ -861,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; @@ -874,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); @@ -941,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++; @@ -954,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); } @@ -964,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; @@ -973,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; } @@ -1010,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) @@ -1034,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; } @@ -1053,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)) @@ -1075,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: @@ -1113,6 +1657,7 @@ ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, return; } + /*------------------------------------------------------------------------* * Followings are vty session control functions. *------------------------------------------------------------------------*/ @@ -1123,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)); @@ -1136,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)); @@ -1163,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); @@ -1185,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; @@ -1201,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])); } @@ -1209,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; @@ -1224,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])); } @@ -1238,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); } @@ -1252,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); @@ -1269,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); @@ -1283,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); @@ -1306,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); } @@ -1317,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); } @@ -1363,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; @@ -1416,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); + 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); - 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); - - 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; } @@ -1466,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; @@ -1487,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; @@ -1530,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") { @@ -1578,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; @@ -1590,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); @@ -1844,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 { @@ -1877,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") @@ -1909,24 +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 (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, &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 (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; } - -#endif /* HAVE_OSPF_TE */ diff --git a/ospfd/ospf_te.h b/ospfd/ospf_te.h index 863d8ba8f2..8bb77c40c5 100644 --- a/ospfd/ospf_te.h +++ b/ospfd/ospf_te.h @@ -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 @@ -21,6 +24,10 @@ * 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 @@ -62,6 +70,31 @@ * +--------+--------+--------+--------+ --- */ +/* 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 */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 16fab68c99..264249b4c0 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -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; @@ -3265,7 +3265,6 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_ar ospf_lsdb_checksum (area->lsdb, OSPF_AS_NSSA_LSA), VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { json_object_int_add(json_area, "lsaOpaqueLinkNumber", ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_LINK_LSA)); @@ -3282,7 +3281,6 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_ar ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_AREA_LSA), ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_AREA_LSA), VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ if (use_json) json_object_object_add(json_areas, inet_ntoa (area->area_id), json_area); @@ -3366,7 +3364,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) "enabled" : "disabled", VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) @@ -3380,7 +3377,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE) ? "enabled" : "disabled", VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ /* Show stub-router configuration */ if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED @@ -3534,7 +3530,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) ospf_lsdb_checksum (ospf->lsdb, OSPF_AS_EXTERNAL_LSA), VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { json_object_int_add(json, "lsaAsopaqueCounter", @@ -3548,7 +3543,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) ospf_lsdb_count (ospf->lsdb, OSPF_OPAQUE_AS_LSA), ospf_lsdb_checksum (ospf->lsdb, OSPF_OPAQUE_AS_LSA), VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ /* Show number of areas attached. */ if (use_json) @@ -5095,11 +5089,9 @@ show_lsa_summary (struct vty *vty, struct ospf_lsa *lsa, int self) break; case OSPF_NETWORK_LSA: case OSPF_ASBR_SUMMARY_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -5119,12 +5111,10 @@ static const char *show_database_desc[] = "AS External Link States", "Group Membership LSA", "NSSA-external Link States", -#ifdef HAVE_OPAQUE_LSA "Type-8 LSA", "Link-Local Opaque-LSA", "Area-Local Opaque-LSA", "AS-external Opaque-LSA", -#endif /* HAVE_OPAQUE_LSA */ }; static const char *show_database_header[] = @@ -5137,12 +5127,10 @@ static const char *show_database_header[] = "Link ID ADV Router Age Seq# CkSum Route", " --- header for Group Member ----", "Link ID ADV Router Age Seq# CkSum Route", -#ifdef HAVE_OPAQUE_LSA " --- type-8 ---", "Opaque-Type/Id ADV Router Age Seq# CkSum", "Opaque-Type/Id ADV Router Age Seq# CkSum", "Opaque-Type/Id ADV Router Age Seq# CkSum", -#endif /* HAVE_OPAQUE_LSA */ }; static void @@ -5414,7 +5402,6 @@ show_func_dummy (struct vty *vty, struct ospf_lsa *lsa) return 0; } -#ifdef HAVE_OPAQUE_LSA static int show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) { @@ -5427,7 +5414,6 @@ show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) } return 0; } -#endif /* HAVE_OPAQUE_LSA */ int (*show_function[])(struct vty *, struct ospf_lsa *) = { @@ -5439,12 +5425,10 @@ int (*show_function[])(struct vty *, struct ospf_lsa *) = show_as_external_lsa_detail, show_func_dummy, show_as_nssa_lsa_detail, /* almost same as external */ -#ifdef HAVE_OPAQUE_LSA NULL, /* type-8 */ show_opaque_lsa_detail, show_opaque_lsa_detail, show_opaque_lsa_detail, -#endif /* HAVE_OPAQUE_LSA */ }; static void @@ -5503,9 +5487,7 @@ show_lsa_detail (struct vty *vty, struct ospf *ospf, int type, switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ vty_out (vty, " %s %s%s", show_database_desc[type], VTY_NEWLINE, VTY_NEWLINE); @@ -5552,9 +5534,7 @@ show_lsa_detail_adv_router (struct vty *vty, struct ospf *ospf, int type, switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ vty_out (vty, " %s %s%s", show_database_desc[type], VTY_NEWLINE, VTY_NEWLINE); @@ -5590,9 +5570,7 @@ show_ip_ospf_database_summary (struct vty *vty, struct ospf *ospf, int self) switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ continue; default: break; @@ -5619,9 +5597,7 @@ show_ip_ospf_database_summary (struct vty *vty, struct ospf *ospf, int self) switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ break; default: continue; @@ -5673,17 +5649,10 @@ show_ip_ospf_database_maxage (struct vty *vty, struct ospf *ospf) #define OSPF_LSA_TYPE_NSSA_DESC "NSSA external link state\n" #define OSPF_LSA_TYPE_NSSA_CMD_STR "|nssa-external" -#ifdef HAVE_OPAQUE_LSA #define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "Link local Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "Link area Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_AS_DESC "Link AS Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_CMD_STR "|opaque-link|opaque-area|opaque-as" -#else /* HAVE_OPAQUE_LSA */ -#define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_AS_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_CMD_STR "" -#endif /* HAVE_OPAQUE_LSA */ #define OSPF_LSA_TYPES_CMD_STR \ "asbr-summary|external|network|router|summary" \ @@ -5745,14 +5714,12 @@ show_ip_ospf_database_common (struct vty *vty, struct ospf *ospf, show_ip_ospf_database_maxage (vty, ospf); return CMD_SUCCESS; } -#ifdef HAVE_OPAQUE_LSA else if (strncmp (argv[arg_base + 0], "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; else if (strncmp (argv[arg_base + 0], "opaque-ar", 9) == 0) type = OSPF_OPAQUE_AREA_LSA; else if (strncmp (argv[arg_base + 0], "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; -#endif /* HAVE_OPAQUE_LSA */ else return CMD_WARNING; @@ -5947,14 +5914,12 @@ show_ip_ospf_database_type_adv_router_common (struct vty *vty, struct ospf *ospf type = OSPF_ASBR_SUMMARY_LSA; else if (strncmp (argv[arg_base + 0], "e", 1) == 0) type = OSPF_AS_EXTERNAL_LSA; -#ifdef HAVE_OPAQUE_LSA else if (strncmp (argv[arg_base + 0], "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; else if (strncmp (argv[arg_base + 0], "opaque-ar", 9) == 0) type = OSPF_OPAQUE_AREA_LSA; else if (strncmp (argv[arg_base + 0], "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; -#endif /* HAVE_OPAQUE_LSA */ else return CMD_WARNING; @@ -9489,9 +9454,7 @@ config_write_interface (struct vty *vty) } } while (rn); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_config_write_if (vty, ifp); -#endif /* HAVE_OPAQUE_LSA */ } return write; @@ -9987,9 +9950,7 @@ ospf_config_write (struct vty *vty) /* Distance configuration. */ config_write_ospf_distance (vty, ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_config_write_router (vty, ospf); -#endif /* HAVE_OPAQUE_LSA */ } return write; diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h index 28bb419af8..429ac318f7 100644 --- a/ospfd/ospf_vty.h +++ b/ospfd/ospf_vty.h @@ -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 */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index f945a4acb7..c0b94a3360 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -35,6 +35,7 @@ #include "plist.h" #include "log.h" #include "lib/bfd.h" +#include "nexthop.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -52,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; @@ -330,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) { @@ -393,18 +413,18 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else @@ -414,18 +434,18 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else @@ -514,18 +534,18 @@ ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or) if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, path->ifindex); } @@ -1579,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; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 6d6bf12873..7156c1edac 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -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 * @@ -351,9 +351,7 @@ ospf_get () if (ospf->router_id_static.s_addr == 0) ospf_router_id_update (ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_init (ospf); -#endif /* HAVE_OPAQUE_LSA */ } return ospf; @@ -373,9 +371,7 @@ ospf_get_instance (u_short instance) if (ospf->router_id_static.s_addr == 0) ospf_router_id_update (ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_init (ospf); -#endif /* HAVE_OPAQUE_LSA */ } return ospf; @@ -513,9 +509,7 @@ ospf_finish_final (struct ospf *ospf) int i; u_short instance = 0; -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_term (ospf); -#endif /* HAVE_OPAQUE_LSA */ /* be nice if this worked, but it doesn't */ /*ospf_flush_self_originated_lsas_now (ospf);*/ @@ -611,17 +605,13 @@ ospf_finish_final (struct ospf *ospf) OSPF_TIMER_OFF (ospf->t_lsa_refresher); OSPF_TIMER_OFF (ospf->t_read); OSPF_TIMER_OFF (ospf->t_write); -#ifdef HAVE_OPAQUE_LSA OSPF_TIMER_OFF (ospf->t_opaque_lsa_self); -#endif close (ospf->fd); stream_free(ospf->ibuf); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_discard_from_db (ospf, ospf->lsdb, lsa); -#endif /* HAVE_OPAQUE_LSA */ LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_discard_from_db (ospf, ospf->lsdb, lsa); @@ -733,9 +723,7 @@ ospf_area_new (struct ospf *ospf, struct in_addr area_id) /* Self-originated LSAs initialize. */ new->router_lsa_self = NULL; -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type10_lsa_init (new); -#endif /* HAVE_OPAQUE_LSA */ new->oiflist = list_new (); new->ranges = route_table_init (); @@ -764,12 +752,10 @@ ospf_area_free (struct ospf_area *area) LSDB_LOOP (NSSA_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); -#endif /* HAVE_OPAQUE_LSA */ ospf_lsdb_delete_all (area->lsdb); ospf_lsdb_free (area->lsdb); @@ -787,9 +773,7 @@ ospf_area_free (struct ospf_area *area) /* Cancel timer. */ OSPF_TIMER_OFF (area->t_stub_router); -#ifdef HAVE_OPAQUE_LSA OSPF_TIMER_OFF (area->t_opaque_lsa_self); -#endif /* HAVE_OPAQUE_LSA */ if (OSPF_IS_AREA_BACKBONE (area)) area->ospf->backbone = NULL; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 1a925c2c6a..af238c53ae 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -59,13 +59,14 @@ #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 @@ -162,11 +163,9 @@ struct ospf #define OSPF_LOG_ADJACENCY_CHANGES (1 << 3) #define OSPF_LOG_ADJACENCY_DETAIL (1 << 4) -#ifdef HAVE_OPAQUE_LSA /* Opaque-LSA administrative flags. */ u_char opaque; #define OPAQUE_OPERATION_READY_BIT (1 << 0) -#endif /* HAVE_OPAQUE_LSA */ /* RFC3137 stub router. Configured time to stay stub / max-metric */ unsigned int stub_router_startup_time; /* seconds */ @@ -209,9 +208,7 @@ struct ospf int external_origin; /* AS-external-LSA origin flag. */ int ase_calc; /* ASE calculation flag. */ -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ /* Routing tables. */ struct route_table *old_table; /* Old routing table. */ @@ -240,9 +237,7 @@ struct ospf struct thread *t_spf_calc; /* SPF calculation timer. */ struct thread *t_ase_calc; /* ASE calculation timer. */ struct thread *t_external_lsa; /* AS-external-LSA origin timer. */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ -#endif /* HAVE_OPAQUE_LSA */ unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */ struct thread *t_maxage; /* MaxAge LSA remover timer. */ @@ -365,9 +360,7 @@ struct ospf_area /* Self-originated LSAs. */ struct ospf_lsa *router_lsa_self; -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-10 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ /* Area announce list. */ struct @@ -409,9 +402,7 @@ struct ospf_area /* Threads. */ struct thread *t_stub_router; /* Stub-router timer */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-10 Opaque-LSAs origin. */ -#endif /* HAVE_OPAQUE_LSA */ /* Statistics field. */ u_int32_t spf_calculation; /* SPF Calculation Count. */ diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 13cc305274..6cfed0f2c6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2087,10 +2087,10 @@ static void show_multicast_interfaces(struct vty *vty) inet_ntoa(ifaddr), ifp->ifindex, pim_ifp->mroute_vif_index, - vreq.icount, - vreq.ocount, - vreq.ibytes, - vreq.obytes, + (unsigned long) vreq.icount, + (unsigned long) vreq.ocount, + (unsigned long) vreq.ibytes, + (unsigned long) vreq.obytes, VTY_NEWLINE); } } @@ -2462,9 +2462,9 @@ DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D", IP_STR - "pim multicast routing" - "Rendevous Point" - "ip address of RP") + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n") { int result; @@ -2487,9 +2487,9 @@ DEFUN (no_ip_pim_rp, "no ip pim rp {A.B.C.D}", NO_STR IP_STR - "pim multicast routing" - "Rendevous Point" - "ip address of RP") + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n") { qpim_rp.rpf_addr.s_addr = INADDR_NONE; diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 14c8c7262e..a8a1d08805 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -41,19 +41,6 @@ #include "pim_time.h" #include "pim_ssmpingd.h" -#ifndef VIFF_USE_IFINDEX -# ifdef linux -/* make it work compile-time - whether it works runtime depends on the user - * having 2.6.32 or newer */ -# define VIFF_USE_IFINDEX 0x8 -# else -# error no VIFF_USE_IFINDEX on this system, code needs porting -/* NB: without VIFF_USE_IFINDEX, the local IP address is used to identify - * interfaces, which means it's impossible to support multiple interfaces that - * have the same or no IP address (e.g. unnumbered) */ -# endif -#endif - struct interface *pim_regiface = NULL; static void pim_if_igmp_join_del_all(struct interface *ifp); @@ -645,7 +632,7 @@ int pim_if_add_vif(struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; struct in_addr ifaddr; - unsigned char flags; + unsigned char flags = 0; zassert(pim_ifp); @@ -681,8 +668,13 @@ int pim_if_add_vif(struct interface *ifp) return -3; } - flags = (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) ? - VIFF_REGISTER : VIFF_USE_IFINDEX; + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + flags = VIFF_REGISTER; +#ifdef VIFF_USE_IFINDEX + else + flags = VIFF_USE_IFINDEX; +#endif + if (pim_mroute_add_vif(ifp, ifaddr, flags)) { /* pim_mroute_add_vif reported error */ return -5; @@ -780,7 +772,7 @@ void pim_if_del_vif_all() } } -struct interface *pim_if_find_by_vif_index(int vif_index) +struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) { struct listnode *ifnode; struct interface *ifp; @@ -792,6 +784,7 @@ struct interface *pim_if_find_by_vif_index(int vif_index) if (ifp->info) { struct pim_interface *pim_ifp; pim_ifp = ifp->info; + if (vif_index == pim_ifp->mroute_vif_index) return ifp; } @@ -803,7 +796,7 @@ struct interface *pim_if_find_by_vif_index(int vif_index) /* pim_if_add_vif() uses ifindex as vif_index */ -int pim_if_find_vifindex_by_ifindex(int ifindex) +int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) { struct pim_interface *pim_ifp; struct interface *ifp; @@ -962,7 +955,7 @@ static struct igmp_join *igmp_join_find(struct list *join_list, } static int igmp_join_sock(const char *ifname, - int ifindex, + ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 15489f81fa..790afabea1 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -63,7 +63,7 @@ enum pim_interface_type { struct pim_interface { enum pim_interface_type itype; uint32_t options; /* bit vector */ - int mroute_vif_index; + ifindex_t mroute_vif_index; struct in_addr primary_address; /* remember addr to detect change */ int igmp_default_robustness_variable; /* IGMPv3 QRV */ @@ -133,8 +133,8 @@ int pim_if_del_vif(struct interface *ifp); void pim_if_add_vif_all(void); void pim_if_del_vif_all(void); -struct interface *pim_if_find_by_vif_index(int vif_index); -int pim_if_find_vifindex_by_ifindex(int ifindex); +struct interface *pim_if_find_by_vif_index(ifindex_t vif_index); +int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex); int pim_if_lan_delay_enabled(struct interface *ifp); uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 440d648723..3b63b10e0d 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -46,7 +46,7 @@ static void group_timer_off(struct igmp_group *group); -static int igmp_sock_open(struct in_addr ifaddr, int ifindex, uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim_options) { int fd; int join = 0; @@ -971,7 +971,7 @@ static int pim_igmp_read(struct thread *t) socklen_t tolen = sizeof(to); uint8_t buf[PIM_IGMP_BUFSIZE_READ]; int len; - int ifindex = -1; + ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); @@ -1009,7 +1009,7 @@ static int pim_igmp_read(struct thread *t) #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ - if (ifindex != (int) igmp->interface->ifindex) { + if (ifindex != igmp->interface->ifindex) { char from_str[100]; char to_str[100]; struct interface *ifp; @@ -1021,7 +1021,7 @@ static int pim_igmp_read(struct thread *t) ifp = if_lookup_by_index(ifindex); if (ifp) { - zassert(ifindex == (int) ifp->ifindex); + zassert(ifindex == ifp->ifindex); } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 95519ff974..1700276de8 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -39,7 +39,7 @@ struct group_source_req }; #endif -static int pim_igmp_join_source(int fd, int ifindex, +static int pim_igmp_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index ab3742438d..56f49d62f5 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -501,7 +501,16 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned ch memset(&vc, 0, sizeof(vc)); vc.vifc_vifi = pim_ifp->mroute_vif_index; +#ifdef VIFF_USE_IFINDEX vc.vifc_lcl_ifindex = ifp->ifindex; +#else + if (ifaddr.s_addr == INADDR_ANY) { + zlog_warn("%s: unnumbered interfaces are not supported on this platform", + __PRETTY_FUNCTION__); + return -1; + } + memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); +#endif vc.vifc_flags = flags; vc.vifc_threshold = PIM_MROUTE_MIN_TTL; vc.vifc_rate_limit = 0; diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index eedbc116d8..0dfd39cd16 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -278,7 +278,7 @@ static int pim_sock_read(struct thread *t) socklen_t tolen = sizeof(to); uint8_t buf[PIM_PIM_BUFSIZE_READ]; int len; - int ifindex = -1; + ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); @@ -386,7 +386,7 @@ static void pim_sock_read_on(struct interface *ifp) pim_ifp->pim_sock_fd); } -static int pim_sock_open(struct in_addr ifaddr, int ifindex) +static int pim_sock_open(struct in_addr ifaddr, ifindex_t ifindex) { int fd; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index a2e166f796..a024e3ae01 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -79,6 +79,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) return PIM_SOCK_ERR_SOCKET; } +#ifdef SO_BINDTODEVICE if (protocol == IPPROTO_PIM) { int ret; @@ -104,7 +105,10 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) return PIM_SOCK_ERR_BIND; } } - +#else + /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to + * only use 1 socket for all interfaces? */ +#endif /* Needed to obtain destination address from recvmsg() */ { @@ -209,7 +213,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) } int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, int ifindex) + struct in_addr ifaddr, ifindex_t ifindex) { int ret; @@ -257,7 +261,7 @@ int pim_socket_join(int fd, struct in_addr group, return ret; } -int pim_socket_join_source(int fd, int ifindex, +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr, const char *ifname) @@ -281,7 +285,7 @@ int pim_socket_join_source(int fd, int ifindex, int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, - int *ifindex) + ifindex_t *ifindex) { struct msghdr msgh; struct cmsghdr *cmsg; diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 9a9b64a4a3..f0a1600818 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -41,15 +41,15 @@ int pim_socket_raw(int protocol); int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop); int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, int ifindex); -int pim_socket_join_source(int fd, int ifindex, + struct in_addr ifaddr, ifindex_t ifindex); +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr, const char *ifname); int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, - int *ifindex); + ifindex_t *ifindex); int pim_socket_mcastloop_get(int fd); diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index d564bf57bc..fe88eba271 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -250,7 +250,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) struct sockaddr_in to; socklen_t fromlen = sizeof(from); socklen_t tolen = sizeof(to); - int ifindex = -1; + ifindex_t ifindex = -1; uint8_t buf[1000]; int len; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 1931f1ee6c..c1154dc088 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -85,8 +85,8 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr struct static_route *original_s_route = 0; struct pim_interface *pim_iif = iif ? iif->info : 0; struct pim_interface *pim_oif = oif ? oif->info : 0; - unsigned int iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - unsigned int oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; if (!iif_index || !oif_index) { zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", @@ -229,8 +229,8 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr struct static_route *s_route = 0; struct pim_interface *pim_iif = iif ? iif->info : 0; struct pim_interface *pim_oif = oif ? oif->info : 0; - unsigned int iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - unsigned int oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; if (!iif_index || !oif_index) { zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", diff --git a/pimd/pim_static.h b/pimd/pim_static.h index ff89fb150e..07d31d59b7 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -33,7 +33,7 @@ struct static_route { struct in_addr source; struct channel_oil c_oil; - unsigned int iif; + ifindex_t iif; unsigned char oif_ttls[MAXVIFS]; }; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index efab00e227..d357e5cc83 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -533,7 +533,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, { struct stream *s; struct zapi_ipv4 api; - unsigned long ifindex; + ifindex_t ifindex; struct in_addr nexthop; struct prefix_ipv4 p; int min_len = 4; @@ -620,7 +620,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: add %s %s/%d " - "nexthop %s ifindex %ld metric%s %u distance%s %u", + "nexthop %s ifindex %d metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), @@ -638,7 +638,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: delete %s %s/%d " - "nexthop %s ifindex %ld metric%s %u distance%s %u", + "nexthop %s ifindex %d metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), @@ -763,7 +763,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; int num_ifindex; int vif_index; - int first_ifindex; + ifindex_t first_ifindex; num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 1f8cdfa07e..86d7edbd01 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -229,8 +229,8 @@ static int zclient_read_nexthop(struct zclient *zlookup, --length; switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: if (num_ifindex >= tab_size) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); @@ -239,7 +239,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, (num_ifindex + 1), tab_size, addr_str); return num_ifindex; } - if (nexthop_type == ZEBRA_NEXTHOP_IPV4_IFINDEX) { + if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { if (length < 4) { zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d", __func__, zlookup->sock, length); @@ -256,7 +256,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_tab[num_ifindex].route_metric = metric; ++num_ifindex; break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: if (num_ifindex >= tab_size) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 1f184942ca..f2be6d4fa0 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -31,7 +31,7 @@ struct pim_zlookup_nexthop { struct in_addr nexthop_addr; - int ifindex; + ifindex_t ifindex; uint32_t route_metric; uint8_t protocol_distance; }; diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index fe64fbc005..5c4574024b 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -20,6 +20,8 @@ $QuaggaId: $Format:%an, %ai, %h$ $ */ +#include <zebra.h> + #include <stdlib.h> #include <stdio.h> #include <errno.h> @@ -30,6 +32,7 @@ #include <net/if.h> #include <arpa/inet.h> +#include "if.h" #include "pim_igmp_join.h" const char *prog_name = 0; @@ -37,7 +40,7 @@ const char *prog_name = 0; static int iface_solve_index(const char *ifname) { struct if_nameindex *ini; - int ifindex = -1; + ifindex_t ifindex = -1; int i; if (!ifname) @@ -77,7 +80,7 @@ int main(int argc, const char *argv[]) const char *ifname; const char *group; const char *source; - int ifindex; + ifindex_t ifindex; int result; int fd; diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 6748e197da..09b35d00b9 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -74,12 +74,13 @@ static int ipv4_multicast_join (int sock, struct in_addr group, struct in_addr ifa, - unsigned int ifindex) + ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (sock, IP_ADD_MEMBERSHIP, + ifa, group.s_addr, ifindex); @@ -95,12 +96,13 @@ static int ipv4_multicast_leave (int sock, struct in_addr group, struct in_addr ifa, - unsigned int ifindex) + ifindex_t ifindex) { int ret; ret = setsockopt_ipv4_multicast (sock, IP_DROP_MEMBERSHIP, + ifa, group.s_addr, ifindex); @@ -136,9 +138,13 @@ rip_interface_new (void) void rip_interface_multicast_set (int sock, struct connected *connected) { + struct in_addr addr; + assert (connected != NULL); - - if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0) + + addr = CONNECTED_ID(connected)->u.prefix4; + + if (setsockopt_ipv4_multicast_if (sock, addr, connected->ifp->ifindex) < 0) { zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to " "ifindex %d for interface %s", diff --git a/ripd/ripd.c b/ripd/ripd.c index 42f1015453..3a8cd80e7a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1579,7 +1579,7 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, /* Add redistributed route to RIP table. */ void rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, - unsigned int ifindex, struct in_addr *nexthop, + ifindex_t ifindex, struct in_addr *nexthop, unsigned int metric, unsigned char distance) { int ret; @@ -1653,7 +1653,7 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, /* Delete redistributed route from RIP table. */ void rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; struct route_node *rp; @@ -1795,7 +1795,7 @@ setsockopt_pktinfo (int sock) /* Read RIP packet by recvmsg function. */ int rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from, - int *ifindex) + ifindex_t *ifindex) { int ret; struct msghdr msg; @@ -1836,7 +1836,7 @@ rip_read_new (struct thread *t) int sock; char buf[RIP_PACKET_MAXSIZ]; struct sockaddr_in from; - unsigned int ifindex; + ifindex_t ifindex; /* Fetch socket then register myself. */ sock = THREAD_FD (t); diff --git a/ripd/ripd.h b/ripd/ripd.h index fe9e521d88..d01d0b6bbe 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -198,7 +198,7 @@ struct rip_info struct in_addr from; /* Which interface does this route come from. */ - unsigned int ifindex; + ifindex_t ifindex; /* Metric of this route. */ u_int32_t metric; @@ -224,7 +224,7 @@ struct rip_info u_char metric_set; u_int32_t metric_out; u_short tag_out; - unsigned int ifindex_out; + ifindex_t ifindex_out; struct route_node *rp; @@ -400,9 +400,9 @@ extern int rip_request_send (struct sockaddr_in *, struct interface *, u_char, extern int rip_neighbor_lookup (struct sockaddr_in *); extern int rip_redistribute_check (int); -extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, unsigned int, +extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, ifindex_t, struct in_addr *, unsigned int, unsigned char); -extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int); +extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, ifindex_t); extern void rip_redistribute_withdraw (int); extern void rip_zebra_ipv4_add (struct route_node *); extern void rip_zebra_ipv4_delete (struct route_node *); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index ecfe2d5154..d8667cb68c 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -42,7 +42,7 @@ static void ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) { static struct in6_addr **nexthops = NULL; - static unsigned int *ifindexes = NULL; + static ifindex_t *ifindexes = NULL; static unsigned int nexthops_len = 0; struct list *list = (struct list *)rp->info; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index b786c6f938..2858bb6462 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -229,7 +229,7 @@ ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, /* Receive UDP RIPng packet from socket. */ static int ripng_recv_packet (int sock, u_char *buf, int bufsize, - struct sockaddr_in6 *from, unsigned int *ifindex, + struct sockaddr_in6 *from, ifindex_t *ifindex, int *hoplimit) { int ret; @@ -973,7 +973,7 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, /* Add redistributed route to RIPng table. */ void ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, - unsigned int ifindex, struct in6_addr *nexthop) + ifindex_t ifindex, struct in6_addr *nexthop) { struct route_node *rp; struct ripng_info *rinfo = NULL, newinfo; @@ -1043,7 +1043,7 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, /* Delete redistributed route to RIPng table. */ void ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, - unsigned int ifindex) + ifindex_t ifindex) { struct route_node *rp; struct ripng_info *rinfo; @@ -1361,7 +1361,7 @@ ripng_read (struct thread *thread) int sock; struct sockaddr_in6 from; struct ripng_packet *packet; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; struct interface *ifp; int hoplimit = -1; diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 1496de08bf..b87b927f48 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -176,7 +176,7 @@ struct ripng_info struct in6_addr from; /* Which interface does this route come from. */ - unsigned int ifindex; + ifindex_t ifindex; /* Metric of this route. */ u_char metric; @@ -381,9 +381,9 @@ extern void ripng_info_free (struct ripng_info *rinfo); extern void ripng_event (enum ripng_event, int); extern int ripng_request (struct interface *ifp); extern void ripng_redistribute_add (int, int, struct prefix_ipv6 *, - unsigned int, struct in6_addr *); + ifindex_t, struct in6_addr *); extern void ripng_redistribute_delete (int, int, struct prefix_ipv6 *, - unsigned int); + ifindex_t); extern void ripng_redistribute_withdraw (int type); extern void ripng_distribute_update_interface (struct interface *); diff --git a/tests/aspath_test.c b/tests/aspath_test.c index fde12c41c4..9d595807fe 100644 --- a/tests/aspath_test.c +++ b/tests/aspath_test.c @@ -25,6 +25,7 @@ #include "stream.h" #include "privs.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" diff --git a/tests/bgp_capability_test.c b/tests/bgp_capability_test.c index ecabc2f19f..73f46b59a0 100644 --- a/tests/bgp_capability_test.c +++ b/tests/bgp_capability_test.c @@ -26,6 +26,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_open.h" diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c index ba619916d4..928d69752a 100644 --- a/tests/bgp_mp_attr_test.c +++ b/tests/bgp_mp_attr_test.c @@ -26,6 +26,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" diff --git a/tests/bgp_mpath_test.c b/tests/bgp_mpath_test.c index bafbef75fb..66a718cbe2 100644 --- a/tests/bgp_mpath_test.c +++ b/tests/bgp_mpath_test.c @@ -30,6 +30,7 @@ #include "memory.h" #include "zclient.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/tests/ecommunity_test.c b/tests/ecommunity_test.c index 1d4f6a1860..9166af6142 100644 --- a/tests/ecommunity_test.c +++ b/tests/ecommunity_test.c @@ -25,6 +25,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index a7b78bd7b9..4ead722213 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -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"; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 3d3b8e6dce..5cf27facb8 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -37,6 +37,7 @@ #include "linklist.h" #include "command.h" #include "memory.h" +#include "filter.h" #include "vtysh/vtysh.h" #include "log.h" #include "bgpd/bgp_vty.h" @@ -1031,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; @@ -1413,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; } @@ -1745,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, @@ -2842,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); @@ -2871,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); @@ -2964,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); @@ -3014,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); diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index 988c768dce..1886ba3a67 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -195,7 +195,11 @@ vtysh_auth (void) struct vtysh_user *user; struct passwd *passwd; - passwd = getpwuid (geteuid ()); + if ((passwd = getpwuid (geteuid ())) == NULL) + { + fprintf (stderr, "could not lookup user ID %d\n", (int) geteuid()); + exit (1); + } user = user_lookup (passwd->pw_name); if (user && user->nopassword) diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 4492f9e6d4..0218af81b7 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -31,19 +31,19 @@ zebra_SOURCES = \ redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \ irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \ $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ - zebra_ns.c zebra_vrf.c + zebra_ns.c zebra_vrf.c zebra_static.c testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \ kernel_null.c redistribute_null.c ioctl_null.c misc_null.c zebra_rnh_null.c \ - zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c + zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c zebra_static.c noinst_HEADERS = \ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \ interface.h ipforward.h irdp.h router-id.h kernel_socket.h \ rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ - zebra_ns.h zebra_vrf.h ioctl_solaris.h + zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) diff --git a/zebra/connected.c b/zebra/connected.c index 42b5a8ab9c..6e82e6ec78 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -185,26 +185,28 @@ connected_update(struct interface *ifp, struct connected *ifc) void connected_up_ipv4 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv4 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv4 (&p); + apply_mask (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ - if (prefix_ipv4_any (&p)) + if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) return; - rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); - rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); + rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", @@ -303,7 +305,7 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv4 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; @@ -311,19 +313,19 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv4 (&p); + apply_mask (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ - if (prefix_ipv4_any (&p)) + if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, - SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, - SAFI_MULTICAST); + rib_delete (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", @@ -358,28 +360,28 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } -#ifdef HAVE_IPV6 void connected_up_ipv6 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv6 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv6 (&p); + apply_mask (&p); #ifndef LINUX - /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ - if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ + if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; #endif - rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", @@ -456,20 +458,20 @@ connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, void connected_down_ipv6 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv6 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); - apply_mask_ipv6 (&p); + apply_mask (&p); - if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; - rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, - ifp->vrf_id, 0, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", @@ -502,7 +504,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } -#endif /* HAVE_IPV6 */ int connected_is_unnumbered (struct interface *ifp) diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 88fea3427f..0a9807b8b9 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -427,7 +427,7 @@ interface_info_ioctl () struct listnode *node, *nnode; struct interface *ifp; - for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) + for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) { if_get_index (ifp); #ifdef SIOCGIFHWADDR diff --git a/zebra/interface.c b/zebra/interface.c index c3ce83dd4a..2b1e6f4ac6 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -39,6 +39,7 @@ #include "zebra_vrf.h" #include "zebra/interface.h" #include "zebra/rib.h" +#include "zebra/rt.h" #include "zebra/zserv.h" #include "zebra/redistribute.h" #include "zebra/debug.h" @@ -280,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 @@ -744,8 +745,7 @@ if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, inet_pton (AF_INET, buf, &ipv4_ll); ipv6_ll_address_to_mac(address, (u_char *)mac); - netlink_neigh_update (add ? RTM_NEWNEIGH : RTM_DELNEIGH, - ifp->ifindex, ipv4_ll.s_addr, mac, 6); + kernel_neigh_update (add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); } static void @@ -991,9 +991,6 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) static void if_dump_vty (struct vty *vty, struct interface *ifp) { -#ifdef HAVE_STRUCT_SOCKADDR_DL - struct sockaddr_dl *sdl; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ struct connected *connected; struct nbr_connected *nbr_connected; struct listnode *node; @@ -1055,19 +1052,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) if_flag_dump (ifp->flags), VTY_NEWLINE); /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - sdl = &ifp->sdl; - if (sdl != NULL && sdl->sdl_alen != 0) - { - int i; - u_char *ptr; - - vty_out (vty, " HWaddr: "); - for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++) - vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr); - vty_out (vty, "%s", VTY_NEWLINE); - } -#else + vty_out (vty, " Type: %s%s", if_link_type_str (ifp->ll_type), VTY_NEWLINE); if (ifp->hw_addr_len != 0) { int i; @@ -1077,7 +1062,6 @@ if_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]); vty_out (vty, "%s", VTY_NEWLINE); } -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Bandwidth in Mbps */ if (ifp->bandwidth != 0) @@ -1090,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); } @@ -1102,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 */ @@ -1201,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 @@ -1706,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, @@ -2071,6 +2788,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) { struct listnode *node; @@ -2150,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; @@ -2182,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); @@ -2225,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); - } diff --git a/zebra/interface.h b/zebra/interface.h index 2857198373..6039e2d379 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -211,6 +211,16 @@ struct zebra_if struct irdp_interface irdp; #endif +#ifdef HAVE_STRUCT_SOCKADDR_DL + union { + /* note that sdl_storage is never accessed, it only exists to make space. + * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits + * best with C aliasing rules. */ + struct sockaddr_dl sdl; + struct sockaddr_storage sdl_storage; + }; +#endif + #ifdef SUNOS_5 /* the real IFF_UP state of the primary interface. * need this to differentiate between all interfaces being diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 5efc1e2a55..b90c6f57f9 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -60,7 +60,7 @@ int kernel_address_delete_ipv4 (struct interface *a, struct connected *b) return 0; } -int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) +int kernel_neigh_update (int a, int b, uint32_t c, char *d, int e) { return 0; } diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index b47ee787e8..733e627265 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -20,6 +20,7 @@ */ #include <zebra.h> +#include <net/if_types.h> #include "if.h" #include "prefix.h" @@ -240,7 +241,9 @@ static const struct message rtm_flag_str[] = #ifdef RTF_CLONING {RTF_CLONING, "CLONING"}, #endif /* RTF_CLONING */ +#ifdef RTF_XRESOLVE {RTF_XRESOLVE, "XRESOLVE"}, +#endif /* RTF_XRESOLVE */ #ifdef RTF_LLINFO {RTF_LLINFO, "LLINFO"}, #endif /* RTF_LLINFO */ @@ -377,6 +380,29 @@ bsd_linkdetect_translate (struct if_msghdr *ifm) } #endif /* HAVE_BSD_IFI_LINK_STATE */ +static enum zebra_link_type +sdl_to_zebra_link_type (unsigned int sdlt) +{ + switch (sdlt) + { + case IFT_ETHER: return ZEBRA_LLT_ETHER; + case IFT_X25: return ZEBRA_LLT_X25; + case IFT_FDDI: return ZEBRA_LLT_FDDI; + case IFT_PPP: return ZEBRA_LLT_PPP; + case IFT_LOOP: return ZEBRA_LLT_LOOPBACK; + case IFT_SLIP: return ZEBRA_LLT_SLIP; + case IFT_ARCNET: return ZEBRA_LLT_ARCNET; + case IFT_ATM: return ZEBRA_LLT_ATM; + case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK; + case IFT_HIPPI: return ZEBRA_LLT_HIPPI; +#ifdef IFT_IEEE1394 + case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394; +#endif + + default: return ZEBRA_LLT_UNKNOWN; + } +} + /* * Handle struct if_msghdr obtained from reading routing socket or * sysctl (from interface_list). There may or may not be sockaddrs @@ -533,14 +559,23 @@ ifm_read (struct if_msghdr *ifm) * is fine here. * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid */ + ifp->ll_type = ZEBRA_LLT_UNKNOWN; + ifp->hw_addr_len = 0; if (ifnlen) - { + { #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN - memcpy (&ifp->sdl, sdl, sdl->sdl_len); + memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len); #else - memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); + memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl)); #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */ - } + + ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type); + if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) + { + memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen); + ifp->hw_addr_len = sdl->sdl_alen; + } + } if_add_update (ifp); } @@ -882,10 +917,10 @@ rtm_read (struct rt_msghdr *rtm) if (dest.sa.sa_family == AF_INET) { - struct prefix_ipv4 p; + struct prefix p; p.family = AF_INET; - p.prefix = dest.sin.sin_addr; + p.u.prefix4 = dest.sin.sin_addr; if (flags & RTF_HOST) p.prefixlen = IPV4_MAX_PREFIXLEN; else @@ -925,7 +960,7 @@ rtm_read (struct rt_msghdr *rtm) case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); return; break; } @@ -938,18 +973,18 @@ rtm_read (struct rt_msghdr *rtm) case ZEBRA_RIB_FOUND_EXACT: zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); break; case ZEBRA_RIB_FOUND_CONNECTED: case ZEBRA_RIB_FOUND_NOGATE: zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); break; case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); return; break; } @@ -965,19 +1000,19 @@ rtm_read (struct rt_msghdr *rtm) * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, 0, 0); + union g_addr ggate = { .ipv4 = gate.sin.sin_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, + &p, &ggate, NULL, 0, 0, 0, 0, 0); else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0 zebra_flags, - &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &ggate, 0, 0); } -#ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { /* One day we might have a debug section here like one in the @@ -985,11 +1020,11 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) return; - struct prefix_ipv6 p; - unsigned int ifindex = 0; + struct prefix p; + ifindex_t ifindex = 0; p.family = AF_INET6; - p.prefix = dest.sin6.sin6_addr; + p.u.prefix6 = dest.sin6.sin6_addr; if (flags & RTF_HOST) p.prefixlen = IPV6_MAX_PREFIXLEN; else @@ -1007,19 +1042,20 @@ rtm_read (struct rt_msghdr *rtm) * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, SAFI_UNICAST); - + rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, 0, 0); + + union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &ggate, NULL, ifindex, + 0, 0, 0, 0); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &ggate, ifindex, 0); } -#endif /* HAVE_IPV6 */ } /* Interface function for the kernel routing table updates. Support @@ -1097,7 +1133,7 @@ rtm_write (int message, __func__, dest_buf, mask_buf, index); return -1; } - gate = (union sockunion *) & ifp->sdl; + gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl; } if (mask) diff --git a/zebra/main.c b/zebra/main.c index 8a9857a04d..d8892f582a 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -150,7 +150,7 @@ usage (char *progname, int status) "-r, --retain When program terminates, retain added route "\ "by zebra.\n"\ "-u, --user User to run as\n"\ - "-g, --group Group to run as\n", progname); + "-g, --group Group to run as\n", progname); #ifdef HAVE_NETLINK printf ("-s, --nl-bufsize Set netlink receive buffer size\n"); #endif /* HAVE_NETLINK */ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 1867362778..fb9fa0216a 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -144,17 +144,23 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) - if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) - && newrib->type == type - && newrib->instance == instance - && newrib->distance != DISTANCE_INFINITY - && zebra_check_addr (&rn->p)) - { - client->redist_v4_add_cnt++; - zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); - } - -#ifdef HAVE_IPV6 + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, zebra_check_addr=%d", + __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), + newrib->type, newrib->distance, zebra_check_addr (&rn->p)); + + if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) + && newrib->type == type + && newrib->instance == instance + && newrib->distance != DISTANCE_INFINITY + && zebra_check_addr (&rn->p)) + { + client->redist_v4_add_cnt++; + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); + } + } + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) @@ -168,7 +174,6 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v client->redist_v6_add_cnt++; zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, &rn->p, newrib); } -#endif /* HAVE_IPV6 */ } /* Either advertise a route for redistribution to registered clients or */ @@ -380,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); + } } } @@ -413,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 @@ -545,9 +554,9 @@ int zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char *rmap_name) { struct rib *newrib; - struct prefix_ipv4 p4; + struct prefix p; struct nexthop *nhop; - struct in_addr *gate; + union g_addr *gate; route_map_result_t ret = RMAP_MATCH; if (rmap_name) @@ -558,9 +567,9 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char { if (rn->p.family == AF_INET) { - p4.family = AF_INET; - p4.prefixlen = rn->p.prefixlen; - p4.prefix = rn->p.u.prefix4; + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; if (rib->nexthop_num == 1) { @@ -568,14 +577,13 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char if (nhop->type == NEXTHOP_TYPE_IFINDEX) gate = NULL; else - gate = &nhop->gate.ipv4; - - rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, - gate, &nhop->src.ipv4, - nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, - rib->metric, - zebra_import_table_distance[AFI_IP][rib->table], - SAFI_UNICAST); + gate = (union g_addr *)&nhop->gate.ipv4; + + rib_add (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, + rib->table, 0, &p, gate, (union g_addr *)&nhop->src.ipv4, + nhop->ifindex, zebrad.rtm_table_default, + rib->metric, rib->mtu, + zebra_import_table_distance[AFI_IP][rib->table]); } else if (rib->nexthop_num > 1) { @@ -584,6 +592,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char newrib->distance = zebra_import_table_distance[AFI_IP][rib->table]; newrib->flags = rib->flags; newrib->metric = rib->metric; + newrib->mtu = rib->mtu; newrib->table = zebrad.rtm_table_default; newrib->nexthop_num = 0; newrib->uptime = time(NULL); @@ -593,7 +602,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char for (nhop = rib->nexthop; nhop; nhop = nhop->next) rib_copy_nexthops(newrib, nhop); - rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST); + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, newrib); } } } @@ -608,16 +617,17 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char int zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) { - struct prefix_ipv4 p4; + struct prefix p; if (rn->p.family == AF_INET) { - p4.family = AF_INET; - p4.prefixlen = rn->p.prefixlen; - p4.prefix = rn->p.u.prefix4; + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; - rib_delete_ipv4(ZEBRA_ROUTE_TABLE, rib->table, rib->flags, &p4, NULL, - 0, rib->vrf_id, zebrad.rtm_table_default, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, + rib->table, rib->flags, &p, NULL, + 0, zebrad.rtm_table_default); } /* DD: Add IPv6 code */ @@ -791,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); +} diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 5e3cf1bfd3..e3bce7af46 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -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); diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c index c21ee44702..85d3bd2f1b 100644 --- a/zebra/redistribute_null.c +++ b/zebra/redistribute_null.c @@ -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; } diff --git a/zebra/rib.h b/zebra/rib.h index 5e0bce4461..500d96cbe4 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -64,6 +64,10 @@ struct rib /* Metric */ u_int32_t metric; + /* MTU */ + u_int32_t mtu; + u_int32_t nexthop_mtu; + /* Distance. */ u_char distance; @@ -81,6 +85,7 @@ struct rib #define RIB_ENTRY_REMOVED 0x1 /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define RIB_ENTRY_NEXTHOPS_CHANGED 0x2 +#define RIB_ENTRY_CHANGED 0x4 /* Nexthop information. */ u_char nexthop_num; @@ -170,52 +175,6 @@ typedef struct rib_dest_t_ #define RNODE_FOREACH_RIB_SAFE(rn, rib, next) \ RIB_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), rib, next) -/* Static route information. */ -struct static_route -{ - /* For linked list. */ - struct static_route *prev; - struct static_route *next; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Administrative distance. */ - u_char distance; - - /* Tag */ - u_short tag; - - /* Flag for this static route's type. */ - u_char type; -#define STATIC_IFINDEX 1 -#define STATIC_IPV4_GATEWAY 2 -#define STATIC_IPV4_BLACKHOLE 3 -#define STATIC_IPV6_GATEWAY 4 -#define STATIC_IPV6_GATEWAY_IFINDEX 5 - - /* - * Nexthop value. - * - * Under IPv4 addr and ifindex are - * used independentyly. - * STATIC_IPV4_GATEWAY uses addr - * STATIC_IFINDEX uses ifindex - */ - union g_addr addr; - unsigned int ifindex; - - char ifname[INTERFACE_NAMSIZ + 1]; - - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ -}; - - /* The following for loop allows to iterate over the nexthop * structure of routes. * @@ -321,14 +280,14 @@ typedef enum RIB_UPDATE_OTHER } rib_update_event_t; -extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, unsigned int); +extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, ifindex_t); extern struct nexthop *rib_nexthop_blackhole_add (struct rib *); extern struct nexthop *rib_nexthop_ipv4_add (struct rib *, struct in_addr *, struct in_addr *); extern struct nexthop *rib_nexthop_ipv4_ifindex_add (struct rib *, struct in_addr *, struct in_addr *, - unsigned int); + ifindex_t); extern void rib_nexthop_add (struct rib *rib, struct nexthop *nexthop); extern void rib_copy_nexthops (struct rib *rib, struct nexthop *nh); @@ -361,31 +320,40 @@ extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, #define ZEBRA_RIB_FOUND_CONNECTED 2 #define ZEBRA_RIB_NOTFOUND 3 +extern void rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop); extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *); extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, - unsigned int ifindex); + ifindex_t ifindex); extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id); extern int zebra_check_addr (struct prefix *p); +extern void rib_addnode (struct route_node *rn, struct rib *rib, int process); +extern void rib_delnode (struct route_node *rn, struct rib *rib); +extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int update); +extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib); + /* NOTE: - * All rib_add_ipv[46]* functions will not just add prefix into RIB, but + * All rib_add function will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ -extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t, u_char, safi_t); - -extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); - -extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, - vrf_id_t, u_int32_t, safi_t safi); - -extern struct rib *rib_match_ipv4 (struct in_addr, safi_t safi, vrf_id_t, - struct route_node **rn_out); +extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, union g_addr *src, + ifindex_t ifindex, u_int32_t table_id, + u_int32_t, u_int32_t, u_char); + +extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *, + struct rib *); + +extern int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_int32_t table_id); + +extern struct rib *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, + struct route_node **rn_out); extern struct rib *rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out); @@ -400,50 +368,8 @@ extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); extern void rib_queue_add (struct route_node *rn); -extern void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); -extern void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); - -extern int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf); - -extern int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf); - -extern int -rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi); - -extern int -rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi); - -extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); - -extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t); - extern struct route_table *rib_table_ipv6; -extern int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf); - -extern int -rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, - unsigned long); - -extern int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf); - extern int rib_gc_dest (struct route_node *rn); extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); diff --git a/zebra/rt.h b/zebra/rt.h index 331df45c47..4515d56a38 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -33,6 +33,7 @@ extern int kernel_delete_ipv4 (struct prefix *, struct rib *); extern int kernel_add_route (struct prefix_ipv4 *, struct in_addr *, int, int); extern int kernel_address_add_ipv4 (struct interface *, struct connected *); extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); +extern int kernel_neigh_update (int, int, uint32_t, char *, int); #ifdef HAVE_IPV6 extern int kernel_add_ipv6 (struct prefix *, struct rib *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0549900650..fb9aef4aaf 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -20,6 +20,7 @@ */ #include <zebra.h> +#include <net/if_arp.h> /* Hack for GNU libc version 2. */ #ifndef MSG_TRUNC @@ -74,7 +75,7 @@ extern u_int32_t nl_rcvbufsize; /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ static void -set_ifindex(struct interface *ifp, unsigned int ifi_index) +set_ifindex(struct interface *ifp, ifindex_t ifi_index) { struct interface *oifp; struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); @@ -523,6 +524,68 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) } } +static enum zebra_link_type +netlink_to_zebra_link_type (unsigned int hwt) +{ + switch (hwt) + { + case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; + case ARPHRD_X25: return ZEBRA_LLT_X25; + case ARPHRD_PPP: return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; +#ifdef ARPHRD_IP6GRE + case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; +#endif +#ifdef ARPHRD_IEEE802154_PHY + case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; +#endif + + default: return ZEBRA_LLT_UNKNOWN; + } +} + #define parse_rtattr_nested(tb, max, rta) \ netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) @@ -698,7 +761,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Hardware type and address. */ - ifp->hw_type = ifi->ifi_type; + ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); netlink_interface_update_hw_addr (tb, ifp); if_add_update (ifp); @@ -860,12 +923,14 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; + struct prefix p; char anyaddr[16] = { 0 }; int index; int table; int metric; + u_int32_t mtu = 0; void *dest; void *gate; @@ -937,16 +1002,28 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (tb[RTA_PRIORITY]) metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + if (tb[RTA_METRICS]) + { + struct rtattr *mxrta[RTAX_MAX+1]; + + memset (mxrta, 0, sizeof mxrta); + netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + } + if (rtm->rtm_family == AF_INET) { - struct prefix_ipv4 p; p.family = AF_INET; - memcpy (&p.prefix, dest, 4); + memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - vrf_id, table, metric, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, gate, src, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -962,6 +1039,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, rib->distance = 0; rib->flags = flags; rib->metric = metric; + rib->mtu = mtu; rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; @@ -1002,21 +1080,19 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); } } -#ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) { - struct prefix_ipv6 p; p.family = AF_INET6; - memcpy (&p.prefix, dest, 16); + memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, gate, src, index, + table, metric, mtu, 0); } -#endif /* HAVE_IPV6 */ return 0; } @@ -1045,12 +1121,14 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char zebra_flags = 0; - + struct prefix p; + char anyaddr[16] = { 0 }; int index; int table; int metric; + u_int32_t mtu = 0; void *dest; void *gate; @@ -1142,14 +1220,28 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (tb[RTA_PREFSRC]) src = RTA_DATA (tb[RTA_PREFSRC]); - if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + if (h->nlmsg_type == RTM_NEWROUTE) + { + if (tb[RTA_PRIORITY]) + metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + + if (tb[RTA_METRICS]) + { + struct rtattr *mxrta[RTAX_MAX+1]; + + memset (mxrta, 0, sizeof mxrta); + netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + } + } if (rtm->rtm_family == AF_INET) { - struct prefix_ipv4 p; p.family = AF_INET; - memcpy (&p.prefix, dest, 4); + memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) @@ -1163,8 +1255,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, 0, &p, gate, src, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -1180,6 +1273,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, rib->distance = 0; rib->flags = 0; rib->metric = metric; + rib->mtu = mtu; rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; @@ -1221,21 +1315,20 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); } } else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - vrf_id, table, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, + &p, gate, index, table); } -#ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) { - struct prefix_ipv6 p; + struct prefix p; p.family = AF_INET6; - memcpy (&p.prefix, dest, 16); + memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) @@ -1247,13 +1340,13 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, 0, &p, gate, src, index, + table, metric, mtu, 0); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - vrf_id, table, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, gate, index, table); } -#endif /* HAVE_IPV6 */ return 0; } @@ -1973,8 +2066,8 @@ _netlink_route_debug( } } -int -netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) +static int +netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) { struct { struct nlmsghdr n; @@ -2079,6 +2172,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, addattr32(&req.n, sizeof req, RTA_TABLE, rib->table); } + if (rib->mtu || rib->nexthop_mtu) + { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *) buf; + u_int32_t mtu = rib->mtu; + if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu)) + mtu = rib->nexthop_mtu; + rta->rta_type = RTA_METRICS; + rta->rta_len = RTA_LENGTH(0); + rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); + addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta), + RTA_PAYLOAD (rta)); + } + if (discard) { if (cmd == RTM_NEWROUTE) @@ -2392,6 +2499,12 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); } +int +kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +{ + return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr, + lla, llalen); +} extern struct thread_master *master; diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 1d9280a295..80d035e839 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -41,9 +41,6 @@ nl_msg_type_to_str (uint16_t msg_type); extern const char * nl_rtproto_to_str (u_char rtproto); -int -netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); - extern int interface_lookup_netlink (struct zebra_ns *zns); extern int netlink_route_read (struct zebra_ns *zns); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index abeb87a427..24671829f0 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -76,7 +76,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family) struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; char prefix_buf[PREFIX_STRLEN]; @@ -287,7 +287,7 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib, struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; @@ -428,3 +428,10 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) return route; } #endif /* HAVE_IPV6 */ + +int +kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +{ + /* TODO */ + return 0; +} diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 93f0155fdb..8384b327ff 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -70,7 +70,7 @@ static int if_join_all_router (int, struct interface *); static int if_leave_all_router (int, struct interface *); static int -rtadv_increment_received(struct zebra_ns *zns, unsigned int *ifindex) +rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) { int ret = -1; struct interface *iface; @@ -88,7 +88,7 @@ rtadv_increment_received(struct zebra_ns *zns, unsigned int *ifindex) static int rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen, - struct sockaddr_in6 *from, unsigned int *ifindex, + struct sockaddr_in6 *from, ifindex_t *ifindex, int *hoplimit) { int ret; @@ -152,9 +152,6 @@ rtadv_send_packet (int sock, struct interface *ifp) struct cmsghdr *cmsgptr; struct in6_pktinfo *pkt; struct sockaddr_in6 addr; -#ifdef HAVE_STRUCT_SOCKADDR_DL - struct sockaddr_dl *sdl; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ static void *adata = NULL; unsigned char buf[RTADV_MSG_SIZE]; struct nd_router_advert *rtadv; @@ -315,24 +312,6 @@ rtadv_send_packet (int sock, struct interface *ifp) } /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - sdl = &ifp->sdl; - if (sdl != NULL && sdl->sdl_alen != 0) - { - buf[len++] = ND_OPT_SOURCE_LINKADDR; - - /* Option length should be rounded up to next octet if - the link address does not end on an octet boundary. */ - buf[len++] = (sdl->sdl_alen + 9) >> 3; - - memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen); - len += sdl->sdl_alen; - - /* Pad option to end on an octet boundary. */ - memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7); - len += -(sdl->sdl_alen + 2) & 0x7; - } -#else if (ifp->hw_addr_len != 0) { buf[len++] = ND_OPT_SOURCE_LINKADDR; @@ -348,7 +327,6 @@ rtadv_send_packet (int sock, struct interface *ifp) memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); len += -(ifp->hw_addr_len + 2) & 0x7; } -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* MTU */ if (zif->rtadv.AdvLinkMTU) @@ -534,7 +512,7 @@ rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, static void -rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit, +rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit, struct sockaddr_in6 *from, struct zebra_ns *zns) { struct icmp6_hdr *icmph; @@ -609,7 +587,7 @@ rtadv_read (struct thread *thread) int len; u_char buf[RTADV_MSG_SIZE]; struct sockaddr_in6 from; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int hoplimit = -1; struct zebra_ns *zns = THREAD_ARG (thread); diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 6d2edde640..0facc1a19f 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -70,28 +70,30 @@ static void handle_route_entry (mib2_ipRouteEntry_t *routeEntry) { - struct prefix_ipv4 prefix; - struct in_addr tmpaddr, gateway; - u_char zebra_flags = 0; + struct prefix prefix; + struct in_addr tmpaddr, gateway; + union g_addr *ggateway; + u_char zebra_flags = 0; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) - return; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) + return; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) + zebra_flags |= ZEBRA_FLAG_SELFROUTE; - prefix.family = AF_INET; + prefix.family = AF_INET; - tmpaddr.s_addr = routeEntry->ipRouteDest; - prefix.prefix = tmpaddr; + tmpaddr.s_addr = routeEntry->ipRouteDest; + prefix.u.prefix4 = tmpaddr; - tmpaddr.s_addr = routeEntry->ipRouteMask; - prefix.prefixlen = ip_masklen (tmpaddr); + tmpaddr.s_addr = routeEntry->ipRouteMask; + prefix.prefixlen = ip_masklen (tmpaddr); - gateway.s_addr = routeEntry->ipRouteNextHop; + gateway.s_addr = routeEntry->ipRouteNextHop; + ggateway = (union g_addr *)&gateway; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, + zebra_flags, &prefix, ggateway, NULL, 0, 0, 0, 0, 0); } void diff --git a/zebra/test_main.c b/zebra/test_main.c index 902c675aef..95c56bb046 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -112,7 +112,7 @@ usage (char *progname, int status) exit (status); } -static unsigned int test_ifindex = 0; +static ifindex_t test_ifindex = 0; /* testrib commands */ DEFUN (test_interface_state, diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 931fc73e43..133b0fc2e9 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -31,6 +31,7 @@ #include "command.h" #include "stream.h" #include "ptm_lib.h" +#include "network.h" #include "buffer.h" #include "zebra/zebra_ptm_redistribute.h" #include "bfd.h" @@ -383,9 +384,11 @@ zebra_ptm_socket_init (void) ptm_cb.ptm_sock = -1; - sock = socket (PF_UNIX, (SOCK_STREAM | SOCK_NONBLOCK), 0); + sock = socket (PF_UNIX, SOCK_STREAM, 0); if (sock < 0) return -1; + if (set_nonblocking(sock) < 0) + return -1; /* Make server socket. */ memset (&addr, 0, sizeof (struct sockaddr_un)); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8a2728a890..23ec8dab9a 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -21,12 +21,12 @@ #include <zebra.h> +#include "if.h" #include "prefix.h" #include "table.h" #include "memory.h" #include "str.h" #include "command.h" -#include "if.h" #include "log.h" #include "sockunion.h" #include "linklist.h" @@ -119,13 +119,17 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int prior int is_zebra_valid_kernel_table(u_int32_t table_id) { - if ((table_id > ZEBRA_KERNEL_TABLE_MAX) || - (table_id == RT_TABLE_UNSPEC) || + if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) + return 0; + +#ifdef linux + if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL) || (table_id == RT_TABLE_COMPAT)) return 0; - else - return 1; +#endif + + return 1; } int @@ -191,7 +195,7 @@ rib_copy_nexthops (struct rib *rib, struct nexthop *nh) } /* Delete specified nexthop from the list. */ -static void +void rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop) { if (nexthop->next) @@ -206,7 +210,7 @@ rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop) struct nexthop * -rib_nexthop_ifindex_add (struct rib *rib, unsigned int ifindex) +rib_nexthop_ifindex_add (struct rib *rib, ifindex_t ifindex) { struct nexthop *nexthop; @@ -237,7 +241,7 @@ rib_nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src struct nexthop * rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, - struct in_addr *src, unsigned int ifindex) + struct in_addr *src, ifindex_t ifindex) { struct nexthop *nexthop; struct interface *ifp; @@ -277,7 +281,7 @@ rib_nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6) struct nexthop * rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, - unsigned int ifindex) + ifindex_t ifindex) { struct nexthop *nexthop; @@ -348,6 +352,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, zebra_deregister_rnh_static_nexthops(rib->vrf_id, nexthop->resolved, top); nexthops_free(nexthop->resolved); nexthop->resolved = NULL; + rib->nexthop_mtu = 0; } /* Skip nexthops that have been filtered out due to route-map */ @@ -541,6 +546,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, } resolved = 1; } + if (resolved && set) + rib->nexthop_mtu = match->mtu; return resolved; } else @@ -740,10 +747,10 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, } struct rib * -rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id, - struct route_node **rn_out) +rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id, + union g_addr *addr, struct route_node **rn_out) { - struct prefix_ipv4 p; + struct prefix p; struct route_table *table; struct route_node *rn; struct rib *match; @@ -751,14 +758,18 @@ rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id, int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, safi, vrf_id); + table = zebra_vrf_table (afi, safi, vrf_id); if (! table) return 0; - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + memset (&p, 0, sizeof (struct prefix)); + p.family = afi; + p.u.prefix = *(u_char *)addr; p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; + if (afi == AFI_IP) + p.prefixlen = IPV4_MAX_PREFIXLEN; + else + p.prefixlen = IPV6_MAX_PREFIXLEN; rn = route_node_match (table, (struct prefix *) &p); @@ -813,23 +824,23 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out) { struct rib *rib = NULL, *mrib = NULL, *urib = NULL; struct route_node *m_rn = NULL, *u_rn = NULL; - int skip_bgp = 0; /* bool */ + union g_addr gaddr = { .ipv4 = addr }; switch (ipv4_multicast_mode) { case MCAST_MRIB_ONLY: - return rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, rn_out); + return rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, rn_out); case MCAST_URIB_ONLY: - return rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, rn_out); + return rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, rn_out); case MCAST_NO_CONFIG: case MCAST_MIX_MRIB_FIRST: - rib = mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); + rib = mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); if (!mrib) - rib = urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + rib = urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); break; case MCAST_MIX_DISTANCE: - mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); - urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); + urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); if (mrib && urib) rib = urib->distance < mrib->distance ? urib : mrib; else if (mrib) @@ -838,8 +849,8 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out) rib = urib; break; case MCAST_MIX_PFXLEN: - mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); - urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); + urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); if (mrib && urib) rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib; else if (mrib) @@ -1002,68 +1013,6 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, return ZEBRA_RIB_NOTFOUND; } -struct rib * -rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id) -{ - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct rib *match; - struct nexthop *newhop, *tnewhop; - int recursing; - - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return 0; - - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - IPV6_ADDR_COPY (&p.prefix, addr); - - rn = route_node_match (table, (struct prefix *) &p); - - while (rn) - { - route_unlock_node (rn); - - /* Pick up selected route. */ - RNODE_FOREACH_RIB (rn, match) - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } - - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); - } - else - { - if (match->type == ZEBRA_ROUTE_CONNECT) - /* Directly point connected route. */ - return match; - else - { - for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - return match; - return NULL; - } - } - } - return NULL; -} - #define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) @@ -1184,7 +1133,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, /* Iterate over all nexthops of the given RIB entry and refresh their * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any * nexthop is found to toggle the ACTIVE flag, the whole rib structure - * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is + * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is * transparently passed to nexthop_active_check(). * * Return value is the new number of active nexthops. @@ -1195,12 +1144,12 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) { struct nexthop *nexthop; union g_addr prev_src; - unsigned int prev_active, prev_index, new_active, old_num_nh; - + unsigned int prev_active, new_active, old_num_nh; + ifindex_t prev_index; old_num_nh = rib->nexthop_active_num; rib->nexthop_active_num = 0; - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { @@ -1220,15 +1169,15 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && !(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6)))) { - SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG (rib->status, RIB_ENTRY_CHANGED); SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } } if (old_num_nh != rib->nexthop_active_num) - SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG (rib->status, RIB_ENTRY_CHANGED); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_CHANGED)) + if (CHECK_FLAG (rib->status, RIB_ENTRY_CHANGED)) { SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } @@ -1241,7 +1190,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) /* Update flag indicates whether this is a "replace" or not. Currently, this * is only used for IPv4. */ -static int +int rib_install_kernel (struct route_node *rn, struct rib *rib, int update) { int ret = 0; @@ -1296,7 +1245,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, int update) } /* Uninstall the route from kernel. */ -static int +int rib_uninstall_kernel (struct route_node *rn, struct rib *rib) { int ret = 0; @@ -1425,7 +1374,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active or not. */ if (!nexthop_active_update (rn, select, 1)) { - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); return; } @@ -1451,7 +1400,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update for redistribution. */ if (installed) redistribute_update (&rn->p, select, NULL); - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } static void @@ -1478,7 +1427,7 @@ rib_process_del_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update nexthop for route, reset changed flag. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } static void @@ -1499,7 +1448,7 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, * something has changed. */ if (select != fib || - CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) + CHECK_FLAG (select->status, RIB_ENTRY_CHANGED)) { zfpm_trigger_update (rn, "updating existing route"); @@ -1548,7 +1497,6 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); } - } /* Update for redistribution. */ @@ -1619,11 +1567,11 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } /* Clear changed flag. */ - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } /* Core function for processing routing information base. */ @@ -1703,7 +1651,7 @@ rib_process (struct route_node *rn) * the nexthop_active_update() code. Thus, we might miss changes to * recursive NHs. */ - if (!CHECK_FLAG(rib->flags, ZEBRA_FLAG_CHANGED) && + if (!CHECK_FLAG(rib->status, RIB_ENTRY_CHANGED) && ! nexthop_active_update (rn, rib, 0)) { if (rib->type == ZEBRA_ROUTE_TABLE) @@ -1731,7 +1679,7 @@ rib_process (struct route_node *rn) /* Infinite distance. */ if (rib->distance == DISTANCE_INFINITY) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } @@ -1757,30 +1705,30 @@ rib_process (struct route_node *rn) if (select->type != ZEBRA_ROUTE_CONNECT || rib->metric <= select->metric) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; } else - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } else if (select->type == ZEBRA_ROUTE_CONNECT) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } /* higher distance loses */ if (rib->distance > select->distance) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } /* lower wins */ if (rib->distance < select->distance) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; continue; } @@ -1788,7 +1736,7 @@ rib_process (struct route_node *rn) /* metric tie-breaks equal distance */ if (rib->metric <= select->metric) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; } } /* RNODE_FOREACH_RIB_SAFE */ @@ -1819,7 +1767,7 @@ rib_process (struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB) rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p", (void *)select, (void *)fib); - if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) + if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED)) { if (info->safi == SAFI_UNICAST) zfpm_trigger_update (rn, "updating existing route"); @@ -1861,7 +1809,7 @@ rib_process (struct route_node *rn) rib_uninstall_kernel (rn, select); UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); } - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); } else if (! RIB_SYSTEM_ROUTE (select)) { @@ -1914,7 +1862,7 @@ rib_process (struct route_node *rn) /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } /* Regardless of some RIB entry being SELECTED or not before, now we can @@ -1984,7 +1932,7 @@ rib_process (struct route_node *rn) redistribute_delete(&rn->p, fib); } } - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } #endif @@ -2317,7 +2265,7 @@ rib_link (struct route_node *rn, struct rib *rib, int process) rib_queue_add (rn); } -static void +void rib_addnode (struct route_node *rn, struct rib *rib, int process) { /* RIB node has been un-removed before route-node is processed. @@ -2372,7 +2320,7 @@ rib_unlink (struct route_node *rn, struct rib *rib) } -static void +void rib_delnode (struct route_node *rn, struct rib *rib) { afi_t afi; @@ -2406,123 +2354,6 @@ rib_delnode (struct route_node *rn, struct rib *rib) } } -int -rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t metric, u_char distance, safi_t safi) -{ - struct rib *rib; - struct rib *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *nexthop; - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); - if (! table) - return 0; - - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 (p); - - /* Set default distance by route type. */ - if (distance == 0) - { - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; - - /* iBGP distance is 200. */ - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; - } - - /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); - - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type != type) - continue; - if (rib->instance != instance) - continue; - - if (rib->type != ZEBRA_ROUTE_CONNECT) - { - same = rib; - break; - } - /* Duplicate connected route comes in. */ - else if ((nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex && - !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - { - rib->refcnt++; - return 0 ; - } - } - - /* Allocate new rib structure. */ - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - rib->type = type; - rib->instance = instance; - rib->distance = distance; - rib->flags = flags; - rib->metric = metric; - rib->table = table_id; - rib->vrf_id = vrf_id; - rib->nexthop_num = 0; - rib->uptime = time (NULL); - - /* Nexthop settings. */ - if (gate) - { - if (ifindex) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, ifindex); - else - rib_nexthop_ipv4_add (rib, gate, src); - } - else - rib_nexthop_ifindex_add (rib, ifindex); - - /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " - "existing %p", - vrf_id, buf, p->prefixlen, (void *)rn, (void *)rib, rib->type, (void *)same); - } - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); - } - rib_addnode (rn, rib, 1); - - /* Free implicit route.*/ - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; -} - /* This function dumps the contents of a given RIB entry into * standard debug log. Calling function name and IP prefix in * question are passed as 1st and 2nd arguments. @@ -2550,9 +2381,10 @@ void _rib_dump (const char * func, ); zlog_debug ( - "%s: metric == %u, distance == %u, flags == %u, status == %u", + "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", func, rib->metric, + rib->mtu, rib->distance, rib->flags, rib->status @@ -2685,21 +2517,31 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) } int -rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) +rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, + struct rib *rib) { struct route_table *table; struct route_node *rn; struct rib *same; struct nexthop *nexthop; int ret = 0; - + int family; + + if (!rib) + return 0; + + if (p->family == AF_INET) + family = AFI_IP; + else + family = AFI_IP6; + /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, rib->vrf_id, rib->table); + table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table); if (! table) return 0; /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 (p); + apply_mask (p); /* Set default distance by route type. */ if (rib->distance == 0) @@ -2713,7 +2555,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) } /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); + rn = route_node_get (table, p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -2739,7 +2581,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) char buf[INET6_ADDRSTRLEN]; if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", rib->vrf_id, buf, p->prefixlen, (void *)rn, @@ -2763,11 +2605,10 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) return ret; } -/* XXX factor with rib_delete_ipv6 */ int -rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi) +rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, + int flags, struct prefix *p, union g_addr *gate, ifindex_t ifindex, + u_int32_t table_id) { struct route_table *table; struct route_node *rn; @@ -2780,15 +2621,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, char buf2[INET6_ADDRSTRLEN]; /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); + table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) return 0; /* Apply mask. */ - apply_mask_ipv4 (p); + apply_mask (p); /* Lookup route node. */ - rn = route_node_lookup (table, (struct prefix *) p); + rn = route_node_lookup (table, p); if (! rn) { if (IS_ZEBRA_DEBUG_RIB) @@ -2834,7 +2675,8 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, break; } for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate)) + if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || + IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) { same = rib; break; @@ -2852,10 +2694,10 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, { if (IS_ZEBRA_DEBUG_RIB) { - zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted " + zlog_debug ("%u:%s: rn %p, rib %p (type %d) was deleted " "from kernel, adding", - vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, rn, fib, fib->type); + vrf_id, prefix2str(p, buf1, INET6_ADDRSTRLEN), + rn, fib, fib->type); } if (allow_delete) { @@ -2880,7 +2722,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, zlog_debug ("%u:%s: via %s ifindex %d type %d " "doesn't exist in rib", vrf_id, prefix2str (p, buf1, sizeof(buf1)), - inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), + inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), ifindex, type); else @@ -2901,444 +2743,14 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, return 0; } -/* Install static route into rib. */ -void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) -{ - struct rib *rib; - struct route_node *rn; - struct route_table *table; - struct prefix nh_p; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route */ - rn = route_node_get (table, p); - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) - break; - } - - if (rib) - { - /* if tag value changed , update old value in RIB */ - if (rib->tag != si->tag) - rib->tag = si->tag; - - /* Same distance static route is there. Update it with new - nexthop. */ - route_unlock_node (rn); - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - rib_nexthop_ifindex_add (rib, si->ifindex); - break; - case STATIC_IPV4_BLACKHOLE: - rib_nexthop_blackhole_add (rib); - break; - case STATIC_IPV6_GATEWAY: - rib_nexthop_ipv6_add (rib, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); - break; - } - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - /* Schedule route for processing or invoke NHT, as appropriate. */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - else - rib_queue_add (rn); - } - else - { - /* This is new static route. */ - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - - rib->type = ZEBRA_ROUTE_STATIC; - rib->instance = 0; - rib->distance = si->distance; - rib->metric = 0; - rib->vrf_id = si->vrf_id; - rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; - rib->nexthop_num = 0; - rib->tag = si->tag; - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - rib_nexthop_ifindex_add (rib, si->ifindex); - break; - case STATIC_IPV4_BLACKHOLE: - rib_nexthop_blackhole_add (rib); - break; - case STATIC_IPV6_GATEWAY: - rib_nexthop_ipv6_add (rib, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); - break; - } - - /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - /* Link this rib to the tree. Schedule for processing or invoke NHT, - * as appropriate. - */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - { - rib_addnode (rn, rib, 0); - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - } - else - rib_addnode (rn, rib, 1); - } -} - -static int -static_nexthop_same (struct nexthop *nexthop, struct static_route *si) -{ - if (nexthop->type == NEXTHOP_TYPE_IPV4 - && si->type == STATIC_IPV4_GATEWAY - && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - && si->type == STATIC_IFINDEX - && nexthop->ifindex == si->ifindex) - return 1; - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE - && si->type == STATIC_IPV4_BLACKHOLE) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IPV6 - && si->type == STATIC_IPV6_GATEWAY - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX - && si->type == STATIC_IPV6_GATEWAY_IFINDEX - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) - && nexthop->ifindex == si->ifindex) - return 1; - return 0; -} - -/* Uninstall static route from RIB. */ -void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) -{ - struct route_node *rn; - struct rib *rib; - struct nexthop *nexthop; - struct route_table *table; - struct prefix nh_p; - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route with type and distance. */ - rn = route_node_lookup (table, p); - if (! rn) - return; - - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && - rib->tag == si->tag) - break; - } - - if (! rib) - { - route_unlock_node (rn); - return; - } - - /* Lookup nexthop. */ - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (static_nexthop_same (nexthop, si)) - break; - - /* Can't find nexthop. */ - if (! nexthop) - { - route_unlock_node (rn); - return; - } - - /* Check nexthop. */ - if (rib->nexthop_num == 1) - rib_delnode (rn, rib); - else - { - /* Mark this nexthop as inactive and reinstall the route. Then, delete - * the nexthop. There is no need to re-evaluate the route for this - * scenario. - */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - /* If there are other active nexthops, do an update. */ - if (rib->nexthop_active_num > 1) - { - rib_install_kernel (rn, rib, 1); - redistribute_update (&rn->p, rib, NULL); - } - else - { - redistribute_delete (&rn->p, rib); - rib_uninstall_kernel (rn, rib); - } - } - - if (afi == AFI_IP) - { - /* Delete the nexthop and dereg from NHT */ - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nexthop->gate.ipv4; - } - else - { - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nexthop->gate.ipv6; - } - rib_nexthop_delete (rib, nexthop); - zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); - nexthop_free (nexthop); - } - /* Unlock node. */ - route_unlock_node (rn); -} int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf) -{ - u_char type = 0; - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP][safi]; - - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_get (stable, p); - - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag)) - { - route_unlock_node (rn); - return 0; - } - else - update = si; - } - } - - /* Distance or tag changed. */ - if (update) - static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf->vrf_id; - si->ifindex = ifindex; - if (si->ifindex) - strcpy(si->ifname, ifname); - - if (gate) - si->addr.ipv4 = *gate; - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) - { - if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) - break; - if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) - continue; - } - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (AFI_IP, safi, p, si); - - return 1; -} - -int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf) -{ - u_char type = 0; - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, safi, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); - if (! rn) - return 0; - - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (AFI_IP, safi, p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - route_unlock_node (rn); - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - route_unlock_node (rn); - - return 1; -} - -int -rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) +rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, union g_addr *src, ifindex_t ifindex, + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance) { struct rib *rib; struct rib *same = NULL; @@ -3347,22 +2759,28 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct nexthop *nexthop; /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); + table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) return 0; /* Make sure mask is applied. */ - apply_mask_ipv6 (p); + apply_mask (p); /* Set default distance by route type. */ - if (!distance) - distance = route_info[type].distance; - - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; + if (distance == 0) + { + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; + + /* iBGP distance is 200. */ + if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) + distance = 200; + } /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); + rn = route_node_get (table, p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -3380,12 +2798,14 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, same = rib; break; } + /* Duplicate connected route comes in. */ else if ((nexthop = rib->nexthop) && nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex) + nexthop->ifindex == ifindex && + !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) { rib->refcnt++; - return 0; + return 0 ; } } @@ -3397,6 +2817,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, rib->distance = distance; rib->flags = flags; rib->metric = metric; + rib->mtu = mtu; rib->table = table_id; rib->vrf_id = vrf_id; rib->nexthop_num = 0; @@ -3405,10 +2826,20 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Nexthop settings. */ if (gate) { - if (ifindex) - rib_nexthop_ipv6_ifindex_add (rib, gate, ifindex); + if (afi == AFI_IP6) + { + if (ifindex) + rib_nexthop_ipv6_ifindex_add (rib, &gate->ipv6, ifindex); + else + rib_nexthop_ipv6_add (rib, &gate->ipv6); + } else - rib_nexthop_ipv6_add (rib, gate); + { + if (ifindex) + rib_nexthop_ipv4_ifindex_add (rib, &gate->ipv4, &src->ipv4, ifindex); + else + rib_nexthop_ipv4_add (rib, &gate->ipv4, &src->ipv4); + } } else rib_nexthop_ifindex_add (rib, ifindex); @@ -3424,7 +2855,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, char buf[INET6_ADDRSTRLEN]; if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", vrf_id, buf, p->prefixlen, (void *)rn, @@ -3432,7 +2863,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, } if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); + rib_dump (p, rib); } rib_addnode (rn, rib, 1); @@ -3444,406 +2875,6 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, return 0; } -int -rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, - unsigned long ifindex) -{ - struct route_table *table; - struct route_node *rn; - struct rib *same = NULL; - struct nexthop *nexthop; - int ret = 0; - int family; - - if (!rib) - return 0; - - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table); - if (! table) - return 0; - - if (p->family == AF_INET) - { - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 ((struct prefix_ipv4 *)p); - } - else - { - /* Make sure mask is applied. */ - apply_mask_ipv6 ((struct prefix_ipv6 *)p); - } - - /* Set default distance by route type. */ - if (rib->distance == 0) - { - rib->distance = route_info[rib->type].distance; - - /* iBGP distance is 200. */ - if (rib->type == ZEBRA_ROUTE_BGP - && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) - rib->distance = 200; - } - - /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); - - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RIB (rn, same) { - if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED)) { - continue; - } - if (same->type != rib->type) { - continue; - } - - if (same->instance != rib->instance) { - continue; - } - - if (same->table != rib->table) { - continue; - } - if (same->type != ZEBRA_ROUTE_CONNECT) { - break; - } - else if ((nexthop = same->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex) { - same->refcnt++; - return 0; - } - } - - /* If this route is kernel route, set FIB flag to the route. */ - if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) { - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " - "existing %p", - rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same); - } - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); - } - rib_addnode (rn, rib, 1); - ret = 1; - - /* Free implicit route.*/ - if (same) - { - rib_delnode (rn, same); - ret = -1; - } - - route_unlock_node (rn); - return ret; -} - -/* XXX factor with rib_delete_ipv6 */ - -int -rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi) -{ - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct rib *fib = NULL; - struct rib *same = NULL; - struct nexthop *nexthop, *tnexthop; - int recursing; - char buf1[PREFIX_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - /* Apply mask. */ - apply_mask_ipv6 (p); - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); - if (! table) - return 0; - - /* Lookup route node. */ - rn = route_node_lookup (table, (struct prefix *) p); - if (! rn) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s: doesn't exist in rib", - vrf_id, prefix2str (p, buf1, sizeof(buf1))); - return ZEBRA_ERR_RTNOEXIST; - } - - /* Lookup same type route. */ - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) - fib = rib; - - if (rib->type != type) - continue; - if (rib->instance != instance) - continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->ifindex != ifindex) - continue; - if (rib->refcnt) - { - rib->refcnt--; - route_unlock_node (rn); - route_unlock_node (rn); - return 0; - } - same = rib; - break; - } - /* Make sure that the route found has the same gateway. */ - else - { - if (gate == NULL) - { - same = rib; - break; - } - for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) - { - same = rib; - break; - } - if (same) - break; - } - } - - /* If same type of route can't be found and this message is from - kernel. */ - if (! same) - { - if (fib && type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted " - "from kernel, adding", - vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, rn, fib, fib->type); - if (allow_delete) - { - /* Unset flags. */ - for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); - } - else - { - /* This means someone else, other than Zebra, has deleted a Zebra - * route from the kernel. We will add it back */ - rib_install_kernel(rn, fib, 0); - } - } - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (gate) - zlog_debug ("%s: vrf %u via %s ifindex %d type %d " - "doesn't exist in rib", - prefix2str (p, buf1, sizeof(buf1)), vrf_id, - inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), - ifindex, - type); - else - zlog_debug ("%s: vrf %u ifindex %d type %d doesn't exist in rib", - prefix2str (p, buf1, sizeof(buf1)), vrf_id, - ifindex, - type); - } - route_unlock_node (rn); - return ZEBRA_ERR_RTNOEXIST; - } - } - - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; -} - -/* Add static route into static route configuration. */ -int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; - - if (! stable) - return -1; - - if (!gate && - (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - if (!ifindex && - (type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX)) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_get (stable, p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag)) - { - route_unlock_node (rn); - return 0; - } - else - update = si; - } - } - - /* Distance or tag changed. */ - if (update) - static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf->vrf_id; - si->ifindex = ifindex; - if (si->ifindex) - strcpy (si->ifname, ifname); - - switch (type) - { - case STATIC_IPV6_GATEWAY: - si->addr.ipv6 = *gate; - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - si->addr.ipv6 = *gate; - break; - } - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (AFI_IP6, SAFI_UNICAST, p, si); - - return 1; -} - -/* Delete static route from static route configuration. */ -int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); - if (! rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (distance == si->distance - && type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - return 1; -} - /* Schedule routes of a particular table (address-family) based on event. */ static void rib_update_table (struct route_table *table, rib_update_event_t event) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 216a9d1cee..ef2357b99c 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -592,7 +592,7 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, vrfid, bufn, bufs); } - SET_FLAG(srib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG(srib->status, RIB_ENTRY_CHANGED); SET_FLAG(srib->status, RIB_ENTRY_NEXTHOPS_CHANGED); rib_queue_add(static_rn); } @@ -886,21 +886,21 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; #ifdef HAVE_IPV6 - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_put (s, &nexthop->gate.ipv6, 16); break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: stream_put (s, &nexthop->gate.ipv6, 16); stream_putl (s, nexthop->ifindex); break; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index db3e5eaba1..1417824d07 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -252,7 +252,7 @@ route_match_interface (void *rule, struct prefix *prefix, { struct nh_rmap_obj *nh_data; char *ifname = rule; - unsigned int ifindex; + ifindex_t ifindex; if (type == RMAP_ZEBRA) { diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c new file mode 100644 index 0000000000..7d47510635 --- /dev/null +++ b/zebra/zebra_static.c @@ -0,0 +1,480 @@ +/* + * Static Routing Information code + * Copyright (C) 2016 Cumulus Networks + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include <zebra.h> + +#include <lib/nexthop.h> +#include <lib/memory.h> + +#include "zebra/debug.h" +#include "zebra/rib.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/zebra_static.h" +#include "zebra/zebra_rnh.h" +#include "zebra/redistribute.h" + +/* Install static route into rib. */ +void +static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +{ + struct rib *rib; + struct route_node *rn; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table (afi, safi, si->vrf_id); + if (! table) + return; + + /* Lookup existing route */ + rn = route_node_get (table, p); + RNODE_FOREACH_RIB (rn, rib) + { + if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) + continue; + + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) + break; + } + + if (rib) + { + /* if tag value changed , update old value in RIB */ + if (rib->tag != si->tag) + rib->tag = si->tag; + + /* Same distance static route is there. Update it with new + nexthop. */ + route_unlock_node (rn); + switch (si->type) + { + case STATIC_IPV4_GATEWAY: + rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + rib_nexthop_ifindex_add (rib, si->ifindex); + break; + case STATIC_IPV4_BLACKHOLE: + rib_nexthop_blackhole_add (rib); + break; + case STATIC_IPV6_GATEWAY: + rib_nexthop_ipv6_add (rib, &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); + break; + } + + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + /* Schedule route for processing or invoke NHT, as appropriate. */ + if (si->type == STATIC_IPV4_GATEWAY || + si->type == STATIC_IPV6_GATEWAY) + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); + else + rib_queue_add (rn); + } + else + { + /* This is new static route. */ + rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); + + rib->type = ZEBRA_ROUTE_STATIC; + rib->instance = 0; + rib->distance = si->distance; + rib->metric = 0; + rib->mtu = 0; + rib->vrf_id = si->vrf_id; + rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; + rib->nexthop_num = 0; + rib->tag = si->tag; + + switch (si->type) + { + case STATIC_IPV4_GATEWAY: + rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + rib_nexthop_ifindex_add (rib, si->ifindex); + break; + case STATIC_IPV4_BLACKHOLE: + rib_nexthop_blackhole_add (rib); + break; + case STATIC_IPV6_GATEWAY: + rib_nexthop_ipv6_add (rib, &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); + break; + } + + /* Save the flags of this static routes (reject, blackhole) */ + rib->flags = si->flags; + + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + /* Link this rib to the tree. Schedule for processing or invoke NHT, + * as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY || + si->type == STATIC_IPV6_GATEWAY) + { + rib_addnode (rn, rib, 0); + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); + } + else + rib_addnode (rn, rib, 1); + } +} +static int +static_nexthop_same (struct nexthop *nexthop, struct static_route *si) +{ + if (nexthop->type == NEXTHOP_TYPE_IPV4 + && si->type == STATIC_IPV4_GATEWAY + && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + && si->type == STATIC_IFINDEX + && nexthop->ifindex == si->ifindex) + return 1; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_IPV4_BLACKHOLE) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IPV6 + && si->type == STATIC_IPV6_GATEWAY + && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && si->type == STATIC_IPV6_GATEWAY_IFINDEX + && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) + && nexthop->ifindex == si->ifindex) + return 1; + return 0; +} + +/* Uninstall static route from RIB. */ +void +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +{ + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table (afi, safi, si->vrf_id); + if (! table) + return; + + /* Lookup existing route with type and distance. */ + rn = route_node_lookup (table, p); + if (! rn) + return; + + RNODE_FOREACH_RIB (rn, rib) + { + if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) + continue; + + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && + rib->tag == si->tag) + break; + } + + if (! rib) + { + route_unlock_node (rn); + return; + } + + /* Lookup nexthop. */ + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (static_nexthop_same (nexthop, si)) + break; + + /* Can't find nexthop. */ + if (! nexthop) + { + route_unlock_node (rn); + return; + } + + /* Check nexthop. */ + if (rib->nexthop_num == 1) + rib_delnode (rn, rib); + else + { + /* Mark this nexthop as inactive and reinstall the route. Then, delete + * the nexthop. There is no need to re-evaluate the route for this + * scenario. + */ + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + { + /* If there are other active nexthops, do an update. */ + if (rib->nexthop_active_num > 1) + { + rib_install_kernel (rn, rib, 1); + redistribute_update (&rn->p, rib, NULL); + } + else + { + redistribute_delete (&rn->p, rib); + rib_uninstall_kernel (rn, rib); + } + } + + if (afi == AFI_IP) + { + /* Delete the nexthop and dereg from NHT */ + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nexthop->gate.ipv4; + } + else + { + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nexthop->gate.ipv6; + } + rib_nexthop_delete (rib, nexthop); + zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); + nexthop_free (nexthop); + } + /* Unlock node. */ + route_unlock_node (rn); +} + +int +static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf) +{ + struct route_node *rn; + struct static_route *si; + struct static_route *pp; + struct static_route *cp; + struct static_route *update = NULL; + struct route_table *stable = zvrf->stable[afi][safi]; + + if (! stable) + return -1; + + if (!gate && + (type == STATIC_IPV4_GATEWAY || + type == STATIC_IPV6_GATEWAY || + type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + if (!ifindex && + (type == STATIC_IFINDEX || + type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_get (stable, p); + + /* Do nothing if there is a same static route. */ + for (si = rn->info; si; si = si->next) + { + if (type == si->type + && (! gate || + ((afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || + (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) + && (! ifindex || ifindex == si->ifindex)) + { + if ((distance == si->distance) && (tag == si->tag)) + { + route_unlock_node (rn); + return 0; + } + else + update = si; + } + } + + /* Distance or tag changed. */ + if (update) + static_delete_route (afi, safi, type, p, gate, + ifindex, update->tag, update->distance, zvrf); + + /* Make new static route structure. */ + si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); + + si->type = type; + si->distance = distance; + si->flags = flags; + si->tag = tag; + si->vrf_id = zvrf->vrf_id; + si->ifindex = ifindex; + if (si->ifindex) + strcpy(si->ifname, ifname); + + switch (type) + { + case STATIC_IPV4_GATEWAY: + si->addr.ipv4 = gate->ipv4; + break; + case STATIC_IPV6_GATEWAY: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IFINDEX: + break; + } + + /* Add new static route information to the tree with sort by + distance value and gateway address. */ + for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) + { + if (si->distance < cp->distance) + break; + if (si->distance > cp->distance) + continue; + if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) + { + if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) + break; + if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) + continue; + } + } + + /* Make linked list. */ + if (pp) + pp->next = si; + else + rn->info = si; + if (cp) + cp->prev = si; + si->prev = pp; + si->next = cp; + + /* Install into rib. */ + static_install_route (afi, safi, p, si); + + return 1; +} + +int +static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, struct zebra_vrf *zvrf) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + + /* Lookup table. */ + stable = zebra_vrf_static_table (afi, safi, zvrf); + if (! stable) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_lookup (stable, p); + if (! rn) + return 0; + + /* Find same static route is the tree */ + for (si = rn->info; si; si = si->next) + if (type == si->type + && (! gate || ( + (afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || + (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) + && (! ifindex || ifindex == si->ifindex) + && (! tag || (tag == si->tag))) + break; + + /* Can't find static route. */ + if (! si) + { + route_unlock_node (rn); + return 0; + } + + /* Install into rib. */ + static_uninstall_route (AFI_IP, safi, p, si); + + /* Unlink static route from linked list. */ + if (si->prev) + si->prev->next = si->next; + else + rn->info = si->next; + if (si->next) + si->next->prev = si->prev; + route_unlock_node (rn); + + /* Free static route configuration. */ + XFREE (MTYPE_STATIC_ROUTE, si); + + route_unlock_node (rn); + + return 1; +} diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h new file mode 100644 index 0000000000..0f00609b55 --- /dev/null +++ b/zebra/zebra_static.h @@ -0,0 +1,89 @@ +/* + * Static Routing Information header + * Copyright (C) 2016 Cumulus Networks + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef __ZEBRA_STATIC_H__ +#define __ZEBRA_STATIC_H__ + +/* Static route information. */ +struct static_route +{ + /* For linked list. */ + struct static_route *prev; + struct static_route *next; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Administrative distance. */ + u_char distance; + + /* Tag */ + u_short tag; + + /* Flag for this static route's type. */ + u_char type; +#define STATIC_IFINDEX 1 +#define STATIC_IPV4_GATEWAY 2 +#define STATIC_IPV4_BLACKHOLE 3 +#define STATIC_IPV6_GATEWAY 4 +#define STATIC_IPV6_GATEWAY_IFINDEX 5 + + /* + * Nexthop value. + * + * Under IPv4 addr and ifindex are + * used independentyly. + * STATIC_IPV4_GATEWAY uses addr + * STATIC_IFINDEX uses ifindex + */ + union g_addr addr; + ifindex_t ifindex; + + char ifname[INTERFACE_NAMSIZ + 1]; + + /* bit flags */ + u_char flags; +/* + see ZEBRA_FLAG_REJECT + ZEBRA_FLAG_BLACKHOLE + */ +}; + +extern void +static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); +extern void +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); + +extern int +static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf); + +extern int +static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, + struct zebra_vrf *zvrf); + + +#endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 46dc29d102..d9bd919bfe 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -29,6 +29,7 @@ #include "zebra/rib.h" #include "zebra/zebra_vrf.h" #include "zebra/router-id.h" +#include "zebra/zebra_static.h" extern struct zebra_t zebrad; struct list *zvrf_list; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 6d846c3ecb..72d0ced658 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -29,13 +29,14 @@ #include "rib.h" #include "nexthop.h" #include "vrf.h" +#include "lib/json.h" #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_rnh.h" #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" -#include "lib/json.h" +#include "zebra/zebra_static.h" extern int allow_delete; @@ -65,6 +66,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, struct zebra_vrf *zvrf = NULL; unsigned int ifindex = 0; const char *ifname = NULL; + u_char type = STATIC_IPV4_BLACKHOLE; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -116,9 +118,9 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (safi, &p, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, NULL, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -142,9 +144,9 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (gate_str == NULL) { if (add_cmd) - static_add_ipv4 (safi, &p, NULL, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, NULL, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -163,12 +165,15 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, else ifindex = ifp->ifindex; ifname = gate_str; + type = STATIC_IFINDEX; } + else + type = STATIC_IPV4_GATEWAY; if (add_cmd) - static_add_ipv4 (safi, &p, ifindex ? NULL : &gate, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, ifindex ? NULL : &gate, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -1934,6 +1939,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); if (rib->tag) vty_out (vty, ", tag %d", rib->tag); + if (rib->mtu) + vty_out (vty, ", mtu %u", rib->mtu); if (rib->vrf_id != VRF_DEFAULT) { zvrf = vrf_info_lookup(rib->vrf_id); @@ -3730,9 +3737,9 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_ipv6 (&p, type, gate, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv6 (&p, type, gate, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } diff --git a/zebra/zserv.c b/zebra/zserv.c index d625c02ff4..020a252371 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -160,13 +160,19 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); -#ifdef HAVE_STRUCT_SOCKADDR_DL - stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage)); -#else + stream_putl (s, ifp->ll_type); stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); -#endif /* HAVE_STRUCT_SOCKADDR_DL */ + + /* 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)); @@ -255,6 +261,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. * @@ -695,6 +730,8 @@ zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p, SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); stream_putw(s, rib->tag); } + SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU); + stream_putl (s, rib->mtu); } /* write real message flags value */ @@ -710,10 +747,9 @@ zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p, return zebra_server_send_message(client); } -#ifdef HAVE_IPV6 static int -zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, - vrf_id_t vrf_id) +zsend_nexthop_lookup (struct zserv *client, afi_t afi, safi_t safi, + vrf_id_t vrf_id, union g_addr *addr) { struct stream *s; struct rib *rib; @@ -722,82 +758,24 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv6 (addr, vrf_id); + rib = rib_match (afi, safi, vrf_id, addr, NULL); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, vrf_id); - stream_put (s, addr, 16); - - if (rib) + if (afi == AFI_IP) { - stream_putl (s, rib->metric); - num = 0; - nump = stream_get_endp(s); - stream_putc (s, 0); - /* Only non-recursive routes are elegible to resolve nexthop we - * are looking up. Therefore, we will just iterate over the top - * chain of nexthops. */ - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - stream_putc (s, nexthop->type); - switch (nexthop->type) - { - case ZEBRA_NEXTHOP_IPV6: - stream_put (s, &nexthop->gate.ipv6, 16); - break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - case ZEBRA_NEXTHOP_IFINDEX: - stream_putl (s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - num++; - } - stream_putc_at (s, nump, num); + zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id); + stream_put_in_addr (s, &addr->ipv4); } else { - stream_putl (s, 0); - stream_putc (s, 0); + zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, vrf_id); + stream_put (s, &addr->ipv6, 16); } - stream_putw_at (s, 0, stream_get_endp (s)); - - return zebra_server_send_message(client); -} -#endif /* HAVE_IPV6 */ - -static int -zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, - vrf_id_t vrf_id) -{ - struct stream *s; - struct rib *rib; - unsigned long nump; - u_char num; - struct nexthop *nexthop; - - /* Lookup nexthop. */ - rib = rib_match_ipv4 (addr, SAFI_UNICAST, vrf_id, NULL); - - /* Get output stream. */ - s = client->obuf; - stream_reset (s); - - /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id); - stream_put_in_addr (s, &addr); - if (rib) { if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) @@ -806,7 +784,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, num = 0; nump = stream_get_endp(s); stream_putc (s, 0); - /* Only non-recursive routes are elegible to resolve the nexthop we + /* Only non-recursive routes are elegible to resolve nexthop we * are looking up. Therefore, we will just iterate over the top * chain of nexthops. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) @@ -815,14 +793,21 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IPV6: + stream_put (s, &nexthop->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put (s, &nexthop->gate.ipv6, 16); + stream_putl (s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -842,7 +827,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, } stream_putw_at (s, 0, stream_get_endp (s)); - + return zebra_server_send_message(client); } @@ -996,14 +981,14 @@ zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struc stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -1061,14 +1046,14 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p, stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -1182,13 +1167,13 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { int i; struct rib *rib; - struct prefix_ipv4 p; + struct prefix p; u_char message; struct in_addr nexthop; u_char nexthop_num; u_char nexthop_type; struct stream *s; - unsigned int ifindex; + ifindex_t ifindex; safi_t safi; int ret; @@ -1210,7 +1195,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ rib->vrf_id = zvrf->vrf_id; @@ -1227,23 +1212,23 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); rib_nexthop_ifindex_add (rib, ifindex); break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop.s_addr = stream_get_ipv4 (s); rib_nexthop_ipv4_add (rib, &nexthop, NULL); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); ifindex = stream_getl (s); rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex); break; - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_forward_getp (s, IPV6_MAX_BYTELEN); break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1264,10 +1249,15 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* Table */ rib->table = zvrf->table_id; - ret = rib_add_ipv4_multipath (&p, rib, safi); + ret = rib_add_multipath (AFI_IP, safi, &p, rib); /* Stats */ if (ret > 0) @@ -1284,9 +1274,10 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) int i; struct stream *s; struct zapi_ipv4 api; - struct in_addr nexthop, *nexthop_p; + struct in_addr nexthop; + union g_addr *nexthop_p; unsigned long ifindex; - struct prefix_ipv4 p; + struct prefix p; u_char nexthop_num; u_char nexthop_type; u_int32_t table_id; @@ -1307,7 +1298,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) @@ -1320,19 +1311,19 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop.s_addr = stream_get_ipv4 (s); - nexthop_p = &nexthop; + nexthop_p = (union g_addr *)&nexthop; break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); - nexthop_p = &nexthop; + nexthop_p = (union g_addr *)&nexthop; ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_forward_getp (s, IPV6_MAX_BYTELEN); break; } @@ -1359,8 +1350,8 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) table_id = zvrf->table_id; - rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, - zvrf->vrf_id, table_id, api.safi); + rib_delete (AFI_IP, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, nexthop_p, ifindex, table_id); client->v4_route_del_cnt++; return 0; } @@ -1377,7 +1368,8 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length, if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) zlog_debug("%s: looking up %s", __func__, inet_ntop (AF_INET, &addr, buf, BUFSIZ)); - return zsend_ipv4_nexthop_lookup (client, addr, zvrf->vrf_id); + return zsend_nexthop_lookup (client, AFI_IP, SAFI_UNICAST, + zvrf->vrf_id, (union g_addr *)&addr); } /* MRIB Nexthop lookup for IPv4. */ @@ -1417,8 +1409,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct u_char message; u_char nexthop_num; u_char nexthop_type; - unsigned long ifindex; - struct prefix_ipv4 p; + struct prefix p; safi_t safi; static struct in6_addr nexthops[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM]; @@ -1427,7 +1418,6 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct /* Get input stream. */ s = client->ibuf; - ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Allocate new rib. */ @@ -1445,7 +1435,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ rib->vrf_id = zvrf->vrf_id; @@ -1468,18 +1458,18 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); if (nh_count < MULTIPATH_NUM) { nexthops[nh_count++] = nexthop; } break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: if (if_count < MULTIPATH_NUM) { ifindices[if_count++] = stream_getl (s); } break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1518,10 +1508,15 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* Table */ rib->table = zvrf->table_id; - ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); + ret = rib_add_multipath (AFI_IP6, safi, &p, rib); /* Stats */ if (ret > 0) client->v4_route_add_cnt++; @@ -1541,8 +1536,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) u_char message; u_char nexthop_num; u_char nexthop_type; - unsigned long ifindex; - struct prefix_ipv6 p; + struct prefix p; safi_t safi; static struct in6_addr nexthops[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM]; @@ -1551,7 +1545,6 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) /* Get input stream. */ s = client->ibuf; - ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Allocate new rib. */ @@ -1569,7 +1562,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); /* We need to give nh-addr, nh-ifindex with the same next-hop object * to the rib to ensure that IPv6 multipathing works; need to coalesce @@ -1589,18 +1582,18 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); if (nh_count < MULTIPATH_NUM) { nexthops[nh_count++] = nexthop; } break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: if (if_count < MULTIPATH_NUM) { ifindices[if_count++] = stream_getl (s); } break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1636,11 +1629,16 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* VRF ID */ rib->vrf_id = zvrf->vrf_id; rib->table = zvrf->table_id; - ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); + ret = rib_add_multipath (AFI_IP, safi, &p, rib); /* Stats */ if (ret > 0) client->v6_route_add_cnt++; @@ -1658,8 +1656,9 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) struct stream *s; struct zapi_ipv6 api; struct in6_addr nexthop; + union g_addr *pnexthop; unsigned long ifindex; - struct prefix_ipv6 p; + struct prefix p; s = client->ibuf; ifindex = 0; @@ -1676,7 +1675,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) @@ -1690,10 +1689,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); + pnexthop = (union g_addr *)&nexthop; break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); break; } @@ -1719,11 +1719,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) api.tag = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, - zvrf->vrf_id, client->rtm_table, api.safi); + rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, NULL, ifindex, client->rtm_table); else - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, - zvrf->vrf_id, client->rtm_table, api.safi); + rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, pnexthop, ifindex, client->rtm_table); client->v6_route_del_cnt++; return 0; @@ -1741,7 +1741,8 @@ zread_ipv6_nexthop_lookup (struct zserv *client, u_short length, zlog_debug("%s: looking up %s", __func__, inet_ntop (AF_INET6, &addr, buf, BUFSIZ)); - return zsend_ipv6_nexthop_lookup (client, &addr, zvrf->vrf_id); + return zsend_nexthop_lookup (client, AFI_IP6, SAFI_UNICAST, + zvrf->vrf_id, (union g_addr *)&addr); } /* Register zebra server router-id information. Send current router-id */ diff --git a/zebra/zserv.h b/zebra/zserv.h index 737795ad54..3667f5b2b6 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -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); |
