summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_advertise.c1
-rw-r--r--bgpd/bgp_aspath.c1
-rw-r--r--bgpd/bgp_attr.c6
-rw-r--r--bgpd/bgp_attr.h2
-rw-r--r--bgpd/bgp_bfd.c2
-rw-r--r--bgpd/bgp_btoa.c3
-rw-r--r--bgpd/bgp_clist.c1
-rw-r--r--bgpd/bgp_damp.c1
-rw-r--r--bgpd/bgp_debug.c59
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_dump.c2
-rw-r--r--bgpd/bgp_ecommunity.c6
-rw-r--r--bgpd/bgp_filter.c9
-rw-r--r--bgpd/bgp_fsm.c3
-rw-r--r--bgpd/bgp_main.c5
-rw-r--r--bgpd/bgp_mpath.c1
-rw-r--r--bgpd/bgp_mplsvpn.c5
-rw-r--r--bgpd/bgp_network.c23
-rw-r--r--bgpd/bgp_nexthop.c6
-rw-r--r--bgpd/bgp_nht.c13
-rw-r--r--bgpd/bgp_open.c11
-rw-r--r--bgpd/bgp_packet.c1
-rw-r--r--bgpd/bgp_regex.c1
-rw-r--r--bgpd/bgp_route.c73
-rw-r--r--bgpd/bgp_routemap.c8
-rw-r--r--bgpd/bgp_snmp.c1
-rw-r--r--bgpd/bgp_table.c1
-rw-r--r--bgpd/bgp_table.h8
-rw-r--r--bgpd/bgp_updgrp.c4
-rw-r--r--bgpd/bgp_updgrp.h20
-rw-r--r--bgpd/bgp_updgrp_adv.c7
-rw-r--r--bgpd/bgp_vty.c122
-rw-r--r--bgpd/bgp_zebra.c11
-rw-r--r--bgpd/bgp_zebra.h4
-rw-r--r--bgpd/bgpd.c29
-rw-r--r--bgpd/bgpd.h8
-rwxr-xr-xconfigure.ac115
-rw-r--r--cumulus/start-stop-daemon.c7
-rw-r--r--doc/install.texi11
-rw-r--r--doc/isisd.texi432
-rw-r--r--doc/main.texi75
-rw-r--r--doc/mpls/ChangeLog.opaque.txt13
-rw-r--r--doc/mpls/ospfd.conf1
-rw-r--r--doc/ospfd.texi203
-rw-r--r--doc/quagga.texi2
-rw-r--r--isisd/AUTHORS1
-rw-r--r--isisd/Makefile.am4
-rw-r--r--isisd/isis_circuit.c19
-rw-r--r--isisd/isis_circuit.h3
-rw-r--r--isisd/isis_lsp.c81
-rw-r--r--isisd/isis_lsp.h2
-rw-r--r--isisd/isis_main.c3
-rw-r--r--isisd/isis_pdu.c10
-rw-r--r--isisd/isis_route.c10
-rw-r--r--isisd/isis_route.h4
-rw-r--r--isisd/isis_te.c1369
-rw-r--r--isisd/isis_te.h331
-rw-r--r--isisd/isis_tlv.c35
-rw-r--r--isisd/isis_tlv.h20
-rw-r--r--isisd/isis_zebra.c38
-rw-r--r--isisd/isisd.c13
-rw-r--r--isisd/isisd.h4
-rw-r--r--lib/bfd.c4
-rw-r--r--lib/command.c8
-rw-r--r--lib/command.h5
-rw-r--r--lib/filter.h5
-rw-r--r--lib/if.c130
-rw-r--r--lib/if.h163
-rw-r--r--lib/log.c4
-rw-r--r--lib/memory.c14
-rw-r--r--lib/memory.h4
-rw-r--r--lib/memtypes.c4
-rw-r--r--lib/network.c18
-rw-r--r--lib/network.h3
-rw-r--r--lib/nexthop.h2
-rw-r--r--lib/plist.c5
-rw-r--r--lib/prefix.c114
-rw-r--r--lib/prefix.h43
-rw-r--r--lib/privs.c7
-rw-r--r--lib/routemap.c4
-rw-r--r--lib/sigevent.c2
-rw-r--r--lib/sockopt.c35
-rw-r--r--lib/sockopt.h11
-rw-r--r--lib/sockunion.c2
-rw-r--r--lib/sockunion.h3
-rw-r--r--lib/str.c42
-rw-r--r--lib/stream.c44
-rw-r--r--lib/stream.h6
-rw-r--r--lib/zclient.c218
-rw-r--r--lib/zclient.h13
-rw-r--r--lib/zebra.h21
-rw-r--r--ospf6d/ospf6_asbr.c5
-rw-r--r--ospf6d/ospf6_asbr.h6
-rw-r--r--ospf6d/ospf6_interface.c2
-rw-r--r--ospf6d/ospf6_interface.h2
-rw-r--r--ospf6d/ospf6_message.c4
-rw-r--r--ospf6d/ospf6_message.h2
-rw-r--r--ospf6d/ospf6_neighbor.h2
-rw-r--r--ospf6d/ospf6_network.c20
-rw-r--r--ospf6d/ospf6_network.h6
-rw-r--r--ospf6d/ospf6_route.c2
-rw-r--r--ospf6d/ospf6_route.h4
-rw-r--r--ospf6d/ospf6_snmp.c12
-rw-r--r--ospf6d/ospf6_spf.c2
-rw-r--r--ospf6d/ospf6_zebra.c4
-rw-r--r--ospfd/Makefile.am6
-rw-r--r--ospfd/ospf_api.c3
-rw-r--r--ospfd/ospf_apiserver.c3
-rw-r--r--ospfd/ospf_asbr.c2
-rw-r--r--ospfd/ospf_asbr.h4
-rw-r--r--ospfd/ospf_dump.c41
-rw-r--r--ospfd/ospf_dump.h4
-rw-r--r--ospfd/ospf_flood.c28
-rw-r--r--ospfd/ospf_interface.c8
-rw-r--r--ospfd/ospf_interface.h4
-rw-r--r--ospfd/ospf_ism.c2
-rw-r--r--ospfd/ospf_lsa.c32
-rw-r--r--ospfd/ospf_lsa.h8
-rw-r--r--ospfd/ospf_main.c2
-rw-r--r--ospfd/ospf_neighbor.c2
-rw-r--r--ospfd/ospf_neighbor.h2
-rw-r--r--ospfd/ospf_network.c22
-rw-r--r--ospfd/ospf_network.h10
-rw-r--r--ospfd/ospf_nsm.c10
-rw-r--r--ospfd/ospf_opaque.c57
-rw-r--r--ospfd/ospf_opaque.h8
-rw-r--r--ospfd/ospf_packet.c30
-rw-r--r--ospfd/ospf_ri.c1639
-rw-r--r--ospfd/ospf_ri.h191
-rw-r--r--ospfd/ospf_route.h2
-rw-r--r--ospfd/ospf_snmp.c30
-rw-r--r--ospfd/ospf_te.c1917
-rw-r--r--ospfd/ospf_te.h319
-rw-r--r--ospfd/ospf_vty.c41
-rw-r--r--ospfd/ospf_vty.h1
-rw-r--r--ospfd/ospf_zebra.c40
-rw-r--r--ospfd/ospfd.c18
-rw-r--r--ospfd/ospfd.h13
-rw-r--r--pimd/pim_cmd.c20
-rw-r--r--pimd/pim_iface.c31
-rw-r--r--pimd/pim_iface.h6
-rw-r--r--pimd/pim_igmp.c8
-rw-r--r--pimd/pim_igmp_join.h2
-rw-r--r--pimd/pim_mroute.c9
-rw-r--r--pimd/pim_pim.c4
-rw-r--r--pimd/pim_sock.c12
-rw-r--r--pimd/pim_sock.h6
-rw-r--r--pimd/pim_ssmpingd.c2
-rw-r--r--pimd/pim_static.c8
-rw-r--r--pimd/pim_static.h2
-rw-r--r--pimd/pim_zebra.c8
-rw-r--r--pimd/pim_zlookup.c8
-rw-r--r--pimd/pim_zlookup.h2
-rw-r--r--pimd/test_igmpv3_join.c7
-rw-r--r--ripd/rip_interface.c14
-rw-r--r--ripd/ripd.c8
-rw-r--r--ripd/ripd.h8
-rw-r--r--ripngd/ripng_zebra.c2
-rw-r--r--ripngd/ripngd.c8
-rw-r--r--ripngd/ripngd.h6
-rw-r--r--tests/aspath_test.c1
-rw-r--r--tests/bgp_capability_test.c1
-rw-r--r--tests/bgp_mp_attr_test.c1
-rw-r--r--tests/bgp_mpath_test.c1
-rw-r--r--tests/ecommunity_test.c1
-rwxr-xr-xvtysh/extract.pl.in1
-rw-r--r--vtysh/vtysh.c26
-rw-r--r--vtysh/vtysh_user.c6
-rw-r--r--zebra/Makefile.am6
-rw-r--r--zebra/connected.c59
-rw-r--r--zebra/if_ioctl.c2
-rw-r--r--zebra/interface.c839
-rw-r--r--zebra/interface.h10
-rw-r--r--zebra/kernel_null.c2
-rw-r--r--zebra/kernel_socket.c94
-rw-r--r--zebra/main.c2
-rw-r--r--zebra/redistribute.c103
-rw-r--r--zebra/redistribute.h1
-rw-r--r--zebra/redistribute_null.c4
-rw-r--r--zebra/rib.h136
-rw-r--r--zebra/rt.h1
-rw-r--r--zebra/rt_netlink.c179
-rw-r--r--zebra/rt_netlink.h3
-rw-r--r--zebra/rt_socket.c11
-rw-r--r--zebra/rtadv.c30
-rw-r--r--zebra/rtread_getmsg.c32
-rw-r--r--zebra/test_main.c2
-rw-r--r--zebra/zebra_ptm.c5
-rw-r--r--zebra/zebra_rib.c1237
-rw-r--r--zebra/zebra_rnh.c12
-rw-r--r--zebra/zebra_routemap.c2
-rw-r--r--zebra/zebra_static.c480
-rw-r--r--zebra/zebra_static.h89
-rw-r--r--zebra/zebra_vrf.c1
-rw-r--r--zebra/zebra_vty.c25
-rw-r--r--zebra/zserv.c257
-rw-r--r--zebra/zserv.h2
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 */
diff --git a/lib/bfd.c b/lib/bfd.c
index 2116fa5c1f..67a84c95f9 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -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
{
diff --git a/lib/if.c b/lib/if.c
index 8f1461326f..e44882a43e 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -205,6 +205,8 @@ if_delete (struct interface *ifp)
list_free (ifp->connected);
list_free (ifp->nbr_connected);
+ if_link_params_free (ifp);
+
XFREE (MTYPE_IF, ifp);
}
@@ -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;
+}
diff --git a/lib/if.h b/lib/if.h
index 4ec85bc841..17f8565595 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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;
diff --git a/lib/log.c b/lib/log.c
index 453a611dcd..ea50ae18cc 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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 *);
diff --git a/lib/str.c b/lib/str.c
index d8f039a094..16f759c074 100644
--- a/lib/str.c
+++ b/lib/str.c
@@ -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);