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.h7
-rw-r--r--bgpd/bgp_bfd.c7
-rw-r--r--bgpd/bgp_bfd.h3
-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.c61
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_dump.c36
-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.c46
-rw-r--r--bgpd/bgp_mpath.c39
-rw-r--r--bgpd/bgp_mplsvpn.c5
-rw-r--r--bgpd/bgp_network.c26
-rw-r--r--bgpd/bgp_nexthop.c7
-rw-r--r--bgpd/bgp_nht.c34
-rw-r--r--bgpd/bgp_open.c11
-rw-r--r--bgpd/bgp_packet.c5
-rw-r--r--bgpd/bgp_regex.c1
-rw-r--r--bgpd/bgp_route.c201
-rw-r--r--bgpd/bgp_routemap.c98
-rw-r--r--bgpd/bgp_snmp.c9
-rw-r--r--bgpd/bgp_table.c1
-rw-r--r--bgpd/bgp_table.h46
-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.c405
-rw-r--r--bgpd/bgp_zebra.c119
-rw-r--r--bgpd/bgp_zebra.h4
-rw-r--r--bgpd/bgpd.c190
-rw-r--r--bgpd/bgpd.h22
-rwxr-xr-xconfigure.ac119
-rw-r--r--cumulus/etc/quagga/Quagga.conf2
-rw-r--r--cumulus/etc/quagga/bgpd.conf3
-rw-r--r--cumulus/etc/quagga/ospf6d.conf3
-rw-r--r--cumulus/etc/quagga/ospfd.conf3
-rw-r--r--cumulus/etc/quagga/pimd.conf5
-rw-r--r--cumulus/etc/quagga/zebra.conf2
-rw-r--r--cumulus/start-stop-daemon.c7
-rw-r--r--debian/changelog10
-rw-r--r--debian/quagga.install1
-rwxr-xr-xdebian/rules3
-rw-r--r--doc/.gitignore1
-rw-r--r--doc/bgpd.85
-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.am5
-rw-r--r--isisd/isis_circuit.c1710
-rw-r--r--isisd/isis_circuit.h21
-rw-r--r--isisd/isis_events.c115
-rw-r--r--isisd/isis_events.h5
-rw-r--r--isisd/isis_lsp.c102
-rw-r--r--isisd/isis_lsp.h2
-rw-r--r--isisd/isis_main.c7
-rw-r--r--isisd/isis_pdu.c10
-rw-r--r--isisd/isis_redist.h1
-rw-r--r--isisd/isis_route.c10
-rw-r--r--isisd/isis_route.h4
-rw-r--r--isisd/isis_spf.c4
-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_vty.c2428
-rw-r--r--isisd/isis_zebra.c38
-rw-r--r--isisd/isisd.c1367
-rw-r--r--isisd/isisd.h27
-rw-r--r--lib/.gitignore1
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/agentx.c106
-rw-r--r--lib/bfd.c4
-rw-r--r--lib/command.c48
-rw-r--r--lib/command.h6
-rw-r--r--lib/filter.h5
-rw-r--r--lib/if.c130
-rw-r--r--lib/if.h163
-rw-r--r--lib/linklist.c87
-rw-r--r--lib/linklist.h5
-rw-r--r--lib/log.c4
-rw-r--r--lib/memory.c14
-rw-r--r--lib/memory.h4
-rw-r--r--lib/memtypes.c7
-rw-r--r--lib/network.c18
-rw-r--r--lib/network.h3
-rw-r--r--lib/nexthop.c33
-rw-r--r--lib/nexthop.h6
-rw-r--r--lib/ns.c734
-rw-r--r--lib/ns.h142
-rw-r--r--lib/plist.c5
-rw-r--r--lib/prefix.c116
-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.c121
-rw-r--r--lib/stream.h10
-rw-r--r--lib/thread.c141
-rw-r--r--lib/thread.h11
-rw-r--r--lib/vty.h2
-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_bfd.c3
-rw-r--r--ospf6d/ospf6_interface.c2
-rw-r--r--ospf6d/ospf6_interface.h2
-rw-r--r--ospf6d/ospf6_lsa.c8
-rw-r--r--ospf6d/ospf6_main.c4
-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.c26
-rw-r--r--ospf6d/ospf6_spf.c2
-rw-r--r--ospf6d/ospf6_zebra.c8
-rw-r--r--ospfclient/.gitignore2
-rw-r--r--ospfclient/ospf_apiclient.h2
-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_bfd.c3
-rw-r--r--ospfd/ospf_dump.c42
-rw-r--r--ospfd/ospf_dump.h4
-rw-r--r--ospfd/ospf_flood.c28
-rw-r--r--ospfd/ospf_interface.c12
-rw-r--r--ospfd/ospf_interface.h4
-rw-r--r--ospfd/ospf_ism.c2
-rw-r--r--ospfd/ospf_lsa.c38
-rw-r--r--ospfd/ospf_lsa.h8
-rw-r--r--ospfd/ospf_main.c6
-rw-r--r--ospfd/ospf_neighbor.c10
-rw-r--r--ospfd/ospf_neighbor.h6
-rw-r--r--ospfd/ospf_network.c22
-rw-r--r--ospfd/ospf_network.h10
-rw-r--r--ospfd/ospf_nsm.c12
-rw-r--r--ospfd/ospf_opaque.c63
-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.c2
-rw-r--r--ospfd/ospf_route.h8
-rw-r--r--ospfd/ospf_snmp.c52
-rw-r--r--ospfd/ospf_te.c1917
-rw-r--r--ospfd/ospf_te.h319
-rw-r--r--ospfd/ospf_vty.c156
-rw-r--r--ospfd/ospf_vty.h1
-rw-r--r--ospfd/ospf_zebra.c44
-rw-r--r--ospfd/ospfd.c31
-rw-r--r--ospfd/ospfd.h16
-rw-r--r--pimd/Makefile.am6
-rw-r--r--pimd/pim_assert.c8
-rw-r--r--pimd/pim_cmd.c106
-rw-r--r--pimd/pim_iface.c18
-rw-r--r--pimd/pim_iface.h6
-rw-r--r--pimd/pim_igmp.c16
-rw-r--r--pimd/pim_igmp.h2
-rw-r--r--pimd/pim_igmp_join.c71
-rw-r--r--pimd/pim_igmp_join.h46
-rw-r--r--pimd/pim_igmpv3.c25
-rw-r--r--pimd/pim_join.c39
-rw-r--r--pimd/pim_main.c4
-rw-r--r--pimd/pim_mroute.c72
-rw-r--r--pimd/pim_mroute.h5
-rw-r--r--pimd/pim_oil.c3
-rw-r--r--pimd/pim_oil.h13
-rw-r--r--pimd/pim_pim.c4
-rw-r--r--pimd/pim_register.h1
-rw-r--r--pimd/pim_routemap.c47
-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.c66
-rw-r--r--pimd/pim_static.h6
-rw-r--r--pimd/pim_tlv.c173
-rw-r--r--pimd/pim_tlv.h18
-rw-r--r--pimd/pim_upstream.c29
-rw-r--r--pimd/pim_vty.c1
-rw-r--r--pimd/pim_zebra.c39
-rw-r--r--pimd/pim_zlookup.c8
-rw-r--r--pimd/pim_zlookup.h2
-rw-r--r--pimd/pimd.c2
-rw-r--r--pimd/pimd.h2
-rw-r--r--pimd/test_igmpv3_join.c9
-rw-r--r--redhat/quagga.spec.in2
-rw-r--r--ripd/rip_interface.c14
-rw-r--r--ripd/rip_main.c4
-rw-r--r--ripd/rip_snmp.c6
-rw-r--r--ripd/ripd.c8
-rw-r--r--ripd/ripd.h8
-rw-r--r--ripngd/ripng_main.c4
-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
-rw-r--r--tests/testcli.refout2
-rwxr-xr-xtools/quagga-reload.py140
-rw-r--r--vtysh/Makefile.am38
-rwxr-xr-xvtysh/extract.pl.in10
-rw-r--r--vtysh/vtysh.c117
-rw-r--r--vtysh/vtysh.h1
-rw-r--r--vtysh/vtysh_config.c16
-rw-r--r--vtysh/vtysh_main.c9
-rw-r--r--vtysh/vtysh_user.c8
-rw-r--r--watchquagga/watchquagga.c2
-rw-r--r--zebra/Makefile.am6
-rw-r--r--zebra/connected.c59
-rw-r--r--zebra/if_ioctl.c2
-rw-r--r--zebra/interface.c845
-rw-r--r--zebra/interface.h10
-rw-r--r--zebra/kernel_null.c5
-rw-r--r--zebra/kernel_socket.c94
-rw-r--r--zebra/main.c6
-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.h6
-rw-r--r--zebra/rt_ioctl.c110
-rw-r--r--zebra/rt_netlink.c181
-rw-r--r--zebra/rt_netlink.h3
-rw-r--r--zebra/rt_socket.c11
-rw-r--r--zebra/rtadv.c54
-rw-r--r--zebra/rtread_getmsg.c32
-rw-r--r--zebra/test_main.c2
-rw-r--r--zebra/zebra_ns.c3
-rw-r--r--zebra/zebra_ns.h5
-rw-r--r--zebra/zebra_ptm.c37
-rw-r--r--zebra/zebra_ptm.h5
-rw-r--r--zebra/zebra_rib.c1334
-rw-r--r--zebra/zebra_rnh.c27
-rw-r--r--zebra/zebra_routemap.c2
-rw-r--r--zebra/zebra_snmp.c5
-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.c383
-rw-r--r--zebra/zserv.c277
-rw-r--r--zebra/zserv.h2
266 files changed, 15503 insertions, 7198 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 1117f6269d..0bf8c897de 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -99,6 +99,9 @@ struct attr_extra
/* MP Nexthop length */
u_char mp_nexthop_len;
+ /* MP Nexthop preference */
+ u_char mp_nexthop_prefer_global;
+
/* route tag */
u_short tag;
@@ -128,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;
@@ -145,6 +148,7 @@ struct attr
#define BATTR_RMAP_NEXTHOP_UNCHANGED (1 << 3)
#define BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED (1 << 4)
#define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5)
+#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
/* Router Reflector related structure. */
struct cluster_list
@@ -274,6 +278,7 @@ bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) ||
+ CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) ||
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0);
}
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index b64fbee04d..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"
@@ -71,7 +73,7 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
/*
* bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop.
*/
-static int
+int
bgp_bfd_is_peer_multihop(struct peer *peer)
{
struct bfd_info *bfd_info;
@@ -711,7 +713,4 @@ bgp_bfd_init(void)
install_element (BGP_NODE, &no_neighbor_bfd_cmd);
install_element (BGP_NODE, &no_neighbor_bfd_val_cmd);
install_element (BGP_NODE, &no_neighbor_bfd_type_cmd);
-
- /* Send the client registration */
- bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
}
diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h
index 4e554af696..e872637e3e 100644
--- a/bgpd/bgp_bfd.h
+++ b/bgpd/bgp_bfd.h
@@ -42,4 +42,7 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr);
extern void
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh);
+extern int
+bgp_bfd_is_peer_multihop(struct peer *peer);
+
#endif /* _QUAGGA_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 a3d420f691..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;
}
@@ -1663,7 +1711,7 @@ bgp_config_write_debug (struct vty *vty)
if (CONF_BGP_DEBUG (keepalive, KEEPALIVE))
{
- write += bgp_debug_list_conf_print (vty, "debug bgp keepalive",
+ write += bgp_debug_list_conf_print (vty, "debug bgp keepalives",
bgp_debug_keepalive_peers);
}
@@ -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 ea292f5931..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"
@@ -771,15 +771,41 @@ DEFUN (dump_bgp_all,
DEFUN (no_dump_bgp_all,
no_dump_bgp_all_cmd,
- "no dump bgp (all|updates|routes-mrt) [PATH] [INTERVAL]",
+ "no dump bgp (all|all-et|updates|updates-et|routes-mrt) [PATH] [INTERVAL]",
NO_STR
"Stop dump packet\n"
"Stop BGP packet dump\n"
- "Stop dump process all/all-et\n"
- "Stop dump process updates/updates-et\n"
+ "Stop dump process all\n"
+ "Stop dump process all-et\n"
+ "Stop dump process updates\n"
+ "Stop dump process updates-et\n"
"Stop dump process route-mrt\n")
{
- return bgp_dump_unset (vty, &bgp_dump_all);
+ int bgp_dump_type = 0;
+ const struct bgp_dump_type_map *map = NULL;
+ struct bgp_dump *bgp_dump_struct = NULL;
+
+ for (map = bgp_dump_type_map; map->str; map++)
+ if (strcmp(argv[0], map->str) == 0)
+ bgp_dump_type = map->type;
+
+ switch (bgp_dump_type)
+ {
+ case BGP_DUMP_ALL:
+ case BGP_DUMP_ALL_ET:
+ bgp_dump_struct = &bgp_dump_all;
+ break;
+ case BGP_DUMP_UPDATES:
+ case BGP_DUMP_UPDATES_ET:
+ bgp_dump_struct = &bgp_dump_updates;
+ break;
+ case BGP_DUMP_ROUTES:
+ default:
+ bgp_dump_struct = &bgp_dump_routes;
+ break;
+ }
+
+ return bgp_dump_unset (vty, bgp_dump_struct);
}
/* BGP node structure. */
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 1f2f7f86ce..5ef8154faf 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -68,6 +68,7 @@ static const struct option longopts[] =
{ "no_kernel", no_argument, NULL, 'n'},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
+ { "skip_runas", no_argument, NULL, 'S'},
{ "version", no_argument, NULL, 'v'},
{ "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
@@ -163,6 +164,7 @@ redistribution between different routing protocols.\n\n\
-n, --no_kernel Do not install route to kernel.\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
+-S, --skip_runas Skip user and group run as\n\
-v, --version Print program version\n\
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
@@ -200,9 +202,12 @@ sigint (void)
zlog_notice ("Terminating on signal");
if (! retain_mode)
- bgp_terminate ();
+ {
+ bgp_terminate ();
+ if (bgpd_privs.user) /* NULL if skip_runas flag set */
+ zprivs_terminate (&bgpd_privs);
+ }
- zprivs_terminate (&bgpd_privs);
bgp_exit (0);
exit (0);
@@ -227,7 +232,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 +281,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)
@@ -317,6 +321,7 @@ bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
{
struct vrf *vrf;
struct bgp *bgp;
+ vrf_id_t old_vrf_id;
vrf = vrf_lookup (vrf_id);
if (!vrf) // unexpected
@@ -328,8 +333,13 @@ bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
bgp = bgp_lookup_by_name(name);
if (bgp)
{
+ old_vrf_id = bgp->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
bgp_vrf_link (bgp, vrf);
+
+ /* Update any redistribute vrf bitmaps if the vrf_id changed */
+ if (old_vrf_id != bgp->vrf_id)
+ bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_up (bgp);
}
@@ -341,6 +351,7 @@ bgp_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
{
struct vrf *vrf;
struct bgp *bgp;
+ vrf_id_t old_vrf_id;
if (vrf_id == VRF_DEFAULT)
return 0;
@@ -355,8 +366,12 @@ bgp_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
bgp = bgp_lookup_by_name(name);
if (bgp)
{
+ old_vrf_id = bgp->vrf_id;
/* We have instance configured, unlink from VRF and make it "down". */
bgp_vrf_unlink (bgp, vrf);
+ /* Update any redistribute vrf bitmaps if the vrf_id changed */
+ if (old_vrf_id != bgp->vrf_id)
+ bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_down (bgp);
}
@@ -398,6 +413,7 @@ main (int argc, char **argv)
char *progname;
struct thread thread;
int tmp_port;
+ int skip_runas = 0;
/* Set umask before anything for security */
umask (0027);
@@ -405,18 +421,13 @@ main (int argc, char **argv)
/* Preserve name of myself. */
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
- zlog_default = openzlog (progname, ZLOG_BGP, 0,
- LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
- zprivs_init (&bgpd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
-
/* BGP master init. */
bgp_master_init ();
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vC", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vCS", longopts, 0);
if (opt == EOF)
break;
@@ -474,6 +485,9 @@ main (int argc, char **argv)
case 'g':
bgpd_privs.group = optarg;
break;
+ case 'S': /* skip run as = override bgpd_privs */
+ skip_runas = 1;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -490,6 +504,16 @@ main (int argc, char **argv)
}
}
+ zlog_default = openzlog (progname, ZLOG_BGP, 0,
+ LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+
+ if (skip_runas)
+ memset (&bgpd_privs, 0, sizeof (bgpd_privs));
+ zprivs_init (&bgpd_privs);
+
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* Initializations. */
srandom (time (NULL));
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 8397177f8f..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"
@@ -467,6 +468,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
bgp_info_mpath_dequeue (old_best);
}
+ if (debug)
+ zlog_debug("%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d",
+ pfx_buf, new_best ? new_best->peer->host : "NONE",
+ listcount (mp_list), old_mpath_count);
+
/*
* We perform an ordered walk through both lists in parallel.
* The reason for the ordered walk is that if there are paths
@@ -480,6 +486,8 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
*/
while (mp_node || cur_mpath)
{
+ struct bgp_info *tmp_info;
+
/*
* We can bail out of this loop if all existing paths on the
* multipath list have been visited (for cleanup purposes) and
@@ -490,6 +498,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
mp_next_node = mp_node ? listnextnode (mp_node) : NULL;
next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL;
+ tmp_info = mp_node ? listgetdata (mp_node) : NULL;
+
+ if (debug)
+ zlog_debug("%s: comparing candidate %s with existing mpath %s",
+ pfx_buf, tmp_info ? tmp_info->peer->host : "NONE",
+ cur_mpath ? cur_mpath->peer->host : "NONE");
/*
* If equal, the path was a multipath and is still a multipath.
@@ -505,6 +519,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
bgp_info_mpath_enqueue (prev_mpath, cur_mpath);
prev_mpath = cur_mpath;
mpath_count++;
+ if (debug)
+ {
+ bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf);
+ zlog_debug("%s: %s is still multipath, cur count %d",
+ pfx_buf, path_buf, mpath_count);
+ }
}
else
{
@@ -512,10 +532,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (debug)
{
bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf);
- zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf,
+ zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d",
+ pfx_buf, path_buf,
inet_ntop (AF_INET, &cur_mpath->attr->nexthop,
nh_buf[0], sizeof (nh_buf[0])),
- path_buf);
+ mpath_count);
}
}
mp_node = mp_next_node;
@@ -538,10 +559,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (debug)
{
bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf);
- zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf,
+ zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d",
+ pfx_buf, path_buf,
inet_ntop (AF_INET, &cur_mpath->attr->nexthop,
nh_buf[0], sizeof (nh_buf[0])),
- path_buf);
+ mpath_count);
}
cur_mpath = next_mpath;
}
@@ -574,10 +596,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (debug)
{
bgp_info_path_with_addpath_rx_str(new_mpath, path_buf);
- zlog_debug ("%s add mpath nexthop %s %s", pfx_buf,
+ zlog_debug ("%s: add mpath %s nexthop %s, cur count %d",
+ pfx_buf, path_buf,
inet_ntop (AF_INET, &new_mpath->attr->nexthop,
nh_buf[0], sizeof (nh_buf[0])),
- path_buf);
+ mpath_count);
}
}
mp_node = mp_next_node;
@@ -586,6 +609,10 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (new_best)
{
+ if (debug)
+ zlog_debug("%s: New mpath count (incl newbest) %d mpath-change %s",
+ pfx_buf, mpath_count, mpath_changed ? "YES" : "NO");
+
bgp_info_mpath_count_set (new_best, mpath_count-1);
if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count))
SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG);
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..a6e9b7de00 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,13 +253,18 @@ 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;
+#endif
}
if (!strlen(name))
- return 0; /* default instance. */
+ {
+ *bgp_inst = bgp_get_default ();
+ return 0; /* default instance. */
+ }
/* First try match to instance; if that fails, check for interfaces. */
bgp = bgp_lookup_by_name (name);
@@ -275,6 +294,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 +586,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 +676,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 80495065b0..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"
@@ -236,6 +237,7 @@ bgp_connected_add (struct bgp *bgp, struct connected *ifc)
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
+ peer->status != Established &&
!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
{
if (peer_active(peer))
@@ -562,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 9d8d8f3b52..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"
@@ -370,8 +371,8 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
{
char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof (buf));
- zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
- metric, nexthop_num);
+ zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)",
+ vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num);
}
if (metric != bnc->metric)
@@ -396,30 +397,35 @@ 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;
}
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[NEXTHOP_STRLEN];
+ zlog_debug(" nhop via %s",
+ nexthop2str (nexthop, buf, sizeof (buf)));
+ }
+
if (nhlist_tail)
{
nhlist_tail->next = nexthop;
@@ -642,6 +648,14 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
int afi;
struct peer *peer = (struct peer *)bnc->nht_info;
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[PREFIX2STR_BUFFER];
+ bnc_str(bnc, buf, PREFIX2STR_BUFFER);
+ zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
+ buf, bnc->flags, bnc->change_flags);
+ }
+
LIST_FOREACH(path, &(bnc->paths), nh_thread)
{
if (!(path->type == ZEBRA_ROUTE_BGP &&
@@ -681,8 +695,6 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ||
CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
- else
- UNSET_FLAG (path->flags, BGP_INFO_IGP_CHANGED);
bgp_process(bgp, rn, afi, SAFI_UNICAST);
}
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..2f9fdd5a75 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"
@@ -1162,10 +1163,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
if (!peer->nexthop.v4.s_addr)
{
+#if !defined (HAVE_BGP_STANDALONE)
zlog_err ("%s: No local IPv4 addr resetting connection, fd %d",
peer->host, peer->fd);
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return -1;
+#endif
}
}
if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] ||
@@ -1175,10 +1178,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global))
{
+#if !defined (HAVE_BGP_STANDALONE)
zlog_err ("%s: No local IPv6 addr resetting connection, fd %d",
peer->host, peer->fd);
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return -1;
+#endif
}
}
peer->rtt = sockopt_tcp_rtt (peer->fd);
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 fff595d190..7295ff147f 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -376,7 +376,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
}
if (debug)
- bgp_info_path_with_addpath_rx_str (exist, exist_buf);
+ {
+ bgp_info_path_with_addpath_rx_str (exist, exist_buf);
+ zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
+ pfx_buf, new_buf, new->flags, exist_buf, exist->flags);
+ }
newattr = new->attr;
existattr = exist->attr;
@@ -705,6 +709,15 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
* TODO: If unequal cost ibgp multipath is enabled we can
* mark the paths as equal here instead of returning
*/
+ if (debug)
+ {
+ if (ret == 1)
+ zlog_debug("%s: %s wins over %s after IGP metric comparison",
+ pfx_buf, new_buf, exist_buf);
+ else
+ zlog_debug("%s: %s loses to %s after IGP metric comparison",
+ pfx_buf, new_buf, exist_buf);
+ }
return ret;
}
@@ -1638,14 +1651,19 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
/* Now that we know which path is the bestpath see if any of the other paths
* qualify as multipaths
*/
- if (do_mpath && new_select)
+ if (debug)
{
- if (debug)
- {
- bgp_info_path_with_addpath_rx_str (new_select, path_buf);
- zlog_debug("%s: %s is the bestpath, now find multipaths", pfx_buf, path_buf);
- }
+ if (new_select)
+ bgp_info_path_with_addpath_rx_str (new_select, path_buf);
+ else
+ sprintf (path_buf, "NONE");
+ zlog_debug("%s: After path selection, newbest is %s oldbest was %s",
+ pfx_buf, path_buf,
+ old_select ? old_select->peer->host : "NONE");
+ }
+ if (do_mpath && new_select)
+ {
for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri)
{
@@ -1657,7 +1675,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
if (debug)
zlog_debug("%s: %s is the bestpath, add to the multipath list",
pfx_buf, path_buf);
- bgp_mp_list_add (&mp_list, ri);
+ bgp_mp_list_add (&mp_list, ri);
continue;
}
@@ -1749,6 +1767,57 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp,
return 0;
}
+/*
+ * Clear IGP changed flag and attribute changed flag for a route (all paths).
+ * This is called at the end of route processing.
+ */
+static void
+bgp_zebra_clear_route_change_flags (struct bgp_node *rn)
+{
+ struct bgp_info *ri;
+
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ if (BGP_INFO_HOLDDOWN (ri))
+ continue;
+ UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED);
+ UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ }
+}
+
+/*
+ * Has the route changed from the RIB's perspective? This is invoked only
+ * if the route selection returns the same best route as earlier - to
+ * determine if we need to update zebra or not.
+ */
+static int
+bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected)
+{
+ struct bgp_info *mpinfo;
+
+ /* If this is multipath, check all selected paths for any nexthop change or
+ * attribute change. Some attribute changes (e.g., community) aren't of
+ * relevance to the RIB, but we'll update zebra to ensure we handle the
+ * case of BGP nexthop change. This is the behavior when the best path has
+ * an attribute change anyway.
+ */
+ if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) ||
+ CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG))
+ return 1;
+
+ /* If this is multipath, check all selected paths for any nexthop change */
+ for (mpinfo = bgp_info_mpath_first (selected); mpinfo;
+ mpinfo = bgp_info_mpath_next (mpinfo))
+ {
+ if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED)
+ || CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED))
+ return 1;
+ }
+
+ /* Nothing has changed from the RIB's perspective. */
+ return 0;
+}
+
struct bgp_process_queue
{
struct bgp *bgp;
@@ -1799,11 +1868,11 @@ bgp_process_main (struct work_queue *wq, void *data)
!CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) &&
!bgp->addpath_tx_used[afi][safi])
{
- if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) ||
- CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG))
+ if (bgp_zebra_has_route_changed (rn, old_select))
bgp_zebra_announce (p, old_select, bgp, afi, safi);
UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
+ bgp_zebra_clear_route_change_flags (rn);
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
return WQ_SUCCESS;
}
@@ -1856,7 +1925,10 @@ bgp_process_main (struct work_queue *wq, void *data)
bgp_zebra_withdraw (p, old_select, safi);
}
}
-
+
+ /* Clear any route change flags. */
+ bgp_zebra_clear_route_change_flags (rn);
+
/* Reap old select bgp_info, if it has been removed */
if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
bgp_info_reap (rn, old_select);
@@ -5873,7 +5945,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
}
}
-#ifdef HAVE_IPV6
+
/* IPv6 Next Hop */
else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
{
@@ -5901,8 +5973,9 @@ route_vty_out (struct vty *vty, struct prefix *p,
json_object_string_add(json_nexthop_ll, "afi", "ipv6");
json_object_string_add(json_nexthop_ll, "scope", "link-local");
- if (IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global,
- &attr->extra->mp_nexthop_local) != 0)
+ if ((IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global,
+ &attr->extra->mp_nexthop_local) != 0) &&
+ !attr->extra->mp_nexthop_prefer_global)
json_object_boolean_true_add(json_nexthop_ll, "used");
else
json_object_boolean_true_add(json_nexthop_global, "used");
@@ -5912,7 +5985,10 @@ route_vty_out (struct vty *vty, struct prefix *p,
}
else
{
- if ((attr->extra->mp_nexthop_len == 32) || (binfo->peer->conf_if))
+ /* Display LL if LL/Global both in table unless prefer-global is set */
+ if (((attr->extra->mp_nexthop_len == 32) &&
+ !attr->extra->mp_nexthop_prefer_global) ||
+ (binfo->peer->conf_if))
{
if (binfo->peer->conf_if)
{
@@ -5954,7 +6030,6 @@ route_vty_out (struct vty *vty, struct prefix *p,
}
}
}
-#endif /* HAVE_IPV6 */
/* MED/Metric */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
@@ -6635,7 +6710,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (json_paths)
json_object_string_add(json_nexthop_global, "afi", "ipv4");
}
-#ifdef HAVE_IPV6
else
{
assert (attr->extra);
@@ -6654,8 +6728,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
buf, INET6_ADDRSTRLEN));
}
}
-#endif /* HAVE_IPV6 */
-
/* Display the IGP cost or 'inaccessible' */
if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
@@ -6761,7 +6833,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (!json_paths)
vty_out (vty, "%s", VTY_NEWLINE);
-#ifdef HAVE_IPV6
/* display the link-local nexthop */
if (attr->extra && attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{
@@ -6775,13 +6846,19 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
json_object_string_add(json_nexthop_ll, "scope", "link-local");
json_object_boolean_true_add(json_nexthop_ll, "accessible");
- json_object_boolean_true_add(json_nexthop_ll, "used");
+
+ if (!attr->extra->mp_nexthop_prefer_global)
+ json_object_boolean_true_add(json_nexthop_ll, "used");
+ else
+ json_object_boolean_true_add(json_nexthop_global, "used");
}
else
{
- vty_out (vty, " (%s) (used)%s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
+ vty_out (vty, " (%s) %s%s",
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
buf, INET6_ADDRSTRLEN),
+ attr->extra->mp_nexthop_prefer_global ?
+ "(prefer-global)" : "(used)",
VTY_NEWLINE);
}
}
@@ -6791,7 +6868,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (json_paths)
json_object_boolean_true_add(json_nexthop_global, "used");
}
-#endif /* HAVE_IPV6 */
/* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */
if (json_paths)
@@ -7634,7 +7710,9 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
{
vty_out (vty, ", best #%d", best);
if (safi == SAFI_UNICAST)
- vty_out (vty, ", table Default-IP-Routing-Table");
+ vty_out (vty, ", table %s",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? "Default-IP-Routing-Table" : bgp->name);
}
else
vty_out (vty, ", no best path");
@@ -9304,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,
@@ -14438,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);
@@ -14591,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);
@@ -15000,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 3018d074fc..fea9ae6b18 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -103,6 +103,7 @@ o Cisco route-map
o Local extensions
set ipv6 next-hop global: Done
+ set ipv6 next-hop prefer-global: Done
set ipv6 next-hop local : Done
set as-path exclude : Done
@@ -2192,6 +2193,67 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
route_set_ipv6_nexthop_global_free
};
+/* Set next-hop preference value. */
+static route_map_result_t
+route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_info *bgp_info;
+ struct peer *peer;
+
+ if (type == RMAP_BGP)
+ {
+ /* Fetch routemap's rule information. */
+ bgp_info = object;
+ peer = bgp_info->peer;
+
+ if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
+ CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
+ && peer->su_remote
+ && sockunion_family (peer->su_remote) == AF_INET6)
+ {
+ /* Set next hop preference to global */
+ bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE;
+ SET_FLAG(bgp_info->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
+ }
+ else
+ {
+ bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE;
+ SET_FLAG(bgp_info->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
+ }
+ }
+ return RMAP_OKAY;
+}
+
+static void *
+route_set_ipv6_nexthop_prefer_global_compile (const char *arg)
+{
+ int *rins = NULL;
+
+ rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
+ *rins = 1;
+
+ return rins;
+}
+
+/* Free route map's compiled `ip next-hop' value. */
+static void
+route_set_ipv6_nexthop_prefer_global_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set preferred. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd =
+{
+ "ipv6 next-hop prefer-global",
+ route_set_ipv6_nexthop_prefer_global,
+ route_set_ipv6_nexthop_prefer_global_compile,
+ route_set_ipv6_nexthop_prefer_global_free
+};
+
/* `set ipv6 nexthop local IP_ADDRESS' */
/* Set nexthop to object. ojbect must be pointer to struct attr. */
@@ -2935,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);
@@ -2974,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,
@@ -4366,11 +4428,34 @@ DEFUN (no_set_ipv6_nexthop_peer,
SET_STR
IPV6_STR
"IPv6 next-hop address\n"
- )
+ "Use peer address (for BGP only)\n")
{
return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
}
+DEFUN (set_ipv6_nexthop_prefer_global,
+ set_ipv6_nexthop_prefer_global_cmd,
+ "set ipv6 next-hop prefer-global",
+ SET_STR
+ IPV6_STR
+ "IPv6 next-hop address\n"
+ "Prefer global over link-local if both exist\n")
+{
+ return bgp_route_set_add (vty, vty->index, "ipv6 next-hop prefer-global", NULL);;
+}
+
+DEFUN (no_set_ipv6_nexthop_prefer_global,
+ no_set_ipv6_nexthop_prefer_global_cmd,
+ "no set ipv6 next-hop prefer-global",
+ NO_STR
+ SET_STR
+ IPV6_STR
+ "IPv6 next-hop address\n"
+ "Prefer global over link-local if both exist\n")
+{
+ return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop prefer-global", NULL);
+}
+
DEFUN (set_ipv6_nexthop_global,
set_ipv6_nexthop_global_cmd,
"set ipv6 next-hop global X:X::X:X",
@@ -4704,6 +4789,7 @@ bgp_route_map_init (void)
route_map_install_match (&route_match_ipv6_next_hop_cmd);
route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
+ route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd);
route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
@@ -4716,6 +4802,8 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
+ install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
+ install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index 84a527b96a..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"
@@ -116,8 +117,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
SNMP_LOCAL_VARIABLES
/* BGP-MIB instances. */
-oid bgp_oid [] = { BGP4MIB };
-oid bgp_trap_oid [] = { BGP4MIB, 0 };
+static oid bgp_oid [] = { BGP4MIB };
+static oid bgp_trap_oid [] = { BGP4MIB, 0 };
/* IP address 0.0.0.0. */
static struct in_addr bgp_empty_addr = { .s_addr = 0 };
@@ -137,7 +138,7 @@ static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
/* static u_char *bgpTraps (); */
-struct variable bgp_variables[] =
+static struct variable bgp_variables[] =
{
/* BGP version. */
{BGPVERSION, OCTET_STRING, RONLY, bgpVersion,
@@ -831,7 +832,7 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
}
/* BGP Traps. */
-struct trap_object bgpTrapList[] =
+static struct trap_object bgpTrapList[] =
{
{3, {3, 1, BGPPEERLASTERROR}},
{3, {3, 1, BGPPEERSTATE}}
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 f4e5ec5b89..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)
@@ -113,44 +113,6 @@ bgp_node_table (struct bgp_node *node)
}
/*
- * bgp_node_info
- *
- * Returns the 'info' pointer corresponding to a bgp node.
- */
-static inline void *
-bgp_node_info (const struct bgp_node *node)
-{
- return node->info;
-}
-
-/*
- * bgp_node_set_info
- */
-static inline void
-bgp_node_set_info (struct bgp_node *node, void *info)
-{
- node->info = info;
-}
-
-/*
- * bgp_node_prefix
- */
-static inline struct prefix *
-bgp_node_prefix (struct bgp_node *node)
-{
- return &node->p;
-}
-
-/*
- * bgp_node_prefixlen
- */
-static inline u_char
-bgp_node_prefixlen (struct bgp_node *node)
-{
- return bgp_node_prefix (node)->prefixlen;
-}
-
-/*
* bgp_node_parent_nolock
*
* Gets the parent node of the given node without locking it.
@@ -349,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 5dff63e8c2..c83d751743 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -32,8 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "hash.h"
#include "queue.h"
-#include "if.h"
-#include "vrf.h"
+#include "filter.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_advertise.h"
@@ -64,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
@@ -77,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
@@ -304,6 +324,9 @@ bgp_vty_return (struct vty *vty, int ret)
case BGP_ERR_INVALID_FOR_DYNAMIC_PEER:
str = "Operation not allowed on a dynamic neighbor";
break;
+ case BGP_ERR_INVALID_FOR_DIRECT_PEER:
+ str = "Operation not allowed on a directly connected neighbor";
+ break;
}
if (str)
{
@@ -533,26 +556,22 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi,
/* clear soft inbound */
static void
-bgp_clear_star_soft_in (struct vty *vty)
+bgp_clear_star_soft_in (struct vty *vty, const char *name)
{
- bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+ bgp_clear_vty (vty,name, AFI_IP, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_IN, NULL);
-#ifdef HAVE_IPV6
- bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+ bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_IN, NULL);
-#endif /* HAVE_IPV6 */
}
/* clear soft outbound */
static void
-bgp_clear_star_soft_out (struct vty *vty)
+bgp_clear_star_soft_out (struct vty *vty, const char *name)
{
- bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+ bgp_clear_vty (vty, name, AFI_IP, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_OUT, NULL);
-#ifdef HAVE_IPV6
- bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+ bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_OUT, NULL);
-#endif /* HAVE_IPV6 */
}
@@ -742,17 +761,39 @@ DEFUN (no_router_bgp,
struct bgp *bgp;
const char *name = NULL;
- VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
- if (argc == 3)
- name = argv[2];
+ // "no router bgp" without an ASN
+ if (argc < 1)
+ {
+ //Pending: Make VRF option available for ASN less config
+ bgp = bgp_get_default();
- /* Lookup bgp structure. */
- bgp = bgp_lookup (as, name);
- if (! bgp)
+ if (bgp == NULL)
+ {
+ vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (listcount(bm->bgp) > 1)
+ {
+ vty_out (vty, "%% Multiple BGP processes are configured%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
{
- vty_out (vty, "%% Can't find BGP instance%s", VTY_NEWLINE);
- return CMD_WARNING;
+ VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
+
+ if (argc == 3)
+ name = argv[2];
+
+ /* Lookup bgp structure. */
+ bgp = bgp_lookup (as, name);
+ if (! bgp)
+ {
+ vty_out (vty, "%% Can't find BGP instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
bgp_delete (bgp);
@@ -770,6 +811,13 @@ ALIAS (no_router_bgp,
"BGP view\nBGP VRF\n"
"View/VRF name\n")
+ALIAS (no_router_bgp,
+ no_router_bgp_noasn_cmd,
+ "no router bgp",
+ NO_STR
+ ROUTER_STR
+ BGP_STR)
+
/* BGP router-id. */
DEFUN (bgp_router_id,
@@ -792,11 +840,7 @@ DEFUN (bgp_router_id,
return CMD_WARNING;
}
- if (IPV4_ADDR_SAME (&bgp->router_id_static, &id))
- return CMD_SUCCESS;
-
- bgp->router_id_static = id;
- bgp_router_id_set (bgp, &id);
+ bgp_router_id_static_set (bgp, id);
return CMD_SUCCESS;
}
@@ -811,10 +855,6 @@ DEFUN (no_bgp_router_id,
int ret;
struct in_addr id;
struct bgp *bgp;
- struct interface *ifp;
- struct listnode *node;
- struct connected *ifc;
- struct prefix *p;
bgp = vty->index;
@@ -822,32 +862,20 @@ DEFUN (no_bgp_router_id,
{
ret = inet_aton (argv[0], &id);
if (! ret)
- {
- ifp = if_lookup_by_name_vrf(argv[0], bgp->vrf_id);
- if (!ifp) {
- vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
- {
- p = ifc->address;
- if (p && (p->family == AF_INET))
- {
- id = p->u.prefix4;
- break;
- }
- }
- }
+ {
+ vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (! IPV4_ADDR_SAME (&bgp->router_id_static, &id))
- {
- vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
+ {
+ vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
- bgp->router_id_static.s_addr = 0;
- bgp_router_id_set (bgp, &bgp->router_id_zebra);
+ id.s_addr = 0;
+ bgp_router_id_static_set (bgp, id);
return CMD_SUCCESS;
}
@@ -860,56 +888,6 @@ ALIAS (no_bgp_router_id,
"Override configured router identifier\n"
"Manually configured router identifier\n")
-DEFUN (bgp_router_id_interface,
- bgp_router_id_interface_cmd,
- "bgp router-id IFNAME",
- BGP_STR
- "Override configured router identifier\n"
- "Interface name\n")
-{
- struct bgp *bgp;
- struct interface *ifp;
- struct connected *ifc;
- struct listnode *node;
- struct prefix *p;
- struct vrf *vrf;
-
- bgp = vty->index;
- p = NULL;
-
- ifp = if_lookup_by_name_vrf(argv[0], bgp->vrf_id);
- if (!ifp)
- {
- vrf = vrf_lookup(bgp->vrf_id);
- vty_out (vty, "%% Couldnt find interface %s in VRF %s%s", argv[0], vrf? vrf->name:"", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
- {
- p = ifc->address;
-
- if (p && (p->family == AF_INET))
- {
- if (IPV4_ADDR_SAME (&bgp->router_id_static, &p->u.prefix4))
- return CMD_SUCCESS;
- bgp->router_id_static = p->u.prefix4;
- bgp_router_id_set (bgp, &p->u.prefix4);
- return CMD_SUCCESS;
- }
- }
- vty_out (vty, "%% Couldnt assign the router-id%s", VTY_NEWLINE);
- return CMD_WARNING;
-}
-
-ALIAS (no_bgp_router_id,
- no_bgp_router_id_interface_cmd,
- "no bgp router-id IFNAME",
- NO_STR
- BGP_STR
- "Override configured router identifier\n"
- "Interface name\n")
-
/* BGP Cluster ID. */
DEFUN (bgp_cluster_id,
@@ -933,7 +911,7 @@ DEFUN (bgp_cluster_id,
}
bgp_cluster_id_set (bgp, &cluster);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -969,7 +947,7 @@ DEFUN (no_bgp_cluster_id,
}
bgp_cluster_id_unset (bgp);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -1666,7 +1644,7 @@ DEFUN (bgp_client_to_client_reflection,
bgp = vty->index;
bgp_flag_unset (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -1683,7 +1661,7 @@ DEFUN (no_bgp_client_to_client_reflection,
bgp = vty->index;
bgp_flag_set (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -1838,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",
@@ -1856,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>",
@@ -1865,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,
@@ -1904,7 +1929,7 @@ DEFUN (bgp_enforce_first_as,
bgp = vty->index;
bgp_flag_set (bgp, BGP_FLAG_ENFORCE_FIRST_AS);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -1920,7 +1945,7 @@ DEFUN (no_bgp_enforce_first_as,
bgp = vty->index;
bgp_flag_unset (bgp, BGP_FLAG_ENFORCE_FIRST_AS);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -2338,7 +2363,7 @@ DEFUN (bgp_default_local_preference,
VTY_GET_INTEGER ("local preference", local_pref, argv[0]);
bgp_default_local_preference_set (bgp, local_pref);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -2355,7 +2380,7 @@ DEFUN (no_bgp_default_local_preference,
bgp = vty->index;
bgp_default_local_preference_unset (bgp);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -2428,7 +2453,7 @@ DEFUN (bgp_rr_allow_outbound_policy,
{
bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
update_group_announce_rrclients(bgp);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
}
return CMD_SUCCESS;
@@ -2450,7 +2475,7 @@ DEFUN (no_bgp_rr_allow_outbound_policy,
{
bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
update_group_announce_rrclients(bgp);
- bgp_clear_star_soft_out (vty);
+ bgp_clear_star_soft_out (vty, bgp->name);
}
return CMD_SUCCESS;
@@ -2697,7 +2722,7 @@ DEFUN (bgp_disable_connected_route_check,
bgp = vty->index;
bgp_flag_set (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -2713,7 +2738,7 @@ DEFUN (no_bgp_disable_connected_route_check,
bgp = vty->index;
bgp_flag_unset (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK);
- bgp_clear_star_soft_in (vty);
+ bgp_clear_star_soft_in (vty, bgp->name);
return CMD_SUCCESS;
}
@@ -2802,9 +2827,11 @@ DEFUN (neighbor_remote_as,
static int
peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
- safi_t safi, int v6only, const char *peer_group_name)
+ safi_t safi, int v6only, const char *peer_group_name,
+ const char *as_str)
{
- as_t as;
+ as_t as = 0;
+ int as_type = AS_UNSPECIFIED;
struct bgp *bgp;
struct peer *peer;
struct peer_group *group;
@@ -2820,14 +2847,34 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
return CMD_WARNING;
}
+ if (as_str)
+ {
+ if (strncmp(as_str, "internal", strlen("internal")) == 0)
+ {
+ as_type = AS_INTERNAL;
+ }
+ else if (strncmp(as_str, "external", strlen("external")) == 0)
+ {
+ as_type = AS_EXTERNAL;
+ }
+ else
+ {
+ /* Get AS number. */
+ VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX);
+ as_type = AS_SPECIFIED;
+ }
+ }
+
peer = peer_lookup_by_conf_if (bgp, conf_if);
if (!peer)
{
if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
&& afi == AFI_IP && safi == SAFI_UNICAST)
- peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, 0, 0, NULL);
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, 0, 0,
+ NULL);
else
- peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, afi, safi, NULL);
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, afi, safi,
+ NULL);
if (peer && v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
@@ -2838,7 +2885,10 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
* gets deleted later etc.)
*/
if (peer->ifp)
- bgp_zebra_initiate_radv (bgp, peer);
+ {
+ bgp_zebra_initiate_radv (bgp, peer);
+ }
+ peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
}
else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) ||
(!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)))
@@ -2885,9 +2935,11 @@ DEFUN (neighbor_interface_config,
"Enable BGP on interface\n")
{
if (argc == 2)
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ argv[1], NULL);
else
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ NULL, NULL);
}
ALIAS (neighbor_interface_config,
@@ -2908,9 +2960,11 @@ DEFUN (neighbor_interface_config_v6only,
"Enable BGP with v6 link-local only\n")
{
if (argc == 2)
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ argv[1], NULL);
else
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ NULL, NULL);
}
ALIAS (neighbor_interface_config_v6only,
@@ -2923,6 +2977,30 @@ ALIAS (neighbor_interface_config_v6only,
"Member of the peer-group\n"
"peer-group name\n")
+DEFUN (neighbor_interface_config_remote_as,
+ neighbor_interface_config_remote_as_cmd,
+ "neighbor WORD interface remote-as (" CMD_AS_RANGE "|external|internal)",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ AS_STR)
+{
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ NULL, argv[1]);
+}
+
+DEFUN (neighbor_interface_v6only_config_remote_as,
+ neighbor_interface_v6only_config_remote_as_cmd,
+ "neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|external|internal)",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ AS_STR)
+{
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ NULL, argv[1]);
+}
+
DEFUN (neighbor_peer_group,
neighbor_peer_group_cmd,
"neighbor WORD peer-group",
@@ -3073,6 +3151,24 @@ ALIAS (no_neighbor_interface_config,
"Member of the peer-group\n"
"peer-group name\n")
+ALIAS (no_neighbor_interface_config,
+ no_neighbor_interface_config_remote_as_cmd,
+ "no neighbor WORD interface remote-as (" CMD_AS_RANGE "|internal|external)",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n"
+ AS_STR)
+
+ALIAS (no_neighbor_interface_config,
+ no_neighbor_interface_config_v6only_remote_as_cmd,
+ "no neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|internal|external)",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n"
+ "Enable BGP with v6 link-local only\n"
+ AS_STR)
DEFUN (no_neighbor_peer_group,
no_neighbor_peer_group_cmd,
@@ -4434,6 +4530,9 @@ peer_ebgp_multihop_set_vty (struct vty *vty, const char *ip_str,
if (! peer)
return CMD_WARNING;
+ if (peer->conf_if)
+ return bgp_vty_return (vty, BGP_ERR_INVALID_FOR_DIRECT_PEER);
+
if (! ttl_str)
ttl = MAXTTL;
else
@@ -12982,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;
@@ -13109,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));
@@ -13125,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));
@@ -13139,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));
@@ -13153,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));
@@ -13173,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;
@@ -13220,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;
@@ -13339,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]);
@@ -13361,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]);
@@ -13387,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;
@@ -13408,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]);
@@ -13428,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]);
@@ -13569,7 +13668,7 @@ bgp_show_peer_group (struct vty *vty, struct bgp *bgp,
}
if (type == show_peer_group && ! find)
- vty_out (vty, "%% No such peer-groupr%s", VTY_NEWLINE);
+ vty_out (vty, "%% No such peer-group%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -14376,13 +14475,12 @@ bgp_vty_init (void)
/* "no router bgp" commands. */
install_element (CONFIG_NODE, &no_router_bgp_cmd);
install_element (CONFIG_NODE, &no_router_bgp_instance_cmd);
+ install_element (CONFIG_NODE, &no_router_bgp_noasn_cmd);
/* "bgp router-id" commands. */
install_element (BGP_NODE, &bgp_router_id_cmd);
install_element (BGP_NODE, &no_bgp_router_id_cmd);
install_element (BGP_NODE, &no_bgp_router_id_val_cmd);
- install_element (BGP_NODE, &bgp_router_id_interface_cmd);
- install_element (BGP_NODE, &no_bgp_router_id_interface_cmd);
/* "bgp cluster-id" commands. */
install_element (BGP_NODE, &bgp_cluster_id_cmd);
@@ -14481,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);
@@ -14560,12 +14661,16 @@ bgp_vty_init (void)
install_element (BGP_NODE, &neighbor_interface_config_v6only_cmd);
install_element (BGP_NODE, &neighbor_interface_config_peergroup_cmd);
install_element (BGP_NODE, &neighbor_interface_config_v6only_peergroup_cmd);
+ install_element (BGP_NODE, &neighbor_interface_config_remote_as_cmd);
+ install_element (BGP_NODE, &neighbor_interface_v6only_config_remote_as_cmd);
install_element (BGP_NODE, &no_neighbor_cmd);
install_element (BGP_NODE, &no_neighbor_remote_as_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_v6only_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_peergroup_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_v6only_peergroup_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_config_remote_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_config_v6only_remote_as_cmd);
/* "neighbor peer-group" commands. */
install_element (BGP_NODE, &neighbor_peer_group_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index ceded236cd..c2df521e79 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA. */
#include "queue.h"
#include "memory.h"
#include "lib/json.h"
+#include "lib/bfd.h"
+#include "filter.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h"
@@ -109,8 +111,6 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
vrf_id_t vrf_id)
{
struct prefix router_id;
- struct listnode *node, *nnode;
- struct bgp *bgp;
zebra_router_id_update_read(zclient->ibuf,&router_id);
@@ -121,32 +121,7 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf);
}
- if (vrf_id == VRF_DEFAULT)
- {
- /* Router-id change for default VRF has to also update all views. */
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
- continue;
-
- bgp->router_id_zebra = router_id.u.prefix4;
-
- if (!bgp->router_id_static.s_addr)
- bgp_router_id_set (bgp, &router_id.u.prefix4);
- }
- }
- else
- {
- bgp = bgp_lookup_by_vrf_id (vrf_id);
- if (bgp)
- {
- bgp->router_id_zebra = router_id.u.prefix4;
-
- if (!bgp->router_id_static.s_addr)
- bgp_router_id_set (bgp, &router_id.u.prefix4);
- }
- }
-
+ bgp_router_id_zebra_bump (vrf_id, &router_id);
return 0;
}
@@ -385,7 +360,16 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
+#if defined(HAVE_CUMULUS)
+ /* Take down directly connected EBGP peers as well as 1-hop BFD
+ * tracked (directly connected) IBGP peers.
+ */
+ if ((peer->ttl != 1) && (peer->gtsm_hops != 1) &&
+ (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer)))
+#else
+ /* Take down directly connected EBGP peers */
if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
+#endif
continue;
if (ifp == peer->nexthop.ifp)
@@ -882,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;
@@ -904,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;
@@ -918,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;
@@ -1163,12 +1147,18 @@ bgp_info_to_ipv6_nexthop (struct bgp_info *info)
/* If both global and link-local address present. */
if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{
- /* Workaround for Cisco's nexthop bug. */
- if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
- && info->peer->su_remote->sa.sa_family == AF_INET6)
- nexthop = &info->peer->su_remote->sin6.sin6_addr;
+ /* Check if route-map is set to prefer global over link-local */
+ if (info->attr->extra->mp_nexthop_prefer_global)
+ nexthop = &info->attr->extra->mp_nexthop_global;
else
- nexthop = &info->attr->extra->mp_nexthop_local;
+ {
+ /* Workaround for Cisco's nexthop bug. */
+ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
+ && info->peer->su_remote->sa.sa_family == AF_INET6)
+ nexthop = &info->peer->su_remote->sin6.sin6_addr;
+ else
+ nexthop = &info->attr->extra->mp_nexthop_local;
+ }
}
return nexthop;
@@ -1401,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;
@@ -1547,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;
@@ -1891,16 +1881,30 @@ bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi,
red->redist_metric_flag = 1;
red->redist_metric = metric;
- for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) {
- for (ri = rn->info; ri; ri = ri->next) {
- if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && ri->type == type &&
- ri->instance == red->instance) {
- ri->attr->med = red->redist_metric;
- bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
- bgp_process(bgp, rn, afi, SAFI_UNICAST);
- }
+ for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn))
+ {
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE &&
+ ri->type == type &&
+ ri->instance == red->instance)
+ {
+ struct attr *old_attr;
+ struct attr new_attr;
+ struct attr_extra new_extra;
+
+ new_attr.extra = &new_extra;
+ bgp_attr_dup (&new_attr, ri->attr);
+ new_attr.med = red->redist_metric;
+ old_attr = ri->attr;
+ ri->attr = bgp_attr_intern (&new_attr);
+ bgp_attr_unintern (&old_attr);
+
+ bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
+ bgp_process(bgp, rn, afi, SAFI_UNICAST);
+ }
+ }
}
- }
return 1;
}
@@ -1972,6 +1976,24 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type, u_short instance)
return CMD_SUCCESS;
}
+/* Update redistribute vrf bitmap during triggers like
+ restart networking or delete/add VRFs */
+void
+bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id)
+{
+ int i;
+ afi_t afi;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id))
+ {
+ vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id);
+ vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id);
+ }
+ return;
+}
+
void
bgp_zclient_reset (void)
{
@@ -2057,6 +2079,9 @@ bgp_zebra_connected (struct zclient *zclient)
bgp_zebra_instance_register (bgp);
+ /* Send the client registration */
+ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
/* TODO - What if we have peers and networks configured, do we have to
* kick-start them?
*/
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 243e800a89..bfde53d3e4 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -209,8 +209,8 @@ bgp_config_check (struct bgp *bgp, int config)
}
/* Set BGP router identifier. */
-int
-bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
+static int
+bgp_router_id_set (struct bgp *bgp, const struct in_addr *id)
{
struct peer *peer;
struct listnode *node, *nnode;
@@ -235,6 +235,46 @@ bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
return 0;
}
+void
+bgp_router_id_zebra_bump (vrf_id_t vrf_id, const struct prefix *router_id)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ if (vrf_id == VRF_DEFAULT)
+ {
+ /* Router-id change for default VRF has to also update all views. */
+ for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
+ {
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ bgp->router_id_zebra = router_id->u.prefix4;
+ if (!bgp->router_id_static.s_addr)
+ bgp_router_id_set (bgp, &router_id->u.prefix4);
+ }
+ }
+ else
+ {
+ bgp = bgp_lookup_by_vrf_id (vrf_id);
+ if (bgp)
+ {
+ bgp->router_id_zebra = router_id->u.prefix4;
+
+ if (!bgp->router_id_static.s_addr)
+ bgp_router_id_set (bgp, &router_id->u.prefix4);
+ }
+ }
+}
+
+int
+bgp_router_id_static_set (struct bgp *bgp, struct in_addr id)
+{
+ bgp->router_id_static = id;
+ bgp_router_id_set (bgp, id.s_addr ? &id : &bgp->router_id_zebra);
+ return 0;
+}
+
/* BGP's cluster-id control. */
int
bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
@@ -1255,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
@@ -1269,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;
}
@@ -1827,6 +1867,15 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
return ret;
}
+int
+peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
+{
+ if (enable)
+ return peer_activate (peer, afi, safi);
+ else
+ return peer_deactivate (peer, afi, safi);
+}
+
static void
peer_nsf_stop (struct peer *peer)
{
@@ -2546,6 +2595,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
int first_member = 0;
afi_t afi;
safi_t safi;
+ int cap_enhe_preset = 0;
/* Lookup the peer. */
if (!peer)
@@ -2580,8 +2630,18 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
first_member = 1;
}
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ cap_enhe_preset = 1;
+
peer_group2peer_config_copy(group, peer);
+ /*
+ * Capability extended-nexthop is enabled for an interface neighbor by
+ * default. So, fix that up here.
+ */
+ if (peer->ifp && cap_enhe_preset)
+ peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
@@ -3167,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)
@@ -4078,7 +4140,7 @@ peer_ebgp_multihop_unset (struct peer *peer)
/* Neighbor description. */
int
-peer_description_set (struct peer *peer, char *desc)
+peer_description_set (struct peer *peer, const char *desc)
{
if (peer->desc)
XFREE (MTYPE_PEER_DESC, peer->desc);
@@ -4171,7 +4233,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname)
}
int
-peer_update_source_addr_set (struct peer *peer, union sockunion *su)
+peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
{
struct peer_group *group;
struct listnode *node, *nnode;
@@ -6269,6 +6331,8 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
struct peer *g_peer = NULL;
char buf[SU_ADDRSTRLEN];
char *addr;
+ int if_pg_printed = FALSE;
+ int if_ras_printed = FALSE;
/* Skip dynamic neighbors. */
if (peer_dynamic_neighbor (peer))
@@ -6290,7 +6354,25 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
vty_out (vty, " neighbor %s interface", addr);
if (peer_group_active (peer))
- vty_out (vty, " peer-group %s", peer->group->name);
+ {
+ vty_out (vty, " peer-group %s", peer->group->name);
+ if_pg_printed = TRUE;
+ }
+ else if (peer->as_type == AS_SPECIFIED)
+ {
+ vty_out (vty, " remote-as %u", peer->as);
+ if_ras_printed = TRUE;
+ }
+ else if (peer->as_type == AS_INTERNAL)
+ {
+ vty_out (vty, " remote-as internal");
+ if_ras_printed = TRUE;
+ }
+ else if (peer->as_type == AS_EXTERNAL)
+ {
+ vty_out (vty, " remote-as external");
+ if_ras_printed = TRUE;
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
@@ -6301,7 +6383,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
{
g_peer = peer->group->conf;
- if (g_peer->as_type == AS_UNSPECIFIED)
+ if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed)
{
if (peer->as_type == AS_SPECIFIED)
{
@@ -6320,7 +6402,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
/* For swpX peers we displayed the peer-group
* via 'neighbor swpX interface peer-group WORD' */
- if (!peer->conf_if)
+ if (!if_pg_printed)
vty_out (vty, " neighbor %s peer-group %s%s", addr,
peer->group->name, VTY_NEWLINE);
}
@@ -6335,18 +6417,21 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
VTY_NEWLINE);
}
- if (peer->as_type == AS_SPECIFIED)
- {
- vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
- VTY_NEWLINE);
- }
- else if (peer->as_type == AS_INTERNAL)
- {
- vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
- }
- else if (peer->as_type == AS_EXTERNAL)
+ if (!if_ras_printed)
{
- vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
+ if (peer->as_type == AS_SPECIFIED)
+ {
+ vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
+ VTY_NEWLINE);
+ }
+ else if (peer->as_type == AS_INTERNAL)
+ {
+ vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
+ }
+ else if (peer->as_type == AS_EXTERNAL)
+ {
+ vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
+ }
}
}
@@ -6541,7 +6626,17 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
}
/* capability extended-nexthop */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ {
+ if (! peer_group_active (peer) ||
+ ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ {
+ vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr,
+ VTY_NEWLINE);
+ }
+ }
+
+ if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
{
if (! peer_group_active (peer) ||
! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
@@ -6630,10 +6725,32 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
{
if (peer->afc[afi][safi])
{
- afi_header_vty_out (vty, afi, safi, write,
- " neighbor %s activate%s",
- addr, VTY_NEWLINE);
+ if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
+ {
+ if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
+ {
+ afi_header_vty_out(vty, afi, safi, write,
+ " neighbor %s activate%s",
+ addr, VTY_NEWLINE);
+ }
+ }
+ else
+ afi_header_vty_out (vty, afi, safi, write,
+ " neighbor %s activate%s",
+ addr, VTY_NEWLINE);
}
+ else
+ {
+ if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
+ {
+ if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
+ {
+ afi_header_vty_out (vty, afi, safi, write,
+ " no neighbor %s activate%s",
+ addr, VTY_NEWLINE);
+ }
+ }
+ }
}
/* addpath TX knobs */
@@ -7116,6 +7233,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);
@@ -7216,8 +7336,6 @@ bgp_config_write (struct vty *vty)
/* ENCAPv6 configuration. */
write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
- vty_out (vty, " exit%s", VTY_NEWLINE);
-
write++;
}
return write;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0c6aa6b21a..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. */
@@ -1120,6 +1120,7 @@ enum bgp_clear_type
#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -31
#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -32
#define BGP_ERR_MAX -33
+#define BGP_ERR_INVALID_FOR_DIRECT_PEER -34
/*
* Enumeration of different policy kinds a peer can be configured with.
@@ -1207,7 +1208,8 @@ extern int bgp_flag_check (struct bgp *, int);
extern void bgp_lock (struct bgp *);
extern void bgp_unlock (struct bgp *);
-extern int bgp_router_id_set (struct bgp *, struct in_addr *);
+extern void bgp_router_id_zebra_bump (vrf_id_t, const struct prefix*);
+extern int bgp_router_id_static_set (struct bgp *, struct in_addr);
extern int bgp_cluster_id_set (struct bgp *, struct in_addr *);
extern int bgp_cluster_id_unset (struct bgp *);
@@ -1219,7 +1221,7 @@ extern int bgp_confederation_peers_check (struct bgp *, as_t);
extern int bgp_confederation_peers_add (struct bgp *, as_t);
extern int bgp_confederation_peers_remove (struct bgp *, as_t);
-extern int bgp_timers_set (struct bgp *, u_int32_t, u_int32_t);
+extern int bgp_timers_set (struct bgp *, u_int32_t keepalive, u_int32_t holdtime);
extern int bgp_timers_unset (struct bgp *);
extern int bgp_default_local_preference_set (struct bgp *, u_int32_t);
@@ -1244,6 +1246,7 @@ extern int peer_group_listen_range_add(struct peer_group *, struct prefix *);
extern int peer_activate (struct peer *, afi_t, safi_t);
extern int peer_deactivate (struct peer *, afi_t, safi_t);
+extern int peer_afc_set (struct peer *, afi_t, safi_t, int);
extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *,
struct peer_group *, as_t *);
@@ -1260,11 +1263,11 @@ extern int peer_ebgp_multihop_set (struct peer *, int);
extern int peer_ebgp_multihop_unset (struct peer *);
extern int is_ebgp_multihop_configured (struct peer *peer);
-extern int peer_description_set (struct peer *, char *);
+extern int peer_description_set (struct peer *, const char *);
extern int peer_description_unset (struct peer *);
extern int peer_update_source_if_set (struct peer *, const char *);
-extern int peer_update_source_addr_set (struct peer *, union sockunion *);
+extern int peer_update_source_addr_set (struct peer *, const union sockunion *);
extern int peer_update_source_unset (struct peer *);
extern int peer_default_originate_set (struct peer *, afi_t, safi_t, const char *);
@@ -1276,7 +1279,7 @@ extern int peer_port_unset (struct peer *);
extern int peer_weight_set (struct peer *, u_int16_t);
extern int peer_weight_unset (struct peer *);
-extern int peer_timers_set (struct peer *, u_int32_t, u_int32_t);
+extern int peer_timers_set (struct peer *, u_int32_t keepalive, u_int32_t holdtime);
extern int peer_timers_unset (struct peer *);
extern int peer_timers_connect_set (struct peer *, u_int32_t);
@@ -1501,4 +1504,5 @@ bgp_vrf_unlink (struct bgp *bgp, struct vrf *vrf)
bgp->vrf_id = VRF_UNKNOWN;
}
+extern void bgp_update_redist_vrf_bitmaps (struct bgp*, vrf_id_t);
#endif /* _QUAGGA_BGPD_H */
diff --git a/configure.ac b/configure.ac
index cb4c8724f1..8a1131d347 100755
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ(2.60)
-AC_INIT(Quagga, 0.99.24+cl3u2, [https://bugzilla.quagga.net])
+AC_INIT(Quagga, 0.99.24+cl3u3, [https://bugzilla.quagga.net])
CONFIG_ARGS="$*"
AC_SUBST(CONFIG_ARGS)
AC_CONFIG_SRCDIR(lib/zebra.h)
@@ -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,13 +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])
+ 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
@@ -368,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
@@ -380,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
@@ -416,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
@@ -438,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)
@@ -710,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.])
@@ -851,6 +852,14 @@ AC_CHECK_FUNCS([dup2 ftruncate getcwd gethostbyname getpagesize gettimeofday \
if_nametoindex if_indextoname getifaddrs \
uname fcntl getgrouplist])
+AC_CHECK_HEADER([asm-generic/unistd.h],
+ [AC_CHECK_DECL(__NR_setns,
+ AC_DEFINE(HAVE_NETNS,, Have netns),,
+ QUAGGA_INCLUDES [#include <asm-generic/unistd.h>
+ ])
+ AC_CHECK_FUNCS(setns, AC_DEFINE(HAVE_SETNS,, Have setns))]
+ )
+
dnl ------------------------------------
dnl Determine routing get and set method
dnl ------------------------------------
@@ -993,11 +1002,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>
@@ -1095,6 +1139,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 ----------
@@ -1202,16 +1251,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/etc/quagga/Quagga.conf b/cumulus/etc/quagga/Quagga.conf
new file mode 100644
index 0000000000..e52f3f8aab
--- /dev/null
+++ b/cumulus/etc/quagga/Quagga.conf
@@ -0,0 +1,2 @@
+log file /var/log/quagga/quagga.log
+log timestamp precision 6
diff --git a/cumulus/etc/quagga/bgpd.conf b/cumulus/etc/quagga/bgpd.conf
deleted file mode 100644
index 7c9c5ae286..0000000000
--- a/cumulus/etc/quagga/bgpd.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-hostname bgpd
-log timestamp precision 6
-log file /var/log/quagga/bgpd.log
diff --git a/cumulus/etc/quagga/ospf6d.conf b/cumulus/etc/quagga/ospf6d.conf
deleted file mode 100644
index 408ca1af1e..0000000000
--- a/cumulus/etc/quagga/ospf6d.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-hostname ospfd
-log timestamp precision 6
-log file /var/log/quagga/ospf6d.log
diff --git a/cumulus/etc/quagga/ospfd.conf b/cumulus/etc/quagga/ospfd.conf
deleted file mode 100644
index 8f2e53e030..0000000000
--- a/cumulus/etc/quagga/ospfd.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-hostname ospfd
-log timestamp precision 6
-log file /var/log/quagga/ospfd.log
diff --git a/cumulus/etc/quagga/pimd.conf b/cumulus/etc/quagga/pimd.conf
deleted file mode 100644
index 8aa1e7f5f0..0000000000
--- a/cumulus/etc/quagga/pimd.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-hostname pimd
-password cn321
-enable password cn321
-log timestamp precision 6
-log file /var/log/quagga/pimd.log
diff --git a/cumulus/etc/quagga/zebra.conf b/cumulus/etc/quagga/zebra.conf
deleted file mode 100644
index 67e4799413..0000000000
--- a/cumulus/etc/quagga/zebra.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-hostname zebra
-log file /var/log/quagga/zebra.log
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/debian/changelog b/debian/changelog
index b83daec10a..3114db3fd1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,12 @@
-quagga (0.99.23.1-1+cl3u2) Release; urgency=medium
+quagga (0.99.24+cl3u3) RELEASED; urgency=medium
+
+ * New Enabled: Merge up-to 0.99.24 code from upstream
+ * New Enabled: Additional CLI simplification
+ * New Enabled: Various Bug Fixes
+
+ -- dev-support <dev-support@cumulusnetworks.com> Thu, 04 Aug 2016 08:43:36 -0700
+
+quagga (0.99.23.1-1+cl3u2) RELEASED; urgency=medium
* New Enabled: VRF - See Documentation for how to use
* New Enabled: Improved interface statistics
diff --git a/debian/quagga.install b/debian/quagga.install
index 2651dd9e00..6a70be9925 100644
--- a/debian/quagga.install
+++ b/debian/quagga.install
@@ -1,6 +1,5 @@
etc/quagga/
usr/bin/vtysh
-usr/bin/test_igmpv3_join
usr/include/quagga/
usr/lib/
tools/quagga-reload.py usr/lib/quagga/
diff --git a/debian/rules b/debian/rules
index e5e3ad8c11..25461b89d8 100755
--- a/debian/rules
+++ b/debian/rules
@@ -39,6 +39,8 @@ override_dh_auto_configure:
--sysconfdir=/etc/quagga \
$(USE_SNMP) \
--enable-ospfapi=yes \
+ --enable-vtysh=yes \
+ --enable-isisd=yes \
--enable-multipath=256 \
--enable-user=quagga \
--enable-group=quagga \
@@ -51,6 +53,7 @@ override_dh_auto_configure:
--enable-systemd=yes \
--enable-poll=yes \
--enable-cumulus=yes \
+ --enable-pimd=no \
--enable-dependency-tracking; \
fi
diff --git a/doc/.gitignore b/doc/.gitignore
index 5071f98707..66c43c73e6 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -32,3 +32,4 @@ stamp-vti
.arch-ids
*~
*.loT
+refix
diff --git a/doc/bgpd.8 b/doc/bgpd.8
index 67143c2c59..7e90eaec5b 100644
--- a/doc/bgpd.8
+++ b/doc/bgpd.8
@@ -6,7 +6,7 @@ software
.SH SYNOPSIS
.B bgpd
[
-.B \-dhrv
+.B \-dhrSv
] [
.B \-f
.I config-file
@@ -74,6 +74,9 @@ Specify the user to run as. Default is \fIquagga\fR.
\fB\-r\fR, \fB\-\-retain\fR
When the program terminates, retain routes added by \fBbgpd\fR.
.TP
+\fB\-S\fR, \fB\-\-skip_runas\fR
+Skip setting the process effective user and group.
+.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES
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 5f866638d9..bfe2e94779 100644
--- a/isisd/Makefile.am
+++ b/isisd/Makefile.am
@@ -16,7 +16,8 @@ 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
noinst_HEADERS = \
@@ -24,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 17ba40aa59..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.
@@ -92,13 +94,12 @@ isis_circuit_new ()
circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL;
circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL;
circuit->priority[i] = DEFAULT_PRIORITY;
- circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRIC;
- circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED;
- circuit->metrics[i].metric_error = METRICS_UNSUPPORTED;
- circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED;
+ circuit->metric[i] = DEFAULT_CIRCUIT_METRIC;
circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC;
}
+ circuit->mtc = mpls_te_circuit_new();
+
return circuit;
}
@@ -196,30 +197,6 @@ circuit_scan_by_ifp (struct interface *ifp)
return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
}
-static struct isis_circuit *
-isis_circuit_lookup (struct vty *vty)
-{
- struct interface *ifp;
- struct isis_circuit *circuit;
-
- ifp = (struct interface *) vty->index;
- if (!ifp)
- {
- vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
- return NULL;
- }
-
- circuit = circuit_scan_by_ifp (ifp);
- if (!circuit)
- {
- vty_out (vty, "ISIS is not enabled on circuit %s%s",
- ifp->name, VTY_NEWLINE);
- return NULL;
- }
-
- return circuit;
-}
-
void
isis_circuit_add_addr (struct isis_circuit *circuit,
struct connected *connected)
@@ -249,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);
@@ -545,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
@@ -646,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");
@@ -668,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 ();
@@ -923,7 +895,7 @@ isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
vty_out (vty, " Metric: %d", circuit->te_metric[0]);
else
vty_out (vty, " Metric: %d",
- circuit->metrics[0].metric_default);
+ circuit->metric[0]);
if (!circuit->is_passive)
{
vty_out (vty, ", Active neighbors: %u%s",
@@ -956,7 +928,7 @@ isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
vty_out (vty, " Metric: %d", circuit->te_metric[1]);
else
vty_out (vty, " Metric: %d",
- circuit->metrics[1].metric_default);
+ circuit->metric[1]);
if (!circuit->is_passive)
{
vty_out (vty, ", Active neighbors: %u%s",
@@ -1250,1562 +1222,164 @@ isis_interface_config_write (struct vty *vty)
return write;
}
-DEFUN (ip_router_isis,
- ip_router_isis_cmd,
- "ip router isis WORD",
- "Interface Internet Protocol config commands\n"
- "IP router interface commands\n"
- "IS-IS Routing for IP\n"
- "Routing process tag\n")
+struct isis_circuit *
+isis_circuit_create (struct isis_area *area, struct interface *ifp)
{
- struct isis_circuit *circuit;
- struct interface *ifp;
- struct isis_area *area;
- int rv;
-
- ifp = (struct interface *) vty->index;
- assert (ifp);
-
- /* Prevent more than one area per circuit */
- circuit = circuit_scan_by_ifp (ifp);
- if (circuit)
- {
- if (circuit->ip_router == 1)
- {
- if (strcmp (circuit->area->area_tag, argv[0]))
- {
- vty_out (vty, "ISIS circuit is already defined on %s%s",
- circuit->area->area_tag, VTY_NEWLINE);
- return CMD_ERR_NOTHING_TODO;
- }
- return CMD_SUCCESS;
- }
- }
-
- if (isis_area_get (vty, argv[0]) != CMD_SUCCESS)
- {
- vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
- area = vty->index;
-
+ struct isis_circuit *circuit = circuit_scan_by_ifp (ifp);
+ if (circuit && circuit->area)
+ return NULL;
circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
- {
- vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE);
- rv = CMD_WARNING;
- }
- else
- {
- isis_circuit_if_bind (circuit, ifp);
-
- circuit->ip_router = 1;
- area->ip_circuits++;
- circuit_update_nlpids (circuit);
- rv = CMD_SUCCESS;
- }
-
- vty->node = INTERFACE_NODE;
- vty->index = ifp;
-
- if (circuit->ipv6_router)
- lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
- return rv;
+ return circuit;
+ isis_circuit_if_bind (circuit, ifp);
+ return circuit;
}
-DEFUN (no_ip_router_isis,
- no_ip_router_isis_cmd,
- "no ip router isis WORD",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "IP router interface commands\n"
- "IS-IS Routing for IP\n"
- "Routing process tag\n")
+void
+isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router)
{
- struct interface *ifp;
- struct isis_area *area;
- struct isis_circuit *circuit;
+ struct isis_area *area = circuit->area;
+ bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router;
+ bool was_enabled = !!circuit->area;
- ifp = (struct interface *) vty->index;
- if (!ifp)
- {
- vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
+ area->ip_circuits += ip_router - circuit->ip_router;
+ area->ipv6_circuits += ipv6_router - circuit->ipv6_router;
+ circuit->ip_router = ip_router;
+ circuit->ipv6_router = ipv6_router;
- area = isis_area_lookup (argv[0]);
- if (!area)
- {
- vty_out (vty, "Can't find ISIS instance %s%s",
- argv[0], VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
+ if (!change)
+ return;
- circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
- if (!circuit)
- {
- vty_out (vty, "ISIS is not enabled on circuit %s%s",
- ifp->name, VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
+ circuit_update_nlpids (circuit);
- circuit->ip_router = 0;
- area->ip_circuits--;
- if (circuit->ipv6_router == 0)
+ if (!ip_router && !ipv6_router)
isis_csm_state_change (ISIS_DISABLE, circuit, area);
+ else if (!was_enabled)
+ isis_csm_state_change (ISIS_ENABLE, circuit, area);
else
- lsp_regenerate_schedule(area, circuit->is_type, 0);
-
- return CMD_SUCCESS;
-}
-
-#ifdef HAVE_IPV6
-DEFUN (ipv6_router_isis,
- ipv6_router_isis_cmd,
- "ipv6 router isis WORD",
- "IPv6 interface subcommands\n"
- "IPv6 Router interface commands\n"
- "IS-IS Routing for IPv6\n"
- "Routing process tag\n")
-{
- struct isis_circuit *circuit;
- struct interface *ifp;
- struct isis_area *area;
- int rv;
-
- ifp = (struct interface *) vty->index;
- assert (ifp);
-
- /* Prevent more than one area per circuit */
- circuit = circuit_scan_by_ifp (ifp);
- if (circuit)
- {
- if (circuit->ipv6_router == 1)
- {
- if (strcmp (circuit->area->area_tag, argv[0]))
- {
- vty_out (vty, "ISIS circuit is already defined for IPv6 on %s%s",
- circuit->area->area_tag, VTY_NEWLINE);
- return CMD_ERR_NOTHING_TODO;
- }
- return CMD_SUCCESS;
- }
- }
-
- if (isis_area_get (vty, argv[0]) != CMD_SUCCESS)
- {
- vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
- area = vty->index;
-
- circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
- if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
- {
- vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE);
- rv = CMD_WARNING;
- }
- else
- {
- isis_circuit_if_bind (circuit, ifp);
-
- circuit->ipv6_router = 1;
- area->ipv6_circuits++;
- circuit_update_nlpids (circuit);
- rv = CMD_SUCCESS;
- }
-
- vty->node = INTERFACE_NODE;
- vty->index = ifp;
-
- if (circuit->ip_router)
lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
- return rv;
-}
-
-DEFUN (no_ipv6_router_isis,
- no_ipv6_router_isis_cmd,
- "no ipv6 router isis WORD",
- NO_STR
- "IPv6 interface subcommands\n"
- "IPv6 Router interface commands\n"
- "IS-IS Routing for IPv6\n"
- "Routing process tag\n")
-{
- struct interface *ifp;
- struct isis_area *area;
- struct isis_circuit *circuit;
-
- ifp = (struct interface *) vty->index;
- if (!ifp)
- {
- vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- area = isis_area_lookup (argv[0]);
- if (!area)
- {
- vty_out (vty, "Can't find ISIS instance %s%s",
- argv[0], VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
- if (!circuit)
- {
- vty_out (vty, "ISIS is not enabled on circuit %s%s",
- ifp->name, VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- circuit->ipv6_router = 0;
- area->ipv6_circuits--;
- if (circuit->ip_router == 0)
- isis_csm_state_change (ISIS_DISABLE, circuit, area);
- else
- lsp_regenerate_schedule(area, circuit->is_type, 0);
-
- return CMD_SUCCESS;
}
-#endif /* HAVE_IPV6 */
-DEFUN (isis_passive,
- isis_passive_cmd,
- "isis passive",
- "IS-IS commands\n"
- "Configure the passive mode for interface\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- if (circuit->is_passive == 1)
- return CMD_SUCCESS;
-
- if (circuit->state != C_STATE_UP)
- {
- circuit->is_passive = 1;
- }
- else
- {
- struct isis_area *area = circuit->area;
- isis_csm_state_change (ISIS_DISABLE, circuit, area);
- circuit->is_passive = 1;
- isis_csm_state_change (ISIS_ENABLE, circuit, area);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_passive,
- no_isis_passive_cmd,
- "no isis passive",
- NO_STR
- "IS-IS commands\n"
- "Configure the passive mode for interface\n")
+int
+isis_circuit_passive_set (struct isis_circuit *circuit, bool passive)
{
- struct interface *ifp;
- struct isis_circuit *circuit;
+ if (circuit->is_passive == passive)
+ return 0;
- ifp = (struct interface *) vty->index;
- if (!ifp)
- {
- vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- /* FIXME: what is wrong with circuit = ifp->info ? */
- circuit = circuit_scan_by_ifp (ifp);
- if (!circuit)
- {
- vty_out (vty, "ISIS is not enabled on circuit %s%s",
- ifp->name, VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- if (if_is_loopback(ifp))
- {
- vty_out (vty, "Can't set no passive for loopback interface%s",
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- if (circuit->is_passive == 0)
- return CMD_SUCCESS;
+ if (if_is_loopback (circuit->interface) && !passive)
+ return -1;
if (circuit->state != C_STATE_UP)
{
- circuit->is_passive = 0;
+ circuit->is_passive = passive;
}
else
{
struct isis_area *area = circuit->area;
isis_csm_state_change (ISIS_DISABLE, circuit, area);
- circuit->is_passive = 0;
+ circuit->is_passive = passive;
isis_csm_state_change (ISIS_ENABLE, circuit, area);
}
- return CMD_SUCCESS;
+ return 0;
}
-DEFUN (isis_circuit_type,
- isis_circuit_type_cmd,
- "isis circuit-type (level-1|level-1-2|level-2-only)",
- "IS-IS commands\n"
- "Configure circuit type for interface\n"
- "Level-1 only adjacencies are formed\n"
- "Level-1-2 adjacencies are formed\n"
- "Level-2 only adjacencies are formed\n")
+int
+isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric)
{
- int circuit_type;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
+ assert (level == IS_LEVEL_1 || level == IS_LEVEL_2);
+ if (metric > MAX_WIDE_LINK_METRIC)
+ return -1;
+ if (circuit->area && circuit->area->oldmetric
+ && metric > MAX_NARROW_LINK_METRIC)
+ return -1;
- circuit_type = string2circuit_t (argv[0]);
- if (!circuit_type)
- {
- vty_out (vty, "Unknown circuit-type %s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- if (circuit->state == C_STATE_UP &&
- circuit->area->is_type != IS_LEVEL_1_AND_2 &&
- circuit->area->is_type != circuit_type)
- {
- vty_out (vty, "Invalid circuit level for area %s.%s",
- circuit->area->area_tag, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- isis_event_circuit_type_change (circuit, circuit_type);
+ circuit->te_metric[level - 1] = metric;
+ circuit->metric[level - 1] = metric;
- return CMD_SUCCESS;
+ if (circuit->area)
+ lsp_regenerate_schedule (circuit->area, level, 0);
+ return 0;
}
-DEFUN (no_isis_circuit_type,
- no_isis_circuit_type_cmd,
- "no isis circuit-type (level-1|level-1-2|level-2-only)",
- NO_STR
- "IS-IS commands\n"
- "Configure circuit type for interface\n"
- "Level-1 only adjacencies are formed\n"
- "Level-1-2 adjacencies are formed\n"
- "Level-2 only adjacencies are formed\n")
+int
+isis_circuit_passwd_unset (struct isis_circuit *circuit)
{
- int circuit_type;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- /*
- * Set the circuits level to its default value
- */
- if (circuit->state == C_STATE_UP)
- circuit_type = circuit->area->is_type;
- else
- circuit_type = IS_LEVEL_1_AND_2;
- isis_event_circuit_type_change (circuit, circuit_type);
-
- return CMD_SUCCESS;
+ memset(&circuit->passwd, 0, sizeof(circuit->passwd));
+ return 0;
}
-DEFUN (isis_passwd_md5,
- isis_passwd_md5_cmd,
- "isis password md5 WORD",
- "IS-IS commands\n"
- "Configure the authentication password for a circuit\n"
- "Authentication type\n"
- "Circuit password\n")
+static int
+isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd)
{
int len;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
- len = strlen (argv[0]);
- if (len > 254)
- {
- vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- circuit->passwd.len = len;
- circuit->passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5;
- strncpy ((char *)circuit->passwd.passwd, argv[0], 255);
+ if (!passwd)
+ return -1;
- return CMD_SUCCESS;
-}
-
-DEFUN (isis_passwd_clear,
- isis_passwd_clear_cmd,
- "isis password clear WORD",
- "IS-IS commands\n"
- "Configure the authentication password for a circuit\n"
- "Authentication type\n"
- "Circuit password\n")
-{
- int len;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- len = strlen (argv[0]);
+ len = strlen(passwd);
if (len > 254)
- {
- vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- circuit->passwd.len = len;
- circuit->passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
- strncpy ((char *)circuit->passwd.passwd, argv[0], 255);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_passwd,
- no_isis_passwd_cmd,
- "no isis password",
- NO_STR
- "IS-IS commands\n"
- "Configure the authentication password for a circuit\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- memset (&circuit->passwd, 0, sizeof (struct isis_passwd));
-
- return CMD_SUCCESS;
-}
-
-DEFUN (isis_priority,
- isis_priority_cmd,
- "isis priority <0-127>",
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n")
-{
- int prio;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- prio = atoi (argv[0]);
- if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
- {
- vty_out (vty, "Invalid priority %d - should be <0-127>%s",
- prio, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->priority[0] = prio;
- circuit->priority[1] = prio;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_priority,
- no_isis_priority_cmd,
- "no isis priority",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->priority[0] = DEFAULT_PRIORITY;
- circuit->priority[1] = DEFAULT_PRIORITY;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_priority,
- no_isis_priority_arg_cmd,
- "no isis priority <0-127>",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n")
-
-DEFUN (isis_priority_l1,
- isis_priority_l1_cmd,
- "isis priority <0-127> level-1",
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n"
- "Specify priority for level-1 routing\n")
-{
- int prio;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- prio = atoi (argv[0]);
- if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
- {
- vty_out (vty, "Invalid priority %d - should be <0-127>%s",
- prio, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->priority[0] = prio;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_priority_l1,
- no_isis_priority_l1_cmd,
- "no isis priority level-1",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Specify priority for level-1 routing\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->priority[0] = DEFAULT_PRIORITY;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_priority_l1,
- no_isis_priority_l1_arg_cmd,
- "no isis priority <0-127> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n"
- "Specify priority for level-1 routing\n")
-
-DEFUN (isis_priority_l2,
- isis_priority_l2_cmd,
- "isis priority <0-127> level-2",
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n"
- "Specify priority for level-2 routing\n")
-{
- int prio;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- prio = atoi (argv[0]);
- if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
- {
- vty_out (vty, "Invalid priority %d - should be <0-127>%s",
- prio, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->priority[1] = prio;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_priority_l2,
- no_isis_priority_l2_cmd,
- "no isis priority level-2",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Specify priority for level-2 routing\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->priority[1] = DEFAULT_PRIORITY;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_priority_l2,
- no_isis_priority_l2_arg_cmd,
- "no isis priority <0-127> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set priority for Designated Router election\n"
- "Priority value\n"
- "Specify priority for level-2 routing\n")
-
-/* Metric command */
-DEFUN (isis_metric,
- isis_metric_cmd,
- "isis metric <0-16777215>",
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n")
-{
- int met;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- met = atoi (argv[0]);
-
- /* RFC3787 section 5.1 */
- if (circuit->area && circuit->area->oldmetric == 1 &&
- met > MAX_NARROW_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-63> "
- "when narrow metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- /* RFC4444 */
- if (circuit->area && circuit->area->newmetric == 1 &&
- met > MAX_WIDE_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-16777215> "
- "when wide metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->te_metric[0] = met;
- circuit->te_metric[1] = met;
-
- circuit->metrics[0].metric_default = met;
- circuit->metrics[1].metric_default = met;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_metric,
- no_isis_metric_cmd,
- "no isis metric",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->te_metric[0] = DEFAULT_CIRCUIT_METRIC;
- circuit->te_metric[1] = DEFAULT_CIRCUIT_METRIC;
- circuit->metrics[0].metric_default = DEFAULT_CIRCUIT_METRIC;
- circuit->metrics[1].metric_default = DEFAULT_CIRCUIT_METRIC;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_metric,
- no_isis_metric_arg_cmd,
- "no isis metric <0-16777215>",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n")
-
-DEFUN (isis_metric_l1,
- isis_metric_l1_cmd,
- "isis metric <0-16777215> level-1",
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n"
- "Specify metric for level-1 routing\n")
-{
- int met;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- met = atoi (argv[0]);
-
- /* RFC3787 section 5.1 */
- if (circuit->area && circuit->area->oldmetric == 1 &&
- met > MAX_NARROW_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-63> "
- "when narrow metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
+ return -1;
- /* RFC4444 */
- if (circuit->area && circuit->area->newmetric == 1 &&
- met > MAX_WIDE_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-16777215> "
- "when wide metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->te_metric[0] = met;
- circuit->metrics[0].metric_default = met;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, IS_LEVEL_1, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_metric_l1,
- no_isis_metric_l1_cmd,
- "no isis metric level-1",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Specify metric for level-1 routing\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->te_metric[0] = DEFAULT_CIRCUIT_METRIC;
- circuit->metrics[0].metric_default = DEFAULT_CIRCUIT_METRIC;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, IS_LEVEL_1, 0);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_metric_l1,
- no_isis_metric_l1_arg_cmd,
- "no isis metric <0-16777215> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n"
- "Specify metric for level-1 routing\n")
-
-DEFUN (isis_metric_l2,
- isis_metric_l2_cmd,
- "isis metric <0-16777215> level-2",
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n"
- "Specify metric for level-2 routing\n")
-{
- int met;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- met = atoi (argv[0]);
-
- /* RFC3787 section 5.1 */
- if (circuit->area && circuit->area->oldmetric == 1 &&
- met > MAX_NARROW_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-63> "
- "when narrow metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- /* RFC4444 */
- if (circuit->area && circuit->area->newmetric == 1 &&
- met > MAX_WIDE_LINK_METRIC)
- {
- vty_out (vty, "Invalid metric %d - should be <0-16777215> "
- "when wide metric type enabled%s",
- met, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->te_metric[1] = met;
- circuit->metrics[1].metric_default = met;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, IS_LEVEL_2, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_metric_l2,
- no_isis_metric_l2_cmd,
- "no isis metric level-2",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Specify metric for level-2 routing\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->te_metric[1] = DEFAULT_CIRCUIT_METRIC;
- circuit->metrics[1].metric_default = DEFAULT_CIRCUIT_METRIC;
-
- if (circuit->area)
- lsp_regenerate_schedule (circuit->area, IS_LEVEL_2, 0);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_metric_l2,
- no_isis_metric_l2_arg_cmd,
- "no isis metric <0-16777215> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set default metric for circuit\n"
- "Default metric value\n"
- "Specify metric for level-2 routing\n")
-/* end of metrics */
-
-DEFUN (isis_hello_interval,
- isis_hello_interval_cmd,
- "isis hello-interval <1-600>",
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 seconds, interval depends on multiplier\n")
-{
- int interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atoi (argv[0]);
- if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
- {
- vty_out (vty, "Invalid hello-interval %d - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_interval[0] = (u_int16_t) interval;
- circuit->hello_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_interval,
- no_isis_hello_interval_cmd,
- "no isis hello-interval",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
- circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_interval,
- no_isis_hello_interval_arg_cmd,
- "no isis hello-interval <1-600>",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 second, interval depends on multiplier\n")
-
-DEFUN (isis_hello_interval_l1,
- isis_hello_interval_l1_cmd,
- "isis hello-interval <1-600> level-1",
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 second, interval depends on multiplier\n"
- "Specify hello-interval for level-1 IIHs\n")
-{
- long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atoi (argv[0]);
- if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
- {
- vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_interval[0] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_interval_l1,
- no_isis_hello_interval_l1_cmd,
- "no isis hello-interval level-1",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Specify hello-interval for level-1 IIHs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_interval_l1,
- no_isis_hello_interval_l1_arg_cmd,
- "no isis hello-interval <1-600> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 second, interval depends on multiplier\n"
- "Specify hello-interval for level-1 IIHs\n")
-
-DEFUN (isis_hello_interval_l2,
- isis_hello_interval_l2_cmd,
- "isis hello-interval <1-600> level-2",
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 second, interval depends on multiplier\n"
- "Specify hello-interval for level-2 IIHs\n")
-{
- long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atoi (argv[0]);
- if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
- {
- vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_interval_l2,
- no_isis_hello_interval_l2_cmd,
- "no isis hello-interval level-2",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Specify hello-interval for level-2 IIHs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_interval_l2,
- no_isis_hello_interval_l2_arg_cmd,
- "no isis hello-interval <1-600> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set Hello interval\n"
- "Hello interval value\n"
- "Holdtime 1 second, interval depends on multiplier\n"
- "Specify hello-interval for level-2 IIHs\n")
-
-DEFUN (isis_hello_multiplier,
- isis_hello_multiplier_cmd,
- "isis hello-multiplier <2-100>",
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n")
-{
- int mult;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- mult = atoi (argv[0]);
- if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
- {
- vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
- mult, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_multiplier[0] = (u_int16_t) mult;
- circuit->hello_multiplier[1] = (u_int16_t) mult;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_multiplier,
- no_isis_hello_multiplier_cmd,
- "no isis hello-multiplier",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
- circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_multiplier,
- no_isis_hello_multiplier_arg_cmd,
- "no isis hello-multiplier <2-100>",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n")
-
-DEFUN (isis_hello_multiplier_l1,
- isis_hello_multiplier_l1_cmd,
- "isis hello-multiplier <2-100> level-1",
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n"
- "Specify hello multiplier for level-1 IIHs\n")
-{
- int mult;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- mult = atoi (argv[0]);
- if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
- {
- vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
- mult, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_multiplier[0] = (u_int16_t) mult;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_multiplier_l1,
- no_isis_hello_multiplier_l1_cmd,
- "no isis hello-multiplier level-1",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Specify hello multiplier for level-1 IIHs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_multiplier_l1,
- no_isis_hello_multiplier_l1_arg_cmd,
- "no isis hello-multiplier <2-100> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n"
- "Specify hello multiplier for level-1 IIHs\n")
-
-DEFUN (isis_hello_multiplier_l2,
- isis_hello_multiplier_l2_cmd,
- "isis hello-multiplier <2-100> level-2",
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n"
- "Specify hello multiplier for level-2 IIHs\n")
-{
- int mult;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- mult = atoi (argv[0]);
- if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
- {
- vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
- mult, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->hello_multiplier[1] = (u_int16_t) mult;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_multiplier_l2,
- no_isis_hello_multiplier_l2_cmd,
- "no isis hello-multiplier level-2",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Specify hello multiplier for level-2 IIHs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_isis_hello_multiplier_l2,
- no_isis_hello_multiplier_l2_arg_cmd,
- "no isis hello-multiplier <2-100> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set multiplier for Hello holding time\n"
- "Hello multiplier value\n"
- "Specify hello multiplier for level-2 IIHs\n")
-
-DEFUN (isis_hello_padding,
- isis_hello_padding_cmd,
- "isis hello padding",
- "IS-IS commands\n"
- "Add padding to IS-IS hello packets\n"
- "Pad hello packets\n"
- "<cr>\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->pad_hellos = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_hello_padding,
- no_isis_hello_padding_cmd,
- "no isis hello padding",
- NO_STR
- "IS-IS commands\n"
- "Add padding to IS-IS hello packets\n"
- "Pad hello packets\n"
- "<cr>\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->pad_hellos = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (csnp_interval,
- csnp_interval_cmd,
- "isis csnp-interval <1-600>",
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n")
-{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
- {
- vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->csnp_interval[0] = (u_int16_t) interval;
- circuit->csnp_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_csnp_interval,
- no_csnp_interval_cmd,
- "no isis csnp-interval",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
- circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_csnp_interval,
- no_csnp_interval_arg_cmd,
- "no isis csnp-interval <1-600>",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n")
-
-DEFUN (csnp_interval_l1,
- csnp_interval_l1_cmd,
- "isis csnp-interval <1-600> level-1",
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n"
- "Specify interval for level-1 CSNPs\n")
-{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
- {
- vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->csnp_interval[0] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_csnp_interval_l1,
- no_csnp_interval_l1_cmd,
- "no isis csnp-interval level-1",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "Specify interval for level-1 CSNPs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_csnp_interval_l1,
- no_csnp_interval_l1_arg_cmd,
- "no isis csnp-interval <1-600> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n"
- "Specify interval for level-1 CSNPs\n")
-
-DEFUN (csnp_interval_l2,
- csnp_interval_l2_cmd,
- "isis csnp-interval <1-600> level-2",
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n"
- "Specify interval for level-2 CSNPs\n")
-{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
- {
- vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->csnp_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_csnp_interval_l2,
- no_csnp_interval_l2_cmd,
- "no isis csnp-interval level-2",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "Specify interval for level-2 CSNPs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_csnp_interval_l2,
- no_csnp_interval_l2_arg_cmd,
- "no isis csnp-interval <1-600> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set CSNP interval in seconds\n"
- "CSNP interval value\n"
- "Specify interval for level-2 CSNPs\n")
-
-DEFUN (psnp_interval,
- psnp_interval_cmd,
- "isis psnp-interval <1-120>",
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n")
-{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
- {
- vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->psnp_interval[0] = (u_int16_t) interval;
- circuit->psnp_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_psnp_interval,
- no_psnp_interval_cmd,
- "no isis psnp-interval",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
- circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_psnp_interval,
- no_psnp_interval_arg_cmd,
- "no isis psnp-interval <1-120>",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n")
-
-DEFUN (psnp_interval_l1,
- psnp_interval_l1_cmd,
- "isis psnp-interval <1-120> level-1",
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n"
- "Specify interval for level-1 PSNPs\n")
-{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
- {
- vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->psnp_interval[0] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_psnp_interval_l1,
- no_psnp_interval_l1_cmd,
- "no isis psnp-interval level-1",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "Specify interval for level-1 PSNPs\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
-
- return CMD_SUCCESS;
+ circuit->passwd.len = len;
+ strncpy((char *)circuit->passwd.passwd, passwd, 255);
+ circuit->passwd.type = passwd_type;
+ return 0;
}
-ALIAS (no_psnp_interval_l1,
- no_psnp_interval_l1_arg_cmd,
- "no isis psnp-interval <1-120> level-1",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n"
- "Specify interval for level-1 PSNPs\n")
-
-DEFUN (psnp_interval_l2,
- psnp_interval_l2_cmd,
- "isis psnp-interval <1-120> level-2",
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n"
- "Specify interval for level-2 PSNPs\n")
+int
+isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd)
{
- unsigned long interval;
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- interval = atol (argv[0]);
- if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
- {
- vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
- interval, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- circuit->psnp_interval[1] = (u_int16_t) interval;
-
- return CMD_SUCCESS;
+ return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd);
}
-DEFUN (no_psnp_interval_l2,
- no_psnp_interval_l2_cmd,
- "no isis psnp-interval level-2",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "Specify interval for level-2 PSNPs\n")
+int
+isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd)
{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
-
- return CMD_SUCCESS;
+ return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd);
}
-
-ALIAS (no_psnp_interval_l2,
- no_psnp_interval_l2_arg_cmd,
- "no isis psnp-interval <1-120> level-2",
- NO_STR
- "IS-IS commands\n"
- "Set PSNP interval in seconds\n"
- "PSNP interval value\n"
- "Specify interval for level-2 PSNPs\n")
-
struct cmd_node interface_node = {
INTERFACE_NODE,
"%s(config-if)# ",
1,
};
-DEFUN (isis_network,
- isis_network_cmd,
- "isis network point-to-point",
- "IS-IS commands\n"
- "Set network type\n"
- "point-to-point network type\n")
+int
+isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type)
{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- /* RFC5309 section 4 */
- if (circuit->circ_type == CIRCUIT_T_P2P)
- return CMD_SUCCESS;
-
- if (circuit->state != C_STATE_UP)
- {
- circuit->circ_type = CIRCUIT_T_P2P;
- circuit->circ_type_config = CIRCUIT_T_P2P;
- }
- else
+ /* Changing the network type to/of loopback or unknown interfaces
+ * is not supported. */
+ if (circ_type == CIRCUIT_T_UNKNOWN
+ || circ_type == CIRCUIT_T_LOOPBACK
+ || circuit->circ_type == CIRCUIT_T_LOOPBACK)
{
- struct isis_area *area = circuit->area;
- if (!if_is_broadcast (circuit->interface))
- {
- vty_out (vty, "isis network point-to-point "
- "is valid only on broadcast interfaces%s",
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- isis_csm_state_change (ISIS_DISABLE, circuit, area);
- circuit->circ_type = CIRCUIT_T_P2P;
- circuit->circ_type_config = CIRCUIT_T_P2P;
- isis_csm_state_change (ISIS_ENABLE, circuit, area);
+ if (circuit->circ_type != circ_type)
+ return -1;
+ else
+ return 0;
}
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_network,
- no_isis_network_cmd,
- "no isis network point-to-point",
- NO_STR
- "IS-IS commands\n"
- "Set network type for circuit\n"
- "point-to-point network type\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup (vty);
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- /* RFC5309 section 4 */
- if (circuit->circ_type == CIRCUIT_T_BROADCAST)
- return CMD_SUCCESS;
+ if (circuit->circ_type == circ_type)
+ return 0;
if (circuit->state != C_STATE_UP)
{
- circuit->circ_type = CIRCUIT_T_BROADCAST;
- circuit->circ_type_config = CIRCUIT_T_BROADCAST;
+ circuit->circ_type = circ_type;
+ circuit->circ_type_config = circ_type;
}
else
{
struct isis_area *area = circuit->area;
- if (circuit->interface &&
- !if_is_broadcast (circuit->interface))
- {
- vty_out (vty, "no isis network point-to-point "
- "is valid only on broadcast interfaces%s",
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
+ if (circ_type == CIRCUIT_T_BROADCAST
+ && !if_is_broadcast(circuit->interface))
+ return -1;
- isis_csm_state_change (ISIS_DISABLE, circuit, area);
- circuit->circ_type = CIRCUIT_T_BROADCAST;
- circuit->circ_type_config = CIRCUIT_T_BROADCAST;
- isis_csm_state_change (ISIS_ENABLE, circuit, area);
+ isis_csm_state_change(ISIS_DISABLE, circuit, area);
+ circuit->circ_type = circ_type;
+ circuit->circ_type_config = circ_type;
+ isis_csm_state_change(ISIS_ENABLE, circuit, area);
}
-
- return CMD_SUCCESS;
+ return 0;
}
int
@@ -2845,87 +1419,5 @@ isis_circuit_init ()
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
- install_element (INTERFACE_NODE, &ip_router_isis_cmd);
- install_element (INTERFACE_NODE, &no_ip_router_isis_cmd);
-
- install_element (INTERFACE_NODE, &isis_passive_cmd);
- install_element (INTERFACE_NODE, &no_isis_passive_cmd);
-
- install_element (INTERFACE_NODE, &isis_circuit_type_cmd);
- install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd);
-
- install_element (INTERFACE_NODE, &isis_passwd_clear_cmd);
- install_element (INTERFACE_NODE, &isis_passwd_md5_cmd);
- install_element (INTERFACE_NODE, &no_isis_passwd_cmd);
-
- install_element (INTERFACE_NODE, &isis_priority_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd);
- install_element (INTERFACE_NODE, &isis_priority_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_l1_arg_cmd);
- install_element (INTERFACE_NODE, &isis_priority_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_priority_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &isis_metric_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_arg_cmd);
- install_element (INTERFACE_NODE, &isis_metric_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_l1_arg_cmd);
- install_element (INTERFACE_NODE, &isis_metric_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &isis_hello_interval_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd);
- install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_arg_cmd);
- install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_arg_cmd);
- install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_arg_cmd);
- install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &isis_hello_padding_cmd);
- install_element (INTERFACE_NODE, &no_isis_hello_padding_cmd);
-
- install_element (INTERFACE_NODE, &csnp_interval_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_arg_cmd);
- install_element (INTERFACE_NODE, &csnp_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_l1_arg_cmd);
- install_element (INTERFACE_NODE, &csnp_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_csnp_interval_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &psnp_interval_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_arg_cmd);
- install_element (INTERFACE_NODE, &psnp_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_l1_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_l1_arg_cmd);
- install_element (INTERFACE_NODE, &psnp_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd);
- install_element (INTERFACE_NODE, &no_psnp_interval_l2_arg_cmd);
-
- install_element (INTERFACE_NODE, &isis_network_cmd);
- install_element (INTERFACE_NODE, &no_isis_network_cmd);
-
-#ifdef HAVE_IPV6
- install_element (INTERFACE_NODE, &ipv6_router_isis_cmd);
- install_element (INTERFACE_NODE, &no_ipv6_router_isis_cmd);
-#endif
+ isis_vty_init ();
}
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index d883879731..9ada1e26a3 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -24,6 +24,10 @@
#define ISIS_CIRCUIT_H
#include "vty.h"
+#include "if.h"
+
+#include "isis_constants.h"
+#include "isis_common.h"
#define CIRCUIT_MAX 255
@@ -108,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 */
- struct metric metrics[2]; /* l1XxxMetric */
+ 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 */
@@ -167,4 +172,16 @@ void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
size_t isis_circuit_pdu_size(struct isis_circuit *circuit);
void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream);
+struct isis_circuit *isis_circuit_create (struct isis_area *area, struct interface *ifp);
+void isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router);
+int isis_circuit_passive_set (struct isis_circuit *circuit, bool passive);
+void isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type);
+int isis_circuit_circ_type_set (struct isis_circuit *circuit, int circ_type);
+
+int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric);
+
+int isis_circuit_passwd_unset (struct isis_circuit *circuit);
+int isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd);
+int isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd);
+
#endif /* _ZEBRA_ISIS_CIRCUIT_H */
diff --git a/isisd/isis_events.c b/isisd/isis_events.c
index 0dee9e6f52..460b1d25ba 100644
--- a/isisd/isis_events.c
+++ b/isisd/isis_events.c
@@ -78,119 +78,6 @@ isis_event_circuit_state_change (struct isis_circuit *circuit,
}
static void
-area_resign_level (struct isis_area *area, int level)
-{
- if (area->lspdb[level - 1])
- {
- lsp_db_destroy (area->lspdb[level - 1]);
- area->lspdb[level - 1] = NULL;
- }
- if (area->spftree[level - 1])
- {
- isis_spftree_del (area->spftree[level - 1]);
- area->spftree[level - 1] = NULL;
- }
-#ifdef HAVE_IPV6
- if (area->spftree6[level - 1])
- {
- isis_spftree_del (area->spftree6[level - 1]);
- area->spftree6[level - 1] = NULL;
- }
-#endif
- if (area->route_table[level - 1])
- {
- route_table_finish (area->route_table[level - 1]);
- area->route_table[level - 1] = NULL;
- }
-#ifdef HAVE_IPV6
- if (area->route_table6[level - 1])
- {
- route_table_finish (area->route_table6[level - 1]);
- area->route_table6[level - 1] = NULL;
- }
-#endif /* HAVE_IPV6 */
-
- sched_debug("ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.",
- area->area_tag, level);
- THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]);
- area->lsp_regenerate_pending[level - 1] = 0;
-}
-
-void
-isis_event_system_type_change (struct isis_area *area, int newtype)
-{
- struct listnode *node;
- struct isis_circuit *circuit;
-
- if (isis->debugs & DEBUG_EVENTS)
- zlog_debug ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag,
- circuit_t2string (area->is_type), circuit_t2string (newtype));
-
- if (area->is_type == newtype)
- return; /* No change */
-
- switch (area->is_type)
- {
- case IS_LEVEL_1:
- if (newtype == IS_LEVEL_2)
- area_resign_level (area, IS_LEVEL_1);
-
- if (area->lspdb[1] == NULL)
- area->lspdb[1] = lsp_db_init ();
- if (area->route_table[1] == NULL)
- area->route_table[1] = route_table_init ();
-#ifdef HAVE_IPV6
- if (area->route_table6[1] == NULL)
- area->route_table6[1] = route_table_init ();
-#endif /* HAVE_IPV6 */
- break;
-
- case IS_LEVEL_1_AND_2:
- if (newtype == IS_LEVEL_1)
- area_resign_level (area, IS_LEVEL_2);
- else
- area_resign_level (area, IS_LEVEL_1);
- break;
-
- case IS_LEVEL_2:
- if (newtype == IS_LEVEL_1)
- area_resign_level (area, IS_LEVEL_2);
-
- if (area->lspdb[0] == NULL)
- area->lspdb[0] = lsp_db_init ();
- if (area->route_table[0] == NULL)
- area->route_table[0] = route_table_init ();
-#ifdef HAVE_IPV6
- if (area->route_table6[0] == NULL)
- area->route_table6[0] = route_table_init ();
-#endif /* HAVE_IPV6 */
- break;
-
- default:
- break;
- }
-
- area->is_type = newtype;
-
- /* override circuit's is_type */
- if (area->is_type != IS_LEVEL_1_AND_2)
- {
- for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
- isis_event_circuit_type_change (circuit, newtype);
- }
-
- spftree_area_init (area);
-
- if (newtype & IS_LEVEL_1)
- lsp_generate (area, IS_LEVEL_1);
- if (newtype & IS_LEVEL_2)
- lsp_generate (area, IS_LEVEL_2);
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
-
- return;
-}
-
-static void
circuit_commence_level (struct isis_circuit *circuit, int level)
{
if (level == 1)
@@ -258,7 +145,7 @@ circuit_resign_level (struct isis_circuit *circuit, int level)
}
void
-isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype)
+isis_circuit_is_type_set (struct isis_circuit *circuit, int newtype)
{
if (circuit->state != C_STATE_UP)
{
diff --git a/isisd/isis_events.h b/isisd/isis_events.h
index c252f3def9..e7cfa3509e 100644
--- a/isisd/isis_events.h
+++ b/isisd/isis_events.h
@@ -23,11 +23,6 @@
#define _ZEBRA_ISIS_EVENTS_H
/*
- * Events related to area
- */
-void isis_event_system_type_change (struct isis_area *area, int newtype);
-
-/*
* Events related to circuit
*/
void isis_event_circuit_state_change (struct isis_circuit *circuit,
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 7309248611..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)
{
@@ -1481,7 +1542,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
{
ipreach =
XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
- ipreach->metrics = circuit->metrics[level - 1];
+ ipreach->metrics.metric_default = circuit->metric[level - 1];
+ ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
masklen2ip (ipv4->prefixlen, &ipreach->mask);
ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
(ipv4->prefix.s_addr));
@@ -1506,7 +1570,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
((ipv4->prefixlen + 7)/8) - 1);
if (area->oldmetric)
- te_ipreach->te_metric = htonl (circuit->metrics[level - 1].metric_default);
+ te_ipreach->te_metric = htonl (circuit->metric[level - 1]);
else
te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]);
@@ -1541,7 +1605,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
if (area->oldmetric)
ip6reach->metric =
- htonl (circuit->metrics[level - 1].metric_default);
+ htonl (circuit->metric[level - 1]);
else
ip6reach->metric = htonl (circuit->te_metric[level - 1]);
@@ -1580,7 +1644,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
else
memcpy (is_neigh->neigh_id,
circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
- is_neigh->metrics = circuit->metrics[level - 1];
+ is_neigh->metrics.metric_default = circuit->metric[level - 1];
+ is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
if (!memcmp (is_neigh->neigh_id, zero_id,
ISIS_SYS_ID_LEN + 1))
{
@@ -1612,7 +1679,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
memcpy (te_is_neigh->neigh_id,
circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
if (area->oldmetric)
- metric = circuit->metrics[level - 1].metric_default;
+ metric = circuit->metric[level - 1];
else
metric = circuit->te_metric[level - 1];
SET_TE_METRIC(te_is_neigh, metric);
@@ -1625,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),
@@ -1651,7 +1726,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
}
is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
- is_neigh->metrics = circuit->metrics[level - 1];
+ is_neigh->metrics.metric_default = circuit->metric[level - 1];
+ is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
listnode_add (tlv_data.is_neighs, is_neigh);
lsp_debug("ISIS (%s): Adding old-style is reach for %s", area->area_tag,
sysid_print(is_neigh->neigh_id));
@@ -1670,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 f088bc1dec..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"
@@ -245,7 +247,9 @@ main (int argc, char **argv, char **envp)
zlog_default = openzlog (progname, ZLOG_ISIS, 0,
LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
zprivs_init (&isisd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME , zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* for reload */
_argc = argc;
@@ -346,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_redist.h b/isisd/isis_redist.h
index 2184620054..cc9c2e6345 100644
--- a/isisd/isis_redist.h
+++ b/isisd/isis_redist.h
@@ -44,6 +44,7 @@ struct isis_redist
struct isis_area;
struct prefix;
+struct vty;
struct route_table *get_ext_reach(struct isis_area *area,
int family, int level);
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_spf.c b/isisd/isis_spf.c
index 32026f9b17..fd5af4a2b8 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -545,13 +545,13 @@ isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
v = listgetdata (node);
if (v->d_N > vertex->d_N)
{
- list_add_node_prev (spftree->tents, node, vertex);
+ listnode_add_before (spftree->tents, node, vertex);
break;
}
else if (v->d_N == vertex->d_N && v->type > vertex->type)
{
/* Tie break, add according to type */
- list_add_node_prev (spftree->tents, node, vertex);
+ listnode_add_before (spftree->tents, node, vertex);
break;
}
}
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_vty.c b/isisd/isis_vty.c
new file mode 100644
index 0000000000..4148eb55b9
--- /dev/null
+++ b/isisd/isis_vty.c
@@ -0,0 +1,2428 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_circuit.h
+ *
+ * Copyright (C) 2001,2002 Sampo Saaristo
+ * Tampere University of Technology
+ * Institute of Communications Engineering
+ * Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public Licenseas published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include <command.h>
+
+#include "isis_circuit.h"
+#include "isis_csm.h"
+#include "isis_misc.h"
+#include "isisd.h"
+
+static struct isis_circuit *
+isis_circuit_lookup (struct vty *vty)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *) vty->index;
+ if (!ifp)
+ {
+ vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
+ return NULL;
+ }
+
+ circuit = circuit_scan_by_ifp (ifp);
+ if (!circuit)
+ {
+ vty_out (vty, "ISIS is not enabled on circuit %s%s",
+ ifp->name, VTY_NEWLINE);
+ return NULL;
+ }
+
+ return circuit;
+}
+
+DEFUN (ip_router_isis,
+ ip_router_isis_cmd,
+ "(ip|ipv6) router isis WORD",
+ "Interface Internet Protocol config commands\n"
+ "IP router interface commands\n"
+ "IS-IS Routing for IP\n"
+ "Routing process tag\n")
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_area *area;
+ const char *af = argv[0];
+ const char *area_tag = argv[1];
+
+ ifp = (struct interface *) vty->index;
+ assert (ifp);
+
+ /* Prevent more than one area per circuit */
+ circuit = circuit_scan_by_ifp (ifp);
+ if (circuit && circuit->area)
+ {
+ if (strcmp (circuit->area->area_tag, area_tag))
+ {
+ vty_out (vty, "ISIS circuit is already defined on %s%s",
+ circuit->area->area_tag, VTY_NEWLINE);
+ return CMD_ERR_NOTHING_TODO;
+ }
+ }
+
+ area = isis_area_lookup (area_tag);
+ if (!area)
+ area = isis_area_create (area_tag);
+
+ if (!circuit || !circuit->area) {
+ circuit = isis_circuit_create (area, ifp);
+
+ if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
+ {
+ vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
+ if (af[2] != '\0')
+ ipv6 = true;
+ else
+ ip = true;
+
+ isis_circuit_af_set (circuit, ip, ipv6);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_router_isis,
+ no_ip_router_isis_cmd,
+ "no (ip|ipv6) router isis WORD",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "IP router interface commands\n"
+ "IS-IS Routing for IP\n"
+ "Routing process tag\n")
+{
+ struct interface *ifp;
+ struct isis_area *area;
+ struct isis_circuit *circuit;
+ const char *af = argv[0];
+ const char *area_tag = argv[1];
+
+ ifp = (struct interface *) vty->index;
+ if (!ifp)
+ {
+ vty_out (vty, "Invalid interface %s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ area = isis_area_lookup (area_tag);
+ if (!area)
+ {
+ vty_out (vty, "Can't find ISIS instance %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
+ if (!circuit)
+ {
+ vty_out (vty, "ISIS is not enabled on circuit %s%s",
+ ifp->name, VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
+ if (af[2] != '\0')
+ ipv6 = false;
+ else
+ ip = false;
+
+ isis_circuit_af_set (circuit, ip, ipv6);
+ return CMD_SUCCESS;
+}
+
+DEFUN (isis_passive,
+ isis_passive_cmd,
+ "isis passive",
+ "IS-IS commands\n"
+ "Configure the passive mode for interface\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ isis_circuit_passive_set (circuit, 1);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_passive,
+ no_isis_passive_cmd,
+ "no isis passive",
+ NO_STR
+ "IS-IS commands\n"
+ "Configure the passive mode for interface\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (if_is_loopback (circuit->interface))
+ {
+ vty_out (vty, "Can't set no passive for loopback interface%s",
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ isis_circuit_passive_set (circuit, 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN (isis_circuit_type,
+ isis_circuit_type_cmd,
+ "isis circuit-type (level-1|level-1-2|level-2-only)",
+ "IS-IS commands\n"
+ "Configure circuit type for interface\n"
+ "Level-1 only adjacencies are formed\n"
+ "Level-1-2 adjacencies are formed\n"
+ "Level-2 only adjacencies are formed\n")
+{
+ int is_type;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ is_type = string2circuit_t (argv[0]);
+ if (!is_type)
+ {
+ vty_out (vty, "Unknown circuit-type %s", VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ if (circuit->state == C_STATE_UP &&
+ circuit->area->is_type != IS_LEVEL_1_AND_2 &&
+ circuit->area->is_type != is_type)
+ {
+ vty_out (vty, "Invalid circuit level for area %s.%s",
+ circuit->area->area_tag, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ isis_circuit_is_type_set (circuit, is_type);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_circuit_type,
+ no_isis_circuit_type_cmd,
+ "no isis circuit-type (level-1|level-1-2|level-2-only)",
+ NO_STR
+ "IS-IS commands\n"
+ "Configure circuit type for interface\n"
+ "Level-1 only adjacencies are formed\n"
+ "Level-1-2 adjacencies are formed\n"
+ "Level-2 only adjacencies are formed\n")
+{
+ int is_type;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ /*
+ * Set the circuits level to its default value
+ */
+ if (circuit->state == C_STATE_UP)
+ is_type = circuit->area->is_type;
+ else
+ is_type = IS_LEVEL_1_AND_2;
+ isis_circuit_is_type_set (circuit, is_type);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (isis_network,
+ isis_network_cmd,
+ "isis network point-to-point",
+ "IS-IS commands\n"
+ "Set network type\n"
+ "point-to-point network type\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P))
+ {
+ vty_out (vty, "isis network point-to-point "
+ "is valid only on broadcast interfaces%s",
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_network,
+ no_isis_network_cmd,
+ "no isis network point-to-point",
+ NO_STR
+ "IS-IS commands\n"
+ "Set network type for circuit\n"
+ "point-to-point network type\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST))
+ {
+ vty_out (vty, "isis network point-to-point "
+ "is valid only on broadcast interfaces%s",
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (isis_passwd,
+ isis_passwd_cmd,
+ "isis password (md5|clear) WORD",
+ "IS-IS commands\n"
+ "Configure the authentication password for a circuit\n"
+ "HMAC-MD5 authentication\n"
+ "Cleartext password\n"
+ "Circuit password\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ int rv;
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (argv[0][0] == 'm')
+ rv = isis_circuit_passwd_hmac_md5_set(circuit, argv[1]);
+ else
+ rv = isis_circuit_passwd_cleartext_set(circuit, argv[1]);
+ if (rv)
+ {
+ vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_passwd,
+ no_isis_passwd_cmd,
+ "no isis password",
+ NO_STR
+ "IS-IS commands\n"
+ "Configure the authentication password for a circuit\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ isis_circuit_passwd_unset(circuit);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_passwd,
+ no_isis_passwd_arg_cmd,
+ "no isis password (md5|clear) WORD",
+ NO_STR
+ "IS-IS commands\n"
+ "Configure the authentication password for a circuit\n"
+ "HMAC-MD5 authentication\n"
+ "Cleartext password\n"
+ "Circuit password\n")
+
+DEFUN (isis_priority,
+ isis_priority_cmd,
+ "isis priority <0-127>",
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n")
+{
+ int prio;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ prio = atoi (argv[0]);
+ if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
+ {
+ vty_out (vty, "Invalid priority %d - should be <0-127>%s",
+ prio, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->priority[0] = prio;
+ circuit->priority[1] = prio;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority,
+ no_isis_priority_cmd,
+ "no isis priority",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->priority[0] = DEFAULT_PRIORITY;
+ circuit->priority[1] = DEFAULT_PRIORITY;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority,
+ no_isis_priority_arg_cmd,
+ "no isis priority <0-127>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n")
+
+DEFUN (isis_priority_l1,
+ isis_priority_l1_cmd,
+ "isis priority <0-127> level-1",
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n"
+ "Specify priority for level-1 routing\n")
+{
+ int prio;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ prio = atoi (argv[0]);
+ if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
+ {
+ vty_out (vty, "Invalid priority %d - should be <0-127>%s",
+ prio, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->priority[0] = prio;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority_l1,
+ no_isis_priority_l1_cmd,
+ "no isis priority level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Specify priority for level-1 routing\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->priority[0] = DEFAULT_PRIORITY;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority_l1,
+ no_isis_priority_l1_arg_cmd,
+ "no isis priority <0-127> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n"
+ "Specify priority for level-1 routing\n")
+
+DEFUN (isis_priority_l2,
+ isis_priority_l2_cmd,
+ "isis priority <0-127> level-2",
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n"
+ "Specify priority for level-2 routing\n")
+{
+ int prio;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ prio = atoi (argv[0]);
+ if (prio < MIN_PRIORITY || prio > MAX_PRIORITY)
+ {
+ vty_out (vty, "Invalid priority %d - should be <0-127>%s",
+ prio, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->priority[1] = prio;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority_l2,
+ no_isis_priority_l2_cmd,
+ "no isis priority level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Specify priority for level-2 routing\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->priority[1] = DEFAULT_PRIORITY;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority_l2,
+ no_isis_priority_l2_arg_cmd,
+ "no isis priority <0-127> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set priority for Designated Router election\n"
+ "Priority value\n"
+ "Specify priority for level-2 routing\n")
+
+/* Metric command */
+DEFUN (isis_metric,
+ isis_metric_cmd,
+ "isis metric <0-16777215>",
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n")
+{
+ int met;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ met = atoi (argv[0]);
+
+ /* RFC3787 section 5.1 */
+ if (circuit->area && circuit->area->oldmetric == 1 &&
+ met > MAX_NARROW_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-63> "
+ "when narrow metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ /* RFC4444 */
+ if (circuit->area && circuit->area->newmetric == 1 &&
+ met > MAX_WIDE_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-16777215> "
+ "when wide metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_1, met);
+ isis_circuit_metric_set (circuit, IS_LEVEL_2, met);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_metric,
+ no_isis_metric_cmd,
+ "no isis metric",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC);
+ isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_metric,
+ no_isis_metric_arg_cmd,
+ "no isis metric <0-16777215>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n")
+
+DEFUN (isis_metric_l1,
+ isis_metric_l1_cmd,
+ "isis metric <0-16777215> level-1",
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n"
+ "Specify metric for level-1 routing\n")
+{
+ int met;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ met = atoi (argv[0]);
+
+ /* RFC3787 section 5.1 */
+ if (circuit->area && circuit->area->oldmetric == 1 &&
+ met > MAX_NARROW_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-63> "
+ "when narrow metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ /* RFC4444 */
+ if (circuit->area && circuit->area->newmetric == 1 &&
+ met > MAX_WIDE_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-16777215> "
+ "when wide metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_1, met);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_metric_l1,
+ no_isis_metric_l1_cmd,
+ "no isis metric level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Specify metric for level-1 routing\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_metric_l1,
+ no_isis_metric_l1_arg_cmd,
+ "no isis metric <0-16777215> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n"
+ "Specify metric for level-1 routing\n")
+
+DEFUN (isis_metric_l2,
+ isis_metric_l2_cmd,
+ "isis metric <0-16777215> level-2",
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n"
+ "Specify metric for level-2 routing\n")
+{
+ int met;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ met = atoi (argv[0]);
+
+ /* RFC3787 section 5.1 */
+ if (circuit->area && circuit->area->oldmetric == 1 &&
+ met > MAX_NARROW_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-63> "
+ "when narrow metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ /* RFC4444 */
+ if (circuit->area && circuit->area->newmetric == 1 &&
+ met > MAX_WIDE_LINK_METRIC)
+ {
+ vty_out (vty, "Invalid metric %d - should be <0-16777215> "
+ "when wide metric type enabled%s",
+ met, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_2, met);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_metric_l2,
+ no_isis_metric_l2_cmd,
+ "no isis metric level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Specify metric for level-2 routing\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_metric_l2,
+ no_isis_metric_l2_arg_cmd,
+ "no isis metric <0-16777215> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set default metric for circuit\n"
+ "Default metric value\n"
+ "Specify metric for level-2 routing\n")
+/* end of metrics */
+
+DEFUN (isis_hello_interval,
+ isis_hello_interval_cmd,
+ "isis hello-interval <1-600>",
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 seconds, interval depends on multiplier\n")
+{
+ int interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atoi (argv[0]);
+ if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
+ {
+ vty_out (vty, "Invalid hello-interval %d - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_interval[0] = (u_int16_t) interval;
+ circuit->hello_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval,
+ no_isis_hello_interval_cmd,
+ "no isis hello-interval",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
+ circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval,
+ no_isis_hello_interval_arg_cmd,
+ "no isis hello-interval <1-600>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 second, interval depends on multiplier\n")
+
+DEFUN (isis_hello_interval_l1,
+ isis_hello_interval_l1_cmd,
+ "isis hello-interval <1-600> level-1",
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 second, interval depends on multiplier\n"
+ "Specify hello-interval for level-1 IIHs\n")
+{
+ long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atoi (argv[0]);
+ if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
+ {
+ vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_interval[0] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval_l1,
+ no_isis_hello_interval_l1_cmd,
+ "no isis hello-interval level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Specify hello-interval for level-1 IIHs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval_l1,
+ no_isis_hello_interval_l1_arg_cmd,
+ "no isis hello-interval <1-600> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 second, interval depends on multiplier\n"
+ "Specify hello-interval for level-1 IIHs\n")
+
+DEFUN (isis_hello_interval_l2,
+ isis_hello_interval_l2_cmd,
+ "isis hello-interval <1-600> level-2",
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 second, interval depends on multiplier\n"
+ "Specify hello-interval for level-2 IIHs\n")
+{
+ long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atoi (argv[0]);
+ if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL)
+ {
+ vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval_l2,
+ no_isis_hello_interval_l2_cmd,
+ "no isis hello-interval level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Specify hello-interval for level-2 IIHs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval_l2,
+ no_isis_hello_interval_l2_arg_cmd,
+ "no isis hello-interval <1-600> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set Hello interval\n"
+ "Hello interval value\n"
+ "Holdtime 1 second, interval depends on multiplier\n"
+ "Specify hello-interval for level-2 IIHs\n")
+
+DEFUN (isis_hello_multiplier,
+ isis_hello_multiplier_cmd,
+ "isis hello-multiplier <2-100>",
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n")
+{
+ int mult;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ mult = atoi (argv[0]);
+ if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
+ {
+ vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
+ mult, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_multiplier[0] = (u_int16_t) mult;
+ circuit->hello_multiplier[1] = (u_int16_t) mult;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier,
+ no_isis_hello_multiplier_cmd,
+ "no isis hello-multiplier",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
+ circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier,
+ no_isis_hello_multiplier_arg_cmd,
+ "no isis hello-multiplier <2-100>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n")
+
+DEFUN (isis_hello_multiplier_l1,
+ isis_hello_multiplier_l1_cmd,
+ "isis hello-multiplier <2-100> level-1",
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n"
+ "Specify hello multiplier for level-1 IIHs\n")
+{
+ int mult;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ mult = atoi (argv[0]);
+ if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
+ {
+ vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
+ mult, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_multiplier[0] = (u_int16_t) mult;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier_l1,
+ no_isis_hello_multiplier_l1_cmd,
+ "no isis hello-multiplier level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Specify hello multiplier for level-1 IIHs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier_l1,
+ no_isis_hello_multiplier_l1_arg_cmd,
+ "no isis hello-multiplier <2-100> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n"
+ "Specify hello multiplier for level-1 IIHs\n")
+
+DEFUN (isis_hello_multiplier_l2,
+ isis_hello_multiplier_l2_cmd,
+ "isis hello-multiplier <2-100> level-2",
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n"
+ "Specify hello multiplier for level-2 IIHs\n")
+{
+ int mult;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ mult = atoi (argv[0]);
+ if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER)
+ {
+ vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s",
+ mult, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->hello_multiplier[1] = (u_int16_t) mult;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier_l2,
+ no_isis_hello_multiplier_l2_cmd,
+ "no isis hello-multiplier level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Specify hello multiplier for level-2 IIHs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier_l2,
+ no_isis_hello_multiplier_l2_arg_cmd,
+ "no isis hello-multiplier <2-100> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set multiplier for Hello holding time\n"
+ "Hello multiplier value\n"
+ "Specify hello multiplier for level-2 IIHs\n")
+
+DEFUN (isis_hello_padding,
+ isis_hello_padding_cmd,
+ "isis hello padding",
+ "IS-IS commands\n"
+ "Add padding to IS-IS hello packets\n"
+ "Pad hello packets\n"
+ "<cr>\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->pad_hellos = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_padding,
+ no_isis_hello_padding_cmd,
+ "no isis hello padding",
+ NO_STR
+ "IS-IS commands\n"
+ "Add padding to IS-IS hello packets\n"
+ "Pad hello packets\n"
+ "<cr>\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->pad_hellos = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (csnp_interval,
+ csnp_interval_cmd,
+ "isis csnp-interval <1-600>",
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->csnp_interval[0] = (u_int16_t) interval;
+ circuit->csnp_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval,
+ no_csnp_interval_cmd,
+ "no isis csnp-interval",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
+ circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval,
+ no_csnp_interval_arg_cmd,
+ "no isis csnp-interval <1-600>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n")
+
+DEFUN (csnp_interval_l1,
+ csnp_interval_l1_cmd,
+ "isis csnp-interval <1-600> level-1",
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n"
+ "Specify interval for level-1 CSNPs\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->csnp_interval[0] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval_l1,
+ no_csnp_interval_l1_cmd,
+ "no isis csnp-interval level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "Specify interval for level-1 CSNPs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval_l1,
+ no_csnp_interval_l1_arg_cmd,
+ "no isis csnp-interval <1-600> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n"
+ "Specify interval for level-1 CSNPs\n")
+
+DEFUN (csnp_interval_l2,
+ csnp_interval_l2_cmd,
+ "isis csnp-interval <1-600> level-2",
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n"
+ "Specify interval for level-2 CSNPs\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->csnp_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval_l2,
+ no_csnp_interval_l2_cmd,
+ "no isis csnp-interval level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "Specify interval for level-2 CSNPs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval_l2,
+ no_csnp_interval_l2_arg_cmd,
+ "no isis csnp-interval <1-600> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set CSNP interval in seconds\n"
+ "CSNP interval value\n"
+ "Specify interval for level-2 CSNPs\n")
+
+DEFUN (psnp_interval,
+ psnp_interval_cmd,
+ "isis psnp-interval <1-120>",
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->psnp_interval[0] = (u_int16_t) interval;
+ circuit->psnp_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_psnp_interval,
+ no_psnp_interval_cmd,
+ "no isis psnp-interval",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
+ circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_psnp_interval,
+ no_psnp_interval_arg_cmd,
+ "no isis psnp-interval <1-120>",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n")
+
+DEFUN (psnp_interval_l1,
+ psnp_interval_l1_cmd,
+ "isis psnp-interval <1-120> level-1",
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n"
+ "Specify interval for level-1 PSNPs\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->psnp_interval[0] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_psnp_interval_l1,
+ no_psnp_interval_l1_cmd,
+ "no isis psnp-interval level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "Specify interval for level-1 PSNPs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_psnp_interval_l1,
+ no_psnp_interval_l1_arg_cmd,
+ "no isis psnp-interval <1-120> level-1",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n"
+ "Specify interval for level-1 PSNPs\n")
+
+DEFUN (psnp_interval_l2,
+ psnp_interval_l2_cmd,
+ "isis psnp-interval <1-120> level-2",
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n"
+ "Specify interval for level-2 PSNPs\n")
+{
+ unsigned long interval;
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ interval = atol (argv[0]);
+ if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL)
+ {
+ vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s",
+ interval, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ circuit->psnp_interval[1] = (u_int16_t) interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_psnp_interval_l2,
+ no_psnp_interval_l2_cmd,
+ "no isis psnp-interval level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "Specify interval for level-2 PSNPs\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup (vty);
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_psnp_interval_l2,
+ no_psnp_interval_l2_arg_cmd,
+ "no isis psnp-interval <1-120> level-2",
+ NO_STR
+ "IS-IS commands\n"
+ "Set PSNP interval in seconds\n"
+ "PSNP interval value\n"
+ "Specify interval for level-2 PSNPs\n")
+
+static int
+validate_metric_style_narrow (struct vty *vty, struct isis_area *area)
+{
+ struct isis_circuit *circuit;
+ struct listnode *node;
+
+ if (! vty)
+ return CMD_ERR_AMBIGUOUS;
+
+ if (! area)
+ {
+ vty_out (vty, "ISIS area is invalid%s", VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
+ {
+ if ((area->is_type & IS_LEVEL_1) &&
+ (circuit->is_type & IS_LEVEL_1) &&
+ (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC))
+ {
+ vty_out (vty, "ISIS circuit %s metric is invalid%s",
+ circuit->interface->name, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ if ((area->is_type & IS_LEVEL_2) &&
+ (circuit->is_type & IS_LEVEL_2) &&
+ (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC))
+ {
+ vty_out (vty, "ISIS circuit %s metric is invalid%s",
+ circuit->interface->name, VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (metric_style,
+ metric_style_cmd,
+ "metric-style (narrow|transition|wide)",
+ "Use old-style (ISO 10589) or new-style packet formats\n"
+ "Use old style of TLVs with narrow metric\n"
+ "Send and accept both styles of TLVs during transition\n"
+ "Use new style of TLVs to carry wider metric\n")
+{
+ struct isis_area *area = vty->index;
+ int ret;
+
+ assert(area);
+
+ if (strncmp (argv[0], "w", 1) == 0)
+ {
+ isis_area_metricstyle_set(area, false, true);
+ return CMD_SUCCESS;
+ }
+
+ ret = validate_metric_style_narrow (vty, area);
+ if (ret != CMD_SUCCESS)
+ return ret;
+
+ if (strncmp (argv[0], "t", 1) == 0)
+ isis_area_metricstyle_set(area, true, true);
+ else if (strncmp (argv[0], "n", 1) == 0)
+ isis_area_metricstyle_set(area, true, false);
+ return CMD_SUCCESS;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_metric_style,
+ no_metric_style_cmd,
+ "no metric-style",
+ NO_STR
+ "Use old-style (ISO 10589) or new-style packet formats\n")
+{
+ struct isis_area *area = vty->index;
+ int ret;
+
+ assert (area);
+ ret = validate_metric_style_narrow (vty, area);
+ if (ret != CMD_SUCCESS)
+ return ret;
+
+ isis_area_metricstyle_set(area, true, false);
+ return CMD_SUCCESS;
+}
+
+DEFUN (set_overload_bit,
+ set_overload_bit_cmd,
+ "set-overload-bit",
+ "Set overload bit to avoid any transit traffic\n"
+ "Set overload bit\n")
+{
+ struct isis_area *area = vty->index;
+ assert (area);
+
+ isis_area_overload_bit_set(area, true);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_set_overload_bit,
+ no_set_overload_bit_cmd,
+ "no set-overload-bit",
+ "Reset overload bit to accept transit traffic\n"
+ "Reset overload bit\n")
+{
+ struct isis_area *area = vty->index;
+ assert (area);
+
+ isis_area_overload_bit_set(area, false);
+ return CMD_SUCCESS;
+}
+
+DEFUN (set_attached_bit,
+ set_attached_bit_cmd,
+ "set-attached-bit",
+ "Set attached bit to identify as L1/L2 router for inter-area traffic\n"
+ "Set attached bit\n")
+{
+ struct isis_area *area = vty->index;
+ assert (area);
+
+ isis_area_attached_bit_set(area, true);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_set_attached_bit,
+ no_set_attached_bit_cmd,
+ "no set-attached-bit",
+ "Reset attached bit\n")
+{
+ struct isis_area *area = vty->index;
+ assert (area);
+
+ isis_area_attached_bit_set(area, false);
+ return CMD_SUCCESS;
+}
+
+DEFUN (dynamic_hostname,
+ dynamic_hostname_cmd,
+ "hostname dynamic",
+ "Dynamic hostname for IS-IS\n"
+ "Dynamic hostname\n")
+{
+ struct isis_area *area = vty->index;
+ assert(area);
+
+ isis_area_dynhostname_set(area, true);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_dynamic_hostname,
+ no_dynamic_hostname_cmd,
+ "no hostname dynamic",
+ NO_STR
+ "Dynamic hostname for IS-IS\n"
+ "Dynamic hostname\n")
+{
+ struct isis_area *area = vty->index;
+ assert(area);
+
+ isis_area_dynhostname_set(area, false);
+ return CMD_SUCCESS;
+}
+
+static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu)
+{
+ struct isis_area *area = vty->index;
+ struct listnode *node;
+ struct isis_circuit *circuit;
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+ {
+ if(circuit->state != C_STATE_INIT && circuit->state != C_STATE_UP)
+ continue;
+ if(lsp_mtu > isis_circuit_pdu_size(circuit))
+ {
+ vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s",
+ circuit->interface->name, isis_circuit_pdu_size(circuit),
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ }
+
+ isis_area_lsp_mtu_set(area, lsp_mtu);
+ return CMD_SUCCESS;
+}
+
+DEFUN (area_lsp_mtu,
+ area_lsp_mtu_cmd,
+ "lsp-mtu <128-4352>",
+ "Configure the maximum size of generated LSPs\n"
+ "Maximum size of generated LSPs\n")
+{
+ unsigned int lsp_mtu;
+
+ VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352);
+
+ return area_lsp_mtu_set(vty, lsp_mtu);
+}
+
+DEFUN(no_area_lsp_mtu,
+ no_area_lsp_mtu_cmd,
+ "no lsp-mtu",
+ NO_STR
+ "Configure the maximum size of generated LSPs\n")
+{
+ return area_lsp_mtu_set(vty, DEFAULT_LSP_MTU);
+}
+
+ALIAS(no_area_lsp_mtu,
+ no_area_lsp_mtu_arg_cmd,
+ "no lsp-mtu <128-4352>",
+ NO_STR
+ "Configure the maximum size of generated LSPs\n"
+ "Maximum size of generated LSPs\n");
+
+DEFUN (is_type,
+ is_type_cmd,
+ "is-type (level-1|level-1-2|level-2-only)",
+ "IS Level for this routing process (OSI only)\n"
+ "Act as a station router only\n"
+ "Act as both a station router and an area router\n"
+ "Act as an area router only\n")
+{
+ struct isis_area *area;
+ int type;
+
+ area = vty->index;
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ type = string2circuit_t (argv[0]);
+ if (!type)
+ {
+ vty_out (vty, "Unknown IS level %s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ isis_area_is_type_set(area, type);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_is_type,
+ no_is_type_cmd,
+ "no is-type (level-1|level-1-2|level-2-only)",
+ NO_STR
+ "IS Level for this routing process (OSI only)\n"
+ "Act as a station router only\n"
+ "Act as both a station router and an area router\n"
+ "Act as an area router only\n")
+{
+ struct isis_area *area;
+ int type;
+
+ area = vty->index;
+ assert (area);
+
+ /*
+ * Put the is-type back to defaults:
+ * - level-1-2 on first area
+ * - level-1 for the rest
+ */
+ if (listgetdata (listhead (isis->area_list)) == area)
+ type = IS_LEVEL_1_AND_2;
+ else
+ type = IS_LEVEL_1;
+
+ isis_area_is_type_set(area, type);
+
+ return CMD_SUCCESS;
+}
+
+static int
+set_lsp_gen_interval (struct vty *vty, struct isis_area *area,
+ uint16_t interval, int level)
+{
+ int lvl;
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+ {
+ if (!(lvl & level))
+ continue;
+
+ if (interval >= area->lsp_refresh[lvl-1])
+ {
+ vty_out (vty, "LSP gen interval %us must be less than "
+ "the LSP refresh interval %us%s",
+ interval, area->lsp_refresh[lvl-1], VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ }
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+ {
+ if (!(lvl & level))
+ continue;
+ area->lsp_gen_interval[lvl-1] = interval;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (lsp_gen_interval,
+ lsp_gen_interval_cmd,
+ "lsp-gen-interval <1-120>",
+ "Minimum interval between regenerating same LSP\n"
+ "Minimum interval in seconds\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ level = IS_LEVEL_1 | IS_LEVEL_2;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+DEFUN (no_lsp_gen_interval,
+ no_lsp_gen_interval_cmd,
+ "no lsp-gen-interval",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
+ level = IS_LEVEL_1 | IS_LEVEL_2;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+ALIAS (no_lsp_gen_interval,
+ no_lsp_gen_interval_arg_cmd,
+ "no lsp-gen-interval <1-120>",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n"
+ "Minimum interval in seconds\n")
+
+DEFUN (lsp_gen_interval_l1,
+ lsp_gen_interval_l1_cmd,
+ "lsp-gen-interval level-1 <1-120>",
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 1 only\n"
+ "Minimum interval in seconds\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ level = IS_LEVEL_1;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+DEFUN (no_lsp_gen_interval_l1,
+ no_lsp_gen_interval_l1_cmd,
+ "no lsp-gen-interval level-1",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 1 only\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
+ level = IS_LEVEL_1;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+ALIAS (no_lsp_gen_interval_l1,
+ no_lsp_gen_interval_l1_arg_cmd,
+ "no lsp-gen-interval level-1 <1-120>",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 1 only\n"
+ "Minimum interval in seconds\n")
+
+DEFUN (lsp_gen_interval_l2,
+ lsp_gen_interval_l2_cmd,
+ "lsp-gen-interval level-2 <1-120>",
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 2 only\n"
+ "Minimum interval in seconds\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ level = IS_LEVEL_2;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+DEFUN (no_lsp_gen_interval_l2,
+ no_lsp_gen_interval_l2_cmd,
+ "no lsp-gen-interval level-2",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 2 only\n")
+{
+ struct isis_area *area;
+ uint16_t interval;
+ int level;
+
+ area = vty->index;
+ interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
+ level = IS_LEVEL_2;
+ return set_lsp_gen_interval (vty, area, interval, level);
+}
+
+ALIAS (no_lsp_gen_interval_l2,
+ no_lsp_gen_interval_l2_arg_cmd,
+ "no lsp-gen-interval level-2 <1-120>",
+ NO_STR
+ "Minimum interval between regenerating same LSP\n"
+ "Set interval for level 2 only\n"
+ "Minimum interval in seconds\n")
+
+DEFUN (spf_interval,
+ spf_interval_cmd,
+ "spf-interval <1-120>",
+ "Minimum interval between SPF calculations\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+{
+ struct isis_area *area;
+ u_int16_t interval;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ area->min_spf_interval[0] = interval;
+ area->min_spf_interval[1] = interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval,
+ no_spf_interval_cmd,
+ "no spf-interval",
+ NO_STR
+ "Minimum interval between SPF calculations\n")
+{
+ struct isis_area *area;
+
+ area = vty->index;
+
+ area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
+ area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+ no_spf_interval_arg_cmd,
+ "no spf-interval <1-120>",
+ NO_STR
+ "Minimum interval between SPF calculations\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+
+DEFUN (spf_interval_l1,
+ spf_interval_l1_cmd,
+ "spf-interval level-1 <1-120>",
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 1 only\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+{
+ struct isis_area *area;
+ u_int16_t interval;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ area->min_spf_interval[0] = interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval_l1,
+ no_spf_interval_l1_cmd,
+ "no spf-interval level-1",
+ NO_STR
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 1 only\n")
+{
+ struct isis_area *area;
+
+ area = vty->index;
+
+ area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+ no_spf_interval_l1_arg_cmd,
+ "no spf-interval level-1 <1-120>",
+ NO_STR
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 1 only\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+
+DEFUN (spf_interval_l2,
+ spf_interval_l2_cmd,
+ "spf-interval level-2 <1-120>",
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 2 only\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+{
+ struct isis_area *area;
+ u_int16_t interval;
+
+ area = vty->index;
+ interval = atoi (argv[0]);
+ area->min_spf_interval[1] = interval;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval_l2,
+ no_spf_interval_l2_cmd,
+ "no spf-interval level-2",
+ NO_STR
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 2 only\n")
+{
+ struct isis_area *area;
+
+ area = vty->index;
+
+ area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+ no_spf_interval_l2_arg_cmd,
+ "no spf-interval level-2 <1-120>",
+ NO_STR
+ "Minimum interval between SPF calculations\n"
+ "Set interval for level 2 only\n"
+ "Minimum interval between consecutive SPFs in seconds\n")
+
+static int
+area_max_lsp_lifetime_set(struct vty *vty, int level,
+ uint16_t interval)
+{
+ struct isis_area *area = vty->index;
+ int lvl;
+ uint16_t refresh_interval = interval - 300;
+ int set_refresh_interval[ISIS_LEVELS] = {0, 0};
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
+ {
+ if (!(lvl & level))
+ continue;
+
+ if (refresh_interval < area->lsp_refresh[lvl-1])
+ {
+ vty_out (vty, "Level %d Max LSP lifetime %us must be 300s greater than "
+ "the configured LSP refresh interval %us%s",
+ lvl, interval, area->lsp_refresh[lvl-1], VTY_NEWLINE);
+ vty_out (vty, "Automatically reducing level %d LSP refresh interval "
+ "to %us%s", lvl, refresh_interval, VTY_NEWLINE);
+ set_refresh_interval[lvl-1] = 1;
+
+ if (refresh_interval <= area->lsp_gen_interval[lvl-1])
+ {
+ vty_out (vty, "LSP refresh interval %us must be greater than "
+ "the configured LSP gen interval %us%s",
+ refresh_interval, area->lsp_gen_interval[lvl-1],
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ }
+ }
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
+ {
+ if (!(lvl & level))
+ continue;
+ isis_area_max_lsp_lifetime_set(area, lvl, interval);
+ if (set_refresh_interval[lvl-1])
+ isis_area_lsp_refresh_set(area, lvl, refresh_interval);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (max_lsp_lifetime,
+ max_lsp_lifetime_cmd,
+ "max-lsp-lifetime <350-65535>",
+ "Maximum LSP lifetime\n"
+ "LSP lifetime in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2, atoi(argv[0]));
+}
+
+DEFUN (no_max_lsp_lifetime,
+ no_max_lsp_lifetime_cmd,
+ "no max-lsp-lifetime",
+ NO_STR
+ "LSP lifetime in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2,
+ DEFAULT_LSP_LIFETIME);
+}
+
+ALIAS (no_max_lsp_lifetime,
+ no_max_lsp_lifetime_arg_cmd,
+ "no max-lsp-lifetime <350-65535>",
+ NO_STR
+ "Maximum LSP lifetime\n"
+ "LSP lifetime in seconds\n")
+
+DEFUN (max_lsp_lifetime_l1,
+ max_lsp_lifetime_l1_cmd,
+ "max-lsp-lifetime level-1 <350-65535>",
+ "Maximum LSP lifetime for Level 1 only\n"
+ "LSP lifetime for Level 1 only in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_1, atoi(argv[0]));
+}
+
+DEFUN (no_max_lsp_lifetime_l1,
+ no_max_lsp_lifetime_l1_cmd,
+ "no max-lsp-lifetime level-1",
+ NO_STR
+ "LSP lifetime for Level 1 only in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_1, DEFAULT_LSP_LIFETIME);
+}
+
+ALIAS (no_max_lsp_lifetime_l1,
+ no_max_lsp_lifetime_l1_arg_cmd,
+ "no max-lsp-lifetime level-1 <350-65535>",
+ NO_STR
+ "Maximum LSP lifetime for Level 1 only\n"
+ "LSP lifetime for Level 1 only in seconds\n")
+
+DEFUN (max_lsp_lifetime_l2,
+ max_lsp_lifetime_l2_cmd,
+ "max-lsp-lifetime level-2 <350-65535>",
+ "Maximum LSP lifetime for Level 2 only\n"
+ "LSP lifetime for Level 2 only in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_2, atoi(argv[0]));
+}
+
+DEFUN (no_max_lsp_lifetime_l2,
+ no_max_lsp_lifetime_l2_cmd,
+ "no max-lsp-lifetime level-2",
+ NO_STR
+ "LSP lifetime for Level 2 only in seconds\n")
+{
+ return area_max_lsp_lifetime_set(vty, IS_LEVEL_2, DEFAULT_LSP_LIFETIME);
+}
+
+ALIAS (no_max_lsp_lifetime_l2,
+ no_max_lsp_lifetime_l2_arg_cmd,
+ "no max-lsp-lifetime level-2 <350-65535>",
+ NO_STR
+ "Maximum LSP lifetime for Level 2 only\n"
+ "LSP lifetime for Level 2 only in seconds\n")
+
+static int
+area_lsp_refresh_interval_set(struct vty *vty, int level, uint16_t interval)
+{
+ struct isis_area *area = vty->index;
+ int lvl;
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+ {
+ if (!(lvl & level))
+ continue;
+ if (interval <= area->lsp_gen_interval[lvl-1])
+ {
+ vty_out (vty, "LSP refresh interval %us must be greater than "
+ "the configured LSP gen interval %us%s",
+ interval, area->lsp_gen_interval[lvl-1],
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ if (interval > (area->max_lsp_lifetime[lvl-1] - 300))
+ {
+ vty_out (vty, "LSP refresh interval %us must be less than "
+ "the configured LSP lifetime %us less 300%s",
+ interval, area->max_lsp_lifetime[lvl-1],
+ VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+ }
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+ {
+ if (!(lvl & level))
+ continue;
+ isis_area_lsp_refresh_set(area, lvl, interval);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (lsp_refresh_interval,
+ lsp_refresh_interval_cmd,
+ "lsp-refresh-interval <1-65235>",
+ "LSP refresh interval\n"
+ "LSP refresh interval in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_1_AND_2, atoi(argv[0]));
+}
+
+DEFUN (no_lsp_refresh_interval,
+ no_lsp_refresh_interval_cmd,
+ "no lsp-refresh-interval",
+ NO_STR
+ "LSP refresh interval in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_1_AND_2,
+ DEFAULT_MAX_LSP_GEN_INTERVAL);
+}
+
+ALIAS (no_lsp_refresh_interval,
+ no_lsp_refresh_interval_arg_cmd,
+ "no lsp-refresh-interval <1-65235>",
+ NO_STR
+ "LSP refresh interval\n"
+ "LSP refresh interval in seconds\n")
+
+DEFUN (lsp_refresh_interval_l1,
+ lsp_refresh_interval_l1_cmd,
+ "lsp-refresh-interval level-1 <1-65235>",
+ "LSP refresh interval for Level 1 only\n"
+ "LSP refresh interval for Level 1 only in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_1, atoi(argv[0]));
+}
+
+DEFUN (no_lsp_refresh_interval_l1,
+ no_lsp_refresh_interval_l1_cmd,
+ "no lsp-refresh-interval level-1",
+ NO_STR
+ "LSP refresh interval for Level 1 only in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_1,
+ DEFAULT_MAX_LSP_GEN_INTERVAL);
+}
+
+ALIAS (no_lsp_refresh_interval_l1,
+ no_lsp_refresh_interval_l1_arg_cmd,
+ "no lsp-refresh-interval level-1 <1-65235>",
+ NO_STR
+ "LSP refresh interval for Level 1 only\n"
+ "LSP refresh interval for Level 1 only in seconds\n")
+
+DEFUN (lsp_refresh_interval_l2,
+ lsp_refresh_interval_l2_cmd,
+ "lsp-refresh-interval level-2 <1-65235>",
+ "LSP refresh interval for Level 2 only\n"
+ "LSP refresh interval for Level 2 only in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_2, atoi(argv[0]));
+}
+
+DEFUN (no_lsp_refresh_interval_l2,
+ no_lsp_refresh_interval_l2_cmd,
+ "no lsp-refresh-interval level-2",
+ NO_STR
+ "LSP refresh interval for Level 2 only in seconds\n")
+{
+ return area_lsp_refresh_interval_set(vty, IS_LEVEL_2,
+ DEFAULT_MAX_LSP_GEN_INTERVAL);
+}
+
+ALIAS (no_lsp_refresh_interval_l2,
+ no_lsp_refresh_interval_l2_arg_cmd,
+ "no lsp-refresh-interval level-2 <1-65235>",
+ NO_STR
+ "LSP refresh interval for Level 2 only\n"
+ "LSP refresh interval for Level 2 only in seconds\n")
+
+static int
+area_passwd_set(struct vty *vty, int level,
+ int (*type_set)(struct isis_area *area, int level,
+ const char *passwd, u_char snp_auth),
+ const char *passwd, u_char snp_auth)
+{
+ struct isis_area *area = vty->index;
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ if (passwd && strlen(passwd) > 254)
+ {
+ vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ type_set(area, level, passwd, snp_auth);
+ return CMD_SUCCESS;
+}
+
+DEFUN (area_passwd_md5,
+ area_passwd_md5_cmd,
+ "(area-password|domain-password) md5 WORD",
+ "Configure the authentication password for an area\n"
+ "Set the authentication password for a routing domain\n"
+ "Authentication type\n"
+ "Level-wide password\n")
+{
+ u_char snp_auth = 0;
+ int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1;
+
+ if (argc > 2)
+ {
+ snp_auth = SNP_AUTH_SEND;
+ if (strncmp(argv[2], "v", 1) == 0)
+ snp_auth |= SNP_AUTH_RECV;
+ }
+
+ return area_passwd_set(vty, level, isis_area_passwd_hmac_md5_set,
+ argv[1], snp_auth);
+}
+
+ALIAS (area_passwd_md5,
+ area_passwd_md5_snpauth_cmd,
+ "(area-password|domain-password) md5 WORD authenticate snp (send-only|validate)",
+ "Configure the authentication password for an area\n"
+ "Set the authentication password for a routing domain\n"
+ "Authentication type\n"
+ "Level-wide password\n"
+ "Authentication\n"
+ "SNP PDUs\n"
+ "Send but do not check PDUs on receiving\n"
+ "Send and check PDUs on receiving\n")
+
+DEFUN (area_passwd_clear,
+ area_passwd_clear_cmd,
+ "(area-password|domain-password) clear WORD",
+ "Configure the authentication password for an area\n"
+ "Set the authentication password for a routing domain\n"
+ "Authentication type\n"
+ "Area password\n")
+{
+ u_char snp_auth = 0;
+ int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1;
+
+ if (argc > 2)
+ {
+ snp_auth = SNP_AUTH_SEND;
+ if (strncmp(argv[2], "v", 1) == 0)
+ snp_auth |= SNP_AUTH_RECV;
+ }
+
+ return area_passwd_set(vty, level, isis_area_passwd_cleartext_set,
+ argv[1], snp_auth);
+}
+
+ALIAS (area_passwd_clear,
+ area_passwd_clear_snpauth_cmd,
+ "(area-password|domain-password) clear WORD authenticate snp (send-only|validate)",
+ "Configure the authentication password for an area\n"
+ "Set the authentication password for a routing domain\n"
+ "Authentication type\n"
+ "Area password\n"
+ "Authentication\n"
+ "SNP PDUs\n"
+ "Send but do not check PDUs on receiving\n"
+ "Send and check PDUs on receiving\n")
+
+DEFUN (no_area_passwd,
+ no_area_passwd_cmd,
+ "no (area-password|domain-password)",
+ NO_STR
+ "Configure the authentication password for an area\n"
+ "Set the authentication password for a routing domain\n")
+{
+ int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1;
+ struct isis_area *area = vty->index;
+
+ if (!area)
+ {
+ vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ return isis_area_passwd_unset (area, level);
+}
+
+void
+isis_vty_init (void)
+{
+ install_element (INTERFACE_NODE, &ip_router_isis_cmd);
+ install_element (INTERFACE_NODE, &no_ip_router_isis_cmd);
+
+ install_element (INTERFACE_NODE, &isis_passive_cmd);
+ install_element (INTERFACE_NODE, &no_isis_passive_cmd);
+
+ install_element (INTERFACE_NODE, &isis_circuit_type_cmd);
+ install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd);
+
+ install_element (INTERFACE_NODE, &isis_network_cmd);
+ install_element (INTERFACE_NODE, &no_isis_network_cmd);
+
+ install_element (INTERFACE_NODE, &isis_passwd_cmd);
+ install_element (INTERFACE_NODE, &no_isis_passwd_cmd);
+ install_element (INTERFACE_NODE, &no_isis_passwd_arg_cmd);
+
+ install_element (INTERFACE_NODE, &isis_priority_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_priority_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_priority_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_priority_l2_arg_cmd);
+
+ install_element (INTERFACE_NODE, &isis_metric_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_metric_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_metric_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd);
+
+ install_element (INTERFACE_NODE, &isis_hello_interval_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_arg_cmd);
+
+ install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_arg_cmd);
+
+ install_element (INTERFACE_NODE, &isis_hello_padding_cmd);
+ install_element (INTERFACE_NODE, &no_isis_hello_padding_cmd);
+
+ install_element (INTERFACE_NODE, &csnp_interval_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_arg_cmd);
+ install_element (INTERFACE_NODE, &csnp_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &csnp_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_csnp_interval_l2_arg_cmd);
+
+ install_element (INTERFACE_NODE, &psnp_interval_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_arg_cmd);
+ install_element (INTERFACE_NODE, &psnp_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_l1_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_l1_arg_cmd);
+ install_element (INTERFACE_NODE, &psnp_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd);
+ install_element (INTERFACE_NODE, &no_psnp_interval_l2_arg_cmd);
+
+ install_element (ISIS_NODE, &metric_style_cmd);
+ install_element (ISIS_NODE, &no_metric_style_cmd);
+
+ install_element (ISIS_NODE, &set_overload_bit_cmd);
+ install_element (ISIS_NODE, &no_set_overload_bit_cmd);
+
+ install_element (ISIS_NODE, &set_attached_bit_cmd);
+ install_element (ISIS_NODE, &no_set_attached_bit_cmd);
+
+ install_element (ISIS_NODE, &dynamic_hostname_cmd);
+ install_element (ISIS_NODE, &no_dynamic_hostname_cmd);
+
+ install_element (ISIS_NODE, &area_lsp_mtu_cmd);
+ install_element (ISIS_NODE, &no_area_lsp_mtu_cmd);
+ install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd);
+
+ install_element (ISIS_NODE, &is_type_cmd);
+ install_element (ISIS_NODE, &no_is_type_cmd);
+
+ install_element (ISIS_NODE, &lsp_gen_interval_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_arg_cmd);
+ install_element (ISIS_NODE, &lsp_gen_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_l1_arg_cmd);
+ install_element (ISIS_NODE, &lsp_gen_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_lsp_gen_interval_l2_arg_cmd);
+
+ install_element (ISIS_NODE, &spf_interval_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_arg_cmd);
+ install_element (ISIS_NODE, &spf_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_l1_arg_cmd);
+ install_element (ISIS_NODE, &spf_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_spf_interval_l2_arg_cmd);
+
+ install_element (ISIS_NODE, &max_lsp_lifetime_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_arg_cmd);
+ install_element (ISIS_NODE, &max_lsp_lifetime_l1_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_arg_cmd);
+ install_element (ISIS_NODE, &max_lsp_lifetime_l2_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_cmd);
+ install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_arg_cmd);
+
+ install_element (ISIS_NODE, &lsp_refresh_interval_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_arg_cmd);
+ install_element (ISIS_NODE, &lsp_refresh_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_arg_cmd);
+ install_element (ISIS_NODE, &lsp_refresh_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd);
+ install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd);
+
+ install_element (ISIS_NODE, &area_passwd_md5_cmd);
+ install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd);
+ install_element (ISIS_NODE, &area_passwd_clear_cmd);
+ install_element (ISIS_NODE, &area_passwd_clear_snpauth_cmd);
+ install_element (ISIS_NODE, &no_area_passwd_cmd);
+}
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 228d2bcb31..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;
}
@@ -1612,1221 +1616,252 @@ DEFUN (no_net,
return area_clear_net_title (vty, argv[0]);
}
-static
-int area_set_lsp_mtu(struct vty *vty, struct isis_area *area, unsigned int lsp_mtu)
+void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu)
{
- struct isis_circuit *circuit;
- struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
- {
- if(circuit->state != C_STATE_INIT && circuit->state != C_STATE_UP)
- continue;
- if(lsp_mtu > isis_circuit_pdu_size(circuit))
- {
- vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s",
- circuit->interface->name, isis_circuit_pdu_size(circuit),
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- }
-
area->lsp_mtu = lsp_mtu;
lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1);
-
- return CMD_SUCCESS;
}
-DEFUN (area_lsp_mtu,
- area_lsp_mtu_cmd,
- "lsp-mtu <128-4352>",
- "Configure the maximum size of generated LSPs\n"
- "Maximum size of generated LSPs\n")
-{
- struct isis_area *area;
-
- area = vty->index;
- if (!area)
- {
- vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- unsigned int lsp_mtu;
-
- VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352);
-
- return area_set_lsp_mtu(vty, area, lsp_mtu);
-}
-
-DEFUN(no_area_lsp_mtu,
- no_area_lsp_mtu_cmd,
- "no lsp-mtu",
- NO_STR
- "Configure the maximum size of generated LSPs\n")
-{
- struct isis_area *area;
-
- area = vty->index;
- if (!area)
- {
- vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- return area_set_lsp_mtu(vty, area, DEFAULT_LSP_MTU);
-}
-
-ALIAS(no_area_lsp_mtu,
- no_area_lsp_mtu_arg_cmd,
- "no lsp-mtu <128-4352>",
- NO_STR
- "Configure the maximum size of generated LSPs\n"
- "Maximum size of generated LSPs\n");
-
-DEFUN (area_passwd_md5,
- area_passwd_md5_cmd,
- "area-password md5 WORD",
- "Configure the authentication password for an area\n"
- "Authentication type\n"
- "Area password\n")
+static int
+isis_area_passwd_set(struct isis_area *area, int level, u_char passwd_type,
+ const char *passwd, u_char snp_auth)
{
- struct isis_area *area;
+ struct isis_passwd *dest;
+ struct isis_passwd modified;
int len;
- area = vty->index;
-
- if (!area)
- {
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- len = strlen (argv[0]);
- if (len > 254)
- {
- vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- area->area_passwd.len = (u_char) len;
- area->area_passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5;
- strncpy ((char *)area->area_passwd.passwd, argv[0], 255);
+ assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2));
+ dest = (level == IS_LEVEL_1) ? &area->area_passwd : &area->domain_passwd;
+ memset(&modified, 0, sizeof(modified));
- if (argc > 1)
- {
- SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
- if (strncmp(argv[1], "v", 1) == 0)
- SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
- else
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
- }
- else
+ if (passwd_type != ISIS_PASSWD_TYPE_UNUSED)
{
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
- }
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
+ if (!passwd)
+ return -1;
- return CMD_SUCCESS;
-}
-
-ALIAS (area_passwd_md5,
- area_passwd_md5_snpauth_cmd,
- "area-password md5 WORD authenticate snp (send-only|validate)",
- "Configure the authentication password for an area\n"
- "Authentication type\n"
- "Area password\n"
- "Authentication\n"
- "SNP PDUs\n"
- "Send but do not check PDUs on receiving\n"
- "Send and check PDUs on receiving\n")
-
-DEFUN (area_passwd_clear,
- area_passwd_clear_cmd,
- "area-password clear WORD",
- "Configure the authentication password for an area\n"
- "Authentication type\n"
- "Area password\n")
-{
- struct isis_area *area;
- int len;
-
- area = vty->index;
-
- if (!area)
- {
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
+ len = strlen(passwd);
+ if (len > 254)
+ return -1;
- len = strlen (argv[0]);
- if (len > 254)
- {
- vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
+ modified.len = len;
+ strncpy((char*)modified.passwd, passwd, 255);
+ modified.type = passwd_type;
+ modified.snp_auth = snp_auth;
}
- area->area_passwd.len = (u_char) len;
- area->area_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
- strncpy ((char *)area->area_passwd.passwd, argv[0], 255);
-
- if (argc > 1)
- {
- SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
- if (strncmp(argv[1], "v", 1) == 0)
- SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
- else
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
- }
- else
+ if (memcmp(&modified, dest, sizeof(modified)))
{
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
- UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
+ memcpy(dest, &modified, sizeof(modified));
+ lsp_regenerate_schedule(area, IS_LEVEL_1|IS_LEVEL_2, 1);
}
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
- return CMD_SUCCESS;
+ return 0;
}
-ALIAS (area_passwd_clear,
- area_passwd_clear_snpauth_cmd,
- "area-password clear WORD authenticate snp (send-only|validate)",
- "Configure the authentication password for an area\n"
- "Authentication type\n"
- "Area password\n"
- "Authentication\n"
- "SNP PDUs\n"
- "Send but do not check PDUs on receiving\n"
- "Send and check PDUs on receiving\n")
-
-DEFUN (no_area_passwd,
- no_area_passwd_cmd,
- "no area-password",
- NO_STR
- "Configure the authentication password for an area\n")
+int
+isis_area_passwd_unset (struct isis_area *area, int level)
{
- struct isis_area *area;
-
- area = vty->index;
-
- if (!area)
- {
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- memset (&area->area_passwd, 0, sizeof (struct isis_passwd));
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
-
- return CMD_SUCCESS;
+ return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_UNUSED, NULL, 0);
}
-DEFUN (domain_passwd_md5,
- domain_passwd_md5_cmd,
- "domain-password md5 WORD",
- "Set the authentication password for a routing domain\n"
- "Authentication type\n"
- "Routing domain password\n")
+int
+isis_area_passwd_cleartext_set (struct isis_area *area, int level,
+ const char *passwd, u_char snp_auth)
{
- struct isis_area *area;
- int len;
-
- area = vty->index;
-
- if (!area)
- {
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- len = strlen (argv[0]);
- if (len > 254)
- {
- vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- area->domain_passwd.len = (u_char) len;
- area->domain_passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5;
- strncpy ((char *)area->domain_passwd.passwd, argv[0], 255);
-
- if (argc > 1)
- {
- SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
- if (strncmp(argv[1], "v", 1) == 0)
- SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- else
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- }
- else
- {
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- }
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
-
- return CMD_SUCCESS;
+ return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_CLEARTXT,
+ passwd, snp_auth);
}
-ALIAS (domain_passwd_md5,
- domain_passwd_md5_snpauth_cmd,
- "domain-password md5 WORD authenticate snp (send-only|validate)",
- "Set the authentication password for a routing domain\n"
- "Authentication type\n"
- "Routing domain password\n"
- "Authentication\n"
- "SNP PDUs\n"
- "Send but do not check PDUs on receiving\n"
- "Send and check PDUs on receiving\n")
-
-DEFUN (domain_passwd_clear,
- domain_passwd_clear_cmd,
- "domain-password clear WORD",
- "Set the authentication password for a routing domain\n"
- "Authentication type\n"
- "Routing domain password\n")
+int
+isis_area_passwd_hmac_md5_set (struct isis_area *area, int level,
+ const char *passwd, u_char snp_auth)
{
- struct isis_area *area;
- int len;
-
- area = vty->index;
-
- if (!area)
- {
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- len = strlen (argv[0]);
- if (len > 254)
- {
- vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- area->domain_passwd.len = (u_char) len;
- area->domain_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
- strncpy ((char *)area->domain_passwd.passwd, argv[0], 255);
-
- if (argc > 1)
- {
- SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
- if (strncmp(argv[1], "v", 1) == 0)
- SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- else
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- }
- else
- {
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
- UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
- }
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
-
- return CMD_SUCCESS;
+ return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_HMAC_MD5,
+ passwd, snp_auth);
}
-ALIAS (domain_passwd_clear,
- domain_passwd_clear_snpauth_cmd,
- "domain-password clear WORD authenticate snp (send-only|validate)",
- "Set the authentication password for a routing domain\n"
- "Authentication type\n"
- "Routing domain password\n"
- "Authentication\n"
- "SNP PDUs\n"
- "Send but do not check PDUs on receiving\n"
- "Send and check PDUs on receiving\n")
-
-DEFUN (no_domain_passwd,
- no_domain_passwd_cmd,
- "no domain-password",
- NO_STR
- "Set the authentication password for a routing domain\n")
+static void
+area_resign_level (struct isis_area *area, int level)
{
- struct isis_area *area;
-
- area = vty->index;
-
- if (!area)
+ if (area->lspdb[level - 1])
{
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
+ lsp_db_destroy (area->lspdb[level - 1]);
+ area->lspdb[level - 1] = NULL;
}
-
- memset (&area->domain_passwd, 0, sizeof (struct isis_passwd));
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (is_type,
- is_type_cmd,
- "is-type (level-1|level-1-2|level-2-only)",
- "IS Level for this routing process (OSI only)\n"
- "Act as a station router only\n"
- "Act as both a station router and an area router\n"
- "Act as an area router only\n")
-{
- struct isis_area *area;
- int type;
-
- area = vty->index;
-
- if (!area)
+ if (area->spftree[level - 1])
{
- vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
+ isis_spftree_del (area->spftree[level - 1]);
+ area->spftree[level - 1] = NULL;
}
-
- type = string2circuit_t (argv[0]);
- if (!type)
+#ifdef HAVE_IPV6
+ if (area->spftree6[level - 1])
{
- vty_out (vty, "Unknown IS level %s", VTY_NEWLINE);
- return CMD_SUCCESS;
+ isis_spftree_del (area->spftree6[level - 1]);
+ area->spftree6[level - 1] = NULL;
}
-
- isis_event_system_type_change (area, type);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_is_type,
- no_is_type_cmd,
- "no is-type (level-1|level-1-2|level-2-only)",
- NO_STR
- "IS Level for this routing process (OSI only)\n"
- "Act as a station router only\n"
- "Act as both a station router and an area router\n"
- "Act as an area router only\n")
-{
- struct isis_area *area;
- int type;
-
- area = vty->index;
- assert (area);
-
- /*
- * Put the is-type back to defaults:
- * - level-1-2 on first area
- * - level-1 for the rest
- */
- if (listgetdata (listhead (isis->area_list)) == area)
- type = IS_LEVEL_1_AND_2;
- else
- type = IS_LEVEL_1;
-
- isis_event_system_type_change (area, type);
-
- return CMD_SUCCESS;
-}
-
-static int
-set_lsp_gen_interval (struct vty *vty, struct isis_area *area,
- uint16_t interval, int level)
-{
- int lvl;
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+#endif
+ if (area->route_table[level - 1])
{
- if (!(lvl & level))
- continue;
-
- if (interval >= area->lsp_refresh[lvl-1])
- {
- vty_out (vty, "LSP gen interval %us must be less than "
- "the LSP refresh interval %us%s",
- interval, area->lsp_refresh[lvl-1], VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
+ route_table_finish (area->route_table[level - 1]);
+ area->route_table[level - 1] = NULL;
}
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+#ifdef HAVE_IPV6
+ if (area->route_table6[level - 1])
{
- if (!(lvl & level))
- continue;
- area->lsp_gen_interval[lvl-1] = interval;
+ route_table_finish (area->route_table6[level - 1]);
+ area->route_table6[level - 1] = NULL;
}
+#endif /* HAVE_IPV6 */
- return CMD_SUCCESS;
-}
-
-DEFUN (lsp_gen_interval,
- lsp_gen_interval_cmd,
- "lsp-gen-interval <1-120>",
- "Minimum interval between regenerating same LSP\n"
- "Minimum interval in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_gen_interval (vty, area, interval, level);
-}
-
-DEFUN (no_lsp_gen_interval,
- no_lsp_gen_interval_cmd,
- "no lsp-gen-interval",
- NO_STR
- "Minimum interval between regenerating same LSP\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_gen_interval (vty, area, interval, level);
-}
-
-ALIAS (no_lsp_gen_interval,
- no_lsp_gen_interval_arg_cmd,
- "no lsp-gen-interval <1-120>",
- NO_STR
- "Minimum interval between regenerating same LSP\n"
- "Minimum interval in seconds\n")
-
-DEFUN (lsp_gen_interval_l1,
- lsp_gen_interval_l1_cmd,
- "lsp-gen-interval level-1 <1-120>",
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 1 only\n"
- "Minimum interval in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1;
- return set_lsp_gen_interval (vty, area, interval, level);
-}
-
-DEFUN (no_lsp_gen_interval_l1,
- no_lsp_gen_interval_l1_cmd,
- "no lsp-gen-interval level-1",
- NO_STR
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 1 only\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
- level = IS_LEVEL_1;
- return set_lsp_gen_interval (vty, area, interval, level);
-}
-
-ALIAS (no_lsp_gen_interval_l1,
- no_lsp_gen_interval_l1_arg_cmd,
- "no lsp-gen-interval level-1 <1-120>",
- NO_STR
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 1 only\n"
- "Minimum interval in seconds\n")
-
-DEFUN (lsp_gen_interval_l2,
- lsp_gen_interval_l2_cmd,
- "lsp-gen-interval level-2 <1-120>",
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 2 only\n"
- "Minimum interval in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_2;
- return set_lsp_gen_interval (vty, area, interval, level);
+ sched_debug("ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.",
+ area->area_tag, level);
+ THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]);
+ area->lsp_regenerate_pending[level - 1] = 0;
}
-DEFUN (no_lsp_gen_interval_l2,
- no_lsp_gen_interval_l2_cmd,
- "no lsp-gen-interval level-2",
- NO_STR
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 2 only\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
- level = IS_LEVEL_2;
- return set_lsp_gen_interval (vty, area, interval, level);
-}
-
-ALIAS (no_lsp_gen_interval_l2,
- no_lsp_gen_interval_l2_arg_cmd,
- "no lsp-gen-interval level-2 <1-120>",
- NO_STR
- "Minimum interval between regenerating same LSP\n"
- "Set interval for level 2 only\n"
- "Minimum interval in seconds\n")
-
-static int
-validate_metric_style_narrow (struct vty *vty, struct isis_area *area)
+void
+isis_area_is_type_set(struct isis_area *area, int is_type)
{
- struct isis_circuit *circuit;
struct listnode *node;
-
- if (! vty)
- return CMD_ERR_AMBIGUOUS;
-
- if (! area)
- {
- vty_out (vty, "ISIS area is invalid%s", VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
- {
- if ((area->is_type & IS_LEVEL_1) &&
- (circuit->is_type & IS_LEVEL_1) &&
- (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC))
- {
- vty_out (vty, "ISIS circuit %s metric is invalid%s",
- circuit->interface->name, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- if ((area->is_type & IS_LEVEL_2) &&
- (circuit->is_type & IS_LEVEL_2) &&
- (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC))
- {
- vty_out (vty, "ISIS circuit %s metric is invalid%s",
- circuit->interface->name, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (metric_style,
- metric_style_cmd,
- "metric-style (narrow|transition|wide)",
- "Use old-style (ISO 10589) or new-style packet formats\n"
- "Use old style of TLVs with narrow metric\n"
- "Send and accept both styles of TLVs during transition\n"
- "Use new style of TLVs to carry wider metric\n")
-{
- struct isis_area *area;
- int ret;
-
- area = vty->index;
- assert (area);
-
- if (strncmp (argv[0], "w", 1) == 0)
- {
- area->newmetric = 1;
- area->oldmetric = 0;
- }
- else
- {
- ret = validate_metric_style_narrow (vty, area);
- if (ret != CMD_SUCCESS)
- return ret;
-
- if (strncmp (argv[0], "t", 1) == 0)
- {
- area->newmetric = 1;
- area->oldmetric = 1;
- }
- else if (strncmp (argv[0], "n", 1) == 0)
- {
- area->newmetric = 0;
- area->oldmetric = 1;
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_metric_style,
- no_metric_style_cmd,
- "no metric-style",
- NO_STR
- "Use old-style (ISO 10589) or new-style packet formats\n")
-{
- struct isis_area *area;
- int ret;
-
- area = vty->index;
- assert (area);
-
- ret = validate_metric_style_narrow (vty, area);
- if (ret != CMD_SUCCESS)
- return ret;
-
- /* Default is narrow metric. */
- area->newmetric = 0;
- area->oldmetric = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (set_overload_bit,
- set_overload_bit_cmd,
- "set-overload-bit",
- "Set overload bit to avoid any transit traffic\n"
- "Set overload bit\n")
-{
- struct isis_area *area;
-
- area = vty->index;
- assert (area);
-
- area->overload_bit = LSPBIT_OL;
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
+ struct isis_circuit *circuit;
- return CMD_SUCCESS;
-}
+ if (isis->debugs & DEBUG_EVENTS)
+ zlog_debug ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag,
+ circuit_t2string (area->is_type), circuit_t2string (is_type));
-DEFUN (no_set_overload_bit,
- no_set_overload_bit_cmd,
- "no set-overload-bit",
- "Reset overload bit to accept transit traffic\n"
- "Reset overload bit\n")
-{
- struct isis_area *area;
+ if (area->is_type == is_type)
+ return; /* No change */
- area = vty->index;
- assert (area);
-
- area->overload_bit = 0;
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
+ switch (area->is_type)
+ {
+ case IS_LEVEL_1:
+ if (is_type == IS_LEVEL_2)
+ area_resign_level (area, IS_LEVEL_1);
+
+ if (area->lspdb[1] == NULL)
+ area->lspdb[1] = lsp_db_init ();
+ if (area->route_table[1] == NULL)
+ area->route_table[1] = route_table_init ();
+#ifdef HAVE_IPV6
+ if (area->route_table6[1] == NULL)
+ area->route_table6[1] = route_table_init ();
+#endif /* HAVE_IPV6 */
+ break;
- return CMD_SUCCESS;
-}
+ case IS_LEVEL_1_AND_2:
+ if (is_type == IS_LEVEL_1)
+ area_resign_level (area, IS_LEVEL_2);
+ else
+ area_resign_level (area, IS_LEVEL_1);
+ break;
-DEFUN (set_attached_bit,
- set_attached_bit_cmd,
- "set-attached-bit",
- "Set attached bit to identify as L1/L2 router for inter-area traffic\n"
- "Set attached bit\n")
-{
- struct isis_area *area;
+ case IS_LEVEL_2:
+ if (is_type == IS_LEVEL_1)
+ area_resign_level (area, IS_LEVEL_2);
- area = vty->index;
- assert (area);
+ if (area->lspdb[0] == NULL)
+ area->lspdb[0] = lsp_db_init ();
+ if (area->route_table[0] == NULL)
+ area->route_table[0] = route_table_init ();
+#ifdef HAVE_IPV6
+ if (area->route_table6[0] == NULL)
+ area->route_table6[0] = route_table_init ();
+#endif /* HAVE_IPV6 */
+ break;
- area->attached_bit = LSPBIT_ATT;
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
+ default:
+ break;
+ }
- return CMD_SUCCESS;
-}
+ area->is_type = is_type;
-DEFUN (no_set_attached_bit,
- no_set_attached_bit_cmd,
- "no set-attached-bit",
- "Reset attached bit\n")
-{
- struct isis_area *area;
+ /* override circuit's is_type */
+ if (area->is_type != IS_LEVEL_1_AND_2)
+ {
+ for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
+ isis_circuit_is_type_set (circuit, is_type);
+ }
- area = vty->index;
- assert (area);
+ spftree_area_init (area);
- area->attached_bit = 0;
+ if (is_type & IS_LEVEL_1)
+ lsp_generate (area, IS_LEVEL_1);
+ if (is_type & IS_LEVEL_2)
+ lsp_generate (area, IS_LEVEL_2);
lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
- return CMD_SUCCESS;
-}
-
-DEFUN (dynamic_hostname,
- dynamic_hostname_cmd,
- "hostname dynamic",
- "Dynamic hostname for IS-IS\n"
- "Dynamic hostname\n")
-{
- struct isis_area *area;
-
- area = vty->index;
- assert (area);
-
- if (!area->dynhostname)
- {
- area->dynhostname = 1;
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0);
- }
-
- return CMD_SUCCESS;
+ return;
}
-DEFUN (no_dynamic_hostname,
- no_dynamic_hostname_cmd,
- "no hostname dynamic",
- NO_STR
- "Dynamic hostname for IS-IS\n"
- "Dynamic hostname\n")
+void isis_area_metricstyle_set(struct isis_area *area, bool old_metric,
+ bool new_metric)
{
- struct isis_area *area;
-
- area = vty->index;
- assert (area);
-
- if (area->dynhostname)
+ if (area->oldmetric != old_metric
+ || area->newmetric != new_metric)
{
- area->dynhostname = 0;
- lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0);
+ area->oldmetric = old_metric;
+ area->newmetric = new_metric;
+ lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1);
}
-
- return CMD_SUCCESS;
}
-DEFUN (spf_interval,
- spf_interval_cmd,
- "spf-interval <1-120>",
- "Minimum interval between SPF calculations\n"
- "Minimum interval between consecutive SPFs in seconds\n")
+void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit)
{
- struct isis_area *area;
- u_int16_t interval;
-
- area = vty->index;
- interval = atoi (argv[0]);
- area->min_spf_interval[0] = interval;
- area->min_spf_interval[1] = interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_spf_interval,
- no_spf_interval_cmd,
- "no spf-interval",
- NO_STR
- "Minimum interval between SPF calculations\n")
-{
- struct isis_area *area;
-
- area = vty->index;
-
- area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
- area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_spf_interval,
- no_spf_interval_arg_cmd,
- "no spf-interval <1-120>",
- NO_STR
- "Minimum interval between SPF calculations\n"
- "Minimum interval between consecutive SPFs in seconds\n")
-
-DEFUN (spf_interval_l1,
- spf_interval_l1_cmd,
- "spf-interval level-1 <1-120>",
- "Minimum interval between SPF calculations\n"
- "Set interval for level 1 only\n"
- "Minimum interval between consecutive SPFs in seconds\n")
-{
- struct isis_area *area;
- u_int16_t interval;
-
- area = vty->index;
- interval = atoi (argv[0]);
- area->min_spf_interval[0] = interval;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_spf_interval_l1,
- no_spf_interval_l1_cmd,
- "no spf-interval level-1",
- NO_STR
- "Minimum interval between SPF calculations\n"
- "Set interval for level 1 only\n")
-{
- struct isis_area *area;
-
- area = vty->index;
-
- area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_spf_interval,
- no_spf_interval_l1_arg_cmd,
- "no spf-interval level-1 <1-120>",
- NO_STR
- "Minimum interval between SPF calculations\n"
- "Set interval for level 1 only\n"
- "Minimum interval between consecutive SPFs in seconds\n")
-
-DEFUN (spf_interval_l2,
- spf_interval_l2_cmd,
- "spf-interval level-2 <1-120>",
- "Minimum interval between SPF calculations\n"
- "Set interval for level 2 only\n"
- "Minimum interval between consecutive SPFs in seconds\n")
-{
- struct isis_area *area;
- u_int16_t interval;
-
- area = vty->index;
- interval = atoi (argv[0]);
- area->min_spf_interval[1] = interval;
-
- return CMD_SUCCESS;
-}
+ char new_overload_bit = overload_bit ? LSPBIT_OL : 0;
-DEFUN (no_spf_interval_l2,
- no_spf_interval_l2_cmd,
- "no spf-interval level-2",
- NO_STR
- "Minimum interval between SPF calculations\n"
- "Set interval for level 2 only\n")
-{
- struct isis_area *area;
-
- area = vty->index;
-
- area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_spf_interval,
- no_spf_interval_l2_arg_cmd,
- "no spf-interval level-2 <1-120>",
- NO_STR
- "Minimum interval between SPF calculations\n"
- "Set interval for level 2 only\n"
- "Minimum interval between consecutive SPFs in seconds\n")
-
-static int
-set_lsp_max_lifetime (struct vty *vty, struct isis_area *area,
- uint16_t interval, int level)
-{
- int lvl;
- int set_refresh_interval[ISIS_LEVELS] = {0, 0};
- uint16_t refresh_interval;
-
- refresh_interval = interval - 300;
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
+ if (new_overload_bit != area->overload_bit)
{
- if (!(lvl & level))
- continue;
- if (refresh_interval < area->lsp_refresh[lvl-1])
- {
- vty_out (vty, "Level %d Max LSP lifetime %us must be 300s greater than "
- "the configured LSP refresh interval %us%s",
- lvl, interval, area->lsp_refresh[lvl-1], VTY_NEWLINE);
- vty_out (vty, "Automatically reducing level %d LSP refresh interval "
- "to %us%s", lvl, refresh_interval, VTY_NEWLINE);
- set_refresh_interval[lvl-1] = 1;
-
- if (refresh_interval <= area->lsp_gen_interval[lvl-1])
- {
- vty_out (vty, "LSP refresh interval %us must be greater than "
- "the configured LSP gen interval %us%s",
- refresh_interval, area->lsp_gen_interval[lvl-1],
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- }
+ area->overload_bit = new_overload_bit;
+ lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1);
}
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
- {
- if (!(lvl & level))
- continue;
- area->max_lsp_lifetime[lvl-1] = interval;
- /* Automatically reducing lsp_refresh_interval to interval - 300 */
- if (set_refresh_interval[lvl-1])
- area->lsp_refresh[lvl-1] = refresh_interval;
- }
-
- lsp_regenerate_schedule (area, level, 1);
-
- return CMD_SUCCESS;
}
-DEFUN (max_lsp_lifetime,
- max_lsp_lifetime_cmd,
- "max-lsp-lifetime <350-65535>",
- "Maximum LSP lifetime\n"
- "LSP lifetime in seconds\n")
+void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit)
{
- struct isis_area *area;
- uint16_t interval;
- int level;
+ char new_attached_bit = attached_bit ? LSPBIT_ATT : 0;
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-DEFUN (no_max_lsp_lifetime,
- no_max_lsp_lifetime_cmd,
- "no max-lsp-lifetime",
- NO_STR
- "LSP lifetime in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_LSP_LIFETIME;
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-ALIAS (no_max_lsp_lifetime,
- no_max_lsp_lifetime_arg_cmd,
- "no max-lsp-lifetime <350-65535>",
- NO_STR
- "Maximum LSP lifetime\n"
- "LSP lifetime in seconds\n")
-
-DEFUN (max_lsp_lifetime_l1,
- max_lsp_lifetime_l1_cmd,
- "max-lsp-lifetime level-1 <350-65535>",
- "Maximum LSP lifetime for Level 1 only\n"
- "LSP lifetime for Level 1 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-DEFUN (no_max_lsp_lifetime_l1,
- no_max_lsp_lifetime_l1_cmd,
- "no max-lsp-lifetime level-1",
- NO_STR
- "LSP lifetime for Level 1 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_LSP_LIFETIME;
- level = IS_LEVEL_1;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-ALIAS (no_max_lsp_lifetime_l1,
- no_max_lsp_lifetime_l1_arg_cmd,
- "no max-lsp-lifetime level-1 <350-65535>",
- NO_STR
- "Maximum LSP lifetime for Level 1 only\n"
- "LSP lifetime for Level 1 only in seconds\n")
-
-DEFUN (max_lsp_lifetime_l2,
- max_lsp_lifetime_l2_cmd,
- "max-lsp-lifetime level-2 <350-65535>",
- "Maximum LSP lifetime for Level 2 only\n"
- "LSP lifetime for Level 2 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_2;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-DEFUN (no_max_lsp_lifetime_l2,
- no_max_lsp_lifetime_l2_cmd,
- "no max-lsp-lifetime level-2",
- NO_STR
- "LSP lifetime for Level 2 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_LSP_LIFETIME;
- level = IS_LEVEL_2;
- return set_lsp_max_lifetime (vty, area, interval, level);
-}
-
-ALIAS (no_max_lsp_lifetime_l2,
- no_max_lsp_lifetime_l2_arg_cmd,
- "no max-lsp-lifetime level-2 <350-65535>",
- NO_STR
- "Maximum LSP lifetime for Level 2 only\n"
- "LSP lifetime for Level 2 only in seconds\n")
-
-static int
-set_lsp_refresh_interval (struct vty *vty, struct isis_area *area,
- uint16_t interval, int level)
-{
- int lvl;
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
- {
- if (!(lvl & level))
- continue;
- if (interval <= area->lsp_gen_interval[lvl-1])
- {
- vty_out (vty, "LSP refresh interval %us must be greater than "
- "the configured LSP gen interval %us%s",
- interval, area->lsp_gen_interval[lvl-1],
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- if (interval > (area->max_lsp_lifetime[lvl-1] - 300))
- {
- vty_out (vty, "LSP refresh interval %us must be less than "
- "the configured LSP lifetime %us less 300%s",
- interval, area->max_lsp_lifetime[lvl-1],
- VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
- }
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl)
+ if (new_attached_bit != area->attached_bit)
{
- if (!(lvl & level))
- continue;
- area->lsp_refresh[lvl-1] = interval;
+ area->attached_bit = new_attached_bit;
+ lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1);
}
- lsp_regenerate_schedule (area, level, 1);
-
- return CMD_SUCCESS;
}
-DEFUN (lsp_refresh_interval,
- lsp_refresh_interval_cmd,
- "lsp-refresh-interval <1-65235>",
- "LSP refresh interval\n"
- "LSP refresh interval in seconds\n")
+void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname)
{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_refresh_interval (vty, area, interval, level);
-}
-
-DEFUN (no_lsp_refresh_interval,
- no_lsp_refresh_interval_cmd,
- "no lsp-refresh-interval",
- NO_STR
- "LSP refresh interval in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_MAX_LSP_GEN_INTERVAL;
- level = IS_LEVEL_1 | IS_LEVEL_2;
- return set_lsp_refresh_interval (vty, area, interval, level);
+ if (area->dynhostname != dynhostname)
+ {
+ area->dynhostname = dynhostname;
+ lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0);
+ }
}
-ALIAS (no_lsp_refresh_interval,
- no_lsp_refresh_interval_arg_cmd,
- "no lsp-refresh-interval <1-65235>",
- NO_STR
- "LSP refresh interval\n"
- "LSP refresh interval in seconds\n")
-
-DEFUN (lsp_refresh_interval_l1,
- lsp_refresh_interval_l1_cmd,
- "lsp-refresh-interval level-1 <1-65235>",
- "LSP refresh interval for Level 1 only\n"
- "LSP refresh interval for Level 1 only in seconds\n")
+void
+isis_area_max_lsp_lifetime_set(struct isis_area *area, int level,
+ uint16_t max_lsp_lifetime)
{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_1;
- return set_lsp_refresh_interval (vty, area, interval, level);
-}
+ assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2));
-DEFUN (no_lsp_refresh_interval_l1,
- no_lsp_refresh_interval_l1_cmd,
- "no lsp-refresh-interval level-1",
- NO_STR
- "LSP refresh interval for Level 1 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
+ if (area->max_lsp_lifetime[level-1] == max_lsp_lifetime)
+ return;
- area = vty->index;
- interval = DEFAULT_MAX_LSP_GEN_INTERVAL;
- level = IS_LEVEL_1;
- return set_lsp_refresh_interval (vty, area, interval, level);
+ area->max_lsp_lifetime[level-1] = max_lsp_lifetime;
+ lsp_regenerate_schedule(area, level, 1);
}
-ALIAS (no_lsp_refresh_interval_l1,
- no_lsp_refresh_interval_l1_arg_cmd,
- "no lsp-refresh-interval level-1 <1-65235>",
- NO_STR
- "LSP refresh interval for Level 1 only\n"
- "LSP refresh interval for Level 1 only in seconds\n")
-
-DEFUN (lsp_refresh_interval_l2,
- lsp_refresh_interval_l2_cmd,
- "lsp-refresh-interval level-2 <1-65235>",
- "LSP refresh interval for Level 2 only\n"
- "LSP refresh interval for Level 2 only in seconds\n")
+void
+isis_area_lsp_refresh_set(struct isis_area *area, int level,
+ uint16_t lsp_refresh)
{
- struct isis_area *area;
- uint16_t interval;
- int level;
+ assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2));
- area = vty->index;
- interval = atoi (argv[0]);
- level = IS_LEVEL_2;
- return set_lsp_refresh_interval (vty, area, interval, level);
-}
+ if (area->lsp_refresh[level-1] == lsp_refresh)
+ return;
-DEFUN (no_lsp_refresh_interval_l2,
- no_lsp_refresh_interval_l2_cmd,
- "no lsp-refresh-interval level-2",
- NO_STR
- "LSP refresh interval for Level 2 only in seconds\n")
-{
- struct isis_area *area;
- uint16_t interval;
- int level;
-
- area = vty->index;
- interval = DEFAULT_MAX_LSP_GEN_INTERVAL;
- level = IS_LEVEL_2;
- return set_lsp_refresh_interval (vty, area, interval, level);
+ area->lsp_refresh[level-1] = lsp_refresh;
+ lsp_regenerate_schedule(area, level, 1);
}
-ALIAS (no_lsp_refresh_interval_l2,
- no_lsp_refresh_interval_l2_arg_cmd,
- "no lsp-refresh-interval level-2 <1-65235>",
- NO_STR
- "LSP refresh interval for Level 2 only\n"
- "LSP refresh interval for Level 2 only in seconds\n")
-
DEFUN (log_adj_changes,
log_adj_changes_cmd,
"log-adjacency-changes",
@@ -3251,6 +2286,7 @@ isis_config_write (struct vty *vty)
#endif /* TOPOLOGY_GENERATE */
}
+ isis_mpls_te_config_write_router(vty);
}
return write;
@@ -3305,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);
@@ -3375,77 +2411,6 @@ isis_init ()
install_element (ISIS_NODE, &net_cmd);
install_element (ISIS_NODE, &no_net_cmd);
- install_element (ISIS_NODE, &is_type_cmd);
- install_element (ISIS_NODE, &no_is_type_cmd);
-
- install_element (ISIS_NODE, &area_lsp_mtu_cmd);
- install_element (ISIS_NODE, &no_area_lsp_mtu_cmd);
- install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd);
-
- install_element (ISIS_NODE, &area_passwd_md5_cmd);
- install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd);
- install_element (ISIS_NODE, &area_passwd_clear_cmd);
- install_element (ISIS_NODE, &area_passwd_clear_snpauth_cmd);
- install_element (ISIS_NODE, &no_area_passwd_cmd);
-
- install_element (ISIS_NODE, &domain_passwd_md5_cmd);
- install_element (ISIS_NODE, &domain_passwd_md5_snpauth_cmd);
- install_element (ISIS_NODE, &domain_passwd_clear_cmd);
- install_element (ISIS_NODE, &domain_passwd_clear_snpauth_cmd);
- install_element (ISIS_NODE, &no_domain_passwd_cmd);
-
- install_element (ISIS_NODE, &lsp_gen_interval_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_arg_cmd);
- install_element (ISIS_NODE, &lsp_gen_interval_l1_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_l1_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_l1_arg_cmd);
- install_element (ISIS_NODE, &lsp_gen_interval_l2_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_l2_cmd);
- install_element (ISIS_NODE, &no_lsp_gen_interval_l2_arg_cmd);
-
- install_element (ISIS_NODE, &spf_interval_cmd);
- install_element (ISIS_NODE, &no_spf_interval_cmd);
- install_element (ISIS_NODE, &no_spf_interval_arg_cmd);
- install_element (ISIS_NODE, &spf_interval_l1_cmd);
- install_element (ISIS_NODE, &no_spf_interval_l1_cmd);
- install_element (ISIS_NODE, &no_spf_interval_l1_arg_cmd);
- install_element (ISIS_NODE, &spf_interval_l2_cmd);
- install_element (ISIS_NODE, &no_spf_interval_l2_cmd);
- install_element (ISIS_NODE, &no_spf_interval_l2_arg_cmd);
-
- install_element (ISIS_NODE, &max_lsp_lifetime_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_arg_cmd);
- install_element (ISIS_NODE, &max_lsp_lifetime_l1_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_arg_cmd);
- install_element (ISIS_NODE, &max_lsp_lifetime_l2_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_cmd);
- install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_arg_cmd);
-
- install_element (ISIS_NODE, &lsp_refresh_interval_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_arg_cmd);
- install_element (ISIS_NODE, &lsp_refresh_interval_l1_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_arg_cmd);
- install_element (ISIS_NODE, &lsp_refresh_interval_l2_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd);
- install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd);
-
- install_element (ISIS_NODE, &set_overload_bit_cmd);
- install_element (ISIS_NODE, &no_set_overload_bit_cmd);
-
- install_element (ISIS_NODE, &set_attached_bit_cmd);
- install_element (ISIS_NODE, &no_set_attached_bit_cmd);
-
- install_element (ISIS_NODE, &dynamic_hostname_cmd);
- install_element (ISIS_NODE, &no_dynamic_hostname_cmd);
-
- install_element (ISIS_NODE, &metric_style_cmd);
- install_element (ISIS_NODE, &no_metric_style_cmd);
-
install_element (ISIS_NODE, &log_adj_changes_cmd);
install_element (ISIS_NODE, &no_log_adj_changes_cmd);
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 6fe1eb8144..9a4f360a2b 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -27,7 +27,11 @@
#define ISISD_VERSION "0.0.7"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
#include "isisd/isis_redist.h"
+#include "isis_flags.h"
+#include "dict.h"
/* uncomment if you are a developer in bug hunt */
/* #define EXTREME_DEBUG */
@@ -139,6 +143,25 @@ struct isis_area *isis_area_lookup (const char *);
int isis_area_get (struct vty *vty, const char *area_tag);
void print_debug(struct vty *, int, int);
+void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit);
+void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit);
+void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname);
+void isis_area_metricstyle_set(struct isis_area *area, bool old_metric,
+ bool new_metric);
+void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu);
+void isis_area_is_type_set(struct isis_area *area, int is_type);
+void isis_area_max_lsp_lifetime_set(struct isis_area *area, int level,
+ uint16_t max_lsp_lifetime);
+void isis_area_lsp_refresh_set(struct isis_area *area, int level,
+ uint16_t lsp_refresh);
+/* IS_LEVEL_1 sets area_passwd, IS_LEVEL_2 domain_passwd */
+int isis_area_passwd_unset (struct isis_area *area, int level);
+int isis_area_passwd_cleartext_set (struct isis_area *area, int level,
+ const char *passwd, u_char snp_auth);
+int isis_area_passwd_hmac_md5_set (struct isis_area *area, int level,
+ const char *passwd, u_char snp_auth);
+void isis_vty_init (void);
+
/* Master of threads. */
extern struct thread_master *master;
@@ -174,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/.gitignore b/lib/.gitignore
index ca49c1b6a3..8174bda7d8 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -19,3 +19,4 @@ route_types.h
command_lex.c
command_parse.c
command_parse.h
+refix
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b7bb434776..3dfd09e2e6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -17,7 +17,7 @@ libzebra_la_SOURCES = \
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \
- ptm_lib.c csv.c bfd.c vrf.c systemd.c
+ ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c
BUILT_SOURCES = memtypes.h route_types.h gitversion.h command_parse.h
@@ -35,7 +35,7 @@ pkginclude_HEADERS = \
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
workqueue.h route_types.h libospf.h nexthop.h json.h \
- ptm_lib.h csv.h bfd.h vrf.h systemd.h bitfield.h
+ ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h
noinst_HEADERS = \
plist_int.h
diff --git a/lib/agentx.c b/lib/agentx.c
index bb95903adf..5996b34a0f 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -24,11 +24,110 @@
#if defined HAVE_SNMP && defined SNMP_AGENTX
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/snmp_vars.h>
#include "command.h"
#include "smux.h"
+#include "memory.h"
+#include "linklist.h"
-int agentx_enabled = 0;
+static int agentx_enabled = 0;
+
+static struct thread_master *agentx_tm;
+static struct thread *timeout_thr = NULL;
+static struct list *events = NULL;
+
+static void agentx_events_update(void);
+
+static int
+agentx_timeout(struct thread *t)
+{
+ timeout_thr = NULL;
+
+ snmp_timeout ();
+ run_alarms ();
+ netsnmp_check_outstanding_agent_requests ();
+ agentx_events_update ();
+ return 0;
+}
+
+static int
+agentx_read(struct thread *t)
+{
+ fd_set fds;
+ struct listnode *ln = THREAD_ARG (t);
+ list_delete_node (events, ln);
+
+ FD_ZERO (&fds);
+ FD_SET (THREAD_FD (t), &fds);
+ snmp_read (&fds);
+
+ netsnmp_check_outstanding_agent_requests ();
+ agentx_events_update ();
+ return 0;
+}
+
+static void
+agentx_events_update(void)
+{
+ int maxfd = 0;
+ int block = 1;
+ struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
+ fd_set fds;
+ struct listnode *ln;
+ struct thread *thr;
+ int fd, thr_fd;
+
+ THREAD_OFF (timeout_thr);
+
+ FD_ZERO (&fds);
+ snmp_select_info (&maxfd, &fds, &timeout, &block);
+
+ if (!block)
+ timeout_thr = thread_add_timer_tv (agentx_tm, agentx_timeout, NULL, &timeout);
+
+ ln = listhead (events);
+ thr = ln ? listgetdata (ln) : NULL;
+ thr_fd = thr ? THREAD_FD (thr) : -1;
+
+ /* "two-pointer" / two-list simultaneous iteration
+ * ln/thr/thr_fd point to the next existing event listener to hit while
+ * fd counts to catch up */
+ for (fd = 0; fd < maxfd; fd++)
+ {
+ /* caught up */
+ if (thr_fd == fd)
+ {
+ struct listnode *nextln = listnextnode (ln);
+ if (!FD_ISSET (fd, &fds))
+ {
+ thread_cancel (thr);
+ list_delete_node (events, ln);
+ }
+ ln = nextln;
+ thr = ln ? listgetdata (ln) : NULL;
+ thr_fd = thr ? THREAD_FD (thr) : -1;
+ }
+ /* need listener, but haven't hit one where it would be */
+ else if (FD_ISSET (fd, &fds))
+ {
+ struct listnode *newln;
+ thr = thread_add_read (agentx_tm, agentx_read, NULL, fd);
+ newln = listnode_add_before (events, ln, thr);
+ thr->arg = newln;
+ }
+ }
+
+ /* leftover event listeners at this point have fd > maxfd, delete them */
+ while (ln)
+ {
+ struct listnode *nextln = listnextnode (ln);
+ thread_cancel (listgetdata (ln));
+ list_delete_node (events, ln);
+ ln = nextln;
+ }
+}
/* AgentX node. */
static struct cmd_node agentx_node =
@@ -77,6 +176,8 @@ DEFUN (agentx_enable,
if (!agentx_enabled)
{
init_snmp("quagga");
+ events = list_new();
+ agentx_events_update ();
agentx_enabled = 1;
return CMD_SUCCESS;
}
@@ -99,6 +200,8 @@ DEFUN (no_agentx,
void
smux_init (struct thread_master *tm)
{
+ agentx_tm = tm;
+
netsnmp_enable_subagent ();
snmp_disable_log ();
snmp_enable_calllog ();
@@ -207,6 +310,7 @@ smux_trap (struct variable *vp, size_t vp_len,
send_v2trap (notification_vars);
snmp_free_varbind (notification_vars);
+ agentx_events_update ();
return 1;
}
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 f7800aa724..b4ef30a300 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -666,8 +666,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;
@@ -961,6 +965,7 @@ DEFUN (config_exit,
vty_config_unlock (vty);
break;
case INTERFACE_NODE:
+ case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
case BGP_NODE:
@@ -989,6 +994,9 @@ DEFUN (config_exit,
case KEYCHAIN_KEY_NODE:
vty->node = KEYCHAIN_NODE;
break;
+ case LINK_PARAMS_NODE:
+ vty->node = INTERFACE_NODE;
+ break;
default:
break;
}
@@ -1016,6 +1024,7 @@ DEFUN (config_end,
break;
case CONFIG_NODE:
case INTERFACE_NODE:
+ case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
case RIP_NODE:
@@ -1038,6 +1047,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;
@@ -1757,6 +1767,10 @@ set_log_file(struct vty *vty, const char *fname, int loglevel)
host.logfile = XSTRDUP (MTYPE_HOST, fname);
+#if defined(HAVE_CUMULUS)
+ if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
+ zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED;
+#endif
return CMD_SUCCESS;
}
@@ -1955,11 +1969,25 @@ DEFUN (no_config_log_timestamp_precision,
int
cmd_banner_motd_file (const char *file)
{
- if (host.motdfile)
- XFREE (MTYPE_HOST, host.motdfile);
- host.motdfile = XSTRDUP (MTYPE_HOST, file);
+ int success = CMD_SUCCESS;
+ char p[PATH_MAX];
+ char *rpath;
+ char *in;
- return CMD_SUCCESS;
+ rpath = realpath (file, p);
+ if (!rpath)
+ return CMD_ERR_NO_FILE;
+ in = strstr (rpath, SYSCONFDIR);
+ if (in == rpath)
+ {
+ if (host.motdfile)
+ XFREE (MTYPE_HOST, host.motdfile);
+ host.motdfile = XSTRDUP (MTYPE_HOST, file);
+ }
+ else
+ success = CMD_WARNING;
+
+ return success;
}
DEFUN (banner_motd_file,
@@ -1970,7 +1998,15 @@ DEFUN (banner_motd_file,
"Banner from a file\n"
"Filename\n")
{
- return cmd_banner_motd_file (argv[3]->arg);
+ int cmd = cmd_banner_motd_file (argv[3]->arg);
+
+ if (cmd == CMD_ERR_NO_FILE)
+ vty_out (vty, "%s does not exist", argv[3]->arg);
+ else if (cmd == CMD_WARNING)
+ vty_out (vty, "%s must be in %s",
+ argv[0], SYSCONFDIR);
+
+ return cmd;
}
DEFUN (banner_motd_default,
@@ -2098,7 +2134,6 @@ cmd_init (int terminal)
install_element (RESTRICTED_NODE, &config_enable_cmd);
install_element (RESTRICTED_NODE, &config_terminal_length_cmd);
install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd);
- install_element (RESTRICTED_NODE, &show_commandtree_cmd);
install_element (RESTRICTED_NODE, &echo_cmd);
}
@@ -2167,7 +2202,6 @@ cmd_init (int terminal)
vrf_install_commands ();
}
- install_element (CONFIG_NODE, &show_commandtree_cmd);
srandom(time(NULL));
}
diff --git a/lib/command.h b/lib/command.h
index 786539034b..5e1b48c68f 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -75,6 +75,7 @@ enum node_type
AAA_NODE, /* AAA node. */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
+ NS_NODE, /* Logical-Router node. */
VRF_NODE, /* VRF mode node. */
INTERFACE_NODE, /* Interface mode node. */
ZEBRA_NODE, /* zebra connection node. */
@@ -109,6 +110,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
@@ -356,6 +358,10 @@ struct cmd_element
#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/linklist.c b/lib/linklist.c
index 4b16f07dd1..d27a2da848 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -122,7 +122,7 @@ listnode_add_sort (struct list *list, void *val)
list->count++;
}
-void
+struct listnode *
listnode_add_after (struct list *list, struct listnode *pp, void *val)
{
struct listnode *nn;
@@ -157,6 +157,45 @@ listnode_add_after (struct list *list, struct listnode *pp, void *val)
pp->next = nn;
}
list->count++;
+ return nn;
+}
+
+struct listnode *
+listnode_add_before (struct list *list, struct listnode *pp, void *val)
+{
+ struct listnode *nn;
+
+ assert (val != NULL);
+
+ nn = listnode_new ();
+ nn->data = val;
+
+ if (pp == NULL)
+ {
+ if (list->tail)
+ list->tail->next = nn;
+ else
+ list->head = nn;
+
+ nn->prev = list->tail;
+ nn->next = pp;
+
+ list->tail = nn;
+ }
+ else
+ {
+ if (pp->prev)
+ pp->prev->next = nn;
+ else
+ list->head = nn;
+
+ nn->prev = pp->prev;
+ nn->next = pp;
+
+ pp->prev = nn;
+ }
+ list->count++;
+ return nn;
}
/* Move given listnode to tail of the list */
@@ -268,52 +307,6 @@ list_delete_node (struct list *list, struct listnode *node)
/* ospf_spf.c */
void
-list_add_node_prev (struct list *list, struct listnode *current, void *val)
-{
- struct listnode *node;
-
- assert (val != NULL);
-
- node = listnode_new ();
- node->next = current;
- node->data = val;
-
- if (current->prev == NULL)
- list->head = node;
- else
- current->prev->next = node;
-
- node->prev = current->prev;
- current->prev = node;
-
- list->count++;
-}
-
-/* ospf_spf.c */
-void
-list_add_node_next (struct list *list, struct listnode *current, void *val)
-{
- struct listnode *node;
-
- assert (val != NULL);
-
- node = listnode_new ();
- node->prev = current;
- node->data = val;
-
- if (current->next == NULL)
- list->tail = node;
- else
- current->next->prev = node;
-
- node->next = current->next;
- current->next = node;
-
- list->count++;
-}
-
-/* ospf_spf.c */
-void
list_add_list (struct list *l, struct list *m)
{
struct listnode *n;
diff --git a/lib/linklist.h b/lib/linklist.h
index 6209c8b9d6..e99e50f4fa 100644
--- a/lib/linklist.h
+++ b/lib/linklist.h
@@ -67,7 +67,8 @@ extern void list_free (struct list *);
extern void listnode_add (struct list *, void *);
extern void listnode_add_sort (struct list *, void *);
-extern void listnode_add_after (struct list *, struct listnode *, void *);
+extern struct listnode *listnode_add_after (struct list *, struct listnode *, void *);
+extern struct listnode *listnode_add_before (struct list *, struct listnode *, void *);
extern void listnode_move_to_tail (struct list *, struct listnode *);
extern void listnode_delete (struct list *, void *);
extern struct listnode *listnode_lookup (struct list *, void *);
@@ -80,8 +81,6 @@ extern void list_delete_all_node (struct list *);
extern void list_delete_node (struct list *, struct listnode *);
/* For ospf_spf.c */
-extern void list_add_node_prev (struct list *, struct listnode *, void *);
-extern void list_add_node_next (struct list *, struct listnode *, void *);
extern void list_add_list (struct list *, struct list *);
/* List iteration macro.
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..510312f336 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -77,6 +77,10 @@ struct memory_list memory_list_lib[] =
{ MTYPE_VRF, "VRF" },
{ MTYPE_VRF_NAME, "VRF name" },
{ MTYPE_VRF_BITMAP, "VRF bit-map" },
+ { MTYPE_NS, "Logical-Router" },
+ { MTYPE_NS_NAME, "Logical-Router Name" },
+ { MTYPE_NS_BITMAP, "Logical-Router bit-map" },
+ { MTYPE_IF_LINK_PARAMS, "Informational Link Parameters" },
{ -1, NULL },
};
@@ -228,6 +232,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 +275,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.c b/lib/nexthop.c
index 5853884218..14486ea157 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -153,3 +153,36 @@ nexthops_free (struct nexthop *nexthop)
nexthop_free (nh);
}
}
+
+const char *
+nexthop2str (struct nexthop *nexthop, char *str, int size)
+{
+ switch (nexthop->type)
+ {
+ case NEXTHOP_TYPE_IFINDEX:
+ snprintf (str, size, "if %u", nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4));
+ break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ snprintf (str, size, "%s if %u",
+ inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6));
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ snprintf (str, size, "%s if %u",
+ inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ snprintf (str, size, "blackhole");
+ break;
+ default:
+ snprintf (str, size, "unknown");
+ break;
+ }
+
+ return str;
+}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index eb9b27ea9e..39e8b5425f 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -26,6 +26,9 @@
#include "prefix.h"
+/* Maximum next hop string length - gateway + ifindex */
+#define NEXTHOP_STRLEN (INET6_ADDRSTRLEN + 30)
+
union g_addr {
struct in_addr ipv4;
struct in6_addr ipv6;
@@ -48,7 +51,7 @@ struct nexthop
struct nexthop *prev;
/* Interface index. */
- unsigned int ifindex;
+ ifindex_t ifindex;
enum nexthop_types_t type;
@@ -97,4 +100,5 @@ void nexthops_free (struct nexthop *nexthop);
extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type);
extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2);
+extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size);
#endif /*_LIB_NEXTHOP_H */
diff --git a/lib/ns.c b/lib/ns.c
new file mode 100644
index 0000000000..4765a18ef2
--- /dev/null
+++ b/lib/ns.c
@@ -0,0 +1,734 @@
+/*
+ * NS functions.
+ * Copyright (C) 2014 6WIND S.A.
+ *
+ * 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>
+
+#ifdef HAVE_NETNS
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#include <sched.h>
+#endif
+
+#include "if.h"
+#include "ns.h"
+#include "prefix.h"
+#include "table.h"
+#include "log.h"
+#include "memory.h"
+
+#include "command.h"
+#include "vty.h"
+
+
+#ifndef CLONE_NEWNET
+#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */
+#endif
+
+#ifndef HAVE_SETNS
+static inline int setns(int fd, int nstype)
+{
+#ifdef __NR_setns
+ return syscall(__NR_setns, fd, nstype);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif /* HAVE_SETNS */
+
+#ifdef HAVE_NETNS
+
+#define NS_DEFAULT_NAME "/proc/self/ns/net"
+static int have_netns_enabled = -1;
+
+#else /* !HAVE_NETNS */
+
+#define NS_DEFAULT_NAME "Default-logical-router"
+
+#endif /* HAVE_NETNS */
+
+static int have_netns(void)
+{
+#ifdef HAVE_NETNS
+ if (have_netns_enabled < 0)
+ {
+ int fd = open (NS_DEFAULT_NAME, O_RDONLY);
+
+ if (fd < 0)
+ have_netns_enabled = 0;
+ else
+ {
+ have_netns_enabled = 1;
+ close(fd);
+ }
+ }
+ return have_netns_enabled;
+#else
+ return 0;
+#endif
+}
+
+struct ns
+{
+ /* Identifier, same as the vector index */
+ ns_id_t ns_id;
+ /* Name */
+ char *name;
+ /* File descriptor */
+ int fd;
+
+ /* Master list of interfaces belonging to this NS */
+ struct list *iflist;
+
+ /* User data */
+ void *info;
+};
+
+/* Holding NS hooks */
+struct ns_master
+{
+ int (*ns_new_hook) (ns_id_t, void **);
+ int (*ns_delete_hook) (ns_id_t, void **);
+ int (*ns_enable_hook) (ns_id_t, void **);
+ int (*ns_disable_hook) (ns_id_t, void **);
+} ns_master = {0,};
+
+/* NS table */
+struct route_table *ns_table = NULL;
+
+static int ns_is_enabled (struct ns *ns);
+static int ns_enable (struct ns *ns);
+static void ns_disable (struct ns *ns);
+
+
+/* Build the table key */
+static void
+ns_build_key (ns_id_t ns_id, struct prefix *p)
+{
+ p->family = AF_INET;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4.s_addr = ns_id;
+}
+
+/* Get a NS. If not found, create one. */
+static struct ns *
+ns_get (ns_id_t ns_id)
+{
+ struct prefix p;
+ struct route_node *rn;
+ struct ns *ns;
+
+ ns_build_key (ns_id, &p);
+ rn = route_node_get (ns_table, &p);
+ if (rn->info)
+ {
+ ns = (struct ns *)rn->info;
+ route_unlock_node (rn); /* get */
+ return ns;
+ }
+
+ ns = XCALLOC (MTYPE_NS, sizeof (struct ns));
+ ns->ns_id = ns_id;
+ ns->fd = -1;
+ rn->info = ns;
+
+ /*
+ * Initialize interfaces.
+ *
+ * I'm not sure if this belongs here or in
+ * the vrf code.
+ */
+ // if_init (&ns->iflist);
+
+ zlog_info ("NS %u is created.", ns_id);
+
+ if (ns_master.ns_new_hook)
+ (*ns_master.ns_new_hook) (ns_id, &ns->info);
+
+ return ns;
+}
+
+/* Delete a NS. This is called in ns_terminate(). */
+static void
+ns_delete (struct ns *ns)
+{
+ zlog_info ("NS %u is to be deleted.", ns->ns_id);
+
+ ns_disable (ns);
+
+ if (ns_master.ns_delete_hook)
+ (*ns_master.ns_delete_hook) (ns->ns_id, &ns->info);
+
+ /*
+ * I'm not entirely sure if the vrf->iflist
+ * needs to be moved into here or not.
+ */
+ //if_terminate (&ns->iflist);
+
+ if (ns->name)
+ XFREE (MTYPE_NS_NAME, ns->name);
+
+ XFREE (MTYPE_NS, ns);
+}
+
+/* Look up a NS by identifier. */
+static struct ns *
+ns_lookup (ns_id_t ns_id)
+{
+ struct prefix p;
+ struct route_node *rn;
+ struct ns *ns = NULL;
+
+ ns_build_key (ns_id, &p);
+ rn = route_node_lookup (ns_table, &p);
+ if (rn)
+ {
+ ns = (struct ns *)rn->info;
+ route_unlock_node (rn); /* lookup */
+ }
+ return ns;
+}
+
+/*
+ * Check whether the NS is enabled - that is, whether the NS
+ * is ready to allocate resources. Currently there's only one
+ * type of resource: socket.
+ */
+static int
+ns_is_enabled (struct ns *ns)
+{
+ if (have_netns())
+ return ns && ns->fd >= 0;
+ else
+ return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT;
+}
+
+/*
+ * Enable a NS - that is, let the NS be ready to use.
+ * The NS_ENABLE_HOOK callback will be called to inform
+ * that they can allocate resources in this NS.
+ *
+ * RETURN: 1 - enabled successfully; otherwise, 0.
+ */
+static int
+ns_enable (struct ns *ns)
+{
+
+ if (!ns_is_enabled (ns))
+ {
+ if (have_netns()) {
+ ns->fd = open (ns->name, O_RDONLY);
+ } else {
+ ns->fd = -2; /* Remember that ns_enable_hook has been called */
+ errno = -ENOTSUP;
+ }
+
+ if (!ns_is_enabled (ns))
+ {
+ zlog_err ("Can not enable NS %u: %s!",
+ ns->ns_id, safe_strerror (errno));
+ return 0;
+ }
+
+ if (have_netns())
+ zlog_info ("NS %u is associated with NETNS %s.",
+ ns->ns_id, ns->name);
+
+ zlog_info ("NS %u is enabled.", ns->ns_id);
+ if (ns_master.ns_enable_hook)
+ (*ns_master.ns_enable_hook) (ns->ns_id, &ns->info);
+ }
+
+ return 1;
+}
+
+/*
+ * Disable a NS - that is, let the NS be unusable.
+ * The NS_DELETE_HOOK callback will be called to inform
+ * that they must release the resources in the NS.
+ */
+static void
+ns_disable (struct ns *ns)
+{
+ if (ns_is_enabled (ns))
+ {
+ zlog_info ("NS %u is to be disabled.", ns->ns_id);
+
+ if (ns_master.ns_disable_hook)
+ (*ns_master.ns_disable_hook) (ns->ns_id, &ns->info);
+
+ if (have_netns())
+ close (ns->fd);
+
+ ns->fd = -1;
+ }
+}
+
+
+/* Add a NS hook. Please add hooks before calling ns_init(). */
+void
+ns_add_hook (int type, int (*func)(ns_id_t, void **))
+{
+ switch (type) {
+ case NS_NEW_HOOK:
+ ns_master.ns_new_hook = func;
+ break;
+ case NS_DELETE_HOOK:
+ ns_master.ns_delete_hook = func;
+ break;
+ case NS_ENABLE_HOOK:
+ ns_master.ns_enable_hook = func;
+ break;
+ case NS_DISABLE_HOOK:
+ ns_master.ns_disable_hook = func;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Return the iterator of the first NS. */
+ns_iter_t
+ns_first (void)
+{
+ struct route_node *rn;
+
+ for (rn = route_top (ns_table); rn; rn = route_next (rn))
+ if (rn->info)
+ {
+ route_unlock_node (rn); /* top/next */
+ return (ns_iter_t)rn;
+ }
+ return NS_ITER_INVALID;
+}
+
+/* Return the next NS iterator to the given iterator. */
+ns_iter_t
+ns_next (ns_iter_t iter)
+{
+ struct route_node *rn = NULL;
+
+ /* Lock it first because route_next() will unlock it. */
+ if (iter != NS_ITER_INVALID)
+ rn = route_next (route_lock_node ((struct route_node *)iter));
+
+ for (; rn; rn = route_next (rn))
+ if (rn->info)
+ {
+ route_unlock_node (rn); /* next */
+ return (ns_iter_t)rn;
+ }
+ return NS_ITER_INVALID;
+}
+
+/* Return the NS iterator of the given NS ID. If it does not exist,
+ * the iterator of the next existing NS is returned. */
+ns_iter_t
+ns_iterator (ns_id_t ns_id)
+{
+ struct prefix p;
+ struct route_node *rn;
+
+ ns_build_key (ns_id, &p);
+ rn = route_node_get (ns_table, &p);
+ if (rn->info)
+ {
+ /* OK, the NS exists. */
+ route_unlock_node (rn); /* get */
+ return (ns_iter_t)rn;
+ }
+
+ /* Find the next NS. */
+ for (rn = route_next (rn); rn; rn = route_next (rn))
+ if (rn->info)
+ {
+ route_unlock_node (rn); /* next */
+ return (ns_iter_t)rn;
+ }
+
+ return NS_ITER_INVALID;
+}
+
+/* Obtain the NS ID from the given NS iterator. */
+ns_id_t
+ns_iter2id (ns_iter_t iter)
+{
+ struct route_node *rn = (struct route_node *) iter;
+ return (rn && rn->info) ? ((struct ns *)rn->info)->ns_id : NS_DEFAULT;
+}
+
+/* Obtain the data pointer from the given NS iterator. */
+void *
+ns_iter2info (ns_iter_t iter)
+{
+ struct route_node *rn = (struct route_node *) iter;
+ return (rn && rn->info) ? ((struct ns *)rn->info)->info : NULL;
+}
+
+/* Obtain the interface list from the given NS iterator. */
+struct list *
+ns_iter2iflist (ns_iter_t iter)
+{
+ struct route_node *rn = (struct route_node *) iter;
+ return (rn && rn->info) ? ((struct ns *)rn->info)->iflist : NULL;
+}
+
+/* Get the data pointer of the specified NS. If not found, create one. */
+void *
+ns_info_get (ns_id_t ns_id)
+{
+ struct ns *ns = ns_get (ns_id);
+ return ns->info;
+}
+
+/* Look up the data pointer of the specified NS. */
+void *
+ns_info_lookup (ns_id_t ns_id)
+{
+ struct ns *ns = ns_lookup (ns_id);
+ return ns ? ns->info : NULL;
+}
+
+/* Look up the interface list in a NS. */
+struct list *
+ns_iflist (ns_id_t ns_id)
+{
+ struct ns * ns = ns_lookup (ns_id);
+ return ns ? ns->iflist : NULL;
+}
+
+/* Get the interface list of the specified NS. Create one if not find. */
+struct list *
+ns_iflist_get (ns_id_t ns_id)
+{
+ struct ns * ns = ns_get (ns_id);
+ return ns->iflist;
+}
+
+/*
+ * NS bit-map
+ */
+
+#define NS_BITMAP_NUM_OF_GROUPS 8
+#define NS_BITMAP_NUM_OF_BITS_IN_GROUP \
+ (UINT16_MAX / NS_BITMAP_NUM_OF_GROUPS)
+#define NS_BITMAP_NUM_OF_BYTES_IN_GROUP \
+ (NS_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
+
+#define NS_BITMAP_GROUP(_id) \
+ ((_id) / NS_BITMAP_NUM_OF_BITS_IN_GROUP)
+#define NS_BITMAP_BIT_OFFSET(_id) \
+ ((_id) % NS_BITMAP_NUM_OF_BITS_IN_GROUP)
+
+#define NS_BITMAP_INDEX_IN_GROUP(_bit_offset) \
+ ((_bit_offset) / CHAR_BIT)
+#define NS_BITMAP_FLAG(_bit_offset) \
+ (((u_char)1) << ((_bit_offset) % CHAR_BIT))
+
+struct ns_bitmap
+{
+ u_char *groups[NS_BITMAP_NUM_OF_GROUPS];
+};
+
+ns_bitmap_t
+ns_bitmap_init (void)
+{
+ return (ns_bitmap_t) XCALLOC (MTYPE_NS_BITMAP, sizeof (struct ns_bitmap));
+}
+
+void
+ns_bitmap_free (ns_bitmap_t bmap)
+{
+ struct ns_bitmap *bm = (struct ns_bitmap *) bmap;
+ int i;
+
+ if (bmap == NS_BITMAP_NULL)
+ return;
+
+ for (i = 0; i < NS_BITMAP_NUM_OF_GROUPS; i++)
+ if (bm->groups[i])
+ XFREE (MTYPE_NS_BITMAP, bm->groups[i]);
+
+ XFREE (MTYPE_NS_BITMAP, bm);
+}
+
+void
+ns_bitmap_set (ns_bitmap_t bmap, ns_id_t ns_id)
+{
+ struct ns_bitmap *bm = (struct ns_bitmap *) bmap;
+ u_char group = NS_BITMAP_GROUP (ns_id);
+ u_char offset = NS_BITMAP_BIT_OFFSET (ns_id);
+
+ if (bmap == NS_BITMAP_NULL)
+ return;
+
+ if (bm->groups[group] == NULL)
+ bm->groups[group] = XCALLOC (MTYPE_NS_BITMAP,
+ NS_BITMAP_NUM_OF_BYTES_IN_GROUP);
+
+ SET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)],
+ NS_BITMAP_FLAG (offset));
+}
+
+void
+ns_bitmap_unset (ns_bitmap_t bmap, ns_id_t ns_id)
+{
+ struct ns_bitmap *bm = (struct ns_bitmap *) bmap;
+ u_char group = NS_BITMAP_GROUP (ns_id);
+ u_char offset = NS_BITMAP_BIT_OFFSET (ns_id);
+
+ if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL)
+ return;
+
+ UNSET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)],
+ NS_BITMAP_FLAG (offset));
+}
+
+int
+ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id)
+{
+ struct ns_bitmap *bm = (struct ns_bitmap *) bmap;
+ u_char group = NS_BITMAP_GROUP (ns_id);
+ u_char offset = NS_BITMAP_BIT_OFFSET (ns_id);
+
+ if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL)
+ return 0;
+
+ return CHECK_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)],
+ NS_BITMAP_FLAG (offset)) ? 1 : 0;
+}
+
+/*
+ * NS realization with NETNS
+ */
+
+static char *
+ns_netns_pathname (struct vty *vty, const char *name)
+{
+ static char pathname[PATH_MAX];
+ char *result;
+
+ if (name[0] == '/') /* absolute pathname */
+ result = realpath (name, pathname);
+ else /* relevant pathname */
+ {
+ char tmp_name[PATH_MAX];
+ snprintf (tmp_name, PATH_MAX, "%s/%s", NS_RUN_DIR, name);
+ result = realpath (tmp_name, pathname);
+ }
+
+ if (! result)
+ {
+ vty_out (vty, "Invalid pathname: %s%s", safe_strerror (errno),
+ VTY_NEWLINE);
+ return NULL;
+ }
+ return pathname;
+}
+
+DEFUN (ns_netns,
+ ns_netns_cmd,
+ "logical-router <1-65535> ns NAME",
+ "Enable a logical-router\n"
+ "Specify the logical-router indentifier\n"
+ "The Name Space\n"
+ "The file name in " NS_RUN_DIR ", or a full pathname\n")
+{
+ ns_id_t ns_id = NS_DEFAULT;
+ struct ns *ns = NULL;
+ char *pathname = ns_netns_pathname (vty, argv[1]);
+
+ if (!pathname)
+ return CMD_WARNING;
+
+ VTY_GET_INTEGER ("NS ID", ns_id, argv[0]);
+ ns = ns_get (ns_id);
+
+ if (ns->name && strcmp (ns->name, pathname) != 0)
+ {
+ vty_out (vty, "NS %u is already configured with NETNS %s%s",
+ ns->ns_id, ns->name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!ns->name)
+ ns->name = XSTRDUP (MTYPE_NS_NAME, pathname);
+
+ if (!ns_enable (ns))
+ {
+ vty_out (vty, "Can not associate NS %u with NETNS %s%s",
+ ns->ns_id, ns->name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ns_netns,
+ no_ns_netns_cmd,
+ "no logical-router <1-65535> ns NAME",
+ NO_STR
+ "Enable a Logical-Router\n"
+ "Specify the Logical-Router identifier\n"
+ "The Name Space\n"
+ "The file name in " NS_RUN_DIR ", or a full pathname\n")
+{
+ ns_id_t ns_id = NS_DEFAULT;
+ struct ns *ns = NULL;
+ char *pathname = ns_netns_pathname (vty, argv[1]);
+
+ if (!pathname)
+ return CMD_WARNING;
+
+ VTY_GET_INTEGER ("NS ID", ns_id, argv[0]);
+ ns = ns_lookup (ns_id);
+
+ if (!ns)
+ {
+ vty_out (vty, "NS %u is not found%s", ns_id, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (ns->name && strcmp (ns->name, pathname) != 0)
+ {
+ vty_out (vty, "Incorrect NETNS file name%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ns_disable (ns);
+
+ if (ns->name)
+ {
+ XFREE (MTYPE_NS_NAME, ns->name);
+ ns->name = NULL;
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* NS node. */
+static struct cmd_node ns_node =
+{
+ NS_NODE,
+ "", /* NS node has no interface. */
+ 1
+};
+
+/* NS configuration write function. */
+static int
+ns_config_write (struct vty *vty)
+{
+ struct route_node *rn;
+ struct ns *ns;
+ int write = 0;
+
+ for (rn = route_top (ns_table); rn; rn = route_next (rn))
+ if ((ns = rn->info) != NULL &&
+ ns->ns_id != NS_DEFAULT && ns->name)
+ {
+ vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, VTY_NEWLINE);
+ write++;
+ }
+
+ return write;
+}
+
+/* Initialize NS module. */
+void
+ns_init (void)
+{
+ struct ns *default_ns;
+
+ /* Allocate NS table. */
+ ns_table = route_table_init ();
+
+ /* The default NS always exists. */
+ default_ns = ns_get (NS_DEFAULT);
+ if (!default_ns)
+ {
+ zlog_err ("ns_init: failed to create the default NS!");
+ exit (1);
+ }
+
+ /* Set the default NS name. */
+ default_ns->name = XSTRDUP (MTYPE_NS_NAME, NS_DEFAULT_NAME);
+
+ /* Enable the default NS. */
+ if (!ns_enable (default_ns))
+ {
+ zlog_err ("ns_init: failed to enable the default NS!");
+ exit (1);
+ }
+
+ if (have_netns())
+ {
+ /* Install NS commands. */
+ install_node (&ns_node, ns_config_write);
+ install_element (CONFIG_NODE, &ns_netns_cmd);
+ install_element (CONFIG_NODE, &no_ns_netns_cmd);
+ }
+}
+
+/* Terminate NS module. */
+void
+ns_terminate (void)
+{
+ struct route_node *rn;
+ struct ns *ns;
+
+ for (rn = route_top (ns_table); rn; rn = route_next (rn))
+ if ((ns = rn->info) != NULL)
+ ns_delete (ns);
+
+ route_table_finish (ns_table);
+ ns_table = NULL;
+}
+
+/* Create a socket for the NS. */
+int
+ns_socket (int domain, int type, int protocol, ns_id_t ns_id)
+{
+ struct ns *ns = ns_lookup (ns_id);
+ int ret = -1;
+
+ if (!ns_is_enabled (ns))
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (have_netns())
+ {
+ ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0;
+ if (ret >= 0)
+ {
+ ret = socket (domain, type, protocol);
+ if (ns_id != NS_DEFAULT)
+ setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET);
+ }
+ }
+ else
+ ret = socket (domain, type, protocol);
+
+ return ret;
+}
diff --git a/lib/ns.h b/lib/ns.h
new file mode 100644
index 0000000000..3fac739861
--- /dev/null
+++ b/lib/ns.h
@@ -0,0 +1,142 @@
+/*
+ * NS related header.
+ * Copyright (C) 2014 6WIND S.A.
+ *
+ * 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_NS_H
+#define _ZEBRA_NS_H
+
+#include "linklist.h"
+
+typedef u_int16_t ns_id_t;
+
+/* The default NS ID */
+#define NS_DEFAULT 0
+
+/*
+ * The command strings
+ */
+#define NS_RUN_DIR "/var/run/netns"
+#define NS_CMD_STR "logical-router <0-65535>"
+#define NS_CMD_HELP_STR "Specify the Logical-Router\nThe Logical-Router ID\n"
+
+#define NS_ALL_CMD_STR "logical-router all"
+#define NS_ALL_CMD_HELP_STR "Specify the logical-router\nAll logical-router's\n"
+
+/*
+ * NS hooks
+ */
+
+#define NS_NEW_HOOK 0 /* a new logical-router is just created */
+#define NS_DELETE_HOOK 1 /* a logical-router is to be deleted */
+#define NS_ENABLE_HOOK 2 /* a logical-router is ready to use */
+#define NS_DISABLE_HOOK 3 /* a logical-router is to be unusable */
+
+/*
+ * Add a specific hook ns module.
+ * @param1: hook type
+ * @param2: the callback function
+ * - param 1: the NS ID
+ * - param 2: the address of the user data pointer (the user data
+ * can be stored in or freed from there)
+ */
+extern void ns_add_hook (int, int (*)(ns_id_t, void **));
+
+/*
+ * NS iteration
+ */
+
+typedef void * ns_iter_t;
+#define NS_ITER_INVALID NULL /* invalid value of the iterator */
+
+/*
+ * NS iteration utilities. Example for the usage:
+ *
+ * ns_iter_t iter = ns_first();
+ * for (; iter != NS_ITER_INVALID; iter = ns_next (iter))
+ *
+ * or
+ *
+ * ns_iter_t iter = ns_iterator (<a given NS ID>);
+ * for (; iter != NS_ITER_INVALID; iter = ns_next (iter))
+ */
+
+/* Return the iterator of the first NS. */
+extern ns_iter_t ns_first (void);
+/* Return the next NS iterator to the given iterator. */
+extern ns_iter_t ns_next (ns_iter_t);
+/* Return the NS iterator of the given NS ID. If it does not exist,
+ * the iterator of the next existing NS is returned. */
+extern ns_iter_t ns_iterator (ns_id_t);
+
+/*
+ * NS iterator to properties
+ */
+extern ns_id_t ns_iter2id (ns_iter_t);
+extern void *ns_iter2info (ns_iter_t);
+extern struct list *ns_iter2iflist (ns_iter_t);
+
+/*
+ * Utilities to obtain the user data
+ */
+
+/* Get the data pointer of the specified NS. If not found, create one. */
+extern void *ns_info_get (ns_id_t);
+/* Look up the data pointer of the specified NS. */
+extern void *ns_info_lookup (ns_id_t);
+
+/*
+ * Utilities to obtain the interface list
+ */
+
+/* Look up the interface list of the specified NS. */
+extern struct list *ns_iflist (ns_id_t);
+/* Get the interface list of the specified NS. Create one if not find. */
+extern struct list *ns_iflist_get (ns_id_t);
+
+/*
+ * NS bit-map: maintaining flags, one bit per NS ID
+ */
+
+typedef void * ns_bitmap_t;
+#define NS_BITMAP_NULL NULL
+
+extern ns_bitmap_t ns_bitmap_init (void);
+extern void ns_bitmap_free (ns_bitmap_t);
+extern void ns_bitmap_set (ns_bitmap_t, ns_id_t);
+extern void ns_bitmap_unset (ns_bitmap_t, ns_id_t);
+extern int ns_bitmap_check (ns_bitmap_t, ns_id_t);
+
+/*
+ * NS initializer/destructor
+ */
+/* Please add hooks before calling ns_init(). */
+extern void ns_init (void);
+extern void ns_terminate (void);
+
+/*
+ * NS utilities
+ */
+
+/* Create a socket serving for the given NS */
+extern int ns_socket (int, int, int, ns_id_t);
+
+#endif /*_ZEBRA_NS_H*/
+
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 256cd3a49a..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)
@@ -572,7 +657,7 @@ str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
{
int plen;
- cp = XMALLOC (0, (pnt - str) + 1);
+ cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
strncpy (cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_pton (AF_INET6, cp, &p->prefix);
@@ -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 4c237563a5..809e749fb9 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -373,6 +373,47 @@ stream_getw_from (struct stream *s, size_t from)
return w;
}
+/* Get next 3-byte from the stream. */
+u_int32_t
+stream_get3_from (struct stream *s, size_t from)
+{
+ u_int32_t l;
+
+ STREAM_VERIFY_SANE(s);
+
+ if (!GETP_VALID (s, from + 3))
+ {
+ STREAM_BOUND_WARN (s, "get 3byte");
+ return 0;
+ }
+
+ l = s->data[from++] << 16;
+ l |= s->data[from++] << 8;
+ l |= s->data[from];
+
+ return l;
+}
+
+u_int32_t
+stream_get3 (struct stream *s)
+{
+ u_int32_t l;
+
+ STREAM_VERIFY_SANE(s);
+
+ if (STREAM_READABLE (s) < 3)
+ {
+ STREAM_BOUND_WARN (s, "get 3byte");
+ return 0;
+ }
+
+ l = s->data[s->getp++] << 16;
+ l |= s->data[s->getp++] << 8;
+ l |= s->data[s->getp++];
+
+ return l;
+}
+
/* Get next long word from the stream. */
u_int32_t
stream_getl_from (struct stream *s, size_t from)
@@ -502,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
@@ -568,6 +631,25 @@ stream_putw (struct stream *s, u_int16_t w)
/* Put long word to the stream. */
int
+stream_put3 (struct stream *s, u_int32_t l)
+{
+ STREAM_VERIFY_SANE (s);
+
+ if (STREAM_WRITEABLE (s) < 3)
+ {
+ STREAM_BOUND_WARN (s, "put");
+ return 0;
+ }
+
+ s->data[s->endp++] = (u_char)(l >> 16);
+ s->data[s->endp++] = (u_char)(l >> 8);
+ s->data[s->endp++] = (u_char)l;
+
+ return 3;
+}
+
+/* Put long word to the stream. */
+int
stream_putl (struct stream *s, u_int32_t l)
{
STREAM_VERIFY_SANE (s);
@@ -611,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);
@@ -644,6 +748,23 @@ stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
}
int
+stream_put3_at (struct stream *s, size_t putp, u_int32_t l)
+{
+ STREAM_VERIFY_SANE(s);
+
+ if (!PUT_AT_VALID (s, putp + 3))
+ {
+ STREAM_BOUND_WARN (s, "put");
+ return 0;
+ }
+ s->data[putp] = (u_char)(l >> 16);
+ s->data[putp + 1] = (u_char)(l >> 8);
+ s->data[putp + 2] = (u_char)l;
+
+ return 3;
+}
+
+int
stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
{
STREAM_VERIFY_SANE(s);
diff --git a/lib/stream.h b/lib/stream.h
index 738034438c..1e2bc89b32 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -167,6 +167,8 @@ extern int stream_putc (struct stream *, u_char);
extern int stream_putc_at (struct stream *, size_t, u_char);
extern int stream_putw (struct stream *, u_int16_t);
extern int stream_putw_at (struct stream *, size_t, u_int16_t);
+extern int stream_put3 (struct stream *, u_int32_t);
+extern int stream_put3_at (struct stream *, size_t, u_int32_t);
extern int stream_putl (struct stream *, u_int32_t);
extern int stream_putl_at (struct stream *, size_t, u_int32_t);
extern int stream_putq (struct stream *, uint64_t);
@@ -186,12 +188,20 @@ extern u_char stream_getc (struct stream *);
extern u_char stream_getc_from (struct stream *, size_t);
extern u_int16_t stream_getw (struct stream *);
extern u_int16_t stream_getw_from (struct stream *, size_t);
+extern u_int32_t stream_get3 (struct stream *);
+extern u_int32_t stream_get3_from (struct stream *, size_t);
extern u_int32_t stream_getl (struct stream *);
extern u_int32_t stream_getl_from (struct stream *, size_t);
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/thread.c b/lib/thread.c
index 8d75509b1d..a128786c3d 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -32,15 +32,6 @@
#include "command.h"
#include "sigevent.h"
-#if defined HAVE_SNMP && defined SNMP_AGENTX
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <net-snmp/agent/net-snmp-agent-includes.h>
-#include <net-snmp/agent/snmp_vars.h>
-
-extern int agentx_enabled;
-#endif
-
#if defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
@@ -48,12 +39,8 @@ extern int agentx_enabled;
/* Recent absolute time of day */
struct timeval recent_time;
-static struct timeval last_recent_time;
/* Relative time, since startup */
static struct timeval relative_time;
-static struct timeval relative_time_base;
-/* init flag */
-static unsigned short timers_inited;
static struct hash *cpu_record = NULL;
@@ -106,27 +93,6 @@ timeval_elapsed (struct timeval a, struct timeval b)
+ (a.tv_usec - b.tv_usec));
}
-#if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__)
-static void
-quagga_gettimeofday_relative_adjust (void)
-{
- struct timeval diff;
- if (timeval_cmp (recent_time, last_recent_time) < 0)
- {
- relative_time.tv_sec++;
- relative_time.tv_usec = 0;
- }
- else
- {
- diff = timeval_subtract (recent_time, last_recent_time);
- relative_time.tv_sec += diff.tv_sec;
- relative_time.tv_usec += diff.tv_usec;
- relative_time = timeval_adjust (relative_time);
- }
- last_recent_time = recent_time;
-}
-#endif /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
-
/* gettimeofday wrapper, to keep recent_time updated */
static int
quagga_gettimeofday (struct timeval *tv)
@@ -137,12 +103,6 @@ quagga_gettimeofday (struct timeval *tv)
if (!(ret = gettimeofday (&recent_time, NULL)))
{
- /* init... */
- if (!timers_inited)
- {
- relative_time_base = last_recent_time = recent_time;
- timers_inited = 1;
- }
/* avoid copy if user passed recent_time pointer.. */
if (tv != &recent_time)
*tv = recent_time;
@@ -182,8 +142,7 @@ quagga_get_relative (struct timeval *tv)
return 0;
}
#else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
- if (!(ret = quagga_gettimeofday (&recent_time)))
- quagga_gettimeofday_relative_adjust();
+#error no monotonic clock on this system
#endif /* HAVE_CLOCK_MONOTONIC */
if (tv)
@@ -192,18 +151,6 @@ quagga_get_relative (struct timeval *tv)
return ret;
}
-/* Get absolute time stamp, but in terms of the internal timer
- * Could be wrong, but at least won't go back.
- */
-static void
-quagga_real_stabilised (struct timeval *tv)
-{
- *tv = relative_time_base;
- tv->tv_sec += relative_time.tv_sec;
- tv->tv_usec += relative_time.tv_usec;
- *tv = timeval_adjust (*tv);
-}
-
/* Exported Quagga timestamp function.
* Modelled on POSIX clock_gettime.
*/
@@ -212,29 +159,19 @@ quagga_gettime (enum quagga_clkid clkid, struct timeval *tv)
{
switch (clkid)
{
- case QUAGGA_CLK_REALTIME:
- return quagga_gettimeofday (tv);
case QUAGGA_CLK_MONOTONIC:
return quagga_get_relative (tv);
- case QUAGGA_CLK_REALTIME_STABILISED:
- quagga_real_stabilised (tv);
- return 0;
default:
errno = EINVAL;
return -1;
}
}
-/* time_t value in terms of stabilised absolute time.
- * replacement for POSIX time()
- */
time_t
-quagga_time (time_t *t)
+quagga_monotime (void)
{
struct timeval tv;
- quagga_real_stabilised (&tv);
- if (t)
- *t = tv.tv_sec;
+ quagga_get_relative(&tv);
return tv.tv_sec;
}
@@ -983,6 +920,17 @@ funcname_thread_add_timer_msec (struct thread_master *m,
arg, &trel, debugargpass);
}
+/* Add timer event thread with "millisecond" resolution */
+struct thread *
+funcname_thread_add_timer_tv (struct thread_master *m,
+ int (*func) (struct thread *),
+ void *arg, struct timeval *tv,
+ debugargdef)
+{
+ return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,
+ arg, tv, debugargpass);
+}
+
/* Add a background thread, with an optional millisec delay */
struct thread *
funcname_thread_add_background (struct thread_master *m,
@@ -1343,12 +1291,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
while (1)
{
int num = 0;
-#if defined HAVE_SNMP && defined SNMP_AGENTX
- struct timeval snmp_timer_wait;
- int snmpblock = 0;
- int fdsetsize;
-#endif
-
+
/* Signals pre-empt everything */
quagga_sigevent_process ();
@@ -1384,35 +1327,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
(!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
timer_wait = timer_wait_bg;
}
-
-#if defined HAVE_SNMP && defined SNMP_AGENTX
- /* When SNMP is enabled, we may have to select() on additional
- FD. snmp_select_info() will add them to `readfd'. The trick
- with this function is its last argument. We need to set it to
- 0 if timer_wait is not NULL and we need to use the provided
- new timer only if it is still set to 0. */
- if (agentx_enabled)
- {
- fdsetsize = FD_SETSIZE;
- snmpblock = 1;
- if (timer_wait)
- {
- snmpblock = 0;
- memcpy(&snmp_timer_wait, timer_wait, sizeof(struct timeval));
- }
-#if defined(HAVE_POLL)
- /* clear fdset since there are no other fds in fd_set,
- then add injected fds from snmp_select_info into pollset */
- FD_ZERO(&readfd);
-#endif
- snmp_select_info(&fdsetsize, &readfd, &snmp_timer_wait, &snmpblock);
-#if defined(HAVE_POLL)
- add_snmp_pollfds(m, &readfd, fdsetsize);
-#endif
- if (snmpblock == 0)
- timer_wait = &snmp_timer_wait;
- }
-#endif
+
num = fd_select (m, FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
/* Signals should get quick treatment */
@@ -1424,30 +1339,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
return NULL;
}
-#if defined HAVE_SNMP && defined SNMP_AGENTX
-#if defined(HAVE_POLL)
- /* re-enter pollfds in fd_set for handling in snmp_read */
- FD_ZERO(&readfd);
- nfds_t i;
- for (i = m->handler.pfdcount; i < m->handler.pfdcountsnmp; ++i)
- {
- if (m->handler.pfds[i].revents == POLLIN)
- FD_SET(m->handler.pfds[i].fd, &readfd);
- }
-#endif
- if (agentx_enabled)
- {
- if (num > 0)
- snmp_read(&readfd);
- else if (num == 0)
- {
- snmp_timeout();
- run_alarms();
- }
- netsnmp_check_outstanding_agent_requests();
- }
-#endif
-
/* Check foreground timers. Historically, they have had higher
priority than I/O threads, so let's push them onto the ready
list in front of the I/O threads. */
diff --git a/lib/thread.h b/lib/thread.h
index 8b42ffe58a..c692142839 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -130,9 +130,7 @@ struct cpu_thread_history
/* Clocks supported by Quagga */
enum quagga_clkid {
- QUAGGA_CLK_REALTIME = 0, /* ala gettimeofday() */
- QUAGGA_CLK_MONOTONIC, /* monotonic, against an indeterminate base */
- QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */
+ QUAGGA_CLK_MONOTONIC = 1, /* monotonic, against an indeterminate base */
};
/* Struct timeval's tv_usec one second value. */
@@ -199,6 +197,7 @@ enum quagga_clkid {
#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__)
#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__)
#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__)
#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__)
#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
@@ -219,6 +218,10 @@ extern struct thread *funcname_thread_add_timer (struct thread_master *,
extern struct thread *funcname_thread_add_timer_msec (struct thread_master *,
int (*)(struct thread *),
void *, long, debugargdef);
+extern struct thread *funcname_thread_add_timer_tv (struct thread_master *,
+ int (*)(struct thread *),
+ void *, struct timeval *,
+ debugargdef);
extern struct thread *funcname_thread_add_event (struct thread_master *,
int (*)(struct thread *),
void *, int, debugargdef);
@@ -253,7 +256,7 @@ extern struct cmd_element clear_thread_cpu_cmd;
* all systems, and fully monotonic on /some/ systems.
*/
extern int quagga_gettime (enum quagga_clkid, struct timeval *);
-extern time_t quagga_time (time_t *);
+extern time_t quagga_monotime (void);
/* Returns elapsed real (wall clock) time. */
extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
diff --git a/lib/vty.h b/lib/vty.h
index 81251e07bb..599882a382 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -220,7 +220,7 @@ do { \
#define VTY_GET_INTEGER_RANGE(NAME,V,STR,MIN,MAX) \
do { \
- unsigned long tmpl; \
+ unsigned long long tmpl; \
VTY_GET_INTEGER_RANGE_HEART(NAME,tmpl,STR,MIN,MAX); \
(V) = tmpl; \
} while (0)
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_bfd.c b/ospf6d/ospf6_bfd.c
index 503c7e0cd7..f9bb6f0031 100644
--- a/ospf6d/ospf6_bfd.c
+++ b/ospf6d/ospf6_bfd.c
@@ -420,7 +420,4 @@ ospf6_bfd_init(void)
install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
-
- /* Send the client registration */
- bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
}
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_lsa.c b/ospf6d/ospf6_lsa.c
index 3f008d3d9f..35e5a91544 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -818,7 +818,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
DEFUN (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_cmd,
- "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
+ "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
@@ -862,7 +862,7 @@ DEFUN (debug_ospf6_lsa_type,
ALIAS (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_detail_cmd,
- "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)",
+ "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown) (originate|examine|flooding)",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
@@ -871,7 +871,7 @@ ALIAS (debug_ospf6_lsa_type,
DEFUN (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_cmd,
- "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
+ "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)",
NO_STR
DEBUG_STR
OSPF6_STR
@@ -915,7 +915,7 @@ DEFUN (no_debug_ospf6_lsa_type,
ALIAS (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_detail_cmd,
- "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)",
+ "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix) (originate|examine|flooding)",
NO_STR
DEBUG_STR
OSPF6_STR
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index c989a5a10a..a368b05304 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -321,7 +321,9 @@ main (int argc, char *argv[], char *envp[])
LOG_CONS|LOG_NDELAY|LOG_PID,
LOG_DAEMON);
zprivs_init (&ospf6d_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* initialize zebra libraries */
signal_init (master, array_size(ospf6_signals), ospf6_signals);
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 307d420ece..382cf62f72 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -29,6 +29,8 @@
#include "log.h"
#include "vty.h"
#include "linklist.h"
+#include "vector.h"
+#include "vrf.h"
#include "smux.h"
#include "ospf6_proto.h"
@@ -205,8 +207,8 @@
SNMP_LOCAL_VARIABLES
/* OSPFv3-MIB instances. */
-oid ospfv3_oid [] = { OSPFv3MIB };
-oid ospfv3_trap_oid [] = { OSPFv3MIB, 0 };
+static oid ospfv3_oid [] = { OSPFv3MIB };
+static oid ospfv3_trap_oid [] = { OSPFv3MIB, 0 };
/* Hook functions. */
static u_char *ospfv3GeneralGroup (struct variable *, oid *, size_t *,
@@ -220,7 +222,7 @@ static u_char *ospfv3NbrEntry (struct variable *, oid *, size_t *,
static u_char *ospfv3IfEntry (struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
-struct variable ospfv3_variables[] =
+static struct variable ospfv3_variables[] =
{
/* OSPF general variables */
{OSPFv3ROUTERID, UNSIGNED, RWRITE, ospfv3GeneralGroup,
@@ -623,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;
@@ -749,7 +751,7 @@ ospfv3WwLsdbEntry (struct variable *v, oid *name, size_t *length,
ifslist = list_new ();
if (!ifslist) return NULL;
ifslist->cmp = (int (*)(void *, void *))if_icmp_func;
- for (ALL_LIST_ELEMENTS_RO (iflist, node, iif))
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, iif))
listnode_add_sort (ifslist, iif);
for (ALL_LIST_ELEMENTS_RO (ifslist, node, iif))
@@ -835,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;
@@ -849,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;
@@ -887,7 +888,7 @@ ospfv3IfEntry (struct variable *v, oid *name, size_t *length,
ifslist = list_new ();
if (!ifslist) return NULL;
ifslist->cmp = (int (*)(void *, void *))if_icmp_func;
- for (ALL_LIST_ELEMENTS_RO (iflist, i, iif))
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif))
listnode_add_sort (ifslist, iif);
for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif))
@@ -988,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;
@@ -1001,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)
@@ -1047,7 +1049,7 @@ ospfv3NbrEntry (struct variable *v, oid *name, size_t *length,
ifslist = list_new ();
if (!ifslist) return NULL;
ifslist->cmp = (int (*)(void *, void *))if_icmp_func;
- for (ALL_LIST_ELEMENTS_RO (iflist, i, iif))
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif))
listnode_add_sort (ifslist, iif);
for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif))
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 93ec1f2ce0..77ea01e53d 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -28,6 +28,7 @@
#include "stream.h"
#include "zclient.h"
#include "memory.h"
+#include "lib/bfd.h"
#include "ospf6_proto.h"
#include "ospf6_top.h"
@@ -376,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;
@@ -442,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");
@@ -656,6 +657,9 @@ DEFUN (no_redistribute_ospf6,
static void
ospf6_zebra_connected (struct zclient *zclient)
{
+ /* Send the client registration */
+ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
zclient_send_reg_requests (zclient, VRF_DEFAULT);
}
diff --git a/ospfclient/.gitignore b/ospfclient/.gitignore
index 191322b6a1..a6000f8021 100644
--- a/ospfclient/.gitignore
+++ b/ospfclient/.gitignore
@@ -13,4 +13,4 @@ TAGS
.arch-ids
*~
*.loT
-
+refix
diff --git a/ospfclient/ospf_apiclient.h b/ospfclient/ospf_apiclient.h
index 0e74787ae0..809861995e 100644
--- a/ospfclient/ospf_apiclient.h
+++ b/ospfclient/ospf_apiclient.h
@@ -23,7 +23,7 @@
#ifndef _OSPF_APICLIENT_H
#define _OSPF_APICLIENT_H
-#define MTYPE_OSPF_APICLIENT 0
+#define MTYPE_OSPF_APICLIENT MTYPE_TMP
/* Structure for the OSPF API client */
struct ospf_apiclient
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_bfd.c b/ospfd/ospf_bfd.c
index ec486c4688..c87bcb0afb 100644
--- a/ospfd/ospf_bfd.c
+++ b/ospfd/ospf_bfd.c
@@ -452,7 +452,4 @@ ospf_bfd_init(void)
install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd);
install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
install_element (INTERFACE_NODE, &no_ip_ospf_bfd_param_cmd);
-
- /* Send the client registration */
- bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
}
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 861f9d3516..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",
@@ -2133,6 +2160,7 @@ config_write_debug (struct vty *vty)
struct ospf *ospf;
char str[16];
+ memset (str, 0, 16);
if ((ospf = ospf_lookup()) == NULL)
return CMD_SUCCESS;
@@ -2271,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);
@@ -2284,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);
@@ -2327,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);
@@ -2340,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 a062004ac4..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;
@@ -297,7 +295,7 @@ ospf_if_cleanup (struct ospf_interface *oi)
ospf_ls_upd_queue_empty (oi);
/* Reset pseudo neighbor. */
- ospf_nbr_self_reset (oi);
+ ospf_nbr_self_reset (oi, oi->ospf->router_id);
}
void
@@ -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));
@@ -926,7 +918,7 @@ ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data)
zlog_debug ("ospf_vl_new(): set associated area to the backbone");
/* Add pseudo neighbor. */
- ospf_nbr_self_reset (voi);
+ ospf_nbr_self_reset (voi, voi->ospf->router_id);
ospf_area_add_if (voi->area, voi);
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 ec0eab5f0a..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;
}
@@ -3731,7 +3701,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
*/
delay = (random() % (max_delay - min_delay)) + min_delay;
- current_index = ospf->lsa_refresh_queue.index + (quagga_time (NULL)
+ current_index = ospf->lsa_refresh_queue.index + (quagga_monotime ()
- ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
@@ -3795,7 +3765,7 @@ ospf_lsa_refresh_walker (struct thread *t)
modulus. */
ospf->lsa_refresh_queue.index =
((unsigned long)(ospf->lsa_refresh_queue.index +
- (quagga_time (NULL) - ospf->lsa_refresher_started)
+ (quagga_monotime () - ospf->lsa_refresher_started)
/ OSPF_LSA_REFRESHER_GRANULARITY))
% OSPF_LSA_REFRESHER_SLOTS;
@@ -3836,7 +3806,7 @@ ospf_lsa_refresh_walker (struct thread *t)
ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
ospf, ospf->lsa_refresh_interval);
- ospf->lsa_refresher_started = quagga_time (NULL);
+ ospf->lsa_refresher_started = quagga_monotime ();
for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa))
{
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 495ee2fd02..55ec2a306c 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -288,7 +288,9 @@ main (int argc, char **argv)
zlog_default = openzlog (progname, ZLOG_OSPF, instance,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
zprivs_init (&ospfd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* OSPF master init. */
ospf_master_init ();
@@ -323,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 16753b85df..a573936c18 100644
--- a/ospfd/ospf_neighbor.c
+++ b/ospfd/ospf_neighbor.c
@@ -238,18 +238,18 @@ ospf_nbr_bidirectional (struct in_addr *router_id,
/* reset nbr_self */
void
-ospf_nbr_self_reset (struct ospf_interface *oi)
+ospf_nbr_self_reset (struct ospf_interface *oi, struct in_addr router_id)
{
if (oi->nbr_self)
ospf_nbr_delete (oi->nbr_self);
oi->nbr_self = ospf_nbr_new (oi);
- ospf_nbr_add_self (oi);
+ ospf_nbr_add_self (oi, router_id);
}
/* Add self to nbr list. */
void
-ospf_nbr_add_self (struct ospf_interface *oi)
+ospf_nbr_add_self (struct ospf_interface *oi, struct in_addr router_id)
{
struct prefix p;
struct route_node *rn;
@@ -260,7 +260,7 @@ ospf_nbr_add_self (struct ospf_interface *oi)
/* Initial state */
oi->nbr_self->address = *oi->address;
oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
- oi->nbr_self->router_id = oi->ospf->router_id;
+ oi->nbr_self->router_id = router_id;
oi->nbr_self->src = oi->address->u.prefix4;
oi->nbr_self->state = NSM_TwoWay;
@@ -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 81e212b573..d62de44b5e 100644
--- a/ospfd/ospf_neighbor.h
+++ b/ospfd/ospf_neighbor.h
@@ -102,12 +102,10 @@ extern struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *);
extern void ospf_nbr_free (struct ospf_neighbor *);
extern void ospf_nbr_delete (struct ospf_neighbor *);
extern int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int);
-extern void ospf_nbr_self_reset (struct ospf_interface *);
-extern void ospf_nbr_add_self (struct ospf_interface *);
+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 23d1e3fc6c..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.
@@ -783,7 +773,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state)
if (state == NSM_ExStart)
{
if (nbr->dd_seqnum == 0)
- nbr->dd_seqnum = quagga_time (NULL);
+ nbr->dd_seqnum = (uint32_t)random ();
else
nbr->dd_seqnum++;
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 4c05c77252..9b395b3e8e 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -22,12 +22,11 @@
*/
/***** MTYPE definitions are not reflected to "memory.h" yet. *****/
-#define MTYPE_OSPF_OPAQUE_FUNCTAB 0
-#define MTYPE_OPAQUE_INFO_PER_TYPE 0
-#define MTYPE_OPAQUE_INFO_PER_ID 0
+#define MTYPE_OSPF_OPAQUE_FUNCTAB MTYPE_TMP
+#define MTYPE_OPAQUE_INFO_PER_TYPE MTYPE_TMP
+#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.c b/ospfd/ospf_route.c
index 7efba7a8c0..175850c318 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -47,8 +47,6 @@ ospf_route_new ()
new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
- new->ctime = quagga_time (NULL);
- new->mtime = new->ctime;
new->paths = list_new ();
new->paths->del = (void (*) (void *))ospf_path_free;
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index 4de3a3da16..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;
};
@@ -90,12 +90,6 @@ struct route_external
struct ospf_route
{
- /* Create time. */
- time_t ctime;
-
- /* Modified time. */
- time_t mtime;
-
/* Destination Type. */
u_char type;
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 1636153378..676756d6d9 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -209,8 +209,8 @@
SNMP_LOCAL_VARIABLES
/* OSPF-MIB instances. */
-oid ospf_oid [] = { OSPF2MIB };
-oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */
+static oid ospf_oid [] = { OSPF2MIB };
+static oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */
/* IP address 0.0.0.0. */
static struct in_addr ospf_empty_addr = { .s_addr = 0 };
@@ -243,7 +243,7 @@ static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int,
static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
-struct variable ospf_variables[] =
+static struct variable ospf_variables[] =
{
/* OSPF general variables */
{OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup,
@@ -1408,25 +1408,25 @@ ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
return NULL;
}
-struct list *ospf_snmp_iflist;
+static struct list *ospf_snmp_iflist;
struct ospf_snmp_if
{
struct in_addr addr;
- unsigned int ifindex;
+ ifindex_t ifindex;
struct interface *ifp;
};
static struct ospf_snmp_if *
ospf_snmp_if_new (void)
{
- return XCALLOC (0, sizeof (struct ospf_snmp_if));
+ return XCALLOC (MTYPE_TMP, sizeof (struct ospf_snmp_if));
}
static void
ospf_snmp_if_free (struct ospf_snmp_if *osif)
{
- XFREE (0, osif);
+ XFREE (MTYPE_TMP, osif);
}
void
@@ -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;
@@ -1912,7 +1912,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
return NULL;
}
-struct route_table *ospf_snmp_vl_table;
+static struct route_table *ospf_snmp_vl_table;
void
ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
@@ -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;
@@ -2618,7 +2618,7 @@ ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
#define NBRSTATECHANGE 2
#define VIRTNBRSTATECHANGE 3
-struct trap_object ospfNbrTrapList[] =
+static struct trap_object ospfNbrTrapList[] =
{
{-2, {1, OSPFROUTERID}},
{3, {10, 1, OSPFNBRIPADDR}},
@@ -2627,7 +2627,7 @@ struct trap_object ospfNbrTrapList[] =
};
-struct trap_object ospfVirtNbrTrapList[] =
+static struct trap_object ospfVirtNbrTrapList[] =
{
{-2, {1, 1}},
{3, {11, 1, OSPFVIRTNBRAREA}},
@@ -2635,7 +2635,7 @@ struct trap_object ospfVirtNbrTrapList[] =
{3, {11, 1, OSPFVIRTNBRSTATE}}
};
-struct trap_object ospfIfTrapList[] =
+static struct trap_object ospfIfTrapList[] =
{
{-2, {1, OSPFROUTERID}},
{3, {7, 1, OSPFIFIPADDRESS}},
@@ -2643,7 +2643,7 @@ struct trap_object ospfIfTrapList[] =
{3, {7, 1, OSPFIFSTATE}}
};
-struct trap_object ospfVirtIfTrapList[] =
+static struct trap_object ospfVirtIfTrapList[] =
{
{-2, {1, OSPFROUTERID}},
{3, {9, 1, OSPFVIRTIFAREAID}},
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index db06623ddf..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 0
+/* 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 beda0caa11..1b26c67866 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;
@@ -271,43 +271,10 @@ DEFUN (no_ospf_router_id,
struct ospf *ospf = vty->index;
struct listnode *node;
struct ospf_area *area;
- struct in_addr id;
- struct interface *ifp;
- struct connected *ifc;
- struct prefix *p;
- int ret;
if (!ospf)
return CMD_SUCCESS;
- if (argc == 1)
- {
- ret = inet_aton (argv[0], &id);
- if (! ret)
- {
- ifp = if_lookup_by_name(argv[0]);
- if (!ifp) {
- vty_out (vty, "%% Malformed OSPF router identifier%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
- {
- p = ifc->address;
- if (p && (p->family == AF_INET))
- {
- id = p->u.prefix4;
- break;
- }
- }
- }
-
- if (! IPV4_ADDR_SAME (&ospf->router_id_static, &id))
- {
- vty_out (vty, "%% OSPF router-id doesn't match%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
-
ospf->router_id_static.s_addr = 0;
for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
@@ -331,63 +298,6 @@ ALIAS (no_ospf_router_id,
"router-id for the OSPF process\n"
"OSPF router-id in IP address format\n")
-DEFUN (ospf_router_id_interface,
- ospf_router_id_interface_cmd,
- "ospf router-id IFNAME",
- "OSPF specific commands\n"
- "router-id for the OSPF process\n"
- "Interface name\n")
-{
- struct ospf *ospf = vty->index;
- struct listnode *node;
- struct ospf_area *area;
- struct interface *ifp;
- struct connected *ifc;
- struct prefix *p;
-
- if (!ospf)
- return CMD_SUCCESS;
-
- p = NULL;
- ifp = if_lookup_by_name(argv[0]);
- if (!ifp)
- {
- vty_out (vty, "%% Couldnt find interface %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
- {
- p = ifc->address;
-
- if (p && (p->family == AF_INET))
- {
- if (IPV4_ADDR_SAME (&ospf->router_id_static, &p->u.prefix4))
- return CMD_SUCCESS;
- ospf->router_id_static = p->u.prefix4;
- for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
- if (area->full_nbrs)
- {
- vty_out (vty, "For this router-id change to take effect,"
- " save config and restart ospfd%s", VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- ospf_router_id_update (ospf);
- return CMD_SUCCESS;
- }
- }
- vty_out (vty, "%% Couldnt assign the router-id%s", VTY_NEWLINE);
- return CMD_WARNING;
-}
-
-ALIAS (no_ospf_router_id,
- no_ospf_router_id_interface_cmd,
- "no ospf router-id IFNAME",
- NO_STR
- "OSPF specific commands\n"
- "router-id for the OSPF process\n"
- "Interface name\n")
-
static void
ospf_passive_interface_default (struct ospf *ospf, u_char newval)
{
@@ -3355,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));
@@ -3372,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);
@@ -3456,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))
@@ -3470,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
@@ -3624,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",
@@ -3638,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)
@@ -3967,7 +3871,13 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface
{
struct timeval result;
unsigned long time_store = 0;
- result = tv_sub (oi->t_hello->u.sands, recent_relative_time());
+ if (oi->t_hello)
+ result = tv_sub (oi->t_hello->u.sands, recent_relative_time());
+ else
+ {
+ result.tv_sec = 0;
+ result.tv_usec = 0;
+ }
time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000);
json_object_int_add(json_interface_sub, "timerHelloInMsecs", time_store);
}
@@ -4029,20 +3939,29 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc,
if (ospf_oi_count(ifp))
{
show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json);
+ if (use_json)
+ json_object_object_add (json, ifp->name, json_interface_sub);
}
}
}
else if (argv[iface_argv] && strcmp(argv[iface_argv], "json") == 0)
{
+ if (!use_json)
+ {
+ json = json_object_new_object();
+ json_interface_sub = json_object_new_object ();
+ use_json = 1;
+ }
/* Show All Interfaces. */
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
{
if (ospf_oi_count(ifp))
{
show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json);
- json_object_object_add(json, ifp->name, json_interface_sub);
- }
- }
+ if (use_json)
+ json_object_object_add(json, ifp->name, json_interface_sub);
+ }
+ }
}
else
{
@@ -5185,11 +5104,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;
}
@@ -5209,12 +5126,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[] =
@@ -5227,12 +5142,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
@@ -5504,7 +5417,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)
{
@@ -5517,7 +5429,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 *) =
{
@@ -5529,12 +5440,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
@@ -5593,9 +5502,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);
@@ -5642,9 +5549,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);
@@ -5680,9 +5585,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;
@@ -5709,9 +5612,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;
@@ -5763,17 +5664,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" \
@@ -5835,14 +5729,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;
@@ -6037,14 +5929,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;
@@ -9579,9 +9469,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;
@@ -10077,9 +9965,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;
@@ -10421,10 +10307,8 @@ ospf_vty_init (void)
/* "ospf router-id" commands. */
install_element (OSPF_NODE, &ospf_router_id_cmd);
install_element (OSPF_NODE, &ospf_router_id_old_cmd);
- install_element (OSPF_NODE, &ospf_router_id_interface_cmd);
install_element (OSPF_NODE, &no_ospf_router_id_cmd);
install_element (OSPF_NODE, &no_ospf_router_id_val_cmd);
- install_element (OSPF_NODE, &no_ospf_router_id_interface_cmd);
/* "passive-interface" commands. */
install_element (OSPF_NODE, &ospf_passive_interface_addr_cmd);
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 c7bf38eb68..c0b94a3360 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -34,6 +34,8 @@
#include "filter.h"
#include "plist.h"
#include "log.h"
+#include "lib/bfd.h"
+#include "nexthop.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@@ -51,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;
@@ -329,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)
{
@@ -392,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
@@ -413,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
@@ -513,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);
}
@@ -1558,6 +1579,9 @@ ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
static void
ospf_zebra_connected (struct zclient *zclient)
{
+ /* Send the client registration */
+ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
zclient_send_reg_requests (zclient, VRF_DEFAULT);
}
@@ -1575,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 ea66042f2e..7156c1edac 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -124,7 +124,7 @@ ospf_router_id_update (struct ospf *ospf)
* oi->nbr_self->router_id = router_id for
* !(virtual | ptop) links
*/
- ospf_nbr_self_reset (oi);
+ ospf_nbr_self_reset (oi, router_id);
}
/* If AS-external-LSA is queued, then flush those LSAs. */
@@ -272,7 +272,7 @@ ospf_new (u_short instance)
new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
new, new->lsa_refresh_interval);
- new->lsa_refresher_started = quagga_time (NULL);
+ new->lsa_refresher_started = quagga_monotime ();
if ((new->fd = ospf_sock_init()) < 0)
{
@@ -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;
@@ -888,7 +872,7 @@ add_ospf_interface (struct interface *ifp, struct ospf_area *area,
oi->type = IF_DEF_PARAMS (ifp)->type;
/* Add pseudo neighbor. */
- ospf_nbr_self_reset (oi);
+ ospf_nbr_self_reset (oi, oi->ospf->router_id);
ospf_area_add_if (oi->area, oi);
@@ -1160,7 +1144,7 @@ ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
oi->output_cost = ospf_if_get_output_cost (oi);
/* Add pseudo neighbor. */
- ospf_nbr_add_self (oi);
+ ospf_nbr_add_self (oi, oi->ospf->router_id);
/* Relate ospf interface to ospf instance. */
oi->ospf = area->ospf;
@@ -1598,7 +1582,7 @@ ospf_timers_refresh_set (struct ospf *ospf, int interval)
return 1;
time_left = ospf->lsa_refresh_interval -
- (quagga_time (NULL) - ospf->lsa_refresher_started);
+ (quagga_monotime () - ospf->lsa_refresher_started);
if (time_left > interval)
{
@@ -1617,7 +1601,7 @@ ospf_timers_refresh_unset (struct ospf *ospf)
int time_left;
time_left = ospf->lsa_refresh_interval -
- (quagga_time (NULL) - ospf->lsa_refresher_started);
+ (quagga_monotime () - ospf->lsa_refresher_started);
if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
{
@@ -1939,5 +1923,4 @@ ospf_master_init ()
om = &ospf_master;
om->ospf = list_new ();
om->master = thread_master_create ();
- om->start_time = quagga_time (NULL);
}
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 95809306d6..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
@@ -98,9 +99,6 @@ struct ospf_master
struct list *external[ZEBRA_ROUTE_MAX + 1];
#define EXTERNAL_INFO(E) (E->external_info)
- /* OSPF start time. */
- time_t start_time;
-
/* Various OSPF global configuration. */
u_char options;
#define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
@@ -165,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 */
@@ -212,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. */
@@ -243,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. */
@@ -368,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
@@ -412,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/Makefile.am b/pimd/Makefile.am
index 115d73678d..d578c97363 100644
--- a/pimd/Makefile.am
+++ b/pimd/Makefile.am
@@ -43,7 +43,7 @@ AM_CFLAGS = $(WERROR)
noinst_LIBRARIES = libpim.a
sbin_PROGRAMS = pimd
-bin_PROGRAMS = test_igmpv3_join
+noinst_PROGRAMS = test_igmpv3_join
libpim_a_SOURCES = \
pimd.c pim_version.c pim_cmd.c pim_signals.c pim_iface.c \
@@ -52,7 +52,7 @@ libpim_a_SOURCES = \
pim_oil.c pim_zlookup.c pim_pim.c pim_tlv.c pim_neighbor.c \
pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \
pim_msg.c pim_upstream.c pim_rpf.c pim_macro.c \
- pim_igmp_join.c pim_ssmpingd.c pim_int.c pim_rp.c \
+ pim_ssmpingd.c pim_int.c pim_rp.c \
pim_static.c pim_br.c pim_register.c pim_routemap.c
noinst_HEADERS = \
@@ -69,7 +69,7 @@ pimd_SOURCES = \
pim_main.c $(libpim_a_SOURCES)
test_igmpv3_join_SOURCES = \
- test_igmpv3_join.c pim_igmp_join.c
+ test_igmpv3_join.c
pimd_LDADD = ../lib/libzebra.la @LIBCAP@
test_igmpv3_join_LDADD = ../lib/libzebra.la
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index 9f9c9e66f0..d3df6a1102 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -258,9 +258,7 @@ int pim_assert_recv(struct interface *ifp,
/*
Parse assert group addr
*/
- offset = pim_parse_addr_group(ifp->name, src_addr,
- &msg_group_addr,
- curr, curr_size);
+ offset = pim_parse_addr_group (&msg_group_addr, curr, curr_size);
if (offset < 1) {
char src_str[100];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
@@ -275,9 +273,7 @@ int pim_assert_recv(struct interface *ifp,
/*
Parse assert source addr
*/
- offset = pim_parse_addr_ucast(ifp->name, src_addr,
- &msg_source_addr,
- curr, curr_size);
+ offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size);
if (offset < 1) {
char src_str[100];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 68446572eb..6cfed0f2c6 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -22,14 +22,13 @@
#include <zebra.h>
-#include <sys/ioctl.h>
-
#include "command.h"
#include "if.h"
#include "prefix.h"
#include "zclient.h"
#include "pimd.h"
+#include "pim_mroute.h"
#include "pim_cmd.h"
#include "pim_iface.h"
#include "pim_vty.h"
@@ -1599,7 +1598,7 @@ static void mroute_add_all()
struct channel_oil *c_oil;
for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
- if (pim_mroute_add(&c_oil->oil)) {
+ if (pim_mroute_add(c_oil)) {
/* just log warning */
char source_str[100];
char group_str[100];
@@ -1618,7 +1617,7 @@ static void mroute_del_all()
struct channel_oil *c_oil;
for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
- if (pim_mroute_del(&c_oil->oil)) {
+ if (pim_mroute_del(c_oil)) {
/* just log warning */
char source_str[100];
char group_str[100];
@@ -1637,12 +1636,12 @@ static void static_mroute_add_all()
struct static_route *s_route;
for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
- if (pim_mroute_add(&s_route->mc)) {
+ if (pim_mroute_add(&s_route->c_oil)) {
/* just log warning */
char source_str[100];
char group_str[100];
- pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
- pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
+ pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
__FILE__, __PRETTY_FUNCTION__,
source_str, group_str);
@@ -1656,12 +1655,12 @@ static void static_mroute_del_all()
struct static_route *s_route;
for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
- if (pim_mroute_del(&s_route->mc)) {
+ if (pim_mroute_del(&s_route->c_oil)) {
/* just log warning */
char source_str[100];
char group_str[100];
- pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
- pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
+ pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
__FILE__, __PRETTY_FUNCTION__,
source_str, group_str);
@@ -2088,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);
}
}
@@ -2189,6 +2188,9 @@ static void show_mroute(struct vty *vty)
char source_str[100];
int oif_vif_index;
+ if (!c_oil->installed)
+ continue;
+
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
@@ -2239,6 +2241,9 @@ static void show_mroute(struct vty *vty)
char source_str[100];
int oif_vif_index;
+ if (!s_route->c_oil.installed)
+ continue;
+
pim_inet4_dump("<group?>", s_route->group, group_str, sizeof(group_str));
pim_inet4_dump("<source?>", s_route->source, source_str, sizeof(source_str));
@@ -2256,7 +2261,7 @@ static void show_mroute(struct vty *vty)
ifp_in = pim_if_find_by_vif_index(s_route->iif);
ifp_out = pim_if_find_by_vif_index(oif_vif_index);
- pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->creation[oif_vif_index]);
+ pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]);
proto[0] = '\0';
strcat(proto, "S");
@@ -2302,34 +2307,21 @@ static void show_mroute_count(struct vty *vty)
for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
char group_str[100];
char source_str[100];
- struct sioc_sg_req sgreq;
- memset(&sgreq, 0, sizeof(sgreq));
- sgreq.src = c_oil->oil.mfcc_origin;
- sgreq.grp = c_oil->oil.mfcc_mcastgrp;
+ if (!c_oil->installed)
+ continue;
+
+ pim_mroute_update_counters (c_oil);
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
- int e = errno;
- vty_out(vty,
- "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s",
- (unsigned long)SIOCGETSGCNT,
- source_str,
- group_str,
- e,
- safe_strerror(e),
- VTY_NEWLINE);
- continue;
- }
-
vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
source_str,
group_str,
- sgreq.pktcnt,
- sgreq.bytecnt,
- sgreq.wrong_if,
+ c_oil->cc.pktcnt,
+ c_oil->cc.bytecnt,
+ c_oil->cc.wrong_if,
VTY_NEWLINE);
}
@@ -2337,37 +2329,21 @@ static void show_mroute_count(struct vty *vty)
for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
char group_str[100];
char source_str[100];
- struct sioc_sg_req sgreq;
- memset(&sgreq, 0, sizeof(sgreq));
- sgreq.src = s_route->mc.mfcc_origin;
- sgreq.grp = s_route->mc.mfcc_mcastgrp;
+ if (!s_route->c_oil.installed)
+ continue;
- pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
+ pim_mroute_update_counters (&s_route->c_oil);
- if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
- int e = errno;
- vty_out(vty,
- "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s",
- /* note that typeof ioctl defs can vary across platforms, from
- * int, to unsigned int, to long unsigned int
- */
- (unsigned long)SIOCGETSGCNT,
- source_str,
- group_str,
- e,
- safe_strerror(e),
- VTY_NEWLINE);
- continue;
- }
+ pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
source_str,
group_str,
- sgreq.pktcnt,
- sgreq.bytecnt,
- sgreq.wrong_if,
+ s_route->c_oil.cc.pktcnt,
+ s_route->c_oil.cc.bytecnt,
+ s_route->c_oil.cc.wrong_if,
VTY_NEWLINE);
}
}
@@ -2486,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;
@@ -2511,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 1dfbd9990a..a8a1d08805 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -632,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);
@@ -668,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;
@@ -767,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;
@@ -779,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;
}
@@ -790,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;
@@ -949,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 6df835e252..3b63b10e0d 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -46,10 +46,7 @@
static void group_timer_off(struct igmp_group *group);
-static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp,
- struct in_addr group_addr);
-
-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;
@@ -974,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);
@@ -1012,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;
@@ -1024,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
@@ -1358,8 +1355,9 @@ void igmp_group_timer_on(struct igmp_group *group,
group, interval_msec);
}
-static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp,
- struct in_addr group_addr)
+struct igmp_group *
+find_group_by_addr (struct igmp_sock *igmp,
+ struct in_addr group_addr)
{
struct igmp_group *group;
struct listnode *node;
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index ab396159e3..c6685c2837 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -162,6 +162,8 @@ struct igmp_group {
int64_t last_igmp_v2_report_dsec;
};
+struct igmp_group *find_group_by_addr (struct igmp_sock *igmp,
+ struct in_addr group_addr);
struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
struct in_addr group_addr);
diff --git a/pimd/pim_igmp_join.c b/pimd/pim_igmp_join.c
deleted file mode 100644
index 62e32c6014..0000000000
--- a/pimd/pim_igmp_join.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- PIM for Quagga
- Copyright (C) 2008 Everton da Silva Marques
-
- This program 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 of the License, or
- (at your option) any later version.
-
- This program 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 this program; see the file COPYING; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
-*/
-
-#include <zebra.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-
-#include "pim_igmp_join.h"
-
-#ifndef SOL_IP
-#define SOL_IP IPPROTO_IP
-#endif
-
-#ifndef MCAST_JOIN_SOURCE_GROUP
-#define MCAST_JOIN_SOURCE_GROUP 46
-struct group_source_req
-{
- uint32_t gsr_interface;
- struct sockaddr_storage gsr_group;
- struct sockaddr_storage gsr_source;
-};
-#endif
-
-int pim_igmp_join_source(int fd, int ifindex,
- struct in_addr group_addr,
- struct in_addr source_addr)
-{
- struct group_source_req req;
- struct sockaddr_in group;
- struct sockaddr_in source;
-
- memset(&group, 0, sizeof(group));
- group.sin_family = AF_INET;
- group.sin_addr = group_addr;
- group.sin_port = htons(0);
- memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in));
-
- memset(&source, 0, sizeof(source));
- source.sin_family = AF_INET;
- source.sin_addr = source_addr;
- source.sin_port = htons(0);
- memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in));
-
- req.gsr_interface = ifindex;
-
- return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP,
- &req, sizeof(req));
-
- return 0;
-}
diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h
index 1127af1202..1700276de8 100644
--- a/pimd/pim_igmp_join.h
+++ b/pimd/pim_igmp_join.h
@@ -23,10 +23,48 @@
#ifndef PIM_IGMP_JOIN_H
#define PIM_IGMP_JOIN_H
-#include <netinet/in.h>
+/* required headers #include'd by caller */
-int pim_igmp_join_source(int fd, int ifindex,
- struct in_addr group_addr,
- struct in_addr source_addr);
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+#ifndef MCAST_JOIN_SOURCE_GROUP
+#define MCAST_JOIN_SOURCE_GROUP 46
+struct group_source_req
+{
+ uint32_t gsr_interface;
+ struct sockaddr_storage gsr_group;
+ struct sockaddr_storage gsr_source;
+};
+#endif
+
+static int pim_igmp_join_source(int fd, ifindex_t ifindex,
+ struct in_addr group_addr,
+ struct in_addr source_addr)
+{
+ struct group_source_req req;
+ struct sockaddr_in group;
+ struct sockaddr_in source;
+
+ memset(&group, 0, sizeof(group));
+ group.sin_family = AF_INET;
+ group.sin_addr = group_addr;
+ group.sin_port = htons(0);
+ memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in));
+
+ memset(&source, 0, sizeof(source));
+ source.sin_family = AF_INET;
+ source.sin_addr = source_addr;
+ source.sin_port = htons(0);
+ memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in));
+
+ req.gsr_interface = ifindex;
+
+ return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP,
+ &req, sizeof(req));
+
+ return 0;
+}
#endif /* PIM_IGMP_JOIN_H */
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index 0a6b6b3795..7300e6c6b4 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -834,11 +834,26 @@ void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from,
on_trace(__PRETTY_FUNCTION__,
ifp, from, group_addr, num_sources, sources);
- /* non-existant group is created as INCLUDE {empty} */
- group = igmp_add_group_by_addr(igmp, group_addr);
- if (!group) {
- return;
- }
+ /*
+ * If the requested filter mode is INCLUDE *and* the requested source
+ * list is empty, then the entry corresponding to the requested
+ * interface and multicast address is deleted if present. If no such
+ * entry is present, the request is ignored.
+ */
+ if (num_sources)
+ {
+ /* non-existant group is created as INCLUDE {empty} */
+ group = igmp_add_group_by_addr(igmp, group_addr);
+ if (!group) {
+ return;
+ }
+ }
+ else
+ {
+ group = find_group_by_addr (igmp, group_addr);
+ if (!group)
+ return;
+ }
if (group->group_filtermode_isexcl) {
/* EXCLUDE mode */
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index f3b5e78ada..3852b423f0 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -127,14 +127,8 @@ int pim_joinprune_recv(struct interface *ifp,
/*
Parse ucast addr
*/
- addr_offset = pim_parse_addr_ucast(ifp->name, src_addr,
- &msg_upstream_addr,
- buf, pastend - buf);
-#if 0
- zlog_warn("%s: pim_parse_addr_ucast addr_offset=%d",
- __PRETTY_FUNCTION__,
- addr_offset);
-#endif
+ addr_offset = pim_parse_addr_ucast (&msg_upstream_addr,
+ buf, pastend - buf);
if (addr_offset < 1) {
char src_str[100];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
@@ -197,14 +191,8 @@ int pim_joinprune_recv(struct interface *ifp,
uint16_t msg_num_pruned_sources;
int source;
- addr_offset = pim_parse_addr_group(ifp->name, src_addr,
- &msg_group_addr,
- buf, pastend - buf);
-#if 0
- zlog_warn("%s: pim_parse_addr_group addr_offset=%d",
- __PRETTY_FUNCTION__,
- addr_offset);
-#endif
+ addr_offset = pim_parse_addr_group (&msg_group_addr,
+ buf, pastend - buf);
if (addr_offset < 1) {
return -5;
}
@@ -243,15 +231,9 @@ int pim_joinprune_recv(struct interface *ifp,
/* Scan joined sources */
for (source = 0; source < msg_num_joined_sources; ++source) {
- addr_offset = pim_parse_addr_source(ifp->name, src_addr,
- &msg_source_addr,
- &msg_source_flags,
- buf, pastend - buf);
-#if 0
- zlog_warn("%s: pim_parse_addr_source addr_offset=%d",
- __PRETTY_FUNCTION__,
- addr_offset);
-#endif
+ addr_offset = pim_parse_addr_source (&msg_source_addr,
+ &msg_source_flags,
+ buf, pastend - buf);
if (addr_offset < 1) {
return -7;
}
@@ -267,10 +249,9 @@ int pim_joinprune_recv(struct interface *ifp,
/* Scan pruned sources */
for (source = 0; source < msg_num_pruned_sources; ++source) {
- addr_offset = pim_parse_addr_source(ifp->name, src_addr,
- &msg_source_addr,
- &msg_source_flags,
- buf, pastend - buf);
+ addr_offset = pim_parse_addr_source (&msg_source_addr,
+ &msg_source_flags,
+ buf, pastend - buf);
if (addr_offset < 1) {
return -8;
}
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index b28b3d6242..b65b925fad 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -138,7 +138,9 @@ int main(int argc, char** argv, char** envp) {
zlog_default = openzlog(progname, ZLOG_PIM, 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
zprivs_init (&pimd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* this while just reads the options */
while (1) {
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 8048d4b3c7..56f49d62f5 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -143,6 +143,8 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
return 0;
}
+ pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD);
+
up->channel_oil = pim_channel_oil_add(msg->im_dst,
msg->im_src,
pim_ifp->mroute_vif_index);
@@ -154,6 +156,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
}
return 0;
}
+ up->channel_oil->cc.pktcnt++;
pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_SOURCE);
@@ -312,7 +315,6 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, sizeof(grp_str));
zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d",
__PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size);
- //zlog_hexdump(buf, buf_size);
}
return 0;
}
@@ -344,7 +346,6 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
return pim_mroute_msg_nocache(fd, ifp, msg, src_str, grp_str);
break;
case IGMPMSG_WHOLEPKT:
- zlog_hexdump(buf, buf_size);
return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg, src_str, grp_str);
break;
default:
@@ -500,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;
@@ -557,7 +567,7 @@ int pim_mroute_del_vif(int vif_index)
return 0;
}
-int pim_mroute_add(struct mfcctl *mc)
+int pim_mroute_add(struct channel_oil *c_oil)
{
int err;
int orig = 0;
@@ -575,17 +585,17 @@ int pim_mroute_add(struct mfcctl *mc)
* vif to be part of the outgoing list
* in the case of a (*,G).
*/
- if (mc->mfcc_origin.s_addr == INADDR_ANY)
+ if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
{
- orig = mc->mfcc_ttls[mc->mfcc_parent];
- mc->mfcc_ttls[mc->mfcc_parent] = 1;
+ orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent];
+ c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1;
}
err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC,
- mc, sizeof(*mc));
+ &c_oil->oil, sizeof(c_oil->oil));
- if (mc->mfcc_origin.s_addr == INADDR_ANY)
- mc->mfcc_ttls[mc->mfcc_parent] = orig;
+ if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
+ c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig;
if (err) {
int e = errno;
@@ -597,10 +607,11 @@ int pim_mroute_add(struct mfcctl *mc)
return -2;
}
+ c_oil->installed = 1;
return 0;
}
-int pim_mroute_del(struct mfcctl *mc)
+int pim_mroute_del (struct channel_oil *c_oil)
{
int err;
@@ -613,7 +624,7 @@ int pim_mroute_del(struct mfcctl *mc)
return -1;
}
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, mc, sizeof(*mc));
+ err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil));
if (err) {
int e = errno;
zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s",
@@ -624,5 +635,44 @@ int pim_mroute_del(struct mfcctl *mc)
return -2;
}
+ c_oil->installed = 0;
+
return 0;
}
+
+void
+pim_mroute_update_counters (struct channel_oil *c_oil)
+{
+ struct sioc_sg_req sgreq;
+
+ memset (&sgreq, 0, sizeof(sgreq));
+ sgreq.src = c_oil->oil.mfcc_origin;
+ sgreq.grp = c_oil->oil.mfcc_mcastgrp;
+
+ c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
+ c_oil->cc.oldbytecnt = c_oil->cc.bytecnt;
+ c_oil->cc.oldwrong_if = c_oil->cc.wrong_if;
+
+ if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq))
+ {
+ char group_str[100];
+ char source_str[100];
+
+ pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+
+ zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s",
+ (unsigned long)SIOCGETSGCNT,
+ source_str,
+ group_str,
+ errno,
+ safe_strerror(errno));
+ return;
+ }
+
+ c_oil->cc.pktcnt = sgreq.pktcnt;
+ c_oil->cc.bytecnt = sgreq.bytecnt;
+ c_oil->cc.wrong_if = sgreq.wrong_if;
+
+ return;
+}
diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h
index c1ce012e2d..176fb81cbc 100644
--- a/pimd/pim_mroute.h
+++ b/pimd/pim_mroute.h
@@ -169,9 +169,10 @@ int pim_mroute_socket_disable(void);
int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags);
int pim_mroute_del_vif(int vif_index);
-int pim_mroute_add(struct mfcctl *mc);
-int pim_mroute_del(struct mfcctl *mc);
+int pim_mroute_add(struct channel_oil *c_oil);
+int pim_mroute_del(struct channel_oil *c_oil);
int pim_mroute_msg(int fd, const char *buf, int buf_size);
+void pim_mroute_update_counters (struct channel_oil *c_oil);
#endif /* PIM_MROUTE_H */
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 8755818c0f..96f9ef2b62 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -79,6 +79,7 @@ static struct channel_oil *channel_oil_new(struct in_addr group_addr,
c_oil->oil.mfcc_origin = source_addr;
c_oil->oil.mfcc_parent = input_vif_index;
c_oil->oil_ref_count = 1;
+ c_oil->installed = 0;
zassert(c_oil->oil_size == 0);
@@ -253,7 +254,7 @@ int pim_channel_add_oif(struct channel_oil *channel_oil,
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL;
- if (pim_mroute_add(&channel_oil->oil)) {
+ if (pim_mroute_add(channel_oil)) {
if (PIM_DEBUG_MROUTE)
{
char group_str[100];
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index f0a14a9baa..c63c026c0f 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -50,6 +50,17 @@
#define PIM_OIF_PIM_REGISTER_VIF (MAXVIFS - 1)
#define PIM_MAX_USABLE_VIFS (MAXVIFS - 2)
+
+struct channel_counts
+{
+ unsigned long pktcnt;
+ unsigned long oldpktcnt;
+ unsigned long bytecnt;
+ unsigned long oldbytecnt;
+ unsigned long wrong_if;
+ unsigned long oldwrong_if;
+};
+
/*
qpim_channel_oil_list holds a list of struct channel_oil.
@@ -59,10 +70,12 @@
struct channel_oil {
struct mfcctl oil;
+ int installed;
int oil_size;
int oil_ref_count;
time_t oif_creation[MAXVIFS];
uint32_t oif_flags[MAXVIFS];
+ struct channel_counts cc;
};
void pim_channel_oil_free(struct channel_oil *c_oil);
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_register.h b/pimd/pim_register.h
index 7f3cdea3a2..039c0006e0 100644
--- a/pimd/pim_register.h
+++ b/pimd/pim_register.h
@@ -29,6 +29,7 @@
#define PIM_REGISTER_NR_BIT 0x40000000
#define PIM_MSG_REGISTER_LEN (8)
+#define PIM_MSG_REGISTER_STOP_LEN (4)
void pim_register_send_test_packet_start (struct in_addr source,
struct in_addr group,
diff --git a/pimd/pim_routemap.c b/pimd/pim_routemap.c
index ced7c87484..adfd4fd2c3 100644
--- a/pimd/pim_routemap.c
+++ b/pimd/pim_routemap.c
@@ -26,9 +26,56 @@
#include "pimd.h"
+
+static void
+pim_route_map_mark_update (const char *rmap_name)
+{
+ // placeholder
+ return;
+}
+
+static void
+pim_route_map_add (const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 0) == 0)
+ pim_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
+}
+
+static void
+pim_route_map_delete (const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 1) == 0)
+ pim_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
+}
+
+static void
+pim_route_map_event (route_map_event_t event, const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 0) == 0)
+ pim_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
+}
+
void
pim_route_map_init (void)
{
route_map_init ();
route_map_init_vty ();
+ route_map_add_hook (pim_route_map_add);
+ route_map_delete_hook (pim_route_map_delete);
+ route_map_event_hook (pim_route_map_event);
+}
+
+void
+pim_route_map_terminate (void)
+{
+ route_map_add_hook (NULL);
+ route_map_delete_hook (NULL);
+ route_map_event_hook (NULL);
+ route_map_finish();
}
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 47a34daf48..c1154dc088 100644
--- a/pimd/pim_static.c
+++ b/pimd/pim_static.c
@@ -24,15 +24,16 @@
#include "vty.h"
#include "if.h"
+#include "log.h"
+#include "memory.h"
+#include "linklist.h"
+#include "pimd.h"
+#include "pim_oil.h"
#include "pim_static.h"
#include "pim_time.h"
#include "pim_str.h"
-#include "pimd.h"
#include "pim_iface.h"
-#include "log.h"
-#include "memory.h"
-#include "linklist.h"
void pim_static_route_free(struct static_route *s_route)
{
@@ -66,12 +67,12 @@ static struct static_route *static_route_new(unsigned int iif,
s_route->source = source;
s_route->iif = iif;
s_route->oif_ttls[oif] = 1;
- s_route->oif_count = 1;
- s_route->mc.mfcc_origin = source;
- s_route->mc.mfcc_mcastgrp = group;
- s_route->mc.mfcc_parent = iif;
- s_route->mc.mfcc_ttls[oif] = 1;
- s_route->creation[oif] = pim_time_monotonic_sec();
+ s_route->c_oil.oil_ref_count = 1;
+ s_route->c_oil.oil.mfcc_origin = source;
+ s_route->c_oil.oil.mfcc_mcastgrp = group;
+ s_route->c_oil.oil.mfcc_parent = iif;
+ s_route->c_oil.oil.mfcc_ttls[oif] = 1;
+ s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec();
return s_route;
}
@@ -84,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)",
@@ -138,30 +139,30 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr
/* Route exists and has the same input interface, but adding a new output interface */
if (s_route->iif == iif_index) {
s_route->oif_ttls[oif_index] = 1;
- s_route->mc.mfcc_ttls[oif_index] = 1;
- s_route->creation[oif_index] = pim_time_monotonic_sec();
- ++s_route->oif_count;
+ s_route->c_oil.oil.mfcc_ttls[oif_index] = 1;
+ s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec();
+ ++s_route->c_oil.oil_ref_count;
} else {
/* input interface changed */
s_route->iif = iif_index;
- s_route->mc.mfcc_parent = iif_index;
+ s_route->c_oil.oil.mfcc_parent = iif_index;
#ifdef PIM_ENFORCE_LOOPFREE_MFC
/* check to make sure the new input was not an old output */
if (s_route->oif_ttls[iif_index]) {
s_route->oif_ttls[iif_index] = 0;
- s_route->creation[iif_index] = 0;
- s_route->mc.mfcc_ttls[iif_index] = 0;
- --s_route->oif_count;
+ s_route->c_oil.oif_creation[iif_index] = 0;
+ s_route->c_oil.oil.mfcc_ttls[iif_index] = 0;
+ --s_route->c_oil.oil_ref_count;
}
#endif
/* now add the new output, if it is new */
if (!s_route->oif_ttls[oif_index]) {
s_route->oif_ttls[oif_index] = 1;
- s_route->creation[oif_index] = pim_time_monotonic_sec();
- s_route->mc.mfcc_ttls[oif_index] = 1;
- ++s_route->oif_count;
+ s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec();
+ s_route->c_oil.oil.mfcc_ttls[oif_index] = 1;
+ ++s_route->c_oil.oil_ref_count;
}
}
@@ -175,7 +176,7 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr
listnode_add(qpim_static_route_list, s_route);
}
- if (pim_mroute_add(&(s_route->mc)))
+ if (pim_mroute_add(&s_route->c_oil))
{
char gifaddr_str[100];
char sifaddr_str[100];
@@ -228,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)",
@@ -245,11 +246,12 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr
s_route->source.s_addr == source.s_addr &&
s_route->oif_ttls[oif_index]) {
s_route->oif_ttls[oif_index] = 0;
- s_route->mc.mfcc_ttls[oif_index] = 0;
- --s_route->oif_count;
+ s_route->c_oil.oil.mfcc_ttls[oif_index] = 0;
+ --s_route->c_oil.oil_ref_count;
/* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */
- if (s_route->oif_count <= 0 ? pim_mroute_del(&s_route->mc) : pim_mroute_add(&s_route->mc)) {
+ if (s_route->c_oil.oil_ref_count <= 0 ?
+ pim_mroute_del(&s_route->c_oil) : pim_mroute_add(&s_route->c_oil)) {
char gifaddr_str[100];
char sifaddr_str[100];
pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str));
@@ -262,15 +264,15 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr
sifaddr_str);
s_route->oif_ttls[oif_index] = 1;
- s_route->mc.mfcc_ttls[oif_index] = 1;
- ++s_route->oif_count;
+ s_route->c_oil.oil.mfcc_ttls[oif_index] = 1;
+ ++s_route->c_oil.oil_ref_count;
return -1;
}
- s_route->creation[oif_index] = 0;
+ s_route->c_oil.oif_creation[oif_index] = 0;
- if (s_route->oif_count <= 0) {
+ if (s_route->c_oil.oil_ref_count <= 0) {
listnode_delete(qpim_static_route_list, s_route);
pim_static_route_free(s_route);
}
diff --git a/pimd/pim_static.h b/pimd/pim_static.h
index b3be09e913..07d31d59b7 100644
--- a/pimd/pim_static.h
+++ b/pimd/pim_static.h
@@ -32,11 +32,9 @@ struct static_route {
struct in_addr group;
struct in_addr source;
- unsigned int iif;
+ struct channel_oil c_oil;
+ ifindex_t iif;
unsigned char oif_ttls[MAXVIFS];
- int oif_count;
- struct mfcctl mc;
- time_t creation[MAXVIFS];
};
void pim_static_route_free(struct static_route *s_route);
diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c
index 0c768be122..38f6de9fea 100644
--- a/pimd/pim_tlv.c
+++ b/pimd/pim_tlv.c
@@ -97,6 +97,25 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,
#define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
+static int
+pim_encode_unicast_address (uint8_t *buf, struct prefix *p)
+{
+ switch (p->family)
+ {
+ case AF_INET:
+ *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
+ ++buf;
+ *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
+ ++buf;
+ memcpy (buf, &p->u.prefix4, sizeof (struct in_addr));
+ return ucast_ipv4_encoding_len;
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
const uint8_t *buf_pastend,
struct list *ifconnected)
@@ -121,22 +140,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
for (; node; node = listnextnode(node)) {
struct connected *ifc = listgetdata(node);
struct prefix *p = ifc->address;
-
- if (p->family != AF_INET)
- continue;
+ int l_encode;
if ((curr + ucast_ipv4_encoding_len) > buf_pastend)
return 0;
- /* Write encoded unicast IPv4 address */
- *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
- ++curr;
- *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
- ++curr;
- memcpy(curr, &p->u.prefix4, sizeof(struct in_addr));
- curr += sizeof(struct in_addr);
-
- option_len += ucast_ipv4_encoding_len;
+ l_encode = pim_encode_unicast_address (curr, p);
+ curr += l_encode;
+ option_len += l_encode;
}
if (PIM_DEBUG_PIM_TRACE_DETAIL) {
@@ -340,10 +351,10 @@ int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
return 0;
}
-int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
- struct prefix *p,
- const uint8_t *buf,
- int buf_size)
+int
+pim_parse_addr_ucast (struct prefix *p,
+ const uint8_t *buf,
+ int buf_size)
{
const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
const uint8_t *addr;
@@ -352,12 +363,9 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
int type;
if (buf_size < ucast_encoding_min_len) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d from %s on %s",
+ zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d",
__PRETTY_FUNCTION__,
- buf_size, ucast_encoding_min_len,
- src_str, ifname);
+ buf_size, ucast_encoding_min_len);
return -1;
}
@@ -367,24 +375,19 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
family = *addr++;
type = *addr++;
+ if (type) {
+ zlog_warn("%s: unknown unicast address encoding type=%d",
+ __PRETTY_FUNCTION__,
+ type);
+ return -2;
+ }
+
switch (family) {
case PIM_MSG_ADDRESS_FAMILY_IPV4:
- if (type) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s",
- __PRETTY_FUNCTION__,
- type, src_str, ifname);
- return -2;
- }
-
if ((addr + sizeof(struct in_addr)) > pastend) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu from %s on %s",
+ zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu",
__PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr),
- src_str, ifname);
+ pastend - addr, sizeof(struct in_addr));
return -3;
}
@@ -396,11 +399,9 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
break;
default:
{
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s",
+ zlog_warn("%s: unknown unicast address encoding family=%d from",
__PRETTY_FUNCTION__,
- family, src_str, ifname);
+ family);
return -4;
}
}
@@ -408,10 +409,10 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
return addr - buf;
}
-int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
- struct prefix *p,
- const uint8_t *buf,
- int buf_size)
+int
+pim_parse_addr_group (struct prefix *p,
+ const uint8_t *buf,
+ int buf_size)
{
const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
const uint8_t *addr;
@@ -421,12 +422,9 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
int mask_len;
if (buf_size < grp_encoding_min_len) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s",
+ zlog_warn("%s: group address encoding overflow: left=%d needed=%d",
__PRETTY_FUNCTION__,
- buf_size, grp_encoding_min_len,
- src_str, ifname);
+ buf_size, grp_encoding_min_len);
return -1;
}
@@ -442,21 +440,15 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
switch (family) {
case PIM_MSG_ADDRESS_FAMILY_IPV4:
if (type) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown group address encoding type=%d from %s on %s",
- __PRETTY_FUNCTION__,
- type, src_str, ifname);
+ zlog_warn("%s: unknown group address encoding type=%d from",
+ __PRETTY_FUNCTION__, type);
return -2;
}
if ((addr + sizeof(struct in_addr)) > pastend) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from %s on %s",
+ zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from",
__PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr),
- src_str, ifname);
+ pastend - addr, sizeof(struct in_addr));
return -3;
}
@@ -469,11 +461,8 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
break;
default:
{
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown group address encoding family=%d from %s on %s",
- __PRETTY_FUNCTION__,
- family, src_str, ifname);
+ zlog_warn("%s: unknown group address encoding family=%d from",
+ __PRETTY_FUNCTION__, family);
return -4;
}
}
@@ -481,12 +470,11 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
return addr - buf;
}
-int pim_parse_addr_source(const char *ifname,
- struct in_addr src_addr,
- struct prefix *p,
- uint8_t *flags,
- const uint8_t *buf,
- int buf_size)
+int
+pim_parse_addr_source(struct prefix *p,
+ uint8_t *flags,
+ const uint8_t *buf,
+ int buf_size)
{
const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
const uint8_t *addr;
@@ -496,12 +484,9 @@ int pim_parse_addr_source(const char *ifname,
int mask_len;
if (buf_size < src_encoding_min_len) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s",
+ zlog_warn("%s: source address encoding overflow: left=%d needed=%d",
__PRETTY_FUNCTION__,
- buf_size, src_encoding_min_len,
- src_str, ifname);
+ buf_size, src_encoding_min_len);
return -1;
}
@@ -513,25 +498,20 @@ int pim_parse_addr_source(const char *ifname,
*flags = *addr++;
mask_len = *addr++;
+ if (type) {
+ zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
+ __PRETTY_FUNCTION__,
+ type,
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+ return -2;
+ }
+
switch (family) {
case PIM_MSG_ADDRESS_FAMILY_IPV4:
- if (type) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown source address encoding type=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
- __PRETTY_FUNCTION__,
- type, src_str, ifname,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
- return -2;
- }
-
if ((addr + sizeof(struct in_addr)) > pastend) {
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu from %s on %s",
+ zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu",
__PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr),
- src_str, ifname);
+ pastend - addr, sizeof(struct in_addr));
return -3;
}
@@ -550,10 +530,8 @@ int pim_parse_addr_source(const char *ifname,
received with any other mask length.
*/
if (p->prefixlen != 32) {
- char src_str[100];
- pim_inet4_dump("<src?>", p->u.prefix4, src_str, sizeof(src_str));
- zlog_warn("%s: IPv4 bad source address mask: %s/%d",
- __PRETTY_FUNCTION__, src_str, p->prefixlen);
+ zlog_warn("%s: IPv4 bad source address mask: %d",
+ __PRETTY_FUNCTION__, p->prefixlen);
return -4;
}
@@ -562,11 +540,9 @@ int pim_parse_addr_source(const char *ifname,
break;
default:
{
- char src_str[100];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: unknown source address encoding family=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
+ zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
__PRETTY_FUNCTION__,
- family, src_str, ifname,
+ family,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
return -5;
}
@@ -606,8 +582,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
/*
Parse ucast addr
*/
- addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp,
- addr, pastend - addr);
+ addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr);
if (addr_offset < 1) {
char src_str[100];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h
index b802cf8977..59d49954e7 100644
--- a/pimd/pim_tlv.h
+++ b/pimd/pim_tlv.h
@@ -115,17 +115,13 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
uint16_t option_len,
const uint8_t *tlv_curr);
-int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
- struct prefix *p,
- const uint8_t *buf,
- int buf_size);
-int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
- struct prefix *p,
- const uint8_t *buf,
- int buf_size);
-int pim_parse_addr_source(const char *ifname,
- struct in_addr src_addr,
- struct prefix *p,
+int pim_parse_addr_ucast (struct prefix *p,
+ const uint8_t *buf,
+ int buf_size);
+int pim_parse_addr_group (struct prefix *p,
+ const uint8_t *buf,
+ int buf_size);
+int pim_parse_addr_source(struct prefix *p,
uint8_t *flags,
const uint8_t *buf,
int buf_size);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index cb2619abb7..8267885756 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -59,7 +59,7 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
{
if (up->channel_oil) {
pim_channel_oil_del(up->channel_oil);
- up->channel_oil = 0;
+ up->channel_oil = NULL;
}
}
@@ -715,12 +715,29 @@ pim_upstream_keep_alive_timer (struct thread *t)
up = THREAD_ARG(t);
- pim_br_clear_pmbr (up->source_addr, up->group_addr);
- /*
- * We need to do more here :)
- * But this is the start.
- */
+ if (I_am_RP (up->group_addr))
+ {
+ pim_br_clear_pmbr (up->source_addr, up->group_addr);
+ /*
+ * We need to do more here :)
+ * But this is the start.
+ */
+ }
+ else
+ {
+ pim_mroute_update_counters (up->channel_oil);
+ if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt)
+ {
+ pim_mroute_del (up->channel_oil);
+ pim_upstream_delete (up);
+ }
+ else
+ {
+ up->t_ka_timer = NULL;
+ pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD);
+ }
+ }
return 1;
}
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index beb0622a3f..f1c8930856 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -33,6 +33,7 @@
#include "pim_str.h"
#include "pim_ssmpingd.h"
#include "pim_pim.h"
+#include "pim_oil.h"
#include "pim_static.h"
int pim_debug_config_write(struct vty *vty)
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index b19b3941b1..d357e5cc83 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -387,18 +387,27 @@ static void scan_upstream_rpf_cache()
void
pim_scan_individual_oil (struct channel_oil *c_oil)
{
+ struct in_addr vif_source;
+ int input_iface_vif_index;
int old_vif_index;
- int input_iface_vif_index = fib_lookup_if_vif_index(c_oil->oil.mfcc_origin);
+ if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin))
+ return;
+
+ input_iface_vif_index = fib_lookup_if_vif_index (vif_source);
if (input_iface_vif_index < 1)
{
- char source_str[100];
- char group_str[100];
- pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- zlog_warn("%s %s: could not find input interface for (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str);
+ if (PIM_DEBUG_ZEBRA)
+ {
+ char source_str[100];
+ char group_str[100];
+ pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent,
+ source_str, group_str);
+ }
+ pim_mroute_del (c_oil);
return;
}
@@ -448,7 +457,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil)
zlog_debug ("FF");
/* update kernel multicast forwarding cache (MFC) */
- if (pim_mroute_add(&c_oil->oil))
+ if (pim_mroute_add(c_oil))
{
/* just log warning */
struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index);
@@ -524,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;
@@ -611,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])),
@@ -629,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])),
@@ -754,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,
@@ -900,7 +909,7 @@ static int del_oif(struct channel_oil *channel_oil,
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
- if (pim_mroute_add(&channel_oil->oil)) {
+ if (pim_mroute_add(channel_oil)) {
char group_str[100];
char source_str[100];
pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
@@ -917,7 +926,7 @@ static int del_oif(struct channel_oil *channel_oil,
--channel_oil->oil_size;
if (channel_oil->oil_size < 1) {
- if (pim_mroute_del(&channel_oil->oil)) {
+ if (pim_mroute_del(channel_oil)) {
/* just log a warning in case of failure */
char group_str[100];
char source_str[100];
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/pimd.c b/pimd/pimd.c
index 5b6824da58..91d8d56afc 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -87,6 +87,8 @@ static void pim_free()
if (qpim_static_route_list)
list_free(qpim_static_route_list);
+
+ pim_route_map_terminate();
}
void pim_init()
diff --git a/pimd/pimd.h b/pimd/pimd.h
index c5fec76675..6d48d83621 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -25,7 +25,6 @@
#include <stdint.h>
-#include "pim_mroute.h"
#include "pim_assert.h"
#define PIMD_PROGNAME "pimd"
@@ -178,5 +177,6 @@ void pim_init(void);
void pim_terminate(void);
extern void pim_route_map_init (void);
+extern void pim_route_map_terminate(void);
#endif /* PIMD_H */
diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c
index 6f1e34de88..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,16 +32,15 @@
#include <net/if.h>
#include <arpa/inet.h>
-#include "thread.h"
+#include "if.h"
#include "pim_igmp_join.h"
-struct thread_master *master;
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)
@@ -79,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/redhat/quagga.spec.in b/redhat/quagga.spec.in
index c1d5f00167..9ff65e9a22 100644
--- a/redhat/quagga.spec.in
+++ b/redhat/quagga.spec.in
@@ -71,7 +71,6 @@
%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospfd6d
-
%if %{with_watchquagga}
%define daemon_watchquagga watchquagga
%else
@@ -220,6 +219,7 @@ developing OSPF-API and quagga applications.
--disable-watchquagga \
%endif
--enable-gcc-rdynamic \
+ --enable-isisd=yes \
--enable-systemd=yes \
--enable-poll=yes
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/rip_main.c b/ripd/rip_main.c
index f920e809e2..aa1c4ff4df 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -205,7 +205,9 @@ main (int argc, char **argv)
zlog_default = openzlog (progname, ZLOG_RIP, 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
zprivs_init (&ripd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
/* Command line option parse. */
while (1)
diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c
index 4b7d1b4c50..c28b9379cc 100644
--- a/ripd/rip_snmp.c
+++ b/ripd/rip_snmp.c
@@ -81,10 +81,10 @@
SNMP_LOCAL_VARIABLES
/* RIP-MIB instances. */
-oid rip_oid [] = { RIPV2MIB };
+static oid rip_oid [] = { RIPV2MIB };
/* Interface cache table sorted by interface's address. */
-struct route_table *rip_ifaddr_table;
+static struct route_table *rip_ifaddr_table;
/* Hook functions. */
static u_char *rip2Globals (struct variable *, oid [], size_t *,
@@ -96,7 +96,7 @@ static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
-struct variable rip_variables[] =
+static struct variable rip_variables[] =
{
/* RIP Global Counters. */
{RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
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_main.c b/ripngd/ripng_main.c
index a1c71c8562..f401a43156 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -204,7 +204,9 @@ main (int argc, char **argv)
zlog_default = openzlog(progname, ZLOG_RIPNG, 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
zprivs_init (&ripngd_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
while (1)
{
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/tests/testcli.refout b/tests/testcli.refout
index 1515ea2c65..7da5494827 100644
--- a/tests/testcli.refout
+++ b/tests/testcli.refout
@@ -272,6 +272,7 @@ Current configuration:
!
hostname test
!
+!
line vty
!
end
@@ -283,6 +284,7 @@ Current configuration:
!
hostname foohost
!
+!
line vty
!
end
diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py
index 9c0cbb48d6..900ed55c43 100755
--- a/tools/quagga-reload.py
+++ b/tools/quagga-reload.py
@@ -23,6 +23,9 @@ from ipaddr import IPv6Address
from pprint import pformat
+log = logging.getLogger(__name__)
+
+
class Context(object):
"""
@@ -80,12 +83,12 @@ class Config(object):
The internal representation has been marked appropriately by passing it
through vtysh with the -m parameter
"""
- logger.info('Loading Config object from file %s', filename)
+ log.info('Loading Config object from file %s', filename)
try:
file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename])
except subprocess.CalledProcessError as e:
- logger.error('vtysh marking of config file %s failed with error %s:', filename, str(e))
+ log.error('vtysh marking of config file %s failed with error %s:', filename, str(e))
print "vtysh marking of file %s failed with error: %s" % (filename, str(e))
sys.exit(1)
@@ -105,14 +108,14 @@ class Config(object):
The internal representation has been marked appropriately by passing it
through vtysh with the -m parameter
"""
- logger.info('Loading Config object from vtysh show running')
+ log.info('Loading Config object from vtysh show running')
try:
config_text = subprocess.check_output(
"/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -",
shell=True)
except subprocess.CalledProcessError as e:
- logger.error('vtysh marking of running config failed with error %s:', str(e))
+ log.error('vtysh marking of running config failed with error %s:', str(e))
print "vtysh marking of running config failed with error %s:" % (str(e))
sys.exit(1)
@@ -259,13 +262,13 @@ end
ctx_keys = [line, ]
current_context_lines = []
- logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
+ log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
self.save_contexts(ctx_keys, current_context_lines)
new_ctx = True
elif line == "end":
self.save_contexts(ctx_keys, current_context_lines)
- logger.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
+ log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
# Start a new context
new_ctx = True
@@ -281,7 +284,7 @@ end
# Start a new context
ctx_keys = copy.deepcopy(main_ctx_key)
current_context_lines = []
- logger.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys)
+ log.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys)
elif new_ctx is True:
if not main_ctx_key:
@@ -292,7 +295,7 @@ end
current_context_lines = []
new_ctx = False
- logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
+ log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
elif "address-family " in line:
main_ctx_key = []
@@ -301,7 +304,7 @@ end
self.save_contexts(ctx_keys, current_context_lines)
current_context_lines = []
main_ctx_key = copy.deepcopy(ctx_keys)
- logger.debug('LINE %-50s: entering sub-context, append to ctx_keys', line)
+ log.debug('LINE %-50s: entering sub-context, append to ctx_keys', line)
if line == "address-family ipv6":
ctx_keys.append("address-family ipv6 unicast")
@@ -313,7 +316,7 @@ end
else:
# Continuing in an existing context, add non-commented lines to it
current_context_lines.append(line)
- logger.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys)
+ log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys)
# Save the context of the last one
self.save_contexts(ctx_keys, current_context_lines)
@@ -448,7 +451,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
for (ctx_keys, line) in lines_to_del:
deleted = False
- if ctx_keys[0].startswith('router bgp') and line.startswith('neighbor '):
+ if ctx_keys[0].startswith('router bgp') and line and line.startswith('neighbor '):
"""
BGP changed how it displays swpX peers that are part of peer-group. Older
versions of quagga would display these on separate lines:
@@ -507,6 +510,56 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
+ """
+ In 3.0.1 we changed how we display neighbor interface command. Older
+ versions of quagga would display the following:
+ neighbor swp1 interface
+ neighbor swp1 remote-as external
+ neighbor swp1 capability extended-nexthop
+
+ but today we display via a single line
+ neighbor swp1 interface remote-as external
+
+ and capability extended-nexthop is no longer needed because we
+ automatically enable it when the neighbor is of type interface.
+
+ This change confuses quagga-reload.py so check to see if we are deleting
+ neighbor swp1 interface remote-as (external|internal|ASNUM)
+
+ and adding
+ neighbor swp1 interface
+ neighbor swp1 remote-as (external|internal|ASNUM)
+ neighbor swp1 capability extended-nexthop
+
+ If so then chop the del line and the corresponding add lines
+ """
+ re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
+ re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
+
+ if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
+ swpx_interface = None
+ swpx_remoteas = None
+
+ if re_swpx_int_remoteas:
+ swpx = re_swpx_int_remoteas.group(1)
+ remoteas = re_swpx_int_remoteas.group(2)
+ swpx_interface = "neighbor %s interface" % swpx
+ elif re_swpx_int_v6only_remoteas:
+ swpx = re_swpx_int_v6only_remoteas.group(1)
+ remoteas = re_swpx_int_v6only_remoteas.group(2)
+ swpx_interface = "neighbor %s interface v6only" % swpx
+
+ swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
+ found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
+ found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
+ tmp_ctx_keys = tuple(list(ctx_keys))
+
+ if found_add_swpx_interface and found_add_swpx_remoteas:
+ deleted = True
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, swpx_interface))
+ lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
+
if not deleted:
found_add_line = line_exist(lines_to_add, ctx_keys, line)
@@ -558,7 +611,7 @@ def compare_context_objects(newconf, running):
# Compare the two Config objects to find the lines that we need to add/del
lines_to_add = []
lines_to_del = []
- restart_bgpd = False
+ delete_bgpd = False
# Find contexts that are in newconf but not in running
# Find contexts that are in running but not in newconf
@@ -566,17 +619,21 @@ def compare_context_objects(newconf, running):
if running_ctx_keys not in newconf.contexts:
- # Check if bgp's local ASN has changed. If yes, just restart it
# We check that the len is 1 here so that we only look at ('router bgp 10')
# and not ('router bgp 10', 'address-family ipv4 unicast'). The
- # latter could cause a false restart_bgpd positive if ipv4 unicast is in
+ # latter could cause a false delete_bgpd positive if ipv4 unicast is in
# running but not in newconf.
if "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) == 1:
- restart_bgpd = True
+ delete_bgpd = True
+ lines_to_del.append((running_ctx_keys, None))
+
+ # If this is an address-family under 'router bgp' and we are already deleting the
+ # entire 'router bgp' context then ignore this sub-context
+ elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd:
continue
# Non-global context
- if running_ctx_keys and not any("address-family" in key for key in running_ctx_keys):
+ elif running_ctx_keys and not any("address-family" in key for key in running_ctx_keys):
lines_to_del.append((running_ctx_keys, None))
# Global context
@@ -602,11 +659,6 @@ def compare_context_objects(newconf, running):
for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems():
if newconf_ctx_keys not in running.contexts:
-
- # If its "router bgp" and we're restarting bgp, skip doing
- # anything specific for bgp
- if "router bgp" in newconf_ctx_keys[0] and restart_bgpd:
- continue
lines_to_add.append((newconf_ctx_keys, None))
for line in newconf_ctx.lines:
@@ -614,7 +666,7 @@ def compare_context_objects(newconf, running):
(lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del)
- return (lines_to_add, lines_to_del, restart_bgpd)
+ return (lines_to_add, lines_to_del)
if __name__ == '__main__':
# Command line options
@@ -624,15 +676,21 @@ if __name__ == '__main__':
group.add_argument('--reload', action='store_true', help='Apply the deltas', default=False)
group.add_argument('--test', action='store_true', help='Show the deltas', default=False)
parser.add_argument('--debug', action='store_true', help='Enable debugs', default=False)
+ parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False)
parser.add_argument('filename', help='Location of new quagga config file')
args = parser.parse_args()
# Logging
# For --test log to stdout
# For --reload log to /var/log/quagga/quagga-reload.log
- if args.test:
+ if args.test or args.stdout:
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)5s: %(message)s')
+
+ # Color the errors and warnings in red
+ logging.addLevelName(logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR))
+ logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING))
+
elif args.reload:
if not os.path.isdir('/var/log/quagga/'):
os.makedirs('/var/log/quagga/')
@@ -644,7 +702,7 @@ if __name__ == '__main__':
# argparse should prevent this from happening but just to be safe...
else:
raise Exception('Must specify --reload or --test')
- logger = logging.getLogger(__name__)
+ log = logging.getLogger(__name__)
# Verify the new config file is valid
if not os.path.isfile(args.filename):
@@ -657,15 +715,15 @@ if __name__ == '__main__':
# Verify that 'service integrated-vtysh-config' is configured
vtysh_filename = '/etc/quagga/vtysh.conf'
- service_integrated_vtysh_config = False
+ service_integrated_vtysh_config = True
if os.path.isfile(vtysh_filename):
with open(vtysh_filename, 'r') as fh:
for line in fh.readlines():
line = line.strip()
- if line == 'service integrated-vtysh-config':
- service_integrated_vtysh_config = True
+ if line == 'no service integrated-vtysh-config':
+ service_integrated_vtysh_config = False
break
if not service_integrated_vtysh_config:
@@ -673,9 +731,9 @@ if __name__ == '__main__':
sys.exit(1)
if args.debug:
- logger.setLevel(logging.DEBUG)
+ log.setLevel(logging.DEBUG)
- logger.info('Called via "%s"', str(args))
+ log.info('Called via "%s"', str(args))
# Create a Config object from the config generated by newconf
newconf = Config()
@@ -691,7 +749,7 @@ if __name__ == '__main__':
else:
running.load_from_show_running()
- (lines_to_add, lines_to_del, restart_bgp) = compare_context_objects(newconf, running)
+ (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
lines_to_configure = []
if lines_to_del:
@@ -720,12 +778,9 @@ if __name__ == '__main__':
lines_to_configure.append(cmd)
print cmd
- if restart_bgp:
- print "BGP local AS changed, bgpd would restart"
-
elif args.reload:
- logger.debug('New Quagga Config\n%s', newconf.get_lines())
+ log.debug('New Quagga Config\n%s', newconf.get_lines())
# This looks a little odd but we have to do this twice...here is why
# If the user had this running bgp config:
@@ -752,9 +807,9 @@ if __name__ == '__main__':
for x in range(2):
running = Config()
running.load_from_show_running()
- logger.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines())
+ log.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines())
- (lines_to_add, lines_to_del, restart_bgp) = compare_context_objects(newconf, running)
+ (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
if lines_to_del:
for (ctx_keys, line) in lines_to_del:
@@ -792,17 +847,17 @@ if __name__ == '__main__':
# 'no ip ospf authentication message-digest 1.1.1.1' in
# our example above
# - Split that last entry by whitespace and drop the last word
- logger.warning('Failed to execute %s', ' '.join(cmd))
+ log.warning('Failed to execute %s', ' '.join(cmd))
last_arg = cmd[-1].split(' ')
if len(last_arg) <= 2:
- logger.error('"%s" we failed to remove this command', original_cmd)
+ log.error('"%s" we failed to remove this command', original_cmd)
break
new_last_arg = last_arg[0:-1]
cmd[-1] = ' '.join(new_last_arg)
else:
- logger.info('Executed "%s"', ' '.join(cmd))
+ log.info('Executed "%s"', ' '.join(cmd))
break
if lines_to_add:
@@ -822,7 +877,7 @@ if __name__ == '__main__':
string.digits) for _ in range(6))
filename = "/var/run/quagga/reload-%s.txt" % random_string
- logger.info("%s content\n%s" % (filename, pformat(lines_to_configure)))
+ log.info("%s content\n%s" % (filename, pformat(lines_to_configure)))
with open(filename, 'w') as fh:
for line in lines_to_configure:
@@ -830,6 +885,5 @@ if __name__ == '__main__':
subprocess.call(['/usr/bin/vtysh', '-f', filename])
os.unlink(filename)
- if restart_bgp:
- subprocess.call(['sudo', 'systemctl', 'reset-failed', 'quagga'])
- subprocess.call(['sudo', 'systemctl', '--no-block', 'restart', 'quagga'])
+ # Make these changes persistent
+ subprocess.call(['/usr/bin/vtysh', '-c', 'write'])
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 2180a78629..ed49acca47 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -20,15 +20,43 @@ dist_examples_DATA = vtysh.conf.sample
EXTRA_DIST = extract.pl
-vtysh_cmd_FILES = $(top_srcdir)/bgpd/*.c $(top_srcdir)/isisd/*.c \
- $(top_srcdir)/ospfd/*.c $(top_srcdir)/ospf6d/*.c \
- $(top_srcdir)/ripd/*.c $(top_srcdir)/ripngd/*.c \
- $(top_srcdir)/pimd/pim_cmd.c \
+vtysh_scan =
+
+if PIMD
+vtysh_scan += $(top_srcdir)/pimd/pim_cmd.c
+endif
+
+if BGPD
+vtysh_scan += $(top_srcdir)/bgpd/*.c
+endif
+
+if ISISD
+vtysh_scan += $(top_srcdir)/isisd/*.c
+endif
+
+if OSPFD
+vtysh_scan += $(top_srcdir)/ospfd/*.c
+endif
+
+if OSPF6D
+vtysh_scan += $(top_srcdir)/ospf6d/*.c
+endif
+
+if RIPD
+vtysh_scan += $(top_srcdir)/ripd/*.c
+endif
+
+if RIPNGD
+vtysh_scan += $(top_srcdir)/ripngd/*.c
+endif
+
+vtysh_cmd_FILES = $(vtysh_scan) \
$(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \
$(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \
$(top_srcdir)/lib/distribute.c $(top_srcdir)/lib/if_rmap.c \
- $(top_srcdir)/lib/vty.c $(top_srcdir)/zebra/debug.c \
$(top_srcdir)/lib/vrf.c \
+ $(top_srcdir)/lib/vty.c $(top_srcdir)/zebra/debug.c \
+ $(top_srcdir)/lib/ns.c \
$(top_srcdir)/zebra/interface.c \
$(top_srcdir)/zebra/irdp_interface.c \
$(top_srcdir)/zebra/rtadv.c $(top_srcdir)/zebra/zebra_vty.c \
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index e8992a036a..7563daa506 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";
@@ -58,6 +59,8 @@ $ignore{'"address-family ipv4 vrf NAME"'} = "ignore";
$ignore{'"address-family encap"'} = "ignore";
$ignore{'"address-family encapv4"'} = "ignore";
$ignore{'"address-family encapv6"'} = "ignore";
+$ignore{'"address-family vpnv6"'} = "ignore";
+$ignore{'"address-family vpnv6 unicast"'} = "ignore";
$ignore{'"exit-address-family"'} = "ignore";
$ignore{'"key chain WORD"'} = "ignore";
$ignore{'"key <0-2147483647>"'} = "ignore";
@@ -118,7 +121,7 @@ foreach (@ARGV) {
$protocol = "VTYSH_RIPD";
}
elsif ($file =~ /lib\/routemap\.c$/) {
- $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
+ $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD";
}
elsif ($file =~ /lib\/vrf\.c$/) {
$protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
@@ -126,11 +129,14 @@ foreach (@ARGV) {
elsif ($file =~ /lib\/filter\.c$/) {
$protocol = "VTYSH_ALL";
}
+ elsif ($file =~ /lib\/ns\.c$/) {
+ $protocol = "VTYSH_ZEBRA";
+ }
elsif ($file =~ /lib\/plist\.c$/) {
if ($defun_array[1] =~ m/ipv6/) {
$protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
} else {
- $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA";
+ $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD";
}
}
elsif ($file =~ /lib\/distribute\.c$/) {
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 9d4061cfcf..18ca0dca29 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -37,9 +37,11 @@
#include "linklist.h"
#include "command.h"
#include "memory.h"
+#include "filter.h"
#include "vtysh/vtysh.h"
#include "log.h"
#include "bgpd/bgp_vty.h"
+#include "ns.h"
#include "vrf.h"
#include "lib/grammar_sandbox.h"
@@ -73,7 +75,7 @@ struct vtysh_client vtysh_client[] =
};
/* Using integrated config from Quagga.conf. Default is no. */
-int vtysh_writeconfig_integrated = 0;
+int vtysh_writeconfig_integrated = 1;
extern char config_default[];
@@ -506,6 +508,28 @@ vtysh_execute (const char *line)
return vtysh_execute_func (line, 1);
}
+static char *
+trim (char *s)
+{
+ size_t size;
+ char *end;
+
+ size = strlen(s);
+
+ if (!size)
+ return s;
+
+ end = s + size - 1;
+ while (end >= s && isspace(*end))
+ end--;
+ *(end + 1) = '\0';
+
+ while (*s && isspace(*s))
+ s++;
+
+ return s;
+}
+
int
vtysh_mark_file (const char *filename)
{
@@ -517,6 +541,8 @@ vtysh_mark_file (const char *filename)
struct cmd_element *cmd;
int saved_ret, prev_node;
int lineno = 0;
+ char *vty_buf_copy = NULL;
+ char *vty_buf_trimmed = NULL;
if (strncmp("-", filename, 1) == 0)
confp = stdin;
@@ -537,13 +563,16 @@ vtysh_mark_file (const char *filename)
vtysh_execute_no_pager ("enable");
vtysh_execute_no_pager ("configure terminal");
+ vty_buf_copy = XCALLOC (MTYPE_VTY, VTY_BUFSIZ);
while (fgets (vty->buf, VTY_BUFSIZ, confp))
{
lineno++;
tried = 0;
+ strcpy(vty_buf_copy, vty->buf);
+ vty_buf_trimmed = trim(vty_buf_copy);
- if (vty->buf[0] == '!' || vty->buf[1] == '#')
+ if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#')
{
fprintf(stdout, "%s", vty->buf);
continue;
@@ -558,6 +587,12 @@ vtysh_mark_file (const char *filename)
continue;
}
+ /* Ignore the "end" lines, we will generate these where appropriate */
+ if (strlen(vty_buf_trimmed) == 3 && strncmp("end", vty_buf_trimmed, 3) == 0)
+ {
+ continue;
+ }
+
prev_node = vty->node;
saved_ret = ret = cmd_execute_command_strict (vline, vty, &cmd);
@@ -608,21 +643,25 @@ vtysh_mark_file (const char *filename)
fprintf (stderr,"line %d: Warning...: %s\n", lineno, vty->buf);
fclose(confp);
vty_close(vty);
+ XFREE(MTYPE_VTY, vty_buf_copy);
return CMD_WARNING;
case CMD_ERR_AMBIGUOUS:
fprintf (stderr,"line %d: %% Ambiguous command: %s\n", lineno, vty->buf);
fclose(confp);
vty_close(vty);
+ XFREE(MTYPE_VTY, vty_buf_copy);
return CMD_ERR_AMBIGUOUS;
case CMD_ERR_NO_MATCH:
fprintf (stderr,"line %d: %% Unknown command: %s\n", lineno, vty->buf);
fclose(confp);
vty_close(vty);
+ XFREE(MTYPE_VTY, vty_buf_copy);
return CMD_ERR_NO_MATCH;
case CMD_ERR_INCOMPLETE:
fprintf (stderr,"line %d: %% Command incomplete: %s\n", lineno, vty->buf);
fclose(confp);
vty_close(vty);
+ XFREE(MTYPE_VTY, vty_buf_copy);
return CMD_ERR_INCOMPLETE;
case CMD_SUCCESS:
fprintf(stdout, "%s", vty->buf);
@@ -654,6 +693,7 @@ vtysh_mark_file (const char *filename)
/* This is the end */
fprintf(stdout, "end\n");
vty_close(vty);
+ XFREE(MTYPE_VTY, vty_buf_copy);
if (confp != stdin)
fclose(confp);
@@ -847,7 +887,10 @@ command_generator (const char *text, int state)
if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
vector_set (vline, NULL);
+ if (matched)
+ XFREE (MTYPE_TMP, matched);
matched = cmd_complete_command (vline, vty, &complete_status);
+ cmd_free_strvec (vline);
}
if (matched && matched[index])
@@ -899,6 +942,12 @@ static struct cmd_node interface_node =
"%s(config-if)# ",
};
+static struct cmd_node ns_node =
+{
+ NS_NODE,
+ "%s(config-logical-router)# ",
+};
+
static struct cmd_node vrf_node =
{
VRF_NODE,
@@ -995,6 +1044,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;
@@ -1348,6 +1403,7 @@ vtysh_exit (struct vty *vty)
vty->node = ENABLE_NODE;
break;
case INTERFACE_NODE:
+ case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
case BGP_NODE:
@@ -1377,6 +1433,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;
}
@@ -1576,6 +1635,19 @@ DEFSH (VTYSH_ZEBRA,
"Interface's name\n"
VRF_CMD_HELP_STR)
+DEFUNSH (VTYSH_NS,
+ vtysh_ns,
+ vtysh_ns_cmd,
+ "logical-router <1-65535 ns NAME",
+ "Enable a logical-router\n"
+ "Specify the logical-router indentifier\n"
+ "The Name Space\n"
+ "The file name in " NS_RUN_DIR ", or a full pathname\n")
+{
+ vty->node = NS_NODE;
+ return CMD_SUCCESS;
+}
+
DEFUNSH (VTYSH_VRF,
vtysh_vrf,
vtysh_vrf_cmd,
@@ -1594,6 +1666,20 @@ DEFSH (VTYSH_ZEBRA,
"Delete a pseudo vrf's configuration\n"
"VRF's name\n")
+DEFUNSH (VTYSH_NS,
+ vtysh_exit_ns,
+ vtysh_exit_ns_cmd,
+ "exit",
+ "Exit current mode and down to previous mode\n")
+{
+ return vtysh_exit (vty);
+}
+
+ALIAS (vtysh_exit_ns,
+ vtysh_quit_ns_cmd,
+ "quit",
+ "Exit current mode and down to previous mode\n")
+
DEFUNSH (VTYSH_VRF,
vtysh_exit_vrf,
vtysh_exit_vrf_cmd,
@@ -1709,6 +1795,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,
@@ -2099,7 +2196,8 @@ DEFUN (vtysh_write_terminal,
vty_out (vty, "!%s", VTY_NEWLINE);
for (i = 0; i < array_size(vtysh_client); i++)
- vtysh_client_config (&vtysh_client[i], line);
+ if ((argc < 1 ) || (begins_with(vtysh_client[i].name, argv[0])))
+ vtysh_client_config (&vtysh_client[i], line);
/* Integrate vtysh specific configuration. */
vtysh_config_write ();
@@ -2319,7 +2417,7 @@ ALIAS (vtysh_write_terminal,
SHOW_STR
"Current operating configuration\n")
-ALIAS (vtysh_write_terminal_daemon,
+ALIAS (vtysh_write_terminal,
vtysh_show_running_config_daemon_cmd,
"show running-config (zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pimd)",
SHOW_STR
@@ -2805,6 +2903,8 @@ 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 (&ns_node, NULL);
install_node (&vrf_node, NULL);
install_node (&rmap_node, NULL);
install_node (&zebra_node, NULL);
@@ -2834,6 +2934,8 @@ 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 (NS_NODE);
vtysh_install_default (VRF_NODE);
vtysh_install_default (RMAP_NODE);
vtysh_install_default (ZEBRA_NODE);
@@ -2927,8 +3029,14 @@ 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 (NS_NODE, &vtysh_end_all_cmd);
+ install_element (NS_NODE, &vtysh_exit_ns_cmd);
+ install_element (NS_NODE, &vtysh_quit_ns_cmd);
+
install_element (VRF_NODE, &vtysh_end_all_cmd);
install_element (VRF_NODE, &vtysh_exit_vrf_cmd);
install_element (VRF_NODE, &vtysh_quit_vrf_cmd);
@@ -2977,6 +3085,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.h b/vtysh/vtysh.h
index e974cf331c..75822b1363 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -34,6 +34,7 @@
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD
+#define VTYSH_NS VTYSH_ZEBRA
#define VTYSH_VRF VTYSH_ZEBRA
/* vtysh local configuration file. */
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index fcad333b9f..118b7ba035 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -171,6 +171,7 @@ vtysh_config_parse_line (const char *line)
{
if (config->index == RMAP_NODE ||
config->index == INTERFACE_NODE ||
+ config->index == NS_NODE ||
config->index == VRF_NODE ||
config->index == VTY_NODE)
config_add_line_uniq (config->line, line);
@@ -183,6 +184,8 @@ vtysh_config_parse_line (const char *line)
default:
if (strncmp (line, "interface", strlen ("interface")) == 0)
config = config_get (INTERFACE_NODE, line);
+ else if (strncmp (line, "logical-router", strlen ("ns")) == 0)
+ config = config_get (NS_NODE, line);
else if (strncmp (line, "vrf", strlen ("vrf")) == 0)
config = config_get (VRF_NODE, line);
else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
@@ -318,7 +321,14 @@ vtysh_config_dump (FILE *fp)
if ((master = vector_slot (configvec, i)) != NULL)
{
for (ALL_LIST_ELEMENTS (master, node, nnode, config))
- {
+ {
+ /* Don't print empty sections for interface/vrf. Route maps on the
+ * other hand could have a legitimate empty section at the end.
+ */
+ if ((config->index == INTERFACE_NODE || (config->index == VRF_NODE))
+ && list_isempty (config->line))
+ continue;
+
fprintf (fp, "%s\n", config->name);
fflush (fp);
@@ -412,8 +422,8 @@ vtysh_config_write ()
sprintf (line, "hostname %s", host.name);
vtysh_config_parse_line(line);
}
- if (vtysh_writeconfig_integrated)
- vtysh_config_parse_line ("service integrated-vtysh-config");
+ if (!vtysh_writeconfig_integrated)
+ vtysh_config_parse_line ("no service integrated-vtysh-config");
user_config_write ();
}
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index cd21c94efd..3c46194d31 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -317,7 +317,7 @@ main (int argc, char **argv, char **env)
case 'c':
{
struct cmd_rec *cr;
- cr = XMALLOC(0, sizeof(*cr));
+ cr = XMALLOC(MTYPE_TMP, sizeof(*cr));
cr->line = optarg;
cr->next = NULL;
if (tail)
@@ -415,7 +415,10 @@ main (int argc, char **argv, char **env)
if (vtysh_connect_all (daemon_name) <= 0)
{
fprintf(stderr, "Exiting: failed to connect to any daemons.\n");
- exit(1);
+ if (no_error)
+ exit(0);
+ else
+ exit(1);
}
if (inputfile)
@@ -501,7 +504,7 @@ main (int argc, char **argv, char **env)
struct cmd_rec *cr;
cr = cmd;
cmd = cmd->next;
- XFREE(0, cr);
+ XFREE(MTYPE_TMP, cr);
}
}
diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c
index 0d72c378a3..1886ba3a67 100644
--- a/vtysh/vtysh_user.c
+++ b/vtysh/vtysh_user.c
@@ -116,7 +116,7 @@ struct list *userlist;
static struct vtysh_user *
user_new (void)
{
- return XCALLOC (0, sizeof (struct vtysh_user));
+ return XCALLOC (MTYPE_TMP, sizeof (struct vtysh_user));
}
static struct vtysh_user *
@@ -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/watchquagga/watchquagga.c b/watchquagga/watchquagga.c
index 2a237efb6a..e882653e38 100644
--- a/watchquagga/watchquagga.c
+++ b/watchquagga/watchquagga.c
@@ -1337,8 +1337,6 @@ main(int argc, char **argv)
zlog_default = openzlog(progname, ZLOG_NONE, 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
-
zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
if (daemon_mode)
{
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 87a426fdc4..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;
@@ -2114,10 +2883,8 @@ if_config_write (struct vty *vty)
if (ifp->bandwidth != 0)
vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
- if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
- vty_out(vty, " link-detect%s", VTY_NEWLINE);
- else
- vty_out(vty, " no link-detect%s", VTY_NEWLINE);
+ if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
+ vty_out(vty, " no link-detect%s", VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
{
@@ -2152,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;
@@ -2184,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);
@@ -2227,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..17b3c7bc8d 100644
--- a/zebra/kernel_null.c
+++ b/zebra/kernel_null.c
@@ -39,9 +39,6 @@ int kernel_add_ipv6 (struct prefix *a, struct rib *b) { return 0; }
int kernel_update_ipv6 (struct prefix *a, struct rib *b) { return 0; }
int kernel_delete_ipv6 (struct prefix *a, struct rib *b) { return 0; }
-int kernel_add_route (struct prefix_ipv4 *a, struct in_addr *b, int c, int d)
-{ return 0; }
-
int kernel_address_add_ipv4 (struct interface *a, struct connected *b)
{
zlog_debug ("%s", __func__);
@@ -60,7 +57,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 ab907f83e8..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 */
@@ -245,7 +245,9 @@ main (int argc, char **argv)
zlog_default = openzlog (progname, ZLOG_ZEBRA, 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
zprivs_init (&zserv_privs);
- zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl);
+#if defined(HAVE_CUMULUS)
+ zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
+#endif
while (1)
{
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..46e71fa46e 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -30,15 +30,13 @@
extern int kernel_add_ipv4 (struct prefix *, struct rib *);
extern int kernel_update_ipv4 (struct prefix *, struct rib *);
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 *);
extern int kernel_update_ipv6 (struct prefix *, struct rib *);
extern int kernel_delete_ipv6 (struct prefix *, struct rib *);
-#endif /* HAVE_IPV6 */
-
#endif /* _ZEBRA_RT_H */
diff --git a/zebra/rt_ioctl.c b/zebra/rt_ioctl.c
index 383c5f71ac..597392c38a 100644
--- a/zebra/rt_ioctl.c
+++ b/zebra/rt_ioctl.c
@@ -46,122 +46,12 @@ kernel_read (int sock)
return;
}
-#if 0
-/* Initialization prototype of struct sockaddr_in. */
-static struct sockaddr_in sin_proto =
-{
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sizeof (struct sockaddr_in),
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
- AF_INET, 0, {0}, {0}
-};
-#endif /* 0 */
-
/* Solaris has ortentry. */
#ifdef HAVE_OLD_RTENTRY
#define rtentry ortentry
#endif /* HAVE_OLD_RTENTRY */
/* Interface to ioctl route message. */
-int
-kernel_add_route (struct prefix_ipv4 *dest, struct in_addr *gate,
- int index, int flags)
-{
- int ret;
- int sock;
- struct rtentry rtentry;
- struct sockaddr_in sin_dest, sin_mask, sin_gate;
-
- memset (&rtentry, 0, sizeof (struct rtentry));
-
- /* Make destination. */
- memset (&sin_dest, 0, sizeof (struct sockaddr_in));
- sin_dest.sin_family = AF_INET;
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sin_dest.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
- sin_dest.sin_addr = dest->prefix;
-
- /* Make gateway. */
- if (gate)
- {
- memset (&sin_gate, 0, sizeof (struct sockaddr_in));
- sin_gate.sin_family = AF_INET;
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sin_gate.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
- sin_gate.sin_addr = *gate;
- }
-
- memset (&sin_mask, 0, sizeof (struct sockaddr_in));
- sin_mask.sin_family = AF_INET;
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sin_gate.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
- masklen2ip (dest->prefixlen, &sin_mask.sin_addr);
-
- /* Set destination address, mask and gateway.*/
- memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in));
- if (gate)
- memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in));
-#ifndef SUNOS_5
- memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in));
-#endif /* SUNOS_5 */
-
- /* Routing entry flag set. */
- if (dest->prefixlen == 32)
- rtentry.rt_flags |= RTF_HOST;
-
- if (gate && gate->s_addr != INADDR_ANY)
- rtentry.rt_flags |= RTF_GATEWAY;
-
- rtentry.rt_flags |= RTF_UP;
-
- /* Additional flags */
- rtentry.rt_flags |= flags;
-
-
- /* For tagging route. */
- /* rtentry.rt_flags |= RTF_DYNAMIC; */
-
- /* Open socket for ioctl. */
- sock = socket (AF_INET, SOCK_DGRAM, 0);
- if (sock < 0)
- {
- zlog_warn ("can't make socket\n");
- return -1;
- }
-
- /* Send message by ioctl(). */
- ret = ioctl (sock, SIOCADDRT, &rtentry);
- if (ret < 0)
- {
- switch (errno)
- {
- case EEXIST:
- close (sock);
- return ZEBRA_ERR_RTEXIST;
- break;
- case ENETUNREACH:
- close (sock);
- return ZEBRA_ERR_RTUNREACH;
- break;
- case EPERM:
- close (sock);
- return ZEBRA_ERR_EPERM;
- break;
- }
-
- close (sock);
- zlog_warn ("write : %s (%d)", safe_strerror (errno), errno);
- return 1;
- }
- close (sock);
-
- return ret;
-}
-
-/* Interface to ioctl route message. */
static int
kernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family)
{
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 481ff781e3..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;
@@ -1998,7 +2091,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
- return netlink_talk (&req.n, &zns->netlink_cmd, NS_DEFAULT);
+ return netlink_talk (&req.n, &zns->netlink_cmd, zns);
}
/* Routing table change via netlink interface. */
@@ -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 750502aa23..8384b327ff 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -69,23 +69,26 @@ static void rtadv_event (struct zebra_ns *, enum rtadv_event, int);
static int if_join_all_router (int, struct interface *);
static int if_leave_all_router (int, struct interface *);
-static int rtadv_increment_received(unsigned int *ifindex) {
+static int
+rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
+{
int ret = -1;
struct interface *iface;
struct zebra_if *zif;
- iface = if_lookup_by_index_vrf(*ifindex, VRF_DEFAULT);
- if (iface && iface->info) {
- zif = iface->info;
- zif->ra_rcvd++;
- ret = 0;
- }
+ iface = if_lookup_by_index_per_ns (zns, *ifindex);
+ if (iface && iface->info)
+ {
+ zif = iface->info;
+ zif->ra_rcvd++;
+ ret = 0;
+ }
return ret;
}
static int
-rtadv_recv_packet (int sock, u_char *buf, int buflen,
- struct sockaddr_in6 *from, unsigned int *ifindex,
+rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen,
+ struct sockaddr_in6 *from, ifindex_t *ifindex,
int *hoplimit)
{
int ret;
@@ -134,10 +137,7 @@ rtadv_recv_packet (int sock, u_char *buf, int buflen,
}
}
- if(rtadv_increment_received(ifindex) < 0)
- zlog_err("%s: could not increment RA received counter on ifindex %d",
- __func__, *ifindex);
-
+ rtadv_increment_received(zns, ifindex);
return 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);
@@ -619,7 +597,7 @@ rtadv_read (struct thread *thread)
/* Register myself. */
rtadv_event (zns, RTADV_READ, sock);
- len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
+ len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit);
if (len < 0)
{
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_ns.c b/zebra/zebra_ns.c
index 6b04aa741a..084a5d181f 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -21,6 +21,7 @@
*/
#include "zebra.h"
+#include "lib/ns.h"
#include "lib/vrf.h"
#include "lib/prefix.h"
#include "lib/memory.h"
@@ -86,6 +87,8 @@ zebra_ns_init (void)
{
dzns = XCALLOC (MTYPE_ZEBRA_NS, sizeof (struct zebra_ns));
+ ns_init ();
+
zebra_vrf_init ();
zebra_ns_enable (0, (void **)&dzns);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index 07fcfcdac1..8a821c465a 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -23,6 +23,8 @@
#if !defined(__ZEBRA_NS_H__)
#define __ZEBRA_NS_H__
+#include <lib/ns.h>
+
#ifdef HAVE_NETLINK
/* Socket interface to kernel */
struct nlsock
@@ -34,9 +36,6 @@ struct nlsock
};
#endif
-/* NetNS ID type. */
-typedef u_int16_t ns_id_t;
-
struct zebra_ns
{
/* net-ns name. */
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index bf6afb0216..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"
@@ -131,11 +132,13 @@ zebra_ptm_init (void)
void
zebra_ptm_finish(void)
{
- if (ptm_cb.ptm_sock != -1)
- close(ptm_cb.ptm_sock);
+ int proto;
- if (ptm_cb.wb)
- buffer_free(ptm_cb.wb);
+ for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++)
+ if (CHECK_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG))
+ zebra_ptm_bfd_client_deregister(proto);
+
+ buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock);
if (ptm_cb.out_data)
free(ptm_cb.out_data);
@@ -150,6 +153,12 @@ zebra_ptm_finish(void)
thread_cancel (ptm_cb.t_write);
if (ptm_cb.t_timer)
thread_cancel (ptm_cb.t_timer);
+
+ if (ptm_cb.wb)
+ buffer_free(ptm_cb.wb);
+
+ if (ptm_cb.ptm_sock != -1)
+ close(ptm_cb.ptm_sock);
}
static int
@@ -375,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));
@@ -999,24 +1010,26 @@ zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length)
zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
ptm_cb.out_data);
zebra_ptm_send_message(ptm_cb.out_data, data_len);
+
+ SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
return 0;
}
/* BFD client deregister */
void
-zebra_ptm_bfd_client_deregister (struct zserv *client)
+zebra_ptm_bfd_client_deregister (int proto)
{
void *out_ctxt;
char tmp_buf[64];
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
- if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP
- && client->proto != ZEBRA_ROUTE_OSPF6)
+ if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP
+ && proto != ZEBRA_ROUTE_OSPF6)
return;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bfd_client_deregister msg for client %s",
- zebra_route_string(client->proto));
+ zlog_err("bfd_client_deregister msg for client %s",
+ zebra_route_string(proto));
if (ptm_cb.ptm_sock == -1)
{
@@ -1030,7 +1043,7 @@ zebra_ptm_bfd_client_deregister (struct zserv *client)
sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD);
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
- sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
+ sprintf(tmp_buf, "%s", zebra_route_string(proto));
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
tmp_buf);
@@ -1039,7 +1052,9 @@ zebra_ptm_bfd_client_deregister (struct zserv *client)
if (IS_ZEBRA_DEBUG_SEND)
zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
ptm_cb.out_data);
+
zebra_ptm_send_message(ptm_cb.out_data, data_len);
+ UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
}
int
diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h
index 27c0e42f99..71c85d9094 100644
--- a/zebra/zebra_ptm.h
+++ b/zebra/zebra_ptm.h
@@ -27,6 +27,8 @@ extern const char ZEBRA_PTM_SOCK_NAME[];
#define ZEBRA_PTM_MAX_SOCKBUF 3200 /* 25B *128 ports */
#define ZEBRA_PTM_SEND_MAX_SOCKBUF 512
+#define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */
+
/* Zebra ptm context block */
struct zebra_ptm_cb
{
@@ -44,6 +46,7 @@ struct zebra_ptm_cb
int ptm_enable;
int pid;
+ u_int8_t client_flags[ZEBRA_ROUTE_MAX];
};
#define ZEBRA_PTM_STATUS_DOWN 0
@@ -72,5 +75,5 @@ int zebra_ptm_bfd_client_register (struct zserv *client, int sock,
void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp);
void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp);
-void zebra_ptm_bfd_client_deregister (struct zserv *client);
+void zebra_ptm_bfd_client_deregister (int proto);
#endif
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d70f528f5a..3812101431 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 */
@@ -405,6 +410,10 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
+
+ /* if the next hop is imported from another table, skip it */
+ if (match->type == ZEBRA_ROUTE_TABLE)
+ continue;
if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
break;
}
@@ -537,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
@@ -736,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;
@@ -747,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);
@@ -809,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)
@@ -834,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)
@@ -998,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)
@@ -1180,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.
@@ -1191,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)
{
@@ -1216,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);
}
@@ -1237,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;
@@ -1292,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;
@@ -1421,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;
}
@@ -1447,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
@@ -1474,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
@@ -1495,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");
@@ -1544,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. */
@@ -1615,11 +1567,53 @@ 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);
+}
+
+/* Check if 'alternate' RIB entry is better than 'current'. */
+static struct rib *
+rib_choose_best (struct rib *current, struct rib *alternate)
+{
+ if (current == NULL)
+ return alternate;
+
+ /* filter route selection in following order:
+ * - connected beats other types
+ * - lower distance beats higher
+ * - lower metric beats higher for equal distance
+ * - last, hence oldest, route wins tie break.
+ */
+
+ /* Connected routes. Pick the last connected
+ * route of the set of lowest metric connected routes.
+ */
+ if (alternate->type == ZEBRA_ROUTE_CONNECT)
+ {
+ if (current->type != ZEBRA_ROUTE_CONNECT
+ || alternate->metric <= current->metric)
+ return alternate;
+
+ return current;
+ }
+
+ if (current->type == ZEBRA_ROUTE_CONNECT)
+ return current;
+
+ /* higher distance loses */
+ if (alternate->distance < current->distance)
+ return alternate;
+ if (current->distance < alternate->distance)
+ return current;
+
+ /* metric tie-breaks equal distance */
+ if (alternate->metric <= current->metric)
+ return alternate;
+
+ return current;
}
/* Core function for processing routing information base. */
@@ -1631,6 +1625,7 @@ rib_process (struct route_node *rn)
struct rib *fib = NULL;
struct rib *select = NULL;
struct rib *del = NULL;
+ struct rib *best = NULL;
char buf[INET6_ADDRSTRLEN];
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
@@ -1699,7 +1694,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)
@@ -1727,66 +1722,16 @@ 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;
}
- /* Newly selected rib, the common case. */
- if (!select)
- {
- select = rib;
- continue;
- }
-
- /* filter route selection in following order:
- * - connected beats other types
- * - lower distance beats higher
- * - lower metric beats higher for equal distance
- * - last, hence oldest, route wins tie break.
- */
-
- /* Connected routes. Pick the last connected
- * route of the set of lowest metric connected routes.
- */
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- if (select->type != ZEBRA_ROUTE_CONNECT
- || rib->metric <= select->metric)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- }
- else
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
- else if (select->type == ZEBRA_ROUTE_CONNECT)
- {
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
-
- /* higher distance loses */
- if (rib->distance > select->distance)
- {
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
-
- /* lower wins */
- if (rib->distance < select->distance)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- continue;
- }
-
- /* metric tie-breaks equal distance */
- if (rib->metric <= select->metric)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- }
+ best = rib_choose_best(select, rib);
+ if (select && best != select)
+ UNSET_FLAG (select->status, RIB_ENTRY_CHANGED);
+ if (best != rib)
+ UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
+ select = best;
} /* RNODE_FOREACH_RIB_SAFE */
/* After the cycle is finished, the following pointers will be set:
@@ -1815,7 +1760,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");
@@ -1857,7 +1802,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))
{
@@ -1910,7 +1855,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
@@ -1980,7 +1925,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
@@ -2313,7 +2258,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.
@@ -2368,7 +2313,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;
@@ -2402,123 +2347,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.
@@ -2546,9 +2374,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
@@ -2681,21 +2510,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)
@@ -2709,7 +2548,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. */
@@ -2735,7 +2574,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,
@@ -2759,11 +2598,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;
@@ -2776,15 +2614,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)
@@ -2830,7 +2668,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;
@@ -2848,10 +2687,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)
{
@@ -2876,7 +2715,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
@@ -2897,444 +2736,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;
@@ -3343,22 +2752,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. */
@@ -3376,12 +2791,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 ;
}
}
@@ -3393,6 +2810,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;
@@ -3401,10 +2819,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);
@@ -3420,7 +2848,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,
@@ -3428,7 +2856,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);
@@ -3440,406 +2868,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 8b76ea65c9..ef2357b99c 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -353,18 +353,17 @@ zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type,
if (!rn)
return NULL;
- /* Do not resolve over default route unless allowed &&
- * match route to be exact if so specified
+ /* When resolving nexthops, do not resolve via the default route unless
+ * 'ip nht resolve-via-default' is configured.
*/
if ((type == RNH_NEXTHOP_TYPE) &&
(is_default_prefix (&rn->p) &&
!nh_resolve_via_default(rn->p.family)))
rib = NULL;
- else if ((type == RNH_IMPORT_CHECK_TYPE) &&
- ((is_default_prefix(&rn->p)) ||
- ((CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) &&
- !prefix_same(&nrn->p, &rn->p))))
- rib = NULL;
+ else if ((type == RNH_IMPORT_CHECK_TYPE) &&
+ CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) &&
+ !prefix_same(&nrn->p, &rn->p))
+ rib = NULL;
else
{
/* Identify appropriate route entry. */
@@ -593,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);
}
@@ -887,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;
@@ -921,7 +920,7 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr
}
stream_putw_at (s, 0, stream_get_endp (s));
- client->nh_last_upd_time = quagga_time(NULL);
+ client->nh_last_upd_time = quagga_monotime();
client->last_write_cmd = cmd;
return zebra_server_send_message(client);
}
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_snmp.c b/zebra/zebra_snmp.c
index 11fc0ef40d..3186ebf693 100644
--- a/zebra/zebra_snmp.c
+++ b/zebra/zebra_snmp.c
@@ -39,6 +39,7 @@
#include "zebra/rib.h"
#include "zebra/zserv.h"
+#include "zebra/zebra_vrf.h"
#define IPFWMIB 1,3,6,1,2,1,4,24
@@ -84,7 +85,7 @@
#define IPADDRESS ASN_IPADDRESS
#define OBJECTIDENTIFIER ASN_OBJECT_ID
-oid ipfw_oid [] = { IPFWMIB };
+static oid ipfw_oid [] = { IPFWMIB };
/* Hook functions. */
static u_char * ipFwNumber (struct variable *, oid [], size_t *,
@@ -96,7 +97,7 @@ static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
static u_char * ipCidrTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
-struct variable zebra_variables[] =
+static struct variable zebra_variables[] =
{
{0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
{IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
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 e9090cbed2..72d0ced658 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -29,19 +29,25 @@
#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 "zebra/zebra_static.h"
extern int allow_delete;
-static int do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi);
+static int do_show_ip_route(struct vty *vty, const char *vrf_name,
+ safi_t safi, u_char use_json);
static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn,
int mcast);
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
/* General function for static route. */
static int
zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd,
@@ -60,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)
@@ -111,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;
}
@@ -137,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;
}
@@ -158,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;
}
@@ -278,7 +288,7 @@ DEFUN (show_ip_rpf,
IP_STR
"Display RPF information for multicast source\n")
{
- return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST);
+ return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST, 0);
}
DEFUN (show_ip_rpf_addr,
@@ -1929,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);
@@ -1944,8 +1956,6 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
vty_out (vty, ", reject");
vty_out (vty, "%s", VTY_NEWLINE);
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
if (rib->type == ZEBRA_ROUTE_RIP
|| rib->type == ZEBRA_ROUTE_OSPF
|| rib->type == ZEBRA_ROUTE_ISIS
@@ -2048,12 +2058,151 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
}
static void
-vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
+vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib,
+ json_object *json)
{
struct nexthop *nexthop, *tnexthop;
int recursing;
int len = 0;
char buf[BUFSIZ];
+ json_object *json_nexthops = NULL;
+ json_object *json_nexthop = NULL;
+ json_object *json_route = NULL;
+
+ if (json)
+ {
+ json_route = json_object_new_object();
+ json_nexthops = json_object_new_array();
+
+ json_object_string_add(json_route, "prefix", prefix2str (&rn->p, buf, sizeof buf));
+ json_object_string_add(json_route, "protocol", zebra_route_string(rib->type));
+
+ if (rib->instance)
+ json_object_int_add(json_route, "instance", rib->instance);
+
+ if (rib->vrf_id)
+ json_object_int_add(json_route, "vrfId", rib->vrf_id);
+
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ json_object_boolean_true_add(json_route, "selected");
+
+ if (rib->type != ZEBRA_ROUTE_CONNECT && rib->type != ZEBRA_ROUTE_KERNEL)
+ {
+ json_object_int_add(json_route, "distance", rib->distance);
+ json_object_int_add(json_route, "metric", rib->metric);
+ }
+
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
+ json_object_boolean_true_add(json_route, "blackhole");
+
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
+ json_object_boolean_true_add(json_route, "reject");
+
+ if (rib->type == ZEBRA_ROUTE_RIP
+ || rib->type == ZEBRA_ROUTE_OSPF
+ || rib->type == ZEBRA_ROUTE_ISIS
+ || rib->type == ZEBRA_ROUTE_TABLE
+ || rib->type == ZEBRA_ROUTE_BGP)
+ {
+ time_t uptime;
+ struct tm *tm;
+
+ uptime = time (NULL);
+ uptime -= rib->uptime;
+ tm = gmtime (&uptime);
+
+ if (uptime < ONE_DAY_SECOND)
+ sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, tm->tm_min);
+ else
+ sprintf(buf, "%02dw%dd%02dh", tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+
+ json_object_string_add(json_route, "uptime", buf);
+ }
+
+ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
+ {
+ json_nexthop = json_object_new_object();
+
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ json_object_boolean_true_add(json_nexthop, "fib");
+
+ switch (nexthop->type)
+ {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ json_object_string_add(json_nexthop, "ip", inet_ntoa (nexthop->gate.ipv4));
+ json_object_string_add(json_nexthop, "afi", "ipv4");
+
+ if (nexthop->ifindex)
+ {
+ json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id));
+ }
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ json_object_string_add(json_nexthop, "ip", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
+ json_object_string_add(json_nexthop, "afi", "ipv6");
+
+ if (nexthop->ifindex)
+ {
+ json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id));
+ }
+ break;
+
+ case NEXTHOP_TYPE_IFINDEX:
+ json_object_boolean_true_add(json_nexthop, "directlyConnected");
+ json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ json_object_boolean_true_add(json_nexthop, "blackhole");
+ break;
+ default:
+ break;
+ }
+
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ json_object_boolean_true_add(json_nexthop, "active");
+
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ json_object_boolean_true_add(json_nexthop, "onLink");
+
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ json_object_boolean_true_add(json_nexthop, "recursive");
+
+ switch (nexthop->type)
+ {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (nexthop->src.ipv4.s_addr)
+ {
+ if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf))
+ json_object_string_add(json_nexthop, "source", buf);
+ }
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ {
+ if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf))
+ json_object_string_add(json_nexthop, "source", buf);
+ }
+ break;
+ default:
+ break;
+ }
+
+ json_object_array_add(json_nexthops, json_nexthop);
+ }
+
+ json_object_object_add(json_route, "nexthops", json_nexthops);
+ json_object_array_add(json, json_route);
+ return;
+ }
/* Nexthop information. */
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
@@ -2160,9 +2309,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
uptime -= rib->uptime;
tm = gmtime (&uptime);
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
if (uptime < ONE_DAY_SECOND)
vty_out (vty, ", %02d:%02d:%02d",
tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -2180,62 +2326,112 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
DEFUN (show_ip_route,
show_ip_route_cmd,
- "show ip route",
+ "show ip route {json}",
SHOW_STR
IP_STR
"IP routing table\n")
{
- return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST);
+ return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST, use_json(argc, argv));
}
static int
-do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi)
+do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi,
+ u_char use_json)
{
struct route_table *table;
struct route_node *rn;
struct rib *rib;
int first = 1;
struct zebra_vrf *zvrf = NULL;
+ char buf[BUFSIZ];
+ json_object *json = NULL;
+ json_object *json_prefix = NULL;
if (!(zvrf = zebra_vrf_list_lookup_by_name (vrf_name)))
{
- vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE);
+ if (use_json)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ else
+ vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE);
return CMD_SUCCESS;
}
if (zvrf->vrf_id == VRF_UNKNOWN)
{
- vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE);
+ if (use_json)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ else
+ vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE);
return CMD_SUCCESS;
}
table = zebra_vrf_table (AFI_IP, safi, zvrf->vrf_id);
if (! table)
- return CMD_SUCCESS;
+ {
+ if (use_json)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (use_json)
+ {
+ json = json_object_new_object();
+
+ /* Show all IPv4 routes. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ {
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (!json_prefix)
+ json_prefix = json_object_new_array();
+ vty_show_ip_route (vty, rn, rib, json_prefix);
+ }
+
+ if (json_prefix)
+ {
+ prefix2str (&rn->p, buf, sizeof buf);
+ json_object_object_add(json, buf, json_prefix);
+ json_prefix = NULL;
+ }
+ }
+
+ vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
+ json_object_free(json);
+ }
+ else
+ {
+ /* Show all IPv4 routes. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ {
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (first)
+ {
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
+ first = 0;
+ }
+ vty_show_ip_route (vty, rn, rib, NULL);
+ }
+ }
+ }
- /* Show all IPv4 routes. */
- for (rn = route_top (table); rn; rn = route_next (rn))
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V4_HEADER);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
return CMD_SUCCESS;
}
DEFUN (show_ip_route_vrf,
show_ip_route_vrf_cmd,
- "show ip route " VRF_CMD_STR,
+ "show ip route " VRF_CMD_STR " {json}",
SHOW_STR
IP_STR
"IP routing table\n"
VRF_CMD_HELP_STR)
{
- return do_show_ip_route (vty, argv[0], SAFI_UNICAST);
+ u_char uj = use_json(argc, argv);
+
+ if (argc == 1 && uj)
+ return do_show_ip_route (vty, NULL, SAFI_UNICAST, uj);
+ else
+ return do_show_ip_route (vty, argv[0], SAFI_UNICAST, uj);
}
DEFUN (show_ip_nht,
@@ -2430,7 +2626,7 @@ DEFUN (show_ip_route_tag,
vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -2490,7 +2686,7 @@ DEFUN (show_ip_route_prefix_longer,
vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -2542,7 +2738,7 @@ DEFUN (show_ip_route_supernets,
vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
}
return CMD_SUCCESS;
@@ -2600,7 +2796,7 @@ DEFUN (show_ip_route_protocol,
vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -2645,7 +2841,7 @@ DEFUN (show_ip_route_ospf_instance,
vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -3014,7 +3210,7 @@ DEFUN (show_ip_route_vrf_all,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -3068,7 +3264,7 @@ DEFUN (show_ip_route_vrf_all_tag,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -3124,7 +3320,7 @@ DEFUN (show_ip_route_vrf_all_prefix_longer,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -3177,7 +3373,7 @@ DEFUN (show_ip_route_vrf_all_supernets,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
}
vrf_header = 1;
@@ -3233,7 +3429,7 @@ DEFUN (show_ip_route_vrf_all_protocol,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -3541,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;
}
@@ -4544,7 +4740,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref_tag_vrf,
DEFUN (show_ipv6_route,
show_ipv6_route_cmd,
- "show ipv6 route",
+ "show ipv6 route {json}",
SHOW_STR
IP_STR
"IPv6 routing table\n")
@@ -4555,18 +4751,28 @@ DEFUN (show_ipv6_route,
int first = 1;
vrf_id_t vrf_id = VRF_DEFAULT;
struct zebra_vrf *zvrf = NULL;
+ char buf[BUFSIZ];
+ json_object *json = NULL;
+ json_object *json_prefix = NULL;
+ u_char uj = use_json(argc, argv);
- if (argc > 0)
+ if (argc > 0 && argv[0] && strcmp(argv[0], "json") != 0)
{
if (!(zvrf = zebra_vrf_list_lookup_by_name (argv[0])))
{
- vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE);
+ if (uj)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ else
+ vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE);
return CMD_SUCCESS;
}
if (zvrf->vrf_id == VRF_UNKNOWN)
{
- vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE);
+ if (uj)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ else
+ vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE);
return CMD_SUCCESS;
}
else
@@ -4575,25 +4781,60 @@ DEFUN (show_ipv6_route,
table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table)
- return CMD_SUCCESS;
+ {
+ if (uj)
+ vty_out (vty, "{}%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (uj)
+ {
+ json = json_object_new_object();
+
+ /* Show all IPv6 route. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ {
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (!json_prefix)
+ json_prefix = json_object_new_array();
+ vty_show_ip_route (vty, rn, rib, json_prefix);
+ }
+
+ if (json_prefix)
+ {
+ prefix2str (&rn->p, buf, sizeof buf);
+ json_object_object_add(json, buf, json_prefix);
+ json_prefix = NULL;
+ }
+ }
+
+ vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
+ json_object_free(json);
+ }
+ else
+ {
+ /* Show all IPv6 route. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ {
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (first)
+ {
+ vty_out (vty, SHOW_ROUTE_V6_HEADER);
+ first = 0;
+ }
+ vty_show_ip_route (vty, rn, rib, NULL);
+ }
+ }
+ }
- /* Show all IPv6 route. */
- for (rn = route_top (table); rn; rn = route_next (rn))
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (first)
- {
- vty_out (vty, SHOW_ROUTE_V6_HEADER);
- first = 0;
- }
- vty_show_ip_route (vty, rn, rib);
- }
return CMD_SUCCESS;
}
ALIAS (show_ipv6_route,
show_ipv6_route_vrf_cmd,
- "show ipv6 route " VRF_CMD_STR,
+ "show ipv6 route " VRF_CMD_STR " {json}",
SHOW_STR
IP_STR
"IPv6 routing table\n"
@@ -4639,7 +4880,7 @@ DEFUN (show_ipv6_route_tag,
vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -4699,7 +4940,7 @@ DEFUN (show_ipv6_route_prefix_longer,
vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -4757,7 +4998,7 @@ DEFUN (show_ipv6_route_protocol,
vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -4983,7 +5224,7 @@ DEFUN (show_ipv6_mroute,
vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
return CMD_SUCCESS;
}
@@ -5033,7 +5274,7 @@ DEFUN (show_ipv6_route_vrf_all,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -5087,7 +5328,7 @@ DEFUN (show_ipv6_route_vrf_all_tag,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -5144,7 +5385,7 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -5199,7 +5440,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol,
vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE);
vrf_header = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
vrf_header = 1;
}
@@ -5343,7 +5584,7 @@ DEFUN (show_ipv6_mroute_vrf_all,
vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
- vty_show_ip_route (vty, rn, rib);
+ vty_show_ip_route (vty, rn, rib, NULL);
}
}
return CMD_SUCCESS;
diff --git a/zebra/zserv.c b/zebra/zserv.c
index daecaf5e10..020a252371 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -97,7 +97,7 @@ zserv_flush_data(struct thread *thread)
break;
}
- client->last_write_time = quagga_time(NULL);
+ client->last_write_time = quagga_monotime();
return 0;
}
@@ -131,7 +131,7 @@ zebra_server_send_message(struct zserv *client)
break;
}
- client->last_write_time = quagga_time(NULL);
+ client->last_write_time = quagga_monotime();
return 0;
}
@@ -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);
}
@@ -864,7 +849,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
s = client->ibuf;
- client->nh_reg_time = quagga_time(NULL);
+ client->nh_reg_time = quagga_monotime();
while (l < length)
{
@@ -952,7 +937,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
rnh = zebra_lookup_rnh(&p, zvrf->vrf_id, type);
if (rnh)
{
- client->nh_dereg_time = quagga_time(NULL);
+ client->nh_dereg_time = quagga_monotime();
zebra_remove_rnh_client(rnh, client, type);
}
}
@@ -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 */
@@ -1832,7 +1833,7 @@ static void
zebra_client_close (struct zserv *client)
{
/* Send client de-registration to BFD */
- zebra_ptm_bfd_client_deregister(client);
+ zebra_ptm_bfd_client_deregister(client->proto);
/* Cleanup any registered nexthops - across all VRFs. */
zebra_client_close_cleanup_rnh (client);
@@ -1867,7 +1868,7 @@ zebra_client_close (struct zserv *client)
/* Free client structure. */
listnode_delete (zebrad.client_list, client);
- XFREE (0, client);
+ XFREE (MTYPE_TMP, client);
}
/* Make new client. */
@@ -1878,7 +1879,7 @@ zebra_client_create (int sock)
int i;
afi_t afi;
- client = XCALLOC (0, sizeof (struct zserv));
+ client = XCALLOC (MTYPE_TMP, sizeof (struct zserv));
/* Make client input/output buffer. */
client->sock = sock;
@@ -1889,7 +1890,7 @@ zebra_client_create (int sock)
/* Set table number. */
client->rtm_table = zebrad.rtm_table_default;
- client->connect_time = quagga_time(NULL);
+ client->connect_time = quagga_monotime();
/* Initialize flags */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
@@ -2015,7 +2016,7 @@ zebra_client_read (struct thread *thread)
zlog_debug ("zebra message received [%s] %d in VRF %u",
zserv_command_string (command), length, vrf_id);
- client->last_read_time = quagga_time(NULL);
+ client->last_read_time = quagga_monotime();
client->last_read_cmd = command;
zvrf = zebra_vrf_lookup (vrf_id);
@@ -2325,7 +2326,7 @@ zserv_time_buf(time_t *time1, char *buf, int buflen)
return (buf);
}
- now = quagga_time(NULL);
+ now = quagga_monotime();
now -= *time1;
tm = gmtime(&now);
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);