summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am94
-rw-r--r--babeld/babeld.conf.sample4
-rw-r--r--bgpd/bgp_attr.c16
-rw-r--r--bgpd/bgp_attr_evpn.c2
-rw-r--r--bgpd/bgp_damp.c2
-rw-r--r--bgpd/bgp_evpn.c14
-rw-r--r--bgpd/bgp_evpn_private.h2
-rw-r--r--bgpd/bgp_fsm.c8
-rw-r--r--bgpd/bgp_open.c17
-rw-r--r--bgpd/bgp_open.h4
-rw-r--r--bgpd/bgp_packet.c15
-rw-r--r--bgpd/bgp_rd.c2
-rw-r--r--bgpd/bgp_route.c6
-rw-r--r--bgpd/bgp_updgrp_packet.c4
-rw-r--r--bgpd/bgp_vty.c14
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/bgpd.c18
-rw-r--r--bgpd/bgpd.h9
-rw-r--r--bgpd/rfapi/rfapi.c4
-rw-r--r--bgpd/rfapi/rfapi_import.c8
-rw-r--r--bgpd/rfapi/rfapi_monitor.c4
-rw-r--r--bgpd/rfapi/rfapi_rib.c2
-rw-r--r--bgpd/rfapi/rfapi_vty.c4
-rw-r--r--common.am38
-rwxr-xr-xconfigure.ac350
-rw-r--r--doc/babeld.texi4
-rw-r--r--eigrpd/eigrp_dump.c66
-rw-r--r--eigrpd/eigrp_packet.c13
-rw-r--r--eigrpd/eigrp_update.c130
-rw-r--r--fpm/.gitignore2
-rw-r--r--fpm/Makefile10
-rw-r--r--fpm/Makefile.am29
-rw-r--r--fpm/fpm.proto2
-rw-r--r--fpm/subdir.am23
-rw-r--r--isisd/Makefile.am12
-rw-r--r--isisd/dict.c6
-rw-r--r--isisd/isis_adjacency.c89
-rw-r--r--isisd/isis_adjacency.h15
-rw-r--r--isisd/isis_bpf.c10
-rw-r--r--isisd/isis_circuit.c5
-rw-r--r--isisd/isis_circuit.h1
-rw-r--r--isisd/isis_common.h10
-rw-r--r--isisd/isis_constants.h4
-rw-r--r--isisd/isis_csm.c1
-rw-r--r--isisd/isis_dr.c1
-rw-r--r--isisd/isis_dynhn.c29
-rw-r--r--isisd/isis_dynhn.h4
-rw-r--r--isisd/isis_events.c1
-rw-r--r--isisd/isis_lsp.c1993
-rw-r--r--isisd/isis_lsp.h42
-rw-r--r--isisd/isis_main.c1
-rw-r--r--isisd/isis_memory.c2
-rw-r--r--isisd/isis_memory.h2
-rw-r--r--isisd/isis_misc.c250
-rw-r--r--isisd/isis_misc.h10
-rw-r--r--isisd/isis_mt.c212
-rw-r--r--isisd/isis_mt.h47
-rw-r--r--isisd/isis_pdu.c2607
-rw-r--r--isisd/isis_pdu.h66
-rw-r--r--isisd/isis_redist.c1
-rw-r--r--isisd/isis_route.c15
-rw-r--r--isisd/isis_routemap.c1
-rw-r--r--isisd/isis_spf.c576
-rw-r--r--isisd/isis_spf.h49
-rw-r--r--isisd/isis_te.c402
-rw-r--r--isisd/isis_te.h11
-rw-r--r--isisd/isis_tlv.c1453
-rw-r--r--isisd/isis_tlv.h340
-rw-r--r--isisd/isis_tlvs.c3090
-rw-r--r--isisd/isis_tlvs.h308
-rw-r--r--isisd/isis_zebra.c1
-rw-r--r--isisd/isisd.c46
-rw-r--r--isisd/isisd.h2
-rw-r--r--isisd/iso_checksum.c2
-rw-r--r--ldpd/address.c6
-rw-r--r--ldpd/l2vpn.c65
-rw-r--r--ldpd/lde.c60
-rw-r--r--ldpd/lde.h1
-rw-r--r--ldpd/lde_lib.c10
-rw-r--r--ldpd/ldp.h3
-rw-r--r--ldpd/ldp_vty_cmds.c74
-rw-r--r--ldpd/ldp_zebra.c78
-rw-r--r--ldpd/ldpd.c41
-rw-r--r--ldpd/ldpd.h37
-rw-r--r--ldpd/neighbor.c7
-rw-r--r--lib/.gitignore2
-rw-r--r--lib/Makefile10
-rw-r--r--lib/Makefile.am155
-rw-r--r--lib/command.c3
-rw-r--r--lib/command.h2
-rw-r--r--lib/command_graph.c4
-rw-r--r--lib/command_lex.l4
-rw-r--r--lib/command_parse.y4
-rw-r--r--lib/defun_lex.l2
-rw-r--r--lib/hash.c45
-rw-r--r--lib/hash.h3
-rw-r--r--lib/libospf.h2
-rw-r--r--lib/log.c6
-rw-r--r--lib/monotime.h4
-rw-r--r--lib/prefix.c18
-rw-r--r--lib/prefix.h32
-rw-r--r--lib/pw.h52
-rw-r--r--lib/sbuf.c107
-rw-r--r--lib/sbuf.h77
-rw-r--r--lib/sockunion.c14
-rw-r--r--lib/subdir.am263
-rw-r--r--lib/table.c16
-rw-r--r--lib/thread.c99
-rw-r--r--lib/thread.h1
-rw-r--r--lib/vty.c35
-rw-r--r--lib/vty.h5
-rw-r--r--lib/zclient.c88
-rw-r--r--lib/zclient.h41
-rw-r--r--lib/zebra.h109
-rw-r--r--m4/Makefile.am1
-rw-r--r--nhrpd/nhrp_cache.c2
-rw-r--r--nhrpd/nhrp_main.c2
-rw-r--r--nhrpd/nhrp_route.c38
-rw-r--r--ospf6d/ospf6_asbr.c3
-rw-r--r--ospf6d/ospf6_lsa.c7
-rw-r--r--ospf6d/ospf6_lsdb.c5
-rw-r--r--ospf6d/ospf6_memory.c1
-rw-r--r--ospf6d/ospf6_memory.h1
-rw-r--r--ospf6d/ospf6_route.c53
-rw-r--r--ospf6d/ospf6_route.h1
-rw-r--r--ospf6d/ospf6_spf.c1
-rw-r--r--ospfd/ospf_dump.c16
-rw-r--r--ospfd/ospf_opaque.c4
-rw-r--r--ospfd/ospf_opaque.h42
-rw-r--r--ospfd/ospf_ri.c279
-rw-r--r--ospfd/ospf_ri.h42
-rw-r--r--ospfd/ospf_te.c343
-rw-r--r--ospfd/ospf_te.h138
-rw-r--r--ospfd/ospf_vty.c359
-rw-r--r--ospfd/ospf_zebra.c11
-rw-r--r--ospfd/ospfd.c12
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--pimd/Makefile.am5
-rw-r--r--pimd/WHY_SSM32
-rw-r--r--pimd/pim_assert.c11
-rw-r--r--pimd/pim_bfd.c1
-rw-r--r--pimd/pim_cmd.c2486
-rw-r--r--pimd/pim_cmd.h9
-rw-r--r--pimd/pim_hello.c7
-rw-r--r--pimd/pim_iface.c373
-rw-r--r--pimd/pim_iface.h31
-rw-r--r--pimd/pim_ifchannel.c191
-rw-r--r--pimd/pim_ifchannel.h13
-rw-r--r--pimd/pim_igmp.c11
-rw-r--r--pimd/pim_igmpv3.c7
-rw-r--r--pimd/pim_instance.c218
-rw-r--r--pimd/pim_instance.h100
-rw-r--r--pimd/pim_join.c34
-rw-r--r--pimd/pim_jp_agg.c7
-rw-r--r--pimd/pim_main.c2
-rw-r--r--pimd/pim_mroute.c325
-rw-r--r--pimd/pim_mroute.h12
-rw-r--r--pimd/pim_msdp.c340
-rw-r--r--pimd/pim_msdp.h58
-rw-r--r--pimd/pim_msdp_packet.c72
-rw-r--r--pimd/pim_msdp_packet.h2
-rw-r--r--pimd/pim_msdp_socket.c47
-rw-r--r--pimd/pim_msdp_socket.h2
-rw-r--r--pimd/pim_msg.c7
-rw-r--r--pimd/pim_neighbor.c6
-rw-r--r--pimd/pim_nht.c645
-rw-r--r--pimd/pim_nht.h28
-rw-r--r--pimd/pim_oil.c62
-rw-r--r--pimd/pim_oil.h9
-rw-r--r--pimd/pim_pim.c69
-rw-r--r--pimd/pim_register.c69
-rw-r--r--pimd/pim_register.h2
-rw-r--r--pimd/pim_rp.c319
-rw-r--r--pimd/pim_rp.h42
-rw-r--r--pimd/pim_rpf.c57
-rw-r--r--pimd/pim_rpf.h10
-rw-r--r--pimd/pim_ssm.c27
-rw-r--r--pimd/pim_ssm.h11
-rw-r--r--pimd/pim_ssmpingd.c52
-rw-r--r--pimd/pim_ssmpingd.h10
-rw-r--r--pimd/pim_static.c35
-rw-r--r--pimd/pim_static.h13
-rw-r--r--pimd/pim_upstream.c278
-rw-r--r--pimd/pim_upstream.h58
-rw-r--r--pimd/pim_util.c6
-rw-r--r--pimd/pim_vty.c266
-rw-r--r--pimd/pim_vty.h1
-rw-r--r--pimd/pim_zebra.c485
-rw-r--r--pimd/pim_zebra.h10
-rw-r--r--pimd/pim_zlookup.c156
-rw-r--r--pimd/pim_zlookup.h3
-rw-r--r--pimd/pimd.c196
-rw-r--r--pimd/pimd.h45
-rw-r--r--pimd/test_igmpv3_join.c3
-rw-r--r--pkgsrc/Makefile.am3
-rw-r--r--python/Makefile.am3
-rw-r--r--qpb/.gitignore2
-rw-r--r--qpb/Makefile10
-rw-r--r--qpb/Makefile.am30
-rw-r--r--qpb/qpb.proto4
-rw-r--r--qpb/qpb_allocator.c3
-rw-r--r--qpb/subdir.am26
-rw-r--r--redhat/Makefile.am5
-rw-r--r--redhat/frr.spec.in3
-rw-r--r--ripd/rip_peer.c4
-rw-r--r--ripngd/ripng_peer.c4
-rw-r--r--snapcraft/Makefile.am8
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/Makefile.am21
-rw-r--r--tests/bgpd/test_capability.c2
-rw-r--r--tests/bgpd/test_capability.py2
-rw-r--r--tests/bgpd/test_mp_attr.c2
-rw-r--r--tests/isisd/.gitignore1
-rw-r--r--tests/isisd/test_fuzz_isis_tlv.c188
-rw-r--r--tests/isisd/test_fuzz_isis_tlv.py6
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin0 -> 232370 bytes
-rw-r--r--vtysh/Makefile.am1
-rwxr-xr-xvtysh/extract.pl.in2
-rw-r--r--vtysh/vtysh.c32
-rw-r--r--vtysh/vtysh.h2
-rw-r--r--vtysh/vtysh_config.c2
-rw-r--r--watchfrr/watchfrr.c2
-rw-r--r--zebra/.gitignore2
-rw-r--r--zebra/Makefile10
-rw-r--r--zebra/Makefile.am96
-rw-r--r--zebra/debug.c25
-rw-r--r--zebra/debug.h4
-rw-r--r--zebra/if_ioctl.c4
-rw-r--r--zebra/if_ioctl_solaris.c4
-rw-r--r--zebra/if_netlink.c31
-rw-r--r--zebra/if_sysctl.c4
-rw-r--r--zebra/interface.c15
-rw-r--r--zebra/ioctl.c4
-rw-r--r--zebra/ioctl_solaris.c4
-rw-r--r--zebra/ipforward_proc.c4
-rw-r--r--zebra/ipforward_solaris.c5
-rw-r--r--zebra/ipforward_sysctl.c5
-rw-r--r--zebra/kernel_netlink.c9
-rw-r--r--zebra/kernel_socket.c6
-rw-r--r--zebra/main.c1
-rw-r--r--zebra/rib.h1
-rw-r--r--zebra/rt.h5
-rw-r--r--zebra/rt_netlink.c42
-rw-r--r--zebra/rt_socket.c13
-rw-r--r--zebra/rtread_getmsg.c4
-rw-r--r--zebra/rtread_netlink.c4
-rw-r--r--zebra/rtread_sysctl.c4
-rw-r--r--zebra/subdir.am133
-rw-r--r--zebra/zebra_fpm_netlink.c4
-rw-r--r--zebra/zebra_mpls.c4
-rw-r--r--zebra/zebra_mpls_netlink.c5
-rw-r--r--zebra/zebra_mpls_null.c4
-rw-r--r--zebra/zebra_mpls_openbsd.c95
-rw-r--r--zebra/zebra_mroute.c17
-rw-r--r--zebra/zebra_pw.c533
-rw-r--r--zebra/zebra_pw.h75
-rw-r--r--zebra/zebra_rib.c13
-rw-r--r--zebra/zebra_rnh.c85
-rw-r--r--zebra/zebra_rnh.h4
-rw-r--r--zebra/zebra_routemap.c12
-rw-r--r--zebra/zebra_static.c121
-rw-r--r--zebra/zebra_static.h12
-rw-r--r--zebra/zebra_vrf.c47
-rw-r--r--zebra/zebra_vrf.h6
-rw-r--r--zebra/zebra_vty.c42
-rw-r--r--zebra/zebra_vxlan.c37
-rw-r--r--zebra/zserv.c164
-rw-r--r--zebra/zserv.h3
268 files changed, 14062 insertions, 10993 deletions
diff --git a/Makefile.am b/Makefile.am
index 0092ba8c10..7cfe4a97e3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,23 +1,95 @@
## Process this file with automake to produce Makefile.in.
-SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \
+AUTOMAKE_OPTIONS = subdir-objects 1.12
+include common.am
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
+AM_CFLAGS = $(WERROR)
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+LIBCAP = @LIBCAP@
+
+EXTRA_DIST =
+BUILT_SOURCES =
+CLEANFILES =
+
+examplesdir = $(exampledir)
+
+bin_PROGRAMS =
+sbin_PROGRAMS =
+noinst_PROGRAMS =
+noinst_HEADERS =
+noinst_LIBRARIES =
+lib_LTLIBRARIES =
+module_LTLIBRARIES =
+pkginclude_HEADERS =
+dist_examples_DATA =
+
+include lib/subdir.am
+include zebra/subdir.am
+include qpb/subdir.am
+include fpm/subdir.am
+
+SUBDIRS = . @LIBRFP@ @RFPTEST@ \
@BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
@ISISD@ @PIMD@ @NHRPD@ @EIGRPD@ @BABELD@ \
- @WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
- redhat @SOLARIS@ tests tools snapcraft
+ @WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ \
+ @SOLARIS@ tests tools
-DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
- isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
+DIST_SUBDIRS = . bgpd ripd ripngd ospfd ospf6d ldpd \
+ isisd watchfrr vtysh ospfclient doc tests \
solaris pimd nhrpd eigrpd bgpd/rfp-example/librfp \
- bgpd/rfp-example/rfptest tools snapcraft babeld python \
+ bgpd/rfp-example/rfptest tools babeld \
# end
-EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \
+if PKGSRC
+rcdir=@pkgsrcrcdir@
+rc_SCRIPTS = \
+ pkgsrc/bgpd.sh \
+ pkgsrc/ospf6d.sh \
+ pkgsrc/ospfd.sh \
+ pkgsrc/ripd.sh \
+ pkgsrc/ripngd.sh \
+ pkgsrc/zebra.sh \
+ # end
+endif
+
+EXTRA_DIST += \
+ REPORTING-BUGS \
+ SERVICES \
+ aclocal.m4 \
update-autotools \
- vtysh/Makefile.in vtysh/Makefile.am \
- tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
- tools/zebra.el tools/multiple-bgpd.sh
+ m4/README.txt \
+ \
+ python/clidef.py \
+ python/clippy/__init__.py \
+ \
+ redhat/frr.init \
+ redhat/frr.service \
+ redhat/daemons \
+ redhat/frr.logrotate \
+ redhat/frr.pam \
+ redhat/frr.spec \
+ redhat/README.rpm_build.md \
+ \
+ snapcraft/snapcraft.yaml \
+ snapcraft/README.snap_build.md \
+ snapcraft/README.usage.md \
+ snapcraft/extra_version_info.txt \
+ snapcraft/scripts \
+ snapcraft/defaults \
+ snapcraft/helpers \
+ snapcraft/snap \
+ \
+ tools/multiple-bgpd.sh \
+ tools/rrcheck.pl \
+ tools/rrlookup.pl \
+ tools/zc.pl \
+ tools/zebra.el \
+ \
+ vtysh/Makefile.am \
+ vtysh/Makefile.in \
+ # end
ACLOCAL_AMFLAGS = -I m4
-noinst_HEADERS = defaults.h
+noinst_HEADERS += defaults.h
diff --git a/babeld/babeld.conf.sample b/babeld/babeld.conf.sample
index a4924ec7b7..a77453a734 100644
--- a/babeld/babeld.conf.sample
+++ b/babeld/babeld.conf.sample
@@ -9,8 +9,8 @@ debug babel common
router babel
! network wlan0
! network eth0
-! redistribute kernel
-! no redistribute static
+! redistribute ipv4 kernel
+! no redistribute ipv6 static
! The defaults are fine for a wireless interface
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ef32b9cf92..dd18797637 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -566,12 +566,6 @@ unsigned int attrhash_key_make(void *p)
MIX(attr->nexthop.s_addr);
MIX(attr->med);
MIX(attr->local_pref);
-
- key += attr->origin;
- key += attr->nexthop.s_addr;
- key += attr->med;
- key += attr->local_pref;
-
MIX(attr->aggregator_as);
MIX(attr->aggregator_addr.s_addr);
MIX(attr->weight);
@@ -1677,7 +1671,8 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
{
iana_afi_t pkt_afi;
afi_t afi;
- safi_t pkt_safi, safi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
bgp_size_t nlri_len;
size_t start;
struct stream *s;
@@ -1826,7 +1821,8 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct stream *s;
iana_afi_t pkt_afi;
afi_t afi;
- safi_t pkt_safi, safi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
u_int16_t withdraw_len;
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -2593,7 +2589,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
{
size_t sizep;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
afi_t nh_afi;
/* Set extended bit always to encode the attribute length as 2 bytes */
@@ -3280,7 +3276,7 @@ size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
{
unsigned long attrlen_pnt;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
/* Set extended bit always to encode the attribute length as 2 bytes */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index cd6b87b299..2f0b566ccf 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -42,7 +42,7 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
- memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
+ memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
if (!attr->ecommunity)
attr->ecommunity = ecommunity_new();
ecommunity_add_val(attr->ecommunity, &routermac_ecom);
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index bd3ae27c05..36ffb0e9c5 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -543,8 +543,6 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
reuse_time = 0;
/* Making formatted timer strings. */
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
if (reuse_time == 0) {
if (use_json)
json_object_int_add(json, "reuseTimerMsecs", 0);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index f0081e6d02..fe311832a2 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -351,7 +351,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
- stream_put(s, &p->prefix.mac.octet, ETHER_ADDR_LEN); /* Mac Addr */
+ stream_put(s, &p->prefix.mac.octet, ETH_ALEN); /* Mac Addr */
/* IP address length and IP address, if any. */
if (IS_EVPN_PREFIX_IPADDR_NONE(p))
stream_putl(s, 0);
@@ -1812,9 +1812,9 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
macaddr_len = *pfx++;
/* Get the MAC Addr */
- if (macaddr_len == (ETHER_ADDR_LEN * 8)) {
- memcpy(&p.prefix.mac.octet, pfx, ETHER_ADDR_LEN);
- pfx += ETHER_ADDR_LEN;
+ if (macaddr_len == (ETH_ALEN * 8)) {
+ memcpy(&p.prefix.mac.octet, pfx, ETH_ALEN);
+ pfx += ETH_ALEN;
} else {
zlog_err(
"%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d",
@@ -2186,7 +2186,7 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
} else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (IS_EVPN_PREFIX_IPADDR_NONE(p))
snprintf(buf, len, "[%d]:[0]:[0]:[%d]:[%s]",
- p->prefix.route_type, 8 * ETHER_ADDR_LEN,
+ p->prefix.route_type, 8 * ETH_ALEN,
prefix_mac2str(&p->prefix.mac, buf1,
sizeof(buf1)));
else {
@@ -2195,7 +2195,7 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
: AF_INET6;
snprintf(buf, len, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]",
- p->prefix.route_type, 8 * ETHER_ADDR_LEN,
+ p->prefix.route_type, 8 * ETH_ALEN,
prefix_mac2str(&p->prefix.mac, buf1,
sizeof(buf1)),
family == AF_INET ? IPV4_MAX_BITLEN
@@ -2237,7 +2237,7 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
stream_put(s, prd->val, 8); /* RD */
stream_put(s, 0, 10); /* ESI */
stream_putl(s, 0); /* Ethernet Tag ID */
- stream_putc(s, 8 * ETHER_ADDR_LEN); /* Mac Addr Len - bits */
+ stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */
stream_putc(s, 8 * ipa_len); /* IP address Length */
if (ipa_len)
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 816a7df98c..095dfa1b15 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -174,7 +174,7 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
p->family = AF_ETHERNET;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
- memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN);
+ memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN);
p->prefix.ip.ipa_type = IPADDR_NONE;
if (ip)
memcpy(&p->prefix.ip, ip, sizeof(*ip));
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index cf1cb18689..b609abac69 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -488,7 +488,7 @@ static int bgp_graceful_restart_timer_expire(struct thread *thread)
/* NSF delete stale route */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
+ for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
@@ -521,7 +521,7 @@ static int bgp_graceful_stale_timer_expire(struct thread *thread)
/* NSF delete stale route */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
+ for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
@@ -1022,7 +1022,7 @@ int bgp_stop(struct peer *peer)
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST;
- safi < SAFI_RESERVED_4; safi++)
+ safi <= SAFI_MPLS_VPN; safi++)
peer->nsf[afi][safi] = 0;
}
@@ -1425,7 +1425,7 @@ static int bgp_establish(struct peer *peer)
/* graceful restart */
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
if (peer->afc_nego[afi][safi]
&& CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
&& CHECK_FLAG(peer->af_cap[afi][safi],
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index b18a4b7c46..3ee865e3ba 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -271,7 +271,7 @@ static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)
}
static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi,
- safi_t safi, u_char type,
+ iana_safi_t safi, u_char type,
u_char mode)
{
if (bgp_debug_neighbor_events(peer))
@@ -298,7 +298,8 @@ static int bgp_capability_orf_entry(struct peer *peer,
u_char num;
iana_afi_t pkt_afi;
afi_t afi;
- safi_t pkt_safi, safi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
u_char type;
u_char mode;
u_int16_t sm_cap = 0; /* capability send-mode receive */
@@ -466,7 +467,7 @@ static int bgp_capability_restart(struct peer *peer,
afi_t afi;
safi_t safi;
iana_afi_t pkt_afi = stream_getw(s);
- safi_t pkt_safi = stream_getc(s);
+ iana_safi_t pkt_safi = stream_getc(s);
u_char flag = stream_getc(s);
/* Convert AFI, SAFI to internal values, check. */
@@ -543,7 +544,7 @@ static int bgp_capability_addpath(struct peer *peer,
afi_t afi;
safi_t safi;
iana_afi_t pkt_afi = stream_getw(s);
- safi_t pkt_safi = stream_getc(s);
+ iana_safi_t pkt_safi = stream_getc(s);
u_char send_receive = stream_getc(s);
if (bgp_debug_neighbor_events(peer))
@@ -600,7 +601,8 @@ static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
while (stream_get_getp(s) + 6 <= end) {
iana_afi_t pkt_afi = stream_getw(s);
afi_t afi;
- safi_t safi, pkt_safi = stream_getw(s);
+ iana_safi_t pkt_safi = stream_getw(s);
+ safi_t safi;
iana_afi_t pkt_nh_afi = stream_getw(s);
afi_t nh_afi;
@@ -1199,7 +1201,7 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
unsigned long numberp;
int number_of_orfs = 0;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -1264,7 +1266,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
unsigned long cp, capp, rcapp;
iana_afi_t pkt_afi;
afi_t afi;
- safi_t safi, pkt_safi;
+ safi_t safi;
+ iana_safi_t pkt_safi;
as_t local_as;
u_int32_t restart_time;
u_char afi_safi_count = 0;
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index cbd32116b4..83b79a589a 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -29,9 +29,9 @@ struct capability_header {
/* Generic MP capability data */
struct capability_mp_data {
- iana_afi_t afi;
+ uint16_t afi; /* iana_afi_t */
u_char reserved;
- safi_t safi;
+ uint8_t safi; /* iana_safi_t */
};
struct capability_as4 {
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index e92f2d6977..003fbaff63 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -142,7 +142,7 @@ static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi,
{
struct stream *s;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
if (DISABLE_BGP_ANNOUNCE)
return NULL;
@@ -671,7 +671,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_filter *filter;
int orf_refresh = 0;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
if (DISABLE_BGP_ANNOUNCE)
return;
@@ -761,7 +761,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
{
struct stream *s;
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -1338,8 +1338,9 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
packet);
case SAFI_EVPN:
return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw);
+ default:
+ return -1;
}
- return -1;
}
/* Parse BGP Update packet and make attribute object. */
@@ -1697,7 +1698,8 @@ static void bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
{
iana_afi_t pkt_afi;
afi_t afi;
- safi_t pkt_safi, safi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
struct stream *s;
struct peer_af *paf;
struct update_group *updgrp;
@@ -1965,7 +1967,8 @@ static int bgp_capability_msg_parse(struct peer *peer, u_char *pnt,
u_char action;
iana_afi_t pkt_afi;
afi_t afi;
- safi_t pkt_safi, safi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
end = pnt + length;
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c
index fd01693942..a15828bd36 100644
--- a/bgpd/bgp_rd.c
+++ b/bgpd/bgp_rd.c
@@ -98,7 +98,7 @@ void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
{
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
rd_vnc_eth->local_nve_id = pnt[1];
- memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
+ memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETH_ALEN);
}
#endif
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b554aeb32b..e4e421510f 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2078,7 +2078,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
vnc_import_bgp_add_route(bgp, p, old_select);
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
#endif
- if (bgp_fibupd_safi(safi) && !bgp->name
+ if (bgp_fibupd_safi(safi)
&& !bgp_option_check(BGP_OPT_NO_FIB)
&& new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_NORMAL)
@@ -2288,7 +2288,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
int always)
{
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
return 0;
@@ -4775,7 +4775,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
}
if (routermac) {
bgp_static->router_mac =
- XCALLOC(MTYPE_ATTR, ETHER_ADDR_LEN + 1);
+ XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
prefix_str2mac(routermac,
bgp_static->router_mac);
}
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 1a23a36e91..692db32fa4 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -845,7 +845,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
send_attr_str);
if (!stream_empty(snlri)) {
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
pkt_afi = afi_int2iana(afi);
pkt_safi = safi_int2iana(safi);
@@ -989,7 +989,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
/* If first time, format the MP_UNREACH header */
if (first_time) {
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
pkt_afi = afi_int2iana(afi);
pkt_safi = safi_int2iana(safi);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 65a1473f75..0220a7e55d 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -78,6 +78,10 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
case SAFI_MPLS_VPN:
return BGP_VPNV4_NODE;
break;
+ default:
+ /* not expected */
+ return BGP_IPV4_NODE;
+ break;
}
break;
case AFI_IP6:
@@ -94,6 +98,10 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
case SAFI_MPLS_VPN:
return BGP_VPNV6_NODE;
break;
+ default:
+ /* not expected */
+ return BGP_IPV4_NODE;
+ break;
}
break;
case AFI_L2VPN:
@@ -7079,12 +7087,6 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
json);
}
safi++;
- if (safi == SAFI_RESERVED_4
- || safi
- == SAFI_RESERVED_5) /* handle special
- cases to match
- zebra.h */
- safi++;
if (!safi_wildcard)
safi = SAFI_MAX;
}
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 4870e54aec..5071be909e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2125,7 +2125,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
memset(&ip, 0, sizeof(ip));
s = zclient->ibuf;
vni = stream_getl(s);
- stream_get(&mac.octet, s, ETHER_ADDR_LEN);
+ stream_get(&mac.octet, s, ETH_ALEN);
ipa_len = stream_getl(s);
if (ipa_len != 0 && ipa_len != IPV4_MAX_BYTELEN
&& ipa_len != IPV6_MAX_BYTELEN) {
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a0e2d6749a..d30def0f07 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -611,8 +611,8 @@ int bgp_listen_limit_unset(struct bgp *bgp)
return 0;
}
-int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi,
- safi_t *safi)
+int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
+ afi_t *afi, safi_t *safi)
{
/* Map from IANA values to internal values, return error if
* values are unrecognized.
@@ -626,7 +626,7 @@ int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi,
}
int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi,
- safi_t *pkt_safi)
+ iana_safi_t *pkt_safi)
{
/* Map from internal values to IANA values, return error if
* internal values are bad (unexpected).
@@ -746,7 +746,7 @@ static unsigned int peer_hash_key_make(void *p)
return sockunion_hash(&peer->su);
}
-static int peer_hash_cmp(const void *p1, const void *p2)
+static int peer_hash_same(const void *p1, const void *p2)
{
const struct peer *peer1 = p1;
const struct peer *peer2 = p2;
@@ -1842,7 +1842,7 @@ static void peer_nsf_stop(struct peer *peer)
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
+ for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
peer->nsf[afi][safi] = 0;
if (peer->t_gr_restart) {
@@ -2757,7 +2757,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
bgp->peer = list_new();
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
- bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_cmp, NULL);
+ bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
+ bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
bgp->group = list_new();
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
@@ -6109,11 +6110,6 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
uptime1 -= uptime2;
tm = gmtime(&uptime1);
-/* Making formatted timer strings. */
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
-#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
-
if (uptime1 < ONE_DAY_SECOND)
snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
tm->tm_sec);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 67b8289c70..208a4e4b4e 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -36,6 +36,7 @@
#include "bitfield.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
+#define BGP_PEER_MAX_HASH_SIZE 16384
/* Default interval for IPv6 RAs when triggered by BGP unnumbered neighbor. */
#define BGP_UNNUM_DEFAULT_RA_INTERVAL 10
@@ -922,10 +923,10 @@ DECLARE_QOBJ_TYPE(peer)
stream. */
struct bgp_nlri {
/* AFI. */
- afi_t afi;
+ uint16_t afi; /* iana_afi_t */
/* SAFI. */
- safi_t safi;
+ uint8_t safi; /* iana_safi_t */
/* Pointer to NLRI byte stream. */
u_char *nlri;
@@ -1381,10 +1382,10 @@ extern void bgp_route_map_terminate(void);
extern int peer_cmp(struct peer *p1, struct peer *p2);
-extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi,
+extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
afi_t *afi, safi_t *safi);
extern int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi,
- iana_afi_t *pkt_afi, safi_t *pkt_safi);
+ iana_afi_t *pkt_afi, iana_safi_t *pkt_safi);
extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t);
extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t);
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index ab71eda126..477716cafb 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -1568,7 +1568,7 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target,
if (l2o) {
if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet,
- ETHER_ADDR_LEN)) {
+ ETH_ALEN)) {
eth_is_0 = 1;
}
/* per t/c Paul/Lou 151022 */
@@ -3416,7 +3416,7 @@ DEFUN (debug_rfapi_query_vn_un_l2o,
/* construct option chain */
memset(valbuf, 0, sizeof(valbuf));
- memcpy(valbuf, &l2o_buf.macaddr.octet, ETHER_ADDR_LEN);
+ memcpy(valbuf, &l2o_buf.macaddr.octet, ETH_ALEN);
valbuf[11] = (l2o_buf.logical_net_id >> 16) & 0xff;
valbuf[12] = (l2o_buf.logical_net_id >> 8) & 0xff;
valbuf[13] = l2o_buf.logical_net_id & 0xff;
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 0bbbe12cce..7e0ed9150b 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -308,7 +308,7 @@ int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o)
if (pEncap->value[1] == 14) {
memcpy(l2o->macaddr.octet,
pEncap->value + 2,
- ETHER_ADDR_LEN);
+ ETH_ALEN);
l2o->label =
((pEncap->value[10]
>> 4)
@@ -1327,7 +1327,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
memcpy(&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet,
- ETHER_ADDR_LEN);
+ ETH_ALEN);
/* only low 3 bytes of this are significant */
if (bi->attr) {
(void)rfapiEcommunityGetLNI(
@@ -3872,6 +3872,10 @@ rfapiBgpInfoFilteredImportFunction(safi_t safi)
case SAFI_ENCAP:
return rfapiBgpInfoFilteredImportEncap;
+
+ default:
+ /* not expected */
+ return NULL;
}
zlog_err("%s: bad safi %d", __func__, safi);
return NULL;
diff --git a/bgpd/rfapi/rfapi_monitor.c b/bgpd/rfapi/rfapi_monitor.c
index 9c0d9da6ff..6a7595443a 100644
--- a/bgpd/rfapi/rfapi_monitor.c
+++ b/bgpd/rfapi/rfapi_monitor.c
@@ -805,7 +805,7 @@ void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p)
(void **)&mon_eth, &cursor)) {
if (!memcmp(mon_eth->macaddr.octet,
- p->u.prefix_eth.octet, ETHER_ADDR_LEN)) {
+ p->u.prefix_eth.octet, ETH_ALEN)) {
rfapiMonitorEthTimerRestart(mon_eth);
}
@@ -1117,7 +1117,7 @@ static int mon_eth_cmp(void *a, void *b)
/*
* compare ethernet addresses
*/
- for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+ for (i = 0; i < ETH_ALEN; ++i) {
if (m1->macaddr.octet[i] != m2->macaddr.octet[i])
return (m1->macaddr.octet[i] - m2->macaddr.octet[i]);
}
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 791eb4c916..748c0c476b 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -687,7 +687,7 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
/* copy from RD already stored in bi, so we don't need it_node
*/
memcpy(&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val + 2,
- ETHER_ADDR_LEN);
+ ETH_ALEN);
if (bi->attr) {
(void)rfapiEcommunityGetLNI(
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 98c3decbd8..e7314d2983 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -3092,7 +3092,7 @@ static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
if (memcmp(cda->l2o.o.macaddr.octet,
adb->u.s.prefix_eth.u
.prefix_eth.octet,
- ETHER_ADDR_LEN)) {
+ ETH_ALEN)) {
#if DEBUG_L2_EXTRA
vnc_zlog_debug_verbose(
"%s: adb=%p, macaddr doesn't match, skipping",
@@ -3211,7 +3211,7 @@ static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
adb->u.s.prefix_eth.u
.prefix_eth
.octet,
- ETHER_ADDR_LEN)) {
+ ETH_ALEN)) {
continue;
}
diff --git a/common.am b/common.am
index 0ccc4c9fd1..b115a871b9 100644
--- a/common.am
+++ b/common.am
@@ -8,12 +8,21 @@ am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY))
am__v_CLIPPY_0 = @echo " CLIPPY " $@;
am__v_CLIPPY_1 =
-SUFFIXES = _clippy.c
+CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
+
+SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
.c_clippy.c:
- $(AM_V_at)$(MAKE) -C $(top_builddir)/$(CLIPPYDIR) clippy
- $(AM_V_CLIPPY)$(top_builddir)/$(CLIPPYDIR)/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp
+ @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
+ $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp
@{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@
+## automake's "ylwrap" is a great piece of GNU software... not.
+.l.c:
+ $(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $<
+.y.c:
+ $(AM_V_YACC)$(am__skipyacc) $(YACCCOMPILE) $<
+
+
if HAVE_PROTOBUF
# Uncomment to use an non-system version of libprotobuf-c.
@@ -27,16 +36,19 @@ Q_PROTOBUF_C_CLIENT_LDOPTS=-lprotobuf-c
Q_PROTOC=protoc
Q_PROTOC_C=protoc-c
-Q_PROTOBUF_CFILES = $(filter %.pb-c.c,$(SOURCES))
-
-Q_PROTOBUF_SRCS = $(Q_PROTOBUF_CFILES) $(Q_PROTOBUF_HFILES)
-
# Rules
-%.pb.h: %.proto
- $(Q_PROTOC) $(PROTOBUF_INCLUDES) --cpp_out=$(top_srcdir) $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
+.proto.pb.h:
+ $(Q_PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
+
+AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V))
+am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY))
+am__v_PROTOC_C_0 = @echo " PROTOC_C" $@;
+am__v_PROTOC_C_1 =
-%.pb-c.c %.pb-c.h: %.proto
- $(Q_PROTOC_C) $(PROTOBUF_INCLUDES) --c_out=$(top_srcdir) $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
+.proto.pb-c.c:
+ $(AM_V_PROTOC_C)$(Q_PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
+.pb-c.c.pb-c.h:
+ @/bin/true
#
# Information about how to link to various libraries.
@@ -46,7 +58,3 @@ Q_FRR_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libfrr_pb.la $(Q_PROTOBUF_C_CLIENT_LD
Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfrrfpm_pb.la $(Q_FRR_PB_CLIENT_LDOPTS)
endif # HAVE_PROTOBUF
-
-Q_CLEANFILES = $(Q_PROTOBUF_SRCS)
-
-Q_BUILT_SRCS = $(Q_PROTOBUF_SRCS)
diff --git a/configure.ac b/configure.ac
index cbda2fc84f..6b5cd19a5f 100755
--- a/configure.ac
+++ b/configure.ac
@@ -46,12 +46,12 @@ AS_IF([test "$host" != "$build"], [
AC_MSG_NOTICE([...])
build_clippy="false"
- CLIPPYDIR="hosttools/lib"
+ HOSTTOOLS="hosttools/"
], [
build_clippy="true"
- CLIPPYDIR="lib"
+ HOSTTOOLS=""
])
-AC_SUBST(CLIPPYDIR)
+AC_SUBST(HOSTTOOLS)
AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy])
# Disable portability warnings -- our automake code (in particular
@@ -75,14 +75,13 @@ AC_SUBST(exampledir)
dnl default is to match previous behavior
pkgsrcrcdir=""
-pkgsrcdir=""
AC_ARG_ENABLE([pkgsrcrcdir],
AS_HELP_STRING([--enable-pkgsrcrcdir],
[specify directory for rc.d scripts]),
- pkgsrcrcdir="$enableval"; pkgsrcdir="pkgsrc",)
+ pkgsrcrcdir="$enableval",)
dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
-AC_SUBST(pkgsrcdir)
AC_SUBST(pkgsrcrcdir)
+AM_CONDITIONAL([PKGSRC], [test "x$pkgsrcrcdir" != "x"])
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
moduledir="$withval"
@@ -379,7 +378,7 @@ AC_ARG_ENABLE([oldvpn_commands],
AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands]))
AC_CHECK_HEADERS(json-c/json.h)
-AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c")
+AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm])
if test $ac_cv_lib_json_c_json_object_get = no; then
AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson")
if test $ac_cv_lib_json_json_object_get = no; then
@@ -415,26 +414,6 @@ if test "${enable_rr_semantics}" != "no" ; then
AC_DEFINE(HAVE_V6_RR_SEMANTICS,, Compile in v6 Route Replacement Semantics)
fi
-dnl ----------
-dnl MPLS check
-dnl ----------
-AC_MSG_CHECKING(whether this OS has MPLS stack)
-case "$host" in
- *-linux*)
- MPLS_METHOD="zebra_mpls_netlink.o"
- AC_MSG_RESULT(Linux MPLS)
- ;;
- *-openbsd*)
- MPLS_METHOD="zebra_mpls_openbsd.o"
- AC_MSG_RESULT(OpenBSD MPLS)
- ;;
- *)
- MPLS_METHOD="zebra_mpls_null.o"
- AC_MSG_RESULT(Unsupported kernel)
- ;;
-esac
-AC_SUBST(MPLS_METHOD)
-
if test "${enable_datacenter}" = "yes" ; then
AC_DEFINE(HAVE_DATACENTER,,Compile extensions for a DataCenter)
DFLT_NAME="datacenter"
@@ -850,50 +829,62 @@ FRR_INCLUDES
dnl V6 headers are checked below, after we check for v6
-dnl Some systems (Solaris 2.x) require libnsl (Network Services Library)
-case "$host" in
- [*-sunos5.[6-7]*] | [*-solaris2.[6-7]*])
- opsys=sol2-6
- AC_DEFINE(SUNOS_56, 1, SunOS 5.6 to 5.7)
- AC_DEFINE(SUNOS_5, 1, SunOS 5)
- AC_CHECK_LIB(xnet, main)
- CURSES=-lcurses
- SOLARIS="solaris"
- ;;
- [*-sunos5.[8-9]] \
- | [*-sunos5.1[0-9]] \
- | [*-sunos5.1[0-9].[0-9]] \
- | [*-solaris2.[8-9]] \
- | [*-solaris2.1[0-9]] \
- | [*-solaris2.1[0-9].[0-9]])
- opsys=sol8
- AC_DEFINE(SUNOS_59, 1, [SunOS 5.8 up])
- AC_DEFINE(SUNOS_5, 1, [SunOS 5])
- AC_CHECK_LIB(socket, main)
- AC_CHECK_LIB(nsl, main)
- AC_CHECK_LIB(umem, main)
- AC_CHECK_FUNCS([printstack],
- [AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
- AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
- ])
- CURSES=-lcurses
- SOLARIS="solaris"
- ;;
- *-sunos5* | *-solaris2*)
- AC_DEFINE(SUNOS_5,,SunOS 5, Unknown SunOS)
- AC_CHECK_LIB(socket, main)
- AC_CHECK_LIB(nsl, main)
- CURSES=-lcurses
- SOLARIS="solaris"
- ;;
- *-linux*)
- opsys=gnu-linux
- AC_DEFINE(GNU_LINUX,,GNU Linux)
- ;;
- *-openbsd*)
- opsys=openbsd
- AC_DEFINE(OPEN_BSD,,OpenBSD)
- ;;
+AC_MSG_CHECKING([which operating system interface to use])
+case "$host_os" in
+ sunos* | solaris2*)
+ AC_MSG_RESULT([Solaris])
+
+ AC_DEFINE(SUNOS_5, 1, [SunOS 5])
+ AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
+
+ AC_CHECK_LIB(socket, main)
+ AC_CHECK_LIB(nsl, main)
+ AC_CHECK_LIB(umem, main)
+ AC_CHECK_FUNCS([printstack], [
+ AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
+ AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
+ ])
+ CURSES=-lcurses
+ SOLARIS="solaris"
+ ;;
+ linux*)
+ AC_MSG_RESULT([Linux])
+
+ AC_DEFINE(GNU_LINUX,,GNU Linux)
+ AC_DEFINE(HAVE_NETLINK,,netlink)
+ AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack)
+
+ dnl Linux has a compilation problem with mixing
+ dnl netinet/in.h and linux/in6.h they are not
+ dnl compatible. There has been discussion on
+ dnl how to fix it but no real progress on implementation
+ dnl when they fix it, remove this
+ AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count)
+
+ AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include <linux/if_link.h>])
+ ;;
+ openbsd*)
+ AC_MSG_RESULT([OpenBSD])
+
+ AC_DEFINE(OPEN_BSD,,OpenBSD)
+ AC_DEFINE(KAME,1,KAME IPv6)
+
+ if test "x${enable_pimd}" != "xno"; then
+ case "$host_os" in
+ openbsd6.0)
+ ;;
+ openbsd[6-9]*)
+ AC_MSG_FAILURE([pimd cannot be enabled as PIM support has been removed from OpenBSD 6.1])
+ ;;
+ esac
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([BSD])
+
+ AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
+ AC_DEFINE(KAME,1,KAME IPv6)
+ ;;
esac
AC_SYS_LARGEFILE
@@ -1049,26 +1040,6 @@ AC_CHECK_HEADER([asm-generic/unistd.h],
AC_CHECK_FUNCS(setns)]
)
-dnl ------------------------------------
-dnl Determine routing get and set method
-dnl ------------------------------------
-AC_MSG_CHECKING(zebra between kernel interface method)
-if test x"$opsys" = x"gnu-linux"; then
- AC_MSG_RESULT(netlink)
- RT_METHOD=rt_netlink.o
- KERNEL_METHOD=kernel_netlink.o
- AC_DEFINE(HAVE_NETLINK,,netlink)
- netlink=yes
- AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include <linux/if_link.h>])
-else
- AC_MSG_RESULT(Route socket)
- KERNEL_METHOD="kernel_socket.o"
- RT_METHOD="rt_socket.o"
-fi
-AC_SUBST(RT_METHOD)
-AC_SUBST(KERNEL_METHOD)
-AM_CONDITIONAL([HAVE_NETLINK], [test "x$netlink" = "xyes"])
-
dnl --------------------------
dnl Determine IS-IS I/O method
dnl --------------------------
@@ -1078,27 +1049,32 @@ AC_DEFINE(ISIS_METHOD_BPF, 3, [ constant value for isis method bpf ])
AC_CHECK_HEADER(net/bpf.h)
AC_CHECK_HEADER(sys/dlpi.h)
AC_MSG_CHECKING(zebra IS-IS I/O method)
-if test x"$opsys" = x"gnu-linux"; then
- AC_MSG_RESULT(pfpacket)
- ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET"
-elif test x"$opsys" = x"sol2-6" -o x"$opsys" = x"sol8"; then
- AC_MSG_RESULT(DLPI)
- ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
-else
- if test $ac_cv_header_net_bpf_h = no; then
- if test $ac_cv_header_sys_dlpi_h = no; then
- AC_MSG_RESULT(none)
- AC_MSG_WARN([*** IS-IS support will not be built ***])
- ISISD=""
+
+case "$host_os" in
+ linux*)
+ AC_MSG_RESULT(pfpacket)
+ ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET"
+ ;;
+ solaris* | sunos*)
+ AC_MSG_RESULT(DLPI)
+ ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
+ ;;
+ *)
+ if test $ac_cv_header_net_bpf_h = no; then
+ if test $ac_cv_header_sys_dlpi_h = no; then
+ AC_MSG_RESULT(none)
+ AC_MSG_WARN([*** IS-IS support will not be built ***])
+ ISISD=""
+ else
+ AC_MSG_RESULT(DLPI)
+ fi
+ ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
else
- AC_MSG_RESULT(DLPI)
+ AC_MSG_RESULT(BPF)
+ ISIS_METHOD_MACRO="ISIS_METHOD_BPF"
fi
- ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
- else
- AC_MSG_RESULT(BPF)
- ISIS_METHOD_MACRO="ISIS_METHOD_BPF"
- fi
-fi
+ ;;
+esac
AC_DEFINE_UNQUOTED(ISIS_METHOD, $ISIS_METHOD_MACRO, [ selected method for isis, == one of the constants ])
dnl ------------------------------------
@@ -1128,59 +1104,6 @@ main()
}]])],[AC_MSG_RESULT(yes - using workaround) AC_DEFINE(HAVE_BROKEN_CMSG_FIRSTHDR,,Broken CMSG_FIRSTHDR)],
[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)])
-dnl ------------------------------
-dnl check kernel route read method
-dnl ------------------------------
-AC_CACHE_CHECK([route read method], [frr_cv_rtread_method],
-[if test "x$netlink" = xyes; then
- frr_cv_rtread_method="netlink"
-else
-for frr_cv_rtread_method in /dev/ip /dev/null;
-do
- test x`ls $frr_cv_rtread_method 2>/dev/null` = x"$frr_cv_rtread_method" && break
-done
-case $frr_cv_rtread_method in
- "/dev/ip")
- case "$host" in
- *-freebsd*) frr_cv_rtread_method="sysctl";;
- *) frr_cv_rtread_method="getmsg";;
- esac;;
- *)
- frr_cv_rtread_method="sysctl";;
-esac
-fi])
-RTREAD_METHOD=rtread_${frr_cv_rtread_method}.o
-AC_SUBST(RTREAD_METHOD)
-
-dnl -----------------------------
-dnl check interface lookup method
-dnl -----------------------------
-IOCTL_METHOD=ioctl.o
-AC_MSG_CHECKING(interface looking up method)
-if test "$netlink" = yes; then
- AC_MSG_RESULT(netlink)
- IF_METHOD=if_netlink.o
-elif test "$opsys" = "sol2-6";then
- AC_MSG_RESULT(Solaris GIF)
- IF_METHOD=if_ioctl.o
-elif test "$opsys" = "sol8";then
- AC_MSG_RESULT(Solaris GLIF)
- IF_METHOD=if_ioctl_solaris.o
- IOCTL_METHOD=ioctl_solaris.o
-elif test "$opsys" = "openbsd";then
- AC_MSG_RESULT(openbsd)
- IF_METHOD=if_ioctl.o
-elif grep NET_RT_IFLIST /usr/include/sys/socket.h >/dev/null 2>&1; then
- AC_MSG_RESULT(sysctl)
- IF_METHOD=if_sysctl.o
- AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
-else
- AC_MSG_RESULT(ioctl)
- IF_METHOD=if_ioctl.o
-fi
-AC_SUBST(IF_METHOD)
-AC_SUBST(IOCTL_METHOD)
-
dnl ---------------------------------------------------------------
dnl figure out how to specify an interface in multicast sockets API
dnl ---------------------------------------------------------------
@@ -1276,71 +1199,11 @@ if test $ac_cv_have_decl_TCP_MD5SIG = no; then
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)])
fi
-dnl -----------------------------
-dnl check ipforward detect method
-dnl -----------------------------
-AC_CACHE_CHECK([ipforward method], [frr_cv_ipforward_method],
-[if test x$cross_compiling = xyes; then
- if test x"$opsys" = x"gnu-linux"; then
- frr_cv_ipforward_method=/proc/net/snmp
- else
- frr_cv_ipforward_method=/dev/ip
- fi
-else
- for frr_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
- do
- test x`ls $frr_cv_ipforward_method 2>/dev/null` = x"$frr_cv_ipforward_method" && break
- done
-fi
-case $frr_cv_ipforward_method in
- "/proc/net/snmp") frr_cv_ipforward_method="proc";;
- "/dev/ip")
- case "$host" in
- *-freebsd*) frr_cv_ipforward_method="sysctl";;
- *) frr_cv_ipforward_method="solaris";;
- esac;;
- *) frr_cv_ipforward_method="sysctl";;
-esac])
-IPFORWARD=ipforward_${frr_cv_ipforward_method}.o
-AC_SUBST(IPFORWARD)
-
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 ----------
-AC_MSG_CHECKING(whether does this OS have IPv6 stack)
-dnl ---------
-dnl KAME IPv6
-dnl ---------
- if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
- AC_DEFINE(KAME,1,KAME IPv6)
- AC_MSG_RESULT(KAME)
-dnl ------------------------------------
-dnl Solaris 9, 10 and potentially higher
-dnl ------------------------------------
- elif test x"$opsys" = x"sol8"; then
- AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
- AC_MSG_RESULT(Solaris IPv6)
-dnl ----------
-dnl Linux IPv6
-dnl ----------
- elif test x"$opsys" = x"gnu-linux"; then
- AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack)
- dnl Linux has a compilation problem with mixing
- dnl netinet/in.h and linux/in6.h they are not
- dnl compatible. There has been discussion on
- dnl how to fix it but no real progress on implementation
- dnl when they fix it, remove this
- AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count)
- AC_MSG_RESULT(Linux IPv6)
- else
- AC_MSG_ERROR([Failed to detect IPv6 stack])
- fi
-
dnl ------------------
dnl IPv6 header checks
dnl ------------------
@@ -1375,12 +1238,7 @@ fi
dnl --------------------
dnl Daemon disable check
dnl --------------------
-if test "${enable_zebra}" = "no";then
- ZEBRA=""
-else
- ZEBRA="zebra"
-fi
-AM_CONDITIONAL(ZEBRA, test "x$ZEBRA" = "xzebra")
+AM_CONDITIONAL(ZEBRA, test "${enable_zebra}" != "no")
if test "${enable_bgpd}" = "no";then
BGPD=""
@@ -1412,15 +1270,18 @@ fi
AM_CONDITIONAL(LDPD, test "x$LDPD" = "xldpd")
NHRPD=""
-if test "$opsys" = "gnu-linux"; then
- if test "${enable_nhrpd}" != "no"; then
- NHRPD="nhrpd"
- fi
-else
- if test "${enable_nhrpd}" = "yes"; then
- AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.])
- fi
-fi
+case "$host_os" in
+ linux*)
+ if test "${enable_nhrpd}" != "no"; then
+ NHRPD="nhrpd"
+ fi
+ ;;
+ *)
+ if test "${enable_nhrpd}" = "yes"; then
+ AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.])
+ fi
+ ;;
+esac
AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
if test "${enable_eigrpd}" = "no";then
@@ -1506,7 +1367,6 @@ fi
AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
AC_SUBST(DOC)
-AC_SUBST(ZEBRA)
AC_SUBST(RFPTEST)
AC_SUBST(LIBRFP)
AC_SUBST(RFPINC)
@@ -1527,7 +1387,8 @@ AC_SUBST(VTYSH)
AC_SUBST(CURSES)
AC_SUBST(OSPFCLIENT)
AC_SUBST(OSPFAPI)
-AC_CHECK_LIB(crypt, crypt)
+AC_CHECK_LIB(crypt, crypt, [],
+ [AC_CHECK_LIB(crypto, DES_crypt)])
AC_CHECK_LIB(resolv, res_init)
dnl ---------------------------
@@ -1969,22 +1830,17 @@ AC_CACHE_VAL(ac_cv_htonl_works,
)
AC_MSG_RESULT($ac_cv_htonl_works)
-AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
+AC_CONFIG_FILES([Makefile ripd/Makefile
ripngd/Makefile bgpd/Makefile ospfd/Makefile watchfrr/Makefile
ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
- doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
+ doc/Makefile ospfclient/Makefile tests/Makefile
bgpd/rfp-example/rfptest/Makefile bgpd/rfp-example/librfp/Makefile
babeld/Makefile
pimd/Makefile
eigrpd/Makefile
nhrpd/Makefile
- redhat/Makefile
tools/Makefile
- pkgsrc/Makefile
- python/Makefile
- fpm/Makefile
redhat/frr.spec
- snapcraft/Makefile
snapcraft/snapcraft.yaml
lib/version.h
tests/lib/cli/test_cli.refout
diff --git a/doc/babeld.texi b/doc/babeld.texi
index 2dfb5f8c0a..341f692869 100644
--- a/doc/babeld.texi
+++ b/doc/babeld.texi
@@ -179,8 +179,8 @@ The default is 4@dmn{s}.
@node Babel redistribution, Show Babel information, Babel configuration, Babel
@section Babel redistribution
-@deffn {Babel command} {redistribute @var{kind}}
-@deffnx {Babel command} {no redistribute @var{kind}}
+@deffn {Babel command} {redistribute @var{<ipv4|ipv6>} @var{kind}}
+@deffnx {Babel command} {no redistribute @var{<ipv4|ipv6>} @var{kind}}
Specify which kind of routes should be redistributed into Babel.
@end deffn
diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c
index ba24abe5b3..15a8a71cf3 100644
--- a/eigrpd/eigrp_dump.c
+++ b/eigrpd/eigrp_dump.c
@@ -395,11 +395,11 @@ DEFUN (debug_eigrp_transmit,
flag = EIGRP_DEBUG_SEND;
else if (argv_find(argv, argc, "recv", &idx))
flag = EIGRP_DEBUG_RECV;
- else if (argv_find(argv, argc, "all", &idx) == 0)
+ else if (argv_find(argv, argc, "all", &idx))
flag = EIGRP_DEBUG_SEND_RECV;
/* detail option */
- if (argv_find(argv, argc, "detail", &idx) == 0)
+ if (argv_find(argv, argc, "detail", &idx))
flag = EIGRP_DEBUG_PACKET_DETAIL;
if (vty->node == CONFIG_NODE)
@@ -426,15 +426,15 @@ DEFUN (no_debug_eigrp_transmit,
int idx = 3;
/* send or recv. */
- if (argv_find(argv, argc, "send", &idx) == 0)
+ if (argv_find(argv, argc, "send", &idx))
flag = EIGRP_DEBUG_SEND;
- else if (argv_find(argv, argc, "recv", &idx) == 0)
+ else if (argv_find(argv, argc, "recv", &idx))
flag = EIGRP_DEBUG_RECV;
- else if (argv_find(argv, argc, "all", &idx) == 0)
+ else if (argv_find(argv, argc, "all", &idx))
flag = EIGRP_DEBUG_SEND_RECV;
/* detail option */
- if (argv_find(argv, argc, "detail", &idx) == 0)
+ if (argv_find(argv, argc, "detail", &idx))
flag = EIGRP_DEBUG_PACKET_DETAIL;
if (vty->node == CONFIG_NODE)
@@ -474,27 +474,27 @@ DEFUN (debug_eigrp_packets,
int idx = 0;
/* Check packet type. */
- if (argv_find(argv, argc, "hello", &idx) == 0)
+ if (argv_find(argv, argc, "hello", &idx))
type = EIGRP_DEBUG_HELLO;
- if (argv_find(argv, argc, "update", &idx) == 0)
+ if (argv_find(argv, argc, "update", &idx))
type = EIGRP_DEBUG_UPDATE;
- if (argv_find(argv, argc, "query", &idx) == 0)
+ if (argv_find(argv, argc, "query", &idx))
type = EIGRP_DEBUG_QUERY;
- if (argv_find(argv, argc, "ack", &idx) == 0)
+ if (argv_find(argv, argc, "ack", &idx))
type = EIGRP_DEBUG_ACK;
- if (argv_find(argv, argc, "probe", &idx) == 0)
+ if (argv_find(argv, argc, "probe", &idx))
type = EIGRP_DEBUG_PROBE;
- if (argv_find(argv, argc, "stub", &idx) == 0)
+ if (argv_find(argv, argc, "stub", &idx))
type = EIGRP_DEBUG_STUB;
- if (argv_find(argv, argc, "reply", &idx) == 0)
+ if (argv_find(argv, argc, "reply", &idx))
type = EIGRP_DEBUG_REPLY;
- if (argv_find(argv, argc, "request", &idx) == 0)
+ if (argv_find(argv, argc, "request", &idx))
type = EIGRP_DEBUG_REQUEST;
- if (argv_find(argv, argc, "siaquery", &idx) == 0)
+ if (argv_find(argv, argc, "siaquery", &idx))
type = EIGRP_DEBUG_SIAQUERY;
- if (argv_find(argv, argc, "siareply", &idx) == 0)
+ if (argv_find(argv, argc, "siareply", &idx))
type = EIGRP_DEBUG_SIAREPLY;
- if (argv_find(argv, argc, "all", &idx) == 0)
+ if (argv_find(argv, argc, "all", &idx))
type = EIGRP_DEBUG_PACKETS_ALL;
@@ -502,13 +502,13 @@ DEFUN (debug_eigrp_packets,
flag = EIGRP_DEBUG_SEND_RECV;
/* send or recv. */
- if (argv_find(argv, argc, "s", &idx) == 0)
+ if (argv_find(argv, argc, "s", &idx))
flag = EIGRP_DEBUG_SEND;
- else if (argv_find(argv, argc, "r", &idx) == 0)
+ else if (argv_find(argv, argc, "r", &idx))
flag = EIGRP_DEBUG_RECV;
/* detail. */
- if (argv_find(argv, argc, "detail", &idx) == 0)
+ if (argv_find(argv, argc, "detail", &idx))
flag |= EIGRP_DEBUG_PACKET_DETAIL;
for (i = 0; i < 11; i++)
@@ -552,38 +552,38 @@ DEFUN (no_debug_eigrp_packets,
int idx = 0;
/* Check packet type. */
- if (argv_find(argv, argc, "hello", &idx) == 0)
+ if (argv_find(argv, argc, "hello", &idx))
type = EIGRP_DEBUG_HELLO;
- if (argv_find(argv, argc, "update", &idx) == 0)
+ if (argv_find(argv, argc, "update", &idx))
type = EIGRP_DEBUG_UPDATE;
- if (argv_find(argv, argc, "query", &idx) == 0)
+ if (argv_find(argv, argc, "query", &idx))
type = EIGRP_DEBUG_QUERY;
- if (argv_find(argv, argc, "ack", &idx) == 0)
+ if (argv_find(argv, argc, "ack", &idx))
type = EIGRP_DEBUG_ACK;
- if (argv_find(argv, argc, "probe", &idx) == 0)
+ if (argv_find(argv, argc, "probe", &idx))
type = EIGRP_DEBUG_PROBE;
- if (argv_find(argv, argc, "stub", &idx) == 0)
+ if (argv_find(argv, argc, "stub", &idx))
type = EIGRP_DEBUG_STUB;
- if (argv_find(argv, argc, "reply", &idx) == 0)
+ if (argv_find(argv, argc, "reply", &idx))
type = EIGRP_DEBUG_REPLY;
- if (argv_find(argv, argc, "request", &idx) == 0)
+ if (argv_find(argv, argc, "request", &idx))
type = EIGRP_DEBUG_REQUEST;
- if (argv_find(argv, argc, "siaquery", &idx) == 0)
+ if (argv_find(argv, argc, "siaquery", &idx))
type = EIGRP_DEBUG_SIAQUERY;
- if (argv_find(argv, argc, "siareply", &idx) == 0)
+ if (argv_find(argv, argc, "siareply", &idx))
type = EIGRP_DEBUG_SIAREPLY;
/* Default, both send and recv. */
flag = EIGRP_DEBUG_SEND_RECV;
/* send or recv. */
- if (argv_find(argv, argc, "send", &idx) == 0)
+ if (argv_find(argv, argc, "send", &idx))
flag = EIGRP_DEBUG_SEND;
- else if (argv_find(argv, argc, "reply", &idx) == 0)
+ else if (argv_find(argv, argc, "reply", &idx))
flag = EIGRP_DEBUG_RECV;
/* detail. */
- if (argv_find(argv, argc, "detail", &idx) == 0)
+ if (argv_find(argv, argc, "detail", &idx))
flag |= EIGRP_DEBUG_PACKET_DETAIL;
for (i = 0; i < 11; i++)
diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c
index f20ec0ad12..3befd8a118 100644
--- a/eigrpd/eigrp_packet.c
+++ b/eigrpd/eigrp_packet.c
@@ -161,6 +161,7 @@ int eigrp_check_md5_digest(struct stream *s,
{
MD5_CTX ctx;
unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN];
+ unsigned char orig[EIGRP_AUTH_TYPE_MD5_LEN];
struct key *key = NULL;
struct keychain *keychain;
u_char *ibuf;
@@ -181,7 +182,9 @@ int eigrp_check_md5_digest(struct stream *s,
auth_TLV = (struct TLV_MD5_Authentication_Type *)(s->data
+ EIGRP_HEADER_LEN);
- memset(auth_TLV->digest, 0, sizeof(auth_TLV->digest));
+ memcpy(orig, auth_TLV->digest, EIGRP_AUTH_TYPE_MD5_LEN);
+ memset(digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
+ memset(auth_TLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
ibuf = s->data;
backup_end = s->endp;
@@ -219,16 +222,15 @@ int eigrp_check_md5_digest(struct stream *s,
MD5Final(digest, &ctx);
/* compare the two */
- if (memcmp(authTLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN) == 0) {
- zlog_debug("VSETKO OK");
- } else {
+ if (memcmp(orig, digest, EIGRP_AUTH_TYPE_MD5_LEN) != 0) {
zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
IF_NAME(nbr->ei));
return 0;
}
/* save neighbor's crypt_seqnum */
- nbr->crypt_seqnum = authTLV->key_sequence;
+ if (nbr)
+ nbr->crypt_seqnum = authTLV->key_sequence;
return 1;
}
@@ -884,6 +886,7 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei,
{
struct eigrp_header *eigrph;
+ stream_reset(s);
eigrph = (struct eigrp_header *)STREAM_DATA(s);
eigrph->version = (u_char)EIGRP_HEADER_VERSION;
diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c
index 3c2ce6ce42..e0169c514b 100644
--- a/eigrpd/eigrp_update.c
+++ b/eigrpd/eigrp_update.c
@@ -504,10 +504,36 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
}
}
+static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr,
+ struct eigrp_packet *ep,
+ u_int32_t seq_no,
+ int length)
+{
+ if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
+ (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) {
+ eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
+ }
+
+ /* EIGRP Checksum */
+ eigrp_packet_checksum(nbr->ei, ep->s, length);
+
+ ep->length = length;
+ ep->dst.s_addr = nbr->src.s_addr;
+
+ /*This ack number we await from neighbor*/
+ ep->sequence_number = seq_no;
+
+ if (IS_DEBUG_EIGRP_PACKET(0, RECV))
+ zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
+ ep->length, ep->sequence_number, inet_ntoa(ep->dst));
+
+ /*Put packet to retransmission queue*/
+ eigrp_fifo_push_head(nbr->retrans_queue, ep);
+}
+
void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
{
struct eigrp_packet *ep;
- // struct eigrp_packet *ep_multicast;
u_int16_t length = EIGRP_HEADER_LEN;
struct eigrp_neighbor_entry *te;
struct eigrp_prefix_entry *pe;
@@ -518,38 +544,53 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
struct prefix_list *plist_i;
struct eigrp *e;
struct prefix_ipv4 *dest_addr;
+ u_int32_t seq_no = nbr->ei->eigrp->sequence_number;
ep = eigrp_packet_new(nbr->ei->ifp->mtu);
/* Prepare EIGRP EOT UPDATE header */
- eigrp_packet_header_init(
- EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
- nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number);
+ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
+ seq_no,
+ nbr->recv_sequence_number);
// encode Authentication TLV, if needed
- if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
- && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) {
- length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei);
+ if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
+ (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) {
+ length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
}
- for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode,
- pe)) {
+ for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) {
for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) {
if ((te->ei == nbr->ei)
&& (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
continue;
+ if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) {
+ eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
+ eigrp_send_packet_reliably(nbr);
+ seq_no++;
+
+ length = EIGRP_HEADER_LEN;
+ ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
+ seq_no, nbr->recv_sequence_number);
+
+ if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
+ (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
+ {
+ length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
+ }
+ }
/* Get destination address from prefix */
dest_addr = pe->destination_ipv4;
/*
* Filtering
*/
- // TODO: Work in progress
+ //TODO: Work in progress
/* get list from eigrp process */
e = eigrp_lookup();
- /* Get access-lists and prefix-lists from process and
- * interface */
+ /* Get access-lists and prefix-lists from process and interface */
alist = e->list[EIGRP_FILTER_OUT];
plist = e->prefix[EIGRP_FILTER_OUT];
alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
@@ -557,65 +598,24 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
/* Check if any list fits */
if ((alist
- && access_list_apply(alist,
- (struct prefix *)dest_addr)
- == FILTER_DENY)
- || (plist
- && prefix_list_apply(plist,
- (struct prefix *)dest_addr)
- == PREFIX_DENY)
- || (alist_i
- && access_list_apply(alist_i,
- (struct prefix *)dest_addr)
- == FILTER_DENY)
- || (plist_i
- && prefix_list_apply(plist_i,
- (struct prefix *)dest_addr)
- == PREFIX_DENY)) {
- zlog_info("PROC OUT EOT: Skipping");
- // pe->reported_metric.delay = EIGRP_MAX_METRIC;
- zlog_info("PROC OUT EOT Prefix: %s",
- inet_ntoa(dest_addr->prefix));
+ && access_list_apply (alist,
+ (struct prefix *) dest_addr) == FILTER_DENY)||
+ (plist && prefix_list_apply (plist,
+ (struct prefix *) dest_addr) == PREFIX_DENY)||
+ (alist_i && access_list_apply (alist_i,
+ (struct prefix *) dest_addr) == FILTER_DENY)||
+ (plist_i && prefix_list_apply (plist_i,
+ (struct prefix *) dest_addr) == PREFIX_DENY)) {
+ //pe->reported_metric.delay = EIGRP_MAX_METRIC;
continue;
} else {
- zlog_info(
- "PROC OUT EOT: NENastavujem metriku ");
- length += eigrp_add_internalTLV_to_stream(ep->s,
- pe);
+ length += eigrp_add_internalTLV_to_stream(ep->s, pe);
}
- /*
- * End of filtering
- */
-
- /* NULL the pointer */
- dest_addr = NULL;
}
}
- if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
- && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) {
- eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
- }
-
- /* EIGRP Checksum */
- eigrp_packet_checksum(nbr->ei, ep->s, length);
-
- ep->length = length;
- ep->dst.s_addr = nbr->src.s_addr;
-
- /*This ack number we await from neighbor*/
- ep->sequence_number = nbr->ei->eigrp->sequence_number;
-
- if (IS_DEBUG_EIGRP_PACKET(0, RECV))
- zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
- ep->length, ep->sequence_number, inet_ntoa(ep->dst));
-
- /*Put packet to retransmission queue*/
- eigrp_fifo_push_head(nbr->retrans_queue, ep);
-
- if (nbr->retrans_queue->count == 1) {
- eigrp_send_packet_reliably(nbr);
- }
+ eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
+ eigrp_send_packet_reliably(nbr);
}
void eigrp_update_send(struct eigrp_interface *ei)
diff --git a/fpm/.gitignore b/fpm/.gitignore
index b133c52a42..17e90443e9 100644
--- a/fpm/.gitignore
+++ b/fpm/.gitignore
@@ -1,4 +1,4 @@
-Makefile
+!Makefile
Makefile.in
*.o
tags
diff --git a/fpm/Makefile b/fpm/Makefile
new file mode 100644
index 0000000000..1d280d176e
--- /dev/null
+++ b/fpm/Makefile
@@ -0,0 +1,10 @@
+all: ALWAYS
+ @$(MAKE) -s -C .. fpm/libfrrfpm_pb.la
+%: ALWAYS
+ @$(MAKE) -s -C .. fpm/$@
+
+Makefile:
+ #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/fpm/Makefile.am b/fpm/Makefile.am
deleted file mode 100644
index 1f46ac6db2..0000000000
--- a/fpm/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-include ../common.am
-
-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
-
-PROTOBUF_INCLUDES=-I$(top_srcdir)
-PROTOBUF_PACKAGE = fpm
-
-lib_LTLIBRARIES = libfrrfpm_pb.la
-libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
-
-if HAVE_PROTOBUF
-protobuf_srcs =
-
-protobuf_srcs_nodist = \
- fpm.pb-c.c
-endif
-
-libfrrfpm_pb_la_SOURCES = \
- fpm.h \
- fpm_pb.h \
- fpm_pb.c \
- $(protobuf_srcs)
-
-nodist_libfrrfpm_pb_la_SOURCES = $(protobuf_srcs_nodist)
-
-CLEANFILES = $(Q_CLEANFILES)
-
-BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
-EXTRA_DIST = fpm.proto
diff --git a/fpm/fpm.proto b/fpm/fpm.proto
index 318e80a92e..4597c7f8eb 100644
--- a/fpm/fpm.proto
+++ b/fpm/fpm.proto
@@ -20,6 +20,8 @@
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
+syntax = "proto2";
+
//
// Protobuf definitions pertaining to the Forwarding Plane Manager component.
//
diff --git a/fpm/subdir.am b/fpm/subdir.am
new file mode 100644
index 0000000000..f81a84222c
--- /dev/null
+++ b/fpm/subdir.am
@@ -0,0 +1,23 @@
+if FPM
+lib_LTLIBRARIES += fpm/libfrrfpm_pb.la
+endif
+
+fpm_libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
+fpm_libfrrfpm_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
+ $(Q_PROTOBUF_C_CLIENT_INCLUDES)
+fpm_libfrrfpm_pb_la_SOURCES = \
+ fpm/fpm.h \
+ fpm/fpm_pb.h \
+ fpm/fpm_pb.c \
+ # end
+
+if HAVE_PROTOBUF
+nodist_fpm_libfrrfpm_pb_la_SOURCES = fpm/fpm.pb-c.c
+BUILT_SOURCES += fpm/fpm.pb-c.c
+CLEANFILES += \
+ fpm/fpm.pb-c.c \
+ fpm/fpm.pb-c.h \
+ # end
+endif
+
+EXTRA_DIST += fpm/fpm.proto
diff --git a/isisd/Makefile.am b/isisd/Makefile.am
index 2973820eed..dc3d3683a1 100644
--- a/isisd/Makefile.am
+++ b/isisd/Makefile.am
@@ -8,24 +8,26 @@ LIBS = @LIBS@
AM_CFLAGS = $(WERROR)
noinst_LIBRARIES = libisis.a
-sbin_PROGRAMS = isisd
+sbin_PROGRAMS = isisd
libisis_a_SOURCES = \
isis_memory.c \
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 \
+ 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_te.c \
- isis_vty.c isis_mt.c
+ isis_vty.c isis_mt.c \
+ isis_tlvs.c
noinst_HEADERS = \
isis_memory.h \
- isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
+ isisd.h isis_pdu.h isis_adjacency.h isis_constants.h \
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_te.h isis_mt.h
+ isis_route.h isis_routemap.h isis_te.h isis_mt.h \
+ isis_tlvs.h
isisd_SOURCES = \
isis_main.c $(libisis_a_SOURCES) \
diff --git a/isisd/dict.c b/isisd/dict.c
index f09a8152a8..2ea86d1b68 100644
--- a/isisd/dict.c
+++ b/isisd/dict.c
@@ -174,6 +174,7 @@ static int verify_bintree(dict_t *dict)
* subtree is not red-black.
*/
+#ifdef EXTREME_DICT_DEBUG
static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
{
unsigned height_left, height_right;
@@ -198,6 +199,7 @@ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
}
return 1;
}
+#endif
/*
* Compute the actual count of nodes by traversing the tree and
@@ -205,6 +207,7 @@ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
* detect a mismatch.
*/
+#ifdef EXTREME_DICT_DEBUG
static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
{
if (root == nil)
@@ -213,6 +216,7 @@ static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
return 1 + verify_node_count(nil, root->left)
+ verify_node_count(nil, root->right);
}
+#endif
/*
* Verify that the tree contains the given node. This is done by
@@ -369,6 +373,7 @@ static void dict_clear(dict_t *dict)
int dict_verify(dict_t *dict)
{
+#ifdef EXTREME_DICT_DEBUG
dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
/* check that the sentinel node and root node are black */
@@ -389,6 +394,7 @@ int dict_verify(dict_t *dict)
return 0;
if (verify_node_count(nil, root) != dict_count(dict))
return 0;
+#endif
return 1;
}
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index d8cb32375b..0afa65d726 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -43,7 +43,6 @@
#include "isisd/isis_dr.h"
#include "isisd/isis_dynhn.h"
#include "isisd/isis_pdu.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_events.h"
@@ -69,11 +68,6 @@ struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa,
adj = adj_alloc(id); /* P2P kludge */
- if (adj == NULL) {
- zlog_err("Out of memory!");
- return NULL;
- }
-
if (snpa) {
memcpy(adj->snpa, snpa, ETH_ALEN);
} else {
@@ -137,12 +131,12 @@ void isis_delete_adj(void *arg)
/* remove from SPF trees */
spftree_area_adj_del(adj->circuit->area, adj);
- if (adj->area_addrs)
- list_delete(adj->area_addrs);
- if (adj->ipv4_addrs)
- list_delete(adj->ipv4_addrs);
- if (adj->ipv6_addrs)
- list_delete(adj->ipv6_addrs);
+ if (adj->area_addresses)
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
+ if (adj->ipv4_addresses)
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
+ if (adj->ipv6_addresses)
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
adj_mt_finish(adj);
@@ -192,7 +186,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
- adj_name = (const char *)dyn->name.name;
+ adj_name = dyn->hostname;
else
adj_name = sysid_print(adj->sysid);
@@ -301,33 +295,29 @@ void isis_adj_state_change(struct isis_adjacency *adj,
void isis_adj_print(struct isis_adjacency *adj)
{
struct isis_dynhn *dyn;
- struct listnode *node;
- struct in_addr *ipv4_addr;
- struct in6_addr *ipv6_addr;
- u_char ip6[INET6_ADDRSTRLEN];
if (!adj)
return;
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
- zlog_debug("%s", dyn->name.name);
+ zlog_debug("%s", dyn->hostname);
zlog_debug("SystemId %20s SNPA %s, level %d\nHolding Time %d",
sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level,
adj->hold_time);
- if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) {
+ if (adj->ipv4_address_count) {
zlog_debug("IPv4 Address(es):");
-
- for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr))
- zlog_debug("%s", inet_ntoa(*ipv4_addr));
+ for (unsigned int i = 0; i < adj->ipv4_address_count; i++)
+ zlog_debug("%s", inet_ntoa(adj->ipv4_addresses[i]));
}
- if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) {
+ if (adj->ipv6_address_count) {
zlog_debug("IPv6 Address(es):");
- for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) {
- inet_ntop(AF_INET6, ipv6_addr, (char *)ip6,
- INET6_ADDRSTRLEN);
- zlog_debug("%s", ip6);
+ for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ipv6_addresses[i], buf,
+ sizeof(buf));
+ zlog_debug("%s", buf);
}
}
zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids));
@@ -358,17 +348,13 @@ int isis_adj_expire(struct thread *thread)
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
char detail)
{
- struct in6_addr *ipv6_addr;
- u_char ip6[INET6_ADDRSTRLEN];
- struct in_addr *ip_addr;
time_t now;
struct isis_dynhn *dyn;
int level;
- struct listnode *node;
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
- vty_out(vty, " %-20s", dyn->name.name);
+ vty_out(vty, " %-20s", dyn->hostname);
else
vty_out(vty, " %-20s", sysid_print(adj->sysid));
@@ -429,8 +415,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
&& (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
dyn = dynhn_find_by_id(adj->lanid);
if (dyn)
- vty_out(vty, ", LAN id: %s.%02x",
- dyn->name.name,
+ vty_out(vty, ", LAN id: %s.%02x", dyn->hostname,
adj->lanid[ISIS_SYS_ID_LEN]);
else
vty_out(vty, ", LAN id: %s.%02x",
@@ -452,28 +437,32 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
}
vty_out(vty, "\n");
- if (adj->area_addrs && listcount(adj->area_addrs) > 0) {
- struct area_addr *area_addr;
+ if (adj->area_address_count) {
vty_out(vty, " Area Address(es):\n");
- for (ALL_LIST_ELEMENTS_RO(adj->area_addrs, node,
- area_addr))
+ for (unsigned int i = 0; i < adj->area_address_count;
+ i++) {
vty_out(vty, " %s\n",
- isonet_print(area_addr->area_addr,
- area_addr->addr_len));
+ isonet_print(adj->area_addresses[i]
+ .area_addr,
+ adj->area_addresses[i]
+ .addr_len));
+ }
}
- if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) {
+ if (adj->ipv4_address_count) {
vty_out(vty, " IPv4 Address(es):\n");
- for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node,
- ip_addr))
- vty_out(vty, " %s\n", inet_ntoa(*ip_addr));
+ for (unsigned int i = 0; i < adj->ipv4_address_count;
+ i++)
+ vty_out(vty, " %s\n",
+ inet_ntoa(adj->ipv4_addresses[i]));
}
- if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) {
+ if (adj->ipv6_address_count) {
vty_out(vty, " IPv6 Address(es):\n");
- for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node,
- ipv6_addr)) {
- inet_ntop(AF_INET6, ipv6_addr, (char *)ip6,
- INET6_ADDRSTRLEN);
- vty_out(vty, " %s\n", ip6);
+ for (unsigned int i = 0; i < adj->ipv6_address_count;
+ i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ipv6_addresses[i],
+ buf, sizeof(buf));
+ vty_out(vty, " %s\n", buf);
}
}
vty_out(vty, "\n");
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index 9f4af1b45d..98bb9838fa 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -73,13 +73,16 @@ struct isis_adjacency {
int dischanges[ISIS_LEVELS]; /* how many DIS changes ? */
/* an array of N levels for M records */
struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS];
- enum isis_adj_state adj_state; /* adjacencyState */
- enum isis_adj_usage adj_usage; /* adjacencyUsage */
- struct list *area_addrs; /* areaAdressesOfNeighbour */
- struct nlpids nlpids; /* protocols spoken ... */
- struct list *ipv4_addrs;
+ enum isis_adj_state adj_state; /* adjacencyState */
+ enum isis_adj_usage adj_usage; /* adjacencyUsage */
+ struct area_addr *area_addresses; /* areaAdressesOfNeighbour */
+ unsigned int area_address_count;
+ struct nlpids nlpids; /* protocols spoken ... */
+ struct in_addr *ipv4_addresses;
+ unsigned int ipv4_address_count;
struct in_addr router_address;
- struct list *ipv6_addrs;
+ struct in6_addr *ipv6_addresses;
+ unsigned int ipv6_address_count;
struct in6_addr router_address6;
u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
int circuit_t; /* from hello PDU hdr */
diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c
index 69c2f941f0..98f612f827 100644
--- a/isisd/isis_bpf.c
+++ b/isisd/isis_bpf.c
@@ -250,8 +250,8 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
stream_set_getp(circuit->rcv_stream, 0);
- memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN,
- ETHER_ADDR_LEN);
+ memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN,
+ ETH_ALEN);
if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
zlog_warn("Flushing failed: %s", safe_strerror(errno));
@@ -281,10 +281,10 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
*/
eth = (struct ether_header *)sock_buff;
if (level == 1)
- memcpy(eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN);
+ memcpy(eth->ether_dhost, ALL_L1_ISS, ETH_ALEN);
else
- memcpy(eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN);
- memcpy(eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN);
+ memcpy(eth->ether_dhost, ALL_L2_ISS, ETH_ALEN);
+ memcpy(eth->ether_shost, circuit->u.bc.snpa, ETH_ALEN);
size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN;
eth->ether_type = htons(isis_ethertype(frame_size));
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 72810532b0..9622dcdbc4 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -26,10 +26,6 @@
#include <netinet/if_ether.h>
#endif
-#ifndef ETHER_ADDR_LEN
-#define ETHER_ADDR_LEN ETHERADDRL
-#endif
-
#include "log.h"
#include "memory.h"
#include "vrf.h"
@@ -48,7 +44,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 5e523cd68b..ad53be4683 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -26,6 +26,7 @@
#include "vty.h"
#include "if.h"
#include "qobj.h"
+#include "prefix.h"
#include "isis_constants.h"
#include "isis_common.h"
diff --git a/isisd/isis_common.h b/isisd/isis_common.h
index ba6c5f876d..b157bb1836 100644
--- a/isisd/isis_common.h
+++ b/isisd/isis_common.h
@@ -47,16 +47,6 @@ struct isis_passwd {
};
/*
- * (Dynamic) Hostname
- * one struct for cache list
- * one struct for LSP TLV
- */
-struct hostname {
- u_char namelen;
- u_char name[255];
-};
-
-/*
* Supported Protocol IDs
*/
struct nlpids {
diff --git a/isisd/isis_constants.h b/isisd/isis_constants.h
index 4b5ff888ba..f3a5a24dde 100644
--- a/isisd/isis_constants.h
+++ b/isisd/isis_constants.h
@@ -167,10 +167,6 @@
((if_is_broadcast((C)->interface)) ? (C->interface->mtu - LLC_LEN) \
: (C->interface->mtu))
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-
#define MAX_LLC_LEN 0x5ff
#define ETHERTYPE_EXT_LLC 0x8870
diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c
index b0ccdee769..10870d5c50 100644
--- a/isisd/isis_csm.c
+++ b/isisd/isis_csm.c
@@ -37,7 +37,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"
diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c
index 3f532ecf84..2db8271915 100644
--- a/isisd/isis_dr.c
+++ b/isisd/isis_dr.c
@@ -42,7 +42,6 @@
#include "isisd/isis_adjacency.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_pdu.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_dr.h"
#include "isisd/isis_events.h"
diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c
index 9249ad6290..6fa7988304 100644
--- a/isisd/isis_dynhn.c
+++ b/isisd/isis_dynhn.c
@@ -94,38 +94,26 @@ struct isis_dynhn *dynhn_find_by_name(const char *hostname)
struct isis_dynhn *dyn = NULL;
for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn))
- if (strncmp((char *)dyn->name.name, hostname, 255) == 0)
+ if (strncmp(dyn->hostname, hostname, 255) == 0)
return dyn;
return NULL;
}
-void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level)
+void isis_dynhn_insert(const u_char *id, const char *hostname, int level)
{
struct isis_dynhn *dyn;
dyn = dynhn_find_by_id(id);
- if (dyn) {
- memcpy(&dyn->name, hostname, hostname->namelen + 1);
- memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
- dyn->refresh = time(NULL);
- return;
- }
- dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn));
if (!dyn) {
- zlog_warn("isis_dynhn_insert(): out of memory!");
- return;
+ dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn));
+ memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
+ dyn->level = level;
+ listnode_add(dyn_cache, dyn);
}
- /* we also copy the length */
- memcpy(&dyn->name, hostname, hostname->namelen + 1);
- memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
+ snprintf(dyn->hostname, sizeof(dyn->hostname), "%s", hostname);
dyn->refresh = time(NULL);
- dyn->level = level;
-
- listnode_add(dyn_cache, dyn);
-
- return;
}
void isis_dynhn_remove(const u_char *id)
@@ -137,7 +125,6 @@ void isis_dynhn_remove(const u_char *id)
return;
listnode_delete(dyn_cache, dyn);
XFREE(MTYPE_ISIS_DYNHN, dyn);
- return;
}
/*
@@ -155,7 +142,7 @@ void dynhn_print_all(struct vty *vty)
for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) {
vty_out(vty, "%-7d", dyn->level);
vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id),
- dyn->name.name);
+ dyn->hostname);
}
vty_out(vty, " * %s %s\n", sysid_print(isis->sysid),
diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h
index f3ca94d40f..635d79f3f3 100644
--- a/isisd/isis_dynhn.h
+++ b/isisd/isis_dynhn.h
@@ -25,13 +25,13 @@
struct isis_dynhn {
u_char id[ISIS_SYS_ID_LEN];
- struct hostname name;
+ char hostname[256];
time_t refresh;
int level;
};
void dyn_cache_init(void);
-void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level);
+void isis_dynhn_insert(const u_char *id, const char *hostname, int level);
void isis_dynhn_remove(const u_char *id);
struct isis_dynhn *dynhn_find_by_id(const u_char *id);
struct isis_dynhn *dynhn_find_by_name(const char *hostname);
diff --git a/isisd/isis_events.c b/isisd/isis_events.c
index 9af256ba38..1cc90d031c 100644
--- a/isisd/isis_events.c
+++ b/isisd/isis_events.c
@@ -37,7 +37,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 40c6141ab8..51fe41a706 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -44,7 +44,6 @@
#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"
@@ -54,6 +53,7 @@
#include "isisd/isis_spf.h"
#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
+#include "isisd/isis_tlvs.h"
/* staticly assigned vars for printing purposes */
char lsp_bits_string[200]; /* FIXME: enough ? */
@@ -105,19 +105,8 @@ static void lsp_clear_data(struct isis_lsp *lsp)
if (!lsp)
return;
- if (lsp->tlv_data.hostname)
- isis_dynhn_remove(lsp->lsp_header->lsp_id);
-
- if (lsp->own_lsp) {
- if (lsp->tlv_data.nlpids)
- XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.nlpids);
- if (lsp->tlv_data.hostname)
- XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.hostname);
- if (lsp->tlv_data.router_id)
- XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.router_id);
- }
-
- free_tlvs(&lsp->tlv_data);
+ isis_free_tlvs(lsp->tlvs);
+ lsp->tlvs = NULL;
}
static void lsp_destroy(struct isis_lsp *lsp)
@@ -146,7 +135,7 @@ static void lsp_destroy(struct isis_lsp *lsp)
lsp_clear_data(lsp);
- if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) {
+ if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0 && lsp->lspu.frags) {
list_delete(lsp->lspu.frags);
lsp->lspu.frags = NULL;
}
@@ -187,7 +176,7 @@ static void lsp_remove_frags(struct list *frags, dict_t *lspdb)
struct isis_lsp *lsp;
for (ALL_LIST_ELEMENTS(frags, lnode, lnnode, lsp)) {
- dnode = dict_lookup(lspdb, lsp->lsp_header->lsp_id);
+ dnode = dict_lookup(lspdb, lsp->hdr.lsp_id);
lsp_destroy(lsp);
dnode_destroy(dict_delete(lspdb, dnode));
}
@@ -209,7 +198,7 @@ void lsp_search_and_destroy(u_char *id, dict_t *lspdb)
/*
* If this is a zero lsp, remove all the frags now
*/
- if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0) {
+ if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0) {
if (lsp->lspu.frags)
lsp_remove_frags(lsp->lspu.frags, lspdb);
} else {
@@ -231,29 +220,25 @@ void lsp_search_and_destroy(u_char *id, dict_t *lspdb)
* Compares a LSP to given values
* Params are given in net order
*/
-int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
- u_int16_t checksum, u_int16_t rem_lifetime)
+int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
+ uint16_t checksum, uint16_t rem_lifetime)
{
- /* no point in double ntohl on seqnum */
- if (lsp->lsp_header->seq_num == seq_num
- && lsp->lsp_header->checksum == checksum &&
- /*comparing with 0, no need to do ntohl */
- ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0)
- || (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) {
+ if (lsp->hdr.seqno == seqno && lsp->hdr.checksum == checksum
+ && ((lsp->hdr.rem_lifetime == 0 && rem_lifetime == 0)
+ || (lsp->hdr.rem_lifetime != 0 && rem_lifetime != 0))) {
if (isis->debugs & DEBUG_SNP_PACKETS) {
zlog_debug(
- "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
- " lifetime %us",
- areatag,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime));
+ "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s",
+ areatag, rawlspid_print(lsp->hdr.lsp_id),
+ lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime);
zlog_debug(
- "ISIS-Snp (%s): is equal to ours seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- areatag, ntohl(seq_num), ntohs(checksum),
- ntohs(rem_lifetime));
+ "ISIS-Snp (%s): is equal to ours seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s",
+ areatag, seqno, checksum, rem_lifetime);
}
return LSP_EQUAL;
}
@@ -270,171 +255,136 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
* as given
* in 7.3.16.2.
*/
- if (ntohl(seq_num) > ntohl(lsp->lsp_header->seq_num)
- || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num)
- && ((lsp->lsp_header->rem_lifetime != 0 && rem_lifetime == 0)
- || lsp->lsp_header->checksum != checksum))) {
+ if (seqno > lsp->hdr.seqno
+ || (seqno == lsp->hdr.seqno
+ && ((lsp->hdr.rem_lifetime != 0 && rem_lifetime == 0)
+ || lsp->hdr.checksum != checksum))) {
if (isis->debugs & DEBUG_SNP_PACKETS) {
zlog_debug(
- "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
- " lifetime %us",
- areatag,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(seq_num), ntohs(checksum),
- ntohs(rem_lifetime));
+ "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s",
+ areatag, rawlspid_print(lsp->hdr.lsp_id), seqno,
+ checksum, rem_lifetime);
zlog_debug(
- "ISIS-Snp (%s): is newer than ours seq 0x%08x, "
- "cksum 0x%04x, lifetime %us",
- areatag, ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime));
+ "ISIS-Snp (%s): is newer than ours seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s",
+ areatag, lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime);
}
return LSP_NEWER;
}
if (isis->debugs & DEBUG_SNP_PACKETS) {
+ zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s",
+ areatag, rawlspid_print(lsp->hdr.lsp_id), seqno,
+ checksum, rem_lifetime);
zlog_debug(
- "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
- areatag, rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(seq_num), ntohs(checksum), ntohs(rem_lifetime));
- zlog_debug(
- "ISIS-Snp (%s): is older than ours seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- areatag, ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime));
+ "ISIS-Snp (%s): is older than ours seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s",
+ areatag, lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime);
}
return LSP_OLDER;
}
-static void lsp_auth_add(struct isis_lsp *lsp)
+static void put_lsp_hdr(struct isis_lsp *lsp, size_t *len_pointer)
{
- struct isis_passwd *passwd;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
-
- /*
- * Add the authentication info if its present
- */
- (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd)
- : (passwd = &lsp->area->domain_passwd);
- switch (passwd->type) {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- memcpy(&lsp->tlv_data.auth_info, passwd,
- sizeof(struct isis_passwd));
- tlv_add_authinfo(passwd->type, passwd->len, passwd->passwd,
- lsp->pdu);
- break;
-
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Remember where TLV is written so we can later
- * overwrite the MD5 hash */
- lsp->auth_tlv_offset = stream_get_endp(lsp->pdu);
- memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
- lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5;
- lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE;
- memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
- ISIS_AUTH_MD5_SIZE);
- tlv_add_authinfo(passwd->type, ISIS_AUTH_MD5_SIZE,
- hmac_md5_hash, lsp->pdu);
- break;
-
- default:
- break;
- }
+ uint8_t pdu_type =
+ (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE;
+ struct isis_lsp_hdr *hdr = &lsp->hdr;
+ struct stream *stream = lsp->pdu;
+
+ fill_fixed_hdr(pdu_type, stream);
+
+ if (len_pointer)
+ *len_pointer = stream_get_endp(stream);
+ stream_putw(stream, hdr->pdu_len);
+ stream_putw(stream, hdr->rem_lifetime);
+ stream_put(stream, hdr->lsp_id, sizeof(hdr->lsp_id));
+ stream_putl(stream, hdr->seqno);
+ stream_putw(stream, hdr->checksum);
+ stream_putc(stream, hdr->lsp_bits);
}
-static void lsp_auth_update(struct isis_lsp *lsp)
+static void lsp_add_auth(struct isis_lsp *lsp)
{
struct isis_passwd *passwd;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
- uint16_t checksum, rem_lifetime;
+ passwd = (lsp->level == IS_LEVEL_1) ? &lsp->area->area_passwd
+ : &lsp->area->domain_passwd;
+ isis_tlvs_add_auth(lsp->tlvs, passwd);
+}
- /* For HMAC MD5 we need to recompute the md5 hash and store it */
- (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd)
- : (passwd = &lsp->area->domain_passwd);
- if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5)
- return;
+static void lsp_pack_pdu(struct isis_lsp *lsp)
+{
+ if (!lsp->tlvs)
+ lsp->tlvs = isis_alloc_tlvs();
- /*
- * In transient conditions (when net is configured where authentication
- * config and lsp regenerate schedule is not yet run), there could be
- * an own_lsp with auth_tlv_offset set to 0. In such a case, simply
- * return, when lsp_regenerate is run, lsp will have auth tlv.
- */
- if (lsp->auth_tlv_offset == 0)
- return;
+ lsp_add_auth(lsp);
- /*
- * RFC 5304 set auth value, checksum and remaining lifetime to zero
- * before computation and reset to old values after computation.
- */
- checksum = lsp->lsp_header->checksum;
- rem_lifetime = lsp->lsp_header->rem_lifetime;
- lsp->lsp_header->checksum = 0;
- lsp->lsp_header->rem_lifetime = 0;
- /* Set the authentication value as well to zero */
- memset(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, 0,
- ISIS_AUTH_MD5_SIZE);
- /* Compute autentication value */
- hmac_md5(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu),
- (unsigned char *)&passwd->passwd, passwd->len,
- (unsigned char *)&hmac_md5_hash);
- /* Copy the hash into the stream */
- memcpy(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, hmac_md5_hash,
- ISIS_AUTH_MD5_SIZE);
- memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
- ISIS_AUTH_MD5_SIZE);
- /* Copy back the checksum and remaining lifetime */
- lsp->lsp_header->checksum = checksum;
- lsp->lsp_header->rem_lifetime = rem_lifetime;
+ size_t len_pointer;
+ stream_reset(lsp->pdu);
+ put_lsp_hdr(lsp, &len_pointer);
+ isis_pack_tlvs(lsp->tlvs, lsp->pdu, len_pointer, false, true);
+
+ lsp->hdr.pdu_len = stream_get_endp(lsp->pdu);
+ lsp->hdr.checksum =
+ ntohs(fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
+ stream_get_endp(lsp->pdu) - 12, 12));
}
-void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num)
+void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
{
- u_int32_t newseq;
+ uint32_t newseq;
- if (seq_num == 0 || ntohl(lsp->lsp_header->seq_num) > seq_num)
- newseq = ntohl(lsp->lsp_header->seq_num) + 1;
+ if (seqno == 0 || lsp->hdr.seqno > seqno)
+ newseq = lsp->hdr.seqno + 1;
else
- newseq = seq_num + 1;
-
- lsp->lsp_header->seq_num = htonl(newseq);
-
- /* Recompute authentication and checksum information */
- lsp_auth_update(lsp);
- /* ISO 10589 - 7.3.11 Generation of the checksum
- * The checksum shall be computed over all fields in the LSP which
- * appear
- * after the Remaining Lifetime field. This field (and those appearing
- * before it) are excluded so that the LSP may be aged by systems
- * without
- * requiring recomputation.
- */
- fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
- ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+ newseq = seqno + 1;
+
+ lsp->hdr.seqno = newseq;
+ lsp_pack_pdu(lsp);
isis_spf_schedule(lsp->area, lsp->level);
+}
- return;
+static void lsp_purge(struct isis_lsp *lsp, int level)
+{
+ /* reset stream */
+ lsp_clear_data(lsp);
+ stream_reset(lsp->pdu);
+
+ /* update header */
+ lsp->hdr.checksum = 0;
+ lsp->hdr.rem_lifetime = 0;
+ lsp->level = level;
+ lsp->age_out = lsp->area->max_lsp_lifetime[level - 1];
+
+ lsp_pack_pdu(lsp);
+ lsp_set_all_srmflags(lsp);
}
/*
- * Genetates checksum for LSP and its frags
+ * Generates checksum for LSP and its frags
*/
-static void lsp_seqnum_update(struct isis_lsp *lsp0)
+static void lsp_seqno_update(struct isis_lsp *lsp0)
{
struct isis_lsp *lsp;
struct listnode *node;
- lsp_inc_seqnum(lsp0, 0);
+ lsp_inc_seqno(lsp0, 0);
if (!lsp0->lspu.frags)
return;
- for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp))
- lsp_inc_seqnum(lsp, 0);
+ for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) {
+ if (lsp->tlvs)
+ lsp_inc_seqno(lsp, 0);
+ else
+ lsp_purge(lsp, lsp0->level);
+ }
return;
}
@@ -453,12 +403,10 @@ static u_int8_t lsp_bits_generate(int level, int overload_bit, int attached_bit)
return lsp_bits;
}
-static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream,
+static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
+ struct isis_tlvs *tlvs, struct stream *stream,
struct isis_area *area, int level)
{
- uint32_t expected = 0, found;
- int retval;
-
/* free the old lsp data */
lsp_clear_data(lsp);
@@ -467,50 +415,17 @@ static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream,
stream_free(lsp->pdu);
lsp->pdu = stream_dup(stream);
- /* setting pointers to the correct place */
- lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
- lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
- + ISIS_FIXED_HDR_LEN);
+ memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr));
lsp->area = area;
lsp->level = level;
lsp->age_out = ZERO_AGE_LIFETIME;
lsp->installed = time(NULL);
- /*
- * Get LSP data i.e. TLVs
- */
- expected |= TLVFLAG_AUTH_INFO;
- expected |= TLVFLAG_AREA_ADDRS;
- expected |= TLVFLAG_IS_NEIGHS;
- expected |= TLVFLAG_NLPID;
- if (area->dynhostname)
- expected |= TLVFLAG_DYN_HOSTNAME;
- if (area->newmetric) {
- expected |= TLVFLAG_TE_IS_NEIGHS;
- expected |= TLVFLAG_TE_IPV4_REACHABILITY;
- expected |= TLVFLAG_TE_ROUTER_ID;
- }
- expected |= TLVFLAG_MT_ROUTER_INFORMATION;
- expected |= TLVFLAG_IPV4_ADDR;
- expected |= TLVFLAG_IPV4_INT_REACHABILITY;
- expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
- expected |= TLVFLAG_IPV6_ADDR;
- expected |= TLVFLAG_IPV6_REACHABILITY;
-
- retval = parse_tlvs(area->area_tag,
- STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN
- + ISIS_LSP_HDR_LEN,
- ntohs(lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN
- - ISIS_LSP_HDR_LEN,
- &expected, &found, &lsp->tlv_data, NULL);
- if (retval != ISIS_OK) {
- zlog_warn("Could not parse LSP");
- return;
- }
- if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname)) {
- isis_dynhn_insert(lsp->lsp_header->lsp_id,
- lsp->tlv_data.hostname,
- (lsp->lsp_header->lsp_bits & LSPBIT_IST)
+ lsp->tlvs = tlvs;
+
+ if (area->dynhostname && lsp->tlvs->hostname) {
+ isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname,
+ (lsp->hdr.lsp_bits & LSPBIT_IST)
== IS_LEVEL_1_AND_2
? IS_LEVEL_2
: IS_LEVEL_1);
@@ -519,44 +434,55 @@ static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream,
return;
}
-void lsp_update(struct isis_lsp *lsp, struct stream *stream,
- struct isis_area *area, int level)
+void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
+ struct isis_tlvs *tlvs, struct stream *stream,
+ struct isis_area *area, int level, bool confusion)
{
dnode_t *dnode = NULL;
/* Remove old LSP from database. This is required since the
* lsp_update_data will free the lsp->pdu (which has the key, lsp_id)
- * and will update it with the new data in the stream. */
- dnode = dict_lookup(area->lspdb[level - 1], lsp->lsp_header->lsp_id);
+ * and will update it with the new data in the stream.
+ * XXX: This doesn't hold true anymore since the header is now a copy.
+ * keeping the LSP in the dict if it is already present should be possible */
+ dnode = dict_lookup(area->lspdb[level - 1], lsp->hdr.lsp_id);
if (dnode)
dnode_destroy(dict_delete(area->lspdb[level - 1], dnode));
if (lsp->own_lsp) {
zlog_err(
"ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP",
- area->area_tag,
- rawlspid_print(lsp->lsp_header->lsp_id));
+ area->area_tag, rawlspid_print(lsp->hdr.lsp_id));
lsp_clear_data(lsp);
lsp->own_lsp = 0;
}
- /* rebuild the lsp data */
- lsp_update_data(lsp, stream, area, level);
+ if (confusion) {
+ lsp_clear_data(lsp);
+ if (lsp->pdu != NULL)
+ stream_free(lsp->pdu);
+ lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
+ lsp->age_out = ZERO_AGE_LIFETIME;
+ lsp->hdr.rem_lifetime = 0;
+ lsp_pack_pdu(lsp);
+ } else {
+ lsp_update_data(lsp, hdr, tlvs, stream, area, level);
+ }
/* insert the lsp back into the database */
lsp_insert(lsp, area->lspdb[level - 1]);
}
/* creation of LSP directly from what we received */
-struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream,
- u_int16_t pdu_len,
- struct isis_lsp *lsp0,
- struct isis_area *area, int level)
+struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr,
+ struct isis_tlvs *tlvs,
+ struct stream *stream, struct isis_lsp *lsp0,
+ struct isis_area *area, int level)
{
struct isis_lsp *lsp;
lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp));
- lsp_update_data(lsp, stream, area, level);
+ lsp_update_data(lsp, hdr, tlvs, stream, area, level);
if (lsp0 == NULL) {
/*
@@ -576,8 +502,8 @@ struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream,
}
struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
- u_int16_t rem_lifetime, u_int32_t seq_num,
- u_int8_t lsp_bits, u_int16_t checksum, int level)
+ uint16_t rem_lifetime, uint32_t seqno,
+ uint8_t lsp_bits, uint16_t checksum, int level)
{
struct isis_lsp *lsp;
@@ -587,44 +513,32 @@ struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
if (LSP_FRAGMENT(lsp_id) == 0)
lsp->lspu.frags = list_new();
- lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
- lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
- + ISIS_FIXED_HDR_LEN);
- /* at first we fill the FIXED HEADER */
- (level == IS_LEVEL_1) ? fill_fixed_hdr(lsp->isis_header, L1_LINK_STATE)
- : fill_fixed_hdr(lsp->isis_header, L2_LINK_STATE);
-
- /* now for the LSP HEADER */
/* Minimal LSP PDU size */
- lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
- memcpy(lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
- lsp->lsp_header->checksum = checksum; /* Provided in network order */
- lsp->lsp_header->seq_num = htonl(seq_num);
- lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
- lsp->lsp_header->lsp_bits = lsp_bits;
+ lsp->hdr.pdu_len = ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN;
+ memcpy(lsp->hdr.lsp_id, lsp_id, sizeof(lsp->hdr.lsp_id));
+ lsp->hdr.checksum = checksum;
+ lsp->hdr.seqno = seqno;
+ lsp->hdr.rem_lifetime = rem_lifetime;
+ lsp->hdr.lsp_bits = lsp_bits;
lsp->level = level;
lsp->age_out = ZERO_AGE_LIFETIME;
-
- stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+ put_lsp_hdr(lsp, NULL);
if (isis->debugs & DEBUG_EVENTS)
zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x",
- sysid_print(lsp_id),
- LSP_PSEUDO_ID(lsp->lsp_header->lsp_id),
- LSP_FRAGMENT(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->pdu_len),
- ntohl(lsp->lsp_header->seq_num));
+ sysid_print(lsp_id), LSP_PSEUDO_ID(lsp->hdr.lsp_id),
+ LSP_FRAGMENT(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
+ lsp->hdr.seqno);
return lsp;
}
void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb)
{
- dict_alloc_insert(lspdb, lsp->lsp_header->lsp_id, lsp);
- if (lsp->lsp_header->seq_num != 0) {
+ dict_alloc_insert(lspdb, lsp->hdr.lsp_id, lsp);
+ if (lsp->hdr.seqno)
isis_spf_schedule(lsp->area, lsp->level);
- }
}
/*
@@ -643,14 +557,13 @@ void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id,
curr = first;
- if (((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime)
+ if (((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
listnode_add(list, first->dict_data);
while (curr) {
curr = dict_next(lspdb, curr);
if (curr
- && ((struct isis_lsp *)(curr->dict_data))
- ->lsp_header->rem_lifetime)
+ && ((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
listnode_add(list, curr->dict_data);
if (curr == last)
break;
@@ -659,77 +572,19 @@ void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id,
return;
}
-/*
- * Build a list of num_lsps LSPs bounded by start_id and stop_id.
- */
-void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps,
- struct list *list, dict_t *lspdb)
-{
- u_char count;
- dnode_t *first, *last, *curr;
-
- first = dict_lower_bound(lspdb, start_id);
- if (!first)
- return;
-
- last = dict_upper_bound(lspdb, stop_id);
-
- curr = first;
-
- listnode_add(list, first->dict_data);
- count = 1;
-
- while (curr) {
- curr = dict_next(lspdb, curr);
- if (curr) {
- listnode_add(list, curr->dict_data);
- count++;
- }
- if (count == num_lsps || curr == last)
- break;
- }
-
- return;
-}
-
-/*
- * Build a list of LSPs with SSN flag set for the given circuit
- */
-void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps,
- struct list *list, dict_t *lspdb)
-{
- dnode_t *dnode, *next;
- struct isis_lsp *lsp;
- u_char count = 0;
-
- dnode = dict_first(lspdb);
- while (dnode != NULL) {
- next = dict_next(lspdb, dnode);
- lsp = dnode_get(dnode);
- if (ISIS_CHECK_FLAG(lsp->SSNflags, circuit)) {
- listnode_add(list, lsp);
- ++count;
- }
- if (count == num_lsps)
- break;
- dnode = next;
- }
-
- return;
-}
-
static void lsp_set_time(struct isis_lsp *lsp)
{
assert(lsp);
- if (lsp->lsp_header->rem_lifetime == 0) {
+ if (lsp->hdr.rem_lifetime == 0) {
if (lsp->age_out > 0)
lsp->age_out--;
return;
}
- lsp->lsp_header->rem_lifetime =
- htons(ntohs(lsp->lsp_header->rem_lifetime) - 1);
+ lsp->hdr.rem_lifetime--;
+ if (lsp->pdu && stream_get_endp(lsp->pdu) >= 12)
+ stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime);
}
static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
@@ -743,7 +598,7 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
dyn = NULL;
if (dyn)
- sprintf((char *)id, "%.14s", dyn->name.name);
+ sprintf((char *)id, "%.14s", dyn->hostname);
else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
sprintf((char *)id, "%.14s", unix_hostname());
else
@@ -756,21 +611,21 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
}
/* Convert the lsp attribute bits to attribute string */
-const char *lsp_bits2string(u_char *lsp_bits)
+static const char *lsp_bits2string(uint8_t lsp_bits)
{
char *pos = lsp_bits_string;
- if (!*lsp_bits)
+ if (!lsp_bits)
return " none";
/* we only focus on the default metric */
pos += sprintf(pos, "%d/",
- ISIS_MASK_LSP_ATT_DEFAULT_BIT(*lsp_bits) ? 1 : 0);
+ ISIS_MASK_LSP_ATT_DEFAULT_BIT(lsp_bits) ? 1 : 0);
pos += sprintf(pos, "%d/",
- ISIS_MASK_LSP_PARTITION_BIT(*lsp_bits) ? 1 : 0);
+ ISIS_MASK_LSP_PARTITION_BIT(lsp_bits) ? 1 : 0);
- pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(*lsp_bits) ? 1 : 0);
+ pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0);
*(pos) = '\0';
@@ -783,276 +638,26 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost)
u_char LSPid[255];
char age_out[8];
- lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
+ lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1);
vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
- vty_out(vty, "%5u ", ntohs(lsp->lsp_header->pdu_len));
- vty_out(vty, "0x%08x ", ntohl(lsp->lsp_header->seq_num));
- vty_out(vty, "0x%04x ", ntohs(lsp->lsp_header->checksum));
- if (ntohs(lsp->lsp_header->rem_lifetime) == 0) {
- snprintf(age_out, 8, "(%u)", lsp->age_out);
+ vty_out(vty, "%5" PRIu16 " ", lsp->hdr.pdu_len);
+ vty_out(vty, "0x%08" PRIx32 " ", lsp->hdr.seqno);
+ vty_out(vty, "0x%04" PRIx16 " ", lsp->hdr.checksum);
+ if (lsp->hdr.rem_lifetime == 0) {
+ snprintf(age_out, 8, "(%d)", lsp->age_out);
age_out[7] = '\0';
vty_out(vty, "%7s ", age_out);
} else
- vty_out(vty, " %5u ", ntohs(lsp->lsp_header->rem_lifetime));
- vty_out(vty, "%s\n", lsp_bits2string(&lsp->lsp_header->lsp_bits));
-}
-
-static void lsp_print_mt_reach(struct list *list, struct vty *vty, char dynhost,
- uint16_t mtid)
-{
- struct listnode *node;
- struct te_is_neigh *neigh;
-
- for (ALL_LIST_ELEMENTS_RO(list, node, neigh)) {
- u_char lspid[255];
-
- lspid_print(neigh->neigh_id, lspid, dynhost, 0);
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- vty_out(vty,
- " Metric : %-8u IS-Extended : %s\n",
- GET_TE_METRIC(neigh), lspid);
- } else {
- vty_out(vty,
- " Metric : %-8u MT-Reach : %s %s\n",
- GET_TE_METRIC(neigh), lspid,
- isis_mtid2str(mtid));
- }
- if (IS_MPLS_TE(isisMplsTE))
- mpls_te_print_detail(vty, neigh);
- }
-}
-
-static void lsp_print_mt_ipv6_reach(struct list *list, struct vty *vty,
- uint16_t mtid)
-{
- struct listnode *node;
- struct ipv6_reachability *ipv6_reach;
- struct in6_addr in6;
- u_char buff[BUFSIZ];
-
- for (ALL_LIST_ELEMENTS_RO(list, node, ipv6_reach)) {
- memset(&in6, 0, sizeof(in6));
- memcpy(in6.s6_addr, ipv6_reach->prefix,
- PSIZE(ipv6_reach->prefix_len));
- inet_ntop(AF_INET6, &in6, (char *)buff, BUFSIZ);
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION)
- == DISTRIBUTION_INTERNAL)
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv6-Internal : %s/%d\n",
- ntohl(ipv6_reach->metric), buff,
- ipv6_reach->prefix_len);
- else
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv6-External : %s/%d\n",
- ntohl(ipv6_reach->metric), buff,
- ipv6_reach->prefix_len);
- } else {
- if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION)
- == DISTRIBUTION_INTERNAL)
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv6-MT-Int : %s/%d %s\n",
- ntohl(ipv6_reach->metric), buff,
- ipv6_reach->prefix_len,
- isis_mtid2str(mtid));
- else
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv6-MT-Ext : %s/%d %s\n",
- ntohl(ipv6_reach->metric), buff,
- ipv6_reach->prefix_len,
- isis_mtid2str(mtid));
- }
- }
-}
-
-static void lsp_print_mt_ipv4_reach(struct list *list, struct vty *vty,
- uint16_t mtid)
-{
- struct listnode *node;
- struct te_ipv4_reachability *te_ipv4_reach;
-
- for (ALL_LIST_ELEMENTS_RO(list, node, te_ipv4_reach)) {
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- /* FIXME: There should be better way to output this
- * stuff. */
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv4-Extended : %s/%d\n",
- ntohl(te_ipv4_reach->te_metric),
- inet_ntoa(newprefix2inaddr(
- &te_ipv4_reach->prefix_start,
- te_ipv4_reach->control)),
- te_ipv4_reach->control & 0x3F);
- } else {
- /* FIXME: There should be better way to output this
- * stuff. */
- vty_out(vty, " Metric : %-8" PRIu32
- " IPv4-MT : %s/%d %s\n",
- ntohl(te_ipv4_reach->te_metric),
- inet_ntoa(newprefix2inaddr(
- &te_ipv4_reach->prefix_start,
- te_ipv4_reach->control)),
- te_ipv4_reach->control & 0x3F,
- isis_mtid2str(mtid));
- }
- }
+ vty_out(vty, " %5" PRIu16 " ", lsp->hdr.rem_lifetime);
+ vty_out(vty, "%s\n", lsp_bits2string(lsp->hdr.lsp_bits));
}
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost)
{
- struct area_addr *area_addr;
- int i;
- struct listnode *lnode;
- struct is_neigh *is_neigh;
- struct ipv4_reachability *ipv4_reach;
- struct in_addr *ipv4_addr;
- struct mt_router_info *mt_router_info;
- struct tlv_mt_ipv6_reachs *mt_ipv6_reachs;
- struct tlv_mt_neighbors *mt_is_neigh;
- struct tlv_mt_ipv4_reachs *mt_ipv4_reachs;
- u_char LSPid[255];
- u_char hostname[255];
- u_char ipv4_reach_prefix[20];
- u_char ipv4_reach_mask[20];
- u_char ipv4_address[20];
-
- lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
lsp_print(lsp, vty, dynhost);
-
- /* for all area address */
- if (lsp->tlv_data.area_addrs)
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.area_addrs, lnode,
- area_addr)) {
- vty_out(vty, " Area Address: %s\n",
- isonet_print(area_addr->area_addr,
- area_addr->addr_len));
- }
-
- /* for the nlpid tlv */
- if (lsp->tlv_data.nlpids) {
- for (i = 0; i < lsp->tlv_data.nlpids->count; i++) {
- switch (lsp->tlv_data.nlpids->nlpids[i]) {
- case NLPID_IP:
- case NLPID_IPV6:
- vty_out(vty, " NLPID : 0x%X\n",
- lsp->tlv_data.nlpids->nlpids[i]);
- break;
- default:
- vty_out(vty, " NLPID : %s\n", "unknown");
- break;
- }
- }
- }
-
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_router_info, lnode,
- mt_router_info)) {
- vty_out(vty, " MT : %s%s\n",
- isis_mtid2str(mt_router_info->mtid),
- mt_router_info->overload ? " (overload)" : "");
- }
-
- /* for the hostname tlv */
- if (lsp->tlv_data.hostname) {
- bzero(hostname, sizeof(hostname));
- memcpy(hostname, lsp->tlv_data.hostname->name,
- lsp->tlv_data.hostname->namelen);
- vty_out(vty, " Hostname : %s\n", hostname);
- }
-
- /* authentication tlv */
- if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED) {
- if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5)
- vty_out(vty, " Auth type : md5\n");
- else if (lsp->tlv_data.auth_info.type
- == ISIS_PASSWD_TYPE_CLEARTXT)
- vty_out(vty, " Auth type : clear text\n");
- }
-
- /* TE router id */
- if (lsp->tlv_data.router_id) {
- memcpy(ipv4_address, inet_ntoa(lsp->tlv_data.router_id->id),
- sizeof(ipv4_address));
- vty_out(vty, " Router ID : %s\n", ipv4_address);
- }
-
- if (lsp->tlv_data.ipv4_addrs)
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_addrs, lnode,
- ipv4_addr)) {
- memcpy(ipv4_address, inet_ntoa(*ipv4_addr),
- sizeof(ipv4_address));
- vty_out(vty, " IPv4 Address: %s\n", ipv4_address);
- }
-
- /* for the IS neighbor tlv */
- if (lsp->tlv_data.is_neighs)
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, lnode,
- is_neigh)) {
- lspid_print(is_neigh->neigh_id, LSPid, dynhost, 0);
- vty_out(vty, " Metric : %-8" PRIu8
- " IS : %s\n",
- is_neigh->metrics.metric_default, LSPid);
- }
-
- /* for the internal reachable tlv */
- if (lsp->tlv_data.ipv4_int_reachs)
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_int_reachs, lnode,
- ipv4_reach)) {
- memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix),
- sizeof(ipv4_reach_prefix));
- memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask),
- sizeof(ipv4_reach_mask));
- vty_out(vty, " Metric : %-8" PRIu8
- " IPv4-Internal : %s %s\n",
- ipv4_reach->metrics.metric_default,
- ipv4_reach_prefix, ipv4_reach_mask);
- }
-
- /* for the external reachable tlv */
- if (lsp->tlv_data.ipv4_ext_reachs)
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_ext_reachs, lnode,
- ipv4_reach)) {
- memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix),
- sizeof(ipv4_reach_prefix));
- memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask),
- sizeof(ipv4_reach_mask));
- vty_out(vty, " Metric : %-8" PRIu8
- " IPv4-External : %s %s\n",
- ipv4_reach->metrics.metric_default,
- ipv4_reach_prefix, ipv4_reach_mask);
- }
-
- /* IPv6 tlv */
- lsp_print_mt_ipv6_reach(lsp->tlv_data.ipv6_reachs, vty,
- ISIS_MT_IPV4_UNICAST);
-
- /* MT IPv6 reachability tlv */
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv6_reachs, lnode,
- mt_ipv6_reachs))
- lsp_print_mt_ipv6_reach(mt_ipv6_reachs->list, vty,
- mt_ipv6_reachs->mtid);
-
- /* TE IS neighbor tlv */
- lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty, dynhost,
- ISIS_MT_IPV4_UNICAST);
-
- /* MT IS neighbor tlv */
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_is_neighs, lnode,
- mt_is_neigh))
- lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost,
- mt_is_neigh->mtid);
-
- /* TE IPv4 tlv */
- lsp_print_mt_ipv4_reach(lsp->tlv_data.te_ipv4_reachs, vty,
- ISIS_MT_IPV4_UNICAST);
-
- /* MT IPv4 reachability tlv */
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv4_reachs, lnode,
- mt_ipv4_reachs))
- lsp_print_mt_ipv4_reach(mt_ipv4_reachs->list, vty,
- mt_ipv4_reachs->mtid);
-
+ if (lsp->tlvs)
+ vty_multiline(vty, " ", "%s", isis_format_tlvs(lsp->tlvs));
vty_out(vty, "\n");
-
- return;
}
/* print all the lsps info in the local lspdb */
@@ -1083,85 +688,6 @@ int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost)
return lsp_count;
}
-static void _lsp_tlv_fit(struct isis_lsp *lsp, struct list **from,
- struct list **to, int frag_thold,
- unsigned int tlv_build_func(struct list *,
- struct stream *,
- void *arg),
- void *arg)
-{
- while (*from && listcount(*from)) {
- unsigned int count;
-
- count = tlv_build_func(*from, lsp->pdu, arg);
-
- if (listcount(*to) != 0 || count != listcount(*from)) {
- struct listnode *node, *nnode;
- void *elem;
-
- for (ALL_LIST_ELEMENTS(*from, node, nnode, elem)) {
- if (!count)
- break;
- listnode_add(*to, elem);
- list_delete_node(*from, node);
- --count;
- }
- } else {
- list_free(*to);
- *to = *from;
- *from = NULL;
- }
- }
-}
-
-#define FRAG_THOLD(S, T) ((STREAM_SIZE(S) * T) / 100)
-
-/* stream*, area->lsp_frag_threshold, increment */
-#define FRAG_NEEDED(S, T, I) \
- (STREAM_SIZE(S) - STREAM_REMAIN(S) + (I) > FRAG_THOLD(S, T))
-
-/* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have
- * variable length (TE TLVs, sub TLVs). */
-static void lsp_tlv_fit(struct isis_lsp *lsp, struct list **from,
- struct list **to, int tlvsize, int frag_thold,
- int tlv_build_func(struct list *, struct stream *))
-{
- int count, i;
-
- /* can we fit all ? */
- if (!FRAG_NEEDED(lsp->pdu, frag_thold,
- listcount(*from) * tlvsize + 2)) {
- tlv_build_func(*from, lsp->pdu);
- if (listcount(*to) != 0) {
- struct listnode *node, *nextnode;
- void *elem;
-
- 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 if (!FRAG_NEEDED(lsp->pdu, frag_thold, tlvsize + 2)) {
- /* fit all we can */
- count = FRAG_THOLD(lsp->pdu, frag_thold) - 2
- - (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu));
- count = count / tlvsize;
- if (count > (int)listcount(*from))
- count = listcount(*from);
- for (i = 0; i < count; i++) {
- listnode_add(*to, listgetdata(listhead(*from)));
- listnode_delete(*from, listgetdata(listhead(*from)));
- }
- tlv_build_func(*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)
{
u_int16_t rem_lifetime;
@@ -1204,155 +730,90 @@ static u_int16_t lsp_refresh_time(struct isis_lsp *lsp, u_int16_t rem_lifetime)
return refresh_time;
}
-static struct isis_lsp *lsp_next_frag(u_char frag_num, struct isis_lsp *lsp0,
- struct isis_area *area, int level)
-{
- struct isis_lsp *lsp;
- u_char frag_id[ISIS_SYS_ID_LEN + 2];
-
- memcpy(frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
- LSP_FRAGMENT(frag_id) = frag_num;
- /* FIXME add authentication TLV for fragment LSPs */
- lsp = lsp_search(frag_id, area->lspdb[level - 1]);
- if (lsp) {
- /* Clear the TLVs */
- lsp_clear_data(lsp);
- return lsp;
- }
- lsp = lsp_new(area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0,
- lsp_bits_generate(level, area->overload_bit,
- area->attached_bit),
- 0, level);
- lsp->area = area;
- lsp->own_lsp = 1;
- lsp_insert(lsp, area->lspdb[level - 1]);
- listnode_add(lsp0->lspu.frags, lsp);
- lsp->lspu.zero_lsp = lsp0;
- return lsp;
-}
-
static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp,
- struct isis_area *area,
- struct tlvs *tlv_data)
+ struct isis_area *area)
{
- struct route_table *er_table;
- struct route_node *rn;
- struct prefix_ipv4 *ipv4;
- struct isis_ext_info *info;
- struct ipv4_reachability *ipreach;
- struct te_ipv4_reachability *te_ipreach;
-
- er_table = get_ext_reach(area, AF_INET, lsp->level);
+ struct route_table *er_table = get_ext_reach(area, AF_INET, lsp->level);
if (!er_table)
return;
- for (rn = route_top(er_table); rn; rn = route_next(rn)) {
+ for (struct route_node *rn = route_top(er_table); rn;
+ rn = route_next(rn)) {
if (!rn->info)
continue;
- ipv4 = (struct prefix_ipv4 *)&rn->p;
- info = rn->info;
- if (area->oldmetric) {
- if (tlv_data->ipv4_ext_reachs == NULL) {
- tlv_data->ipv4_ext_reachs = list_new();
- tlv_data->ipv4_ext_reachs->del = free_tlv;
- }
- ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach));
-
- ipreach->prefix.s_addr = ipv4->prefix.s_addr;
- masklen2ip(ipv4->prefixlen, &ipreach->mask);
- ipreach->prefix.s_addr &= ipreach->mask.s_addr;
-
- if ((info->metric & 0x3f) != info->metric)
- ipreach->metrics.metric_default = 0x3f;
- else
- ipreach->metrics.metric_default = info->metric;
- ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
- listnode_add(tlv_data->ipv4_ext_reachs, ipreach);
- }
- if (area->newmetric) {
- if (tlv_data->te_ipv4_reachs == NULL) {
- tlv_data->te_ipv4_reachs = list_new();
- tlv_data->te_ipv4_reachs->del = free_tlv;
- }
- te_ipreach = XCALLOC(MTYPE_ISIS_TLV,
- sizeof(*te_ipreach) - 1
- + PSIZE(ipv4->prefixlen));
- if (info->metric > MAX_WIDE_PATH_METRIC)
- te_ipreach->te_metric =
- htonl(MAX_WIDE_PATH_METRIC);
- else
- te_ipreach->te_metric = htonl(info->metric);
- te_ipreach->control = ipv4->prefixlen & 0x3f;
- memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
- PSIZE(ipv4->prefixlen));
- listnode_add(tlv_data->te_ipv4_reachs, te_ipreach);
- }
- }
-}
+ struct prefix_ipv4 *ipv4 = (struct prefix_ipv4 *)&rn->p;
+ struct isis_ext_info *info = rn->info;
-static struct list *tlv_get_ipv6_reach_list(struct isis_area *area,
- struct tlvs *tlv_data)
-{
- uint16_t mtid = isis_area_ipv6_topology(area);
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- if (!tlv_data->ipv6_reachs) {
- tlv_data->ipv6_reachs = list_new();
- tlv_data->ipv6_reachs->del = free_tlv;
- }
- return tlv_data->ipv6_reachs;
- }
+ uint32_t metric = info->metric;
+ if (metric > MAX_WIDE_PATH_METRIC)
+ metric = MAX_WIDE_PATH_METRIC;
+ if (area->oldmetric && metric > 0x3f)
+ metric = 0x3f;
- struct tlv_mt_ipv6_reachs *reachs =
- tlvs_get_mt_ipv6_reachs(tlv_data, mtid);
- return reachs->list;
+ if (area->oldmetric)
+ isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4,
+ metric);
+ if (area->newmetric)
+ isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4,
+ metric);
+ }
}
static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp,
- struct isis_area *area,
- struct tlvs *tlv_data)
+ struct isis_area *area)
{
- struct route_table *er_table;
- struct route_node *rn;
- struct prefix_ipv6 *ipv6;
- struct isis_ext_info *info;
- struct ipv6_reachability *ip6reach;
- struct list *reach_list = NULL;
-
- er_table = get_ext_reach(area, AF_INET6, lsp->level);
+ struct route_table *er_table =
+ get_ext_reach(area, AF_INET6, lsp->level);
if (!er_table)
return;
- for (rn = route_top(er_table); rn; rn = route_next(rn)) {
+ for (struct route_node *rn = route_top(er_table); rn;
+ rn = route_next(rn)) {
if (!rn->info)
continue;
- ipv6 = (struct prefix_ipv6 *)&rn->p;
- info = rn->info;
-
- if (!reach_list)
- reach_list = tlv_get_ipv6_reach_list(area, tlv_data);
+ struct prefix_ipv6 *ipv6 = (struct prefix_ipv6 *)&rn->p;
+ struct isis_ext_info *info = rn->info;
- ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach));
+ uint32_t metric = info->metric;
if (info->metric > MAX_WIDE_PATH_METRIC)
- ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC);
- else
- ip6reach->metric = htonl(info->metric);
- ip6reach->control_info = DISTRIBUTION_EXTERNAL;
- ip6reach->prefix_len = ipv6->prefixlen;
- memcpy(ip6reach->prefix, ipv6->prefix.s6_addr,
- sizeof(ip6reach->prefix));
- listnode_add(reach_list, ip6reach);
+ metric = MAX_WIDE_PATH_METRIC;
+ isis_tlvs_add_ipv6_reach(
+ lsp->tlvs, isis_area_ipv6_topology(area), ipv6, metric);
}
}
-static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area,
- struct tlvs *tlv_data)
+static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area)
{
- lsp_build_ext_reach_ipv4(lsp, area, tlv_data);
- lsp_build_ext_reach_ipv6(lsp, area, tlv_data);
+ lsp_build_ext_reach_ipv4(lsp, area);
+ lsp_build_ext_reach_ipv6(lsp, area);
+}
+
+static struct isis_lsp *lsp_next_frag(uint8_t frag_num, struct isis_lsp *lsp0,
+ struct isis_area *area, int level)
+{
+ struct isis_lsp *lsp;
+ uint8_t frag_id[ISIS_SYS_ID_LEN + 2];
+
+ memcpy(frag_id, lsp0->hdr.lsp_id, ISIS_SYS_ID_LEN + 1);
+ LSP_FRAGMENT(frag_id) = frag_num;
+
+ lsp = lsp_search(frag_id, area->lspdb[level - 1]);
+ if (lsp) {
+ lsp_clear_data(lsp);
+ return lsp;
+ }
+
+ lsp = lsp_new(area, frag_id, lsp0->hdr.rem_lifetime, 0,
+ lsp_bits_generate(level, area->overload_bit,
+ area->attached_bit),
+ 0, level);
+ lsp->own_lsp = 1;
+ lsp_insert(lsp, area->lspdb[level - 1]);
+ listnode_add(lsp0->lspu.frags, lsp);
+ lsp->lspu.zero_lsp = lsp0;
+ return lsp;
}
/*
@@ -1361,126 +822,69 @@ static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area,
*/
static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
{
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct listnode *node, *ipnode;
int level = lsp->level;
- struct isis_circuit *circuit;
- struct prefix_ipv4 *ipv4;
- struct ipv4_reachability *ipreach;
- struct te_ipv4_reachability *te_ipreach;
- struct isis_adjacency *nei;
- struct prefix_ipv6 *ipv6, ip6prefix;
- struct list *ipv6_reachs = NULL;
- struct ipv6_reachability *ip6reach;
- struct tlvs tlv_data;
- struct isis_lsp *lsp0 = lsp;
- struct in_addr *routerid;
- uint32_t expected = 0, found = 0;
- uint32_t metric;
- u_char zero_id[ISIS_SYS_ID_LEN + 1];
- int retval = ISIS_OK;
- char buf[BUFSIZ];
+ char buf[PREFIX2STR_BUFFER];
+ struct listnode *node;
+ struct isis_lsp *frag;
+
+ lsp_clear_data(lsp);
+ for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag))
+ lsp_clear_data(frag);
+ lsp->tlvs = isis_alloc_tlvs();
lsp_debug("ISIS (%s): Constructing local system LSP for level %d",
area->area_tag, level);
- /*
- * Building the zero lsp
- */
- memset(zero_id, 0, ISIS_SYS_ID_LEN + 1);
-
- /* Reset stream endp. Stream is always there and on every LSP refresh
- * only
- * TLV part of it is overwritten. So we must seek past header we will
- * not
- * touch. */
- stream_reset(lsp->pdu);
- stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Add the authentication info if its present
- */
- lsp_auth_add(lsp);
+ lsp->hdr.lsp_bits = lsp_bits_generate(level, area->overload_bit,
+ area->attached_bit);
- /*
- * First add the tlvs related to area
- */
+ lsp_add_auth(lsp);
- /* Area addresses */
- if (lsp->tlv_data.area_addrs == NULL)
- lsp->tlv_data.area_addrs = list_new();
- list_add_list(lsp->tlv_data.area_addrs, area->area_addrs);
- if (listcount(lsp->tlv_data.area_addrs) > 0)
- tlv_add_area_addrs(lsp->tlv_data.area_addrs, lsp->pdu);
+ isis_tlvs_add_area_addresses(lsp->tlvs, area->area_addrs);
/* Protocols Supported */
if (area->ip_circuits > 0 || area->ipv6_circuits > 0) {
- lsp->tlv_data.nlpids =
- XCALLOC(MTYPE_ISIS_TLV, sizeof(struct nlpids));
- lsp->tlv_data.nlpids->count = 0;
+ struct nlpids nlpids = {.count = 0};
if (area->ip_circuits > 0) {
lsp_debug(
"ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs",
area->area_tag);
- lsp->tlv_data.nlpids->count++;
- lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
+ nlpids.nlpids[nlpids.count] = NLPID_IP;
+ nlpids.count++;
}
if (area->ipv6_circuits > 0) {
lsp_debug(
"ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs",
area->area_tag);
- lsp->tlv_data.nlpids->count++;
- lsp->tlv_data.nlpids
- ->nlpids[lsp->tlv_data.nlpids->count - 1] =
- NLPID_IPV6;
+ nlpids.nlpids[nlpids.count] = NLPID_IPV6;
+ nlpids.count++;
}
- tlv_add_nlpid(lsp->tlv_data.nlpids, lsp->pdu);
+ isis_tlvs_set_protocols_supported(lsp->tlvs, &nlpids);
}
if (area_is_mt(area)) {
lsp_debug("ISIS (%s): Adding MT router tlv...", area->area_tag);
- lsp->tlv_data.mt_router_info = list_new();
- lsp->tlv_data.mt_router_info->del = free_tlv;
struct isis_area_mt_setting **mt_settings;
unsigned int mt_count;
mt_settings = area_mt_settings(area, &mt_count);
for (unsigned int i = 0; i < mt_count; i++) {
- struct mt_router_info *info;
-
- info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info));
- info->mtid = mt_settings[i]->mtid;
- info->overload = mt_settings[i]->overload;
- listnode_add(lsp->tlv_data.mt_router_info, info);
+ isis_tlvs_add_mt_router_info(
+ lsp->tlvs, mt_settings[i]->mtid,
+ mt_settings[i]->overload, false);
lsp_debug("ISIS (%s): MT %s", area->area_tag,
- isis_mtid2str(info->mtid));
+ isis_mtid2str(mt_settings[i]->mtid));
}
- tlv_add_mt_router_info(lsp->tlv_data.mt_router_info, lsp->pdu);
} else {
lsp_debug("ISIS (%s): Not adding MT router tlv (disabled)",
area->area_tag);
}
/* Dynamic Hostname */
if (area->dynhostname) {
- const char *hostname = unix_hostname();
- size_t hostname_len = strlen(hostname);
-
- lsp->tlv_data.hostname =
- XMALLOC(MTYPE_ISIS_TLV, sizeof(struct hostname));
-
- strncpy((char *)lsp->tlv_data.hostname->name, hostname,
- sizeof(lsp->tlv_data.hostname->name));
- if (hostname_len <= MAX_TLV_LEN)
- lsp->tlv_data.hostname->namelen = hostname_len;
- else
- lsp->tlv_data.hostname->namelen = MAX_TLV_LEN;
-
- lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'",
- area->area_tag, lsp->tlv_data.hostname->namelen,
- lsp->tlv_data.hostname->name);
- tlv_add_dynamic_hostname(lsp->tlv_data.hostname, lsp->pdu);
+ isis_tlvs_set_dynamic_hostname(lsp->tlvs, unix_hostname());
+ lsp_debug("ISIS (%s): Adding dynamic hostname '%s'",
+ area->area_tag, unix_hostname());
} else {
lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)",
area->area_tag);
@@ -1491,45 +895,31 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
* into
* LSP and this address is same as router id. */
if (isis->router_id != 0) {
- inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf));
+ struct in_addr id = {.s_addr = isis->router_id};
+ inet_ntop(AF_INET, &id, buf, sizeof(buf));
lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.",
area->area_tag, buf);
- if (lsp->tlv_data.ipv4_addrs == NULL) {
- lsp->tlv_data.ipv4_addrs = list_new();
- lsp->tlv_data.ipv4_addrs->del = free_tlv;
- }
-
- routerid = XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr));
- routerid->s_addr = isis->router_id;
- listnode_add(lsp->tlv_data.ipv4_addrs, routerid);
- tlv_add_in_addr(routerid, lsp->pdu, IPV4_ADDR);
+ isis_tlvs_add_ipv4_address(lsp->tlvs, &id);
/* Exactly same data is put into TE router ID TLV, but only if
* new style
* TLV's are in use. */
if (area->newmetric) {
+
lsp_debug(
"ISIS (%s): Adding router ID also as TE router ID tlv.",
area->area_tag);
- lsp->tlv_data.router_id =
- XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr));
- lsp->tlv_data.router_id->id.s_addr = isis->router_id;
- tlv_add_in_addr(&lsp->tlv_data.router_id->id, lsp->pdu,
- TE_ROUTER_ID);
+ isis_tlvs_set_te_router_id(lsp->tlvs, &id);
}
} else {
lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.",
area->area_tag);
}
- memset(&tlv_data, 0, sizeof(struct tlvs));
-
lsp_debug("ISIS (%s): Adding circuit specific information.",
area->area_tag);
- /*
- * Then build lists of tlvs related to circuits
- */
+ struct isis_circuit *circuit;
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
if (!circuit->interface)
lsp_debug(
@@ -1549,245 +939,94 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
continue;
}
- /*
- * Add IPv4 internal reachability of this circuit
- */
+ uint32_t metric = area->oldmetric
+ ? circuit->metric[level - 1]
+ : circuit->te_metric[level - 1];
+
if (circuit->ip_router && circuit->ip_addrs
&& circuit->ip_addrs->count > 0) {
lsp_debug(
"ISIS (%s): Circuit has IPv4 active, adding respective TLVs.",
area->area_tag);
- if (area->oldmetric) {
- if (tlv_data.ipv4_int_reachs == NULL) {
- tlv_data.ipv4_int_reachs = list_new();
- tlv_data.ipv4_int_reachs->del =
- free_tlv;
- }
- for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs,
- ipnode, ipv4)) {
- ipreach = XMALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct
- ipv4_reachability));
- 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));
- inet_ntop(AF_INET,
- &ipreach->prefix.s_addr, buf,
- sizeof(buf));
+ struct listnode *ipnode;
+ struct prefix_ipv4 *ipv4;
+ for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode,
+ ipv4)) {
+ if (area->oldmetric) {
lsp_debug(
- "ISIS (%s): Adding old-style IP reachability for %s/%d",
- area->area_tag, buf,
- ipv4->prefixlen);
- listnode_add(tlv_data.ipv4_int_reachs,
- ipreach);
- }
- }
- if (area->newmetric) {
- if (tlv_data.te_ipv4_reachs == NULL) {
- tlv_data.te_ipv4_reachs = list_new();
- tlv_data.te_ipv4_reachs->del = free_tlv;
+ "ISIS (%s): Adding old-style IP reachability for %s",
+ area->area_tag,
+ prefix2str(ipv4, buf,
+ sizeof(buf)));
+ isis_tlvs_add_oldstyle_ip_reach(
+ lsp->tlvs, ipv4, metric);
}
- for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs,
- ipnode, ipv4)) {
- /* FIXME All this assumes that we have
- * no sub TLVs. */
- te_ipreach = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct
- te_ipv4_reachability)
- + ((ipv4->prefixlen + 7)
- / 8)
- - 1);
-
- if (area->oldmetric)
- te_ipreach->te_metric = htonl(
- circuit->metric[level
- - 1]);
- else
- te_ipreach->te_metric = htonl(
- circuit->te_metric
- [level - 1]);
-
- te_ipreach->control =
- (ipv4->prefixlen & 0x3F);
- memcpy(&te_ipreach->prefix_start,
- &ipv4->prefix.s_addr,
- (ipv4->prefixlen + 7) / 8);
- inet_ntop(AF_INET, &ipv4->prefix.s_addr,
- buf, sizeof(buf));
+
+ if (area->newmetric) {
lsp_debug(
- "ISIS (%s): Adding te-style IP reachability for %s/%d",
- area->area_tag, buf,
- ipv4->prefixlen);
- listnode_add(tlv_data.te_ipv4_reachs,
- te_ipreach);
+ "ISIS (%s): Adding te-style IP reachability for %s",
+ area->area_tag,
+ prefix2str(ipv4, buf,
+ sizeof(buf)));
+ isis_tlvs_add_extended_ip_reach(
+ lsp->tlvs, ipv4, metric);
}
}
}
- /*
- * Add IPv6 reachability of this circuit
- */
if (circuit->ipv6_router && circuit->ipv6_non_link
&& circuit->ipv6_non_link->count > 0) {
- if (!ipv6_reachs)
- ipv6_reachs = tlv_get_ipv6_reach_list(
- area, &tlv_data);
-
+ struct listnode *ipnode;
+ struct prefix_ipv6 *ipv6;
for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
ipnode, ipv6)) {
- ip6reach = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct ipv6_reachability));
-
- if (area->oldmetric)
- ip6reach->metric = htonl(
- circuit->metric[level - 1]);
- else
- ip6reach->metric = htonl(
- circuit->te_metric[level - 1]);
-
- ip6reach->control_info = 0;
- ip6reach->prefix_len = ipv6->prefixlen;
- memcpy(&ip6prefix, ipv6, sizeof(ip6prefix));
- apply_mask_ipv6(&ip6prefix);
-
- inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr,
- buf, sizeof(buf));
lsp_debug(
- "ISIS (%s): Adding IPv6 reachability for %s/%d",
- area->area_tag, buf, ipv6->prefixlen);
-
- memcpy(ip6reach->prefix,
- ip6prefix.prefix.s6_addr,
- sizeof(ip6reach->prefix));
- listnode_add(ipv6_reachs, ip6reach);
+ "ISIS (%s): Adding IPv6 reachability for %s",
+ area->area_tag,
+ prefix2str(ipv6, buf, sizeof(buf)));
+ isis_tlvs_add_ipv6_reach(
+ lsp->tlvs,
+ isis_area_ipv6_topology(area), ipv6,
+ metric);
}
}
switch (circuit->circ_type) {
case CIRCUIT_T_BROADCAST:
if (level & circuit->is_type) {
- if (area->oldmetric) {
- if (tlv_data.is_neighs == NULL) {
- tlv_data.is_neighs = list_new();
- tlv_data.is_neighs->del =
- free_tlv;
- }
- is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct is_neigh));
- if (level == IS_LEVEL_1)
- memcpy(is_neigh->neigh_id,
- circuit->u.bc
- .l1_desig_is,
- ISIS_SYS_ID_LEN + 1);
- else
- memcpy(is_neigh->neigh_id,
- circuit->u.bc
- .l2_desig_is,
- ISIS_SYS_ID_LEN + 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)) {
- XFREE(MTYPE_ISIS_TLV, is_neigh);
- lsp_debug(
- "ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.",
- area->area_tag);
- } else {
- listnode_add(tlv_data.is_neighs,
- is_neigh);
+ uint8_t *ne_id =
+ (level == IS_LEVEL_1)
+ ? circuit->u.bc.l1_desig_is
+ : circuit->u.bc.l2_desig_is;
+
+ if (LSP_PSEUDO_ID(ne_id)) {
+ if (area->oldmetric) {
lsp_debug(
"ISIS (%s): Adding DIS %s.%02x as old-style neighbor",
area->area_tag,
- sysid_print(
- is_neigh->neigh_id),
- LSP_PSEUDO_ID(
- is_neigh->neigh_id));
+ sysid_print(ne_id),
+ LSP_PSEUDO_ID(ne_id));
+ isis_tlvs_add_oldstyle_reach(
+ lsp->tlvs, ne_id,
+ metric);
}
- }
- if (area->newmetric) {
- if (tlv_data.te_is_neighs == NULL) {
- tlv_data.te_is_neighs =
- list_new();
- tlv_data.te_is_neighs->del =
- free_tlv;
- }
- te_is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct te_is_neigh));
- if (level == IS_LEVEL_1)
- memcpy(te_is_neigh->neigh_id,
- circuit->u.bc
- .l1_desig_is,
- ISIS_SYS_ID_LEN + 1);
- else
- memcpy(te_is_neigh->neigh_id,
- circuit->u.bc
- .l2_desig_is,
- ISIS_SYS_ID_LEN + 1);
- if (area->oldmetric)
- metric = circuit->metric[level
- - 1];
- else
- metric =
- circuit->te_metric[level
- - 1];
- SET_TE_METRIC(te_is_neigh, metric);
- if (!memcmp(te_is_neigh->neigh_id,
- zero_id,
- ISIS_SYS_ID_LEN + 1)) {
- XFREE(MTYPE_ISIS_TLV,
- te_is_neigh);
- lsp_debug(
- "ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.",
- area->area_tag);
- } else {
- /* Check if MPLS_TE is activate
- */
+ if (area->newmetric) {
+ uint8_t subtlvs[256];
+ uint8_t subtlv_len;
+
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,
+ subtlv_len = add_te_subtlvs(
+ subtlvs,
circuit->mtc);
else
- /* Or keep only TE
- * metric with no
- * SubTLVs if MPLS_TE is
- * off */
- te_is_neigh
- ->sub_tlvs_length =
- 0;
+ subtlv_len = 0;
tlvs_add_mt_bcast(
- &tlv_data, circuit,
- level, te_is_neigh);
- XFREE(MTYPE_ISIS_TLV,
- te_is_neigh);
+ lsp->tlvs, circuit,
+ level, ne_id, metric,
+ subtlvs, subtlv_len);
}
}
} else {
@@ -1796,53 +1035,25 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
area->area_tag);
}
break;
- case CIRCUIT_T_P2P:
- nei = circuit->u.p2p.neighbor;
+ case CIRCUIT_T_P2P: {
+ struct isis_adjacency *nei = circuit->u.p2p.neighbor;
if (nei && (level & nei->circuit_t)) {
+ uint8_t ne_id[7];
+ memcpy(ne_id, nei->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(ne_id) = 0;
+
if (area->oldmetric) {
- if (tlv_data.is_neighs == NULL) {
- tlv_data.is_neighs = list_new();
- tlv_data.is_neighs->del =
- free_tlv;
- }
- is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct is_neigh));
- memcpy(is_neigh->neigh_id, nei->sysid,
- ISIS_SYS_ID_LEN);
- 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));
+ sysid_print(ne_id));
+ isis_tlvs_add_oldstyle_reach(
+ lsp->tlvs, ne_id, metric);
}
if (area->newmetric) {
- uint32_t metric;
+ uint8_t subtlvs[256];
+ uint8_t subtlv_len;
- if (tlv_data.te_is_neighs == NULL) {
- tlv_data.te_is_neighs =
- list_new();
- tlv_data.te_is_neighs->del =
- free_tlv;
- }
- te_is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct te_is_neigh));
- 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))
@@ -1861,28 +1072,24 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
/* Add SubTLVs & Adjust real
* size of SubTLVs */
- te_is_neigh->sub_tlvs_length =
- add_te_subtlvs(
- te_is_neigh
- ->sub_tlvs,
- circuit->mtc);
+ subtlv_len = add_te_subtlvs(
+ subtlvs, circuit->mtc);
else
/* Or keep only TE metric with
* no SubTLVs if MPLS_TE is off
*/
- te_is_neigh->sub_tlvs_length =
- 0;
+ subtlv_len = 0;
- tlvs_add_mt_p2p(&tlv_data, circuit,
- te_is_neigh);
- XFREE(MTYPE_ISIS_TLV, te_is_neigh);
+ tlvs_add_mt_p2p(lsp->tlvs, circuit,
+ ne_id, metric, subtlvs,
+ subtlv_len);
}
} else {
lsp_debug(
"ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors",
area->area_tag);
}
- break;
+ } break;
case CIRCUIT_T_LOOPBACK:
break;
default:
@@ -1890,169 +1097,36 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
}
}
- lsp_build_ext_reach(lsp, area, &tlv_data);
-
- lsp_debug("ISIS (%s): LSP construction is complete. Serializing...",
- area->area_tag);
-
- while (tlv_data.ipv4_int_reachs
- && listcount(tlv_data.ipv4_int_reachs)) {
- if (lsp->tlv_data.ipv4_int_reachs == NULL)
- lsp->tlv_data.ipv4_int_reachs = list_new();
- lsp_tlv_fit(lsp, &tlv_data.ipv4_int_reachs,
- &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN,
- area->lsp_frag_threshold, tlv_add_ipv4_int_reachs);
- if (tlv_data.ipv4_int_reachs
- && listcount(tlv_data.ipv4_int_reachs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
- }
-
- while (tlv_data.ipv4_ext_reachs
- && listcount(tlv_data.ipv4_ext_reachs)) {
- if (lsp->tlv_data.ipv4_ext_reachs == NULL)
- lsp->tlv_data.ipv4_ext_reachs = list_new();
- lsp_tlv_fit(lsp, &tlv_data.ipv4_ext_reachs,
- &lsp->tlv_data.ipv4_ext_reachs, IPV4_REACH_LEN,
- area->lsp_frag_threshold, tlv_add_ipv4_ext_reachs);
- if (tlv_data.ipv4_ext_reachs
- && listcount(tlv_data.ipv4_ext_reachs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
- }
-
- while (tlv_data.te_ipv4_reachs && listcount(tlv_data.te_ipv4_reachs)) {
- if (lsp->tlv_data.te_ipv4_reachs == NULL)
- lsp->tlv_data.te_ipv4_reachs = list_new();
- _lsp_tlv_fit(lsp, &tlv_data.te_ipv4_reachs,
- &lsp->tlv_data.te_ipv4_reachs,
- area->lsp_frag_threshold, tlv_add_te_ipv4_reachs,
- NULL);
- if (tlv_data.te_ipv4_reachs
- && listcount(tlv_data.te_ipv4_reachs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
- }
+ lsp_build_ext_reach(lsp, area);
- struct tlv_mt_ipv4_reachs *mt_ipv4_reachs;
- for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv4_reachs, node,
- mt_ipv4_reachs)) {
- while (mt_ipv4_reachs->list
- && listcount(mt_ipv4_reachs->list)) {
- struct tlv_mt_ipv4_reachs *frag_mt_ipv4_reachs;
-
- frag_mt_ipv4_reachs = tlvs_get_mt_ipv4_reachs(
- &lsp->tlv_data, mt_ipv4_reachs->mtid);
- _lsp_tlv_fit(lsp, &mt_ipv4_reachs->list,
- &frag_mt_ipv4_reachs->list,
- area->lsp_frag_threshold,
- tlv_add_te_ipv4_reachs,
- &mt_ipv4_reachs->mtid);
- if (mt_ipv4_reachs->list
- && listcount(mt_ipv4_reachs->list))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id)
- + 1,
- lsp0, area, level);
- }
- }
+ struct isis_tlvs *tlvs = lsp->tlvs;
+ lsp->tlvs = NULL;
- while (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) {
- if (lsp->tlv_data.ipv6_reachs == NULL)
- lsp->tlv_data.ipv6_reachs = list_new();
- _lsp_tlv_fit(
- lsp, &tlv_data.ipv6_reachs, &lsp->tlv_data.ipv6_reachs,
- area->lsp_frag_threshold, tlv_add_ipv6_reachs, NULL);
- if (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
- }
-
- struct tlv_mt_ipv6_reachs *mt_ipv6_reachs;
- for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv6_reachs, node,
- mt_ipv6_reachs)) {
- while (mt_ipv6_reachs->list
- && listcount(mt_ipv6_reachs->list)) {
- struct tlv_mt_ipv6_reachs *frag_mt_ipv6_reachs;
-
- frag_mt_ipv6_reachs = tlvs_get_mt_ipv6_reachs(
- &lsp->tlv_data, mt_ipv6_reachs->mtid);
- _lsp_tlv_fit(lsp, &mt_ipv6_reachs->list,
- &frag_mt_ipv6_reachs->list,
- area->lsp_frag_threshold,
- tlv_add_ipv6_reachs,
- &mt_ipv6_reachs->mtid);
- if (mt_ipv6_reachs->list
- && listcount(mt_ipv6_reachs->list))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id)
- + 1,
- lsp0, area, level);
- }
- }
-
- while (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) {
- if (lsp->tlv_data.is_neighs == NULL)
- lsp->tlv_data.is_neighs = list_new();
- lsp_tlv_fit(lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs,
- IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
- tlv_add_is_neighs);
- if (tlv_data.is_neighs && listcount(tlv_data.is_neighs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
- }
+ lsp_pack_pdu(lsp);
+ size_t tlv_space = STREAM_WRITEABLE(lsp->pdu) - LLC_LEN;
+ lsp_clear_data(lsp);
- while (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) {
- if (lsp->tlv_data.te_is_neighs == NULL)
- lsp->tlv_data.te_is_neighs = list_new();
- _lsp_tlv_fit(lsp, &tlv_data.te_is_neighs,
- &lsp->tlv_data.te_is_neighs,
- area->lsp_frag_threshold, tlv_add_te_is_neighs,
- NULL);
- if (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
- area, level);
+ struct list *fragments = isis_fragment_tlvs(tlvs, tlv_space);
+ if (!fragments) {
+ zlog_warn("BUG: could not fragment own LSP:");
+ log_multiline(LOG_WARNING, " ", "%s", isis_format_tlvs(tlvs));
+ isis_free_tlvs(tlvs);
+ return;
}
+ isis_free_tlvs(tlvs);
- struct tlv_mt_neighbors *mt_neighs;
- for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_is_neighs, node, mt_neighs)) {
- while (mt_neighs->list && listcount(mt_neighs->list)) {
- struct tlv_mt_neighbors *frag_mt_neighs;
-
- frag_mt_neighs = tlvs_get_mt_neighbors(&lsp->tlv_data,
- mt_neighs->mtid);
- _lsp_tlv_fit(lsp, &mt_neighs->list,
- &frag_mt_neighs->list,
- area->lsp_frag_threshold,
- tlv_add_te_is_neighs, &mt_neighs->mtid);
- if (mt_neighs->list && listcount(mt_neighs->list))
- lsp = lsp_next_frag(
- LSP_FRAGMENT(lsp->lsp_header->lsp_id)
- + 1,
- lsp0, area, level);
+ frag = lsp;
+ for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) {
+ if (node != listhead(fragments)) {
+ frag = lsp_next_frag(LSP_FRAGMENT(frag->hdr.lsp_id) + 1,
+ lsp, area, level);
}
+ frag->tlvs = tlvs;
}
-
- lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
-
- free_tlvs(&tlv_data);
-
- /* Validate the LSP */
- retval = parse_tlvs(area->area_tag,
- STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN
- + ISIS_LSP_HDR_LEN,
- stream_get_endp(lsp->pdu) - ISIS_FIXED_HDR_LEN
- - ISIS_LSP_HDR_LEN,
- &expected, &found, &tlv_data, NULL);
- assert(retval == ISIS_OK);
-
+ list_delete(fragments);
+ lsp_debug("ISIS (%s): LSP construction is complete. Serializing...",
+ area->area_tag);
return;
}
@@ -2076,8 +1150,8 @@ int lsp_generate(struct isis_area *area, int level)
oldlsp = lsp_search(lspid, area->lspdb[level - 1]);
if (oldlsp) {
/* FIXME: we should actually initiate a purge */
- seq_num = ntohl(oldlsp->lsp_header->seq_num);
- lsp_search_and_destroy(oldlsp->lsp_header->lsp_id,
+ seq_num = oldlsp->hdr.seqno;
+ lsp_search_and_destroy(oldlsp->hdr.lsp_id,
area->lspdb[level - 1]);
}
rem_lifetime = lsp_rem_lifetime(area, level);
@@ -2092,7 +1166,7 @@ int lsp_generate(struct isis_area *area, int level)
/* build_lsp_data (newlsp, area); */
lsp_build(newlsp, area);
/* time to calculate our checksum */
- lsp_seqnum_update(newlsp);
+ lsp_seqno_update(newlsp);
newlsp->last_generated = time(NULL);
lsp_set_all_srmflags(newlsp);
@@ -2108,15 +1182,14 @@ int lsp_generate(struct isis_area *area, int level)
&area->t_lsp_refresh[level - 1]);
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
- zlog_debug(
- "ISIS-Upd (%s): Building L%d LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
- area->area_tag, level,
- rawlspid_print(newlsp->lsp_header->lsp_id),
- ntohl(newlsp->lsp_header->pdu_len),
- ntohl(newlsp->lsp_header->seq_num),
- ntohs(newlsp->lsp_header->checksum),
- ntohs(newlsp->lsp_header->rem_lifetime), refresh_time);
+ zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16
+ ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16
+ ", lifetime %" PRIu16 "s refresh %" PRIu16 "s",
+ area->area_tag, level,
+ rawlspid_print(newlsp->hdr.lsp_id),
+ newlsp->hdr.pdu_len, newlsp->hdr.seqno,
+ newlsp->hdr.checksum, newlsp->hdr.rem_lifetime,
+ refresh_time);
}
sched_debug(
"ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.",
@@ -2154,24 +1227,21 @@ static int lsp_regenerate(struct isis_area *area, int level)
lsp_clear_data(lsp);
lsp_build(lsp, area);
- lsp->lsp_header->lsp_bits = lsp_bits_generate(level, area->overload_bit,
- area->attached_bit);
rem_lifetime = lsp_rem_lifetime(area, level);
- lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
- lsp_seqnum_update(lsp);
-
+ lsp->hdr.rem_lifetime = rem_lifetime;
lsp->last_generated = time(NULL);
lsp_set_all_srmflags(lsp);
for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
- frag->lsp_header->lsp_bits = lsp_bits_generate(
+ frag->hdr.lsp_bits = lsp_bits_generate(
level, area->overload_bit, area->attached_bit);
/* Set the lifetime values of all the fragments to the same
* value,
* so that no fragment expires before the lsp is refreshed.
*/
- frag->lsp_header->rem_lifetime = htons(rem_lifetime);
+ frag->hdr.rem_lifetime = rem_lifetime;
lsp_set_all_srmflags(frag);
}
+ lsp_seqno_update(lsp);
refresh_time = lsp_refresh_time(lsp, rem_lifetime);
if (level == IS_LEVEL_1)
@@ -2184,14 +1254,12 @@ static int lsp_regenerate(struct isis_area *area, int level)
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
- area->area_tag, level,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->pdu_len),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %" PRIu16
+ ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16
+ ", lifetime %" PRIu16 "s refresh %" PRIu16 "s",
+ area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id),
+ lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime, refresh_time);
}
sched_debug(
"ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.",
@@ -2351,164 +1419,89 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
int level)
{
struct isis_adjacency *adj;
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct es_neigh *es_neigh;
struct list *adj_list;
struct listnode *node;
struct isis_area *area = circuit->area;
+ lsp_clear_data(lsp);
+ lsp->tlvs = isis_alloc_tlvs();
lsp_debug(
"ISIS (%s): Constructing pseudo LSP %s for interface %s level %d",
- area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id),
+ area->area_tag, rawlspid_print(lsp->hdr.lsp_id),
circuit->interface->name, level);
lsp->level = level;
/* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
- lsp->lsp_header->lsp_bits =
+ lsp->hdr.lsp_bits =
lsp_bits_generate(level, 0, circuit->area->attached_bit);
/*
* add self to IS neighbours
*/
- if (circuit->area->oldmetric) {
- if (lsp->tlv_data.is_neighs == NULL) {
- lsp->tlv_data.is_neighs = list_new();
- lsp->tlv_data.is_neighs->del = free_tlv;
- }
- is_neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct is_neigh));
+ uint8_t ne_id[ISIS_SYS_ID_LEN + 1];
- memcpy(&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
- listnode_add(lsp->tlv_data.is_neighs, is_neigh);
+ memcpy(ne_id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(ne_id) = 0;
+
+ if (circuit->area->oldmetric) {
+ isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0);
lsp_debug(
"ISIS (%s): Adding %s.%02x as old-style neighbor (self)",
- area->area_tag, sysid_print(is_neigh->neigh_id),
- LSP_PSEUDO_ID(is_neigh->neigh_id));
+ area->area_tag, sysid_print(ne_id),
+ LSP_PSEUDO_ID(ne_id));
}
if (circuit->area->newmetric) {
- if (lsp->tlv_data.te_is_neighs == NULL) {
- lsp->tlv_data.te_is_neighs = list_new();
- lsp->tlv_data.te_is_neighs->del = free_tlv;
- }
- te_is_neigh =
- XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh));
-
- memcpy(&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
- listnode_add(lsp->tlv_data.te_is_neighs, te_is_neigh);
+ isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST,
+ ne_id, 0, NULL, 0);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
- area->area_tag, sysid_print(te_is_neigh->neigh_id),
- LSP_PSEUDO_ID(te_is_neigh->neigh_id));
+ area->area_tag, sysid_print(ne_id),
+ LSP_PSEUDO_ID(ne_id));
}
adj_list = list_new();
isis_adj_build_up_list(circuit->u.bc.adjdb[level - 1], adj_list);
for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) {
- if (adj->level & level) {
- if ((level == IS_LEVEL_1
- && adj->sys_type == ISIS_SYSTYPE_L1_IS)
- || (level == IS_LEVEL_1
- && adj->sys_type == ISIS_SYSTYPE_L2_IS
- && adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
- || (level == IS_LEVEL_2
- && adj->sys_type == ISIS_SYSTYPE_L2_IS)) {
- /* an IS neighbour -> add it */
- if (circuit->area->oldmetric) {
- is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct is_neigh));
-
- memcpy(&is_neigh->neigh_id, adj->sysid,
- ISIS_SYS_ID_LEN);
- listnode_add(lsp->tlv_data.is_neighs,
- is_neigh);
- lsp_debug(
- "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)",
- area->area_tag,
- sysid_print(is_neigh->neigh_id),
- LSP_PSEUDO_ID(
- is_neigh->neigh_id));
- }
- if (circuit->area->newmetric) {
- te_is_neigh = XCALLOC(
- MTYPE_ISIS_TLV,
- sizeof(struct te_is_neigh));
- memcpy(&te_is_neigh->neigh_id,
- adj->sysid, ISIS_SYS_ID_LEN);
- listnode_add(lsp->tlv_data.te_is_neighs,
- te_is_neigh);
- lsp_debug(
- "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
- area->area_tag,
- sysid_print(
- te_is_neigh->neigh_id),
- LSP_PSEUDO_ID(
- te_is_neigh->neigh_id));
- }
- } else if (level == IS_LEVEL_1
- && adj->sys_type == ISIS_SYSTYPE_ES) {
- /* an ES neigbour add it, if we are building
- * level 1 LSP */
- /* FIXME: the tlv-format is hard to use here */
- if (lsp->tlv_data.es_neighs == NULL) {
- lsp->tlv_data.es_neighs = list_new();
- lsp->tlv_data.es_neighs->del = free_tlv;
- }
- es_neigh = XCALLOC(MTYPE_ISIS_TLV,
- sizeof(struct es_neigh));
-
- memcpy(&es_neigh->first_es_neigh, adj->sysid,
- ISIS_SYS_ID_LEN);
- listnode_add(lsp->tlv_data.es_neighs, es_neigh);
- lsp_debug(
- "ISIS (%s): Adding %s as ES neighbor (peer)",
- area->area_tag,
- sysid_print(es_neigh->first_es_neigh));
- } else {
- lsp_debug(
- "ISIS (%s): Ignoring neighbor %s, level does not match",
- area->area_tag,
- sysid_print(adj->sysid));
- }
- } else {
+ if (!(adj->level & level)) {
lsp_debug(
"ISIS (%s): Ignoring neighbor %s, level does not intersect",
area->area_tag, sysid_print(adj->sysid));
+ continue;
}
- }
- list_delete(adj_list);
-
- lsp_debug("ISIS (%s): Pseudo LSP construction is complete.",
- area->area_tag);
-
- /* Reset endp of stream to overwrite only TLV part of it. */
- stream_reset(lsp->pdu);
- stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Add the authentication info if it's present
- */
- lsp_auth_add(lsp);
-
- if (lsp->tlv_data.is_neighs && listcount(lsp->tlv_data.is_neighs) > 0)
- tlv_add_is_neighs(lsp->tlv_data.is_neighs, lsp->pdu);
- if (lsp->tlv_data.te_is_neighs
- && listcount(lsp->tlv_data.te_is_neighs) > 0)
- tlv_add_te_is_neighs(lsp->tlv_data.te_is_neighs, lsp->pdu,
- NULL);
-
- if (lsp->tlv_data.es_neighs && listcount(lsp->tlv_data.es_neighs) > 0)
- tlv_add_is_neighs(lsp->tlv_data.es_neighs, lsp->pdu);
-
- lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
-
- /* Recompute authentication and checksum information */
- lsp_auth_update(lsp);
- fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
- ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+ if (!(level == IS_LEVEL_1
+ && adj->sys_type == ISIS_SYSTYPE_L1_IS)
+ && !(level == IS_LEVEL_1
+ && adj->sys_type == ISIS_SYSTYPE_L2_IS
+ && adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
+ && !(level == IS_LEVEL_2
+ && adj->sys_type == ISIS_SYSTYPE_L2_IS)) {
+ lsp_debug(
+ "ISIS (%s): Ignoring neighbor %s, level does not match",
+ area->area_tag, sysid_print(adj->sysid));
+ continue;
+ }
+ memcpy(ne_id, adj->sysid, ISIS_SYS_ID_LEN);
+ if (circuit->area->oldmetric) {
+ isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)",
+ area->area_tag, sysid_print(ne_id),
+ LSP_PSEUDO_ID(ne_id));
+ }
+ if (circuit->area->newmetric) {
+ isis_tlvs_add_extended_reach(lsp->tlvs,
+ ISIS_MT_IPV4_UNICAST,
+ ne_id, 0, NULL, 0);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
+ area->area_tag, sysid_print(ne_id),
+ LSP_PSEUDO_ID(ne_id));
+ }
+ }
+ list_delete(adj_list);
return;
}
@@ -2543,7 +1536,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level)
lsp->area = circuit->area;
lsp_build_pseudo(lsp, circuit, level);
-
+ lsp_pack_pdu(lsp);
lsp->own_lsp = 1;
lsp_insert(lsp, lspdb);
lsp_set_all_srmflags(lsp);
@@ -2562,14 +1555,13 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level)
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
+ "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %" PRIu16
+ ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16
+ ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s",
circuit->area->area_tag, level,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->pdu_len),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
+ lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime, refresh_time);
}
return ISIS_OK;
@@ -2599,16 +1591,11 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
rawlspid_print(lsp_id));
return ISIS_ERROR;
}
- lsp_clear_data(lsp);
- lsp_build_pseudo(lsp, circuit, level);
-
- /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
- lsp->lsp_header->lsp_bits =
- lsp_bits_generate(level, 0, circuit->area->attached_bit);
rem_lifetime = lsp_rem_lifetime(circuit->area, level);
- lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
- lsp_inc_seqnum(lsp, 0);
+ lsp->hdr.rem_lifetime = rem_lifetime;
+ lsp_build_pseudo(lsp, circuit, level);
+ lsp_inc_seqno(lsp, 0);
lsp->last_generated = time(NULL);
lsp_set_all_srmflags(lsp);
@@ -2624,14 +1611,13 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
+ "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %" PRIu16
+ ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16
+ ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s",
circuit->area->area_tag, level,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->pdu_len),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
+ lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime, refresh_time);
}
return ISIS_OK;
@@ -2828,8 +1814,7 @@ int lsp_tick(struct thread *thread)
* when
* the first time rem_lifetime becomes 0.
*/
- rem_lifetime =
- ntohs(lsp->lsp_header->rem_lifetime);
+ rem_lifetime = lsp->hdr.rem_lifetime;
lsp_set_time(lsp);
/*
@@ -2839,8 +1824,7 @@ int lsp_tick(struct thread *thread)
* time.
* ISO 10589 - 7.3.16.4 first paragraph.
*/
- if (rem_lifetime == 1
- && lsp->lsp_header->seq_num != 0) {
+ if (rem_lifetime == 1 && lsp->hdr.seqno != 0) {
/* 7.3.16.4 a) set SRM flags on all */
lsp_set_all_srmflags(lsp);
/* 7.3.16.4 b) retain only the header
@@ -2857,13 +1841,11 @@ int lsp_tick(struct thread *thread)
if (lsp->age_out == 0) {
zlog_debug(
- "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
+ "ISIS-Upd (%s): L%u LSP %s seq "
+ "0x%08" PRIx32 " aged out",
area->area_tag, lsp->level,
- rawlspid_print(
- lsp->lsp_header
- ->lsp_id),
- ntohl(lsp->lsp_header
- ->seq_num));
+ rawlspid_print(lsp->hdr.lsp_id),
+ lsp->hdr.seqno);
lsp_destroy(lsp);
lsp = NULL;
dict_delete_free(area->lspdb[level],
@@ -2924,51 +1906,19 @@ int lsp_tick(struct thread *thread)
void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level)
{
struct isis_lsp *lsp;
- u_int16_t seq_num;
- u_int8_t lsp_bits;
lsp = lsp_search(id, circuit->area->lspdb[level - 1]);
if (!lsp)
return;
- /* store old values */
- seq_num = lsp->lsp_header->seq_num;
- lsp_bits = lsp->lsp_header->lsp_bits;
-
- /* reset stream */
- lsp_clear_data(lsp);
- stream_reset(lsp->pdu);
-
- /* update header */
- lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
- memcpy(lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2);
- lsp->lsp_header->checksum = 0;
- lsp->lsp_header->seq_num = seq_num;
- lsp->lsp_header->rem_lifetime = 0;
- lsp->lsp_header->lsp_bits = lsp_bits;
- lsp->level = level;
- lsp->age_out = lsp->area->max_lsp_lifetime[level - 1];
- stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Add and update the authentication info if its present
- */
- lsp_auth_add(lsp);
- lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
- lsp_auth_update(lsp);
- fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
- ntohs(lsp->lsp_header->pdu_len) - 12, 12);
-
- lsp_set_all_srmflags(lsp);
-
- return;
+ lsp_purge(lsp, level);
}
/*
* Purge own LSP that is received and we don't have.
* -> Do as in 7.3.16.4
*/
-void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
+void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
struct isis_area *area)
{
struct isis_lsp *lsp;
@@ -2980,39 +1930,14 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
lsp->area = area;
lsp->level = level;
lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
- lsp->isis_header = (struct isis_fixed_hdr *)STREAM_DATA(lsp->pdu);
- fill_fixed_hdr(lsp->isis_header,
- (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
- : L2_LINK_STATE);
- lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
- + ISIS_FIXED_HDR_LEN);
- memcpy(lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
- stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Set the remaining lifetime to 0
- */
- lsp->lsp_header->rem_lifetime = 0;
+ lsp->age_out = ZERO_AGE_LIFETIME;
- /*
- * Add and update the authentication info if its present
- */
- lsp_auth_add(lsp);
- lsp_auth_update(lsp);
+ memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr));
+ lsp->hdr.rem_lifetime = 0;
- /*
- * Update the PDU length to header plus any authentication TLV.
- */
- lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+ lsp_pack_pdu(lsp);
- /*
- * Put the lsp into LSPdb
- */
lsp_insert(lsp, area->lspdb[lsp->level - 1]);
-
- /*
- * Send in to whole area
- */
lsp_set_all_srmflags(lsp);
return;
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 7bec162719..0f9c749949 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -24,19 +24,19 @@
#ifndef _ZEBRA_ISIS_LSP_H
#define _ZEBRA_ISIS_LSP_H
+#include "isisd/isis_pdu.h"
+
/* Structure for isis_lsp, this structure will only support the fixed
* System ID (Currently 6) (atleast for now). In order to support more
* We will have to split the header into two parts, and for readability
* sake it should better be avoided */
struct isis_lsp {
- struct isis_fixed_hdr *isis_header; /* normally equals pdu */
- struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */
- struct stream *pdu; /* full pdu lsp */
+ struct isis_lsp_hdr hdr;
+ struct stream *pdu; /* full pdu lsp */
union {
struct list *frags;
struct isis_lsp *zero_lsp;
} lspu;
- u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */
u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
int level; /* L1 or L2? */
@@ -47,7 +47,7 @@ struct isis_lsp {
/* used for 60 second counting when rem_lifetime is zero */
int age_out;
struct isis_area *area;
- struct tlvs tlv_data; /* Simplifies TLV access */
+ struct isis_tlvs *tlvs;
};
dict_t *lsp_db_init(void);
@@ -59,13 +59,13 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo);
int lsp_generate_pseudo(struct isis_circuit *circuit, int level);
int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level);
-struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
- u_int16_t rem_lifetime, u_int32_t seq_num,
- u_int8_t lsp_bits, u_int16_t checksum, int level);
-struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream,
- u_int16_t pdu_len,
- struct isis_lsp *lsp0,
- struct isis_area *area, int level);
+struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id,
+ uint16_t rem_lifetime, uint32_t seq_num,
+ uint8_t lsp_bits, uint16_t checksum, int level);
+struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr,
+ struct isis_tlvs *tlvs,
+ struct stream *stream, struct isis_lsp *lsp0,
+ struct isis_area *area, int level);
void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb);
struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb);
@@ -73,12 +73,9 @@ void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps,
struct list *list, dict_t *lspdb);
void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id,
struct list *list, dict_t *lspdb);
-void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps,
- struct list *list, dict_t *lspdb);
-
void lsp_search_and_destroy(u_char *id, dict_t *lspdb);
void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level);
-void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
+void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
struct isis_area *area);
#define LSP_EQUAL 1
@@ -92,16 +89,15 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
(I)[ISIS_SYS_ID_LEN] = 0; \
(I)[ISIS_SYS_ID_LEN + 1] = 0
int lsp_id_cmp(u_char *id1, u_char *id2);
-int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
- u_int16_t checksum, u_int16_t rem_lifetime);
-void lsp_update(struct isis_lsp *lsp, struct stream *stream,
- struct isis_area *area, int level);
-void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num);
+int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
+ uint16_t checksum, uint16_t rem_lifetime);
+void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
+ struct isis_tlvs *tlvs, struct stream *stream,
+ struct isis_area *area, int level, bool confusion);
+void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost);
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 *);
-
/* 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 463e3abcf3..40ceb99fb2 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -52,7 +52,6 @@
#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 */
diff --git a/isisd/isis_memory.c b/isisd/isis_memory.c
index 4ad26cf91f..7d1ad6b049 100644
--- a/isisd/isis_memory.c
+++ b/isisd/isis_memory.c
@@ -31,9 +31,9 @@ DEFINE_MTYPE(ISISD, ISIS_TMP, "ISIS TMP")
DEFINE_MTYPE(ISISD, ISIS_CIRCUIT, "ISIS circuit")
DEFINE_MTYPE(ISISD, ISIS_LSP, "ISIS LSP")
DEFINE_MTYPE(ISISD, ISIS_ADJACENCY, "ISIS adjacency")
+DEFINE_MTYPE(ISISD, ISIS_ADJACENCY_INFO, "ISIS adjacency info")
DEFINE_MTYPE(ISISD, ISIS_AREA, "ISIS area")
DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address")
-DEFINE_MTYPE(ISISD, ISIS_TLV, "ISIS TLV")
DEFINE_MTYPE(ISISD, ISIS_DYNHN, "ISIS dyn hostname")
DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree")
DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex")
diff --git a/isisd/isis_memory.h b/isisd/isis_memory.h
index 7729ebac33..4078c7a671 100644
--- a/isisd/isis_memory.h
+++ b/isisd/isis_memory.h
@@ -30,9 +30,9 @@ DECLARE_MTYPE(ISIS_TMP)
DECLARE_MTYPE(ISIS_CIRCUIT)
DECLARE_MTYPE(ISIS_LSP)
DECLARE_MTYPE(ISIS_ADJACENCY)
+DECLARE_MTYPE(ISIS_ADJACENCY_INFO)
DECLARE_MTYPE(ISIS_AREA)
DECLARE_MTYPE(ISIS_AREA_ADDR)
-DECLARE_MTYPE(ISIS_TLV)
DECLARE_MTYPE(ISIS_DYNHN)
DECLARE_MTYPE(ISIS_SPFTREE)
DECLARE_MTYPE(ISIS_VERTEX)
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 16c789ff59..e8888a5f5b 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -28,6 +28,7 @@
#include "hash.h"
#include "if.h"
#include "command.h"
+#include "log_int.h"
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
@@ -38,7 +39,6 @@
#include "isisd/isisd.h"
#include "isisd/isis_misc.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h"
@@ -46,15 +46,9 @@
/* staticly assigned vars for printing purposes */
struct in_addr new_prefix;
-/* len of xxxx.xxxx.xxxx + place for #0 termination */
-char sysid[15];
-/* len of xxxx.xxxx.xxxx + place for #0 termination */
-char snpa[15];
/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
-char isonet[51];
/* + place for #0 termination */
-/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
-char lspid[21];
+char isonet[51];
/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
char datestring[20];
char nlpidstring[30];
@@ -179,6 +173,26 @@ int sysid2buff(u_char *buff, const char *dotted)
return len;
}
+const char *nlpid2str(uint8_t nlpid)
+{
+ static char buf[4];
+ switch (nlpid) {
+ case NLPID_IP:
+ return "IPv4";
+ case NLPID_IPV6:
+ return "IPv6";
+ case NLPID_SNAP:
+ return "SNAP";
+ case NLPID_CLNP:
+ return "CLNP";
+ case NLPID_ESIS:
+ return "ES-IS";
+ default:
+ snprintf(buf, sizeof(buf), "%" PRIu8, nlpid);
+ return buf;
+ }
+}
+
/*
* converts the nlpids struct (filled by TLV #129)
* into a string
@@ -190,26 +204,7 @@ char *nlpid2string(struct nlpids *nlpids)
int i;
for (i = 0; i < nlpids->count; i++) {
- switch (nlpids->nlpids[i]) {
- case NLPID_IP:
- pos += sprintf(pos, "IPv4");
- break;
- case NLPID_IPV6:
- pos += sprintf(pos, "IPv6");
- break;
- case NLPID_SNAP:
- pos += sprintf(pos, "SNAP");
- break;
- case NLPID_CLNP:
- pos += sprintf(pos, "CLNP");
- break;
- case NLPID_ESIS:
- pos += sprintf(pos, "ES-IS");
- break;
- default:
- pos += sprintf(pos, "unknown");
- break;
- }
+ pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
if (nlpids->count - i > 1)
pos += sprintf(pos, ", ");
}
@@ -220,25 +215,6 @@ char *nlpid2string(struct nlpids *nlpids)
}
/*
- * supports the given af ?
- */
-int speaks(struct nlpids *nlpids, int family)
-{
- int i, speaks = 0;
-
- if (nlpids == (struct nlpids *)NULL)
- return speaks;
- for (i = 0; i < nlpids->count; i++) {
- if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
- speaks = 1;
- if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
- speaks = 1;
- }
-
- return speaks;
-}
-
-/*
* Returns 0 on error, IS-IS Circuit Type on ok
*/
int string2circuit_t(const char *str)
@@ -330,71 +306,53 @@ const char *syst2string(int type)
*/
const char *snpa_print(const u_char *from)
{
- int i = 0;
- u_char *pos = (u_char *)snpa;
-
- if (!from)
- return "unknown";
-
- while (i < ETH_ALEN - 1) {
- if (i & 1) {
- sprintf((char *)pos, "%02x.", *(from + i));
- pos += 3;
- } else {
- sprintf((char *)pos, "%02x", *(from + i));
- pos += 2;
- }
- i++;
- }
+ return isis_format_id(from, ISIS_SYS_ID_LEN);
+}
- sprintf((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
- pos += 2;
- *(pos) = '\0';
+const char *sysid_print(const u_char *from)
+{
+ return isis_format_id(from, ISIS_SYS_ID_LEN);
+}
- return snpa;
+const char *rawlspid_print(const u_char *from)
+{
+ return isis_format_id(from, 8);
}
-const char *sysid_print(const u_char *from)
+#define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00")
+const char *isis_format_id(const uint8_t *id, size_t len)
{
- int i = 0;
- char *pos = sysid;
+#define FORMAT_BUF_COUNT 4
+ static char buf_ring[FORMAT_BUF_COUNT][FORMAT_ID_SIZE];
+ static size_t cur_buf = 0;
- if (!from)
- return "unknown";
+ char *rv;
- while (i < ISIS_SYS_ID_LEN - 1) {
- if (i & 1) {
- sprintf(pos, "%02x.", *(from + i));
- pos += 3;
- } else {
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
- }
- i++;
- }
+ cur_buf++;
+ if (cur_buf >= FORMAT_BUF_COUNT)
+ cur_buf = 0;
- sprintf(pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
- pos += 2;
- *(pos) = '\0';
+ rv = buf_ring[cur_buf];
- return sysid;
-}
+ if (!id) {
+ snprintf(rv, FORMAT_ID_SIZE, "unknown");
+ return rv;
+ }
-const char *rawlspid_print(const u_char *from)
-{
- char *pos = lspid;
- if (!from)
- return "unknown";
- memcpy(pos, sysid_print(from), 15);
- pos += 14;
- sprintf(pos, ".%02x", LSP_PSEUDO_ID(from));
- pos += 3;
- sprintf(pos, "-%02x", LSP_FRAGMENT(from));
- pos += 3;
+ if (len < 6) {
+ snprintf(rv, FORMAT_ID_SIZE, "Short ID");
+ return rv;
+ }
- *(pos) = '\0';
+ snprintf(rv, FORMAT_ID_SIZE, "%02x%02x.%02x%02x.%02x%02x", id[0], id[1],
+ id[2], id[3], id[4], id[5]);
+
+ if (len > 6)
+ snprintf(rv + 14, FORMAT_ID_SIZE - 14, ".%02x", id[6]);
+ if (len > 7)
+ snprintf(rv + 17, FORMAT_ID_SIZE - 17, "-%02x", id[7]);
- return lspid;
+ return rv;
}
const char *time2string(u_int32_t time)
@@ -508,7 +466,7 @@ const char *print_sys_hostname(const u_char *sysid)
dyn = dynhn_find_by_id(sysid);
if (dyn)
- return (const char *)dyn->name.name;
+ return dyn->hostname;
return sysid_print(sysid);
}
@@ -572,3 +530,93 @@ void zlog_dump_data(void *data, int len)
zlog_debug("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
return;
}
+
+static char *qasprintf(const char *format, va_list ap)
+{
+ va_list aq;
+ va_copy(aq, ap);
+
+ int size = 0;
+ char *p = NULL;
+
+ size = vsnprintf(p, size, format, ap);
+
+ if (size < 0) {
+ va_end(aq);
+ return NULL;
+ }
+
+ size++;
+ p = XMALLOC(MTYPE_TMP, size);
+
+ size = vsnprintf(p, size, format, aq);
+ va_end(aq);
+
+ if (size < 0) {
+ XFREE(MTYPE_TMP, p);
+ return NULL;
+ }
+
+ return p;
+}
+
+void log_multiline(int priority, const char *prefix, const char *format, ...)
+{
+ va_list ap;
+ char *p;
+
+ va_start(ap, format);
+ p = qasprintf(format, ap);
+ va_end(ap);
+
+ if (!p)
+ return;
+
+ char *saveptr = NULL;
+ for (char *line = strtok_r(p, "\n", &saveptr); line;
+ line = strtok_r(NULL, "\n", &saveptr)) {
+ zlog(priority, "%s%s", prefix, line);
+ }
+
+ XFREE(MTYPE_TMP, p);
+}
+
+void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
+{
+ va_list ap;
+ char *p;
+
+ va_start(ap, format);
+ p = qasprintf(format, ap);
+ va_end(ap);
+
+ if (!p)
+ return;
+
+ char *saveptr = NULL;
+ for (char *line = strtok_r(p, "\n", &saveptr); line;
+ line = strtok_r(NULL, "\n", &saveptr)) {
+ vty_out(vty, "%s%s\n", prefix, line);
+ }
+
+ XFREE(MTYPE_TMP, p);
+}
+
+void vty_out_timestr(struct vty *vty, time_t uptime)
+{
+ struct tm *tm;
+ time_t difftime = time(NULL);
+ difftime -= uptime;
+ tm = gmtime(&difftime);
+
+ if (difftime < ONE_DAY_SECOND)
+ vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
+ else if (difftime < ONE_WEEK_SECOND)
+ vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
+ tm->tm_min);
+ else
+ vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
+ tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
+ vty_out(vty, " ago");
+}
diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h
index 12ab0fac1c..5a19a1ffa0 100644
--- a/isisd/isis_misc.h
+++ b/isisd/isis_misc.h
@@ -44,7 +44,9 @@ const char *isonet_print(const u_char *, int len);
const char *sysid_print(const u_char *);
const char *snpa_print(const u_char *);
const char *rawlspid_print(const u_char *);
+const char *isis_format_id(const uint8_t *id, size_t len);
const char *time2string(u_int32_t);
+const char *nlpid2str(uint8_t nlpid);
/* typedef struct nlpids nlpids; */
char *nlpid2string(struct nlpids *);
const char *print_sys_hostname(const u_char *sysid);
@@ -53,7 +55,6 @@ void zlog_dump_data(void *data, int len);
/*
* misc functions
*/
-int speaks(struct nlpids *nlpids, int family);
unsigned long isis_jitter(unsigned long timer, unsigned long jitter);
const char *unix_hostname(void);
@@ -77,4 +78,11 @@ enum { ISIS_UI_LEVEL_BRIEF,
ISIS_UI_LEVEL_EXTENSIVE,
};
+#include "lib/log.h"
+void log_multiline(int priority, const char *prefix, const char *format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+struct vty;
+void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+void vty_out_timestr(struct vty *vty, time_t uptime);
#endif
diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c
index 46b57510ac..52646c2624 100644
--- a/isisd/isis_mt.c
+++ b/isisd/isis_mt.c
@@ -24,19 +24,14 @@
#include "isisd/isis_memory.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_adjacency.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_mt.h"
+#include "isisd/isis_tlvs.h"
DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info")
-DEFINE_MTYPE_STATIC(ISISD, MT_NEIGHBORS, "ISIS MT Neighbors for TLV")
-DEFINE_MTYPE_STATIC(ISISD, MT_IPV4_REACHS,
- "ISIS MT IPv4 Reachabilities for TLV")
-DEFINE_MTYPE_STATIC(ISISD, MT_IPV6_REACHS,
- "ISIS MT IPv6 Reachabilities for TLV")
uint16_t isis_area_ipv6_topology(struct isis_area *area)
{
@@ -367,7 +362,7 @@ static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
adj->mt_set[index] = mtid;
}
-bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
+bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
struct isis_adjacency *adj)
{
struct isis_circuit_mt_setting **mt_settings;
@@ -388,17 +383,20 @@ bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count);
for (unsigned int i = 0; i < circuit_mt_count; i++) {
- if (!tlvs->mt_router_info) {
+ if (!tlvs->mt_router_info.count
+ && !tlvs->mt_router_info_empty) {
/* Other end does not have MT enabled */
if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST
&& v4_usable)
adj_mt_set(adj, intersect_count++,
ISIS_MT_IPV4_UNICAST);
} else {
- struct listnode *node;
- struct mt_router_info *info;
- for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node,
- info)) {
+ struct isis_mt_router_info *info_head;
+
+ info_head = (struct isis_mt_router_info *)
+ tlvs->mt_router_info.head;
+ for (struct isis_mt_router_info *info = info_head; info;
+ info = info->next) {
if (mt_settings[i]->mtid == info->mtid) {
bool usable;
switch (info->mtid) {
@@ -456,153 +454,6 @@ void adj_mt_finish(struct isis_adjacency *adj)
adj->mt_count = 0;
}
-/* TLV Router info api */
-struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs,
- uint16_t mtid)
-{
- return lookup_mt_setting(tlvs->mt_router_info, mtid);
-}
-
-/* TLV MT Neighbors api */
-struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs,
- uint16_t mtid)
-{
- return lookup_mt_setting(tlvs->mt_is_neighs, mtid);
-}
-
-static struct tlv_mt_neighbors *tlvs_new_mt_neighbors(uint16_t mtid)
-{
- struct tlv_mt_neighbors *rv;
-
- rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv));
- rv->mtid = mtid;
- rv->list = list_new();
-
- return rv;
-};
-
-static void tlvs_free_mt_neighbors(void *arg)
-{
- struct tlv_mt_neighbors *neighbors = arg;
-
- if (neighbors && neighbors->list)
- list_delete(neighbors->list);
- XFREE(MTYPE_MT_NEIGHBORS, neighbors);
-}
-
-static void tlvs_add_mt_neighbors(struct tlvs *tlvs,
- struct tlv_mt_neighbors *neighbors)
-{
- add_mt_setting(&tlvs->mt_is_neighs, neighbors);
- tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors;
-}
-
-struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid)
-{
- struct tlv_mt_neighbors *neighbors;
-
- neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid);
- if (!neighbors) {
- neighbors = tlvs_new_mt_neighbors(mtid);
- tlvs_add_mt_neighbors(tlvs, neighbors);
- }
- return neighbors;
-}
-
-/* TLV MT IPv4 reach api */
-struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs,
- uint16_t mtid)
-{
- return lookup_mt_setting(tlvs->mt_ipv4_reachs, mtid);
-}
-
-static struct tlv_mt_ipv4_reachs *tlvs_new_mt_ipv4_reachs(uint16_t mtid)
-{
- struct tlv_mt_ipv4_reachs *rv;
-
- rv = XCALLOC(MTYPE_MT_IPV4_REACHS, sizeof(*rv));
- rv->mtid = mtid;
- rv->list = list_new();
-
- return rv;
-};
-
-static void tlvs_free_mt_ipv4_reachs(void *arg)
-{
- struct tlv_mt_ipv4_reachs *reachs = arg;
-
- if (reachs && reachs->list)
- list_delete(reachs->list);
- XFREE(MTYPE_MT_IPV4_REACHS, reachs);
-}
-
-static void tlvs_add_mt_ipv4_reachs(struct tlvs *tlvs,
- struct tlv_mt_ipv4_reachs *reachs)
-{
- add_mt_setting(&tlvs->mt_ipv4_reachs, reachs);
- tlvs->mt_ipv4_reachs->del = tlvs_free_mt_ipv4_reachs;
-}
-
-struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs,
- uint16_t mtid)
-{
- struct tlv_mt_ipv4_reachs *reachs;
-
- reachs = tlvs_lookup_mt_ipv4_reachs(tlvs, mtid);
- if (!reachs) {
- reachs = tlvs_new_mt_ipv4_reachs(mtid);
- tlvs_add_mt_ipv4_reachs(tlvs, reachs);
- }
- return reachs;
-}
-
-/* TLV MT IPv6 reach api */
-struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs,
- uint16_t mtid)
-{
- return lookup_mt_setting(tlvs->mt_ipv6_reachs, mtid);
-}
-
-static struct tlv_mt_ipv6_reachs *tlvs_new_mt_ipv6_reachs(uint16_t mtid)
-{
- struct tlv_mt_ipv6_reachs *rv;
-
- rv = XCALLOC(MTYPE_MT_IPV6_REACHS, sizeof(*rv));
- rv->mtid = mtid;
- rv->list = list_new();
-
- return rv;
-};
-
-static void tlvs_free_mt_ipv6_reachs(void *arg)
-{
- struct tlv_mt_ipv6_reachs *reachs = arg;
-
- if (reachs && reachs->list)
- list_delete(reachs->list);
- XFREE(MTYPE_MT_IPV6_REACHS, reachs);
-}
-
-static void tlvs_add_mt_ipv6_reachs(struct tlvs *tlvs,
- struct tlv_mt_ipv6_reachs *reachs)
-{
- add_mt_setting(&tlvs->mt_ipv6_reachs, reachs);
- tlvs->mt_ipv6_reachs->del = tlvs_free_mt_ipv6_reachs;
-}
-
-struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs,
- uint16_t mtid)
-{
- struct tlv_mt_ipv6_reachs *reachs;
-
- reachs = tlvs_lookup_mt_ipv6_reachs(tlvs, mtid);
- if (!reachs) {
- reachs = tlvs_new_mt_ipv6_reachs(mtid);
- tlvs_add_mt_ipv6_reachs(tlvs, reachs);
- }
- return reachs;
-}
-
static void mt_set_add(uint16_t **mt_set, unsigned int *size,
unsigned int *index, uint16_t mtid)
{
@@ -647,51 +498,46 @@ static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level,
return rv;
}
-static void tlvs_add_mt_set(struct isis_area *area, struct tlvs *tlvs,
+static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
unsigned int mt_count, uint16_t *mt_set,
- struct te_is_neigh *neigh)
+ uint8_t *id, uint32_t metric, uint8_t *subtlvs,
+ uint8_t subtlv_len)
{
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
- struct te_is_neigh *ne_copy;
-
- ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy));
- memcpy(ne_copy, neigh, sizeof(*ne_copy));
-
if (mt_set[i] == ISIS_MT_IPV4_UNICAST) {
- listnode_add(tlvs->te_is_neighs, ne_copy);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor",
- area->area_tag, sysid_print(ne_copy->neigh_id),
- LSP_PSEUDO_ID(ne_copy->neigh_id));
+ area->area_tag, sysid_print(id),
+ LSP_PSEUDO_ID(id));
} else {
- struct tlv_mt_neighbors *neighbors;
-
- neighbors = tlvs_get_mt_neighbors(tlvs, mtid);
- neighbors->list->del = free_tlv;
- listnode_add(neighbors->list, ne_copy);
lsp_debug(
"ISIS (%s): Adding %s.%02x as mt-style neighbor for %s",
- area->area_tag, sysid_print(ne_copy->neigh_id),
- LSP_PSEUDO_ID(ne_copy->neigh_id),
- isis_mtid2str(mtid));
+ area->area_tag, sysid_print(id),
+ LSP_PSEUDO_ID(id), isis_mtid2str(mtid));
}
+ isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, subtlvs,
+ subtlv_len);
}
}
-void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
- int level, struct te_is_neigh *neigh)
+void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
+ int level, uint8_t *id, uint32_t metric,
+ uint8_t *subtlvs, uint8_t subtlv_len)
{
unsigned int mt_count;
uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count);
- tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh);
+ tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, id, metric,
+ subtlvs, subtlv_len);
}
-void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
- struct te_is_neigh *neigh)
+void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
+ uint8_t *id, uint32_t metric, uint8_t *subtlvs,
+ uint8_t subtlv_len)
{
struct isis_adjacency *adj = circuit->u.p2p.neighbor;
- tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh);
+ tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id,
+ metric, subtlvs, subtlv_len);
}
diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h
index eec089228e..95aa99dba0 100644
--- a/isisd/isis_mt.h
+++ b/isisd/isis_mt.h
@@ -24,6 +24,7 @@
#define ISIS_MT_MASK 0x0fff
#define ISIS_MT_OL_MASK 0x8000
+#define ISIS_MT_AT_MASK 0x4000
#define ISIS_MT_IPV4_UNICAST 0
#define ISIS_MT_IPV4_MGMT 1
@@ -64,21 +65,6 @@ struct isis_circuit_mt_setting {
bool enabled;
};
-struct tlv_mt_neighbors {
- ISIS_MT_INFO_FIELDS
- struct list *list;
-};
-
-struct tlv_mt_ipv4_reachs {
- ISIS_MT_INFO_FIELDS
- struct list *list;
-};
-
-struct tlv_mt_ipv6_reachs {
- ISIS_MT_INFO_FIELDS
- struct list *list;
-};
-
const char *isis_mtid2str(uint16_t mtid);
uint16_t isis_str2mtid(const char *name);
@@ -87,27 +73,10 @@ struct isis_area;
struct isis_circuit;
struct tlvs;
struct te_is_neigh;
+struct isis_tlvs;
uint16_t isis_area_ipv6_topology(struct isis_area *area);
-struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs,
- uint16_t mtid);
-
-struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs,
- uint16_t mtid);
-struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs,
- uint16_t mtid);
-
-struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs,
- uint16_t mtid);
-struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs,
- uint16_t mtid);
-
-struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs,
- uint16_t mtid);
-struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs,
- uint16_t mtid);
-
struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area,
uint16_t mtid);
struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area,
@@ -137,12 +106,14 @@ circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid);
int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty);
struct isis_circuit_mt_setting **
circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count);
-bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
+bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
struct isis_adjacency *adj);
bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid);
void adj_mt_finish(struct isis_adjacency *adj);
-void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
- int level, struct te_is_neigh *neigh);
-void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
- struct te_is_neigh *neigh);
+void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
+ int level, uint8_t *id, uint32_t metric,
+ uint8_t *subtlvs, uint8_t subtlv_len);
+void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
+ uint8_t *id, uint32_t metric, uint8_t *subtlvs,
+ uint8_t subtlv_len);
#endif
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index a3706179a6..17ef8935d8 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -44,7 +44,6 @@
#include "isisd/isis_network.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_dr.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_dynhn.h"
#include "isisd/isis_lsp.h"
@@ -54,497 +53,122 @@
#include "isisd/isis_events.h"
#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
+#include "isisd/isis_tlvs.h"
-#define ISIS_MINIMUM_FIXED_HDR_LEN 15
-#define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */
-
-#ifndef PNBBY
-#define PNBBY 8
-#endif /* PNBBY */
-
-/*
- * HELPER FUNCS
- */
-
-/*
- * Compares two sets of area addresses
- */
-static int area_match(struct list *left, struct list *right)
+static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit,
+ int level)
{
- struct area_addr *addr1, *addr2;
- struct listnode *node1, *node2;
-
- for (ALL_LIST_ELEMENTS_RO(left, node1, addr1)) {
- for (ALL_LIST_ELEMENTS_RO(right, node2, addr2)) {
- if (addr1->addr_len == addr2->addr_len
- && !memcmp(addr1->area_addr, addr2->area_addr,
- (int)addr1->addr_len))
- return 1; /* match */
- }
- }
-
- return 0; /* mismatch */
-}
-
-/*
- * Checks whether we should accept a PDU of given level
- */
-static int accept_level(int level, int circuit_t)
-{
- int retval = ((circuit_t & level) == level); /* simple approach */
-
- return retval;
-}
-
-/*
- * Verify authentication information
- * Support cleartext and HMAC MD5 authentication
- */
-static int authentication_check(struct isis_passwd *remote,
- struct isis_passwd *local,
- struct stream *stream, uint32_t auth_tlv_offset)
-{
- unsigned char digest[ISIS_AUTH_MD5_SIZE];
-
- /* Auth fail () - passwd type mismatch */
- if (local->type != remote->type)
- return ISIS_ERROR;
-
- switch (local->type) {
- /* No authentication required */
- case ISIS_PASSWD_TYPE_UNUSED:
- break;
-
- /* Cleartext (ISO 10589) */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- /* Auth fail () - passwd len mismatch */
- if (remote->len != local->len)
- return ISIS_ERROR;
- return memcmp(local->passwd, remote->passwd, local->len);
-
- /* HMAC MD5 (RFC 3567) */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Auth fail () - passwd len mismatch */
- if (remote->len != ISIS_AUTH_MD5_SIZE)
- return ISIS_ERROR;
- /* Set the authentication value to 0 before the check */
- memset(STREAM_DATA(stream) + auth_tlv_offset + 3, 0,
- ISIS_AUTH_MD5_SIZE);
- /* Compute the digest */
- hmac_md5(STREAM_DATA(stream), stream_get_endp(stream),
- (unsigned char *)&(local->passwd), local->len,
- (unsigned char *)&digest);
- /* Copy back the authentication value after the check */
- memcpy(STREAM_DATA(stream) + auth_tlv_offset + 3,
- remote->passwd, ISIS_AUTH_MD5_SIZE);
- return memcmp(digest, remote->passwd, ISIS_AUTH_MD5_SIZE);
+ unsigned long lenp;
+ int retval;
+ u_int16_t length;
+ uint8_t pdu_type =
+ (level == IS_LEVEL_1) ? L1_PARTIAL_SEQ_NUM : L2_PARTIAL_SEQ_NUM;
- default:
- zlog_err("Unsupported authentication type");
- return ISIS_ERROR;
- }
+ isis_circuit_stream(circuit, &circuit->snd_stream);
- /* Authentication pass when no authentication is configured */
- return ISIS_OK;
-}
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
-static int lsp_authentication_check(struct stream *stream,
- struct isis_area *area, int level,
- struct isis_passwd *passwd)
-{
- struct isis_link_state_hdr *hdr;
- uint32_t expected = 0, found = 0, auth_tlv_offset = 0;
- uint16_t checksum, rem_lifetime, pdu_len;
- struct tlvs tlvs;
- int retval = ISIS_OK;
-
- hdr = (struct isis_link_state_hdr *)(STREAM_PNT(stream));
- pdu_len = ntohs(hdr->pdu_len);
- expected |= TLVFLAG_AUTH_INFO;
- auth_tlv_offset = stream_get_getp(stream) + ISIS_LSP_HDR_LEN;
- retval = parse_tlvs(area->area_tag,
- STREAM_PNT(stream) + ISIS_LSP_HDR_LEN,
- pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN,
- &expected, &found, &tlvs, &auth_tlv_offset);
+ lenp = stream_get_endp(circuit->snd_stream);
+ stream_putw(circuit->snd_stream, 0); /* PDU length */
+ stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+ stream_putc(circuit->snd_stream, circuit->idx);
+ stream_putc(circuit->snd_stream, 9); /* code */
+ stream_putc(circuit->snd_stream, 16); /* len */
- if (retval != ISIS_OK) {
- zlog_err(
- "ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, "
- "cksum 0x%04x, lifetime %us, len %u",
- area->area_tag, level, rawlspid_print(hdr->lsp_id),
- ntohl(hdr->seq_num), ntohs(hdr->checksum),
- ntohs(hdr->rem_lifetime), pdu_len);
- if ((isis->debugs & DEBUG_UPDATE_PACKETS)
- && (isis->debugs & DEBUG_PACKET_DUMP))
- zlog_dump_data(STREAM_DATA(stream),
- stream_get_endp(stream));
- return retval;
- }
-
- if (!(found & TLVFLAG_AUTH_INFO)) {
- zlog_err("No authentication tlv in LSP");
- return ISIS_ERROR;
- }
+ stream_putw(circuit->snd_stream, hdr->rem_lifetime);
+ stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
+ stream_putl(circuit->snd_stream, hdr->seqno);
+ stream_putw(circuit->snd_stream, hdr->checksum);
- if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT
- && tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) {
- zlog_err("Unknown authentication type in LSP");
- return ISIS_ERROR;
- }
+ length = (u_int16_t)stream_get_endp(circuit->snd_stream);
+ /* Update PDU length */
+ stream_putw_at(circuit->snd_stream, lenp, length);
- /*
- * RFC 5304 set checksum and remaining lifetime to zero before
- * verification and reset to old values after verification.
- */
- checksum = hdr->checksum;
- rem_lifetime = hdr->rem_lifetime;
- hdr->checksum = 0;
- hdr->rem_lifetime = 0;
- retval = authentication_check(&tlvs.auth_info, passwd, stream,
- auth_tlv_offset);
- hdr->checksum = checksum;
- hdr->rem_lifetime = rem_lifetime;
+ retval = circuit->tx(circuit, level);
+ if (retval != ISIS_OK)
+ zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed",
+ circuit->area->area_tag, level,
+ circuit->interface->name);
return retval;
}
/*
- * Processing helper functions
- */
-static void del_addr(void *val)
-{
- XFREE(MTYPE_ISIS_TMP, val);
-}
-
-static void tlvs_to_adj_area_addrs(struct tlvs *tlvs,
- struct isis_adjacency *adj)
-{
- struct listnode *node;
- struct area_addr *area_addr, *malloced;
-
- if (adj->area_addrs) {
- adj->area_addrs->del = del_addr;
- list_delete(adj->area_addrs);
- }
- adj->area_addrs = list_new();
- if (tlvs->area_addrs) {
- for (ALL_LIST_ELEMENTS_RO(tlvs->area_addrs, node, area_addr)) {
- malloced = XMALLOC(MTYPE_ISIS_TMP,
- sizeof(struct area_addr));
- memcpy(malloced, area_addr, sizeof(struct area_addr));
- listnode_add(adj->area_addrs, malloced);
- }
- }
-}
-
-static int tlvs_to_adj_nlpids(struct tlvs *tlvs, struct isis_adjacency *adj)
-{
- int i;
- struct nlpids *tlv_nlpids;
-
- if (tlvs->nlpids) {
-
- tlv_nlpids = tlvs->nlpids;
- if (tlv_nlpids->count > array_size(adj->nlpids.nlpids))
- return 1;
-
- adj->nlpids.count = tlv_nlpids->count;
-
- for (i = 0; i < tlv_nlpids->count; i++) {
- adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i];
- }
- }
- return 0;
-}
-
-static void tlvs_to_adj_ipv4_addrs(struct tlvs *tlvs,
- struct isis_adjacency *adj)
-{
- struct listnode *node;
- struct in_addr *ipv4_addr, *malloced;
-
- if (adj->ipv4_addrs) {
- adj->ipv4_addrs->del = del_addr;
- list_delete(adj->ipv4_addrs);
- }
- adj->ipv4_addrs = list_new();
- if (tlvs->ipv4_addrs) {
- for (ALL_LIST_ELEMENTS_RO(tlvs->ipv4_addrs, node, ipv4_addr)) {
- malloced =
- XMALLOC(MTYPE_ISIS_TMP, sizeof(struct in_addr));
- memcpy(malloced, ipv4_addr, sizeof(struct in_addr));
- listnode_add(adj->ipv4_addrs, malloced);
- }
- }
-}
-
-static void tlvs_to_adj_ipv6_addrs(struct tlvs *tlvs,
- struct isis_adjacency *adj)
-{
- struct listnode *node;
- struct in6_addr *ipv6_addr, *malloced;
-
- if (adj->ipv6_addrs) {
- adj->ipv6_addrs->del = del_addr;
- list_delete(adj->ipv6_addrs);
- }
- adj->ipv6_addrs = list_new();
- if (tlvs->ipv6_addrs) {
- for (ALL_LIST_ELEMENTS_RO(tlvs->ipv6_addrs, node, ipv6_addr)) {
- malloced = XMALLOC(MTYPE_ISIS_TMP,
- sizeof(struct in6_addr));
- memcpy(malloced, ipv6_addr, sizeof(struct in6_addr));
- listnode_add(adj->ipv6_addrs, malloced);
- }
- }
-}
-
-/*
* RECEIVE SIDE
*/
-/*
- * Process P2P IIH
- * ISO - 10589
- * Section 8.2.5 - Receiving point-to-point IIH PDUs
- *
- */
-static int process_p2p_hello(struct isis_circuit *circuit)
-{
- int retval = ISIS_OK;
- struct isis_p2p_hello_hdr *hdr;
- struct isis_adjacency *adj;
- u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;
- uint16_t pdu_len;
- struct tlvs tlvs;
- int v4_usable = 0, v6_usable = 0;
-
- if (isis->debugs & DEBUG_ADJ_PACKETS) {
- zlog_debug(
- "ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u",
- circuit->area->area_tag, circuit->interface->name,
- circuit_t2string(circuit->is_type),
- circuit->circuit_id);
- if (isis->debugs & DEBUG_PACKET_DUMP)
- zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
- stream_get_endp(circuit->rcv_stream));
- }
-
- if (circuit->circ_type != CIRCUIT_T_P2P) {
- zlog_warn("p2p hello on non p2p circuit");
- return ISIS_WARNING;
- }
-
- if ((stream_get_endp(circuit->rcv_stream)
- - stream_get_getp(circuit->rcv_stream))
- < ISIS_P2PHELLO_HDRLEN) {
- zlog_warn("Packet too short");
- return ISIS_WARNING;
- }
-
- /* 8.2.5.1 PDU acceptance tests */
-
- /* 8.2.5.1 a) external domain untrue */
- /* FIXME: not useful at all? */
-
- /* 8.2.5.1 b) ID Length mismatch */
- /* checked at the handle_pdu */
-
- /* 8.2.5.2 IIH PDU Processing */
-
- /* 8.2.5.2 a) 1) Maximum Area Addresses */
- /* Already checked, and can also be ommited */
-
- /*
- * Get the header
- */
- hdr = (struct isis_p2p_hello_hdr *)STREAM_PNT(circuit->rcv_stream);
- pdu_len = ntohs(hdr->pdu_len);
-
- if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN)
- || pdu_len > ISO_MTU(circuit)
- || pdu_len > stream_get_endp(circuit->rcv_stream)) {
- zlog_warn(
- "ISIS-Adj (%s): Rcvd P2P IIH from (%s) with "
- "invalid pdu length %d",
- circuit->area->area_tag, circuit->interface->name,
- pdu_len);
- return ISIS_WARNING;
- }
-
- /*
- * Set the stream endp to PDU length, ignoring additional padding
- * introduced by transport chips.
- */
- if (pdu_len < stream_get_endp(circuit->rcv_stream))
- stream_set_endp(circuit->rcv_stream, pdu_len);
-
- stream_forward_getp(circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN);
-
- /*
- * Lets get the TLVS now
- */
- expected |= TLVFLAG_AREA_ADDRS;
- expected |= TLVFLAG_AUTH_INFO;
- expected |= TLVFLAG_NLPID;
- expected |= TLVFLAG_IPV4_ADDR;
- expected |= TLVFLAG_IPV6_ADDR;
- expected |= TLVFLAG_MT_ROUTER_INFORMATION;
-
- auth_tlv_offset = stream_get_getp(circuit->rcv_stream);
- retval = parse_tlvs(circuit->area->area_tag,
- STREAM_PNT(circuit->rcv_stream),
- pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN,
- &expected, &found, &tlvs, &auth_tlv_offset);
-
- if (retval > ISIS_WARNING) {
- zlog_warn("parse_tlvs() failed");
- free_tlvs(&tlvs);
- return retval;
- };
-
- if (!(found & TLVFLAG_AREA_ADDRS)) {
- zlog_warn("No Area addresses TLV in P2P IS to IS hello");
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
-
- if (!(found & TLVFLAG_NLPID)) {
- zlog_warn("No supported protocols TLV in P2P IS to IS hello");
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
-
- /* 8.2.5.1 c) Authentication */
- if (circuit->passwd.type) {
- if (!(found & TLVFLAG_AUTH_INFO)
- || authentication_check(&tlvs.auth_info, &circuit->passwd,
- circuit->rcv_stream,
- auth_tlv_offset)) {
- isis_event_auth_failure(
- circuit->area->area_tag,
- "P2P hello authentication failure",
- hdr->source_id);
- free_tlvs(&tlvs);
- return ISIS_OK;
- }
- }
+struct iih_info {
+ struct isis_circuit *circuit;
+ u_char *ssnpa;
+ int level;
- /*
- * check if both ends have an IPv4 address
- */
- if (circuit->ip_addrs && listcount(circuit->ip_addrs) && tlvs.ipv4_addrs
- && listcount(tlvs.ipv4_addrs)) {
- v4_usable = 1;
- }
-
- if (found & TLVFLAG_IPV6_ADDR) {
- /* TBA: check that we have a linklocal ourselves? */
- struct listnode *node;
- struct in6_addr *ip;
- for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip))
- if (IN6_IS_ADDR_LINKLOCAL(ip)) {
- v6_usable = 1;
- break;
- }
+ uint8_t circ_type;
+ uint8_t sys_id[ISIS_SYS_ID_LEN];
+ uint16_t holdtime;
+ uint16_t pdu_len;
- if (!v6_usable)
- zlog_warn(
- "ISIS-Adj: IPv6 addresses present but no link-local "
- "in P2P IIH from %s\n",
- circuit->interface->name);
- }
+ uint8_t circuit_id;
- if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
- zlog_warn(
- "ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n",
- circuit->interface->name);
+ uint8_t priority;
+ uint8_t dis[ISIS_SYS_ID_LEN + 1];
- if (!v6_usable && !v4_usable) {
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
+ bool v4_usable;
+ bool v6_usable;
- /*
- * it's own p2p IIH PDU - discard
- */
- if (!memcmp(hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) {
- zlog_warn("ISIS-Adj (%s): it's own IIH PDU - discarded",
- circuit->area->area_tag);
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
+ struct isis_tlvs *tlvs;
+};
+static int process_p2p_hello(struct iih_info *iih)
+{
/*
* My interpertation of the ISO, if no adj exists we will create one for
* the circuit
*/
- adj = circuit->u.p2p.neighbor;
+ struct isis_adjacency *adj = iih->circuit->u.p2p.neighbor;
/* If an adjacency exists, check it is with the source of the hello
* packets */
if (adj) {
- if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) {
+ if (memcmp(iih->sys_id, adj->sysid, ISIS_SYS_ID_LEN)) {
zlog_debug(
"hello source and adjacency do not match, set adj down\n");
isis_adj_state_change(adj, ISIS_ADJ_DOWN,
"adj do not exist");
- return 0;
+ return ISIS_OK;
}
}
- if (!adj || adj->level != hdr->circuit_t) {
+ if (!adj || adj->level != iih->circ_type) {
if (!adj) {
- adj = isis_new_adj(hdr->source_id, NULL, hdr->circuit_t,
- circuit);
- if (adj == NULL)
- return ISIS_ERROR;
+ adj = isis_new_adj(iih->sys_id, NULL, iih->circ_type,
+ iih->circuit);
} else {
- adj->level = hdr->circuit_t;
+ adj->level = iih->circ_type;
}
- circuit->u.p2p.neighbor = adj;
+ iih->circuit->u.p2p.neighbor = adj;
/* Build lsp with the new neighbor entry when a new
* adjacency is formed. Set adjacency circuit type to
* IIH PDU header circuit type before lsp is regenerated
* when an adjacency is up. This will result in the new
* adjacency entry getting added to the lsp tlv neighbor list.
*/
- adj->circuit_t = hdr->circuit_t;
+ adj->circuit_t = iih->circ_type;
isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL);
adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
}
/* 8.2.6 Monitoring point-to-point adjacencies */
- adj->hold_time = ntohs(hdr->hold_time);
+ adj->hold_time = iih->holdtime;
adj->last_upd = time(NULL);
- /* we do this now because the adj may not survive till the end... */
- tlvs_to_adj_area_addrs(&tlvs, adj);
-
- /* which protocol are spoken ??? */
- if (tlvs_to_adj_nlpids(&tlvs, adj)) {
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
-
- /* we need to copy addresses to the adj */
- if (found & TLVFLAG_IPV4_ADDR)
- tlvs_to_adj_ipv4_addrs(&tlvs, adj);
+ bool changed;
+ isis_tlvs_to_adj(iih->tlvs, adj, &changed);
+ changed |= tlvs_to_adj_mt_set(iih->tlvs, iih->v4_usable, iih->v6_usable,
+ 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);
- }
-
- if (found & TLVFLAG_IPV6_ADDR)
- tlvs_to_adj_ipv6_addrs(&tlvs, adj);
-
- bool mt_set_changed =
- tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj);
+ if (IS_MPLS_TE(isisMplsTE) && iih->circuit->mtc
+ && IS_CIRCUIT_TE(iih->circuit->mtc) && adj->ipv4_address_count)
+ set_circuitparams_rmt_ipaddr(iih->circuit->mtc,
+ adj->ipv4_addresses[0]);
/* lets take care of the expiry */
THREAD_TIMER_OFF(adj->t_expire);
@@ -552,10 +176,11 @@ static int process_p2p_hello(struct isis_circuit *circuit)
&adj->t_expire);
/* 8.2.5.2 a) a match was detected */
- if (area_match(circuit->area->area_addrs, tlvs.area_addrs)) {
+ if (isis_tlvs_area_addresses_match(iih->tlvs,
+ iih->circuit->area->area_addrs)) {
/* 8.2.5.2 a) 2) If the system is L1 - table 5 */
- if (circuit->area->is_type == IS_LEVEL_1) {
- switch (hdr->circuit_t) {
+ if (iih->circuit->area->is_type == IS_LEVEL_1) {
+ switch (iih->circ_type) {
case IS_LEVEL_1:
case IS_LEVEL_1_AND_2:
if (adj->adj_state != ISIS_ADJ_UP) {
@@ -573,8 +198,7 @@ static int process_p2p_hello(struct isis_circuit *circuit)
/* (7) reject - wrong system type event
*/
zlog_warn("wrongSystemType");
- free_tlvs(&tlvs);
- return ISIS_WARNING; /* Reject */
+ return ISIS_WARNING;
} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
/* (6) down - wrong system */
isis_adj_state_change(adj,
@@ -586,8 +210,8 @@ static int process_p2p_hello(struct isis_circuit *circuit)
}
/* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */
- if (circuit->area->is_type == IS_LEVEL_1_AND_2) {
- switch (hdr->circuit_t) {
+ if (iih->circuit->area->is_type == IS_LEVEL_1_AND_2) {
+ switch (iih->circ_type) {
case IS_LEVEL_1:
if (adj->adj_state != ISIS_ADJ_UP) {
/* (6) adj state up */
@@ -648,15 +272,14 @@ static int process_p2p_hello(struct isis_circuit *circuit)
}
/* 8.2.5.2 a) 4) If the system is L2 - table 7 */
- if (circuit->area->is_type == IS_LEVEL_2) {
- switch (hdr->circuit_t) {
+ if (iih->circuit->area->is_type == IS_LEVEL_2) {
+ switch (iih->circ_type) {
case IS_LEVEL_1:
if (adj->adj_state != ISIS_ADJ_UP) {
/* (5) reject - wrong system type event
*/
zlog_warn("wrongSystemType");
- free_tlvs(&tlvs);
- return ISIS_WARNING; /* Reject */
+ return ISIS_WARNING;
} else if ((adj->adj_usage
== ISIS_ADJ_LEVEL1AND2)
|| (adj->adj_usage
@@ -689,8 +312,8 @@ static int process_p2p_hello(struct isis_circuit *circuit)
}
}
/* 8.2.5.2 b) if no match was detected */
- else if (listcount(circuit->area->area_addrs) > 0) {
- if (circuit->area->is_type == IS_LEVEL_1) {
+ else if (listcount(iih->circuit->area->area_addrs) > 0) {
+ if (iih->circuit->area->is_type == IS_LEVEL_1) {
/* 8.2.5.2 b) 1) is_type L1 and adj is not up */
if (adj->adj_state != ISIS_ADJ_UP) {
isis_adj_state_change(adj, ISIS_ADJ_DOWN,
@@ -703,13 +326,12 @@ static int process_p2p_hello(struct isis_circuit *circuit)
}
/* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */
else {
- switch (hdr->circuit_t) {
+ switch (iih->circ_type) {
case IS_LEVEL_1:
if (adj->adj_state != ISIS_ADJ_UP) {
/* (6) reject - Area Mismatch event */
zlog_warn("AreaMismatch");
- free_tlvs(&tlvs);
- return ISIS_WARNING; /* Reject */
+ return ISIS_WARNING;
} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
/* (7) down - area mismatch */
isis_adj_state_change(adj,
@@ -741,7 +363,7 @@ static int process_p2p_hello(struct isis_circuit *circuit)
"Wrong System");
} else if (adj->adj_usage
== ISIS_ADJ_LEVEL1AND2) {
- if (hdr->circuit_t == IS_LEVEL_2) {
+ if (iih->circ_type == IS_LEVEL_2) {
/* (7) down - wrong system */
isis_adj_state_change(
adj, ISIS_ADJ_DOWN,
@@ -763,7 +385,7 @@ static int process_p2p_hello(struct isis_circuit *circuit)
isis_adj_state_change(adj, ISIS_ADJ_DOWN, "Area Mismatch");
}
- if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed) {
+ if (adj->adj_state == ISIS_ADJ_UP && changed) {
lsp_regenerate_schedule(adj->circuit->area,
isis_adj_usage2levels(adj->adj_usage),
0);
@@ -790,387 +412,269 @@ static int process_p2p_hello(struct isis_circuit *circuit)
break;
}
-
if (isis->debugs & DEBUG_ADJ_PACKETS) {
zlog_debug(
"ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s,"
" cir id %02d, length %d",
- circuit->area->area_tag, circuit->interface->name,
- circuit_t2string(circuit->is_type), circuit->circuit_id,
- pdu_len);
+ iih->circuit->area->area_tag,
+ iih->circuit->interface->name,
+ circuit_t2string(iih->circuit->is_type),
+ iih->circuit->circuit_id, iih->pdu_len);
}
- free_tlvs(&tlvs);
-
- return retval;
+ return ISIS_OK;
}
-/*
- * Process IS-IS LAN Level 1/2 Hello PDU
- */
-static int process_lan_hello(int level, struct isis_circuit *circuit,
- const u_char *ssnpa)
+static int process_lan_hello(struct iih_info *iih)
{
- int retval = ISIS_OK;
- struct isis_lan_hello_hdr hdr;
struct isis_adjacency *adj;
- u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;
- struct tlvs tlvs;
- u_char *snpa;
- struct listnode *node;
- int v4_usable = 0, v6_usable = 0;
+ adj = isis_adj_lookup(iih->sys_id,
+ iih->circuit->u.bc.adjdb[iih->level - 1]);
+ if ((adj == NULL) || (memcmp(adj->snpa, iih->ssnpa, ETH_ALEN))
+ || (adj->level != iih->level)) {
+ if (!adj) {
+ /* Do as in 8.4.2.5 */
+ adj = isis_new_adj(iih->sys_id, iih->ssnpa, iih->level,
+ iih->circuit);
+ } else {
+ if (iih->ssnpa) {
+ memcpy(adj->snpa, iih->ssnpa, 6);
+ } else {
+ memset(adj->snpa, ' ', 6);
+ }
+ adj->level = iih->level;
+ }
+ isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL);
- if (isis->debugs & DEBUG_ADJ_PACKETS) {
- zlog_debug(
- "ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, "
- "cirID %u",
- circuit->area->area_tag, level,
- circuit->interface->name,
- circuit_t2string(circuit->is_type),
- circuit->circuit_id);
- if (isis->debugs & DEBUG_PACKET_DUMP)
- zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
- stream_get_endp(circuit->rcv_stream));
+ if (iih->level == IS_LEVEL_1)
+ adj->sys_type = ISIS_SYSTYPE_L1_IS;
+ else
+ adj->sys_type = ISIS_SYSTYPE_L2_IS;
+ list_delete_all_node(
+ iih->circuit->u.bc.lan_neighs[iih->level - 1]);
+ isis_adj_build_neigh_list(
+ iih->circuit->u.bc.adjdb[iih->level - 1],
+ iih->circuit->u.bc.lan_neighs[iih->level - 1]);
+ }
+
+ if (adj->dis_record[iih->level - 1].dis == ISIS_IS_DIS) {
+ u_char *dis = (iih->level == 1)
+ ? iih->circuit->u.bc.l1_desig_is
+ : iih->circuit->u.bc.l2_desig_is;
+
+ if (memcmp(dis, iih->dis, ISIS_SYS_ID_LEN + 1)) {
+ thread_add_event(master, isis_event_dis_status_change,
+ iih->circuit, 0, NULL);
+ memcpy(dis, iih->dis, ISIS_SYS_ID_LEN + 1);
+ }
}
- if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
- zlog_warn("lan hello on non broadcast circuit");
- return ISIS_WARNING;
- }
+ adj->circuit_t = iih->circ_type;
+ adj->hold_time = iih->holdtime;
+ adj->last_upd = time(NULL);
+ adj->prio[iih->level - 1] = iih->priority;
+ memcpy(adj->lanid, iih->dis, ISIS_SYS_ID_LEN + 1);
- if ((stream_get_endp(circuit->rcv_stream)
- - stream_get_getp(circuit->rcv_stream))
- < ISIS_LANHELLO_HDRLEN) {
- zlog_warn("Packet too short");
- return ISIS_WARNING;
+ bool changed;
+ isis_tlvs_to_adj(iih->tlvs, adj, &changed);
+ changed |= tlvs_to_adj_mt_set(iih->tlvs, iih->v4_usable, iih->v6_usable,
+ adj);
+
+ /* lets take care of the expiry */
+ THREAD_TIMER_OFF(adj->t_expire);
+ thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time,
+ &adj->t_expire);
+
+ /*
+ * If the snpa for this circuit is found from LAN Neighbours TLV
+ * we have two-way communication -> adjacency can be put to state "up"
+ */
+ bool own_snpa_found =
+ isis_tlvs_own_snpa_found(iih->tlvs, iih->circuit->u.bc.snpa);
+
+ if (adj->adj_state != ISIS_ADJ_UP) {
+ if (own_snpa_found) {
+ isis_adj_state_change(
+ adj, ISIS_ADJ_UP,
+ "own SNPA found in LAN Neighbours TLV");
+ }
+ } else {
+ if (!own_snpa_found) {
+ isis_adj_state_change(
+ adj, ISIS_ADJ_INITIALIZING,
+ "own SNPA not found in LAN Neighbours TLV");
+ }
}
- if (circuit->ext_domain) {
+ if (adj->adj_state == ISIS_ADJ_UP && changed)
+ lsp_regenerate_schedule(adj->circuit->area, iih->level, 0);
+
+ if (isis->debugs & DEBUG_ADJ_PACKETS) {
zlog_debug(
- "level %d LAN Hello received over circuit with "
- "externalDomain = true",
- level);
- return ISIS_WARNING;
+ "ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, cirID %u, length %zd",
+ iih->circuit->area->area_tag, iih->level,
+ snpa_print(iih->ssnpa), iih->circuit->interface->name,
+ circuit_t2string(iih->circuit->is_type),
+ iih->circuit->circuit_id,
+ stream_get_endp(iih->circuit->rcv_stream));
}
+ return ISIS_OK;
+}
- if (!accept_level(level, circuit->is_type)) {
- if (isis->debugs & DEBUG_ADJ_PACKETS) {
+static int pdu_len_validate(uint16_t pdu_len, struct isis_circuit *circuit)
+{
+ if (pdu_len < stream_get_getp(circuit->rcv_stream)
+ || pdu_len > ISO_MTU(circuit)
+ || pdu_len > stream_get_endp(circuit->rcv_stream))
+ return 1;
+
+ if (pdu_len < stream_get_endp(circuit->rcv_stream))
+ stream_set_endp(circuit->rcv_stream, pdu_len);
+ return 0;
+}
+
+static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
+ u_char *ssnpa)
+{
+ bool p2p_hello = (pdu_type == P2P_HELLO);
+ int level = p2p_hello ? 0
+ : (pdu_type == L1_LAN_HELLO) ? ISIS_LEVEL1
+ : ISIS_LEVEL2;
+ const char *pdu_name =
+ p2p_hello
+ ? "P2P IIH"
+ : (level == ISIS_LEVEL1) ? "L1 LAN IIH" : "L2 LAN IIH";
+
+ if (isis->debugs & DEBUG_ADJ_PACKETS) {
+ zlog_debug("ISIS-Adj (%s): Rcvd %s on %s, cirType %s, cirID %u",
+ circuit->area->area_tag, pdu_name,
+ circuit->interface->name,
+ circuit_t2string(circuit->is_type),
+ circuit->circuit_id);
+ if (isis->debugs & DEBUG_PACKET_DUMP)
+ zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
+ stream_get_endp(circuit->rcv_stream));
+ }
+
+ if (p2p_hello) {
+ if (circuit->circ_type != CIRCUIT_T_P2P) {
+ zlog_warn("p2p hello on non p2p circuit");
+ return ISIS_WARNING;
+ }
+ } else {
+ if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
+ zlog_warn("lan hello on non broadcast circuit");
+ return ISIS_WARNING;
+ }
+
+ if (circuit->ext_domain) {
zlog_debug(
- "ISIS-Adj (%s): Interface level mismatch, %s",
- circuit->area->area_tag,
- circuit->interface->name);
+ "level %d LAN Hello received over circuit with externalDomain = true",
+ level);
+ return ISIS_WARNING;
+ }
+
+ if (!(circuit->is_type & level)) {
+ if (isis->debugs & DEBUG_ADJ_PACKETS) {
+ zlog_debug(
+ "ISIS-Adj (%s): Interface level mismatch, %s",
+ circuit->area->area_tag,
+ circuit->interface->name);
+ }
+ return ISIS_WARNING;
}
- return ISIS_WARNING;
}
-#if 0
- /* Cisco's debug message compatability */
- if (!accept_level (level, circuit->area->is_type))
- {
- if (isis->debugs & DEBUG_ADJ_PACKETS)
- {
- zlog_debug ("ISIS-Adj (%s): is type mismatch",
- circuit->area->area_tag);
+ struct iih_info iih = {
+ .circuit = circuit, .ssnpa = ssnpa, .level = level};
+
+ /* Generic IIH Header */
+ iih.circ_type = stream_getc(circuit->rcv_stream) & 0x03;
+ stream_get(iih.sys_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
+ iih.holdtime = stream_getw(circuit->rcv_stream);
+ iih.pdu_len = stream_getw(circuit->rcv_stream);
+
+ if (p2p_hello) {
+ iih.circuit_id = stream_getc(circuit->rcv_stream);
+ } else {
+ iih.priority = stream_getc(circuit->rcv_stream);
+ stream_get(iih.dis, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
}
- return ISIS_WARNING;
- }
-#endif
- /*
- * Fill the header
- */
- hdr.circuit_t = stream_getc(circuit->rcv_stream);
- stream_get(hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
- hdr.hold_time = stream_getw(circuit->rcv_stream);
- hdr.pdu_len = stream_getw(circuit->rcv_stream);
- hdr.prio = stream_getc(circuit->rcv_stream);
- stream_get(hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
- if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN)
- || hdr.pdu_len > ISO_MTU(circuit)
- || hdr.pdu_len > stream_get_endp(circuit->rcv_stream)) {
+ if (pdu_len_validate(iih.pdu_len, circuit)) {
zlog_warn(
- "ISIS-Adj (%s): Rcvd LAN IIH from (%s) with "
- "invalid pdu length %d",
- circuit->area->area_tag, circuit->interface->name,
- hdr.pdu_len);
+ "ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16,
+ circuit->area->area_tag, pdu_name,
+ circuit->interface->name, iih.pdu_len);
return ISIS_WARNING;
}
- /*
- * Set the stream endp to PDU length, ignoring additional padding
- * introduced by transport chips.
- */
- if (hdr.pdu_len < stream_get_endp(circuit->rcv_stream))
- stream_set_endp(circuit->rcv_stream, hdr.pdu_len);
-
- if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2
- && hdr.circuit_t != IS_LEVEL_1_AND_2
- && (level & hdr.circuit_t) == 0) {
+ if (!p2p_hello && !(level & iih.circ_type)) {
zlog_err("Level %d LAN Hello with Circuit Type %d", level,
- hdr.circuit_t);
+ iih.circ_type);
return ISIS_ERROR;
}
- /*
- * Then get the tlvs
- */
- expected |= TLVFLAG_AUTH_INFO;
- expected |= TLVFLAG_AREA_ADDRS;
- expected |= TLVFLAG_LAN_NEIGHS;
- expected |= TLVFLAG_NLPID;
- expected |= TLVFLAG_IPV4_ADDR;
- expected |= TLVFLAG_IPV6_ADDR;
- expected |= TLVFLAG_MT_ROUTER_INFORMATION;
-
- auth_tlv_offset = stream_get_getp(circuit->rcv_stream);
- retval = parse_tlvs(
- circuit->area->area_tag, STREAM_PNT(circuit->rcv_stream),
- hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN,
- &expected, &found, &tlvs, &auth_tlv_offset);
-
- if (retval > ISIS_WARNING) {
- zlog_warn("parse_tlvs() failed");
+ const char *error_log;
+ int retval = ISIS_WARNING;
+
+ if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
+ circuit->rcv_stream, &iih.tlvs, &error_log)) {
+ zlog_warn("isis_unpack_tlvs() failed: %s", error_log);
goto out;
}
- if (!(found & TLVFLAG_AREA_ADDRS)) {
- zlog_warn(
- "No Area addresses TLV in Level %d LAN IS to IS hello",
- level);
- retval = ISIS_WARNING;
+ if (!iih.tlvs->area_addresses.count) {
+ zlog_warn("No Area addresses TLV in %s", pdu_name);
goto out;
}
- if (!(found & TLVFLAG_NLPID)) {
- zlog_warn(
- "No supported protocols TLV in Level %d LAN IS to IS hello",
- level);
- retval = ISIS_WARNING;
+ if (!iih.tlvs->protocols_supported.count) {
+ zlog_warn("No supported protocols TLV in %s", pdu_name);
goto out;
}
- /* Verify authentication, either cleartext of HMAC MD5 */
- if (circuit->passwd.type) {
- if (!(found & TLVFLAG_AUTH_INFO)
- || authentication_check(&tlvs.auth_info, &circuit->passwd,
- circuit->rcv_stream,
- auth_tlv_offset)) {
- isis_event_auth_failure(
- circuit->area->area_tag,
- "LAN hello authentication failure",
- hdr.source_id);
- retval = ISIS_WARNING;
- goto out;
- }
+ if (!isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd,
+ circuit->rcv_stream, false)) {
+ isis_event_auth_failure(circuit->area->area_tag,
+ "IIH authentication failure",
+ iih.sys_id);
+ goto out;
}
- if (!memcmp(hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN)) {
- zlog_warn("ISIS-Adj (%s): duplicate system ID on interface %s",
- circuit->area->area_tag, circuit->interface->name);
- return ISIS_WARNING;
+ if (!memcmp(iih.sys_id, isis->sysid, ISIS_SYS_ID_LEN)) {
+ zlog_warn(
+ "ISIS-Adj (%s): Received IIH with own sysid - discard",
+ circuit->area->area_tag);
+ goto out;
}
- /*
- * Accept the level 1 adjacency only if a match between local and
- * remote area addresses is found
- */
- if (listcount(circuit->area->area_addrs) == 0
- || (level == IS_LEVEL_1
- && area_match(circuit->area->area_addrs, tlvs.area_addrs)
- == 0)) {
+ if (!p2p_hello
+ && (listcount(circuit->area->area_addrs) == 0
+ || (level == ISIS_LEVEL1
+ && !isis_tlvs_area_addresses_match(
+ iih.tlvs, circuit->area->area_addrs)))) {
if (isis->debugs & DEBUG_ADJ_PACKETS) {
zlog_debug(
"ISIS-Adj (%s): Area mismatch, level %d IIH on %s",
circuit->area->area_tag, level,
circuit->interface->name);
}
- retval = ISIS_OK;
goto out;
}
- /*
- * it's own IIH PDU - discard silently
- */
- if (!memcmp(circuit->u.bc.snpa, ssnpa, ETH_ALEN)) {
- zlog_debug("ISIS-Adj (%s): it's own IIH PDU - discarded",
- circuit->area->area_tag);
-
- retval = ISIS_OK;
- goto out;
- }
+ iih.v4_usable = (circuit->ip_addrs && listcount(circuit->ip_addrs)
+ && iih.tlvs->ipv4_address.count);
- /*
- * check if both ends have an IPv4 address
- */
- if (circuit->ip_addrs && listcount(circuit->ip_addrs) && tlvs.ipv4_addrs
- && listcount(tlvs.ipv4_addrs)) {
- v4_usable = 1;
- }
-
- if (found & TLVFLAG_IPV6_ADDR) {
- /* TBA: check that we have a linklocal ourselves? */
- struct listnode *node;
- struct in6_addr *ip;
- for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip))
- if (IN6_IS_ADDR_LINKLOCAL(ip)) {
- v6_usable = 1;
- break;
- }
+ iih.v6_usable = (circuit->ipv6_link && listcount(circuit->ipv6_link)
+ && iih.tlvs->ipv6_address.count);
- if (!v6_usable)
- zlog_warn(
- "ISIS-Adj: IPv6 addresses present but no link-local "
- "in LAN IIH from %s\n",
- circuit->interface->name);
- }
-
- if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
- zlog_warn(
- "ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n",
- circuit->interface->name);
-
- if (!v6_usable && !v4_usable) {
- free_tlvs(&tlvs);
- return ISIS_WARNING;
- }
-
-
- adj = isis_adj_lookup(hdr.source_id, circuit->u.bc.adjdb[level - 1]);
- if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN))
- || (adj->level != level)) {
- if (!adj) {
- /*
- * Do as in 8.4.2.5
- */
- adj = isis_new_adj(hdr.source_id, ssnpa, level,
- circuit);
- if (adj == NULL) {
- retval = ISIS_ERROR;
- goto out;
- }
- } else {
- if (ssnpa) {
- memcpy(adj->snpa, ssnpa, 6);
- } else {
- memset(adj->snpa, ' ', 6);
- }
- adj->level = level;
- }
- isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL);
-
- if (level == IS_LEVEL_1)
- adj->sys_type = ISIS_SYSTYPE_L1_IS;
- else
- adj->sys_type = ISIS_SYSTYPE_L2_IS;
- list_delete_all_node(circuit->u.bc.lan_neighs[level - 1]);
- isis_adj_build_neigh_list(circuit->u.bc.adjdb[level - 1],
- circuit->u.bc.lan_neighs[level - 1]);
- }
-
- if (adj->dis_record[level - 1].dis == ISIS_IS_DIS)
- switch (level) {
- case 1:
- if (memcmp(circuit->u.bc.l1_desig_is, hdr.lan_id,
- ISIS_SYS_ID_LEN + 1)) {
- thread_add_event(master,
- isis_event_dis_status_change,
- circuit, 0, NULL);
- memcpy(&circuit->u.bc.l1_desig_is, hdr.lan_id,
- ISIS_SYS_ID_LEN + 1);
- }
- break;
- case 2:
- if (memcmp(circuit->u.bc.l2_desig_is, hdr.lan_id,
- ISIS_SYS_ID_LEN + 1)) {
- thread_add_event(master,
- isis_event_dis_status_change,
- circuit, 0, NULL);
- memcpy(&circuit->u.bc.l2_desig_is, hdr.lan_id,
- ISIS_SYS_ID_LEN + 1);
- }
- break;
- }
-
- adj->hold_time = hdr.hold_time;
- adj->last_upd = time(NULL);
- adj->prio[level - 1] = hdr.prio;
-
- memcpy(adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
-
- tlvs_to_adj_area_addrs(&tlvs, adj);
-
- /* which protocol are spoken ??? */
- if (tlvs_to_adj_nlpids(&tlvs, adj)) {
- retval = ISIS_WARNING;
+ if (!iih.v4_usable && !iih.v6_usable)
goto out;
- }
-
- /* we need to copy addresses to the adj */
- if (found & TLVFLAG_IPV4_ADDR)
- tlvs_to_adj_ipv4_addrs(&tlvs, adj);
-
- if (found & TLVFLAG_IPV6_ADDR)
- tlvs_to_adj_ipv6_addrs(&tlvs, adj);
-
- adj->circuit_t = hdr.circuit_t;
-
- bool mt_set_changed =
- tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj);
-
- /* lets take care of the expiry */
- THREAD_TIMER_OFF(adj->t_expire);
- thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time,
- &adj->t_expire);
-
- /*
- * If the snpa for this circuit is found from LAN Neighbours TLV
- * we have two-way communication -> adjacency can be put to state "up"
- */
-
- if (found & TLVFLAG_LAN_NEIGHS) {
- if (adj->adj_state != ISIS_ADJ_UP) {
- for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node,
- snpa)) {
- if (!memcmp(snpa, circuit->u.bc.snpa,
- ETH_ALEN)) {
- isis_adj_state_change(
- adj, ISIS_ADJ_UP,
- "own SNPA found in LAN Neighbours TLV");
- }
- }
- } else {
- int found = 0;
- for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node, snpa))
- if (!memcmp(snpa, circuit->u.bc.snpa,
- ETH_ALEN)) {
- found = 1;
- break;
- }
- if (found == 0)
- isis_adj_state_change(
- adj, ISIS_ADJ_INITIALIZING,
- "own SNPA not found in LAN Neighbours TLV");
- }
- } else if (adj->adj_state == ISIS_ADJ_UP) {
- isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING,
- "no LAN Neighbours TLV found");
- }
-
- if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed)
- lsp_regenerate_schedule(adj->circuit->area, level, 0);
+ retval = p2p_hello ? process_p2p_hello(&iih) : process_lan_hello(&iih);
out:
- if (isis->debugs & DEBUG_ADJ_PACKETS) {
- zlog_debug(
- "ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
- "cirID %u, length %zd",
- circuit->area->area_tag, level, snpa_print(ssnpa),
- circuit->interface->name,
- circuit_t2string(circuit->is_type), circuit->circuit_id,
- stream_get_endp(circuit->rcv_stream));
- }
-
- free_tlvs(&tlvs);
+ isis_free_tlvs(iih.tlvs);
return retval;
}
@@ -1180,17 +684,10 @@ out:
* ISO - 10589
* Section 7.3.15.1 - Action on receipt of a link state PDU
*/
-static int process_lsp(int level, struct isis_circuit *circuit,
+static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
const u_char *ssnpa)
{
- struct isis_link_state_hdr *hdr;
- struct isis_adjacency *adj = NULL;
- struct isis_lsp *lsp, *lsp0 = NULL;
- int retval = ISIS_OK, comp = 0;
- u_char lspid[ISIS_SYS_ID_LEN + 2];
- struct isis_passwd *passwd;
- uint16_t pdu_len;
- int lsp_confusion;
+ int level = (pdu_type == L1_LINK_STATE) ? ISIS_LEVEL1 : ISIS_LEVEL2;
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug(
@@ -1204,65 +701,50 @@ static int process_lsp(int level, struct isis_circuit *circuit,
stream_get_endp(circuit->rcv_stream));
}
- if ((stream_get_endp(circuit->rcv_stream)
- - stream_get_getp(circuit->rcv_stream))
- < ISIS_LSP_HDR_LEN) {
- zlog_warn("Packet too short");
- return ISIS_WARNING;
- }
-
- /* Reference the header */
- hdr = (struct isis_link_state_hdr *)STREAM_PNT(circuit->rcv_stream);
- pdu_len = ntohs(hdr->pdu_len);
-
- /* lsp length check */
- if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN)
- || pdu_len > ISO_MTU(circuit)
- || pdu_len > stream_get_endp(circuit->rcv_stream)) {
- zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %d",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
- pdu_len);
+ struct isis_lsp_hdr hdr = {};
+ hdr.pdu_len = stream_getw(circuit->rcv_stream);
+ hdr.rem_lifetime = stream_getw(circuit->rcv_stream);
+ stream_get(hdr.lsp_id, circuit->rcv_stream, sizeof(hdr.lsp_id));
+ hdr.seqno = stream_getl(circuit->rcv_stream);
+ hdr.checksum = stream_getw(circuit->rcv_stream);
+ hdr.lsp_bits = stream_getc(circuit->rcv_stream);
+
+ if (pdu_len_validate(hdr.pdu_len, circuit)) {
+ zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %" PRIu16,
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
+ hdr.pdu_len);
return ISIS_WARNING;
}
- /*
- * Set the stream endp to PDU length, ignoring additional padding
- * introduced by transport chips.
- */
- if (pdu_len < stream_get_endp(circuit->rcv_stream))
- stream_set_endp(circuit->rcv_stream, pdu_len);
-
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
- zlog_debug(
- "ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, "
- "lifetime %us, len %u, on %s",
- circuit->area->area_tag, level,
- rawlspid_print(hdr->lsp_id), ntohl(hdr->seq_num),
- ntohs(hdr->checksum), ntohs(hdr->rem_lifetime), pdu_len,
- circuit->interface->name);
+ zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s, len %" PRIu16 ", on %s",
+ circuit->area->area_tag, level,
+ rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum,
+ hdr.rem_lifetime, hdr.pdu_len,
+ circuit->interface->name);
}
/* lsp is_type check */
- if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1
- && (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) {
- zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP is type %x",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
- hdr->lsp_bits);
+ if ((hdr.lsp_bits & IS_LEVEL_1) != IS_LEVEL_1) {
+ zlog_debug(
+ "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%" PRIx8,
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
+ hdr.lsp_bits & IS_LEVEL_1_AND_2);
/* continue as per RFC1122 Be liberal in what you accept, and
* conservative in what you send */
}
/* Checksum sanity check - FIXME: move to correct place */
/* 12 = sysid+pdu+remtime */
- if (iso_csum_verify(STREAM_PNT(circuit->rcv_stream) + 4, pdu_len - 12,
- hdr->checksum,
- offsetof(struct isis_link_state_hdr, checksum)
- - 4)) {
- zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
- ntohs(hdr->checksum));
-
+ if (iso_csum_verify(STREAM_DATA(circuit->rcv_stream) + 12,
+ hdr.pdu_len - 12, hdr.checksum, 12)) {
+ zlog_debug(
+ "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04" PRIx16,
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
+ hdr.checksum);
return ISIS_WARNING;
}
@@ -1271,46 +753,56 @@ static int process_lsp(int level, struct isis_circuit *circuit,
zlog_debug(
"ISIS-Upd (%s): LSP %s received at level %d over circuit with "
"externalDomain = true",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
level);
-
return ISIS_WARNING;
}
/* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
- if (!accept_level(level, circuit->is_type)) {
+ if (!(circuit->is_type & level)) {
zlog_debug(
"ISIS-Upd (%s): LSP %s received at level %d over circuit of"
" type %s",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
level, circuit_t2string(circuit->is_type));
-
return ISIS_WARNING;
}
+ struct isis_tlvs *tlvs = NULL;
+ int retval = ISIS_WARNING;
+ const char *error_log;
+
+ if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
+ circuit->rcv_stream, &tlvs, &error_log)) {
+ zlog_warn("Something went wrong unpacking the LSP: %s",
+ error_log);
+ goto out;
+ }
+
/* 7.3.15.1 a) 4 - need to make sure IDLength matches */
/* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use
* 3 */
/* 7.3.15.1 a) 7 - password check */
- (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd)
- : (passwd = &circuit->area->domain_passwd);
- if (passwd->type) {
- if (lsp_authentication_check(circuit->rcv_stream, circuit->area,
- level, passwd)) {
- isis_event_auth_failure(circuit->area->area_tag,
- "LSP authentication failure",
- hdr->lsp_id);
- return ISIS_WARNING;
- }
+ struct isis_passwd *passwd = (level == ISIS_LEVEL1)
+ ? &circuit->area->area_passwd
+ : &circuit->area->domain_passwd;
+ if (!isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream, true)) {
+ isis_event_auth_failure(circuit->area->area_tag,
+ "LSP authentication failure",
+ hdr.lsp_id);
+ goto out;
}
+
/* Find the LSP in our database and compare it to this Link State header
*/
- lsp = lsp_search(hdr->lsp_id, circuit->area->lspdb[level - 1]);
+ struct isis_lsp *lsp =
+ lsp_search(hdr.lsp_id, circuit->area->lspdb[level - 1]);
+ int comp = 0;
if (lsp)
- comp = lsp_compare(circuit->area->area_tag, lsp, hdr->seq_num,
- hdr->checksum, hdr->rem_lifetime);
+ comp = lsp_compare(circuit->area->area_tag, lsp, hdr.seqno,
+ hdr.checksum, hdr.rem_lifetime);
if (lsp && (lsp->own_lsp))
goto dontcheckadj;
@@ -1319,25 +811,24 @@ static int process_lsp(int level, struct isis_circuit *circuit,
/* for broadcast circuits, snpa should be compared */
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
- adj = isis_adj_lookup_snpa(ssnpa,
- circuit->u.bc.adjdb[level - 1]);
- if (!adj) {
- zlog_debug(
- "(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, "
- "lifetime %us on %s",
- circuit->area->area_tag,
- rawlspid_print(hdr->lsp_id),
- ntohl(hdr->seq_num), ntohs(hdr->checksum),
- ntohs(hdr->rem_lifetime),
- circuit->interface->name);
- return ISIS_WARNING; /* Silently discard */
+ if (!isis_adj_lookup_snpa(ssnpa,
+ circuit->u.bc.adjdb[level - 1])) {
+ zlog_debug("(%s): DS ======= LSP %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s on %s",
+ circuit->area->area_tag,
+ rawlspid_print(hdr.lsp_id), hdr.seqno,
+ hdr.checksum, hdr.rem_lifetime,
+ circuit->interface->name);
+ goto out; /* Silently discard */
}
}
/* for non broadcast, we just need to find same level adj */
else {
/* If no adj, or no sharing of level */
if (!circuit->u.p2p.neighbor) {
- return ISIS_OK; /* Silently discard */
+ retval = ISIS_OK;
+ goto out;
} else {
if (((level == IS_LEVEL_1)
&& (circuit->u.p2p.neighbor->adj_usage
@@ -1345,10 +836,12 @@ static int process_lsp(int level, struct isis_circuit *circuit,
|| ((level == IS_LEVEL_2)
&& (circuit->u.p2p.neighbor->adj_usage
== ISIS_ADJ_LEVEL1)))
- return ISIS_WARNING; /* Silently discard */
+ goto out;
}
}
+ bool lsp_confusion;
+
dontcheckadj:
/* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */
@@ -1360,33 +853,36 @@ dontcheckadj:
/* 7.3.16.2 - If this is an LSP from another IS with identical seq_num
* but
* wrong checksum, initiate a purge. */
- if (lsp && (lsp->lsp_header->seq_num == hdr->seq_num)
- && (lsp->lsp_header->checksum != hdr->checksum)) {
- zlog_warn(
- "ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.",
- circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
- ntohl(hdr->seq_num));
- hdr->rem_lifetime = 0;
- lsp_confusion = 1;
+ if (lsp && (lsp->hdr.seqno == hdr.seqno)
+ && (lsp->hdr.checksum != hdr.checksum)) {
+ zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08" PRIx32
+ " with confused checksum received.",
+ circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
+ hdr.seqno);
+ hdr.rem_lifetime = 0;
+ lsp_confusion = true;
} else
- lsp_confusion = 0;
+ lsp_confusion = false;
/* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */
- if (hdr->rem_lifetime == 0) {
+ if (hdr.rem_lifetime == 0) {
if (!lsp) {
/* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't
* save */
/* only needed on explicit update, eg - p2p */
if (circuit->circ_type == CIRCUIT_T_P2P)
- ack_lsp(hdr, circuit, level);
- return retval; /* FIXME: do we need a purge? */
+ ack_lsp(&hdr, circuit, level);
+ goto out; /* FIXME: do we need a purge? */
} else {
- if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) {
+ if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) {
/* LSP by some other system -> do 7.3.16.4 b) */
/* 7.3.16.4 b) 1) */
if (comp == LSP_NEWER) {
- lsp_update(lsp, circuit->rcv_stream,
- circuit->area, level);
+ lsp_update(lsp, &hdr, tlvs,
+ circuit->rcv_stream,
+ circuit->area, level,
+ lsp_confusion);
+ tlvs = NULL;
/* ii */
lsp_set_all_srmflags(lsp);
/* v */
@@ -1427,11 +923,10 @@ dontcheckadj:
ISIS_SET_FLAG(lsp->SRMflags, circuit);
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
}
- } else if (lsp->lsp_header->rem_lifetime != 0) {
+ } else if (lsp->hdr.rem_lifetime != 0) {
/* our own LSP -> 7.3.16.4 c) */
if (comp == LSP_NEWER) {
- lsp_inc_seqnum(lsp,
- ntohl(hdr->seq_num));
+ lsp_inc_seqno(lsp, hdr.seqno);
lsp_set_all_srmflags(lsp);
} else {
ISIS_SET_FLAG(lsp->SRMflags, circuit);
@@ -1439,23 +934,22 @@ dontcheckadj:
}
if (isis->debugs & DEBUG_UPDATE_PACKETS)
zlog_debug(
- "ISIS-Upd (%s): (1) re-originating LSP %s new "
- "seq 0x%08x",
+ "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08" PRIx32,
circuit->area->area_tag,
- rawlspid_print(hdr->lsp_id),
- ntohl(lsp->lsp_header
- ->seq_num));
+ rawlspid_print(hdr.lsp_id),
+ lsp->hdr.seqno);
}
}
- return retval;
+ goto out;
}
/* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a
* purge */
- if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) {
+ if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) {
if (!lsp) {
/* 7.3.16.4: initiate a purge */
- lsp_purge_non_exist(level, hdr, circuit->area);
- return ISIS_OK;
+ lsp_purge_non_exist(level, &hdr, circuit->area);
+ retval = ISIS_OK;
+ goto out;
}
/* 7.3.15.1 d) - If this is our own lsp and we have it */
@@ -1465,16 +959,15 @@ dontcheckadj:
* is
* "greater" than that held by S, ... */
- if (ntohl(hdr->seq_num) > ntohl(lsp->lsp_header->seq_num)) {
+ if (hdr.seqno > lsp->hdr.seqno) {
/* 7.3.16.1 */
- lsp_inc_seqnum(lsp, ntohl(hdr->seq_num));
+ lsp_inc_seqno(lsp, hdr.seqno);
if (isis->debugs & DEBUG_UPDATE_PACKETS)
zlog_debug(
- "ISIS-Upd (%s): (2) re-originating LSP %s new seq "
- "0x%08x",
+ "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08" PRIx32,
circuit->area->area_tag,
- rawlspid_print(hdr->lsp_id),
- ntohl(lsp->lsp_header->seq_num));
+ rawlspid_print(hdr.lsp_id),
+ lsp->hdr.seqno);
}
/* If the received LSP is older or equal,
* resend the LSP which will act as ACK */
@@ -1489,8 +982,10 @@ dontcheckadj:
* If this lsp is a frag, need to see if we have zero
* lsp present
*/
- if (LSP_FRAGMENT(hdr->lsp_id) != 0) {
- memcpy(lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1);
+ struct isis_lsp *lsp0 = NULL;
+ if (LSP_FRAGMENT(hdr.lsp_id) != 0) {
+ uint8_t lspid[ISIS_SYS_ID_LEN + 2];
+ memcpy(lspid, hdr.lsp_id, ISIS_SYS_ID_LEN + 1);
LSP_FRAGMENT(lspid) = 0;
lsp0 = lsp_search(
lspid, circuit->area->lspdb[level - 1]);
@@ -1502,15 +997,17 @@ dontcheckadj:
}
/* i */
if (!lsp) {
- lsp = lsp_new_from_stream_ptr(
- circuit->rcv_stream, pdu_len, lsp0,
+ lsp = lsp_new_from_recv(
+ &hdr, tlvs, circuit->rcv_stream, lsp0,
circuit->area, level);
+ tlvs = NULL;
lsp_insert(lsp,
circuit->area->lspdb[level - 1]);
} else /* exists, so we overwrite */
{
- lsp_update(lsp, circuit->rcv_stream,
- circuit->area, level);
+ lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream,
+ circuit->area, level, false);
+ tlvs = NULL;
}
/* ii */
lsp_set_all_srmflags(lsp);
@@ -1525,8 +1022,9 @@ dontcheckadj:
/* 7.3.15.1 e) 2) LSP equal to the one in db */
else if (comp == LSP_EQUAL) {
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
- lsp_update(lsp, circuit->rcv_stream, circuit->area,
- level);
+ lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream,
+ circuit->area, level, false);
+ tlvs = NULL;
if (circuit->circ_type != CIRCUIT_T_BROADCAST)
ISIS_SET_FLAG(lsp->SSNflags, circuit);
}
@@ -1536,6 +1034,11 @@ dontcheckadj:
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
}
}
+
+ retval = ISIS_OK;
+
+out:
+ isis_free_tlvs(tlvs);
return retval;
}
@@ -1545,60 +1048,48 @@ dontcheckadj:
* Section 7.3.15.2 - Action on receipt of a sequence numbers PDU
*/
-static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
+static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
const u_char *ssnpa)
{
- int retval = ISIS_OK;
- int cmp, own_lsp;
- char typechar = ' ';
- uint16_t pdu_len;
- struct isis_adjacency *adj;
- struct isis_complete_seqnum_hdr *chdr = NULL;
- struct isis_partial_seqnum_hdr *phdr = NULL;
- uint32_t found = 0, expected = 0, auth_tlv_offset = 0;
- struct isis_lsp *lsp;
- struct lsp_entry *entry;
- struct listnode *node, *nnode;
- struct listnode *node2, *nnode2;
- struct tlvs tlvs;
- struct list *lsp_list = NULL;
- struct isis_passwd *passwd;
-
- if (snp_type == ISIS_SNP_CSNP_FLAG) {
- /* getting the header info */
- typechar = 'C';
- chdr = (struct isis_complete_seqnum_hdr *)STREAM_PNT(
- circuit->rcv_stream);
- stream_forward_getp(circuit->rcv_stream, ISIS_CSNP_HDRLEN);
- pdu_len = ntohs(chdr->pdu_len);
- if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN)
- || pdu_len > ISO_MTU(circuit)
- || pdu_len > stream_get_endp(circuit->rcv_stream)) {
- zlog_warn("Received a CSNP with bogus length %d",
- pdu_len);
- return ISIS_WARNING;
- }
- } else {
- typechar = 'P';
- phdr = (struct isis_partial_seqnum_hdr *)STREAM_PNT(
- circuit->rcv_stream);
- stream_forward_getp(circuit->rcv_stream, ISIS_PSNP_HDRLEN);
- pdu_len = ntohs(phdr->pdu_len);
- if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN)
- || pdu_len > ISO_MTU(circuit)
- || pdu_len > stream_get_endp(circuit->rcv_stream)) {
- zlog_warn("Received a PSNP with bogus length %d",
- pdu_len);
- return ISIS_WARNING;
- }
+ bool is_csnp = (pdu_type == L1_COMPLETE_SEQ_NUM
+ || pdu_type == L2_COMPLETE_SEQ_NUM);
+ char typechar = is_csnp ? 'C' : 'P';
+ int level = (pdu_type == L1_COMPLETE_SEQ_NUM
+ || pdu_type == L1_PARTIAL_SEQ_NUM)
+ ? ISIS_LEVEL1
+ : ISIS_LEVEL2;
+
+ uint16_t pdu_len = stream_getw(circuit->rcv_stream);
+ uint8_t rem_sys_id[ISIS_SYS_ID_LEN];
+ stream_get(rem_sys_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
+ stream_forward_getp(circuit->rcv_stream, 1); /* Circuit ID - unused */
+
+ uint8_t start_lsp_id[ISIS_SYS_ID_LEN + 2] = {};
+ uint8_t stop_lsp_id[ISIS_SYS_ID_LEN + 2] = {};
+
+ if (is_csnp) {
+ stream_get(start_lsp_id, circuit->rcv_stream,
+ ISIS_SYS_ID_LEN + 2);
+ stream_get(stop_lsp_id, circuit->rcv_stream,
+ ISIS_SYS_ID_LEN + 2);
+ }
+
+ if (pdu_len_validate(pdu_len, circuit)) {
+ zlog_warn("Received a CSNP with bogus length %d", pdu_len);
+ return ISIS_WARNING;
}
- /*
- * Set the stream endp to PDU length, ignoring additional padding
- * introduced by transport chips.
- */
- if (pdu_len < stream_get_endp(circuit->rcv_stream))
- stream_set_endp(circuit->rcv_stream, pdu_len);
+ if (isis->debugs & DEBUG_SNP_PACKETS) {
+ zlog_debug(
+ "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, cirType %s, cirID %u",
+ circuit->area->area_tag, level, typechar,
+ circuit->interface->name,
+ circuit_t2string(circuit->is_type),
+ circuit->circuit_id);
+ if (isis->debugs & DEBUG_PACKET_DUMP)
+ zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
+ stream_get_endp(circuit->rcv_stream));
+ }
/* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */
if (circuit->ext_domain) {
@@ -1613,8 +1104,7 @@ static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
}
/* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */
- if (!accept_level(level, circuit->is_type)) {
-
+ if (!(circuit->is_type & level)) {
zlog_debug(
"ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
"skipping: circuit type %s does not match level %d",
@@ -1626,9 +1116,8 @@ static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
}
/* 7.3.15.2 a) 4 - not applicable for CSNP only PSNPs on broadcast */
- if ((snp_type == ISIS_SNP_PSNP_FLAG)
- && (circuit->circ_type == CIRCUIT_T_BROADCAST)
- && (!circuit->u.bc.is_dr[level - 1])) {
+ if (!is_csnp && (circuit->circ_type == CIRCUIT_T_BROADCAST)
+ && !circuit->u.bc.is_dr[level - 1]) {
zlog_debug(
"ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, "
"skipping: we are not the DIS",
@@ -1650,15 +1139,8 @@ static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
/* for broadcast circuits, snpa should be compared */
/* FIXME : Do we need to check SNPA? */
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
- if (snp_type == ISIS_SNP_CSNP_FLAG) {
- adj = isis_adj_lookup(chdr->source_id,
- circuit->u.bc.adjdb[level - 1]);
- } else {
- /* a psnp on a broadcast, how lovely of Juniper :) */
- adj = isis_adj_lookup(phdr->source_id,
- circuit->u.bc.adjdb[level - 1]);
- }
- if (!adj)
+ if (!isis_adj_lookup(rem_sys_id,
+ circuit->u.bc.adjdb[level - 1]))
return ISIS_OK; /* Silently discard */
} else {
if (!circuit->u.p2p.neighbor) {
@@ -1668,164 +1150,128 @@ static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
}
}
- /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */
+ struct isis_tlvs *tlvs;
+ int retval = ISIS_WARNING;
+ const char *error_log;
- /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */
-
- memset(&tlvs, 0, sizeof(struct tlvs));
-
- /* parse the SNP */
- expected |= TLVFLAG_LSP_ENTRIES;
- expected |= TLVFLAG_AUTH_INFO;
-
- auth_tlv_offset = stream_get_getp(circuit->rcv_stream);
- retval = parse_tlvs(circuit->area->area_tag,
- STREAM_PNT(circuit->rcv_stream),
- pdu_len - stream_get_getp(circuit->rcv_stream),
- &expected, &found, &tlvs, &auth_tlv_offset);
-
- if (retval > ISIS_WARNING) {
- zlog_warn("something went very wrong processing SNP");
- free_tlvs(&tlvs);
- return retval;
+ if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
+ circuit->rcv_stream, &tlvs, &error_log)) {
+ zlog_warn("Something went wrong unpacking the SNP: %s",
+ error_log);
+ goto out;
}
- if (level == IS_LEVEL_1)
- passwd = &circuit->area->area_passwd;
- else
- passwd = &circuit->area->domain_passwd;
-
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) {
- if (passwd->type) {
- if (!(found & TLVFLAG_AUTH_INFO)
- || authentication_check(&tlvs.auth_info, passwd,
- circuit->rcv_stream,
- auth_tlv_offset)) {
- isis_event_auth_failure(circuit->area->area_tag,
- "SNP authentication"
- " failure",
- phdr ? phdr->source_id
- : chdr->source_id);
- free_tlvs(&tlvs);
- return ISIS_OK;
- }
- }
+ struct isis_passwd *passwd = (level == IS_LEVEL_1)
+ ? &circuit->area->area_passwd
+ : &circuit->area->domain_passwd;
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)
+ && !isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream,
+ false)) {
+ isis_event_auth_failure(circuit->area->area_tag,
+ "SNP authentication failure",
+ rem_sys_id);
+ goto out;
}
+ struct isis_lsp_entry *entry_head =
+ (struct isis_lsp_entry *)tlvs->lsp_entries.head;
+
/* debug isis snp-packets */
if (isis->debugs & DEBUG_SNP_PACKETS) {
zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s",
circuit->area->area_tag, level, typechar,
snpa_print(ssnpa), circuit->interface->name);
- if (tlvs.lsp_entries) {
- for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node,
- entry)) {
- zlog_debug(
- "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- circuit->area->area_tag, typechar,
- rawlspid_print(entry->lsp_id),
- ntohl(entry->seq_num),
- ntohs(entry->checksum),
- ntohs(entry->rem_lifetime));
- }
+ for (struct isis_lsp_entry *entry = entry_head; entry;
+ entry = entry->next) {
+ zlog_debug(
+ "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s",
+ circuit->area->area_tag, typechar,
+ rawlspid_print(entry->id), entry->seqno,
+ entry->checksum, entry->rem_lifetime);
}
}
/* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
- if (tlvs.lsp_entries) {
- for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node, entry)) {
- lsp = lsp_search(entry->lsp_id,
- circuit->area->lspdb[level - 1]);
- own_lsp = !memcmp(entry->lsp_id, isis->sysid,
- ISIS_SYS_ID_LEN);
- if (lsp) {
- /* 7.3.15.2 b) 1) is this LSP newer */
- cmp = lsp_compare(circuit->area->area_tag, lsp,
- entry->seq_num,
- entry->checksum,
- entry->rem_lifetime);
- /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p
- */
- if (cmp == LSP_EQUAL) {
+ for (struct isis_lsp_entry *entry = entry_head; entry;
+ entry = entry->next) {
+ struct isis_lsp *lsp =
+ lsp_search(entry->id, circuit->area->lspdb[level - 1]);
+ bool own_lsp = !memcmp(entry->id, isis->sysid, ISIS_SYS_ID_LEN);
+ if (lsp) {
+ /* 7.3.15.2 b) 1) is this LSP newer */
+ int cmp = lsp_compare(circuit->area->area_tag, lsp,
+ entry->seqno, entry->checksum,
+ entry->rem_lifetime);
+ /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */
+ if (cmp == LSP_EQUAL) {
+ /* if (circuit->circ_type !=
+ * CIRCUIT_T_BROADCAST) */
+ ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
+ }
+ /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM
+ */
+ else if (cmp == LSP_OLDER) {
+ ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
+ ISIS_SET_FLAG(lsp->SRMflags, circuit);
+ }
+ /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM
+ on p2p */
+ else {
+ if (own_lsp) {
+ lsp_inc_seqno(lsp, entry->seqno);
+ ISIS_SET_FLAG(lsp->SRMflags, circuit);
+ } else {
+ ISIS_SET_FLAG(lsp->SSNflags, circuit);
/* if (circuit->circ_type !=
* CIRCUIT_T_BROADCAST) */
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
}
- /* 7.3.15.2 b) 3) if it is older, clear SSN and
- set SRM */
- else if (cmp == LSP_OLDER) {
- ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
- ISIS_SET_FLAG(lsp->SRMflags, circuit);
- }
- /* 7.3.15.2 b) 4) if it is newer, set SSN and
- clear SRM on p2p */
- else {
- if (own_lsp) {
- lsp_inc_seqnum(
- lsp,
- ntohl(entry->seq_num));
- ISIS_SET_FLAG(lsp->SRMflags,
- circuit);
- } else {
- ISIS_SET_FLAG(lsp->SSNflags,
- circuit);
- /* if (circuit->circ_type !=
- * CIRCUIT_T_BROADCAST) */
- ISIS_CLEAR_FLAG(lsp->SRMflags,
- circuit);
- }
- }
- } else {
- /* 7.3.15.2 b) 5) if it was not found, and all
- * of those are not 0,
- * insert it and set SSN on it */
- if (entry->rem_lifetime && entry->checksum
- && entry->seq_num
- && memcmp(entry->lsp_id, isis->sysid,
- ISIS_SYS_ID_LEN)) {
- lsp = lsp_new(
- circuit->area, entry->lsp_id,
- ntohs(entry->rem_lifetime), 0,
- 0, entry->checksum, level);
- lsp_insert(lsp,
- circuit->area
- ->lspdb[level - 1]);
- ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
- ISIS_SET_FLAG(lsp->SSNflags, circuit);
- }
+ }
+ } else {
+ /* 7.3.15.2 b) 5) if it was not found, and all of those
+ * are not 0,
+ * insert it and set SSN on it */
+ if (entry->rem_lifetime && entry->checksum
+ && entry->seqno && memcmp(entry->id, isis->sysid,
+ ISIS_SYS_ID_LEN)) {
+ struct isis_lsp *lsp =
+ lsp_new(circuit->area, entry->id,
+ entry->rem_lifetime, 0, 0,
+ entry->checksum, level);
+ lsp_insert(lsp,
+ circuit->area->lspdb[level - 1]);
+ ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
+ ISIS_SET_FLAG(lsp->SSNflags, circuit);
}
}
}
/* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported
*/
- if (snp_type == ISIS_SNP_CSNP_FLAG) {
+ if (is_csnp) {
/*
* Build a list from our own LSP db bounded with
* start_lsp_id and stop_lsp_id
*/
- lsp_list = list_new();
- lsp_build_list_nonzero_ht(chdr->start_lsp_id, chdr->stop_lsp_id,
- lsp_list,
+ struct list *lsp_list = list_new();
+ lsp_build_list_nonzero_ht(start_lsp_id, stop_lsp_id, lsp_list,
circuit->area->lspdb[level - 1]);
/* Fixme: Find a better solution */
- if (tlvs.lsp_entries) {
- for (ALL_LIST_ELEMENTS(tlvs.lsp_entries, node, nnode,
- entry)) {
- for (ALL_LIST_ELEMENTS(lsp_list, node2, nnode2,
- lsp)) {
- if (lsp_id_cmp(lsp->lsp_header->lsp_id,
- entry->lsp_id)
- == 0) {
- list_delete_node(lsp_list,
- node2);
- break;
- }
+ struct listnode *node, *nnode;
+ struct isis_lsp *lsp;
+ for (struct isis_lsp_entry *entry = entry_head; entry;
+ entry = entry->next) {
+ for (ALL_LIST_ELEMENTS(lsp_list, node, nnode, lsp)) {
+ if (lsp_id_cmp(lsp->hdr.lsp_id, entry->id)
+ == 0) {
+ list_delete_node(lsp_list, node);
+ break;
}
}
}
+
/* on remaining LSPs we set SRM (neighbor knew not of) */
for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp))
ISIS_SET_FLAG(lsp->SRMflags, circuit);
@@ -1833,59 +1279,39 @@ static int process_snp(int snp_type, int level, struct isis_circuit *circuit,
list_delete(lsp_list);
}
- free_tlvs(&tlvs);
+ retval = ISIS_OK;
+out:
+ isis_free_tlvs(tlvs);
return retval;
}
-static int process_csnp(int level, struct isis_circuit *circuit,
- const u_char *ssnpa)
-{
- if (isis->debugs & DEBUG_SNP_PACKETS) {
- zlog_debug(
- "ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u",
- circuit->area->area_tag, level,
- circuit->interface->name,
- circuit_t2string(circuit->is_type),
- circuit->circuit_id);
- if (isis->debugs & DEBUG_PACKET_DUMP)
- zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
- stream_get_endp(circuit->rcv_stream));
- }
-
- /* Sanity check - FIXME: move to correct place */
- if ((stream_get_endp(circuit->rcv_stream)
- - stream_get_getp(circuit->rcv_stream))
- < ISIS_CSNP_HDRLEN) {
- zlog_warn("Packet too short ( < %d)", ISIS_CSNP_HDRLEN);
- return ISIS_WARNING;
- }
-
- return process_snp(ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);
-}
-
-static int process_psnp(int level, struct isis_circuit *circuit,
- const u_char *ssnpa)
+static int pdu_size(uint8_t pdu_type, uint8_t *size)
{
- if (isis->debugs & DEBUG_SNP_PACKETS) {
- zlog_debug(
- "ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u",
- circuit->area->area_tag, level,
- circuit->interface->name,
- circuit_t2string(circuit->is_type),
- circuit->circuit_id);
- if (isis->debugs & DEBUG_PACKET_DUMP)
- zlog_dump_data(STREAM_DATA(circuit->rcv_stream),
- stream_get_endp(circuit->rcv_stream));
- }
-
- if ((stream_get_endp(circuit->rcv_stream)
- - stream_get_getp(circuit->rcv_stream))
- < ISIS_PSNP_HDRLEN) {
- zlog_warn("Packet too short ( < %d)", ISIS_PSNP_HDRLEN);
- return ISIS_WARNING;
+ switch (pdu_type) {
+ case L1_LAN_HELLO:
+ case L2_LAN_HELLO:
+ *size = ISIS_LANHELLO_HDRLEN;
+ break;
+ case P2P_HELLO:
+ *size = ISIS_P2PHELLO_HDRLEN;
+ break;
+ case L1_LINK_STATE:
+ case L2_LINK_STATE:
+ *size = ISIS_LSP_HDR_LEN;
+ break;
+ case L1_COMPLETE_SEQ_NUM:
+ case L2_COMPLETE_SEQ_NUM:
+ *size = ISIS_CSNP_HDRLEN;
+ break;
+ case L1_PARTIAL_SEQ_NUM:
+ case L2_PARTIAL_SEQ_NUM:
+ *size = ISIS_PSNP_HDRLEN;
+ break;
+ default:
+ return 1;
}
-
- return process_snp(ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
+ *size += ISIS_FIXED_HDR_LEN;
+ return 0;
}
/*
@@ -1894,53 +1320,68 @@ static int process_psnp(int level, struct isis_circuit *circuit,
static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
{
- struct isis_fixed_hdr *hdr;
-
int retval = ISIS_OK;
- /*
- * Let's first read data from stream to the header
- */
- hdr = (struct isis_fixed_hdr *)STREAM_DATA(circuit->rcv_stream);
+ /* Verify that at least the 8 bytes fixed header have been received */
+ if (stream_get_endp(circuit->rcv_stream) < ISIS_FIXED_HDR_LEN) {
+ zlog_err("PDU is too short to be IS-IS.");
+ return ISIS_ERROR;
+ }
- if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) {
- zlog_err("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
+ uint8_t idrp = stream_getc(circuit->rcv_stream);
+ uint8_t length = stream_getc(circuit->rcv_stream);
+ uint8_t version1 = stream_getc(circuit->rcv_stream);
+ uint8_t id_len = stream_getc(circuit->rcv_stream);
+ uint8_t pdu_type = stream_getc(circuit->rcv_stream)
+ & 0x1f; /* bits 6-8 are reserved */
+ uint8_t version2 = stream_getc(circuit->rcv_stream);
+ stream_forward_getp(circuit->rcv_stream, 1); /* reserved */
+ uint8_t max_area_addrs = stream_getc(circuit->rcv_stream);
+
+ if (idrp == ISO9542_ESIS) {
+ zlog_err("No support for ES-IS packet IDRP=%" PRIx8, idrp);
return ISIS_ERROR;
}
- /* now we need to know if this is an ISO 9542 packet and
- * take real good care of it, waaa!
- */
- if (hdr->idrp == ISO9542_ESIS) {
- zlog_err("No support for ES-IS packet IDRP=%02x", hdr->idrp);
+ if (idrp != ISO10589_ISIS) {
+ zlog_err("Not an IS-IS packet IDRP=%" PRIx8, idrp);
return ISIS_ERROR;
}
- stream_set_getp(circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
- /*
- * and then process it
- */
+ if (version1 != 1) {
+ zlog_warn("Unsupported ISIS version %" PRIu8, version1);
+ return ISIS_WARNING;
+ }
- if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) {
- zlog_err("Fixed header length = %d", hdr->length);
+ if (id_len != 0 && id_len != ISIS_SYS_ID_LEN) {
+ zlog_err(
+ "IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8
+ ", while the parameter for this IS is %u",
+ id_len, ISIS_SYS_ID_LEN);
return ISIS_ERROR;
}
- if (hdr->version1 != 1) {
- zlog_warn("Unsupported ISIS version %u", hdr->version1);
+ uint8_t expected_length;
+ if (pdu_size(pdu_type, &expected_length)) {
+ zlog_warn("Unsupported ISIS PDU %" PRIu8, pdu_type);
return ISIS_WARNING;
}
- /* either 6 or 0 */
- if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) {
+
+ if (length != expected_length) {
+ zlog_err("Exepected fixed header length = %" PRIu8
+ " but got %" PRIu8,
+ expected_length, length);
+ return ISIS_ERROR;
+ }
+
+ if (stream_get_endp(circuit->rcv_stream) < length) {
zlog_err(
- "IDFieldLengthMismatch: ID Length field in a received PDU %u, "
- "while the parameter for this IS is %u",
- hdr->id_len, ISIS_SYS_ID_LEN);
+ "PDU is too short to contain fixed header of given PDU type.");
return ISIS_ERROR;
}
- if (hdr->version2 != 1) {
- zlog_warn("Unsupported ISIS version %u", hdr->version2);
+ if (version2 != 1) {
+ zlog_warn("Unsupported ISIS PDU version %" PRIu8, version2);
return ISIS_WARNING;
}
@@ -1951,42 +1392,29 @@ static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
}
/* either 3 or 0 */
- if ((hdr->max_area_addrs != 0)
- && (hdr->max_area_addrs != isis->max_area_addrs)) {
+ if (max_area_addrs != 0 && max_area_addrs != isis->max_area_addrs) {
zlog_err(
- "maximumAreaAddressesMismatch: maximumAreaAdresses in a "
- "received PDU %u while the parameter for this IS is %u",
- hdr->max_area_addrs, isis->max_area_addrs);
+ "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
+ " while the parameter for this IS is %u",
+ max_area_addrs, isis->max_area_addrs);
return ISIS_ERROR;
}
- switch (hdr->pdu_type) {
+ switch (pdu_type) {
case L1_LAN_HELLO:
- retval = process_lan_hello(ISIS_LEVEL1, circuit, ssnpa);
- break;
case L2_LAN_HELLO:
- retval = process_lan_hello(ISIS_LEVEL2, circuit, ssnpa);
- break;
case P2P_HELLO:
- retval = process_p2p_hello(circuit);
+ retval = process_hello(pdu_type, circuit, ssnpa);
break;
case L1_LINK_STATE:
- retval = process_lsp(ISIS_LEVEL1, circuit, ssnpa);
- break;
case L2_LINK_STATE:
- retval = process_lsp(ISIS_LEVEL2, circuit, ssnpa);
+ retval = process_lsp(pdu_type, circuit, ssnpa);
break;
case L1_COMPLETE_SEQ_NUM:
- retval = process_csnp(ISIS_LEVEL1, circuit, ssnpa);
- break;
case L2_COMPLETE_SEQ_NUM:
- retval = process_csnp(ISIS_LEVEL2, circuit, ssnpa);
- break;
case L1_PARTIAL_SEQ_NUM:
- retval = process_psnp(ISIS_LEVEL1, circuit, ssnpa);
- break;
case L2_PARTIAL_SEQ_NUM:
- retval = process_psnp(ISIS_LEVEL2, circuit, ssnpa);
+ retval = process_snp(pdu_type, circuit, ssnpa);
break;
default:
return ISIS_ERROR;
@@ -2025,73 +1453,67 @@ int isis_receive(struct thread *thread)
return retval;
}
-/* filling of the fixed isis header */
-void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type)
-{
- memset(hdr, 0, sizeof(struct isis_fixed_hdr));
-
- hdr->idrp = ISO10589_ISIS;
-
- switch (pdu_type) {
- case L1_LAN_HELLO:
- case L2_LAN_HELLO:
- hdr->length = ISIS_LANHELLO_HDRLEN;
- break;
- case P2P_HELLO:
- hdr->length = ISIS_P2PHELLO_HDRLEN;
- break;
- case L1_LINK_STATE:
- case L2_LINK_STATE:
- hdr->length = ISIS_LSP_HDR_LEN;
- break;
- case L1_COMPLETE_SEQ_NUM:
- case L2_COMPLETE_SEQ_NUM:
- hdr->length = ISIS_CSNP_HDRLEN;
- break;
- case L1_PARTIAL_SEQ_NUM:
- case L2_PARTIAL_SEQ_NUM:
- hdr->length = ISIS_PSNP_HDRLEN;
- break;
- default:
- zlog_warn("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
- return;
- }
- hdr->length += ISIS_FIXED_HDR_LEN;
- hdr->pdu_type = pdu_type;
- hdr->version1 = 1;
- hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */
- hdr->version2 = 1;
- hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */
-}
-
/*
* SEND SIDE
*/
-static void fill_fixed_hdr_andstream(struct isis_fixed_hdr *hdr,
- u_char pdu_type, struct stream *stream)
+void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream)
{
- fill_fixed_hdr(hdr, pdu_type);
-
- stream_putc(stream, hdr->idrp);
- stream_putc(stream, hdr->length);
- stream_putc(stream, hdr->version1);
- stream_putc(stream, hdr->id_len);
- stream_putc(stream, hdr->pdu_type);
- stream_putc(stream, hdr->version2);
- stream_putc(stream, hdr->reserved);
- stream_putc(stream, hdr->max_area_addrs);
-
- return;
+ uint8_t length;
+
+ if (pdu_size(pdu_type, &length))
+ assert(!"Unknown PDU Type");
+
+ stream_putc(stream, ISO10589_ISIS); /* IDRP */
+ stream_putc(stream, length); /* Length of fixed header */
+ stream_putc(stream, 1); /* Version/Protocol ID Extension 1 */
+ stream_putc(stream, 0); /* ID Length, 0 => 6 */
+ stream_putc(stream, pdu_type);
+ stream_putc(stream, 1); /* Subversion */
+ stream_putc(stream, 0); /* Reserved */
+ stream_putc(stream, 0); /* Max Area Addresses 0 => 3 */
+}
+
+static void put_hello_hdr(struct isis_circuit *circuit, int level,
+ size_t *len_pointer)
+{
+ uint8_t pdu_type;
+
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+ pdu_type = (level == IS_LEVEL_1) ? L1_LAN_HELLO : L2_LAN_HELLO;
+ else
+ pdu_type = P2P_HELLO;
+
+ isis_circuit_stream(circuit, &circuit->snd_stream);
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
+
+ stream_putc(circuit->snd_stream, circuit->is_type);
+ stream_put(circuit->snd_stream, circuit->area->isis->sysid,
+ ISIS_SYS_ID_LEN);
+
+ uint32_t holdtime = circuit->hello_multiplier[level - 1]
+ * circuit->hello_interval[level - 1];
+
+ if (holdtime > 0xffff)
+ holdtime = 0xffff;
+
+ stream_putw(circuit->snd_stream, holdtime);
+ *len_pointer = stream_get_endp(circuit->snd_stream);
+ stream_putw(circuit->snd_stream, 0); /* length is filled in later */
+
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+ u_char *desig_is = (level == IS_LEVEL_1)
+ ? circuit->u.bc.l1_desig_is
+ : circuit->u.bc.l2_desig_is;
+ stream_putc(circuit->snd_stream, circuit->priority[level - 1]);
+ stream_put(circuit->snd_stream, desig_is, ISIS_SYS_ID_LEN + 1);
+ } else {
+ stream_putc(circuit->snd_stream, circuit->circuit_id);
+ }
}
int send_hello(struct isis_circuit *circuit, int level)
{
- struct isis_fixed_hdr fixed_hdr;
- struct isis_lan_hello_hdr hello_hdr;
- struct isis_p2p_hello_hdr p2p_hello_hdr;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
- size_t len_pointer, length, auth_tlv_offset = 0;
- u_int32_t interval;
+ size_t len_pointer;
int retval;
if (circuit->is_passive)
@@ -2102,113 +1524,21 @@ int send_hello(struct isis_circuit *circuit, int level)
return ISIS_WARNING;
}
- isis_circuit_stream(circuit, &circuit->snd_stream);
-
- if (circuit->circ_type == CIRCUIT_T_BROADCAST)
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_LAN_HELLO,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_LAN_HELLO,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, P2P_HELLO,
- circuit->snd_stream);
-
- /*
- * Fill LAN Level 1 or 2 Hello PDU header
- */
- memset(&hello_hdr, 0, sizeof(struct isis_lan_hello_hdr));
- interval = circuit->hello_multiplier[level - 1]
- * circuit->hello_interval[level - 1];
- if (interval > USHRT_MAX)
- interval = USHRT_MAX;
- hello_hdr.circuit_t = circuit->is_type;
- memcpy(hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN);
- hello_hdr.hold_time = htons((u_int16_t)interval);
-
- hello_hdr.pdu_len = 0; /* Update the PDU Length later */
- len_pointer =
- stream_get_endp(circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN;
-
- /* copy the shared part of the hello to the p2p hello if needed */
- if (circuit->circ_type == CIRCUIT_T_P2P) {
- memcpy(&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN);
- p2p_hello_hdr.local_id = circuit->circuit_id;
- /* FIXME: need better understanding */
- stream_put(circuit->snd_stream, &p2p_hello_hdr,
- ISIS_P2PHELLO_HDRLEN);
- } else {
- hello_hdr.prio = circuit->priority[level - 1];
- if (level == IS_LEVEL_1) {
- memcpy(hello_hdr.lan_id, circuit->u.bc.l1_desig_is,
- ISIS_SYS_ID_LEN + 1);
- } else if (level == IS_LEVEL_2) {
- memcpy(hello_hdr.lan_id, circuit->u.bc.l2_desig_is,
- ISIS_SYS_ID_LEN + 1);
- }
- stream_put(circuit->snd_stream, &hello_hdr,
- ISIS_LANHELLO_HDRLEN);
- }
-
- /*
- * Then the variable length part.
- */
-
- /* add circuit password */
- switch (circuit->passwd.type) {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- if (tlv_add_authinfo(circuit->passwd.type, circuit->passwd.len,
- circuit->passwd.passwd,
- circuit->snd_stream))
- return ISIS_WARNING;
- break;
+ put_hello_hdr(circuit, level, &len_pointer);
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Remember where TLV is written so we can later overwrite the
- * MD5 hash */
- auth_tlv_offset = stream_get_endp(circuit->snd_stream);
- memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
- if (tlv_add_authinfo(circuit->passwd.type, ISIS_AUTH_MD5_SIZE,
- hmac_md5_hash, circuit->snd_stream))
- return ISIS_WARNING;
- break;
+ struct isis_tlvs *tlvs = isis_alloc_tlvs();
- default:
- break;
- }
+ isis_tlvs_add_auth(tlvs, &circuit->passwd);
- /* Area Addresses TLV */
- if (listcount(circuit->area->area_addrs) == 0)
- return ISIS_WARNING;
- if (tlv_add_area_addrs(circuit->area->area_addrs, circuit->snd_stream))
+ if (!listcount(circuit->area->area_addrs))
return ISIS_WARNING;
+ isis_tlvs_add_area_addresses(tlvs, circuit->area->area_addrs);
- /* LAN Neighbors TLV */
- if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
- if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0]
- && listcount(circuit->u.bc.lan_neighs[0]) > 0)
- if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[0],
- circuit->snd_stream))
- return ISIS_WARNING;
- if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1]
- && listcount(circuit->u.bc.lan_neighs[1]) > 0)
- if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[1],
- circuit->snd_stream))
- return ISIS_WARNING;
- }
-
- /* Protocols Supported TLV */
- if (circuit->nlpids.count > 0)
- if (tlv_add_nlpid(&circuit->nlpids, circuit->snd_stream))
- return ISIS_WARNING;
- /* IP interface Address TLV */
- if (circuit->ip_router && circuit->ip_addrs
- && listcount(circuit->ip_addrs) > 0)
- if (tlv_add_ip_addrs(circuit->ip_addrs, circuit->snd_stream))
- return ISIS_WARNING;
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+ isis_tlvs_add_lan_neighbors(
+ tlvs, circuit->u.bc.lan_neighs[level - 1]);
+
+ isis_tlvs_set_protocols_supported(tlvs, &circuit->nlpids);
/*
* MT Supported TLV
@@ -2221,48 +1551,26 @@ int send_hello(struct isis_circuit *circuit, int level)
unsigned int mt_count;
mt_settings = circuit_mt_settings(circuit, &mt_count);
- if ((mt_count == 0 && area_is_mt(circuit->area))
- || (mt_count == 1 && mt_settings[0]->mtid != ISIS_MT_IPV4_UNICAST)
- || (mt_count > 1)) {
- struct list *mt_info = list_new();
- mt_info->del = free_tlv;
-
- for (unsigned int i = 0; i < mt_count; i++) {
- struct mt_router_info *info;
-
- info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info));
- info->mtid = mt_settings[i]->mtid;
- /* overload info is not valid in IIH, so it's not
- * included here */
- listnode_add(mt_info, info);
- }
- tlv_add_mt_router_info(mt_info, circuit->snd_stream);
- list_free(mt_info);
+ if (mt_count == 0 && area_is_mt(circuit->area)) {
+ tlvs->mt_router_info_empty = true;
+ } else if ((mt_count == 1
+ && mt_settings[0]->mtid != ISIS_MT_IPV4_UNICAST)
+ || (mt_count > 1)) {
+ for (unsigned int i = 0; i < mt_count; i++)
+ isis_tlvs_add_mt_router_info(tlvs, mt_settings[i]->mtid,
+ false, false);
}
- /* IPv6 Interface Address TLV */
- if (circuit->ipv6_router && circuit->ipv6_link
- && listcount(circuit->ipv6_link) > 0)
- if (tlv_add_ipv6_addrs(circuit->ipv6_link, circuit->snd_stream))
- return ISIS_WARNING;
+ if (circuit->ip_router && circuit->ip_addrs)
+ isis_tlvs_add_ipv4_addresses(tlvs, circuit->ip_addrs);
- if (circuit->pad_hellos)
- if (tlv_add_padding(circuit->snd_stream))
- return ISIS_WARNING;
-
- length = stream_get_endp(circuit->snd_stream);
- /* Update PDU length */
- stream_putw_at(circuit->snd_stream, len_pointer, (u_int16_t)length);
+ if (circuit->ipv6_router && circuit->ipv6_link)
+ isis_tlvs_add_ipv6_addresses(tlvs, circuit->ipv6_link);
- /* For HMAC MD5 we need to compute the md5 hash and store it */
- if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) {
- hmac_md5(STREAM_DATA(circuit->snd_stream),
- stream_get_endp(circuit->snd_stream),
- (unsigned char *)&circuit->passwd.passwd,
- circuit->passwd.len, (unsigned char *)&hmac_md5_hash);
- /* Copy the hash into the stream */
- memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3,
- hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
+ if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer,
+ circuit->pad_hellos, false)) {
+ isis_free_tlvs(tlvs);
+ return ISIS_WARNING; /* XXX: Maybe Log TLV structure? */
}
if (isis->debugs & DEBUG_ADJ_PACKETS) {
@@ -2270,18 +1578,22 @@ int send_hello(struct isis_circuit *circuit, int level)
zlog_debug(
"ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd",
circuit->area->area_tag, level,
- circuit->interface->name, length);
+ circuit->interface->name,
+ stream_get_endp(circuit->snd_stream));
} else {
zlog_debug(
"ISIS-Adj (%s): Sending P2P IIH on %s, length %zd",
circuit->area->area_tag,
- circuit->interface->name, length);
+ circuit->interface->name,
+ stream_get_endp(circuit->snd_stream));
}
if (isis->debugs & DEBUG_PACKET_DUMP)
zlog_dump_data(STREAM_DATA(circuit->snd_stream),
stream_get_endp(circuit->snd_stream));
}
+ isis_free_tlvs(tlvs);
+
retval = circuit->tx(circuit, level);
if (retval != ISIS_OK)
zlog_err("ISIS-Adj (%s): Send L%d IIH on %s failed",
@@ -2366,101 +1678,10 @@ int send_p2p_hello(struct thread *thread)
return ISIS_OK;
}
-static int build_csnp(int level, u_char *start, u_char *stop, struct list *lsps,
- struct isis_circuit *circuit)
-{
- struct isis_fixed_hdr fixed_hdr;
- struct isis_passwd *passwd;
- unsigned long lenp;
- u_int16_t length;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
- unsigned long auth_tlv_offset = 0;
- int retval = ISIS_OK;
-
- isis_circuit_stream(circuit, &circuit->snd_stream);
-
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_COMPLETE_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_COMPLETE_SEQ_NUM,
- circuit->snd_stream);
-
- /*
- * Fill Level 1 or 2 Complete Sequence Numbers header
- */
-
- lenp = stream_get_endp(circuit->snd_stream);
- stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */
- /* no need to send the source here, it is always us if we csnp */
- stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
- /* with zero circuit id - ref 9.10, 9.11 */
- stream_putc(circuit->snd_stream, 0x00);
-
- stream_put(circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2);
- stream_put(circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2);
-
- /*
- * And TLVs
- */
- if (level == IS_LEVEL_1)
- passwd = &circuit->area->area_passwd;
- else
- passwd = &circuit->area->domain_passwd;
-
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) {
- switch (passwd->type) {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT,
- passwd->len, passwd->passwd,
- circuit->snd_stream))
- return ISIS_WARNING;
- break;
-
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Remember where TLV is written so we can later
- * overwrite the MD5 hash */
- auth_tlv_offset = stream_get_endp(circuit->snd_stream);
- memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
- if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5,
- ISIS_AUTH_MD5_SIZE, hmac_md5_hash,
- circuit->snd_stream))
- return ISIS_WARNING;
- break;
-
- default:
- break;
- }
- }
-
- retval = tlv_add_lsp_entries(lsps, circuit->snd_stream);
- if (retval != ISIS_OK)
- return retval;
-
- length = (u_int16_t)stream_get_endp(circuit->snd_stream);
- /* Update PU length */
- stream_putw_at(circuit->snd_stream, lenp, length);
-
- /* For HMAC MD5 we need to compute the md5 hash and store it */
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)
- && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) {
- hmac_md5(STREAM_DATA(circuit->snd_stream),
- stream_get_endp(circuit->snd_stream),
- (unsigned char *)&passwd->passwd, passwd->len,
- (unsigned char *)&hmac_md5_hash);
- /* Copy the hash into the stream */
- memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3,
- hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
- }
-
- return retval;
-}
-
/*
* Count the maximum number of lsps that can be accomodated by a given size.
*/
+#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN)
static uint16_t get_max_lsp_count(uint16_t size)
{
uint16_t tlv_count;
@@ -2479,109 +1700,81 @@ static uint16_t get_max_lsp_count(uint16_t size)
return lsp_count;
}
-/*
- * Calculate the length of Authentication Info. TLV.
- */
-static uint16_t auth_tlv_length(int level, struct isis_circuit *circuit)
+int send_csnp(struct isis_circuit *circuit, int level)
{
- struct isis_passwd *passwd;
- uint16_t length;
+ if (circuit->area->lspdb[level - 1] == NULL
+ || dict_count(circuit->area->lspdb[level - 1]) == 0)
+ return ISIS_OK;
- if (level == IS_LEVEL_1)
- passwd = &circuit->area->area_passwd;
- else
- passwd = &circuit->area->domain_passwd;
-
- /* Also include the length of TLV header */
- length = AUTH_INFO_HDRLEN;
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) {
- switch (passwd->type) {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- length += passwd->len;
- break;
-
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- length += ISIS_AUTH_MD5_SIZE;
- break;
-
- default:
- break;
- }
- }
+ isis_circuit_stream(circuit, &circuit->snd_stream);
+ fill_fixed_hdr((level == ISIS_LEVEL1) ? L1_COMPLETE_SEQ_NUM
+ : L2_COMPLETE_SEQ_NUM,
+ circuit->snd_stream);
- return length;
-}
+ size_t len_pointer = stream_get_endp(circuit->snd_stream);
+ stream_putw(circuit->snd_stream, 0);
+ stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+ /* with zero circuit id - ref 9.10, 9.11 */
+ stream_putc(circuit->snd_stream, 0);
-/*
- * Calculate the maximum number of lsps that can be accomodated in a CSNP/PSNP.
- */
-static uint16_t max_lsps_per_snp(int snp_type, int level,
- struct isis_circuit *circuit)
-{
- int snp_hdr_len;
- int auth_tlv_len;
- uint16_t lsp_count;
+ size_t start_pointer = stream_get_endp(circuit->snd_stream);
+ stream_put(circuit->snd_stream, 0, ISIS_SYS_ID_LEN + 2);
+ size_t end_pointer = stream_get_endp(circuit->snd_stream);
+ stream_put(circuit->snd_stream, 0, ISIS_SYS_ID_LEN + 2);
- snp_hdr_len = ISIS_FIXED_HDR_LEN;
- if (snp_type == ISIS_SNP_CSNP_FLAG)
- snp_hdr_len += ISIS_CSNP_HDRLEN;
- else
- snp_hdr_len += ISIS_PSNP_HDRLEN;
+ struct isis_passwd *passwd = (level == ISIS_LEVEL1)
+ ? &circuit->area->area_passwd
+ : &circuit->area->domain_passwd;
- auth_tlv_len = auth_tlv_length(level, circuit);
- lsp_count = get_max_lsp_count(stream_get_size(circuit->snd_stream)
- - snp_hdr_len - auth_tlv_len);
- return lsp_count;
-}
+ struct isis_tlvs *tlvs = isis_alloc_tlvs();
-/*
- * FIXME: support multiple CSNPs
- */
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+ isis_tlvs_add_auth(tlvs, passwd);
-int send_csnp(struct isis_circuit *circuit, int level)
-{
- u_char start[ISIS_SYS_ID_LEN + 2];
- u_char stop[ISIS_SYS_ID_LEN + 2];
- struct list *list = NULL;
- struct listnode *node;
- struct isis_lsp *lsp;
- u_char num_lsps, loop = 1;
- int i, retval = ISIS_OK;
+ size_t tlv_start = stream_get_endp(circuit->snd_stream);
+ if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false,
+ false)) {
+ isis_free_tlvs(tlvs);
+ return ISIS_WARNING;
+ }
+ isis_free_tlvs(tlvs);
- if (circuit->area->lspdb[level - 1] == NULL
- || dict_count(circuit->area->lspdb[level - 1]) == 0)
- return retval;
+ uint16_t num_lsps =
+ get_max_lsp_count(STREAM_WRITEABLE(circuit->snd_stream));
+ uint8_t start[ISIS_SYS_ID_LEN + 2];
memset(start, 0x00, ISIS_SYS_ID_LEN + 2);
+ uint8_t stop[ISIS_SYS_ID_LEN + 2];
memset(stop, 0xff, ISIS_SYS_ID_LEN + 2);
- num_lsps = max_lsps_per_snp(ISIS_SNP_CSNP_FLAG, level, circuit);
-
+ bool loop = true;
while (loop) {
- list = list_new();
- lsp_build_list(start, stop, num_lsps, list,
- circuit->area->lspdb[level - 1]);
+ tlvs = isis_alloc_tlvs();
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+ isis_tlvs_add_auth(tlvs, passwd);
+
+ struct isis_lsp *last_lsp;
+ isis_tlvs_add_csnp_entries(tlvs, start, stop, num_lsps,
+ circuit->area->lspdb[level - 1],
+ &last_lsp);
/*
* Update the stop lsp_id before encoding this CSNP.
*/
- if (listcount(list) < num_lsps) {
+ if (tlvs->lsp_entries.count < num_lsps) {
memset(stop, 0xff, ISIS_SYS_ID_LEN + 2);
} else {
- node = listtail(list);
- lsp = listgetdata(node);
- memcpy(stop, lsp->lsp_header->lsp_id,
- ISIS_SYS_ID_LEN + 2);
+ memcpy(stop, last_lsp->hdr.lsp_id, sizeof(stop));
}
- retval = build_csnp(level, start, stop, list, circuit);
- if (retval != ISIS_OK) {
- zlog_err("ISIS-Snp (%s): Build L%d CSNP on %s failed",
- circuit->area->area_tag, level,
- circuit->interface->name);
- list_delete(list);
- return retval;
+ memcpy(STREAM_DATA(circuit->snd_stream) + start_pointer, start,
+ ISIS_SYS_ID_LEN + 2);
+ memcpy(STREAM_DATA(circuit->snd_stream) + end_pointer, stop,
+ ISIS_SYS_ID_LEN + 2);
+ stream_set_endp(circuit->snd_stream, tlv_start);
+ if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer,
+ false, false)) {
+ isis_free_tlvs(tlvs);
+ return ISIS_WARNING;
}
if (isis->debugs & DEBUG_SNP_PACKETS) {
@@ -2590,28 +1783,20 @@ int send_csnp(struct isis_circuit *circuit, int level)
circuit->area->area_tag, level,
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
- for (ALL_LIST_ELEMENTS_RO(list, node, lsp)) {
- zlog_debug(
- "ISIS-Snp (%s): CSNP entry %s, seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- circuit->area->area_tag,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime));
- }
+ log_multiline(LOG_DEBUG, " ", "%s",
+ isis_format_tlvs(tlvs));
if (isis->debugs & DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
stream_get_endp(circuit->snd_stream));
}
- retval = circuit->tx(circuit, level);
+ int retval = circuit->tx(circuit, level);
if (retval != ISIS_OK) {
zlog_err("ISIS-Snp (%s): Send L%d CSNP on %s failed",
circuit->area->area_tag, level,
circuit->interface->name);
- list_delete(list);
+ isis_free_tlvs(tlvs);
return retval;
}
@@ -2621,7 +1806,7 @@ int send_csnp(struct isis_circuit *circuit, int level)
*/
memcpy(start, stop, ISIS_SYS_ID_LEN + 2);
loop = 0;
- for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) {
+ for (int i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) {
if (start[i] < (u_char)0xff) {
start[i] += 1;
loop = 1;
@@ -2629,10 +1814,10 @@ int send_csnp(struct isis_circuit *circuit, int level)
}
}
memset(stop, 0xff, ISIS_SYS_ID_LEN + 2);
- list_delete(list);
+ isis_free_tlvs(tlvs);
}
- return retval;
+ return ISIS_OK;
}
int send_l1_csnp(struct thread *thread)
@@ -2679,120 +1864,12 @@ int send_l2_csnp(struct thread *thread)
return retval;
}
-static int build_psnp(int level, struct isis_circuit *circuit,
- struct list *lsps)
-{
- struct isis_fixed_hdr fixed_hdr;
- unsigned long lenp;
- u_int16_t length;
- struct isis_lsp *lsp;
- struct isis_passwd *passwd;
- struct listnode *node;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
- unsigned long auth_tlv_offset = 0;
- int retval = ISIS_OK;
-
- isis_circuit_stream(circuit, &circuit->snd_stream);
-
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
-
- /*
- * Fill Level 1 or 2 Partial Sequence Numbers header
- */
- lenp = stream_get_endp(circuit->snd_stream);
- stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */
- stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
- stream_putc(circuit->snd_stream, circuit->idx);
-
- /*
- * And TLVs
- */
-
- if (level == IS_LEVEL_1)
- passwd = &circuit->area->area_passwd;
- else
- passwd = &circuit->area->domain_passwd;
-
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) {
- switch (passwd->type) {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT,
- passwd->len, passwd->passwd,
- circuit->snd_stream))
- return ISIS_WARNING;
- break;
-
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Remember where TLV is written so we can later
- * overwrite the MD5 hash */
- auth_tlv_offset = stream_get_endp(circuit->snd_stream);
- memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
- if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5,
- ISIS_AUTH_MD5_SIZE, hmac_md5_hash,
- circuit->snd_stream))
- return ISIS_WARNING;
- break;
-
- default:
- break;
- }
- }
-
- retval = tlv_add_lsp_entries(lsps, circuit->snd_stream);
- if (retval != ISIS_OK)
- return retval;
-
- if (isis->debugs & DEBUG_SNP_PACKETS) {
- for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) {
- zlog_debug(
- "ISIS-Snp (%s): PSNP entry %s, seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- circuit->area->area_tag,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime));
- }
- }
-
- length = (u_int16_t)stream_get_endp(circuit->snd_stream);
- /* Update PDU length */
- stream_putw_at(circuit->snd_stream, lenp, length);
-
- /* For HMAC MD5 we need to compute the md5 hash and store it */
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)
- && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) {
- hmac_md5(STREAM_DATA(circuit->snd_stream),
- stream_get_endp(circuit->snd_stream),
- (unsigned char *)&passwd->passwd, passwd->len,
- (unsigned char *)&hmac_md5_hash);
- /* Copy the hash into the stream */
- memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3,
- hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
- }
-
- return ISIS_OK;
-}
-
/*
* 7.3.15.4 action on expiration of partial SNP interval
* level 1
*/
static int send_psnp(int level, struct isis_circuit *circuit)
{
- struct isis_lsp *lsp;
- struct list *list = NULL;
- struct listnode *node;
- u_char num_lsps;
- int retval = ISIS_OK;
-
if (circuit->circ_type == CIRCUIT_T_BROADCAST
&& circuit->u.bc.is_dr[level - 1])
return ISIS_OK;
@@ -2804,25 +1881,64 @@ static int send_psnp(int level, struct isis_circuit *circuit)
if (!circuit->snd_stream)
return ISIS_ERROR;
- num_lsps = max_lsps_per_snp(ISIS_SNP_PSNP_FLAG, level, circuit);
+ isis_circuit_stream(circuit, &circuit->snd_stream);
+ fill_fixed_hdr((level == ISIS_LEVEL1) ? L1_PARTIAL_SEQ_NUM
+ : L2_PARTIAL_SEQ_NUM,
+ circuit->snd_stream);
+
+ size_t len_pointer = stream_get_endp(circuit->snd_stream);
+ stream_putw(circuit->snd_stream, 0); /* length is filled in later */
+ stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+ stream_putc(circuit->snd_stream, circuit->idx);
+
+ struct isis_passwd *passwd = (level == ISIS_LEVEL1)
+ ? &circuit->area->area_passwd
+ : &circuit->area->domain_passwd;
+
+ struct isis_tlvs *tlvs = isis_alloc_tlvs();
+
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+ isis_tlvs_add_auth(tlvs, passwd);
+
+ size_t tlv_start = stream_get_endp(circuit->snd_stream);
+ if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false,
+ false)) {
+ isis_free_tlvs(tlvs);
+ return ISIS_WARNING;
+ }
+ isis_free_tlvs(tlvs);
+
+ uint16_t num_lsps =
+ get_max_lsp_count(STREAM_WRITEABLE(circuit->snd_stream));
while (1) {
- list = list_new();
- lsp_build_list_ssn(circuit, num_lsps, list,
- circuit->area->lspdb[level - 1]);
+ tlvs = isis_alloc_tlvs();
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+ isis_tlvs_add_auth(tlvs, passwd);
+
+ for (dnode_t *dnode =
+ dict_first(circuit->area->lspdb[level - 1]);
+ dnode; dnode = dict_next(circuit->area->lspdb[level - 1],
+ dnode)) {
+ struct isis_lsp *lsp = dnode_get(dnode);
- if (listcount(list) == 0) {
- list_delete(list);
+ if (ISIS_CHECK_FLAG(lsp->SSNflags, circuit))
+ isis_tlvs_add_lsp_entry(tlvs, lsp);
+
+ if (tlvs->lsp_entries.count == num_lsps)
+ break;
+ }
+
+ if (!tlvs->lsp_entries.count) {
+ isis_free_tlvs(tlvs);
return ISIS_OK;
}
- retval = build_psnp(level, circuit, list);
- if (retval != ISIS_OK) {
- zlog_err("ISIS-Snp (%s): Build L%d PSNP on %s failed",
- circuit->area->area_tag, level,
- circuit->interface->name);
- list_delete(list);
- return retval;
+ stream_set_endp(circuit->snd_stream, tlv_start);
+ if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer,
+ false, false)) {
+ isis_free_tlvs(tlvs);
+ return ISIS_WARNING;
}
if (isis->debugs & DEBUG_SNP_PACKETS) {
@@ -2831,18 +1947,20 @@ static int send_psnp(int level, struct isis_circuit *circuit)
circuit->area->area_tag, level,
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
+ log_multiline(LOG_DEBUG, " ", "%s",
+ isis_format_tlvs(tlvs));
if (isis->debugs & DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
stream_get_endp(circuit->snd_stream));
}
- retval = circuit->tx(circuit, level);
+ int retval = circuit->tx(circuit, level);
if (retval != ISIS_OK) {
zlog_err("ISIS-Snp (%s): Send L%d PSNP on %s failed",
circuit->area->area_tag, level,
circuit->interface->name);
- list_delete(list);
+ isis_free_tlvs(tlvs);
return retval;
}
@@ -2850,12 +1968,15 @@ static int send_psnp(int level, struct isis_circuit *circuit)
* sending succeeded, we can clear SSN flags of this circuit
* for the LSPs in list
*/
- for (ALL_LIST_ELEMENTS_RO(list, node, lsp))
- ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
- list_delete(list);
+ struct isis_lsp_entry *entry_head;
+ entry_head = (struct isis_lsp_entry *)tlvs->lsp_entries.head;
+ for (struct isis_lsp_entry *entry = entry_head; entry;
+ entry = entry->next)
+ ISIS_CLEAR_FLAG(entry->lsp->SSNflags, circuit);
+ isis_free_tlvs(tlvs);
}
- return retval;
+ return ISIS_OK;
}
int send_l1_psnp(struct thread *thread)
@@ -2963,14 +2084,12 @@ int send_lsp(struct thread *thread)
* the circuit's MTU. So handle and log this case here. */
if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) {
zlog_err(
- "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x,"
- " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu"
- " while interface stream size is %zu.",
+ "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s on %s. LSP Size is %zu while interface stream size is %zu.",
circuit->area->area_tag, lsp->level,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime),
+ rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno,
+ lsp->hdr.checksum, lsp->hdr.rem_lifetime,
circuit->interface->name, stream_get_endp(lsp->pdu),
stream_get_size(circuit->snd_stream));
if (isis->debugs & DEBUG_PACKET_DUMP)
@@ -2984,15 +2103,13 @@ int send_lsp(struct thread *thread)
stream_copy(circuit->snd_stream, lsp->pdu);
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
- zlog_debug(
- "ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
- " lifetime %us on %s",
- circuit->area->area_tag, lsp->level,
- rawlspid_print(lsp->lsp_header->lsp_id),
- ntohl(lsp->lsp_header->seq_num),
- ntohs(lsp->lsp_header->checksum),
- ntohs(lsp->lsp_header->rem_lifetime),
- circuit->interface->name);
+ zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
+ "s on %s",
+ circuit->area->area_tag, lsp->level,
+ rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno,
+ lsp->hdr.checksum, lsp->hdr.rem_lifetime,
+ circuit->interface->name);
if (isis->debugs & DEBUG_PACKET_DUMP)
zlog_dump_data(STREAM_DATA(circuit->snd_stream),
stream_get_endp(circuit->snd_stream));
@@ -3026,47 +2143,3 @@ out:
return retval;
}
-
-int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
- int level)
-{
- unsigned long lenp;
- int retval;
- u_int16_t length;
- struct isis_fixed_hdr fixed_hdr;
-
- isis_circuit_stream(circuit, &circuit->snd_stream);
-
- // fill_llc_hdr (stream);
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
-
-
- lenp = stream_get_endp(circuit->snd_stream);
- stream_putw(circuit->snd_stream, 0); /* PDU length */
- stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
- stream_putc(circuit->snd_stream, circuit->idx);
- stream_putc(circuit->snd_stream, 9); /* code */
- stream_putc(circuit->snd_stream, 16); /* len */
-
- stream_putw(circuit->snd_stream, ntohs(hdr->rem_lifetime));
- stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
- stream_putl(circuit->snd_stream, ntohl(hdr->seq_num));
- stream_putw(circuit->snd_stream, ntohs(hdr->checksum));
-
- length = (u_int16_t)stream_get_endp(circuit->snd_stream);
- /* Update PDU length */
- stream_putw_at(circuit->snd_stream, lenp, length);
-
- retval = circuit->tx(circuit, level);
- if (retval != ISIS_OK)
- zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed",
- circuit->area->area_tag, level,
- circuit->interface->name);
-
- return retval;
-}
diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h
index fa8006cda0..7096761879 100644
--- a/isisd/isis_pdu.h
+++ b/isisd/isis_pdu.h
@@ -65,36 +65,6 @@ struct esis_fixed_hdr {
#define ISH_PDU 4
#define RD_PDU 5
-/*
- * IS to IS Fixed Header
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Intradomain Routeing Protocol Discriminator |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Length Indicator |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Version/Protocol ID extension |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | R | R | R | PDU Type |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Version |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Reserved |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Maximum Area Addresses |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
-
-struct isis_fixed_hdr {
- u_char idrp;
- u_char length;
- u_char version1;
- u_char id_len;
- u_char pdu_type;
- u_char version2;
- u_char reserved;
- u_char max_area_addrs;
-} __attribute__((packed));
-
#define ISIS_FIXED_HDR_LEN 8
/*
@@ -155,30 +125,14 @@ struct isis_p2p_hello_hdr {
#define L1_LINK_STATE 18
#define L2_LINK_STATE 20
-/*
- * L1 and L2 IS to IS link state PDU header
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * + PDU Length + 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * + Remaining Lifetime + 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | LSP ID | id_len + 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * + Sequence Number + 4
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * + Checksum + 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | P | ATT |LSPDBOL| ISTYPE |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
-struct isis_link_state_hdr {
- u_int16_t pdu_len;
- u_int16_t rem_lifetime;
- u_char lsp_id[ISIS_SYS_ID_LEN + 2];
- u_int32_t seq_num;
- u_int16_t checksum;
- u_int8_t lsp_bits;
-} __attribute__((packed));
+struct isis_lsp_hdr {
+ uint16_t pdu_len;
+ uint16_t rem_lifetime;
+ uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
+ uint32_t seqno;
+ uint16_t checksum;
+ uint8_t lsp_bits;
+};
#define ISIS_LSP_HDR_LEN 19
/*
@@ -259,9 +213,7 @@ int send_l2_csnp(struct thread *thread);
int send_l1_psnp(struct thread *thread);
int send_l2_psnp(struct thread *thread);
int send_lsp(struct thread *thread);
-int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
- int level);
-void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type);
+void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
int send_hello(struct isis_circuit *circuit, int level);
#endif /* _ZEBRA_ISIS_PDU_H */
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c
index 8e329494dd..ea94b65805 100644
--- a/isisd/isis_redist.c
+++ b/isisd/isis_redist.c
@@ -37,7 +37,6 @@
#include "isisd/isis_flags.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_circuit.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h"
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index afc4f65128..267e72002f 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -42,7 +42,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
-#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_spf.h"
@@ -208,13 +207,12 @@ static void nexthops6_print(struct list *nhs6)
static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj)
{
struct isis_nexthop *nh;
- struct listnode *node;
- struct in_addr *ipv4_addr;
- if (adj->ipv4_addrs == NULL)
+ if (!adj->ipv4_address_count)
return;
- for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr)) {
+ for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
+ struct in_addr *ipv4_addr = &adj->ipv4_addresses[i];
if (!nexthoplookup(nexthops, ipv4_addr,
adj->circuit->interface->ifindex)) {
nh = isis_nexthop_create(
@@ -227,14 +225,13 @@ static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj)
static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj)
{
- struct listnode *node;
- struct in6_addr *ipv6_addr;
struct isis_nexthop6 *nh6;
- if (!adj->ipv6_addrs)
+ if (!adj->ipv6_address_count)
return;
- for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) {
+ for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
+ struct in6_addr *ipv6_addr = &adj->ipv6_addresses[i];
if (!nexthop6lookup(nexthops6, ipv6_addr,
adj->circuit->interface->ifindex)) {
nh6 = isis_nexthop6_create(
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index 44d7fa0403..d92207d57c 100644
--- a/isisd/isis_routemap.c
+++ b/isisd/isis_routemap.c
@@ -42,7 +42,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
-#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_spf.h"
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 615c2eeaa2..9acbc21838 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -35,6 +35,7 @@
#include "if.h"
#include "table.h"
#include "spf_backoff.h"
+#include "jhash.h"
#include "isis_constants.h"
#include "isis_common.h"
@@ -44,7 +45,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
-#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_dynhn.h"
@@ -52,9 +52,178 @@
#include "isis_route.h"
#include "isis_csm.h"
#include "isis_mt.h"
+#include "isis_tlvs.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
+enum vertextype {
+ VTYPE_PSEUDO_IS = 1,
+ VTYPE_PSEUDO_TE_IS,
+ VTYPE_NONPSEUDO_IS,
+ VTYPE_NONPSEUDO_TE_IS,
+ VTYPE_ES,
+ VTYPE_IPREACH_INTERNAL,
+ VTYPE_IPREACH_EXTERNAL,
+ VTYPE_IPREACH_TE,
+ VTYPE_IP6REACH_INTERNAL,
+ VTYPE_IP6REACH_EXTERNAL
+};
+
+#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
+#define VTYPE_ES(t) ((t) == VTYPE_ES)
+#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
+
+/*
+ * Triple <N, d(N), {Adj(N)}>
+ */
+struct isis_vertex {
+ enum vertextype type;
+
+ union {
+ u_char id[ISIS_SYS_ID_LEN + 1];
+ struct prefix prefix;
+ } N;
+
+ u_int32_t d_N; /* d(N) Distance from this IS */
+ u_int16_t depth; /* The depth in the imaginary tree */
+ struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
+ struct list *parents; /* list of parents for ECMP */
+ struct list *children; /* list of children used for tree dump */
+};
+
+/* Vertex Queue and associated functions */
+
+struct isis_vertex_queue {
+ struct list *list;
+ struct hash *hash;
+};
+
+static unsigned isis_vertex_queue_hash_key(void *vp)
+{
+ struct isis_vertex *vertex = vp;
+
+ if (VTYPE_IP(vertex->type))
+ return prefix_hash_key(&vertex->N.prefix);
+
+ return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a);
+}
+
+static int isis_vertex_queue_hash_cmp(const void *a, const void *b)
+{
+ const struct isis_vertex *va = a, *vb = b;
+
+ if (va->type != vb->type)
+ return 0;
+
+ if (VTYPE_IP(va->type))
+ return prefix_cmp(&va->N.prefix, &vb->N.prefix) == 0;
+
+ return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0;
+}
+
+static void isis_vertex_queue_init(struct isis_vertex_queue *queue, const char *name)
+{
+ queue->list = list_new();
+ queue->hash = hash_create(isis_vertex_queue_hash_key,
+ isis_vertex_queue_hash_cmp,
+ name);
+}
+
+static void isis_vertex_del(struct isis_vertex *vertex);
+
+static void isis_vertex_queue_clear(struct isis_vertex_queue *queue)
+{
+ hash_clean(queue->hash, NULL);
+
+ queue->list->del = (void (*)(void *))isis_vertex_del;
+ list_delete_all_node(queue->list);
+ queue->list->del = NULL;
+}
+
+static void isis_vertex_queue_free(struct isis_vertex_queue *queue)
+{
+ isis_vertex_queue_clear(queue);
+
+ hash_free(queue->hash);
+ queue->hash = NULL;
+
+ list_delete(queue->list);
+ queue->list = NULL;
+}
+
+static unsigned int isis_vertex_queue_count(struct isis_vertex_queue *queue)
+{
+ return listcount(queue->list);
+}
+
+static void isis_vertex_queue_add(struct isis_vertex_queue *queue,
+ struct isis_vertex *vertex)
+{
+ listnode_add(queue->list, vertex);
+
+ struct isis_vertex *inserted;
+
+ inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
+ assert(inserted == vertex);
+}
+
+static struct isis_vertex *isis_vertex_queue_pop(struct isis_vertex_queue *queue)
+{
+ struct listnode *node;
+
+ node = listhead(queue->list);
+ if (!node)
+ return NULL;
+
+ struct isis_vertex *rv = listgetdata(node);
+
+ list_delete_node(queue->list, node);
+ hash_release(queue->hash, rv);
+
+ return rv;
+}
+
+static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
+ struct isis_vertex *vertex)
+{
+ listnode_delete(queue->list, vertex);
+ hash_release(queue->hash, vertex);
+}
+
+#define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \
+ ALL_LIST_ELEMENTS_RO((queue)->list, node, data)
+
+
+/* End of vertex queue definitions */
+
+struct isis_spftree {
+ struct isis_vertex_queue paths; /* the SPT */
+ struct isis_vertex_queue tents; /* TENT */
+ struct isis_area *area; /* back pointer to area */
+ unsigned int runcount; /* number of runs since uptime */
+ time_t last_run_timestamp; /* last run timestamp for scheduling */
+ time_t last_run_duration; /* last run duration in msec */
+
+ uint16_t mtid;
+ int family;
+ int level;
+};
+
+
+/*
+ * supports the given af ?
+ */
+static bool speaks(uint8_t *protocols, uint8_t count, int family)
+{
+ for (uint8_t i = 0; i < count; i++) {
+ if (family == AF_INET && protocols[i] == NLPID_IP)
+ return true;
+ if (family == AF_INET6 && protocols[i] == NLPID_IPV6)
+ return true;
+ }
+ return false;
+}
+
struct isis_spf_run {
struct isis_area *area;
int level;
@@ -160,12 +329,8 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
return "UNKNOWN";
}
-static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype)
+static void isis_vertex_id_init(struct isis_vertex *vertex, void *id, enum vertextype vtype)
{
- struct isis_vertex *vertex;
-
- vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
-
vertex->type = vtype;
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
@@ -176,6 +341,15 @@ static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype)
} else {
zlog_err("WTF!");
}
+}
+
+static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype)
+{
+ struct isis_vertex *vertex;
+
+ vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
+
+ isis_vertex_id_init(vertex, id, vtype);
vertex->Adj_N = list_new();
vertex->parents = list_new();
@@ -223,8 +397,8 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area)
return NULL;
}
- tree->tents = list_new();
- tree->paths = list_new();
+ isis_vertex_queue_init(&tree->tents, "IS-IS SPF tents");
+ isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths");
tree->area = area;
tree->last_run_timestamp = 0;
tree->last_run_duration = 0;
@@ -234,15 +408,8 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area)
void isis_spftree_del(struct isis_spftree *spftree)
{
-
- spftree->tents->del = (void (*)(void *))isis_vertex_del;
- list_delete(spftree->tents);
- spftree->tents = NULL;
-
- spftree->paths->del = (void (*)(void *))isis_vertex_del;
- list_delete(spftree->paths);
- spftree->paths = NULL;
-
+ isis_vertex_queue_free(&spftree->tents);
+ isis_vertex_queue_free(&spftree->paths);
XFREE(MTYPE_ISIS_SPFTREE, spftree);
return;
@@ -252,12 +419,13 @@ static void isis_spftree_adj_del(struct isis_spftree *spftree,
struct isis_adjacency *adj)
{
struct listnode *node;
+ struct isis_vertex *v;
if (!adj)
return;
- for (node = listhead(spftree->tents); node; node = listnextnode(node))
- isis_vertex_adj_del(listgetdata(node), adj);
- for (node = listhead(spftree->paths); node; node = listnextnode(node))
- isis_vertex_adj_del(listgetdata(node), adj);
+ for (ALL_QUEUE_ELEMENTS_RO(&spftree->tents, node, v))
+ isis_vertex_adj_del(v, adj);
+ for (ALL_QUEUE_ELEMENTS_RO(&spftree->paths, node, v))
+ isis_vertex_adj_del(v, adj);
return;
}
@@ -340,7 +508,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level,
LSP_PSEUDO_ID(lspid) = 0;
LSP_FRAGMENT(lspid) = 0;
lsp = lsp_search(lspid, area->lspdb[level - 1]);
- if (lsp && lsp->lsp_header->rem_lifetime != 0)
+ if (lsp && lsp->hdr.rem_lifetime != 0)
return lsp;
return NULL;
}
@@ -370,7 +538,7 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
spftree->area->oldmetric
? VTYPE_NONPSEUDO_IS
: VTYPE_NONPSEUDO_TE_IS);
- listnode_add(spftree->paths, vertex);
+ isis_vertex_queue_add(&spftree->paths, vertex);
#ifdef EXTREME_DEBUG
zlog_debug("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
@@ -382,35 +550,13 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
return vertex;
}
-static struct isis_vertex *isis_find_vertex(struct list *list, void *id,
+static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue, void *id,
enum vertextype vtype)
{
- struct listnode *node;
- struct isis_vertex *vertex;
- struct prefix *p1, *p2;
+ struct isis_vertex querier;
- for (ALL_LIST_ELEMENTS_RO(list, node, vertex)) {
- if (vertex->type != vtype)
- continue;
- if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) {
- if (memcmp((u_char *)id, vertex->N.id,
- ISIS_SYS_ID_LEN + 1)
- == 0)
- return vertex;
- }
- if (VTYPE_IP(vertex->type)) {
- p1 = (struct prefix *)id;
- p2 = (struct prefix *)&vertex->N.id;
- if (p1->family == p2->family
- && p1->prefixlen == p2->prefixlen
- && !memcmp(&p1->u.prefix, &p2->u.prefix,
- PSIZE(p1->prefixlen))) {
- return vertex;
- }
- }
- }
-
- return NULL;
+ isis_vertex_id_init(&querier, id, vtype);
+ return hash_lookup(queue->hash, &querier);
}
/*
@@ -428,6 +574,30 @@ static bool tent_cmp(struct isis_vertex *current, struct isis_vertex *candidate)
return false;
}
+static void isis_vertex_queue_insert(struct isis_vertex_queue *queue,
+ struct isis_vertex *vertex)
+{
+ struct listnode *node;
+ struct isis_vertex *v;
+
+ /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */
+ for (node = listhead(queue->list); node; node = listnextnode(node)) {
+ v = listgetdata(node);
+ if (tent_cmp(v, vertex)) {
+ listnode_add_before(queue->list, node, vertex);
+ break;
+ }
+ }
+
+ if (node == NULL)
+ listnode_add(queue->list, vertex);
+
+ struct isis_vertex *inserted;
+
+ inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
+ assert(inserted == vertex);
+}
+
/*
* Add a vertex to TENT sorted by cost and by vertextype on tie break situation
*/
@@ -437,15 +607,15 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
struct isis_adjacency *adj,
struct isis_vertex *parent)
{
- struct isis_vertex *vertex, *v;
+ struct isis_vertex *vertex;
struct listnode *node;
struct isis_adjacency *parent_adj;
#ifdef EXTREME_DEBUG
char buff[PREFIX2STR_BUFFER];
#endif
- assert(isis_find_vertex(spftree->paths, id, vtype) == NULL);
- assert(isis_find_vertex(spftree->tents, id, vtype) == NULL);
+ assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL);
+ assert(isis_find_vertex(&spftree->tents, id, vtype) == NULL);
vertex = isis_vertex_new(id, vtype);
vertex->d_N = cost;
vertex->depth = depth;
@@ -471,23 +641,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
vertex->d_N, listcount(vertex->Adj_N));
#endif /* EXTREME_DEBUG */
- if (list_isempty(spftree->tents)) {
- listnode_add(spftree->tents, vertex);
- return vertex;
- }
-
- /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */
- for (node = listhead(spftree->tents); node; node = listnextnode(node)) {
- v = listgetdata(node);
- if (tent_cmp(v, vertex)) {
- listnode_add_before(spftree->tents, node, vertex);
- break;
- }
- }
-
- if (node == NULL)
- listnode_add(spftree->tents, vertex);
-
+ isis_vertex_queue_insert(&spftree->tents, vertex);
return vertex;
}
@@ -498,7 +652,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree,
{
struct isis_vertex *vertex;
- vertex = isis_find_vertex(spftree->tents, id, vtype);
+ vertex = isis_find_vertex(&spftree->tents, id, vtype);
if (vertex) {
/* C.2.5 c) */
@@ -522,7 +676,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree,
/* f) */
struct listnode *pnode, *pnextnode;
struct isis_vertex *pvertex;
- listnode_delete(spftree->tents, vertex);
+ isis_vertex_queue_delete(&spftree->tents, vertex);
assert(listcount(vertex->children) == 0);
for (ALL_LIST_ELEMENTS(vertex->parents, pnode,
pnextnode, pvertex))
@@ -546,6 +700,13 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
assert(spftree && parent);
+ struct prefix p;
+ if (vtype >= VTYPE_IPREACH_INTERNAL) {
+ prefix_copy(&p, id);
+ apply_mask(&p);
+ id = &p;
+ }
+
/* RFC3787 section 5.1 */
if (spftree->area->newmetric == 1) {
if (dist > MAX_WIDE_PATH_METRIC)
@@ -558,7 +719,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
}
/* c) */
- vertex = isis_find_vertex(spftree->paths, id, vtype);
+ vertex = isis_find_vertex(&spftree->paths, id, vtype);
if (vertex) {
#ifdef EXTREME_DEBUG
zlog_debug(
@@ -570,7 +731,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
return;
}
- vertex = isis_find_vertex(spftree->tents, id, vtype);
+ vertex = isis_find_vertex(&spftree->tents, id, vtype);
/* d) */
if (vertex) {
/* 1) */
@@ -605,7 +766,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
} else {
struct listnode *pnode, *pnextnode;
struct isis_vertex *pvertex;
- listnode_delete(spftree->tents, vertex);
+ isis_vertex_queue_delete(&spftree->tents, vertex);
assert(listcount(vertex->children) == 0);
for (ALL_LIST_ELEMENTS(vertex->parents, pnode,
pnextnode, pvertex))
@@ -632,30 +793,35 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
uint16_t depth, u_char *root_sysid,
struct isis_vertex *parent)
{
- bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id);
- struct listnode *node, *fragnode = NULL;
+ bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id);
+ struct listnode *fragnode = NULL;
uint32_t dist;
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct ipv4_reachability *ipreach;
- struct te_ipv4_reachability *te_ipv4_reach;
enum vertextype vtype;
- struct prefix prefix;
- struct ipv6_reachability *ip6reach;
static const u_char null_sysid[ISIS_SYS_ID_LEN];
- struct mt_router_info *mt_router_info = NULL;
+ struct isis_mt_router_info *mt_router_info = NULL;
+
+ if (!lsp->tlvs)
+ return ISIS_OK;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST)
- mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data,
- spftree->mtid);
+ mt_router_info = isis_tlvs_lookup_mt_router_info(lsp->tlvs,
+ spftree->mtid);
if (!pseudo_lsp && (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !speaks(lsp->tlv_data.nlpids, spftree->family))
+ && !speaks(lsp->tlvs->protocols_supported.protocols,
+ lsp->tlvs->protocols_supported.count,
+ spftree->family))
&& !mt_router_info)
return ISIS_OK;
+ /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
+ bool no_overload = (pseudo_lsp
+ || (spftree->mtid == ISIS_MT_IPV4_UNICAST
+ && !ISIS_MASK_LSP_OL_BIT(lsp->hdr.lsp_bits))
+ || (mt_router_info && !mt_router_info->overload));
+
lspfragloop:
- if (lsp->lsp_header->seq_num == 0) {
+ if (lsp->hdr.seqno == 0) {
zlog_warn(
"isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
return ISIS_WARNING;
@@ -663,142 +829,117 @@ lspfragloop:
#ifdef EXTREME_DEBUG
zlog_debug("ISIS-Spf: process_lsp %s",
- print_sys_hostname(lsp->lsp_header->lsp_id));
+ print_sys_hostname(lsp->hdr.lsp_id));
#endif /* EXTREME_DEBUG */
- /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
- if (pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits))
- || (mt_router_info && !mt_router_info->overload))
-
- {
+ if (no_overload) {
if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, node,
- is_neigh)) {
+ struct isis_oldstyle_reach *r;
+ for (r = (struct isis_oldstyle_reach *)
+ lsp->tlvs->oldstyle_reach.head;
+ r; r = r->next) {
/* C.2.6 a) */
/* Two way connectivity */
- if (!memcmp(is_neigh->neigh_id, root_sysid,
- ISIS_SYS_ID_LEN))
+ if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
- && !memcmp(is_neigh->neigh_id, null_sysid,
+ && !memcmp(r->id, null_sysid,
ISIS_SYS_ID_LEN))
continue;
- dist = cost + is_neigh->metrics.metric_default;
+ dist = cost + r->metric;
process_N(spftree,
- LSP_PSEUDO_ID(is_neigh->neigh_id)
+ LSP_PSEUDO_ID(r->id)
? VTYPE_PSEUDO_IS
: VTYPE_NONPSEUDO_IS,
- (void *)is_neigh->neigh_id, dist,
- depth + 1, parent);
+ (void *)r->id, dist, depth + 1,
+ parent);
}
}
- struct list *te_is_neighs = NULL;
- if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- te_is_neighs = lsp->tlv_data.te_is_neighs;
- } else {
- struct tlv_mt_neighbors *mt_neighbors;
- mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data,
- spftree->mtid);
- if (mt_neighbors)
- te_is_neighs = mt_neighbors->list;
- }
- for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) {
- if (!memcmp(te_is_neigh->neigh_id, root_sysid,
- ISIS_SYS_ID_LEN))
+ struct isis_item_list *te_neighs = NULL;
+ if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ te_neighs = &lsp->tlvs->extended_reach;
+ else
+ te_neighs = isis_lookup_mt_items(&lsp->tlvs->mt_reach,
+ spftree->mtid);
+
+ struct isis_extended_reach *er;
+ for (er = te_neighs
+ ? (struct isis_extended_reach *)
+ te_neighs->head
+ : NULL;
+ er; er = er->next) {
+ if (!memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
- && !memcmp(te_is_neigh->neigh_id, null_sysid,
- ISIS_SYS_ID_LEN))
+ && !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
continue;
- dist = cost + GET_TE_METRIC(te_is_neigh);
+ dist = cost + er->metric;
process_N(spftree,
- LSP_PSEUDO_ID(te_is_neigh->neigh_id)
- ? VTYPE_PSEUDO_TE_IS
- : VTYPE_NONPSEUDO_TE_IS,
- (void *)te_is_neigh->neigh_id, dist,
- depth + 1, parent);
+ LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
+ : VTYPE_NONPSEUDO_TE_IS,
+ (void *)er->id, dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET
&& spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs,
- lsp->tlv_data.ipv4_ext_reachs};
+ struct isis_item_list *reachs[] = {
+ &lsp->tlvs->oldstyle_ip_reach,
+ &lsp->tlvs->oldstyle_ip_reach_ext};
- prefix.family = AF_INET;
for (unsigned int i = 0; i < array_size(reachs); i++) {
- vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs)
- ? VTYPE_IPREACH_INTERNAL
- : VTYPE_IPREACH_EXTERNAL;
- for (ALL_LIST_ELEMENTS_RO(reachs[i], node, ipreach)) {
- dist = cost + ipreach->metrics.metric_default;
- prefix.u.prefix4 = ipreach->prefix;
- prefix.prefixlen = ip_masklen(ipreach->mask);
- apply_mask(&prefix);
- process_N(spftree, vtype, (void *)&prefix, dist,
- depth + 1, parent);
+ vtype = i ? VTYPE_IPREACH_EXTERNAL
+ : VTYPE_IPREACH_INTERNAL;
+
+ struct isis_oldstyle_ip_reach *r;
+ for (r = (struct isis_oldstyle_ip_reach *)reachs[i]
+ ->head;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ process_N(spftree, vtype, (void *)&r->prefix,
+ dist, depth + 1, parent);
}
}
}
if (!pseudo_lsp && spftree->family == AF_INET) {
- struct list *ipv4reachs = NULL;
-
- if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- ipv4reachs = lsp->tlv_data.te_ipv4_reachs;
- } else {
- struct tlv_mt_ipv4_reachs *mt_reachs;
- mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data,
- spftree->mtid);
- if (mt_reachs)
- ipv4reachs = mt_reachs->list;
- }
-
- prefix.family = AF_INET;
- for (ALL_LIST_ELEMENTS_RO(ipv4reachs, node, te_ipv4_reach)) {
- assert((te_ipv4_reach->control & 0x3F)
- <= IPV4_MAX_BITLEN);
-
- dist = cost + ntohl(te_ipv4_reach->te_metric);
- prefix.u.prefix4 =
- newprefix2inaddr(&te_ipv4_reach->prefix_start,
- te_ipv4_reach->control);
- prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
- apply_mask(&prefix);
- process_N(spftree, VTYPE_IPREACH_TE, (void *)&prefix,
+ struct isis_item_list *ipv4_reachs;
+ if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ ipv4_reachs = &lsp->tlvs->extended_ip_reach;
+ else
+ ipv4_reachs = isis_lookup_mt_items(
+ &lsp->tlvs->mt_ip_reach, spftree->mtid);
+
+ struct isis_extended_ip_reach *r;
+ for (r = ipv4_reachs
+ ? (struct isis_extended_ip_reach *)
+ ipv4_reachs->head
+ : NULL;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ process_N(spftree, VTYPE_IPREACH_TE, (void *)&r->prefix,
dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET6) {
- struct list *ipv6reachs = NULL;
-
- if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- ipv6reachs = lsp->tlv_data.ipv6_reachs;
- } else {
- struct tlv_mt_ipv6_reachs *mt_reachs;
- mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data,
- spftree->mtid);
- if (mt_reachs)
- ipv6reachs = mt_reachs->list;
- }
-
- prefix.family = AF_INET6;
- for (ALL_LIST_ELEMENTS_RO(ipv6reachs, node, ip6reach)) {
- assert(ip6reach->prefix_len <= IPV6_MAX_BITLEN);
-
- dist = cost + ntohl(ip6reach->metric);
- vtype = (ip6reach->control_info
- & CTRL_INFO_DISTRIBUTION)
- ? VTYPE_IP6REACH_EXTERNAL
- : VTYPE_IP6REACH_INTERNAL;
- prefix.prefixlen = ip6reach->prefix_len;
- memcpy(&prefix.u.prefix6.s6_addr, ip6reach->prefix,
- PSIZE(ip6reach->prefix_len));
- apply_mask(&prefix);
- process_N(spftree, vtype, (void *)&prefix, dist,
+ struct isis_item_list *ipv6_reachs;
+ if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ ipv6_reachs = &lsp->tlvs->ipv6_reach;
+ else
+ ipv6_reachs = isis_lookup_mt_items(
+ &lsp->tlvs->mt_ipv6_reach, spftree->mtid);
+
+ struct isis_ipv6_reach *r;
+ for (r = ipv6_reachs
+ ? (struct isis_ipv6_reach *)ipv6_reachs->head
+ : NULL;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ vtype = r->external ? VTYPE_IP6REACH_EXTERNAL
+ : VTYPE_IP6REACH_INTERNAL;
+ process_N(spftree, vtype, (void *)&r->prefix, dist,
depth + 1, parent);
}
}
@@ -893,7 +1034,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
if (!adj_has_mt(adj, spftree->mtid))
continue;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !speaks(&adj->nlpids, spftree->family))
+ && !speaks(adj->nlpids.nlpids,
+ adj->nlpids.count,
+ spftree->family))
continue;
switch (adj->sys_type) {
case ISIS_SYSTYPE_ES:
@@ -928,8 +1071,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
->lspdb[spftree->level
- 1]);
if (lsp == NULL
- || lsp->lsp_header->rem_lifetime
- == 0)
+ || lsp->hdr.rem_lifetime == 0)
zlog_warn(
"ISIS-Spf: No LSP %s found for IS adjacency "
"L%d on %s (ID %u)",
@@ -979,7 +1121,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
lsp = lsp_search(
lsp_id,
spftree->area->lspdb[spftree->level - 1]);
- if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) {
+ if (lsp == NULL || lsp->hdr.rem_lifetime == 0) {
zlog_warn(
"ISIS-Spf: No lsp (%p) found from root "
"to L%d DR %s on %s (ID %d)",
@@ -1015,7 +1157,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
LSP_PSEUDO_ID(lsp_id) = 0;
LSP_FRAGMENT(lsp_id) = 0;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST
- || speaks(&adj->nlpids, spftree->family))
+ || speaks(adj->nlpids.nlpids,
+ adj->nlpids.count,
+ spftree->family))
isis_spf_add_local(
spftree,
spftree->area->oldmetric
@@ -1052,9 +1196,9 @@ static void add_to_paths(struct isis_spftree *spftree,
{
char buff[PREFIX2STR_BUFFER];
- if (isis_find_vertex(spftree->paths, vertex->N.id, vertex->type))
+ if (isis_find_vertex(&spftree->paths, vertex->N.id, vertex->type))
return;
- listnode_add(spftree->paths, vertex);
+ isis_vertex_queue_add(&spftree->paths, vertex);
#ifdef EXTREME_DEBUG
zlog_debug("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS",
@@ -1083,11 +1227,8 @@ static void add_to_paths(struct isis_spftree *spftree,
static void init_spt(struct isis_spftree *spftree, int mtid, int level,
int family)
{
- spftree->tents->del = spftree->paths->del =
- (void (*)(void *))isis_vertex_del;
- list_delete_all_node(spftree->tents);
- list_delete_all_node(spftree->paths);
- spftree->tents->del = spftree->paths->del = NULL;
+ isis_vertex_queue_clear(&spftree->tents);
+ isis_vertex_queue_clear(&spftree->paths);
spftree->mtid = mtid;
spftree->level = level;
@@ -1099,7 +1240,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
u_char *sysid)
{
int retval = ISIS_OK;
- struct listnode *node;
struct isis_vertex *vertex;
struct isis_vertex *root_vertex;
struct isis_spftree *spftree = NULL;
@@ -1154,15 +1294,14 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
/*
* C.2.7 Step 2
*/
- if (listcount(spftree->tents) == 0) {
+ if (isis_vertex_queue_count(&spftree->tents) == 0) {
zlog_warn("ISIS-Spf: TENT is empty SPF-root:%s",
print_sys_hostname(sysid));
goto out;
}
- while (listcount(spftree->tents) > 0) {
- node = listhead(spftree->tents);
- vertex = listgetdata(node);
+ while (isis_vertex_queue_count(&spftree->tents)) {
+ vertex = isis_vertex_queue_pop(&spftree->tents);
#ifdef EXTREME_DEBUG
zlog_debug(
@@ -1171,14 +1310,12 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
vtype2string(vertex->type), vertex->depth, vertex->d_N);
#endif /* EXTREME_DEBUG */
- /* Remove from tent list and add to paths list */
- list_delete_node(spftree->tents, node);
add_to_paths(spftree, vertex);
if (VTYPE_IS(vertex->type)) {
memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
LSP_FRAGMENT(lsp_id) = 0;
lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
- if (lsp && lsp->lsp_header->rem_lifetime != 0) {
+ if (lsp && lsp->hdr.rem_lifetime != 0) {
isis_spf_process_lsp(spftree, lsp, vertex->d_N,
vertex->depth, sysid,
vertex);
@@ -1299,7 +1436,7 @@ int isis_spf_schedule(struct isis_area *area, int level)
return ISIS_OK;
}
-static void isis_print_paths(struct vty *vty, struct list *paths,
+static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue,
u_char *root_sysid)
{
struct listnode *node;
@@ -1311,7 +1448,7 @@ static void isis_print_paths(struct vty *vty, struct list *paths,
vty_out(vty,
"Vertex Type Metric Next-Hop Interface Parent\n");
- for (ALL_LIST_ELEMENTS_RO(paths, node, vertex)) {
+ for (ALL_QUEUE_ELEMENTS_RO(queue, node, vertex)) {
if (memcmp(vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) {
vty_out(vty, "%-20s %-12s %-6s",
print_sys_hostname(root_sysid), "", "");
@@ -1395,22 +1532,22 @@ DEFUN (show_isis_topology,
continue;
if (area->ip_circuits > 0 && area->spftree[level - 1]
- && area->spftree[level - 1]->paths->count > 0) {
+ && isis_vertex_queue_count(&area->spftree[level - 1]->paths) > 0) {
vty_out(vty,
"IS-IS paths to level-%d routers that speak IP\n",
level);
isis_print_paths(
- vty, area->spftree[level - 1]->paths,
+ vty, &area->spftree[level - 1]->paths,
isis->sysid);
vty_out(vty, "\n");
}
if (area->ipv6_circuits > 0 && area->spftree6[level - 1]
- && area->spftree6[level - 1]->paths->count > 0) {
+ && isis_vertex_queue_count(&area->spftree6[level - 1]->paths) > 0) {
vty_out(vty,
"IS-IS paths to level-%d routers that speak IPv6\n",
level);
isis_print_paths(
- vty, area->spftree6[level - 1]->paths,
+ vty, &area->spftree6[level - 1]->paths,
isis->sysid);
vty_out(vty, "\n");
}
@@ -1426,3 +1563,16 @@ void isis_spf_cmds_init()
{
install_element(VIEW_NODE, &show_isis_topology_cmd);
}
+
+void isis_spf_print(struct isis_spftree *spftree, struct vty *vty)
+{
+ vty_out(vty, " last run elapsed : ");
+ vty_out_timestr(vty, spftree->last_run_timestamp);
+ vty_out(vty, "\n");
+
+ vty_out(vty, " last run duration : %u usec\n",
+ (u_int32_t)spftree->last_run_duration);
+
+ vty_out(vty, " run count : %u\n",
+ spftree->runcount);
+}
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
index c7a505489f..84e07861d2 100644
--- a/isisd/isis_spf.h
+++ b/isisd/isis_spf.h
@@ -24,53 +24,7 @@
#ifndef _ZEBRA_ISIS_SPF_H
#define _ZEBRA_ISIS_SPF_H
-enum vertextype {
- VTYPE_PSEUDO_IS = 1,
- VTYPE_PSEUDO_TE_IS,
- VTYPE_NONPSEUDO_IS,
- VTYPE_NONPSEUDO_TE_IS,
- VTYPE_ES,
- VTYPE_IPREACH_INTERNAL,
- VTYPE_IPREACH_EXTERNAL,
- VTYPE_IPREACH_TE,
- VTYPE_IP6REACH_INTERNAL,
- VTYPE_IP6REACH_EXTERNAL
-};
-
-#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
-#define VTYPE_ES(t) ((t) == VTYPE_ES)
-#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
-
-/*
- * Triple <N, d(N), {Adj(N)}>
- */
-struct isis_vertex {
- enum vertextype type;
-
- union {
- u_char id[ISIS_SYS_ID_LEN + 1];
- struct prefix prefix;
- } N;
-
- u_int32_t d_N; /* d(N) Distance from this IS */
- u_int16_t depth; /* The depth in the imaginary tree */
- struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
- struct list *parents; /* list of parents for ECMP */
- struct list *children; /* list of children used for tree dump */
-};
-
-struct isis_spftree {
- struct list *paths; /* the SPT */
- struct list *tents; /* TENT */
- struct isis_area *area; /* back pointer to area */
- unsigned int runcount; /* number of runs since uptime */
- time_t last_run_timestamp; /* last run timestamp for scheduling */
- time_t last_run_duration; /* last run duration in msec */
-
- uint16_t mtid;
- int family;
- int level;
-};
+struct isis_spftree;
struct isis_spftree *isis_spftree_new(struct isis_area *area);
void isis_spftree_del(struct isis_spftree *spftree);
@@ -79,4 +33,5 @@ void spftree_area_del(struct isis_area *area);
void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj);
int isis_spf_schedule(struct isis_area *area, int level);
void isis_spf_cmds_init(void);
+void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
#endif /* _ZEBRA_ISIS_SPF_H */
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 5296d99480..70afef1a86 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -41,6 +41,7 @@
#include "md5.h"
#include "sockunion.h"
#include "network.h"
+#include "sbuf.h"
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
@@ -48,7 +49,6 @@
#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"
@@ -100,9 +100,9 @@ struct mpls_te_circuit *mpls_te_circuit_new()
/* 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)
+uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc)
{
- u_char size, *tlvs = buf;
+ uint8_t size, *tlvs = buf;
zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
@@ -232,7 +232,7 @@ u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc)
}
/* Compute total Sub-TLVs size */
-u_char subtlvs_len(struct mpls_te_circuit *mtc)
+uint8_t subtlvs_len(struct mpls_te_circuit *mtc)
{
int length = 0;
@@ -306,7 +306,7 @@ u_char subtlvs_len(struct mpls_te_circuit *mtc)
return 0;
}
- mtc->length = (u_char)length;
+ mtc->length = (uint8_t)length;
return mtc->length;
}
@@ -546,13 +546,9 @@ void isis_link_params_update(struct isis_circuit *circuit,
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 (adj->ipv4_address_count) {
+ set_circuitparams_rmt_ipaddr(
+ mtc, adj->ipv4_addresses[0]);
}
}
@@ -670,163 +666,116 @@ void isis_mpls_te_update(struct interface *ifp)
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
-static u_char show_vty_subtlv_admin_grp(struct vty *vty,
- struct te_subtlv_admin_grp *tlv)
+static u_char print_subtlv_admin_grp(struct sbuf *buf, int indent,
+ struct te_subtlv_admin_grp *tlv)
{
-
- if (vty != NULL)
- vty_out(vty, " Administrative Group: 0x%x\n",
- (u_int32_t)ntohl(tlv->value));
- else
- zlog_debug(" Administrative Group: 0x%x",
- (u_int32_t)ntohl(tlv->value));
-
+ sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
+ 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)
+static u_char print_subtlv_llri(struct sbuf *buf, int indent,
+ struct te_subtlv_llri *tlv)
{
- if (vty != NULL) {
- vty_out(vty, " Link Local ID: %d\n",
- (u_int32_t)ntohl(tlv->local));
- vty_out(vty, " Link Remote ID: %d\n",
- (u_int32_t)ntohl(tlv->remote));
- } 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));
- }
+ sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
+ ntohl(tlv->local));
+ sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
+ 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)
+static u_char print_subtlv_local_ipaddr(struct sbuf *buf, int indent,
+ struct te_subtlv_local_ipaddr *tlv)
{
- if (vty != NULL)
- vty_out(vty, " Local Interface IP Address(es): %s\n",
- inet_ntoa(tlv->value));
- else
- zlog_debug(" Local Interface IP Address(es): %s",
- inet_ntoa(tlv->value));
+ sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
+ 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)
+static u_char print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent,
+ struct te_subtlv_rmt_ipaddr *tlv)
{
- if (vty != NULL)
- vty_out(vty, " Remote Interface IP Address(es): %s\n",
- inet_ntoa(tlv->value));
- else
- zlog_debug(" Remote Interface IP Address(es): %s",
- inet_ntoa(tlv->value));
+ sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
+ 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)
+static u_char print_subtlv_max_bw(struct sbuf *buf, int indent,
+ struct te_subtlv_max_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
- if (vty != NULL)
- vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval);
- else
- zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval);
+ sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", 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)
+static u_char print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
+ 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)\n",
- fval);
- else
- zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)",
- fval);
+ sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", 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)
+static u_char print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
+ struct te_subtlv_unrsv_bw *tlv)
{
float fval1, fval2;
int i;
- if (vty != NULL)
- vty_out(vty, " Unreserved Bandwidth:\n");
- else
- zlog_debug(" Unreserved Bandwidth:");
+ sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
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)\n",
- i, fval1, i + 1, fval2);
- else
- zlog_debug(
- " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)",
- i, fval1, i + 1, fval2);
+ sbuf_push(buf, indent + 2, "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
+ 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)
+static u_char print_subtlv_te_metric(struct sbuf *buf, int indent,
+ 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\n", te_metric);
- else
- zlog_debug(" Traffic Engineering Metric: %u", te_metric);
+ sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
-static u_char show_vty_subtlv_ras(struct vty *vty, struct te_subtlv_ras *tlv)
+static u_char print_subtlv_ras(struct sbuf *buf, int indent,
+ struct te_subtlv_ras *tlv)
{
- if (vty != NULL)
- vty_out(vty, " Inter-AS TE Remote AS number: %u\n",
- ntohl(tlv->value));
- else
- zlog_debug(" Inter-AS TE Remote AS number: %u",
- ntohl(tlv->value));
+ sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n",
+ 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)
+static u_char print_subtlv_rip(struct sbuf *buf, int indent,
+ struct te_subtlv_rip *tlv)
{
- if (vty != NULL)
- vty_out(vty, " Inter-AS TE Remote ASBR IP address: %s\n",
- inet_ntoa(tlv->value));
- else
- zlog_debug(" Inter-AS TE Remote ASBR IP address: %s",
- inet_ntoa(tlv->value));
+ sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n",
+ 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)
+static u_char print_subtlv_av_delay(struct sbuf *buf, int indent,
+ struct te_subtlv_av_delay *tlv)
{
u_int32_t delay;
u_int32_t A;
@@ -834,18 +783,14 @@ static u_char show_vty_subtlv_av_delay(struct vty *vty,
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)\n",
- A ? "Anomalous" : "Normal", delay);
- else
- zlog_debug(" %s Average Link Delay: %d (micro-sec)",
- A ? "Anomalous" : "Normal", delay);
+ sbuf_push(buf, indent, "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
+ 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)
+static u_char print_subtlv_mm_delay(struct sbuf *buf, int indent,
+ struct te_subtlv_mm_delay *tlv)
{
u_int32_t low, high;
u_int32_t A;
@@ -854,33 +799,26 @@ static u_char show_vty_subtlv_mm_delay(struct vty *vty,
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)\n",
- A ? "Anomalous" : "Normal", low, high);
- else
- zlog_debug(" %s Min/Max Link Delay: %d / %d (micro-sec)",
- A ? "Anomalous" : "Normal", low, high);
+ sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
+ 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)
+static u_char print_subtlv_delay_var(struct sbuf *buf, int indent,
+ 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)\n", jitter);
- else
- zlog_debug(" Delay Variation: %d (micro-sec)", jitter);
+ sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n", 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)
+static u_char print_subtlv_pkt_loss(struct sbuf *buf, int indent,
+ struct te_subtlv_pkt_loss *tlv)
{
u_int32_t loss;
u_int32_t A;
@@ -890,189 +828,162 @@ static u_char show_vty_subtlv_pkt_loss(struct vty *vty,
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 (%%)\n",
- A ? "Anomalous" : "Normal", fval);
- else
- zlog_debug(" %s Link Packet Loss: %g (%%)",
- A ? "Anomalous" : "Normal", fval);
+ sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
+ 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)
+static u_char print_subtlv_res_bw(struct sbuf *buf, int indent,
+ struct te_subtlv_res_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
- if (vty != NULL)
- vty_out(vty,
- " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
- fval);
- else
- zlog_debug(
- " Unidirectional Residual Bandwidth: %g (Bytes/sec)",
- fval);
+ sbuf_push(buf, indent, "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
+ 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)
+static u_char print_subtlv_ava_bw(struct sbuf *buf, int indent,
+ struct te_subtlv_ava_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
- if (vty != NULL)
- vty_out(vty,
- " Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
- fval);
- else
- zlog_debug(
- " Unidirectional Available Bandwidth: %g (Bytes/sec)",
- fval);
+ sbuf_push(buf, indent, "Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
+ 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)
+static u_char print_subtlv_use_bw(struct sbuf *buf, int indent,
+ struct te_subtlv_use_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
- if (vty != NULL)
- vty_out(vty,
- " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
- fval);
- else
- zlog_debug(
- " Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
- fval);
+ sbuf_push(buf, indent, "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
+ fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
-static u_char show_vty_unknown_tlv(struct vty *vty, struct subtlv_header *tlvh)
+static u_char print_unknown_tlv(struct sbuf *buf, int indent,
+ 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)]\n",
- tlvh->type, tlvh->length);
- 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, "\n [%.2x]",
- i + 1);
- rtn = 1;
- } else
- rtn++;
- }
- vty_out(vty, "\n");
- } else
- vty_out(vty,
- " Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
- tlvh->type, tlvh->length);
+ if (tlvh->length != 0) {
+ sbuf_push(buf, indent,
+ "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
+ tlvh->type, tlvh->length);
+ sbuf_push(buf, indent + 2, "Dump: [00]");
+ rtn = 1; /* initialize end of line counter */
+ for (i = 0; i < tlvh->length; i++) {
+ sbuf_push(buf, 0, " %#.2x", v[i]);
+ if (rtn == 8) {
+ sbuf_push(buf, 0, "\n");
+ sbuf_push(buf, indent + 8,
+ "[%.2x]", i + 1);
+ rtn = 1;
+ } else
+ rtn++;
+ }
+ sbuf_push(buf, 0, "\n");
} else {
- zlog_debug(" Unknown TLV: [type(%#.2x), length(%#.2x)]",
- tlvh->type, tlvh->length);
+ sbuf_push(buf, indent,
+ "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
+ tlvh->type, tlvh->length);
}
return SUBTLV_SIZE(tlvh);
}
/* Main Show function */
-void mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te)
+void mpls_te_print_detail(struct sbuf *buf, int indent,
+ uint8_t *subtlvs, uint8_t subtlv_len)
{
- struct subtlv_header *tlvh;
- u_int16_t sum = 0;
-
- zlog_debug("ISIS MPLS-TE: Show database TE detail");
+ struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
+ uint16_t sum = 0;
- tlvh = (struct subtlv_header *)te->sub_tlvs;
-
- for (; sum < te->sub_tlvs_length; tlvh = SUBTLV_HDR_NEXT(tlvh)) {
+ for (; sum < subtlv_len; tlvh = SUBTLV_HDR_NEXT(tlvh)) {
switch (tlvh->type) {
case TE_SUBTLV_ADMIN_GRP:
- sum += show_vty_subtlv_admin_grp(
- vty, (struct te_subtlv_admin_grp *)tlvh);
+ sum += print_subtlv_admin_grp(buf, indent,
+ (struct te_subtlv_admin_grp *)tlvh);
break;
case TE_SUBTLV_LLRI:
- sum += show_vty_subtlv_llri(
- vty, (struct te_subtlv_llri *)tlvh);
+ sum += print_subtlv_llri(buf, indent,
+ (struct te_subtlv_llri *)tlvh);
break;
case TE_SUBTLV_LOCAL_IPADDR:
- sum += show_vty_subtlv_local_ipaddr(
- vty, (struct te_subtlv_local_ipaddr *)tlvh);
+ sum += print_subtlv_local_ipaddr(buf, indent,
+ (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);
+ sum += print_subtlv_rmt_ipaddr(buf, indent,
+ (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);
+ sum += print_subtlv_max_bw(buf, indent,
+ (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);
+ sum += print_subtlv_max_rsv_bw(buf, indent,
+ (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);
+ sum += print_subtlv_unrsv_bw(buf, indent,
+ (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);
+ sum += print_subtlv_te_metric(buf, indent,
+ (struct te_subtlv_te_metric *)tlvh);
break;
case TE_SUBTLV_RAS:
- sum += show_vty_subtlv_ras(
- vty, (struct te_subtlv_ras *)tlvh);
+ sum += print_subtlv_ras(buf, indent,
+ (struct te_subtlv_ras *)tlvh);
break;
case TE_SUBTLV_RIP:
- sum += show_vty_subtlv_rip(
- vty, (struct te_subtlv_rip *)tlvh);
+ sum += print_subtlv_rip(buf, indent,
+ (struct te_subtlv_rip *)tlvh);
break;
case TE_SUBTLV_AV_DELAY:
- sum += show_vty_subtlv_av_delay(
- vty, (struct te_subtlv_av_delay *)tlvh);
+ sum += print_subtlv_av_delay(buf, indent,
+ (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);
+ sum += print_subtlv_mm_delay(buf, indent,
+ (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);
+ sum += print_subtlv_delay_var(buf, indent,
+ (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);
+ sum += print_subtlv_pkt_loss(buf, indent,
+ (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);
+ sum += print_subtlv_res_bw(buf, indent,
+ (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);
+ sum += print_subtlv_ava_bw(buf, indent,
+ (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);
+ sum += print_subtlv_use_bw(buf, indent,
+ (struct te_subtlv_use_bw *)tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += print_unknown_tlv(buf, indent, tlvh);
break;
}
}
@@ -1256,6 +1167,9 @@ DEFUN (show_isis_mpls_te_router,
static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
{
struct mpls_te_circuit *mtc;
+ struct sbuf buf;
+
+ sbuf_init(&buf, NULL, 0);
if ((IS_MPLS_TE(isisMplsTE))
&& ((mtc = lookup_mpls_params_by_ifp(ifp)) != NULL)) {
@@ -1280,38 +1194,42 @@ static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
ifp->name);
}
- show_vty_subtlv_admin_grp(vty, &mtc->admin_grp);
+ sbuf_reset(&buf);
+ print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp);
if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
- show_vty_subtlv_local_ipaddr(vty, &mtc->local_ipaddr);
+ print_subtlv_local_ipaddr(&buf, 4, &mtc->local_ipaddr);
if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
- show_vty_subtlv_rmt_ipaddr(vty, &mtc->rmt_ipaddr);
+ print_subtlv_rmt_ipaddr(&buf, 4, &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);
+ print_subtlv_max_bw(&buf, 4, &mtc->max_bw);
+ print_subtlv_max_rsv_bw(&buf, 4, &mtc->max_rsv_bw);
+ print_subtlv_unrsv_bw(&buf, 4, &mtc->unrsv_bw);
+ print_subtlv_te_metric(&buf, 4, &mtc->te_metric);
if (IS_INTER_AS(mtc->type)) {
if (SUBTLV_TYPE(mtc->ras) != 0)
- show_vty_subtlv_ras(vty, &mtc->ras);
+ print_subtlv_ras(&buf, 4, &mtc->ras);
if (SUBTLV_TYPE(mtc->rip) != 0)
- show_vty_subtlv_rip(vty, &mtc->rip);
+ print_subtlv_rip(&buf, 4, &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);
+ print_subtlv_av_delay(&buf, 4, &mtc->av_delay);
+ print_subtlv_mm_delay(&buf, 4, &mtc->mm_delay);
+ print_subtlv_delay_var(&buf, 4, &mtc->delay_var);
+ print_subtlv_pkt_loss(&buf, 4, &mtc->pkt_loss);
+ print_subtlv_res_bw(&buf, 4, &mtc->res_bw);
+ print_subtlv_ava_bw(&buf, 4, &mtc->ava_bw);
+ print_subtlv_use_bw(&buf, 4, &mtc->use_bw);
+
+ vty_multiline(vty, "", "%s", sbuf_buf(&buf));
vty_out(vty, "---------------\n\n");
} else {
vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
ifp->name);
}
+ sbuf_free(&buf);
return;
}
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index 0bd076af19..9b29792e2b 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -81,6 +81,8 @@ struct subtlv_header {
u_char length; /* Value portion only, in byte */
};
+#define MAX_SUBTLV_SIZE 256
+
#define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */
#define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length)
@@ -306,12 +308,13 @@ struct mpls_te_circuit {
/* 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 *);
+struct sbuf;
+void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs, uint8_t subtlv_len);
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 *);
+uint8_t subtlvs_len(struct mpls_te_circuit *);
+uint8_t add_te_subtlvs(uint8_t *, struct mpls_te_circuit *);
+uint8_t build_te_subtlvs(uint8_t *, 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 *);
diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c
deleted file mode 100644
index a295f4dd3f..0000000000
--- a/isisd/isis_tlv.c
+++ /dev/null
@@ -1,1453 +0,0 @@
-/*
- * IS-IS Rout(e)ing protocol - isis_tlv.c
- * IS-IS TLV related routines
- *
- * Copyright (C) 2001,2002 Sampo Saaristo
- * Tampere University of Technology
- * Institute of Communications Engineering
- *
- * 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; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-
-#include "log.h"
-#include "linklist.h"
-#include "stream.h"
-#include "memory.h"
-#include "prefix.h"
-#include "vty.h"
-#include "if.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/isis_tlv.h"
-#include "isisd/isisd.h"
-#include "isisd/isis_dynhn.h"
-#include "isisd/isis_misc.h"
-#include "isisd/isis_pdu.h"
-#include "isisd/isis_lsp.h"
-#include "isisd/isis_te.h"
-#include "isisd/isis_mt.h"
-
-void free_tlv(void *val)
-{
- XFREE(MTYPE_ISIS_TLV, val);
-
- return;
-}
-
-/*
- * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
- * is only a caution to avoid memory leaks
- */
-void free_tlvs(struct tlvs *tlvs)
-{
- if (tlvs->area_addrs)
- list_delete(tlvs->area_addrs);
- if (tlvs->mt_router_info)
- list_delete(tlvs->mt_router_info);
- if (tlvs->is_neighs)
- list_delete(tlvs->is_neighs);
- if (tlvs->te_is_neighs)
- list_delete(tlvs->te_is_neighs);
- if (tlvs->mt_is_neighs)
- list_delete(tlvs->mt_is_neighs);
- if (tlvs->es_neighs)
- list_delete(tlvs->es_neighs);
- if (tlvs->lsp_entries)
- list_delete(tlvs->lsp_entries);
- if (tlvs->prefix_neighs)
- list_delete(tlvs->prefix_neighs);
- if (tlvs->lan_neighs)
- list_delete(tlvs->lan_neighs);
- if (tlvs->ipv4_addrs)
- list_delete(tlvs->ipv4_addrs);
- if (tlvs->ipv4_int_reachs)
- list_delete(tlvs->ipv4_int_reachs);
- if (tlvs->ipv4_ext_reachs)
- list_delete(tlvs->ipv4_ext_reachs);
- if (tlvs->te_ipv4_reachs)
- list_delete(tlvs->te_ipv4_reachs);
- if (tlvs->mt_ipv4_reachs)
- list_delete(tlvs->mt_ipv4_reachs);
- if (tlvs->ipv6_addrs)
- list_delete(tlvs->ipv6_addrs);
- if (tlvs->ipv6_reachs)
- list_delete(tlvs->ipv6_reachs);
- if (tlvs->mt_ipv6_reachs)
- list_delete(tlvs->mt_ipv6_reachs);
-
- memset(tlvs, 0, sizeof(struct tlvs));
-
- return;
-}
-
-static int parse_mtid(uint16_t *mtid, bool read_mtid, unsigned int *length,
- u_char **pnt)
-{
- if (!read_mtid) {
- *mtid = ISIS_MT_IPV4_UNICAST;
- return ISIS_OK;
- }
-
- uint16_t mtid_buf;
-
- if (*length < sizeof(mtid_buf)) {
- zlog_warn("ISIS-TLV: mt tlv too short to contain MT id");
- return ISIS_WARNING;
- }
-
- memcpy(&mtid_buf, *pnt, sizeof(mtid_buf));
- *pnt += sizeof(mtid_buf);
- *length -= sizeof(mtid_buf);
-
- *mtid = ntohs(mtid_buf) & ISIS_MT_MASK;
- return ISIS_OK;
-}
-
-static int parse_mt_is_neighs(struct tlvs *tlvs, bool read_mtid,
- unsigned int length, u_char *pnt)
-{
- struct list *neigh_list;
- uint16_t mtid;
- int rv;
-
- rv = parse_mtid(&mtid, read_mtid, &length, &pnt);
- if (rv != ISIS_OK)
- return rv;
-
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- if (!tlvs->te_is_neighs) {
- tlvs->te_is_neighs = list_new();
- tlvs->te_is_neighs->del = free_tlv;
- }
- neigh_list = tlvs->te_is_neighs;
- } else {
- struct tlv_mt_neighbors *neighbors;
-
- neighbors = tlvs_get_mt_neighbors(tlvs, mtid);
- neighbors->list->del = free_tlv;
- neigh_list = neighbors->list;
- }
-
- while (length >= IS_NEIGHBOURS_LEN) {
- struct te_is_neigh *neigh =
- XCALLOC(MTYPE_ISIS_TLV, sizeof(*neigh));
-
- memcpy(neigh, pnt, IS_NEIGHBOURS_LEN);
- pnt += IS_NEIGHBOURS_LEN;
- length -= IS_NEIGHBOURS_LEN;
-
- if (neigh->sub_tlvs_length > length) {
- zlog_warn(
- "ISIS-TLV: neighbor subtlv length exceeds TLV size");
- XFREE(MTYPE_ISIS_TLV, neigh);
- return ISIS_WARNING;
- }
-
- memcpy(neigh->sub_tlvs, pnt, neigh->sub_tlvs_length);
- pnt += neigh->sub_tlvs_length;
- length -= neigh->sub_tlvs_length;
-
- listnode_add(neigh_list, neigh);
- }
-
- if (length) {
- zlog_warn("ISIS-TLV: TE/MT neighor TLV has trailing data");
- return ISIS_WARNING;
- }
-
- return ISIS_OK;
-}
-
-static int parse_mt_ipv4_reachs(struct tlvs *tlvs, bool read_mtid,
- unsigned int length, u_char *pnt)
-{
- struct list *reach_list;
- uint16_t mtid;
- int rv;
-
- rv = parse_mtid(&mtid, read_mtid, &length, &pnt);
- if (rv != ISIS_OK)
- return rv;
-
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- if (!tlvs->te_ipv4_reachs) {
- tlvs->te_ipv4_reachs = list_new();
- tlvs->te_ipv4_reachs->del = free_tlv;
- }
- reach_list = tlvs->te_ipv4_reachs;
- } else {
- struct tlv_mt_ipv4_reachs *reachs;
-
- reachs = tlvs_get_mt_ipv4_reachs(tlvs, mtid);
- reachs->list->del = free_tlv;
- reach_list = reachs->list;
- }
-
- while (length >= 5) /* Metric + Control */
- {
- struct te_ipv4_reachability *reach =
- XCALLOC(MTYPE_ISIS_TLV, TE_IPV4_REACH_LEN);
-
- memcpy(reach, pnt, 5); /* Metric + Control */
- pnt += 5;
- length -= 5;
-
- unsigned char prefixlen = reach->control & 0x3F;
-
- if (prefixlen > IPV4_MAX_BITLEN) {
- zlog_warn(
- "ISIS-TLV: invalid IPv4 extended reachability prefix length %d",
- prefixlen);
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- if (length < (unsigned int)PSIZE(prefixlen)) {
- zlog_warn(
- "ISIS-TLV: invalid IPv4 extended reachability prefix too long for tlv");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- memcpy(&reach->prefix_start, pnt, PSIZE(prefixlen));
- pnt += PSIZE(prefixlen);
- length -= PSIZE(prefixlen);
-
- if (reach->control & TE_IPV4_HAS_SUBTLV) {
- if (length < 1) {
- zlog_warn(
- "ISIS-TLV: invalid IPv4 extended reachability SubTLV missing");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- u_char subtlv_len = *pnt;
- pnt++;
- length--;
-
- if (length < subtlv_len) {
- zlog_warn(
- "ISIS-TLV: invalid IPv4 extended reachability SubTLVs have oversize");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- /* Skip Sub-TLVs for now */
- pnt += subtlv_len;
- length -= subtlv_len;
- }
- listnode_add(reach_list, reach);
- }
-
- if (length) {
- zlog_warn(
- "ISIS-TLV: TE/MT ipv4 reachability TLV has trailing data");
- return ISIS_WARNING;
- }
-
- return ISIS_OK;
-}
-
-static int parse_mt_ipv6_reachs(struct tlvs *tlvs, bool read_mtid,
- unsigned int length, u_char *pnt)
-{
- struct list *reach_list;
- uint16_t mtid;
- int rv;
-
- rv = parse_mtid(&mtid, read_mtid, &length, &pnt);
- if (rv != ISIS_OK)
- return rv;
-
- if (mtid == ISIS_MT_IPV4_UNICAST) {
- if (!tlvs->ipv6_reachs) {
- tlvs->ipv6_reachs = list_new();
- tlvs->ipv6_reachs->del = free_tlv;
- }
- reach_list = tlvs->ipv6_reachs;
- } else {
- struct tlv_mt_ipv6_reachs *reachs;
-
- reachs = tlvs_get_mt_ipv6_reachs(tlvs, mtid);
- reachs->list->del = free_tlv;
- reach_list = reachs->list;
- }
-
- while (length >= 6) /* Metric + Control + Prefixlen */
- {
- struct ipv6_reachability *reach =
- XCALLOC(MTYPE_ISIS_TLV, sizeof(*reach));
-
- memcpy(reach, pnt, 6); /* Metric + Control + Prefixlen */
- pnt += 6;
- length -= 6;
-
- if (reach->prefix_len > IPV6_MAX_BITLEN) {
- zlog_warn(
- "ISIS-TLV: invalid IPv6 reachability prefix length %d",
- reach->prefix_len);
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- if (length < (unsigned int)PSIZE(reach->prefix_len)) {
- zlog_warn(
- "ISIS-TLV: invalid IPv6 reachability prefix too long for tlv");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- memcpy(&reach->prefix, pnt, PSIZE(reach->prefix_len));
- pnt += PSIZE(reach->prefix_len);
- length -= PSIZE(reach->prefix_len);
-
- if (reach->control_info & CTRL_INFO_SUBTLVS) {
- if (length < 1) {
- zlog_warn(
- "ISIS-TLV: invalid IPv6 reachability SubTLV missing");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- u_char subtlv_len = *pnt;
- pnt++;
- length--;
-
- if (length < subtlv_len) {
- zlog_warn(
- "ISIS-TLV: invalid IPv6 reachability SubTLVs have oversize");
- XFREE(MTYPE_ISIS_TLV, reach);
- return ISIS_WARNING;
- }
-
- /* Skip Sub-TLVs for now */
- pnt += subtlv_len;
- length -= subtlv_len;
- }
- listnode_add(reach_list, reach);
- }
-
- if (length) {
- zlog_warn(
- "ISIS-TLV: (MT) IPv6 reachability TLV has trailing data");
- return ISIS_WARNING;
- }
-
- return ISIS_OK;
-}
-
-/*
- * Parses the tlvs found in the variant length part of the PDU.
- * Caller tells with flags in "expected" which TLV's it is interested in.
- */
-int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected,
- u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset)
-{
- u_char type, length;
- struct lan_neigh *lan_nei;
- struct area_addr *area_addr;
- struct is_neigh *is_nei;
- struct es_neigh *es_nei;
- struct lsp_entry *lsp_entry;
- struct in_addr *ipv4_addr;
- struct ipv4_reachability *ipv4_reach;
- struct in6_addr *ipv6_addr;
- int value_len, retval = ISIS_OK;
- u_char *start = stream, *pnt = stream;
-
- *found = 0;
- memset(tlvs, 0, sizeof(struct tlvs));
-
- while (pnt < stream + size - 2) {
- type = *pnt;
- length = *(pnt + 1);
- pnt += 2;
- value_len = 0;
- if (pnt + length > stream + size) {
- zlog_warn(
- "ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
- "boundaries",
- areatag, type, length);
- retval = ISIS_WARNING;
- break;
- }
- switch (type) {
- case AREA_ADDRESSES:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Address Length |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Area Address |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_AREA_ADDRS;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("TLV Area Adresses len %d", length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_AREA_ADDRS) {
- while (length > value_len) {
- area_addr = (struct area_addr *)pnt;
- value_len += area_addr->addr_len + 1;
- pnt += area_addr->addr_len + 1;
- if (!tlvs->area_addrs)
- tlvs->area_addrs = list_new();
- listnode_add(tlvs->area_addrs,
- area_addr);
- }
- } else {
- pnt += length;
- }
- break;
-
- case IS_NEIGHBOURS:
- *found |= TLVFLAG_IS_NEIGHS;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): IS Neighbours length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (TLVFLAG_IS_NEIGHS & *expected) {
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Virtual Flag |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
- pnt++;
- value_len++;
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 0 | I/E | Default
- * Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Delay Metric
- * |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Expense
- * Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Error Metric
- * |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Neighbour ID |
- * +---------------------------------------------------------------+
- * : :
- */
- while (length > value_len) {
- is_nei = (struct is_neigh *)pnt;
- value_len += 4 + ISIS_SYS_ID_LEN + 1;
- pnt += 4 + ISIS_SYS_ID_LEN + 1;
- if (!tlvs->is_neighs)
- tlvs->is_neighs = list_new();
- listnode_add(tlvs->is_neighs, is_nei);
- }
- } else {
- pnt += length;
- }
- break;
-
- case TE_IS_NEIGHBOURS:
- *found |= TLVFLAG_TE_IS_NEIGHS;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): Extended IS Neighbours length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (TLVFLAG_TE_IS_NEIGHS & *expected)
- retval = parse_mt_is_neighs(tlvs, false, length,
- pnt);
- pnt += length;
- break;
-
- case MT_IS_NEIGHBOURS:
- *found |= TLVFLAG_TE_IS_NEIGHS;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): MT IS Neighbours length %d",
- areatag, length);
-#endif
- if (TLVFLAG_TE_IS_NEIGHS & *expected)
- retval = parse_mt_is_neighs(tlvs, true, length,
- pnt);
- pnt += length;
- break;
-
- case ES_NEIGHBOURS:
-/* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 0 | I/E | Default Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Delay Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Expense Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Error Metric |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Neighbour ID |
- * +---------------------------------------------------------------+
- * | Neighbour ID |
- * +---------------------------------------------------------------+
- * : :
- */
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): ES Neighbours length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- *found |= TLVFLAG_ES_NEIGHS;
- if (*expected & TLVFLAG_ES_NEIGHS) {
- es_nei = (struct es_neigh *)pnt;
- value_len += 4;
- pnt += 4;
- while (length > value_len) {
- /* FIXME FIXME FIXME - add to the list
- */
- /* sys_id->id = pnt; */
- value_len += ISIS_SYS_ID_LEN;
- pnt += ISIS_SYS_ID_LEN;
- /* if (!es_nei->neigh_ids)
- * es_nei->neigh_ids = sysid; */
- }
- if (!tlvs->es_neighs)
- tlvs->es_neighs = list_new();
- listnode_add(tlvs->es_neighs, es_nei);
- } else {
- pnt += length;
- }
- break;
-
- case LAN_NEIGHBOURS:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | LAN Address |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_LAN_NEIGHS;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): LAN Neigbours length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (TLVFLAG_LAN_NEIGHS & *expected) {
- while (length > value_len) {
- lan_nei = (struct lan_neigh *)pnt;
- if (!tlvs->lan_neighs)
- tlvs->lan_neighs = list_new();
- listnode_add(tlvs->lan_neighs, lan_nei);
- value_len += ETH_ALEN;
- pnt += ETH_ALEN;
- }
- } else {
- pnt += length;
- }
- break;
-
- case PADDING:
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("TLV padding %d", length);
-#endif /* EXTREME_TLV_DEBUG */
- pnt += length;
- break;
-
- case LSP_ENTRIES:
-/* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Remaining Lifetime | 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | LSP ID | id+2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | LSP Sequence Number | 4
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Checksum | 2
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): LSP Entries length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- *found |= TLVFLAG_LSP_ENTRIES;
- if (TLVFLAG_LSP_ENTRIES & *expected) {
- while (length > value_len) {
- lsp_entry = (struct lsp_entry *)pnt;
- value_len += 10 + ISIS_SYS_ID_LEN;
- pnt += 10 + ISIS_SYS_ID_LEN;
- if (!tlvs->lsp_entries)
- tlvs->lsp_entries = list_new();
- listnode_add(tlvs->lsp_entries,
- lsp_entry);
- }
- } else {
- pnt += length;
- }
- break;
-
- case CHECKSUM:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 16 bit fletcher CHECKSUM |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_CHECKSUM;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): Checksum length %d", areatag,
- length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_CHECKSUM) {
- tlvs->checksum = (struct checksum *)pnt;
- }
- pnt += length;
- break;
-
- case PROTOCOLS_SUPPORTED:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | NLPID |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_NLPID;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): Protocols Supported length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_NLPID) {
- tlvs->nlpids = (struct nlpids *)(pnt - 1);
- }
- pnt += length;
- break;
-
- case IPV4_ADDR:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * + IP version 4 address + 4
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_IPV4_ADDR;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): IPv4 Address length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV4_ADDR) {
- while (length > value_len) {
- ipv4_addr = (struct in_addr *)pnt;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s) : IP ADDR %s, pnt %p",
- areatag, inet_ntoa(*ipv4_addr),
- pnt);
-#endif /* EXTREME_TLV_DEBUG */
- if (!tlvs->ipv4_addrs)
- tlvs->ipv4_addrs = list_new();
- listnode_add(tlvs->ipv4_addrs,
- ipv4_addr);
- value_len += 4;
- pnt += 4;
- }
- } else {
- pnt += length;
- }
- break;
-
- case AUTH_INFO:
- *found |= TLVFLAG_AUTH_INFO;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): IS-IS Authentication Information",
- areatag);
-#endif
- if (*expected & TLVFLAG_AUTH_INFO) {
- tlvs->auth_info.type = *pnt;
- if (length == 0) {
- zlog_warn(
- "ISIS-TLV (%s): TLV (type %d, length %d) "
- "incorrect.",
- areatag, type, length);
- return ISIS_WARNING;
- }
- --length;
- tlvs->auth_info.len = length;
- pnt++;
- memcpy(tlvs->auth_info.passwd, pnt, length);
- /* Return the authentication tlv pos for later
- * computation
- * of MD5 (RFC 5304, 2)
- */
- if (auth_tlv_offset)
- *auth_tlv_offset += (pnt - start - 3);
- pnt += length;
- } else {
- pnt += length;
- }
- break;
-
- case DYNAMIC_HOSTNAME:
- *found |= TLVFLAG_DYN_HOSTNAME;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): Dynamic Hostname length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_DYN_HOSTNAME) {
- /* the length is also included in the pointed
- * struct */
- tlvs->hostname = (struct hostname *)(pnt - 1);
- }
- pnt += length;
- break;
-
- case TE_ROUTER_ID:
- /* +---------------------------------------------------------------+
- * + Router ID + 4
- * +---------------------------------------------------------------+
- */
- *found |= TLVFLAG_TE_ROUTER_ID;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): TE Router ID %d", areatag,
- length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_TE_ROUTER_ID)
- tlvs->router_id = (struct te_router_id *)(pnt);
- pnt += length;
- break;
-
- case IPV4_INT_REACHABILITY:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 0 | I/E | Default Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Delay Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Expense Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Error Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | ip address | 4
- * +---------------------------------------------------------------+
- * | address mask | 4
- * +---------------------------------------------------------------+
- * : :
- */
- *found |= TLVFLAG_IPV4_INT_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): IPv4 internal Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) {
- while (length > value_len) {
- ipv4_reach =
- (struct ipv4_reachability *)pnt;
- if (!tlvs->ipv4_int_reachs)
- tlvs->ipv4_int_reachs =
- list_new();
- listnode_add(tlvs->ipv4_int_reachs,
- ipv4_reach);
- value_len += 12;
- pnt += 12;
- }
- } else {
- pnt += length;
- }
- break;
-
- case IPV4_EXT_REACHABILITY:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 0 | I/E | Default Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Delay Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Expense Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | S | I/E | Error Metric | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | ip address | 4
- * +---------------------------------------------------------------+
- * | address mask | 4
- * +---------------------------------------------------------------+
- * : :
- */
- *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): IPv4 external Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY) {
- while (length > value_len) {
- ipv4_reach =
- (struct ipv4_reachability *)pnt;
- if (!tlvs->ipv4_ext_reachs)
- tlvs->ipv4_ext_reachs =
- list_new();
- listnode_add(tlvs->ipv4_ext_reachs,
- ipv4_reach);
- value_len += 12;
- pnt += 12;
- }
- } else {
- pnt += length;
- }
- break;
-
- case TE_IPV4_REACHABILITY:
- *found |= TLVFLAG_TE_IPV4_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): IPv4 extended Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
- retval = parse_mt_ipv4_reachs(tlvs, false,
- length, pnt);
- pnt += length;
- break;
- case MT_IPV4_REACHABILITY:
- *found |= TLVFLAG_TE_IPV4_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug(
- "ISIS-TLV (%s): IPv4 MT Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
- retval = parse_mt_ipv4_reachs(tlvs, true,
- length, pnt);
- pnt += length;
- break;
- case IPV6_ADDR:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * + IP version 6 address + 16
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * : :
- */
- *found |= TLVFLAG_IPV6_ADDR;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): IPv6 Address length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV6_ADDR) {
- while (length > value_len) {
- ipv6_addr = (struct in6_addr *)pnt;
- if (!tlvs->ipv6_addrs)
- tlvs->ipv6_addrs = list_new();
- listnode_add(tlvs->ipv6_addrs,
- ipv6_addr);
- value_len += 16;
- pnt += 16;
- }
- } else {
- pnt += length;
- }
- break;
-
- case IPV6_REACHABILITY:
- *found |= TLVFLAG_IPV6_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV6_REACHABILITY)
- retval = parse_mt_ipv6_reachs(tlvs, false,
- length, pnt);
- pnt += length;
- break;
- case MT_IPV6_REACHABILITY:
- *found |= TLVFLAG_IPV6_REACHABILITY;
-#ifdef EXTREME_TLV_DEBUG
- zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d",
- areatag, length);
-#endif /* EXTREME_TLV_DEBUG */
- if (*expected & TLVFLAG_IPV6_REACHABILITY)
- retval = parse_mt_ipv6_reachs(tlvs, true,
- length, pnt);
- pnt += length;
- break;
- case WAY3_HELLO:
- /* +---------------------------------------------------------------+
- * | Adjacency state | 1
- * +---------------------------------------------------------------+
- * | Extended Local Circuit ID | 4
- * +---------------------------------------------------------------+
- * | Neighbor System ID (If known)
- * | 0-8
- * (probably 6)
- * +---------------------------------------------------------------+
- * | Neighbor Local Circuit ID (If
- * known) | 4
- * +---------------------------------------------------------------+
- */
- *found |= TLVFLAG_3WAY_HELLO;
- if (*expected & TLVFLAG_3WAY_HELLO) {
- while (length > value_len) {
- /* FIXME: make this work */
- /* Adjacency State (one
- octet):
- 0 = Up
- 1 = Initializing
- 2 = Down
- Extended Local Circuit ID
- (four octets)
- Neighbor System ID if known
- (zero to eight octets)
- Neighbor Extended Local
- Circuit ID (four octets, if Neighbor
- System ID is present) */
- pnt += length;
- value_len += length;
- }
- } else {
- pnt += length;
- }
-
- break;
- case GRACEFUL_RESTART:
- /* +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Reserved | SA | RA
- * | RR | 1
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Remaining Time | 2
- * +---------------------------------------------------------------+
- * | Restarting Neighbor ID (If known)
- * | 0-8
- * +---------------------------------------------------------------+
- */
- *found |= TLVFLAG_GRACEFUL_RESTART;
- if (*expected & TLVFLAG_GRACEFUL_RESTART) {
- /* FIXME: make this work */
- }
- pnt += length;
- break;
-
- case MT_ROUTER_INFORMATION:
- *found |= TLVFLAG_MT_ROUTER_INFORMATION;
- if (*expected & TLVFLAG_MT_ROUTER_INFORMATION) {
- if (!tlvs->mt_router_info) {
- tlvs->mt_router_info = list_new();
- tlvs->mt_router_info->del = free_tlv;
- }
- while (length > value_len) {
- uint16_t mt_info;
- struct mt_router_info *info;
-
- if (value_len + sizeof(mt_info)
- > length) {
- zlog_warn(
- "ISIS-TLV (%s): TLV 229 is truncated.",
- areatag);
- pnt += length - value_len;
- break;
- }
-
- memcpy(&mt_info, pnt, sizeof(mt_info));
- pnt += sizeof(mt_info);
- value_len += sizeof(mt_info);
-
- mt_info = ntohs(mt_info);
- info = XCALLOC(MTYPE_ISIS_TLV,
- sizeof(*info));
- info->mtid = mt_info & ISIS_MT_MASK;
- info->overload =
- mt_info & ISIS_MT_OL_MASK;
- listnode_add(tlvs->mt_router_info,
- info);
- }
- } else {
- pnt += length;
- }
- break;
- default:
- zlog_warn(
- "ISIS-TLV (%s): unsupported TLV type %d, length %d",
- areatag, type, length);
-
- pnt += length;
- break;
- }
- /* Abort Parsing if error occured */
- if (retval != ISIS_OK)
- return retval;
- }
-
- return retval;
-}
-
-int add_tlv(u_char tag, u_char len, u_char *value, struct stream *stream)
-{
- if ((stream_get_size(stream) - stream_get_endp(stream))
- < (((unsigned)len) + 2)) {
- zlog_warn(
- "No room for TLV of type %d "
- "(total size %d available %d required %d)",
- tag, (int)stream_get_size(stream),
- (int)(stream_get_size(stream)
- - stream_get_endp(stream)),
- len + 2);
- return ISIS_WARNING;
- }
-
- stream_putc(stream, tag); /* TAG */
- stream_putc(stream, len); /* LENGTH */
- stream_put(stream, value, (int)len); /* VALUE */
-
-#ifdef EXTREME_DEBUG
- zlog_debug("Added TLV %d len %d", tag, len);
-#endif /* EXTREME DEBUG */
- return ISIS_OK;
-}
-
-int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream)
-{
- struct listnode *node;
- struct mt_router_info *info;
-
- uint16_t value[127];
- uint16_t *pos = value;
-
- for (ALL_LIST_ELEMENTS_RO(mt_router_info, node, info)) {
- uint16_t mt_info;
-
- mt_info = info->mtid;
- if (info->overload)
- mt_info |= ISIS_MT_OL_MASK;
-
- *pos = htons(mt_info);
- pos++;
- }
-
- return add_tlv(MT_ROUTER_INFORMATION, (pos - value) * sizeof(*pos),
- (u_char *)value, stream);
-}
-
-int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream)
-{
- struct listnode *node;
- struct area_addr *area_addr;
-
- u_char value[255];
- u_char *pos = value;
-
- for (ALL_LIST_ELEMENTS_RO(area_addrs, node, area_addr)) {
- if (pos - value + area_addr->addr_len > 255)
- goto err;
- *pos = area_addr->addr_len;
- pos++;
- memcpy(pos, area_addr->area_addr, (int)area_addr->addr_len);
- pos += area_addr->addr_len;
- }
-
- return add_tlv(AREA_ADDRESSES, pos - value, value, stream);
-
-err:
- zlog_warn("tlv_add_area_addrs(): TLV longer than 255");
- return ISIS_WARNING;
-}
-
-int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream)
-{
- struct listnode *node;
- struct is_neigh *is_neigh;
- u_char value[255];
- u_char *pos = value;
- int retval;
-
- *pos = 0; /*is_neigh->virtual; */
- pos++;
-
- for (ALL_LIST_ELEMENTS_RO(is_neighs, node, is_neigh)) {
- if (pos - value + IS_NEIGHBOURS_LEN > 255) {
- retval = add_tlv(IS_NEIGHBOURS, pos - value, value,
- stream);
- if (retval != ISIS_OK)
- return retval;
- pos = value;
- }
- *pos = is_neigh->metrics.metric_default;
- pos++;
- *pos = is_neigh->metrics.metric_delay;
- pos++;
- *pos = is_neigh->metrics.metric_expense;
- pos++;
- *pos = is_neigh->metrics.metric_error;
- pos++;
- memcpy(pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
- pos += ISIS_SYS_ID_LEN + 1;
- }
-
- return add_tlv(IS_NEIGHBOURS, pos - value, value, stream);
-}
-
-static size_t max_tlv_size(struct stream *stream)
-{
- size_t avail = stream_get_size(stream) - stream_get_endp(stream);
-
- if (avail < 2)
- return 0;
-
- if (avail < 257)
- return avail - 2;
-
- return 255;
-}
-
-unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs,
- struct stream *stream, void *arg)
-{
- struct listnode *node;
- struct te_is_neigh *te_is_neigh;
- u_char value[255];
- u_char *pos = value;
- uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST;
- unsigned int consumed = 0;
- size_t max_size = max_tlv_size(stream);
-
- if (mtid != ISIS_MT_IPV4_UNICAST) {
- uint16_t mtid_conversion = ntohs(mtid);
- memcpy(pos, &mtid_conversion, sizeof(mtid_conversion));
- pos += sizeof(mtid_conversion);
- }
-
- for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) {
- /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
- if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN
- + te_is_neigh->sub_tlvs_length
- > max_size)
- break;
-
- memcpy(pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
- pos += ISIS_SYS_ID_LEN + 1;
- memcpy(pos, te_is_neigh->te_metric, 3);
- pos += 3;
- /* 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;
- }
- consumed++;
- }
-
- if (consumed) {
- int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST)
- ? MT_IS_NEIGHBOURS
- : TE_IS_NEIGHBOURS,
- pos - value, value, stream);
- assert(rv == ISIS_OK);
- }
- return consumed;
-}
-
-int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream)
-{
- struct listnode *node;
- u_char *snpa;
- u_char value[255];
- u_char *pos = value;
- int retval;
-
- for (ALL_LIST_ELEMENTS_RO(lan_neighs, node, snpa)) {
- if (pos - value + ETH_ALEN > 255) {
- retval = add_tlv(LAN_NEIGHBOURS, pos - value, value,
- stream);
- if (retval != ISIS_OK)
- return retval;
- pos = value;
- }
- memcpy(pos, snpa, ETH_ALEN);
- pos += ETH_ALEN;
- }
-
- return add_tlv(LAN_NEIGHBOURS, pos - value, value, stream);
-}
-
-int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream)
-{
- return add_tlv(PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids,
- stream);
-}
-
-int tlv_add_authinfo(u_char auth_type, u_char auth_len, u_char *auth_value,
- struct stream *stream)
-{
- u_char value[255];
- u_char *pos = value;
- *pos++ = auth_type;
- memcpy(pos, auth_value, auth_len);
-
- return add_tlv(AUTH_INFO, auth_len + 1, value, stream);
-}
-
-int tlv_add_checksum(struct checksum *checksum, struct stream *stream)
-{
- u_char value[255];
- u_char *pos = value;
- return add_tlv(CHECKSUM, pos - value, value, stream);
-}
-
-int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream)
-{
- struct listnode *node;
- struct prefix_ipv4 *ipv4;
- u_char value[255];
- u_char *pos = value;
-
- for (ALL_LIST_ELEMENTS_RO(ip_addrs, node, ipv4)) {
- if (pos - value + IPV4_MAX_BYTELEN > 255) {
- /* RFC 1195 s4.2: only one tuple of 63 allowed. */
- zlog_warn(
- "tlv_add_ip_addrs(): cutting off at 63 IP addresses");
- break;
- }
- *(u_int32_t *)pos = ipv4->prefix.s_addr;
- pos += IPV4_MAX_BYTELEN;
- }
-
- return add_tlv(IPV4_ADDR, pos - value, value, stream);
-}
-
-/* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
- * (in case of LSP) or TE router ID TLV. */
-int tlv_add_in_addr(struct in_addr *addr, struct stream *stream, u_char tag)
-{
- u_char value[255];
- u_char *pos = value;
-
- memcpy(pos, addr, IPV4_MAX_BYTELEN);
- pos += IPV4_MAX_BYTELEN;
-
- return add_tlv(tag, pos - value, value, stream);
-}
-
-int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream)
-{
- return add_tlv(DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
- stream);
-}
-
-int tlv_add_lsp_entries(struct list *lsps, struct stream *stream)
-{
- struct listnode *node;
- struct isis_lsp *lsp;
- u_char value[255];
- u_char *pos = value;
- int retval;
-
- for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) {
- if (pos - value + LSP_ENTRIES_LEN > 255) {
- retval = add_tlv(LSP_ENTRIES, pos - value, value,
- stream);
- if (retval != ISIS_OK)
- return retval;
- pos = value;
- }
- *((u_int16_t *)pos) = lsp->lsp_header->rem_lifetime;
- pos += 2;
- memcpy(pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
- pos += ISIS_SYS_ID_LEN + 2;
- *((u_int32_t *)pos) = lsp->lsp_header->seq_num;
- pos += 4;
- *((u_int16_t *)pos) = lsp->lsp_header->checksum;
- pos += 2;
- }
-
- return add_tlv(LSP_ENTRIES, pos - value, value, stream);
-}
-
-static int tlv_add_ipv4_reachs(u_char tag, struct list *ipv4_reachs,
- struct stream *stream)
-{
- struct listnode *node;
- struct ipv4_reachability *reach;
- u_char value[255];
- u_char *pos = value;
- int retval;
-
- for (ALL_LIST_ELEMENTS_RO(ipv4_reachs, node, reach)) {
- if (pos - value + IPV4_REACH_LEN > 255) {
- retval = add_tlv(tag, pos - value, value, stream);
- if (retval != ISIS_OK)
- return retval;
- pos = value;
- }
- *pos = reach->metrics.metric_default;
- pos++;
- *pos = reach->metrics.metric_delay;
- pos++;
- *pos = reach->metrics.metric_expense;
- pos++;
- *pos = reach->metrics.metric_error;
- pos++;
- *(u_int32_t *)pos = reach->prefix.s_addr;
- pos += IPV4_MAX_BYTELEN;
- *(u_int32_t *)pos = reach->mask.s_addr;
- pos += IPV4_MAX_BYTELEN;
- }
-
- return add_tlv(tag, pos - value, value, stream);
-}
-
-int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream)
-{
- return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream);
-}
-
-int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream)
-{
- return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream);
-}
-
-
-unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs,
- struct stream *stream, void *arg)
-{
- struct listnode *node;
- struct te_ipv4_reachability *te_reach;
- u_char value[255];
- u_char *pos = value;
- uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST;
- unsigned int consumed = 0;
- size_t max_size = max_tlv_size(stream);
-
- if (mtid != ISIS_MT_IPV4_UNICAST) {
- uint16_t mtid_conversion = ntohs(mtid);
- memcpy(pos, &mtid_conversion, sizeof(mtid_conversion));
- pos += sizeof(mtid_conversion);
- }
-
- for (ALL_LIST_ELEMENTS_RO(te_ipv4_reachs, node, te_reach)) {
- unsigned char prefixlen = te_reach->control & 0x3F;
-
- if ((size_t)(pos - value) + 5 + PSIZE(prefixlen) > max_size)
- break;
-
- *(u_int32_t *)pos = te_reach->te_metric;
- pos += 4;
- *pos = te_reach->control;
- pos++;
- memcpy(pos, &te_reach->prefix_start, PSIZE(prefixlen));
- pos += PSIZE(prefixlen);
- consumed++;
- }
-
- if (consumed) {
- int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST)
- ? MT_IPV4_REACHABILITY
- : TE_IPV4_REACHABILITY,
- pos - value, value, stream);
- assert(rv == ISIS_OK);
- }
-
- return consumed;
-}
-
-int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream)
-{
- struct listnode *node;
- struct prefix_ipv6 *ipv6;
- u_char value[255];
- u_char *pos = value;
- int retval;
-
- for (ALL_LIST_ELEMENTS_RO(ipv6_addrs, node, ipv6)) {
- if (pos - value + IPV6_MAX_BYTELEN > 255) {
- retval = add_tlv(IPV6_ADDR, pos - value, value, stream);
- if (retval != ISIS_OK)
- return retval;
- pos = value;
- }
- memcpy(pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
- pos += IPV6_MAX_BYTELEN;
- }
-
- return add_tlv(IPV6_ADDR, pos - value, value, stream);
-}
-
-unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs,
- struct stream *stream, void *arg)
-{
- struct listnode *node;
- struct ipv6_reachability *ip6reach;
- u_char value[255];
- u_char *pos = value;
- uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST;
- unsigned int consumed = 0;
- size_t max_size = max_tlv_size(stream);
-
- if (mtid != ISIS_MT_IPV4_UNICAST) {
- uint16_t mtid_conversion = ntohs(mtid);
- memcpy(pos, &mtid_conversion, sizeof(mtid_conversion));
- pos += sizeof(mtid_conversion);
- }
-
- for (ALL_LIST_ELEMENTS_RO(ipv6_reachs, node, ip6reach)) {
- if ((size_t)(pos - value) + 6 + PSIZE(ip6reach->prefix_len)
- > max_size)
- break;
-
- *(uint32_t *)pos = ip6reach->metric;
- pos += 4;
- *pos = ip6reach->control_info;
- pos++;
- *pos = ip6reach->prefix_len;
- pos++;
- memcpy(pos, ip6reach->prefix, PSIZE(ip6reach->prefix_len));
- pos += PSIZE(ip6reach->prefix_len);
- consumed++;
- }
-
- if (consumed) {
- int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST)
- ? MT_IPV6_REACHABILITY
- : IPV6_REACHABILITY,
- pos - value, value, stream);
- assert(rv == ISIS_OK);
- }
-
- return consumed;
-}
-
-int tlv_add_padding(struct stream *stream)
-{
- int fullpads, i, left;
-
- /*
- * How many times can we add full padding ?
- */
- fullpads = (stream_get_size(stream) - stream_get_endp(stream)) / 257;
- for (i = 0; i < fullpads; i++) {
- if (!stream_putc(stream, (u_char)PADDING)) /* TAG */
- goto err;
- if (!stream_putc(stream, (u_char)255)) /* LENGHT */
- goto err;
- stream_put(stream, NULL, 255); /* zero padding */
- }
-
- left = stream_get_size(stream) - stream_get_endp(stream);
-
- if (left < 2)
- return ISIS_OK;
-
- if (left == 2) {
- stream_putc(stream, PADDING);
- stream_putc(stream, 0);
- return ISIS_OK;
- }
-
- stream_putc(stream, PADDING);
- stream_putc(stream, left - 2);
- stream_put(stream, NULL, left - 2);
-
- return ISIS_OK;
-
-err:
- zlog_warn("tlv_add_padding(): no room for tlv");
- return ISIS_WARNING;
-}
diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h
deleted file mode 100644
index d06548519f..0000000000
--- a/isisd/isis_tlv.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * IS-IS Rout(e)ing protocol - isis_tlv.h
- * IS-IS TLV related routines
- *
- * Copyright (C) 2001,2002 Sampo Saaristo
- * Tampere University of Technology
- * Institute of Communications Engineering
- *
- * 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; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ZEBRA_ISIS_TLV_H
-#define _ZEBRA_ISIS_TLV_H
-
-#include "isisd/isis_mt.h"
-
-/*
- * The list of TLVs we (should) support.
- * ____________________________________________________________________________
- * Name Value IIH LSP SNP Status
- * LAN
- * ____________________________________________________________________________
- *
- * Area Addresses 1 y y n ISO10589
- * IIS Neighbors 2 n y n ISO10589
- * ES Neighbors 3 n y n ISO10589
- * IIS Neighbors 6 y n n ISO10589
- * Padding 8 y n n ISO10589
- * LSP Entries 9 n n y ISO10589
- * Authentication 10 y y y ISO10589, RFC3567
- * Checksum 12 y n y RFC3358
- * 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
- * IP Ext. Reachability 130 n y n RFC1195
- * IDRPI 131 n y y RFC1195
- * IP Interface Address 132 y y n RFC1195
- * TE Router ID 134 n y n RFC5305
- * 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
- * IPv6 Interface Address 232 y y n RFC5308
- * MT IP Reachability 235 n y n RFC5120
- * IPv6 IP Reachability 236 n y n RFC5308
- * 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 n y n RFC4971
- *
- *
- * IS Reachability sub-TLVs we support (See isis_te.[c,h])
- * ____________________________________________________________________________
- * 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
- *
- *
- * IP Reachability sub-TLVs we (should) support.
- * ____________________________________________________________________________
- * Name Value Status
- * ____________________________________________________________________________
- * 32bit administrative tag 1 RFC5130
- * 64bit administrative tag 2 RFC5130
- * Management prefix color 117 RFC5120
- */
-
-#define AREA_ADDRESSES 1
-#define IS_NEIGHBOURS 2
-#define ES_NEIGHBOURS 3
-#define LAN_NEIGHBOURS 6
-#define PADDING 8
-#define LSP_ENTRIES 9
-#define AUTH_INFO 10
-#define CHECKSUM 12
-#define TE_IS_NEIGHBOURS 22
-#define IS_ALIAS 24
-#define IPV4_INT_REACHABILITY 128
-#define PROTOCOLS_SUPPORTED 129
-#define IPV4_EXT_REACHABILITY 130
-#define IDRP_INFO 131
-#define IPV4_ADDR 132
-#define TE_ROUTER_ID 134
-#define TE_IPV4_REACHABILITY 135
-#define DYNAMIC_HOSTNAME 137
-#define GRACEFUL_RESTART 211
-#define MT_IS_NEIGHBOURS 222
-#define MT_ROUTER_INFORMATION 229
-#define IPV6_ADDR 232
-#define MT_IPV4_REACHABILITY 235
-#define IPV6_REACHABILITY 236
-#define MT_IPV6_REACHABILITY 237
-#define WAY3_HELLO 240
-#define ROUTER_INFORMATION 242
-
-#define AUTH_INFO_HDRLEN 3
-
-#define MAX_TLV_LEN 255
-
-#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5)
-#define LAN_NEIGHBOURS_LEN 6
-#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */
-#define IPV4_REACH_LEN 12
-#define IPV6_REACH_LEN 22
-#define TE_IPV4_REACH_LEN 9
-
-#define MAX_SUBTLV_SIZE 256
-
-/* struct for neighbor */
-struct is_neigh {
- struct metric metrics;
- u_char neigh_id[ISIS_SYS_ID_LEN + 1];
-};
-
-/* 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 */
-#define GET_TE_METRIC(t) \
- (((unsigned)(t)->te_metric[0] << 16) | ((t)->te_metric[1] << 8) \
- | (t)->te_metric[2])
-#define SET_TE_METRIC(t, m) \
- (((t)->te_metric[0] = (m) >> 16), ((t)->te_metric[1] = (m) >> 8), \
- ((t)->te_metric[2] = (m)))
-
-/* struct for es neighbors */
-struct es_neigh {
- struct metric metrics;
- /* approximate position of first, we use the
- * length ((uchar*)metric-1) to know all */
- u_char first_es_neigh[ISIS_SYS_ID_LEN];
-};
-
-struct partition_desig_level2_is {
- struct list *isis_system_ids;
-};
-
-/* struct for lan neighbors */
-struct lan_neigh {
- u_char LAN_addr[6];
-};
-
-#ifdef __SUNPRO_C
-#pragma pack(1)
-#endif
-
-/* struct for LSP entry */
-struct lsp_entry {
- u_int16_t rem_lifetime;
- u_char lsp_id[ISIS_SYS_ID_LEN + 2];
- u_int32_t seq_num;
- u_int16_t checksum;
-} __attribute__((packed));
-
-#ifdef __SUNPRO_C
-#pragma pack()
-#endif
-
-/* struct for checksum */
-struct checksum {
- u_int16_t checksum;
-};
-
-/* ipv4 reachability */
-struct ipv4_reachability {
- struct metric metrics;
- struct in_addr prefix;
- struct in_addr mask;
-};
-
-/* te router id */
-struct te_router_id {
- struct in_addr id;
-};
-
-/* te ipv4 reachability */
-struct te_ipv4_reachability {
- u_int32_t te_metric;
- u_char control;
- u_char prefix_start; /* since this is variable length by nature it only
- */
-}; /* points to an approximate location */
-
-#define TE_IPV4_HAS_SUBTLV (0x40)
-
-struct idrp_info {
- u_char len;
- u_char *value;
-};
-
-struct ipv6_reachability {
- u_int32_t metric;
- u_char control_info;
- u_char prefix_len;
- u_char prefix[16];
-};
-
-/* bits in control_info */
-#define CTRL_INFO_DIRECTION 0x80
-#define DIRECTION_UP 0x00
-#define DIRECTION_DOWN 0x80
-
-#define CTRL_INFO_DISTRIBUTION 0x40
-#define DISTRIBUTION_INTERNAL 0x00
-#define DISTRIBUTION_EXTERNAL 0x40
-
-#define CTRL_INFO_SUBTLVS 0x20
-
-struct mt_router_info {
- ISIS_MT_INFO_FIELDS
- bool overload;
-};
-
-/*
- * Pointer to each tlv type, filled by parse_tlvs()
- */
-struct tlvs {
- struct checksum *checksum;
- struct hostname *hostname;
- struct nlpids *nlpids;
- struct te_router_id *router_id;
- struct list *area_addrs;
- struct list *mt_router_info;
- struct list *is_neighs;
- struct list *te_is_neighs;
- struct list *mt_is_neighs;
- struct list *es_neighs;
- struct list *lsp_entries;
- struct list *prefix_neighs;
- struct list *lan_neighs;
- struct list *ipv4_addrs;
- struct list *ipv4_int_reachs;
- struct list *ipv4_ext_reachs;
- struct list *te_ipv4_reachs;
- struct list *mt_ipv4_reachs;
- struct list *ipv6_addrs;
- struct list *ipv6_reachs;
- struct list *mt_ipv6_reachs;
- struct isis_passwd auth_info;
-};
-
-/*
- * Own definitions - used to bitmask found and expected
- */
-
-#define TLVFLAG_AREA_ADDRS (1<<0)
-#define TLVFLAG_IS_NEIGHS (1<<1)
-#define TLVFLAG_ES_NEIGHS (1<<2)
-#define TLVFLAG_PARTITION_DESIG_LEVEL2_IS (1<<3)
-#define TLVFLAG_PREFIX_NEIGHS (1<<4)
-#define TLVFLAG_LAN_NEIGHS (1<<5)
-#define TLVFLAG_LSP_ENTRIES (1<<6)
-#define TLVFLAG_PADDING (1<<7)
-#define TLVFLAG_AUTH_INFO (1<<8)
-#define TLVFLAG_IPV4_INT_REACHABILITY (1<<9)
-#define TLVFLAG_NLPID (1<<10)
-#define TLVFLAG_IPV4_EXT_REACHABILITY (1<<11)
-#define TLVFLAG_IPV4_ADDR (1<<12)
-#define TLVFLAG_DYN_HOSTNAME (1<<13)
-#define TLVFLAG_IPV6_ADDR (1<<14)
-#define TLVFLAG_IPV6_REACHABILITY (1<<15)
-#define TLVFLAG_TE_IS_NEIGHS (1<<16)
-#define TLVFLAG_TE_IPV4_REACHABILITY (1<<17)
-#define TLVFLAG_3WAY_HELLO (1<<18)
-#define TLVFLAG_TE_ROUTER_ID (1<<19)
-#define TLVFLAG_CHECKSUM (1<<20)
-#define TLVFLAG_GRACEFUL_RESTART (1<<21)
-#define TLVFLAG_MT_ROUTER_INFORMATION (1<<22)
-
-void init_tlvs(struct tlvs *tlvs, uint32_t expected);
-void free_tlvs(struct tlvs *tlvs);
-int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected,
- u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset);
-int add_tlv(u_char, u_char, u_char *, struct stream *);
-void free_tlv(void *val);
-
-int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream);
-int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream);
-int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream);
-unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs,
- struct stream *stream, void *arg);
-int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream);
-int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream);
-int tlv_add_checksum(struct checksum *checksum, struct stream *stream);
-int tlv_add_authinfo(u_char auth_type, u_char authlen, u_char *auth_value,
- struct stream *stream);
-int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream);
-int tlv_add_in_addr(struct in_addr *, struct stream *stream, u_char tag);
-int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream);
-int tlv_add_lsp_entries(struct list *lsps, struct stream *stream);
-int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream);
-int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream);
-unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs,
- struct stream *stream, void *arg);
-int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream);
-unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs,
- struct stream *stream, void *arg);
-
-int tlv_add_padding(struct stream *stream);
-
-#endif /* _ZEBRA_ISIS_TLV_H */
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
new file mode 100644
index 0000000000..8efbcd2811
--- /dev/null
+++ b/isisd/isis_tlvs.c
@@ -0,0 +1,3090 @@
+/*
+ * IS-IS TLV Serializer/Deserializer
+ *
+ * Copyright (C) 2015,2017 Christian Franke
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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.
+ *
+ * FRR 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 FRR; 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 "md5.h"
+#include "memory.h"
+#include "stream.h"
+#include "sbuf.h"
+
+#include "isisd/isisd.h"
+#include "isisd/isis_memory.h"
+#include "isisd/isis_tlvs.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_mt.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_te.h"
+
+DEFINE_MTYPE_STATIC(ISISD, ISIS_TLV, "ISIS TLVs")
+DEFINE_MTYPE_STATIC(ISISD, ISIS_SUBTLV, "ISIS Sub-TLVs")
+DEFINE_MTYPE_STATIC(ISISD, ISIS_MT_ITEM_LIST, "ISIS MT Item Lists")
+
+typedef int (*unpack_tlv_func)(enum isis_tlv_context context, uint8_t tlv_type,
+ uint8_t tlv_len, struct stream *s,
+ struct sbuf *log, void *dest, int indent);
+typedef int (*pack_item_func)(struct isis_item *item, struct stream *s);
+typedef void (*free_item_func)(struct isis_item *i);
+typedef int (*unpack_item_func)(uint16_t mtid, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent);
+typedef void (*format_item_func)(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent);
+typedef struct isis_item *(*copy_item_func)(struct isis_item *i);
+
+struct tlv_ops {
+ const char *name;
+ unpack_tlv_func unpack;
+
+ pack_item_func pack_item;
+ free_item_func free_item;
+ unpack_item_func unpack_item;
+ format_item_func format_item;
+ copy_item_func copy_item;
+};
+
+enum how_to_pack {
+ ISIS_ITEMS,
+ ISIS_MT_ITEMS,
+};
+
+struct pack_order_entry {
+ enum isis_tlv_context context;
+ enum isis_tlv_type type;
+ enum how_to_pack how_to_pack;
+ size_t what_to_pack;
+};
+#define PACK_ENTRY(t, h, w) \
+ { \
+ .context = ISIS_CONTEXT_LSP, .type = ISIS_TLV_##t, \
+ .how_to_pack = (h), \
+ .what_to_pack = offsetof(struct isis_tlvs, w), \
+ }
+
+static struct pack_order_entry pack_order[] = {
+ PACK_ENTRY(OLDSTYLE_REACH, ISIS_ITEMS, oldstyle_reach),
+ PACK_ENTRY(LAN_NEIGHBORS, ISIS_ITEMS, lan_neighbor),
+ PACK_ENTRY(LSP_ENTRY, ISIS_ITEMS, lsp_entries),
+ PACK_ENTRY(EXTENDED_REACH, ISIS_ITEMS, extended_reach),
+ PACK_ENTRY(MT_REACH, ISIS_MT_ITEMS, mt_reach),
+ PACK_ENTRY(OLDSTYLE_IP_REACH, ISIS_ITEMS, oldstyle_ip_reach),
+ PACK_ENTRY(OLDSTYLE_IP_REACH_EXT, ISIS_ITEMS, oldstyle_ip_reach_ext),
+ PACK_ENTRY(IPV4_ADDRESS, ISIS_ITEMS, ipv4_address),
+ PACK_ENTRY(IPV6_ADDRESS, ISIS_ITEMS, ipv6_address),
+ PACK_ENTRY(EXTENDED_IP_REACH, ISIS_ITEMS, extended_ip_reach),
+ PACK_ENTRY(MT_IP_REACH, ISIS_MT_ITEMS, mt_ip_reach),
+ PACK_ENTRY(IPV6_REACH, ISIS_ITEMS, ipv6_reach),
+ PACK_ENTRY(MT_IPV6_REACH, ISIS_MT_ITEMS, mt_ipv6_reach)};
+
+/* This is a forward definition. The table is actually initialized
+ * in at the bottom. */
+static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX];
+
+/* End of _ops forward definition. */
+
+/* Prototypes */
+static void append_item(struct isis_item_list *dest, struct isis_item *item);
+
+/* Functions for Sub-TVL ??? IPv6 Source Prefix */
+
+static struct prefix_ipv6 *copy_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p)
+{
+ if (!p)
+ return NULL;
+
+ struct prefix_ipv6 *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
+ rv->family = p->family;
+ rv->prefixlen = p->prefixlen;
+ memcpy(&rv->prefix, &p->prefix, sizeof(rv->prefix));
+ return rv;
+}
+
+static void format_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
+ struct sbuf *buf, int indent)
+{
+ if (!p)
+ return;
+
+ char prefixbuf[PREFIX2STR_BUFFER];
+ sbuf_push(buf, indent, "IPv6 Source Prefix: %s\n",
+ prefix2str(p, prefixbuf, sizeof(prefixbuf)));
+}
+
+static int pack_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
+ struct stream *s)
+{
+ if (!p)
+ return 0;
+
+ if (STREAM_WRITEABLE(s) < 3 + (unsigned)PSIZE(p->prefixlen))
+ return 1;
+
+ stream_putc(s, ISIS_SUBTLV_IPV6_SOURCE_PREFIX);
+ stream_putc(s, 1 + PSIZE(p->prefixlen));
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->prefix, PSIZE(p->prefixlen));
+ return 0;
+}
+
+static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_subtlvs *subtlvs = dest;
+ struct prefix_ipv6 p = {
+ .family = AF_INET6,
+ };
+
+ sbuf_push(log, indent, "Unpacking IPv6 Source Prefix Sub-TLV...\n");
+
+ if (tlv_len < 1) {
+ sbuf_push(log, indent,
+ "Not enough data left. (expected 1 or more bytes, got %" PRIu8 ")\n",
+ tlv_len);
+ return 1;
+ }
+
+ p.prefixlen = stream_getc(s);
+ if (p.prefixlen > 128) {
+ sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv6\n",
+ p.prefixlen);
+ return 1;
+ }
+
+ if (tlv_len != 1 + PSIZE(p.prefixlen)) {
+ sbuf_push(
+ log, indent,
+ "TLV size differs from expected size for the prefixlen. "
+ "(expected %u but got %" PRIu8 ")\n",
+ 1 + PSIZE(p.prefixlen), tlv_len);
+ return 1;
+ }
+
+ stream_get(&p.prefix, s, PSIZE(p.prefixlen));
+
+ if (subtlvs->source_prefix) {
+ sbuf_push(
+ log, indent,
+ "WARNING: source prefix Sub-TLV present multiple times.\n");
+ /* Ignore all but first occurrence of the source prefix Sub-TLV
+ */
+ return 0;
+ }
+
+ subtlvs->source_prefix = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(p));
+ memcpy(subtlvs->source_prefix, &p, sizeof(p));
+ return 0;
+}
+
+/* Functions related to subtlvs */
+
+static struct isis_subtlvs *isis_alloc_subtlvs(void)
+{
+ struct isis_subtlvs *result;
+
+ result = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*result));
+
+ return result;
+}
+
+static struct isis_subtlvs *copy_subtlvs(struct isis_subtlvs *subtlvs)
+{
+ if (!subtlvs)
+ return NULL;
+
+ struct isis_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
+
+ rv->source_prefix =
+ copy_subtlv_ipv6_source_prefix(subtlvs->source_prefix);
+ return rv;
+}
+
+static void format_subtlvs(struct isis_subtlvs *subtlvs, struct sbuf *buf,
+ int indent)
+{
+ format_subtlv_ipv6_source_prefix(subtlvs->source_prefix, buf, indent);
+}
+
+static void isis_free_subtlvs(struct isis_subtlvs *subtlvs)
+{
+ if (!subtlvs)
+ return;
+
+ XFREE(MTYPE_ISIS_SUBTLV, subtlvs->source_prefix);
+
+ XFREE(MTYPE_ISIS_SUBTLV, subtlvs);
+}
+
+static int pack_subtlvs(struct isis_subtlvs *subtlvs, struct stream *s)
+{
+ int rv;
+ size_t subtlv_len_pos = stream_get_endp(s);
+
+ if (STREAM_WRITEABLE(s) < 1)
+ return 1;
+
+ stream_putc(s, 0); /* Put 0 as subtlvs length, filled in later */
+
+ rv = pack_subtlv_ipv6_source_prefix(subtlvs->source_prefix, s);
+ if (rv)
+ return rv;
+
+ size_t subtlv_len = stream_get_endp(s) - subtlv_len_pos - 1;
+ if (subtlv_len > 255)
+ return 1;
+
+ stream_putc_at(s, subtlv_len_pos, subtlv_len);
+ return 0;
+}
+
+static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
+ struct stream *stream, struct sbuf *log, void *dest,
+ int indent);
+
+/* Functions related to TLVs 1 Area Addresses */
+
+static struct isis_item *copy_item_area_address(struct isis_item *i)
+{
+ struct isis_area_address *addr = (struct isis_area_address *)i;
+ struct isis_area_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->len = addr->len;
+ memcpy(rv->addr, addr->addr, addr->len);
+ return (struct isis_item *)rv;
+}
+
+static void format_item_area_address(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_area_address *addr = (struct isis_area_address *)i;
+
+ sbuf_push(buf, indent, "Area Address: %s\n",
+ isonet_print(addr->addr, addr->len));
+}
+
+static void free_item_area_address(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_area_address(struct isis_item *i, struct stream *s)
+{
+ struct isis_area_address *addr = (struct isis_area_address *)i;
+
+ if (STREAM_WRITEABLE(s) < (unsigned)1 + addr->len)
+ return 1;
+ stream_putc(s, addr->len);
+ stream_put(s, addr->addr, addr->len);
+ return 0;
+}
+
+static int unpack_item_area_address(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+ struct isis_area_address *rv = NULL;
+
+ sbuf_push(log, indent, "Unpack area address...\n");
+ if (len < 1) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left. (Expected 1 byte of address length, got %" PRIu8
+ ")\n",
+ len);
+ goto out;
+ }
+
+ rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ rv->len = stream_getc(s);
+
+ if (len < 1 + rv->len) {
+ sbuf_push(log, indent, "Not enough data left. (Expected %" PRIu8
+ " bytes of address, got %" PRIu8 ")\n",
+ rv->len, len - 1);
+ goto out;
+ }
+
+ if (rv->len < 1 || rv->len > 20) {
+ sbuf_push(log, indent,
+ "Implausible area address length %" PRIu8 "\n",
+ rv->len);
+ goto out;
+ }
+
+ stream_get(rv->addr, s, rv->len);
+
+ format_item_area_address(ISIS_MT_IPV4_UNICAST, (struct isis_item *)rv,
+ log, indent + 2);
+ append_item(&tlvs->area_addresses, (struct isis_item *)rv);
+ return 0;
+out:
+ XFREE(MTYPE_ISIS_TLV, rv);
+ return 1;
+}
+
+/* Functions related to TLV 2 (Old-Style) IS Reach */
+static struct isis_item *copy_item_oldstyle_reach(struct isis_item *i)
+{
+ struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i;
+ struct isis_oldstyle_reach *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ memcpy(rv->id, r->id, 7);
+ rv->metric = r->metric;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i;
+
+ sbuf_push(buf, indent, "IS Reachability: %s (Metric: %" PRIu8 ")\n",
+ isis_format_id(r->id, 7), r->metric);
+}
+
+static void free_item_oldstyle_reach(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_oldstyle_reach(struct isis_item *i, struct stream *s)
+{
+ struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i;
+
+ if (STREAM_WRITEABLE(s) < 11)
+ return 1;
+
+ stream_putc(s, r->metric);
+ stream_putc(s, 0x80); /* delay metric - unsupported */
+ stream_putc(s, 0x80); /* expense metric - unsupported */
+ stream_putc(s, 0x80); /* error metric - unsupported */
+ stream_put(s, r->id, 7);
+
+ return 0;
+}
+
+static int unpack_item_oldstyle_reach(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack oldstyle reach...\n");
+ if (len < 11) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 11 bytes of reach information, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_oldstyle_reach *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ rv->metric = stream_getc(s);
+ if ((rv->metric & 0x3f) != rv->metric) {
+ sbuf_push(log, indent, "Metric has unplausible format\n");
+ rv->metric &= 0x3f;
+ }
+ stream_forward_getp(s, 3); /* Skip other metrics */
+ stream_get(rv->id, s, 7);
+
+ format_item_oldstyle_reach(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+ append_item(&tlvs->oldstyle_reach, (struct isis_item *)rv);
+ return 0;
+}
+
+/* Functions related to TLV 6 LAN Neighbors */
+static struct isis_item *copy_item_lan_neighbor(struct isis_item *i)
+{
+ struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i;
+ struct isis_lan_neighbor *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ memcpy(rv->mac, n->mac, 6);
+ return (struct isis_item *)rv;
+}
+
+static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i;
+
+ sbuf_push(buf, indent, "LAN Neighbor: %s\n", isis_format_id(n->mac, 6));
+}
+
+static void free_item_lan_neighbor(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_lan_neighbor(struct isis_item *i, struct stream *s)
+{
+ struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i;
+
+ if (STREAM_WRITEABLE(s) < 6)
+ return 1;
+
+ stream_put(s, n->mac, 6);
+
+ return 0;
+}
+
+static int unpack_item_lan_neighbor(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack LAN neighbor...\n");
+ if (len < 6) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 6 bytes of mac, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_lan_neighbor *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(rv->mac, s, 6);
+
+ format_item_lan_neighbor(mtid, (struct isis_item *)rv, log, indent + 2);
+ append_item(&tlvs->lan_neighbor, (struct isis_item *)rv);
+ return 0;
+}
+
+/* Functions related to TLV 9 LSP Entry */
+static struct isis_item *copy_item_lsp_entry(struct isis_item *i)
+{
+ struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
+ struct isis_lsp_entry *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->rem_lifetime = e->rem_lifetime;
+ memcpy(rv->id, e->id, sizeof(rv->id));
+ rv->seqno = e->seqno;
+ rv->checksum = e->checksum;
+
+ return (struct isis_item *)rv;
+}
+
+static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
+
+ sbuf_push(buf, indent, "LSP Entry: %s, seq 0x%08" PRIx32
+ ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s\n",
+ isis_format_id(e->id, 8), e->seqno, e->checksum,
+ e->rem_lifetime);
+}
+
+static void free_item_lsp_entry(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_lsp_entry(struct isis_item *i, struct stream *s)
+{
+ struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
+
+ if (STREAM_WRITEABLE(s) < 16)
+ return 1;
+
+ stream_putw(s, e->rem_lifetime);
+ stream_put(s, e->id, 8);
+ stream_putl(s, e->seqno);
+ stream_putw(s, e->checksum);
+
+ return 0;
+}
+
+static int unpack_item_lsp_entry(uint16_t mtid, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack LSP entry...\n");
+ if (len < 16) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left. (Expected 16 bytes of LSP info, got %" PRIu8,
+ len);
+ return 1;
+ }
+
+ struct isis_lsp_entry *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ rv->rem_lifetime = stream_getw(s);
+ stream_get(rv->id, s, 8);
+ rv->seqno = stream_getl(s);
+ rv->checksum = stream_getw(s);
+
+ format_item_lsp_entry(mtid, (struct isis_item *)rv, log, indent + 2);
+ append_item(&tlvs->lsp_entries, (struct isis_item *)rv);
+ return 0;
+}
+
+/* Functions related to TLVs 22/222 Extended Reach/MT Reach */
+
+static struct isis_item *copy_item_extended_reach(struct isis_item *i)
+{
+ struct isis_extended_reach *r = (struct isis_extended_reach *)i;
+ struct isis_extended_reach *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ memcpy(rv->id, r->id, 7);
+ rv->metric = r->metric;
+
+ if (r->subtlvs && r->subtlv_len) {
+ rv->subtlvs = XCALLOC(MTYPE_ISIS_TLV, r->subtlv_len);
+ memcpy(rv->subtlvs, r->subtlvs, r->subtlv_len);
+ rv->subtlv_len = r->subtlv_len;
+ }
+
+ return (struct isis_item *)rv;
+}
+
+static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_extended_reach *r = (struct isis_extended_reach *)i;
+
+ sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
+ isis_format_id(r->id, 7), r->metric);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
+
+ if (r->subtlv_len && r->subtlvs)
+ mpls_te_print_detail(buf, indent + 2, r->subtlvs, r->subtlv_len);
+}
+
+static void free_item_extended_reach(struct isis_item *i)
+{
+ struct isis_extended_reach *item = (struct isis_extended_reach *)i;
+ XFREE(MTYPE_ISIS_TLV, item->subtlvs);
+ XFREE(MTYPE_ISIS_TLV, item);
+}
+
+static int pack_item_extended_reach(struct isis_item *i, struct stream *s)
+{
+ struct isis_extended_reach *r = (struct isis_extended_reach *)i;
+
+ if (STREAM_WRITEABLE(s) < 11 + (unsigned)r->subtlv_len)
+ return 1;
+ stream_put(s, r->id, sizeof(r->id));
+ stream_put3(s, r->metric);
+ stream_putc(s, r->subtlv_len);
+ stream_put(s, r->subtlvs, r->subtlv_len);
+ return 0;
+}
+
+static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+ struct isis_extended_reach *rv = NULL;
+ uint8_t subtlv_len;
+ struct isis_item_list *items;
+
+ if (mtid == ISIS_MT_IPV4_UNICAST) {
+ items = &tlvs->extended_reach;
+ } else {
+ items = isis_get_mt_items(&tlvs->mt_reach, mtid);
+ }
+
+ sbuf_push(log, indent, "Unpacking %s reachability...\n",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "extended" : "mt");
+
+ if (len < 11) {
+ sbuf_push(log, indent,
+ "Not enough data left. (expected 11 or more bytes, got %"
+ PRIu8 ")\n",
+ len);
+ goto out;
+ }
+
+ rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(rv->id, s, 7);
+ rv->metric = stream_get3(s);
+ subtlv_len = stream_getc(s);
+
+ format_item_extended_reach(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+
+ if ((size_t)len < ((size_t)11) + subtlv_len) {
+ sbuf_push(log, indent,
+ "Not enough data left for subtlv size %" PRIu8
+ ", there are only %" PRIu8 " bytes left.\n",
+ subtlv_len, len - 11);
+ goto out;
+ }
+
+ sbuf_push(log, indent, "Storing %" PRIu8 " bytes of subtlvs\n",
+ subtlv_len);
+
+ if (subtlv_len) {
+ size_t subtlv_start = stream_get_getp(s);
+
+ if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_NE_REACH, subtlv_len, s,
+ log, NULL, indent + 4)) {
+ goto out;
+ }
+
+ stream_set_getp(s, subtlv_start);
+
+ rv->subtlvs = XCALLOC(MTYPE_ISIS_TLV, subtlv_len);
+ stream_get(rv->subtlvs, s, subtlv_len);
+ rv->subtlv_len = subtlv_len;
+ }
+
+ append_item(items, (struct isis_item *)rv);
+ return 0;
+out:
+ if (rv)
+ free_item_extended_reach((struct isis_item *)rv);
+
+ return 1;
+}
+
+/* Functions related to TLV 128 (Old-Style) IP Reach */
+static struct isis_item *copy_item_oldstyle_ip_reach(struct isis_item *i)
+{
+ struct isis_oldstyle_ip_reach *r = (struct isis_oldstyle_ip_reach *)i;
+ struct isis_oldstyle_ip_reach *rv =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->metric = r->metric;
+ rv->prefix = r->prefix;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_oldstyle_ip_reach *r = (struct isis_oldstyle_ip_reach *)i;
+ char prefixbuf[PREFIX2STR_BUFFER];
+
+ sbuf_push(buf, indent, "IP Reachability: %s (Metric: %" PRIu8 ")\n",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric);
+}
+
+static void free_item_oldstyle_ip_reach(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_oldstyle_ip_reach(struct isis_item *i, struct stream *s)
+{
+ struct isis_oldstyle_ip_reach *r = (struct isis_oldstyle_ip_reach *)i;
+
+ if (STREAM_WRITEABLE(s) < 12)
+ return 1;
+
+ stream_putc(s, r->metric);
+ stream_putc(s, 0x80); /* delay metric - unsupported */
+ stream_putc(s, 0x80); /* expense metric - unsupported */
+ stream_putc(s, 0x80); /* error metric - unsupported */
+ stream_put(s, &r->prefix.prefix, 4);
+
+ struct in_addr mask;
+ masklen2ip(r->prefix.prefixlen, &mask);
+ stream_put(s, &mask, sizeof(mask));
+
+ return 0;
+}
+
+static int unpack_item_oldstyle_ip_reach(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ sbuf_push(log, indent, "Unpack oldstyle ip reach...\n");
+ if (len < 12) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 12 bytes of reach information, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_oldstyle_ip_reach *rv =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ rv->metric = stream_getc(s);
+ if ((rv->metric & 0x7f) != rv->metric) {
+ sbuf_push(log, indent, "Metric has unplausible format\n");
+ rv->metric &= 0x7f;
+ }
+ stream_forward_getp(s, 3); /* Skip other metrics */
+ rv->prefix.family = AF_INET;
+ stream_get(&rv->prefix.prefix, s, 4);
+
+ struct in_addr mask;
+ stream_get(&mask, s, 4);
+ rv->prefix.prefixlen = ip_masklen(mask);
+
+ format_item_oldstyle_ip_reach(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+ append_item(dest, (struct isis_item *)rv);
+ return 0;
+}
+
+
+/* Functions related to TLV 129 protocols supported */
+
+static void copy_tlv_protocols_supported(struct isis_protocols_supported *src,
+ struct isis_protocols_supported *dest)
+{
+ if (!src->protocols || !src->count)
+ return;
+ dest->count = src->count;
+ dest->protocols = XCALLOC(MTYPE_ISIS_TLV, src->count);
+ memcpy(dest->protocols, src->protocols, src->count);
+}
+
+static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
+ struct sbuf *buf, int indent)
+{
+ if (!p || !p->count || !p->protocols)
+ return;
+
+ sbuf_push(buf, indent, "Protocols Supported: ");
+ for (uint8_t i = 0; i < p->count; i++) {
+ sbuf_push(buf, 0, "%s%s", nlpid2str(p->protocols[i]),
+ (i + 1 < p->count) ? ", " : "");
+ }
+ sbuf_push(buf, 0, "\n");
+}
+
+static void free_tlv_protocols_supported(struct isis_protocols_supported *p)
+{
+ XFREE(MTYPE_ISIS_TLV, p->protocols);
+}
+
+static int pack_tlv_protocols_supported(struct isis_protocols_supported *p,
+ struct stream *s)
+{
+ if (!p || !p->count || !p->protocols)
+ return 0;
+
+ if (STREAM_WRITEABLE(s) < (unsigned)(p->count + 2))
+ return 1;
+
+ stream_putc(s, ISIS_TLV_PROTOCOLS_SUPPORTED);
+ stream_putc(s, p->count);
+ stream_put(s, p->protocols, p->count);
+ return 0;
+}
+
+static int unpack_tlv_protocols_supported(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpacking Protocols Supported TLV...\n");
+ if (!tlv_len) {
+ sbuf_push(log, indent, "WARNING: No protocols included\n");
+ return 0;
+ }
+ if (tlvs->protocols_supported.protocols) {
+ sbuf_push(
+ log, indent,
+ "WARNING: protocols supported TLV present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ tlvs->protocols_supported.count = tlv_len;
+ tlvs->protocols_supported.protocols = XCALLOC(MTYPE_ISIS_TLV, tlv_len);
+ stream_get(tlvs->protocols_supported.protocols, s, tlv_len);
+
+ format_tlv_protocols_supported(&tlvs->protocols_supported, log,
+ indent + 2);
+ return 0;
+}
+
+/* Functions related to TLV 132 IPv4 Interface addresses */
+static struct isis_item *copy_item_ipv4_address(struct isis_item *i)
+{
+ struct isis_ipv4_address *a = (struct isis_ipv4_address *)i;
+ struct isis_ipv4_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->addr = a->addr;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_ipv4_address(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_ipv4_address *a = (struct isis_ipv4_address *)i;
+ char addrbuf[INET_ADDRSTRLEN];
+
+ inet_ntop(AF_INET, &a->addr, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "IPv4 Interface Address: %s\n", addrbuf);
+}
+
+static void free_item_ipv4_address(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_ipv4_address(struct isis_item *i, struct stream *s)
+{
+ struct isis_ipv4_address *a = (struct isis_ipv4_address *)i;
+
+ if (STREAM_WRITEABLE(s) < 4)
+ return 1;
+
+ stream_put(s, &a->addr, 4);
+
+ return 0;
+}
+
+static int unpack_item_ipv4_address(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack IPv4 Interface address...\n");
+ if (len < 4) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 4 bytes of IPv4 address, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_ipv4_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(&rv->addr, s, 4);
+
+ format_item_ipv4_address(mtid, (struct isis_item *)rv, log, indent + 2);
+ append_item(&tlvs->ipv4_address, (struct isis_item *)rv);
+ return 0;
+}
+
+
+/* Functions related to TLV 232 IPv6 Interface addresses */
+static struct isis_item *copy_item_ipv6_address(struct isis_item *i)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->addr = a->addr;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_ipv6_address(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ char addrbuf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "IPv6 Interface Address: %s\n", addrbuf);
+}
+
+static void free_item_ipv6_address(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_ipv6_address(struct isis_item *i, struct stream *s)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+
+ if (STREAM_WRITEABLE(s) < 16)
+ return 1;
+
+ stream_put(s, &a->addr, 16);
+
+ return 0;
+}
+
+static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack IPv6 Interface address...\n");
+ if (len < 16) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 16 bytes of IPv6 address, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(&rv->addr, s, 16);
+
+ format_item_ipv6_address(mtid, (struct isis_item *)rv, log, indent + 2);
+ append_item(&tlvs->ipv6_address, (struct isis_item *)rv);
+ return 0;
+}
+
+
+/* Functions related to TLV 229 MT Router information */
+static struct isis_item *copy_item_mt_router_info(struct isis_item *i)
+{
+ struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
+ struct isis_mt_router_info *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->overload = info->overload;
+ rv->attached = info->attached;
+ rv->mtid = info->mtid;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_mt_router_info(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
+
+ sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
+ isis_mtid2str(info->mtid),
+ info->overload ? " Overload" : "",
+ info->attached ? " Attached" : "");
+}
+
+static void free_item_mt_router_info(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_mt_router_info(struct isis_item *i, struct stream *s)
+{
+ struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
+
+ if (STREAM_WRITEABLE(s) < 2)
+ return 1;
+
+ uint16_t entry = info->mtid;
+
+ if (info->overload)
+ entry |= ISIS_MT_OL_MASK;
+ if (info->attached)
+ entry |= ISIS_MT_AT_MASK;
+
+ stream_putw(s, entry);
+
+ return 0;
+}
+
+static int unpack_item_mt_router_info(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack MT Router info...\n");
+ if (len < 2) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 2 bytes of MT info, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_mt_router_info *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ uint16_t entry = stream_getw(s);
+ rv->overload = entry & ISIS_MT_OL_MASK;
+ rv->attached = entry & ISIS_MT_AT_MASK;
+ rv->mtid = entry & ISIS_MT_MASK;
+
+ format_item_mt_router_info(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+ append_item(&tlvs->mt_router_info, (struct isis_item *)rv);
+ return 0;
+}
+
+/* Functions related to TLV 134 TE Router ID */
+
+static struct in_addr *copy_tlv_te_router_id(const struct in_addr *id)
+{
+ if (!id)
+ return NULL;
+
+ struct in_addr *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ memcpy(rv, id, sizeof(*rv));
+ return rv;
+}
+
+static void format_tlv_te_router_id(const struct in_addr *id, struct sbuf *buf,
+ int indent)
+{
+ if (!id)
+ return;
+
+ char addrbuf[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, id, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "TE Router ID: %s\n", addrbuf);
+}
+
+static void free_tlv_te_router_id(struct in_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, id);
+}
+
+static int pack_tlv_te_router_id(const struct in_addr *id, struct stream *s)
+{
+ if (!id)
+ return 0;
+
+ if (STREAM_WRITEABLE(s) < (unsigned)(2 + sizeof(*id)))
+ return 1;
+
+ stream_putc(s, ISIS_TLV_TE_ROUTER_ID);
+ stream_putc(s, 4);
+ stream_put(s, id, 4);
+ return 0;
+}
+
+static int unpack_tlv_te_router_id(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpacking TE Router ID TLV...\n");
+ if (tlv_len != 4) {
+ sbuf_push(log, indent, "WARNING: Length invalid\n");
+ return 1;
+ }
+
+ if (tlvs->te_router_id) {
+ sbuf_push(log, indent,
+ "WARNING: TE Router ID present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ tlvs->te_router_id = XCALLOC(MTYPE_ISIS_TLV, 4);
+ stream_get(tlvs->te_router_id, s, 4);
+ format_tlv_te_router_id(tlvs->te_router_id, log, indent + 2);
+ return 0;
+}
+
+
+/* Functions related to TLVs 135/235 extended IP reach/MT IP Reach */
+
+static struct isis_item *copy_item_extended_ip_reach(struct isis_item *i)
+{
+ struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
+ struct isis_extended_ip_reach *rv =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->metric = r->metric;
+ rv->down = r->down;
+ rv->prefix = r->prefix;
+
+ return (struct isis_item *)rv;
+}
+
+static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
+ char prefixbuf[PREFIX2STR_BUFFER];
+
+ sbuf_push(buf, indent, "%s IP Reachability: %s (Metric: %u)%s",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric,
+ r->down ? " Down" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
+}
+
+static void free_item_extended_ip_reach(struct isis_item *i)
+{
+ struct isis_extended_ip_reach *item =
+ (struct isis_extended_ip_reach *)i;
+ XFREE(MTYPE_ISIS_TLV, item);
+}
+
+static int pack_item_extended_ip_reach(struct isis_item *i, struct stream *s)
+{
+ struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
+ uint8_t control;
+
+ if (STREAM_WRITEABLE(s) < 5)
+ return 1;
+ stream_putl(s, r->metric);
+
+ control = r->down ? ISIS_EXTENDED_IP_REACH_DOWN : 0;
+ control |= r->prefix.prefixlen;
+ stream_putc(s, control);
+
+ if (STREAM_WRITEABLE(s) < (unsigned)PSIZE(r->prefix.prefixlen))
+ return 1;
+ stream_put(s, &r->prefix.prefix.s_addr, PSIZE(r->prefix.prefixlen));
+ return 0;
+}
+
+static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+ struct isis_extended_ip_reach *rv = NULL;
+ size_t consume;
+ uint8_t control, subtlv_len;
+ struct isis_item_list *items;
+
+ if (mtid == ISIS_MT_IPV4_UNICAST) {
+ items = &tlvs->extended_ip_reach;
+ } else {
+ items = isis_get_mt_items(&tlvs->mt_ip_reach, mtid);
+ }
+
+ sbuf_push(log, indent, "Unpacking %s IPv4 reachability...\n",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "extended" : "mt");
+
+ consume = 5;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Not enough data left. (expected 5 or more bytes, got %" PRIu8 ")\n",
+ len);
+ goto out;
+ }
+
+ rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->metric = stream_getl(s);
+ control = stream_getc(s);
+ rv->down = (control & ISIS_EXTENDED_IP_REACH_DOWN);
+ rv->prefix.family = AF_INET;
+ rv->prefix.prefixlen = control & 0x3f;
+ if (rv->prefix.prefixlen > 32) {
+ sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv4\n",
+ rv->prefix.prefixlen);
+ goto out;
+ }
+
+ consume += PSIZE(rv->prefix.prefixlen);
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected %u bytes of prefix, but only %u bytes available.\n",
+ PSIZE(rv->prefix.prefixlen), len - 5);
+ goto out;
+ }
+ stream_get(&rv->prefix.prefix.s_addr, s, PSIZE(rv->prefix.prefixlen));
+ in_addr_t orig_prefix = rv->prefix.prefix.s_addr;
+ apply_mask_ipv4(&rv->prefix);
+ if (orig_prefix != rv->prefix.prefix.s_addr)
+ sbuf_push(log, indent + 2,
+ "WARNING: Prefix had hostbits set.\n");
+ format_item_extended_ip_reach(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+
+ if (control & ISIS_EXTENDED_IP_REACH_SUBTLV) {
+ consume += 1;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected 1 byte of subtlv len, but no more data present.\n");
+ goto out;
+ }
+ subtlv_len = stream_getc(s);
+
+ if (!subtlv_len) {
+ sbuf_push(log, indent + 2,
+ " WARNING: subtlv bit is set, but there are no subtlvs.\n");
+ }
+ consume += subtlv_len;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected %" PRIu8
+ " bytes of subtlvs, but only %u bytes available.\n",
+ subtlv_len,
+ len - 6 - PSIZE(rv->prefix.prefixlen));
+ goto out;
+ }
+ sbuf_push(log, indent, "Skipping %" PRIu8 " bytes of subvls",
+ subtlv_len);
+ stream_forward_getp(s, subtlv_len);
+ }
+
+ append_item(items, (struct isis_item *)rv);
+ return 0;
+out:
+ if (rv)
+ free_item_extended_ip_reach((struct isis_item *)rv);
+ return 1;
+}
+
+/* Functions related to TLV 137 Dynamic Hostname */
+
+static char *copy_tlv_dynamic_hostname(const char *hostname)
+{
+ if (!hostname)
+ return NULL;
+
+ return XSTRDUP(MTYPE_ISIS_TLV, hostname);
+}
+
+static void format_tlv_dynamic_hostname(const char *hostname, struct sbuf *buf,
+ int indent)
+{
+ if (!hostname)
+ return;
+
+ sbuf_push(buf, indent, "Hostname: %s\n", hostname);
+}
+
+static void free_tlv_dynamic_hostname(char *hostname)
+{
+ XFREE(MTYPE_ISIS_TLV, hostname);
+}
+
+static int pack_tlv_dynamic_hostname(const char *hostname, struct stream *s)
+{
+ if (!hostname)
+ return 0;
+
+ uint8_t name_len = strlen(hostname);
+
+ if (STREAM_WRITEABLE(s) < (unsigned)(2 + name_len))
+ return 1;
+
+ stream_putc(s, ISIS_TLV_DYNAMIC_HOSTNAME);
+ stream_putc(s, name_len);
+ stream_put(s, hostname, name_len);
+ return 0;
+}
+
+static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpacking Dynamic Hostname TLV...\n");
+ if (!tlv_len) {
+ sbuf_push(log, indent, "WARNING: No hostname included\n");
+ return 0;
+ }
+
+ if (tlvs->hostname) {
+ sbuf_push(log, indent,
+ "WARNING: Hostname present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ tlvs->hostname = XCALLOC(MTYPE_ISIS_TLV, tlv_len + 1);
+ stream_get(tlvs->hostname, s, tlv_len);
+ tlvs->hostname[tlv_len] = '\0';
+
+ bool sane = true;
+ for (uint8_t i = 0; i < tlv_len; i++) {
+ if ((unsigned char)tlvs->hostname[i] > 127
+ || !isprint(tlvs->hostname[i])) {
+ sane = false;
+ tlvs->hostname[i] = '?';
+ }
+ }
+ if (!sane) {
+ sbuf_push(
+ log, indent,
+ "WARNING: Hostname contained non-printable/non-ascii characters.\n");
+ }
+
+ return 0;
+}
+
+/* Functions related to TLVs 236/237 IPv6/MT-IPv6 reach */
+
+static struct isis_item *copy_item_ipv6_reach(struct isis_item *i)
+{
+ struct isis_ipv6_reach *r = (struct isis_ipv6_reach *)i;
+ struct isis_ipv6_reach *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ rv->metric = r->metric;
+ rv->down = r->down;
+ rv->external = r->external;
+ rv->prefix = r->prefix;
+ rv->subtlvs = copy_subtlvs(r->subtlvs);
+
+ return (struct isis_item *)rv;
+}
+
+static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_ipv6_reach *r = (struct isis_ipv6_reach *)i;
+ char prefixbuf[PREFIX2STR_BUFFER];
+
+ sbuf_push(buf, indent, "%sIPv6 Reachability: %s (Metric: %u)%s%s",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "MT ",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
+ r->metric,
+ r->down ? " Down" : "",
+ r->external ? " External" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
+
+ if (r->subtlvs) {
+ sbuf_push(buf, indent, " Subtlvs:\n");
+ format_subtlvs(r->subtlvs, buf, indent + 4);
+ }
+}
+
+static void free_item_ipv6_reach(struct isis_item *i)
+{
+ struct isis_ipv6_reach *item = (struct isis_ipv6_reach *)i;
+
+ isis_free_subtlvs(item->subtlvs);
+ XFREE(MTYPE_ISIS_TLV, item);
+}
+
+static int pack_item_ipv6_reach(struct isis_item *i, struct stream *s)
+{
+ struct isis_ipv6_reach *r = (struct isis_ipv6_reach *)i;
+ uint8_t control;
+
+ if (STREAM_WRITEABLE(s) < 6)
+ return 1;
+ stream_putl(s, r->metric);
+
+ control = r->down ? ISIS_IPV6_REACH_DOWN : 0;
+ control |= r->external ? ISIS_IPV6_REACH_EXTERNAL : 0;
+ control |= r->subtlvs ? ISIS_IPV6_REACH_SUBTLV : 0;
+
+ stream_putc(s, control);
+ stream_putc(s, r->prefix.prefixlen);
+
+ if (STREAM_WRITEABLE(s) < (unsigned)PSIZE(r->prefix.prefixlen))
+ return 1;
+ stream_put(s, &r->prefix.prefix.s6_addr, PSIZE(r->prefix.prefixlen));
+
+ if (r->subtlvs)
+ return pack_subtlvs(r->subtlvs, s);
+
+ return 0;
+}
+
+static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+ struct isis_ipv6_reach *rv = NULL;
+ size_t consume;
+ uint8_t control, subtlv_len;
+ struct isis_item_list *items;
+
+ if (mtid == ISIS_MT_IPV4_UNICAST) {
+ items = &tlvs->ipv6_reach;
+ } else {
+ items = isis_get_mt_items(&tlvs->mt_ipv6_reach, mtid);
+ }
+
+ sbuf_push(log, indent, "Unpacking %sIPv6 reachability...\n",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "mt ");
+ consume = 6;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Not enough data left. (expected 6 or more bytes, got %"
+ PRIu8 ")\n",
+ len);
+ goto out;
+ }
+
+ rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->metric = stream_getl(s);
+ control = stream_getc(s);
+ rv->down = (control & ISIS_IPV6_REACH_DOWN);
+ rv->external = (control & ISIS_IPV6_REACH_EXTERNAL);
+
+ rv->prefix.family = AF_INET6;
+ rv->prefix.prefixlen = stream_getc(s);
+ if (rv->prefix.prefixlen > 128) {
+ sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv6\n",
+ rv->prefix.prefixlen);
+ goto out;
+ }
+
+ consume += PSIZE(rv->prefix.prefixlen);
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected %u bytes of prefix, but only %u bytes available.\n",
+ PSIZE(rv->prefix.prefixlen), len - 6);
+ goto out;
+ }
+ stream_get(&rv->prefix.prefix.s6_addr, s, PSIZE(rv->prefix.prefixlen));
+ struct in6_addr orig_prefix = rv->prefix.prefix;
+ apply_mask_ipv6(&rv->prefix);
+ if (memcmp(&orig_prefix, &rv->prefix.prefix, sizeof(orig_prefix)))
+ sbuf_push(log, indent + 2,
+ "WARNING: Prefix had hostbits set.\n");
+ format_item_ipv6_reach(mtid, (struct isis_item *)rv, log, indent + 2);
+
+ if (control & ISIS_IPV6_REACH_SUBTLV) {
+ consume += 1;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected 1 byte of subtlv len, but no more data persent.\n");
+ goto out;
+ }
+ subtlv_len = stream_getc(s);
+
+ if (!subtlv_len) {
+ sbuf_push(log, indent + 2,
+ " WARNING: subtlv bit set, but there are no subtlvs.\n");
+ }
+ consume += subtlv_len;
+ if (len < consume) {
+ sbuf_push(log, indent,
+ "Expected %" PRIu8
+ " bytes of subtlvs, but only %u bytes available.\n",
+ subtlv_len,
+ len - 6 - PSIZE(rv->prefix.prefixlen));
+ goto out;
+ }
+
+ rv->subtlvs = isis_alloc_subtlvs();
+ if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH, subtlv_len, s,
+ log, rv->subtlvs, indent + 4)) {
+ goto out;
+ }
+ }
+
+ append_item(items, (struct isis_item *)rv);
+ return 0;
+out:
+ if (rv)
+ free_item_ipv6_reach((struct isis_item *)rv);
+ return 1;
+}
+
+/* Functions related to TLV 10 Authentication */
+static struct isis_item *copy_item_auth(struct isis_item *i)
+{
+ struct isis_auth *auth = (struct isis_auth *)i;
+ struct isis_auth *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->type = auth->type;
+ rv->length = auth->length;
+ memcpy(rv->value, auth->value, sizeof(rv->value));
+ return (struct isis_item *)rv;
+}
+
+static void format_item_auth(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_auth *auth = (struct isis_auth *)i;
+ char obuf[768];
+
+ sbuf_push(buf, indent, "Authentication:\n");
+ switch (auth->type) {
+ case ISIS_PASSWD_TYPE_CLEARTXT:
+ zlog_sanitize(obuf, sizeof(obuf), auth->value, auth->length);
+ sbuf_push(buf, indent, " Password: %s\n", obuf);
+ break;
+ case ISIS_PASSWD_TYPE_HMAC_MD5:
+ for (unsigned int i = 0; i < 16; i++) {
+ snprintf(obuf + 2 * i, sizeof(obuf) - 2 * i,
+ "%02" PRIx8, auth->value[i]);
+ }
+ sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf);
+ break;
+ default:
+ sbuf_push(buf, indent, " Unknown (%" PRIu8 ")\n", auth->type);
+ break;
+ };
+}
+
+static void free_item_auth(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_auth(struct isis_item *i, struct stream *s)
+{
+ struct isis_auth *auth = (struct isis_auth *)i;
+
+ if (STREAM_WRITEABLE(s) < 1)
+ return 1;
+ stream_putc(s, auth->type);
+
+ switch (auth->type) {
+ case ISIS_PASSWD_TYPE_CLEARTXT:
+ if (STREAM_WRITEABLE(s) < auth->length)
+ return 1;
+ stream_put(s, auth->passwd, auth->length);
+ break;
+ case ISIS_PASSWD_TYPE_HMAC_MD5:
+ if (STREAM_WRITEABLE(s) < 16)
+ return 1;
+ auth->offset = stream_get_endp(s);
+ stream_put(s, NULL, 16);
+ break;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+static int unpack_item_auth(uint16_t mtid, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack Auth TLV...\n");
+ if (len < 1) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 1 bytes of auth type, got %" PRIu8
+ ")\n",
+ len);
+ return 1;
+ }
+
+ struct isis_auth *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->type = stream_getc(s);
+ rv->length = len - 1;
+
+ if (rv->type == ISIS_PASSWD_TYPE_HMAC_MD5 && rv->length != 16) {
+ sbuf_push(
+ log, indent,
+ "Unexpected auth length for HMAC-MD5 (expected 16, got %" PRIu8
+ ")\n",
+ rv->length);
+ XFREE(MTYPE_ISIS_TLV, rv);
+ return 1;
+ }
+
+ rv->offset = stream_get_getp(s);
+ stream_get(rv->value, s, rv->length);
+ format_item_auth(mtid, (struct isis_item *)rv, log, indent + 2);
+ append_item(&tlvs->isis_auth, (struct isis_item *)rv);
+ return 0;
+}
+
+/* Functions relating to item TLVs */
+
+static void init_item_list(struct isis_item_list *items)
+{
+ items->head = NULL;
+ items->tail = &items->head;
+ items->count = 0;
+}
+
+static struct isis_item *copy_item(enum isis_tlv_context context,
+ enum isis_tlv_type type,
+ struct isis_item *item)
+{
+ const struct tlv_ops *ops = tlv_table[context][type];
+
+ if (ops && ops->copy_item)
+ return ops->copy_item(item);
+
+ assert(!"Unknown item tlv type!");
+ return NULL;
+}
+
+static void copy_items(enum isis_tlv_context context, enum isis_tlv_type type,
+ struct isis_item_list *src, struct isis_item_list *dest)
+{
+ struct isis_item *item;
+
+ init_item_list(dest);
+
+ for (item = src->head; item; item = item->next) {
+ append_item(dest, copy_item(context, type, item));
+ }
+}
+
+static void format_item(uint16_t mtid, enum isis_tlv_context context,
+ enum isis_tlv_type type, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ const struct tlv_ops *ops = tlv_table[context][type];
+
+ if (ops && ops->format_item) {
+ ops->format_item(mtid, i, buf, indent);
+ return;
+ }
+
+ assert(!"Unknown item tlv type!");
+}
+
+static void format_items_(uint16_t mtid, enum isis_tlv_context context,
+ enum isis_tlv_type type, struct isis_item_list *items,
+ struct sbuf *buf, int indent)
+{
+ struct isis_item *i;
+
+ for (i = items->head; i; i = i->next)
+ format_item(mtid, context, type, i, buf, indent);
+}
+#define format_items(...) format_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
+
+static void free_item(enum isis_tlv_context tlv_context,
+ enum isis_tlv_type tlv_type, struct isis_item *item)
+{
+ const struct tlv_ops *ops = tlv_table[tlv_context][tlv_type];
+
+ if (ops && ops->free_item) {
+ ops->free_item(item);
+ return;
+ }
+
+ assert(!"Unknown item tlv type!");
+}
+
+static void free_items(enum isis_tlv_context context, enum isis_tlv_type type,
+ struct isis_item_list *items)
+{
+ struct isis_item *item, *next_item;
+
+ for (item = items->head; item; item = next_item) {
+ next_item = item->next;
+ free_item(context, type, item);
+ }
+}
+
+static int pack_item(enum isis_tlv_context context, enum isis_tlv_type type,
+ struct isis_item *i, struct stream *s,
+ struct isis_tlvs **fragment_tlvs,
+ struct pack_order_entry *pe, uint16_t mtid)
+{
+ const struct tlv_ops *ops = tlv_table[context][type];
+
+ if (ops && ops->pack_item) {
+ return ops->pack_item(i, s);
+ }
+
+ assert(!"Unknown item tlv type!");
+ return 1;
+}
+
+static void add_item_to_fragment(struct isis_item *i, struct pack_order_entry *pe,
+ struct isis_tlvs *fragment_tlvs, uint16_t mtid)
+{
+ struct isis_item_list *l;
+
+ if (pe->how_to_pack == ISIS_ITEMS) {
+ l = (struct isis_item_list *)(((char *)fragment_tlvs) + pe->what_to_pack);
+ } else {
+ struct isis_mt_item_list *m;
+ m = (struct isis_mt_item_list *)(((char *)fragment_tlvs) + pe->what_to_pack);
+ l = isis_get_mt_items(m, mtid);
+ }
+
+ append_item(l, copy_item(pe->context, pe->type, i));
+}
+
+static int pack_items_(uint16_t mtid, enum isis_tlv_context context,
+ enum isis_tlv_type type, struct isis_item_list *items,
+ struct stream *s, struct isis_tlvs **fragment_tlvs,
+ struct pack_order_entry *pe,
+ struct isis_tlvs *(*new_fragment)(struct list *l),
+ struct list *new_fragment_arg)
+{
+ size_t len_pos, last_len, len;
+ struct isis_item *item = NULL;
+ int rv;
+
+ if (!items->head)
+ return 0;
+
+top:
+ if (STREAM_WRITEABLE(s) < 2)
+ goto too_long;
+
+ stream_putc(s, type);
+ len_pos = stream_get_endp(s);
+ stream_putc(s, 0); /* Put 0 as length for now */
+
+ if (context == ISIS_CONTEXT_LSP && IS_COMPAT_MT_TLV(type)
+ && mtid != ISIS_MT_IPV4_UNICAST) {
+ if (STREAM_WRITEABLE(s) < 2)
+ goto too_long;
+ stream_putw(s, mtid);
+ }
+
+ if (context == ISIS_CONTEXT_LSP && type == ISIS_TLV_OLDSTYLE_REACH) {
+ if (STREAM_WRITEABLE(s) < 1)
+ goto too_long;
+ stream_putc(s, 0); /* Virtual flag is set to 0 */
+ }
+
+ last_len = len = 0;
+ for (item = item ? item : items->head; item; item = item->next) {
+ rv = pack_item(context, type, item, s, fragment_tlvs, pe, mtid);
+ if (rv)
+ goto too_long;
+
+ len = stream_get_endp(s) - len_pos - 1;
+
+ /* Multiple auths don't go into one TLV, so always break */
+ if (context == ISIS_CONTEXT_LSP && type == ISIS_TLV_AUTH) {
+ item = item->next;
+ break;
+ }
+
+ if (len > 255) {
+ if (!last_len) /* strange, not a single item fit */
+ return 1;
+ /* drop last tlv, otherwise, its too long */
+ stream_set_endp(s, len_pos + 1 + last_len);
+ len = last_len;
+ break;
+ }
+
+ if (fragment_tlvs)
+ add_item_to_fragment(item, pe, *fragment_tlvs, mtid);
+
+ last_len = len;
+ }
+
+ stream_putc_at(s, len_pos, len);
+ if (item)
+ goto top;
+
+ return 0;
+too_long:
+ if (!fragment_tlvs)
+ return 1;
+ stream_reset(s);
+ *fragment_tlvs = new_fragment(new_fragment_arg);
+ goto top;
+}
+#define pack_items(...) pack_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
+
+static void append_item(struct isis_item_list *dest, struct isis_item *item)
+{
+ *dest->tail = item;
+ dest->tail = &(*dest->tail)->next;
+ dest->count++;
+}
+
+static int unpack_item(uint16_t mtid, enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent)
+{
+ const struct tlv_ops *ops = tlv_table[context][tlv_type];
+
+ if (ops && ops->unpack_item)
+ return ops->unpack_item(mtid, len, s, log, dest, indent);
+
+ assert(!"Unknown item tlv type!");
+ sbuf_push(log, indent, "Unknown item tlv type!\n");
+ return 1;
+}
+
+static int unpack_tlv_with_items(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log, void *dest,
+ int indent)
+{
+ size_t tlv_start;
+ size_t tlv_pos;
+ int rv;
+ uint16_t mtid;
+
+ tlv_start = stream_get_getp(s);
+ tlv_pos = 0;
+
+ if (context == ISIS_CONTEXT_LSP && IS_COMPAT_MT_TLV(tlv_type)) {
+ if (tlv_len < 2) {
+ sbuf_push(log, indent,
+ "TLV is too short to contain MTID\n");
+ return 1;
+ }
+ mtid = stream_getw(s) & ISIS_MT_MASK;
+ tlv_pos += 2;
+ sbuf_push(log, indent, "Unpacking as MT %s item TLV...\n",
+ isis_mtid2str(mtid));
+ } else {
+ sbuf_push(log, indent, "Unpacking as item TLV...\n");
+ mtid = ISIS_MT_IPV4_UNICAST;
+ }
+
+ if (context == ISIS_CONTEXT_LSP
+ && tlv_type == ISIS_TLV_OLDSTYLE_REACH) {
+ if (tlv_len - tlv_pos < 1) {
+ sbuf_push(log, indent,
+ "TLV is too short for old style reach\n");
+ return 1;
+ }
+ stream_forward_getp(s, 1);
+ tlv_pos += 1;
+ }
+
+ if (context == ISIS_CONTEXT_LSP
+ && tlv_type == ISIS_TLV_OLDSTYLE_IP_REACH) {
+ struct isis_tlvs *tlvs = dest;
+ dest = &tlvs->oldstyle_ip_reach;
+ } else if (context == ISIS_CONTEXT_LSP
+ && tlv_type == ISIS_TLV_OLDSTYLE_IP_REACH_EXT) {
+ struct isis_tlvs *tlvs = dest;
+ dest = &tlvs->oldstyle_ip_reach_ext;
+ }
+
+ if (context == ISIS_CONTEXT_LSP
+ && tlv_type == ISIS_TLV_MT_ROUTER_INFO) {
+ struct isis_tlvs *tlvs = dest;
+ tlvs->mt_router_info_empty = (tlv_pos >= (size_t)tlv_len);
+ }
+
+ while (tlv_pos < (size_t)tlv_len) {
+ rv = unpack_item(mtid, context, tlv_type, tlv_len - tlv_pos, s,
+ log, dest, indent + 2);
+ if (rv)
+ return rv;
+
+ tlv_pos = stream_get_getp(s) - tlv_start;
+ }
+
+ return 0;
+}
+
+/* Functions to manipulate mt_item_lists */
+
+static int isis_mt_item_list_cmp(const struct isis_item_list *a,
+ const struct isis_item_list *b)
+{
+ if (a->mtid < b->mtid)
+ return -1;
+ if (a->mtid > b->mtid)
+ return 1;
+ return 0;
+}
+
+RB_PROTOTYPE(isis_mt_item_list, isis_item_list, mt_tree, isis_mt_item_list_cmp);
+RB_GENERATE(isis_mt_item_list, isis_item_list, mt_tree, isis_mt_item_list_cmp);
+
+struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
+ uint16_t mtid)
+{
+ struct isis_item_list *rv;
+
+ rv = isis_lookup_mt_items(m, mtid);
+ if (!rv) {
+ rv = XCALLOC(MTYPE_ISIS_MT_ITEM_LIST, sizeof(*rv));
+ init_item_list(rv);
+ rv->mtid = mtid;
+ RB_INSERT(isis_mt_item_list, m, rv);
+ }
+
+ return rv;
+}
+
+struct isis_item_list *isis_lookup_mt_items(struct isis_mt_item_list *m,
+ uint16_t mtid)
+{
+ struct isis_item_list key = {.mtid = mtid};
+
+ return RB_FIND(isis_mt_item_list, m, &key);
+}
+
+static void free_mt_items(enum isis_tlv_context context,
+ enum isis_tlv_type type, struct isis_mt_item_list *m)
+{
+ struct isis_item_list *n, *nnext;
+
+ RB_FOREACH_SAFE(n, isis_mt_item_list, m, nnext)
+ {
+ free_items(context, type, n);
+ RB_REMOVE(isis_mt_item_list, m, n);
+ XFREE(MTYPE_ISIS_MT_ITEM_LIST, n);
+ }
+}
+
+static void format_mt_items(enum isis_tlv_context context,
+ enum isis_tlv_type type,
+ struct isis_mt_item_list *m, struct sbuf *buf,
+ int indent)
+{
+ struct isis_item_list *n;
+
+ RB_FOREACH(n, isis_mt_item_list, m)
+ {
+ format_items_(n->mtid, context, type, n, buf, indent);
+ }
+}
+
+static int pack_mt_items(enum isis_tlv_context context, enum isis_tlv_type type,
+ struct isis_mt_item_list *m, struct stream *s,
+ struct isis_tlvs **fragment_tlvs,
+ struct pack_order_entry *pe,
+ struct isis_tlvs *(*new_fragment)(struct list *l),
+ struct list *new_fragment_arg)
+{
+ struct isis_item_list *n;
+
+ RB_FOREACH(n, isis_mt_item_list, m)
+ {
+ int rv;
+
+ rv = pack_items_(n->mtid, context, type, n, s, fragment_tlvs,
+ pe, new_fragment, new_fragment_arg);
+ if (rv)
+ return rv;
+ }
+
+ return 0;
+}
+
+static void copy_mt_items(enum isis_tlv_context context,
+ enum isis_tlv_type type,
+ struct isis_mt_item_list *src,
+ struct isis_mt_item_list *dest)
+{
+ struct isis_item_list *n;
+
+ RB_INIT(isis_mt_item_list, dest);
+
+ RB_FOREACH(n, isis_mt_item_list, src)
+ {
+ copy_items(context, type, n, isis_get_mt_items(dest, n->mtid));
+ }
+}
+
+/* Functions related to tlvs in general */
+
+struct isis_tlvs *isis_alloc_tlvs(void)
+{
+ struct isis_tlvs *result;
+
+ result = XCALLOC(MTYPE_ISIS_TLV, sizeof(*result));
+
+ init_item_list(&result->isis_auth);
+ init_item_list(&result->area_addresses);
+ init_item_list(&result->mt_router_info);
+ init_item_list(&result->oldstyle_reach);
+ init_item_list(&result->lan_neighbor);
+ init_item_list(&result->lsp_entries);
+ init_item_list(&result->extended_reach);
+ RB_INIT(isis_mt_item_list, &result->mt_reach);
+ init_item_list(&result->oldstyle_ip_reach);
+ init_item_list(&result->oldstyle_ip_reach_ext);
+ init_item_list(&result->ipv4_address);
+ init_item_list(&result->ipv6_address);
+ init_item_list(&result->extended_ip_reach);
+ RB_INIT(isis_mt_item_list, &result->mt_ip_reach);
+ init_item_list(&result->ipv6_reach);
+ RB_INIT(isis_mt_item_list, &result->mt_ipv6_reach);
+
+ return result;
+}
+
+struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
+{
+ struct isis_tlvs *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth,
+ &rv->isis_auth);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
+ &tlvs->area_addresses, &rv->area_addresses);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
+ &tlvs->mt_router_info, &rv->mt_router_info);
+
+ tlvs->mt_router_info_empty = rv->mt_router_info_empty;
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_REACH,
+ &tlvs->oldstyle_reach, &rv->oldstyle_reach);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_LAN_NEIGHBORS,
+ &tlvs->lan_neighbor, &rv->lan_neighbor);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_LSP_ENTRY, &tlvs->lsp_entries,
+ &rv->lsp_entries);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
+ &tlvs->extended_reach, &rv->extended_reach);
+
+ copy_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_REACH, &tlvs->mt_reach,
+ &rv->mt_reach);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH,
+ &tlvs->oldstyle_ip_reach, &rv->oldstyle_ip_reach);
+
+ copy_tlv_protocols_supported(&tlvs->protocols_supported,
+ &rv->protocols_supported);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH_EXT,
+ &tlvs->oldstyle_ip_reach_ext, &rv->oldstyle_ip_reach_ext);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV4_ADDRESS, &tlvs->ipv4_address,
+ &rv->ipv4_address);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS, &tlvs->ipv6_address,
+ &rv->ipv6_address);
+
+ rv->te_router_id = copy_tlv_te_router_id(tlvs->te_router_id);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
+ &tlvs->extended_ip_reach, &rv->extended_ip_reach);
+
+ copy_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
+ &tlvs->mt_ip_reach, &rv->mt_ip_reach);
+
+ rv->hostname = copy_tlv_dynamic_hostname(tlvs->hostname);
+
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach,
+ &rv->ipv6_reach);
+
+ copy_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
+ &tlvs->mt_ipv6_reach, &rv->mt_ipv6_reach);
+
+ return rv;
+}
+
+static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
+{
+ format_tlv_protocols_supported(&tlvs->protocols_supported, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth, buf,
+ indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
+ &tlvs->area_addresses, buf, indent);
+
+ if (tlvs->mt_router_info_empty) {
+ sbuf_push(buf, indent, "MT Router Info: None\n");
+ } else {
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
+ &tlvs->mt_router_info, buf, indent);
+ }
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_REACH,
+ &tlvs->oldstyle_reach, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_LAN_NEIGHBORS,
+ &tlvs->lan_neighbor, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_LSP_ENTRY, &tlvs->lsp_entries,
+ buf, indent);
+
+ format_tlv_dynamic_hostname(tlvs->hostname, buf, indent);
+ format_tlv_te_router_id(tlvs->te_router_id, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
+ &tlvs->extended_reach, buf, indent);
+
+ format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_REACH, &tlvs->mt_reach,
+ buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH,
+ &tlvs->oldstyle_ip_reach, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH_EXT,
+ &tlvs->oldstyle_ip_reach_ext, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV4_ADDRESS,
+ &tlvs->ipv4_address, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
+ &tlvs->ipv6_address, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
+ &tlvs->extended_ip_reach, buf, indent);
+
+ format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
+ &tlvs->mt_ip_reach, buf, indent);
+
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach,
+ buf, indent);
+
+ format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
+ &tlvs->mt_ipv6_reach, buf, indent);
+}
+
+const char *isis_format_tlvs(struct isis_tlvs *tlvs)
+{
+ static struct sbuf buf;
+
+ if (!sbuf_buf(&buf))
+ sbuf_init(&buf, NULL, 0);
+
+ sbuf_reset(&buf);
+ format_tlvs(tlvs, &buf, 0);
+ return sbuf_buf(&buf);
+}
+
+void isis_free_tlvs(struct isis_tlvs *tlvs)
+{
+ if (!tlvs)
+ return;
+
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
+ &tlvs->area_addresses);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
+ &tlvs->mt_router_info);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_REACH,
+ &tlvs->oldstyle_reach);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_LAN_NEIGHBORS,
+ &tlvs->lan_neighbor);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_LSP_ENTRY, &tlvs->lsp_entries);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
+ &tlvs->extended_reach);
+ free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_REACH, &tlvs->mt_reach);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH,
+ &tlvs->oldstyle_ip_reach);
+ free_tlv_protocols_supported(&tlvs->protocols_supported);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH_EXT,
+ &tlvs->oldstyle_ip_reach_ext);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV4_ADDRESS,
+ &tlvs->ipv4_address);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
+ &tlvs->ipv6_address);
+ free_tlv_te_router_id(tlvs->te_router_id);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
+ &tlvs->extended_ip_reach);
+ free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
+ &tlvs->mt_ip_reach);
+ free_tlv_dynamic_hostname(tlvs->hostname);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach);
+ free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
+ &tlvs->mt_ipv6_reach);
+
+ XFREE(MTYPE_ISIS_TLV, tlvs);
+}
+
+static void add_padding(struct stream *s)
+{
+ while (STREAM_WRITEABLE(s)) {
+ if (STREAM_WRITEABLE(s) == 1)
+ break;
+ uint32_t padding_len = STREAM_WRITEABLE(s) - 2;
+
+ if (padding_len > 255) {
+ if (padding_len == 256)
+ padding_len = 254;
+ else
+ padding_len = 255;
+ }
+
+ stream_putc(s, ISIS_TLV_PADDING);
+ stream_putc(s, padding_len);
+ stream_put(s, NULL, padding_len);
+ }
+}
+
+#define LSP_REM_LIFETIME_OFF 10
+#define LSP_CHECKSUM_OFF 24
+static void safe_auth_md5(struct stream *s, uint16_t *checksum,
+ uint16_t *rem_lifetime)
+{
+ memcpy(rem_lifetime, STREAM_DATA(s) + LSP_REM_LIFETIME_OFF,
+ sizeof(*rem_lifetime));
+ memset(STREAM_DATA(s) + LSP_REM_LIFETIME_OFF, 0, sizeof(*rem_lifetime));
+ memcpy(checksum, STREAM_DATA(s) + LSP_CHECKSUM_OFF, sizeof(*checksum));
+ memset(STREAM_DATA(s) + LSP_CHECKSUM_OFF, 0, sizeof(*checksum));
+}
+
+static void restore_auth_md5(struct stream *s, uint16_t checksum,
+ uint16_t rem_lifetime)
+{
+ memcpy(STREAM_DATA(s) + LSP_REM_LIFETIME_OFF, &rem_lifetime,
+ sizeof(rem_lifetime));
+ memcpy(STREAM_DATA(s) + LSP_CHECKSUM_OFF, &checksum, sizeof(checksum));
+}
+
+static void update_auth_hmac_md5(struct isis_auth *auth, struct stream *s,
+ bool is_lsp)
+{
+ uint8_t digest[16];
+ uint16_t checksum, rem_lifetime;
+
+ if (is_lsp)
+ safe_auth_md5(s, &checksum, &rem_lifetime);
+
+ memset(STREAM_DATA(s) + auth->offset, 0, 16);
+ hmac_md5(STREAM_DATA(s), stream_get_endp(s), auth->passwd,
+ auth->plength, digest);
+ memcpy(auth->value, digest, 16);
+ memcpy(STREAM_DATA(s) + auth->offset, digest, 16);
+
+ if (is_lsp)
+ restore_auth_md5(s, checksum, rem_lifetime);
+}
+
+static void update_auth(struct isis_tlvs *tlvs, struct stream *s, bool is_lsp)
+{
+ struct isis_auth *auth_head = (struct isis_auth *)tlvs->isis_auth.head;
+
+ for (struct isis_auth *auth = auth_head; auth; auth = auth->next) {
+ if (auth->type == ISIS_PASSWD_TYPE_HMAC_MD5)
+ update_auth_hmac_md5(auth, s, is_lsp);
+ }
+}
+
+static int handle_pack_entry(struct pack_order_entry *pe,
+ struct isis_tlvs *tlvs, struct stream *stream,
+ struct isis_tlvs **fragment_tlvs,
+ struct isis_tlvs *(*new_fragment)(struct list *l),
+ struct list *new_fragment_arg)
+{
+ int rv;
+
+ if (pe->how_to_pack == ISIS_ITEMS) {
+ struct isis_item_list *l;
+ l = (struct isis_item_list *)(((char *)tlvs)
+ + pe->what_to_pack);
+ rv = pack_items(pe->context, pe->type, l, stream, fragment_tlvs,
+ pe, new_fragment, new_fragment_arg);
+ } else {
+ struct isis_mt_item_list *l;
+ l = (struct isis_mt_item_list *)(((char *)tlvs)
+ + pe->what_to_pack);
+ rv = pack_mt_items(pe->context, pe->type, l, stream,
+ fragment_tlvs, pe, new_fragment,
+ new_fragment_arg);
+ }
+
+ return rv;
+}
+
+static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
+ struct isis_tlvs *fragment_tlvs,
+ struct isis_tlvs *(*new_fragment)(struct list *l),
+ struct list *new_fragment_arg)
+{
+ int rv;
+
+ /* When fragmenting, don't add auth as it's already accounted for in the
+ * size we are given. */
+ if (!fragment_tlvs) {
+ rv = pack_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth,
+ stream, NULL, NULL, NULL, NULL);
+ if (rv)
+ return rv;
+ }
+
+ rv = pack_tlv_protocols_supported(&tlvs->protocols_supported, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ copy_tlv_protocols_supported(
+ &tlvs->protocols_supported,
+ &fragment_tlvs->protocols_supported);
+ }
+
+ rv = pack_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
+ &tlvs->area_addresses, stream, NULL, NULL, NULL, NULL);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
+ &tlvs->area_addresses,
+ &fragment_tlvs->area_addresses);
+ }
+
+
+ if (tlvs->mt_router_info_empty) {
+ if (STREAM_WRITEABLE(stream) < 2)
+ return 1;
+ stream_putc(stream, ISIS_TLV_MT_ROUTER_INFO);
+ stream_putc(stream, 0);
+ if (fragment_tlvs)
+ fragment_tlvs->mt_router_info_empty = true;
+ } else {
+ rv = pack_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
+ &tlvs->mt_router_info, stream, NULL, NULL, NULL,
+ NULL);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
+ &tlvs->mt_router_info,
+ &fragment_tlvs->mt_router_info);
+ }
+ }
+
+ rv = pack_tlv_dynamic_hostname(tlvs->hostname, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs)
+ fragment_tlvs->hostname =
+ copy_tlv_dynamic_hostname(tlvs->hostname);
+
+ rv = pack_tlv_te_router_id(tlvs->te_router_id, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ fragment_tlvs->te_router_id =
+ copy_tlv_te_router_id(tlvs->te_router_id);
+ }
+
+ for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
+ pack_idx++) {
+ rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
+ fragment_tlvs ? &fragment_tlvs : NULL,
+ new_fragment, new_fragment_arg);
+
+ if (rv)
+ return rv;
+ }
+
+ return 0;
+}
+
+int isis_pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
+ size_t len_pointer, bool pad, bool is_lsp)
+{
+ int rv;
+
+ rv = pack_tlvs(tlvs, stream, NULL, NULL, NULL);
+ if (rv)
+ return rv;
+
+ if (pad)
+ add_padding(stream);
+
+ if (len_pointer != (size_t)-1) {
+ stream_putw_at(stream, len_pointer, stream_get_endp(stream));
+ }
+
+ update_auth(tlvs, stream, is_lsp);
+
+ return 0;
+}
+
+static struct isis_tlvs *new_fragment(struct list *l)
+{
+ struct isis_tlvs *rv = isis_alloc_tlvs();
+
+ listnode_add(l, rv);
+ return rv;
+}
+
+struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size)
+{
+ struct stream *dummy_stream = stream_new(size);
+ struct list *rv = list_new();
+ struct isis_tlvs *fragment_tlvs = new_fragment(rv);
+
+ if (pack_tlvs(tlvs, dummy_stream, fragment_tlvs, new_fragment, rv)) {
+ struct listnode *node;
+ for (ALL_LIST_ELEMENTS_RO(rv, node, fragment_tlvs))
+ isis_free_tlvs(fragment_tlvs);
+ list_delete(rv);
+ rv = NULL;
+ }
+
+ stream_free(dummy_stream);
+ return rv;
+}
+
+static int unpack_tlv_unknown(enum isis_tlv_context context, uint8_t tlv_type,
+ uint8_t tlv_len, struct stream *s,
+ struct sbuf *log, int indent)
+{
+ stream_forward_getp(s, tlv_len);
+ sbuf_push(log, indent,
+ "Skipping unknown TLV %" PRIu8 " (%" PRIu8 " bytes)\n",
+ tlv_type, tlv_len);
+ return 0;
+}
+
+static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
+ struct stream *stream, struct sbuf *log, void *dest,
+ int indent)
+{
+ uint8_t tlv_type, tlv_len;
+ const struct tlv_ops *ops;
+
+ sbuf_push(log, indent, "Unpacking TLV...\n");
+
+ if (avail_len < 2) {
+ sbuf_push(
+ log, indent + 2,
+ "Available data %zu too short to contain a TLV header.\n",
+ avail_len);
+ return 1;
+ }
+
+ tlv_type = stream_getc(stream);
+ tlv_len = stream_getc(stream);
+
+ sbuf_push(log, indent + 2,
+ "Found TLV of type %" PRIu8 " and len %" PRIu8 ".\n",
+ tlv_type, tlv_len);
+
+ if (avail_len < ((size_t)tlv_len) + 2) {
+ sbuf_push(log, indent + 2,
+ "Available data %zu too short for claimed TLV len %" PRIu8 ".\n",
+ avail_len - 2, tlv_len);
+ return 1;
+ }
+
+ ops = tlv_table[context][tlv_type];
+ if (ops && ops->unpack) {
+ return ops->unpack(context, tlv_type, tlv_len, stream, log,
+ dest, indent + 2);
+ }
+
+ return unpack_tlv_unknown(context, tlv_type, tlv_len, stream, log,
+ indent + 2);
+}
+
+static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
+ struct stream *stream, struct sbuf *log, void *dest,
+ int indent)
+{
+ int rv;
+ size_t tlv_start, tlv_pos;
+
+ tlv_start = stream_get_getp(stream);
+ tlv_pos = 0;
+
+ sbuf_push(log, indent, "Unpacking %zu bytes of %s...\n", avail_len,
+ (context == ISIS_CONTEXT_LSP) ? "TLVs" : "sub-TLVs");
+
+ while (tlv_pos < avail_len) {
+ rv = unpack_tlv(context, avail_len - tlv_pos, stream, log, dest,
+ indent + 2);
+ if (rv)
+ return rv;
+
+ tlv_pos = stream_get_getp(stream) - tlv_start;
+ }
+
+ return 0;
+}
+
+int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
+ struct isis_tlvs **dest, const char **log)
+{
+ static struct sbuf logbuf;
+ int indent = 0;
+ int rv;
+ struct isis_tlvs *result;
+
+ if (!sbuf_buf(&logbuf))
+ sbuf_init(&logbuf, NULL, 0);
+
+ sbuf_reset(&logbuf);
+ if (avail_len > STREAM_READABLE(stream)) {
+ sbuf_push(&logbuf, indent,
+ "Stream doesn't contain sufficient data. "
+ "Claimed %zu, available %zu\n",
+ avail_len, STREAM_READABLE(stream));
+ return 1;
+ }
+
+ result = isis_alloc_tlvs();
+ rv = unpack_tlvs(ISIS_CONTEXT_LSP, avail_len, stream, &logbuf, result,
+ indent);
+
+ *log = sbuf_buf(&logbuf);
+ *dest = result;
+
+ return rv;
+}
+
+#define TLV_OPS(_name_, _desc_) \
+ static const struct tlv_ops tlv_##_name_##_ops = { \
+ .name = _desc_, .unpack = unpack_tlv_##_name_, \
+ }
+
+#define ITEM_TLV_OPS(_name_, _desc_) \
+ static const struct tlv_ops tlv_##_name_##_ops = { \
+ .name = _desc_, \
+ .unpack = unpack_tlv_with_items, \
+ \
+ .pack_item = pack_item_##_name_, \
+ .free_item = free_item_##_name_, \
+ .unpack_item = unpack_item_##_name_, \
+ .format_item = format_item_##_name_, \
+ .copy_item = copy_item_##_name_}
+
+#define SUBTLV_OPS(_name_, _desc_) \
+ static const struct tlv_ops subtlv_##_name_##_ops = { \
+ .name = _desc_, .unpack = unpack_subtlv_##_name_, \
+ }
+
+ITEM_TLV_OPS(area_address, "TLV 1 Area Addresses");
+ITEM_TLV_OPS(oldstyle_reach, "TLV 2 IS Reachability");
+ITEM_TLV_OPS(lan_neighbor, "TLV 6 LAN Neighbors");
+ITEM_TLV_OPS(lsp_entry, "TLV 9 LSP Entries");
+ITEM_TLV_OPS(auth, "TLV 10 IS-IS Auth");
+ITEM_TLV_OPS(extended_reach, "TLV 22 Extended Reachability");
+ITEM_TLV_OPS(oldstyle_ip_reach, "TLV 128/130 IP Reachability");
+TLV_OPS(protocols_supported, "TLV 129 Protocols Supported");
+ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
+TLV_OPS(te_router_id, "TLV 134 TE Router ID");
+ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
+TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
+ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
+ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
+ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
+
+SUBTLV_OPS(ipv6_source_prefix, "Sub-TLV 22 IPv6 Source Prefix");
+
+static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
+ [ISIS_CONTEXT_LSP] = {
+ [ISIS_TLV_AREA_ADDRESSES] = &tlv_area_address_ops,
+ [ISIS_TLV_OLDSTYLE_REACH] = &tlv_oldstyle_reach_ops,
+ [ISIS_TLV_LAN_NEIGHBORS] = &tlv_lan_neighbor_ops,
+ [ISIS_TLV_LSP_ENTRY] = &tlv_lsp_entry_ops,
+ [ISIS_TLV_AUTH] = &tlv_auth_ops,
+ [ISIS_TLV_EXTENDED_REACH] = &tlv_extended_reach_ops,
+ [ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
+ [ISIS_TLV_OLDSTYLE_IP_REACH] = &tlv_oldstyle_ip_reach_ops,
+ [ISIS_TLV_PROTOCOLS_SUPPORTED] = &tlv_protocols_supported_ops,
+ [ISIS_TLV_OLDSTYLE_IP_REACH_EXT] = &tlv_oldstyle_ip_reach_ops,
+ [ISIS_TLV_IPV4_ADDRESS] = &tlv_ipv4_address_ops,
+ [ISIS_TLV_TE_ROUTER_ID] = &tlv_te_router_id_ops,
+ [ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
+ [ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
+ [ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
+ [ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
+ [ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
+ [ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
+ [ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
+ },
+ [ISIS_CONTEXT_SUBTLV_NE_REACH] = {},
+ [ISIS_CONTEXT_SUBTLV_IP_REACH] = {},
+ [ISIS_CONTEXT_SUBTLV_IPV6_REACH] = {
+ [ISIS_SUBTLV_IPV6_SOURCE_PREFIX] = &subtlv_ipv6_source_prefix_ops,
+ }
+};
+
+/* Accessor functions */
+
+void isis_tlvs_add_auth(struct isis_tlvs *tlvs, struct isis_passwd *passwd)
+{
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth);
+ init_item_list(&tlvs->isis_auth);
+
+ if (passwd->type == ISIS_PASSWD_TYPE_UNUSED)
+ return;
+
+ struct isis_auth *auth = XCALLOC(MTYPE_ISIS_TLV, sizeof(*auth));
+
+ auth->type = passwd->type;
+
+ auth->plength = passwd->len;
+ memcpy(auth->passwd, passwd->passwd,
+ MIN(sizeof(auth->passwd), sizeof(passwd->passwd)));
+
+ if (auth->type == ISIS_PASSWD_TYPE_CLEARTXT) {
+ auth->length = passwd->len;
+ memcpy(auth->value, passwd->passwd,
+ MIN(sizeof(auth->value), sizeof(passwd->passwd)));
+ }
+
+ append_item(&tlvs->isis_auth, (struct isis_item *)auth);
+}
+
+void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct listnode *node;
+ struct area_addr *area_addr;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, area_addr)) {
+ struct isis_area_address *a =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
+
+ a->len = area_addr->addr_len;
+ memcpy(a->addr, area_addr->area_addr, 20);
+ append_item(&tlvs->area_addresses, (struct isis_item *)a);
+ }
+}
+
+void isis_tlvs_add_lan_neighbors(struct isis_tlvs *tlvs, struct list *neighbors)
+{
+ struct listnode *node;
+ u_char *snpa;
+
+ for (ALL_LIST_ELEMENTS_RO(neighbors, node, snpa)) {
+ struct isis_lan_neighbor *n =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*n));
+
+ memcpy(n->mac, snpa, 6);
+ append_item(&tlvs->lan_neighbor, (struct isis_item *)n);
+ }
+}
+
+void isis_tlvs_set_protocols_supported(struct isis_tlvs *tlvs,
+ struct nlpids *nlpids)
+{
+ tlvs->protocols_supported.count = nlpids->count;
+ if (tlvs->protocols_supported.protocols)
+ XFREE(MTYPE_ISIS_TLV, tlvs->protocols_supported.protocols);
+ if (nlpids->count) {
+ tlvs->protocols_supported.protocols =
+ XCALLOC(MTYPE_ISIS_TLV, nlpids->count);
+ memcpy(tlvs->protocols_supported.protocols, nlpids->nlpids,
+ nlpids->count);
+ } else {
+ tlvs->protocols_supported.protocols = NULL;
+ }
+}
+
+void isis_tlvs_add_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid,
+ bool overload, bool attached)
+{
+ struct isis_mt_router_info *i = XCALLOC(MTYPE_ISIS_TLV, sizeof(*i));
+
+ i->overload = overload;
+ i->attached = attached;
+ i->mtid = mtid;
+ append_item(&tlvs->mt_router_info, (struct isis_item *)i);
+}
+
+void isis_tlvs_add_ipv4_address(struct isis_tlvs *tlvs, struct in_addr *addr)
+{
+ struct isis_ipv4_address *a = XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
+ a->addr = *addr;
+ append_item(&tlvs->ipv4_address, (struct isis_item *)a);
+}
+
+
+void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct listnode *node;
+ struct prefix_ipv4 *ip_addr;
+ unsigned int addr_count = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, ip_addr)) {
+ isis_tlvs_add_ipv4_address(tlvs, &ip_addr->prefix);
+ addr_count++;
+ if (addr_count >= 63)
+ break;
+ }
+}
+
+void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct listnode *node;
+ struct prefix_ipv6 *ip_addr;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, ip_addr)) {
+ struct isis_ipv6_address *a =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
+
+ a->addr = ip_addr->prefix;
+ append_item(&tlvs->ipv6_address, (struct isis_item *)a);
+ }
+}
+
+typedef bool (*auth_validator_func)(struct isis_passwd *passwd,
+ struct stream *stream,
+ struct isis_auth *auth, bool is_lsp);
+
+static bool auth_validator_cleartxt(struct isis_passwd *passwd,
+ struct stream *stream,
+ struct isis_auth *auth, bool is_lsp)
+{
+ return (auth->length == passwd->len
+ && !memcmp(auth->value, passwd->passwd, passwd->len));
+}
+
+static bool auth_validator_hmac_md5(struct isis_passwd *passwd,
+ struct stream *stream,
+ struct isis_auth *auth, bool is_lsp)
+{
+ uint8_t digest[16];
+ uint16_t checksum;
+ uint16_t rem_lifetime;
+
+ if (is_lsp)
+ safe_auth_md5(stream, &checksum, &rem_lifetime);
+
+ memset(STREAM_DATA(stream) + auth->offset, 0, 16);
+ hmac_md5(STREAM_DATA(stream), stream_get_endp(stream), passwd->passwd,
+ passwd->len, digest);
+ memcpy(STREAM_DATA(stream) + auth->offset, auth->value, 16);
+
+ bool rv = !memcmp(digest, auth->value, 16);
+
+ if (is_lsp)
+ restore_auth_md5(stream, checksum, rem_lifetime);
+
+ return rv;
+}
+
+static const auth_validator_func auth_validators[] = {
+ [ISIS_PASSWD_TYPE_CLEARTXT] = auth_validator_cleartxt,
+ [ISIS_PASSWD_TYPE_HMAC_MD5] = auth_validator_hmac_md5,
+};
+
+bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
+ struct stream *stream, bool is_lsp)
+{
+ /* If no auth is set, always pass authentication */
+ if (!passwd->type)
+ return true;
+
+ /* If we don't known how to validate the auth, return invalid */
+ if (passwd->type >= array_size(auth_validators)
+ || !auth_validators[passwd->type])
+ return false;
+
+ struct isis_auth *auth_head = (struct isis_auth *)tlvs->isis_auth.head;
+ struct isis_auth *auth;
+ for (auth = auth_head; auth; auth = auth->next) {
+ if (auth->type == passwd->type)
+ break;
+ }
+
+ /* If matching auth TLV could not be found, return invalid */
+ if (!auth)
+ return false;
+
+ /* Perform validation and return result */
+ return auth_validators[passwd->type](passwd, stream, auth, is_lsp);
+}
+
+bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct isis_area_address *addr_head;
+
+ addr_head = (struct isis_area_address *)tlvs->area_addresses.head;
+ for (struct isis_area_address *addr = addr_head; addr;
+ addr = addr->next) {
+ struct listnode *node;
+ struct area_addr *a;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, a)) {
+ if (a->addr_len == addr->len
+ && !memcmp(a->area_addr, addr->addr, addr->len))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void tlvs_area_addresses_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ if (adj->area_address_count != tlvs->area_addresses.count) {
+ *changed = true;
+ adj->area_address_count = tlvs->area_addresses.count;
+ adj->area_addresses = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses,
+ adj->area_address_count * sizeof(*adj->area_addresses));
+ }
+
+ struct isis_area_address *addr = NULL;
+ for (unsigned int i = 0; i < tlvs->area_addresses.count; i++) {
+ if (!addr)
+ addr = (struct isis_area_address *)
+ tlvs->area_addresses.head;
+ else
+ addr = addr->next;
+
+ if (adj->area_addresses[i].addr_len == addr->len
+ && !memcmp(adj->area_addresses[i].area_addr, addr->addr,
+ addr->len)) {
+ continue;
+ }
+
+ *changed = true;
+ adj->area_addresses[i].addr_len = addr->len;
+ memcpy(adj->area_addresses[i].area_addr, addr->addr, addr->len);
+ }
+}
+
+static void tlvs_protocols_supported_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ bool ipv4_supported = false, ipv6_supported = false;
+
+ for (uint8_t i = 0; i < tlvs->protocols_supported.count; i++) {
+ if (tlvs->protocols_supported.protocols[i] == NLPID_IP)
+ ipv4_supported = true;
+ if (tlvs->protocols_supported.protocols[i] == NLPID_IPV6)
+ ipv6_supported = true;
+ }
+
+ struct nlpids reduced = {};
+
+ if (ipv4_supported && ipv6_supported) {
+ reduced.count = 2;
+ reduced.nlpids[0] = NLPID_IP;
+ reduced.nlpids[1] = NLPID_IPV6;
+ } else if (ipv4_supported) {
+ reduced.count = 1;
+ reduced.nlpids[0] = NLPID_IP;
+ } else if (ipv6_supported) {
+ reduced.count = 1;
+ reduced.nlpids[1] = NLPID_IPV6;
+ } else {
+ reduced.count = 0;
+ }
+
+ if (adj->nlpids.count == reduced.count
+ && !memcmp(adj->nlpids.nlpids, reduced.nlpids, reduced.count))
+ return;
+
+ *changed = true;
+ adj->nlpids.count = reduced.count;
+ memcpy(adj->nlpids.nlpids, reduced.nlpids, reduced.count);
+}
+
+static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ if (adj->ipv4_address_count != tlvs->ipv4_address.count) {
+ *changed = true;
+ adj->ipv4_address_count = tlvs->ipv4_address.count;
+ adj->ipv4_addresses = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses,
+ adj->ipv4_address_count * sizeof(*adj->ipv4_addresses));
+ }
+
+ struct isis_ipv4_address *addr = NULL;
+ for (unsigned int i = 0; i < tlvs->ipv4_address.count; i++) {
+ if (!addr)
+ addr = (struct isis_ipv4_address *)
+ tlvs->ipv4_address.head;
+ else
+ addr = addr->next;
+
+ if (!memcmp(&adj->ipv4_addresses[i], &addr->addr,
+ sizeof(addr->addr)))
+ continue;
+
+ *changed = true;
+ adj->ipv4_addresses[i] = addr->addr;
+ }
+}
+
+static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ if (adj->ipv6_address_count != tlvs->ipv6_address.count) {
+ *changed = true;
+ adj->ipv6_address_count = tlvs->ipv6_address.count;
+ adj->ipv6_addresses = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses,
+ adj->ipv6_address_count * sizeof(*adj->ipv6_addresses));
+ }
+
+ struct isis_ipv6_address *addr = NULL;
+ for (unsigned int i = 0; i < tlvs->ipv6_address.count; i++) {
+ if (!addr)
+ addr = (struct isis_ipv6_address *)
+ tlvs->ipv6_address.head;
+ else
+ addr = addr->next;
+
+ if (!memcmp(&adj->ipv6_addresses[i], &addr->addr,
+ sizeof(addr->addr)))
+ continue;
+
+ *changed = true;
+ adj->ipv6_addresses[i] = addr->addr;
+ }
+}
+
+void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
+ bool *changed)
+{
+ *changed = false;
+
+ tlvs_area_addresses_to_adj(tlvs, adj, changed);
+ tlvs_protocols_supported_to_adj(tlvs, adj, changed);
+ tlvs_ipv4_addresses_to_adj(tlvs, adj, changed);
+ tlvs_ipv6_addresses_to_adj(tlvs, adj, changed);
+}
+
+bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa)
+{
+ struct isis_lan_neighbor *ne_head;
+
+ ne_head = (struct isis_lan_neighbor *)tlvs->lan_neighbor.head;
+ for (struct isis_lan_neighbor *ne = ne_head; ne; ne = ne->next) {
+ if (!memcmp(ne->mac, snpa, ETH_ALEN))
+ return true;
+ }
+
+ return false;
+}
+
+void isis_tlvs_add_lsp_entry(struct isis_tlvs *tlvs, struct isis_lsp *lsp)
+{
+ struct isis_lsp_entry *entry = XCALLOC(MTYPE_ISIS_TLV, sizeof(*entry));
+
+ entry->rem_lifetime = lsp->hdr.rem_lifetime;
+ memcpy(entry->id, lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 2);
+ entry->checksum = lsp->hdr.checksum;
+ entry->seqno = lsp->hdr.seqno;
+ entry->lsp = lsp;
+
+ append_item(&tlvs->lsp_entries, (struct isis_item *)entry);
+}
+
+void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id,
+ uint8_t *stop_id, uint16_t num_lsps,
+ dict_t *lspdb, struct isis_lsp **last_lsp)
+{
+ dnode_t *first = dict_lower_bound(lspdb, start_id);
+ if (!first)
+ return;
+
+ dnode_t *last = dict_upper_bound(lspdb, stop_id);
+ dnode_t *curr = first;
+
+ isis_tlvs_add_lsp_entry(tlvs, first->dict_data);
+ *last_lsp = first->dict_data;
+
+ while (curr) {
+ curr = dict_next(lspdb, curr);
+ if (curr) {
+ isis_tlvs_add_lsp_entry(tlvs, curr->dict_data);
+ *last_lsp = curr->dict_data;
+ }
+ if (curr == last || tlvs->lsp_entries.count == num_lsps)
+ break;
+ }
+}
+
+void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs,
+ const char *hostname)
+{
+ XFREE(MTYPE_ISIS_TLV, tlvs->hostname);
+ if (hostname)
+ tlvs->hostname = XSTRDUP(MTYPE_ISIS_TLV, hostname);
+}
+
+void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
+ const struct in_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, tlvs->te_router_id);
+ if (!id)
+ return;
+ tlvs->te_router_id = XCALLOC(MTYPE_ISIS_TLV, sizeof(*id));
+ memcpy(tlvs->te_router_id, id, sizeof(*id));
+}
+
+void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
+ struct prefix_ipv4 *dest, uint8_t metric)
+{
+ struct isis_oldstyle_ip_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
+
+ r->metric = metric;
+ memcpy(&r->prefix, dest, sizeof(*dest));
+ apply_mask_ipv4(&r->prefix);
+ append_item(&tlvs->oldstyle_ip_reach, (struct isis_item *)r);
+}
+
+void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
+ struct prefix_ipv4 *dest, uint32_t metric)
+{
+ struct isis_extended_ip_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
+
+ r->metric = metric;
+ memcpy(&r->prefix, dest, sizeof(*dest));
+ apply_mask_ipv4(&r->prefix);
+ append_item(&tlvs->extended_ip_reach, (struct isis_item *)r);
+}
+
+void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid,
+ struct prefix_ipv6 *dest, uint32_t metric)
+{
+ struct isis_ipv6_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
+
+ r->metric = metric;
+ memcpy(&r->prefix, dest, sizeof(*dest));
+ apply_mask_ipv6(&r->prefix);
+
+ struct isis_item_list *l;
+ l = (mtid == ISIS_MT_IPV4_UNICAST)
+ ? &tlvs->ipv6_reach
+ : isis_get_mt_items(&tlvs->mt_ipv6_reach, mtid);
+ append_item(l, (struct isis_item *)r);
+}
+
+void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
+ uint8_t metric)
+{
+ struct isis_oldstyle_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
+
+ r->metric = metric;
+ memcpy(r->id, id, sizeof(r->id));
+ append_item(&tlvs->oldstyle_reach, (struct isis_item *)r);
+}
+
+void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
+ uint8_t *id, uint32_t metric,
+ uint8_t *subtlvs, uint8_t subtlv_len)
+{
+ struct isis_extended_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
+
+ memcpy(r->id, id, sizeof(r->id));
+ r->metric = metric;
+ if (subtlvs && subtlv_len) {
+ r->subtlvs = XCALLOC(MTYPE_ISIS_TLV, subtlv_len);
+ memcpy(r->subtlvs, subtlvs, subtlv_len);
+ r->subtlv_len = subtlv_len;
+ }
+
+ struct isis_item_list *l;
+ if (mtid == ISIS_MT_IPV4_UNICAST)
+ l = &tlvs->extended_reach;
+ else
+ l = isis_get_mt_items(&tlvs->mt_reach, mtid);
+ append_item(l, (struct isis_item *)r);
+}
+
+struct isis_mt_router_info *
+isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
+{
+ if (tlvs->mt_router_info_empty)
+ return NULL;
+
+ struct isis_mt_router_info *rv;
+ for (rv = (struct isis_mt_router_info *)tlvs->mt_router_info.head; rv;
+ rv = rv->next) {
+ if (rv->mtid == mtid)
+ return rv;
+ }
+
+ return NULL;
+}
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
new file mode 100644
index 0000000000..6ade0af28c
--- /dev/null
+++ b/isisd/isis_tlvs.h
@@ -0,0 +1,308 @@
+/*
+ * IS-IS TLV Serializer/Deserializer
+ *
+ * Copyright (C) 2015,2017 Christian Franke
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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.
+ *
+ * FRR 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef ISIS_TLVS_H
+#define ISIS_TLVS_H
+
+#include "openbsd-tree.h"
+#include "prefix.h"
+#include "isisd/dict.h"
+
+struct isis_subtlvs;
+
+struct isis_area_address;
+struct isis_area_address {
+ struct isis_area_address *next;
+
+ uint8_t addr[20];
+ uint8_t len;
+};
+
+struct isis_oldstyle_reach;
+struct isis_oldstyle_reach {
+ struct isis_oldstyle_reach *next;
+
+ uint8_t id[7];
+ uint8_t metric;
+};
+
+struct isis_oldstyle_ip_reach;
+struct isis_oldstyle_ip_reach {
+ struct isis_oldstyle_ip_reach *next;
+
+ uint8_t metric;
+ struct prefix_ipv4 prefix;
+};
+
+struct isis_lsp_entry;
+struct isis_lsp_entry {
+ struct isis_lsp_entry *next;
+
+ uint16_t rem_lifetime;
+ uint8_t id[8];
+ uint16_t checksum;
+ uint32_t seqno;
+
+ struct isis_lsp *lsp;
+};
+
+struct isis_extended_reach;
+struct isis_extended_reach {
+ struct isis_extended_reach *next;
+
+ uint8_t id[7];
+ uint32_t metric;
+
+ uint8_t *subtlvs;
+ uint8_t subtlv_len;
+};
+
+struct isis_extended_ip_reach;
+struct isis_extended_ip_reach {
+ struct isis_extended_ip_reach *next;
+
+ uint32_t metric;
+ bool down;
+ struct prefix_ipv4 prefix;
+};
+
+struct isis_ipv6_reach;
+struct isis_ipv6_reach {
+ struct isis_ipv6_reach *next;
+
+ uint32_t metric;
+ bool down;
+ bool external;
+
+ struct prefix_ipv6 prefix;
+
+ struct isis_subtlvs *subtlvs;
+};
+
+struct isis_protocols_supported {
+ uint8_t count;
+ uint8_t *protocols;
+};
+
+struct isis_item;
+struct isis_item {
+ struct isis_item *next;
+};
+
+struct isis_lan_neighbor;
+struct isis_lan_neighbor {
+ struct isis_lan_neighbor *next;
+
+ uint8_t mac[6];
+};
+
+struct isis_ipv4_address;
+struct isis_ipv4_address {
+ struct isis_ipv4_address *next;
+
+ struct in_addr addr;
+};
+
+struct isis_ipv6_address;
+struct isis_ipv6_address {
+ struct isis_ipv6_address *next;
+
+ struct in6_addr addr;
+};
+
+struct isis_mt_router_info;
+struct isis_mt_router_info {
+ struct isis_mt_router_info *next;
+
+ bool overload;
+ bool attached;
+ uint16_t mtid;
+};
+
+struct isis_auth;
+struct isis_auth {
+ struct isis_auth *next;
+
+ uint8_t type;
+ uint8_t length;
+ uint8_t value[256];
+
+ uint8_t plength;
+ uint8_t passwd[256];
+
+ size_t offset; /* Only valid after packing */
+};
+
+struct isis_item_list;
+struct isis_item_list {
+ struct isis_item *head;
+ struct isis_item **tail;
+
+ RB_ENTRY(isis_item_list) mt_tree;
+ uint16_t mtid;
+ unsigned int count;
+};
+
+RB_HEAD(isis_mt_item_list, isis_item_list);
+
+struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
+ uint16_t mtid);
+struct isis_item_list *isis_lookup_mt_items(struct isis_mt_item_list *m,
+ uint16_t mtid);
+
+struct isis_tlvs {
+ struct isis_item_list isis_auth;
+ struct isis_item_list area_addresses;
+ struct isis_item_list oldstyle_reach;
+ struct isis_item_list lan_neighbor;
+ struct isis_item_list lsp_entries;
+ struct isis_item_list extended_reach;
+ struct isis_mt_item_list mt_reach;
+ struct isis_item_list oldstyle_ip_reach;
+ struct isis_protocols_supported protocols_supported;
+ struct isis_item_list oldstyle_ip_reach_ext;
+ struct isis_item_list ipv4_address;
+ struct isis_item_list ipv6_address;
+ struct isis_item_list mt_router_info;
+ bool mt_router_info_empty;
+ struct in_addr *te_router_id;
+ struct isis_item_list extended_ip_reach;
+ struct isis_mt_item_list mt_ip_reach;
+ char *hostname;
+ struct isis_item_list ipv6_reach;
+ struct isis_mt_item_list mt_ipv6_reach;
+};
+
+struct isis_subtlvs {
+ /* draft-baker-ipv6-isis-dst-src-routing-06 */
+ struct prefix_ipv6 *source_prefix;
+};
+
+enum isis_tlv_context {
+ ISIS_CONTEXT_LSP,
+ ISIS_CONTEXT_SUBTLV_NE_REACH,
+ ISIS_CONTEXT_SUBTLV_IP_REACH,
+ ISIS_CONTEXT_SUBTLV_IPV6_REACH,
+ ISIS_CONTEXT_MAX
+};
+
+enum isis_tlv_type {
+ ISIS_TLV_AREA_ADDRESSES = 1,
+ ISIS_TLV_OLDSTYLE_REACH = 2,
+ ISIS_TLV_LAN_NEIGHBORS = 6,
+ ISIS_TLV_PADDING = 8,
+ ISIS_TLV_LSP_ENTRY = 9,
+ ISIS_TLV_AUTH = 10,
+ ISIS_TLV_EXTENDED_REACH = 22,
+
+ ISIS_TLV_OLDSTYLE_IP_REACH = 128,
+ ISIS_TLV_PROTOCOLS_SUPPORTED = 129,
+ ISIS_TLV_OLDSTYLE_IP_REACH_EXT = 130,
+ ISIS_TLV_IPV4_ADDRESS = 132,
+ ISIS_TLV_TE_ROUTER_ID = 134,
+ ISIS_TLV_EXTENDED_IP_REACH = 135,
+ ISIS_TLV_DYNAMIC_HOSTNAME = 137,
+ ISIS_TLV_MT_REACH = 222,
+ ISIS_TLV_MT_ROUTER_INFO = 229,
+ ISIS_TLV_IPV6_ADDRESS = 232,
+ ISIS_TLV_MT_IP_REACH = 235,
+ ISIS_TLV_IPV6_REACH = 236,
+ ISIS_TLV_MT_IPV6_REACH = 237,
+ ISIS_TLV_MAX = 256,
+
+ ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
+};
+
+#define IS_COMPAT_MT_TLV(tlv_type) \
+ ((tlv_type == ISIS_TLV_MT_REACH) || (tlv_type == ISIS_TLV_MT_IP_REACH) \
+ || (tlv_type == ISIS_TLV_MT_IPV6_REACH))
+
+struct stream;
+int isis_pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
+ size_t len_pointer, bool pad, bool is_lsp);
+void isis_free_tlvs(struct isis_tlvs *tlvs);
+struct isis_tlvs *isis_alloc_tlvs(void);
+int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
+ struct isis_tlvs **dest, const char **error_log);
+const char *isis_format_tlvs(struct isis_tlvs *tlvs);
+struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs);
+struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size);
+
+#define ISIS_EXTENDED_IP_REACH_DOWN 0x80
+#define ISIS_EXTENDED_IP_REACH_SUBTLV 0x40
+
+#define ISIS_IPV6_REACH_DOWN 0x80
+#define ISIS_IPV6_REACH_EXTERNAL 0x40
+#define ISIS_IPV6_REACH_SUBTLV 0x20
+
+#ifndef ISIS_MT_MASK
+#define ISIS_MT_MASK 0x0fff
+#define ISIS_MT_OL_MASK 0x8000
+#define ISIS_MT_AT_MASK 0x4000
+#endif
+
+
+void isis_tlvs_add_auth(struct isis_tlvs *tlvs, struct isis_passwd *passwd);
+void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses);
+void isis_tlvs_add_lan_neighbors(struct isis_tlvs *tlvs,
+ struct list *neighbors);
+void isis_tlvs_set_protocols_supported(struct isis_tlvs *tlvs,
+ struct nlpids *nlpids);
+void isis_tlvs_add_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid,
+ bool overload, bool attached);
+void isis_tlvs_add_ipv4_address(struct isis_tlvs *tlvs, struct in_addr *addr);
+void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses);
+void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses);
+bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
+ struct stream *stream, bool is_lsp);
+bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
+ struct list *addresses);
+struct isis_adjacency;
+void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
+ bool *changed);
+bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa);
+void isis_tlvs_add_lsp_entry(struct isis_tlvs *tlvs, struct isis_lsp *lsp);
+void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id,
+ uint8_t *stop_id, uint16_t num_lsps,
+ dict_t *lspdb, struct isis_lsp **last_lsp);
+void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs,
+ const char *hostname);
+void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
+ const struct in_addr *id);
+void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
+ struct prefix_ipv4 *dest, uint8_t metric);
+void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
+ struct prefix_ipv4 *dest, uint32_t metric);
+void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid,
+ struct prefix_ipv6 *dest, uint32_t metric);
+void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
+ uint8_t metric);
+void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
+ uint8_t *id, uint32_t metric,
+ uint8_t *subtlvs, uint8_t subtlv_len);
+
+struct isis_mt_router_info *
+isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
+#endif
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 18a59d1fc5..8c6968f8ec 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -42,7 +42,6 @@
#include "isisd/isis_flags.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_circuit.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 8bbb5cf949..60b9367da9 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -49,7 +49,6 @@
#include "isisd/isis_pdu.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_constants.h"
-#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_route.h"
@@ -1232,27 +1231,6 @@ DEFUN (show_hostname,
return CMD_SUCCESS;
}
-static void vty_out_timestr(struct vty *vty, time_t uptime)
-{
- struct tm *tm;
- time_t difftime = time(NULL);
- difftime -= uptime;
- tm = gmtime(&difftime);
-
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
- if (difftime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
- tm->tm_sec);
- else if (difftime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
- tm->tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
- tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
- vty_out(vty, " ago");
-}
-
DEFUN (show_isis_spf_ietf,
show_isis_spf_ietf_cmd,
"show isis spf-delay-ietf",
@@ -1309,7 +1287,6 @@ DEFUN (show_isis_summary,
{
struct listnode *node, *node2;
struct isis_area *area;
- struct isis_spftree *spftree;
int level;
if (isis == NULL) {
@@ -1350,7 +1327,6 @@ DEFUN (show_isis_summary,
continue;
vty_out(vty, " Level-%d:\n", level);
- spftree = area->spftree[level - 1];
if (area->spf_timer[level - 1])
vty_out(vty, " SPF: (pending)\n");
else
@@ -1364,28 +1340,10 @@ DEFUN (show_isis_summary,
vty_out(vty, "\n");
vty_out(vty, " IPv4 route computation:\n");
- vty_out(vty, " last run elapsed : ");
- vty_out_timestr(vty, spftree->last_run_timestamp);
- vty_out(vty, "\n");
+ isis_spf_print(area->spftree[level - 1], vty);
- vty_out(vty, " last run duration : %u usec\n",
- (u_int32_t)spftree->last_run_duration);
-
- vty_out(vty, " run count : %d\n",
- spftree->runcount);
-
- spftree = area->spftree6[level - 1];
vty_out(vty, " IPv6 route computation:\n");
-
- vty_out(vty, " last run elapsed : ");
- vty_out_timestr(vty, spftree->last_run_timestamp);
- vty_out(vty, "\n");
-
- vty_out(vty, " last run duration : %llu msec\n",
- (unsigned long long)spftree->last_run_duration);
-
- vty_out(vty, " run count : %d\n",
- spftree->runcount);
+ isis_spf_print(area->spftree6[level - 1], vty);
}
}
vty_out(vty, "\n");
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 1aacea881f..da02854f5c 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -37,7 +37,7 @@
/* uncomment if you are a developer in bug hunt */
/* #define EXTREME_DEBUG */
-/* #define EXTREME_TLV_DEBUG */
+/* #define EXTREME_DICT_DEBUG */
struct isis {
u_long process_id;
diff --git a/isisd/iso_checksum.c b/isisd/iso_checksum.c
index e0a4ba3700..25a870991a 100644
--- a/isisd/iso_checksum.c
+++ b/isisd/iso_checksum.c
@@ -67,7 +67,7 @@ int iso_csum_verify(u_char *buffer, int len, uint16_t csum, int offset)
return 1;
checksum = fletcher_checksum(buffer, len, offset);
- if (checksum == csum)
+ if (checksum == htons(csum))
return 0;
return 1;
}
diff --git a/ldpd/address.c b/ldpd/address.c
index 584240de84..18ab037760 100644
--- a/ldpd/address.c
+++ b/ldpd/address.c
@@ -160,7 +160,7 @@ send_mac_withdrawal(struct nbr *nbr, struct map *fec, uint8_t *mac)
size = LDP_HDR_SIZE + LDP_MSG_SIZE + ADDR_LIST_SIZE + len_fec_tlv(fec) +
TLV_HDR_SIZE;
if (mac)
- size += ETHER_ADDR_LEN;
+ size += ETH_ALEN;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
@@ -372,10 +372,10 @@ gen_mac_list_tlv(struct ibuf *buf, uint8_t *mac)
memset(&tlv, 0, sizeof(tlv));
tlv.type = htons(TLV_TYPE_MAC_LIST);
if (mac)
- tlv.length = htons(ETHER_ADDR_LEN);
+ tlv.length = htons(ETH_ALEN);
err = ibuf_add(buf, &tlv, sizeof(tlv));
if (mac)
- err |= ibuf_add(buf, mac, ETHER_ADDR_LEN);
+ err |= ibuf_add(buf, mac, ETH_ALEN);
return (err);
}
diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c
index f15461d3d2..9bad503b9c 100644
--- a/ldpd/l2vpn.c
+++ b/ldpd/l2vpn.c
@@ -235,6 +235,7 @@ void
l2vpn_pw_init(struct l2vpn_pw *pw)
{
struct fec fec;
+ struct zapi_pw zpw;
l2vpn_pw_reset(pw);
@@ -242,16 +243,23 @@ l2vpn_pw_init(struct l2vpn_pw *pw)
lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
0, (void *)pw);
lde_kernel_update(&fec);
+
+ pw2zpw(pw, &zpw);
+ lde_imsg_compose_parent(IMSG_KPW_ADD, 0, &zpw, sizeof(zpw));
}
void
l2vpn_pw_exit(struct l2vpn_pw *pw)
{
struct fec fec;
+ struct zapi_pw zpw;
l2vpn_pw_fec(pw, &fec);
lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0);
lde_kernel_update(&fec);
+
+ pw2zpw(pw, &zpw);
+ lde_imsg_compose_parent(IMSG_KPW_DELETE, 0, &zpw, sizeof(zpw));
}
static void
@@ -269,7 +277,8 @@ l2vpn_pw_reset(struct l2vpn_pw *pw)
{
pw->remote_group = 0;
pw->remote_mtu = 0;
- pw->remote_status = 0;
+ pw->local_status = PW_FORWARDING;
+ pw->remote_status = PW_NOT_FORWARDING;
if (pw->flags & F_PW_CWORD_CONF)
pw->flags |= F_PW_CWORD;
@@ -475,6 +484,56 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
}
}
+int
+l2vpn_pw_status_update(struct zapi_pw_status *zpw)
+{
+ struct l2vpn *l2vpn;
+ struct l2vpn_pw *pw = NULL;
+ struct lde_nbr *ln;
+ struct fec fec;
+ uint32_t local_status;
+
+ RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
+ pw = l2vpn_pw_find(l2vpn, zpw->ifname);
+ if (pw)
+ break;
+ }
+ if (!pw) {
+ log_warnx("%s: pseudowire %s not found", __func__, zpw->ifname);
+ return (1);
+ }
+
+ if (zpw->status == PW_STATUS_UP)
+ local_status = PW_FORWARDING;
+ else
+ local_status = PW_NOT_FORWARDING;
+
+ /* local status didn't change */
+ if (pw->local_status == local_status)
+ return (0);
+ pw->local_status = local_status;
+
+ /* notify remote peer about the status update */
+ ln = lde_nbr_find_by_lsrid(pw->lsr_id);
+ if (ln == NULL)
+ return (0);
+ l2vpn_pw_fec(pw, &fec);
+ if (pw->flags & F_PW_STATUSTLV)
+ l2vpn_send_pw_status(ln, local_status, &fec);
+ else {
+ struct fec_node *fn;
+ fn = (struct fec_node *)fec_find(&ft, &fec);
+ if (fn) {
+ if (pw->local_status == PW_FORWARDING)
+ lde_send_labelmapping(ln, fn, 1);
+ else
+ lde_send_labelwithdraw(ln, fn, NULL, NULL);
+ }
+ }
+
+ return (0);
+}
+
void
l2vpn_pw_ctl(pid_t pid)
{
@@ -491,7 +550,9 @@ l2vpn_pw_ctl(pid_t pid)
sizeof(pwctl.ifname));
pwctl.pwid = pw->pwid;
pwctl.lsr_id = pw->lsr_id;
- pwctl.status = pw->flags & F_PW_STATUS_UP;
+ if (pw->local_status == PW_FORWARDING &&
+ pw->remote_status == PW_FORWARDING)
+ pwctl.status = 1;
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
pid, &pwctl, sizeof(pwctl));
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 77643ff48b..588ccd6952 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -472,6 +472,15 @@ lde_dispatch_parent(struct thread *thread)
}
}
break;
+ case IMSG_PW_UPDATE:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct zapi_pw_status))
+ fatalx("PW_UPDATE imsg with wrong len");
+
+ if (l2vpn_pw_status_update(imsg.data) != 0)
+ log_warnx("%s: error updating PW status",
+ __func__);
+ break;
case IMSG_NETWORK_ADD:
case IMSG_NETWORK_UPDATE:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -712,8 +721,8 @@ lde_update_label(struct fec_node *fn)
void
lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
{
- struct kroute kr;
- struct kpw kpw;
+ struct kroute kr;
+ struct zapi_pw zpw;
struct l2vpn_pw *pw;
switch (fn->fec.type) {
@@ -751,19 +760,10 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
return;
pw = (struct l2vpn_pw *) fn->data;
- pw->flags |= F_PW_STATUS_UP;
-
- memset(&kpw, 0, sizeof(kpw));
- kpw.ifindex = pw->ifindex;
- kpw.pw_type = fn->fec.u.pwid.type;
- kpw.af = pw->af;
- kpw.nexthop = pw->addr;
- kpw.local_label = fn->local_label;
- kpw.remote_label = fnh->remote_label;
- kpw.flags = pw->flags;
-
- lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE, 0, &kpw,
- sizeof(kpw));
+ pw2zpw(pw, &zpw);
+ zpw.local_label = fn->local_label;
+ zpw.remote_label = fnh->remote_label;
+ lde_imsg_compose_parent(IMSG_KPW_SET, 0, &zpw, sizeof(zpw));
break;
}
}
@@ -772,7 +772,7 @@ void
lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
{
struct kroute kr;
- struct kpw kpw;
+ struct zapi_pw zpw;
struct l2vpn_pw *pw;
switch (fn->fec.type) {
@@ -806,21 +806,10 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
break;
case FEC_TYPE_PWID:
pw = (struct l2vpn_pw *) fn->data;
- if (!(pw->flags & F_PW_STATUS_UP))
- return;
- pw->flags &= ~F_PW_STATUS_UP;
-
- memset(&kpw, 0, sizeof(kpw));
- kpw.ifindex = pw->ifindex;
- kpw.pw_type = fn->fec.u.pwid.type;
- kpw.af = pw->af;
- kpw.nexthop = pw->addr;
- kpw.local_label = fn->local_label;
- kpw.remote_label = fnh->remote_label;
- kpw.flags = pw->flags;
-
- lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE, 0, &kpw,
- sizeof(kpw));
+ pw2zpw(pw, &zpw);
+ zpw.local_label = fn->local_label;
+ zpw.remote_label = fnh->remote_label;
+ lde_imsg_compose_parent(IMSG_KPW_UNSET, 0, &zpw, sizeof(zpw));
break;
}
}
@@ -901,8 +890,12 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
*/
lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
if (lw) {
- if (!fec_find(&ln->sent_map_pending, &fn->fec))
+ if (!fec_find(&ln->sent_map_pending, &fn->fec)) {
+ debug_evt("%s: FEC %s: scheduling to send label "
+ "mapping later (waiting for pending label release)",
+ __func__, log_fec(&fn->fec));
lde_map_pending_add(ln, fn);
+ }
return;
}
@@ -948,8 +941,7 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
map.flags |= F_MAP_PW_CWORD;
if (pw->flags & F_PW_STATUSTLV) {
map.flags |= F_MAP_PW_STATUS;
- /* VPLS are always up */
- map.pw_status = PW_FORWARDING;
+ map.pw_status = pw->local_status;
}
break;
}
diff --git a/ldpd/lde.h b/ldpd/lde.h
index 1cce483832..43f1d36481 100644
--- a/ldpd/lde.h
+++ b/ldpd/lde.h
@@ -238,6 +238,7 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t,
void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *);
void l2vpn_recv_pw_status_wcard(struct lde_nbr *,
struct notify_msg *);
+int l2vpn_pw_status_update(struct zapi_pw_status *);
void l2vpn_pw_ctl(pid_t);
void l2vpn_binding_ctl(pid_t);
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index edf686537f..c56b7e33d0 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -396,8 +396,7 @@ lde_kernel_update(struct fec *fec)
lde_gc_start_timer();
} else {
fn->local_label = lde_update_label(fn);
- if (fn->local_label != NO_LABEL &&
- RB_EMPTY(lde_map_head, &fn->upstream))
+ if (fn->local_label != NO_LABEL)
/* FEC.1: perform lsr label distribution procedure */
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
lde_send_labelmapping(ln, fn, 1);
@@ -531,6 +530,8 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
pw->remote_mtu = map->fec.pwid.ifmtu;
if (map->flags & F_MAP_PW_STATUS)
pw->remote_status = map->pw_status;
+ else
+ pw->remote_status = PW_FORWARDING;
fnh->remote_label = map->label;
if (l2vpn_pw_ok(pw, fnh))
lde_send_change_klabel(fn, fnh);
@@ -774,6 +775,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
pw = (struct l2vpn_pw *) fn->data;
if (pw == NULL)
continue;
+ pw->remote_status = PW_NOT_FORWARDING;
break;
default:
break;
@@ -802,6 +804,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
struct fec_node *fn;
struct fec_nh *fnh;
struct lde_map *me;
+ struct l2vpn_pw *pw;
/* LWd.2: send label release */
lde_send_labelrelease(ln, NULL, map, map->label);
@@ -825,6 +828,9 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
case FEC_TYPE_PWID:
if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
continue;
+ pw = (struct l2vpn_pw *) fn->data;
+ if (pw)
+ pw->remote_status = PW_NOT_FORWARDING;
break;
default:
break;
diff --git a/ldpd/ldp.h b/ldpd/ldp.h
index c2b64d20c6..cac3da7c55 100644
--- a/ldpd/ldp.h
+++ b/ldpd/ldp.h
@@ -285,9 +285,6 @@ struct address_list_tlv {
#define MAP_TYPE_GENPWID 0x81
#define CONTROL_WORD_FLAG 0x8000
-#define PW_TYPE_ETHERNET_TAGGED 0x0004
-#define PW_TYPE_ETHERNET 0x0005
-#define PW_TYPE_WILDCARD 0x7FFF
#define DEFAULT_PW_TYPE PW_TYPE_ETHERNET
#define PW_TWCARD_RESERVED_BIT 0x8000
diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c
index 7da76185c6..3f39ad926c 100644
--- a/ldpd/ldp_vty_cmds.c
+++ b/ldpd/ldp_vty_cmds.c
@@ -37,7 +37,7 @@ DEFUN_NOSH(ldp_mpls_ldp,
DEFPY (no_ldp_mpls_ldp,
no_ldp_mpls_ldp_cmd,
"no mpls ldp",
- "Negate a command or set its defaults\n"
+ NO_STR
"Global MPLS configuration subcommands\n"
"Label Distribution Protocol\n")
{
@@ -64,7 +64,7 @@ DEFUN_NOSH(ldp_l2vpn,
DEFPY (no_ldp_l2vpn,
no_ldp_l2vpn_cmd,
"no l2vpn WORD$l2vpn_name type vpls",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure l2vpn commands\n"
"L2VPN name\n"
"L2VPN type\n"
@@ -92,7 +92,7 @@ DEFUN_NOSH(ldp_address_family,
DEFPY (no_ldp_address_family,
no_ldp_address_family_cmd,
"no address-family <ipv4|ipv6>$af",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure Address Family and its parameters\n"
"IPv4\n"
"IPv6\n")
@@ -113,7 +113,7 @@ DEFUN_NOSH(ldp_exit_address_family,
DEFPY (ldp_discovery_holdtime,
ldp_discovery_holdtime_cmd,
"[no] discovery <hello|targeted-hello>$hello_type holdtime (1-65535)$holdtime",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure discovery parameters\n"
"LDP Link Hellos\n"
"LDP Targeted Hellos\n"
@@ -126,7 +126,7 @@ DEFPY (ldp_discovery_holdtime,
DEFPY (ldp_discovery_interval,
ldp_discovery_interval_cmd,
"[no] discovery <hello|targeted-hello>$hello_type interval (1-65535)$interval",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure discovery parameters\n"
"LDP Link Hellos\n"
"LDP Targeted Hellos\n"
@@ -139,7 +139,7 @@ DEFPY (ldp_discovery_interval,
DEFPY (ldp_dual_stack_transport_connection_prefer_ipv4,
ldp_dual_stack_transport_connection_prefer_ipv4_cmd,
"[no] dual-stack transport-connection prefer ipv4",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure dual stack parameters\n"
"Configure TCP transport parameters\n"
"Configure prefered address family for TCP transport connection with neighbor\n"
@@ -151,7 +151,7 @@ DEFPY (ldp_dual_stack_transport_connection_prefer_ipv4,
DEFPY (ldp_dual_stack_cisco_interop,
ldp_dual_stack_cisco_interop_cmd,
"[no] dual-stack cisco-interop",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure dual stack parameters\n"
"Use Cisco non-compliant format to send and interpret the Dual-Stack capability TLV\n")
{
@@ -161,7 +161,7 @@ DEFPY (ldp_dual_stack_cisco_interop,
DEFPY (ldp_neighbor_password,
ldp_neighbor_password_cmd,
"[no] neighbor A.B.C.D$neighbor password WORD$password",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure neighbor parameters\n"
"LDP Id of neighbor\n"
"Configure password for MD5 authentication\n"
@@ -173,7 +173,7 @@ DEFPY (ldp_neighbor_password,
DEFPY (ldp_neighbor_session_holdtime,
ldp_neighbor_session_holdtime_cmd,
"[no] neighbor A.B.C.D$neighbor session holdtime (15-65535)$holdtime",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure neighbor parameters\n"
"LDP Id of neighbor\n"
"Configure session parameters\n"
@@ -186,7 +186,7 @@ DEFPY (ldp_neighbor_session_holdtime,
DEFPY (ldp_neighbor_ttl_security,
ldp_neighbor_ttl_security_cmd,
"[no] neighbor A.B.C.D$neighbor ttl-security <disable|hops (1-254)$hops>",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure neighbor parameters\n"
"LDP Id of neighbor\n"
"LDP ttl security check\n"
@@ -200,7 +200,7 @@ DEFPY (ldp_neighbor_ttl_security,
DEFPY (ldp_router_id,
ldp_router_id_cmd,
"[no] router-id A.B.C.D$address",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure router Id\n"
"LSR Id (in form of an IPv4 address)\n")
{
@@ -210,7 +210,7 @@ DEFPY (ldp_router_id,
DEFPY (ldp_discovery_targeted_hello_accept,
ldp_discovery_targeted_hello_accept_cmd,
"[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure discovery parameters\n"
"LDP Targeted Hellos\n"
"Accept and respond to targeted hellos\n"
@@ -225,7 +225,7 @@ DEFPY (ldp_discovery_targeted_hello_accept,
DEFPY (ldp_discovery_transport_address_ipv4,
ldp_discovery_transport_address_ipv4_cmd,
"[no] discovery transport-address A.B.C.D$address",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure discovery parameters\n"
"Specify transport address for TCP connection\n"
"IP address to be used as transport address\n")
@@ -236,7 +236,7 @@ DEFPY (ldp_discovery_transport_address_ipv4,
DEFPY (ldp_discovery_transport_address_ipv6,
ldp_discovery_transport_address_ipv6_cmd,
"[no] discovery transport-address X:X::X:X$address",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure discovery parameters\n"
"Specify transport address for TCP connection\n"
"IPv6 address to be used as transport address\n")
@@ -247,7 +247,7 @@ DEFPY (ldp_discovery_transport_address_ipv6,
DEFPY (ldp_label_local_advertise,
ldp_label_local_advertise_cmd,
"[no] label local advertise [{to <(1-199)|(1300-2699)|WORD>$to_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}]",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure label control and policies\n"
"Configure local label control and policies\n"
"Configure outbound label advertisement control\n"
@@ -266,7 +266,7 @@ DEFPY (ldp_label_local_advertise,
DEFPY (ldp_label_local_advertise_explicit_null,
ldp_label_local_advertise_explicit_null_cmd,
"[no] label local advertise explicit-null [for <(1-199)|(1300-2699)|WORD>$for_acl]",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure label control and policies\n"
"Configure local label control and policies\n"
"Configure outbound label advertisement control\n"
@@ -282,7 +282,7 @@ DEFPY (ldp_label_local_advertise_explicit_null,
DEFPY (ldp_label_local_allocate,
ldp_label_local_allocate_cmd,
"[no] label local allocate <host-routes$host_routes|for <(1-199)|(1300-2699)|WORD>$for_acl>",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure label control and policies\n"
"Configure local label control and policies\n"
"Configure label allocation control\n"
@@ -298,7 +298,7 @@ DEFPY (ldp_label_local_allocate,
DEFPY (ldp_label_remote_accept,
ldp_label_remote_accept_cmd,
"[no] label remote accept {from <(1-199)|(1300-2699)|WORD>$from_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure label control and policies\n"
"Configure remote/peer label control and policies\n"
"Configure inbound label acceptance control\n"
@@ -317,7 +317,7 @@ DEFPY (ldp_label_remote_accept,
DEFPY (ldp_ttl_security_disable,
ldp_ttl_security_disable_cmd,
"[no] ttl-security disable",
- "Negate a command or set its defaults\n"
+ NO_STR
"LDP ttl security check\n"
"Disable ttl security\n")
{
@@ -327,7 +327,7 @@ DEFPY (ldp_ttl_security_disable,
DEFPY (ldp_session_holdtime,
ldp_session_holdtime_cmd,
"[no] session holdtime (15-65535)$holdtime",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure session parameters\n"
"Configure session holdtime\n"
"Time (seconds)\n")
@@ -353,7 +353,7 @@ DEFUN_NOSH(ldp_interface,
DEFPY (no_ldp_interface,
no_ldp_interface_cmd,
"no interface IFNAME$ifname",
- "Negate a command or set its defaults\n"
+ NO_STR
"Enable LDP on an interface and enter interface submode\n"
"Interface's name\n")
{
@@ -363,7 +363,7 @@ DEFPY (no_ldp_interface,
DEFPY (ldp_neighbor_ipv4_targeted,
ldp_neighbor_ipv4_targeted_cmd,
"[no] neighbor A.B.C.D$address targeted",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure neighbor parameters\n"
"IP address of neighbor\n"
"Establish targeted session\n")
@@ -374,7 +374,7 @@ DEFPY (ldp_neighbor_ipv4_targeted,
DEFPY (ldp_neighbor_ipv6_targeted,
ldp_neighbor_ipv6_targeted_cmd,
"[no] neighbor X:X::X:X$address targeted",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure neighbor parameters\n"
"IPv6 address of neighbor\n"
"Establish targeted session\n")
@@ -385,7 +385,7 @@ DEFPY (ldp_neighbor_ipv6_targeted,
DEFPY (ldp_bridge,
ldp_bridge_cmd,
"[no] bridge IFNAME$ifname",
- "Negate a command or set its defaults\n"
+ NO_STR
"Bridge interface\n"
"Interface's name\n")
{
@@ -395,7 +395,7 @@ DEFPY (ldp_bridge,
DEFPY (ldp_mtu,
ldp_mtu_cmd,
"[no] mtu (1500-9180)$mtu",
- "Negate a command or set its defaults\n"
+ NO_STR
"Set Maximum Transmission Unit\n"
"Maximum Transmission Unit value\n")
{
@@ -405,7 +405,7 @@ DEFPY (ldp_mtu,
DEFPY (ldp_member_interface,
ldp_member_interface_cmd,
"[no] member interface IFNAME$ifname",
- "Negate a command or set its defaults\n"
+ NO_STR
"L2VPN member configuration\n"
"Local interface\n"
"Interface's name\n")
@@ -432,7 +432,7 @@ DEFUN_NOSH(ldp_member_pseudowire,
DEFPY (no_ldp_member_pseudowire,
no_ldp_member_pseudowire_cmd,
"no member pseudowire IFNAME$ifname",
- "Negate a command or set its defaults\n"
+ NO_STR
"L2VPN member configuration\n"
"Pseudowire interface\n"
"Interface's name\n")
@@ -443,7 +443,7 @@ DEFPY (no_ldp_member_pseudowire,
DEFPY (ldp_vc_type,
ldp_vc_type_cmd,
"[no] vc type <ethernet|ethernet-tagged>$vc_type",
- "Negate a command or set its defaults\n"
+ NO_STR
"Virtual Circuit options\n"
"Virtual Circuit type to use\n"
"Ethernet (type 5)\n"
@@ -455,7 +455,7 @@ DEFPY (ldp_vc_type,
DEFPY (ldp_control_word,
ldp_control_word_cmd,
"[no] control-word <exclude|include>$preference",
- "Negate a command or set its defaults\n"
+ NO_STR
"Control-word options\n"
"Exclude control-word in pseudowire packets\n"
"Include control-word in pseudowire packets\n")
@@ -466,7 +466,7 @@ DEFPY (ldp_control_word,
DEFPY (ldp_neighbor_address,
ldp_neighbor_address_cmd,
"[no] neighbor address <A.B.C.D|X:X::X:X>$pw_address",
- "Negate a command or set its defaults\n"
+ NO_STR
"Remote endpoint configuration\n"
"Specify the IPv4 or IPv6 address of the remote endpoint\n"
"IPv4 address\n"
@@ -478,7 +478,7 @@ DEFPY (ldp_neighbor_address,
DEFPY (ldp_neighbor_lsr_id,
ldp_neighbor_lsr_id_cmd,
"[no] neighbor lsr-id A.B.C.D$address",
- "Negate a command or set its defaults\n"
+ NO_STR
"Remote endpoint configuration\n"
"Specify the LSR-ID of the remote endpoint\n"
"IPv4 address\n")
@@ -489,7 +489,7 @@ DEFPY (ldp_neighbor_lsr_id,
DEFPY (ldp_pw_id,
ldp_pw_id_cmd,
"[no] pw-id (1-4294967295)$pwid",
- "Negate a command or set its defaults\n"
+ NO_STR
"Set the Virtual Circuit ID\n"
"Virtual Circuit ID value\n")
{
@@ -499,7 +499,7 @@ DEFPY (ldp_pw_id,
DEFPY (ldp_pw_status_disable,
ldp_pw_status_disable_cmd,
"[no] pw-status disable",
- "Negate a command or set its defaults\n"
+ NO_STR
"Configure PW status\n"
"Disable PW status\n")
{
@@ -522,7 +522,7 @@ DEFPY (ldp_clear_mpls_ldp_neighbor,
DEFPY (ldp_debug_mpls_ldp_discovery_hello,
ldp_debug_mpls_ldp_discovery_hello_cmd,
"[no] debug mpls ldp discovery hello <recv|sent>$dir",
- "Negate a command or set its defaults\n"
+ NO_STR
"Debugging functions\n"
"MPLS information\n"
"Label Distribution Protocol\n"
@@ -537,7 +537,7 @@ DEFPY (ldp_debug_mpls_ldp_discovery_hello,
DEFPY (ldp_debug_mpls_ldp_type,
ldp_debug_mpls_ldp_type_cmd,
"[no] debug mpls ldp <errors|event|zebra>$type",
- "Negate a command or set its defaults\n"
+ NO_STR
"Debugging functions\n"
"MPLS information\n"
"Label Distribution Protocol\n"
@@ -551,7 +551,7 @@ DEFPY (ldp_debug_mpls_ldp_type,
DEFPY (ldp_debug_mpls_ldp_messages_recv,
ldp_debug_mpls_ldp_messages_recv_cmd,
"[no] debug mpls ldp messages recv [all]$all",
- "Negate a command or set its defaults\n"
+ NO_STR
"Debugging functions\n"
"MPLS information\n"
"Label Distribution Protocol\n"
@@ -565,7 +565,7 @@ DEFPY (ldp_debug_mpls_ldp_messages_recv,
DEFPY (ldp_debug_mpls_ldp_messages_sent,
ldp_debug_mpls_ldp_messages_sent_cmd,
"[no] debug mpls ldp messages sent [all]$all",
- "Negate a command or set its defaults\n"
+ NO_STR
"Debugging functions\n"
"MPLS information\n"
"Label Distribution Protocol\n"
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 79fff01c4c..ecc7db8f2e 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -52,6 +52,8 @@ static int ldp_interface_address_delete(int, struct zclient *,
zebra_size_t, vrf_id_t);
static int ldp_zebra_read_route(int, struct zclient *, zebra_size_t,
vrf_id_t);
+static int ldp_zebra_read_pw_status_update(int, struct zclient *,
+ zebra_size_t, vrf_id_t);
static void ldp_zebra_connected(struct zclient *);
static struct zclient *zclient;
@@ -64,7 +66,7 @@ ifp2kif(struct interface *ifp, struct kif *kif)
kif->ifindex = ifp->ifindex;
kif->operative = if_is_operative(ifp);
if (ifp->ll_type == ZEBRA_LLT_ETHER)
- memcpy(kif->mac, ifp->hw_addr, ETHER_ADDR_LEN);
+ memcpy(kif->mac, ifp->hw_addr, ETH_ALEN);
}
static void
@@ -92,6 +94,25 @@ ifc2kaddr(struct interface *ifp, struct connected *ifc, struct kaddr *ka)
}
}
+void
+pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw)
+{
+ memset(zpw, 0, sizeof(*zpw));
+ strlcpy(zpw->ifname, pw->ifname, sizeof(zpw->ifname));
+ zpw->ifindex = pw->ifindex;
+ zpw->type = pw->l2vpn->pw_type;
+ zpw->af = pw->af;
+ zpw->nexthop.ipv6 = pw->addr.v6;
+ zpw->local_label = NO_LABEL;
+ zpw->remote_label = NO_LABEL;
+ if (pw->flags & F_PW_CWORD)
+ zpw->flags = F_PSEUDOWIRE_CWORD;
+ zpw->data.ldp.lsr_id = pw->lsr_id;
+ zpw->data.ldp.pwid = pw->pwid;
+ strlcpy(zpw->data.ldp.vpn_name, pw->l2vpn->name,
+ sizeof(zpw->data.ldp.vpn_name));
+}
+
static int
zebra_send_mpls_labels(int cmd, struct kroute *kr)
{
@@ -152,17 +173,40 @@ kr_delete(struct kroute *kr)
}
int
-kmpw_set(struct kpw *kpw)
+kmpw_add(struct zapi_pw *zpw)
{
- /* TODO */
- return (0);
+ debug_zebra_out("pseudowire %s nexthop %s (add)",
+ zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop));
+
+ return (zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw));
}
int
-kmpw_unset(struct kpw *kpw)
+kmpw_del(struct zapi_pw *zpw)
{
- /* TODO */
- return (0);
+ debug_zebra_out("pseudowire %s nexthop %s (del)",
+ zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop));
+
+ return (zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw));
+}
+
+int
+kmpw_set(struct zapi_pw *zpw)
+{
+ debug_zebra_out("pseudowire %s nexthop %s labels %u/%u (set)",
+ zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop),
+ zpw->local_label, zpw->remote_label);
+
+ return (zebra_send_pw(zclient, ZEBRA_PW_SET, zpw));
+}
+
+int
+kmpw_unset(struct zapi_pw *zpw)
+{
+ debug_zebra_out("pseudowire %s nexthop %s (unset)",
+ zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop));
+
+ return (zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw));
}
void
@@ -464,6 +508,25 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
return (0);
}
+/*
+ * Receive PW status update from Zebra and send it to LDE process.
+ */
+static int
+ldp_zebra_read_pw_status_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct zapi_pw_status zpw;
+
+ zebra_read_pw_status_update(command, zclient, length, vrf_id, &zpw);
+
+ debug_zebra_in("pseudowire %s status %s", zpw.ifname,
+ (zpw.status == PW_STATUS_UP) ? "up" : "down");
+
+ main_imsg_compose_lde(IMSG_PW_UPDATE, 0, &zpw, sizeof(zpw));
+
+ return (0);
+}
+
static void
ldp_zebra_connected(struct zclient *zclient)
{
@@ -494,6 +557,7 @@ ldp_zebra_init(struct thread_master *master)
zclient->redistribute_route_ipv4_del = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
+ zclient->pw_status_update = ldp_zebra_read_pw_status_update;
}
void
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index abcad79d67..2d7afd5df8 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -578,21 +578,36 @@ main_dispatch_lde(struct thread *thread)
if (kr_delete(imsg.data))
log_warnx("%s: error deleting route", __func__);
break;
- case IMSG_KPWLABEL_CHANGE:
+ case IMSG_KPW_ADD:
+ case IMSG_KPW_DELETE:
+ case IMSG_KPW_SET:
+ case IMSG_KPW_UNSET:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(struct kpw))
+ sizeof(struct zapi_pw))
fatalx("invalid size of IMSG_KPWLABEL_CHANGE");
- if (kmpw_set(imsg.data))
- log_warnx("%s: error changing pseudowire",
- __func__);
- break;
- case IMSG_KPWLABEL_DELETE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(struct kpw))
- fatalx("invalid size of IMSG_KPWLABEL_DELETE");
- if (kmpw_unset(imsg.data))
- log_warnx("%s: error unsetting pseudowire",
- __func__);
+
+ switch (imsg.hdr.type) {
+ case IMSG_KPW_ADD:
+ if (kmpw_add(imsg.data))
+ log_warnx("%s: error adding "
+ "pseudowire", __func__);
+ break;
+ case IMSG_KPW_DELETE:
+ if (kmpw_del(imsg.data))
+ log_warnx("%s: error deleting "
+ "pseudowire", __func__);
+ break;
+ case IMSG_KPW_SET:
+ if (kmpw_set(imsg.data))
+ log_warnx("%s: error setting "
+ "pseudowire", __func__);
+ break;
+ case IMSG_KPW_UNSET:
+ if (kmpw_unset(imsg.data))
+ log_warnx("%s: error unsetting "
+ "pseudowire", __func__);
+ break;
+ }
break;
case IMSG_ACL_CHECK:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index 352a7b0d7e..31d0bc69b1 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -30,6 +30,8 @@
#include "prefix.h"
#include "filter.h"
#include "vty.h"
+#include "pw.h"
+#include "zclient.h"
#include "ldp.h"
@@ -44,7 +46,6 @@
#define LDPD_OPT_NOACTION 0x00000004
#define TCP_MD5_KEY_LEN 80
-#define L2VPN_NAME_LEN 32
#define RT_BUF_SIZE 16384
#define MAX_RTSOCK_BUF 128 * 1024
@@ -102,8 +103,10 @@ enum imsg_type {
IMSG_CTL_LOG_VERBOSE,
IMSG_KLABEL_CHANGE,
IMSG_KLABEL_DELETE,
- IMSG_KPWLABEL_CHANGE,
- IMSG_KPWLABEL_DELETE,
+ IMSG_KPW_ADD,
+ IMSG_KPW_DELETE,
+ IMSG_KPW_SET,
+ IMSG_KPW_UNSET,
IMSG_IFSTATUS,
IMSG_NEWADDR,
IMSG_DELADDR,
@@ -147,7 +150,8 @@ enum imsg_type {
IMSG_DEBUG_UPDATE,
IMSG_LOG,
IMSG_ACL_CHECK,
- IMSG_INIT
+ IMSG_INIT,
+ IMSG_PW_UPDATE
};
struct ldpd_init {
@@ -389,7 +393,7 @@ struct l2vpn_if {
char ifname[IF_NAMESIZE];
unsigned int ifindex;
int operative;
- uint8_t mac[ETHER_ADDR_LEN];
+ uint8_t mac[ETH_ALEN];
QOBJ_FIELDS
};
RB_HEAD(l2vpn_if_head, l2vpn_if);
@@ -407,6 +411,7 @@ struct l2vpn_pw {
unsigned int ifindex;
uint32_t remote_group;
uint16_t remote_mtu;
+ uint32_t local_status;
uint32_t remote_status;
uint8_t flags;
QOBJ_FIELDS
@@ -418,8 +423,7 @@ DECLARE_QOBJ_TYPE(l2vpn_pw)
#define F_PW_STATUSTLV 0x02 /* status tlv negotiated */
#define F_PW_CWORD_CONF 0x04 /* control word configured */
#define F_PW_CWORD 0x08 /* control word negotiated */
-#define F_PW_STATUS_UP 0x10 /* pseudowire is operational */
-#define F_PW_STATIC_NBR_ADDR 0x20 /* static neighbor address configured */
+#define F_PW_STATIC_NBR_ADDR 0x10 /* static neighbor address configured */
struct l2vpn {
RB_ENTRY(l2vpn) entry;
@@ -542,16 +546,6 @@ struct kroute {
uint16_t flags;
};
-struct kpw {
- unsigned short ifindex;
- int pw_type;
- int af;
- union ldpd_addr nexthop;
- uint32_t local_label;
- uint32_t remote_label;
- uint8_t flags;
-};
-
struct kaddr {
char ifname[IF_NAMESIZE];
unsigned short ifindex;
@@ -566,7 +560,7 @@ struct kif {
unsigned short ifindex;
int flags;
int operative;
- uint8_t mac[ETHER_ADDR_LEN];
+ uint8_t mac[ETH_ALEN];
int mtu;
};
@@ -668,11 +662,14 @@ struct ldpd_conf *parse_config(char *);
int cmdline_symset(char *);
/* kroute.c */
+void pw2zpw(struct l2vpn_pw *, struct zapi_pw *);
void kif_redistribute(const char *);
int kr_change(struct kroute *);
int kr_delete(struct kroute *);
-int kmpw_set(struct kpw *);
-int kmpw_unset(struct kpw *);
+int kmpw_add(struct zapi_pw *);
+int kmpw_del(struct zapi_pw *);
+int kmpw_set(struct zapi_pw *);
+int kmpw_unset(struct zapi_pw *);
/* util.c */
uint8_t mask2prefixlen(in_addr_t);
diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c
index f8d4b5f5fd..39860a1859 100644
--- a/ldpd/neighbor.c
+++ b/ldpd/neighbor.c
@@ -289,6 +289,8 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
void
nbr_del(struct nbr *nbr)
{
+ struct adj *adj;
+
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
@@ -314,6 +316,11 @@ nbr_del(struct nbr *nbr)
mapping_list_clr(&nbr->release_list);
mapping_list_clr(&nbr->abortreq_list);
+ while ((adj = RB_ROOT(nbr_adj_head, &nbr->adj_tree)) != NULL) {
+ adj->nbr = NULL;
+ RB_REMOVE(nbr_adj_head, &nbr->adj_tree, adj);
+ }
+
if (nbr->peerid)
RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);
diff --git a/lib/.gitignore b/lib/.gitignore
index 60cde149f5..94f401ebe6 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -1,4 +1,4 @@
-Makefile
+!Makefile
Makefile.in
*.o
*.lo
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000000..62051ac4cc
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,10 @@
+all: ALWAYS
+ @$(MAKE) -s -C .. lib/libfrr.la
+%: ALWAYS
+ @$(MAKE) -s -C .. lib/$@
+
+Makefile:
+ #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/lib/Makefile.am b/lib/Makefile.am
deleted file mode 100644
index 5847ad4939..0000000000
--- a/lib/Makefile.am
+++ /dev/null
@@ -1,155 +0,0 @@
-## Process this file with automake to produce Makefile.in.
-
-include ../common.am
-
-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
-AM_CFLAGS = $(WERROR)
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
-AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ @BISON_VERBOSE@
-
-command_lex.h: command_lex.c
- @if test ! -f $@; then rm -f command_lex.c; else :; fi
- @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) command_lex.c; else :; fi
-command_parse.lo: command_lex.h
-clippy-command_parse.$(OBJEXT): command_lex.h
-
-lib_LTLIBRARIES = libfrr.la
-libfrr_la_LDFLAGS = -version-info 0:0:0
-
-libfrr_la_SOURCES = \
- network.c pid_output.c getopt.c getopt1.c \
- checksum.c vector.c linklist.c vty.c openbsd-tree.c \
- graph.c command_parse.y command_lex.l command_match.c \
- command_graph.c \
- command.c \
- sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \
- filter.c routemap.c distribute.c stream.c log.c plist.c \
- zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \
- sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
- ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
- imsg-buffer.c imsg.c skiplist.c \
- qobj.c wheel.c \
- event_counter.c \
- grammar_sandbox.c \
- srcdest_table.c \
- spf_backoff.c \
- libfrr.c \
- strlcpy.c \
- strlcat.c \
- sha256.c \
- module.c \
- hook.c \
- frr_pthread.c \
- termtable.c \
- # end
-
-BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h
-
-libfrr_la_LIBADD = @LIBCAP@
-
-if SNMP
-lib_LTLIBRARIES += libfrrsnmp.la
-endif
-
-libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
-libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
-libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS)
-libfrrsnmp_la_SOURCES = \
- agentx.c \
- smux.c \
- snmp.c \
- #end
-
-pkginclude_HEADERS = \
- frratomic.h \
- buffer.h checksum.h filter.h getopt.h hash.h \
- if.h linklist.h log.h \
- graph.h command_match.h \
- command_graph.h \
- command.h \
- memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
- stream.h table.h thread.h vector.h version.h vty.h zebra.h \
- 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 \
- workqueue.h route_types.h libospf.h nexthop.h json.h \
- ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h \
- fifo.h memory_vty.h mpls.h imsg.h openbsd-queue.h openbsd-tree.h \
- skiplist.h qobj.h wheel.h \
- event_counter.h \
- monotime.h \
- spf_backoff.h \
- srcdest_table.h \
- module.h \
- hook.h \
- libfrr.h \
- sha256.h \
- frr_pthread.h \
- vrf_int.h \
- termtable.h \
- vlan.h \
- vxlan.h \
- ipaddr.h \
- # end
-
-noinst_HEADERS = \
- plist_int.h \
- log_int.h \
- clippy.h \
- # end
-
-noinst_PROGRAMS = grammar_sandbox
-if BUILD_CLIPPY
-noinst_PROGRAMS += clippy
-endif
-
-grammar_sandbox_SOURCES = grammar_sandbox_main.c
-grammar_sandbox_LDADD = libfrr.la
-
-clippy_SOURCES = \
- defun_lex.l \
- command_parse.y \
- command_lex.l \
- command_graph.c \
- command_py.c \
- memory.c \
- graph.c \
- vector.c \
- clippy.c \
- # end
-clippy_CPPFLAGS = -D_GNU_SOURCE
-clippy_CFLAGS = $(PYTHON_CFLAGS)
-clippy_LDADD = $(PYTHON_LIBS)
-clippy-command_graph.$(OBJEXT): route_types.h
-
-plist.lo: plist_clippy.c
-
-EXTRA_DIST = \
- queue.h \
- command_lex.h \
- route_types.pl route_types.txt \
- gitversion.pl
-
-route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl
- @PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@
-
-if GIT_VERSION
-
-# bit of a trick here to always have up-to-date git stamps without triggering
-# unneccessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
-# but if we use that on gitversion.h it'll ripple through the .c file deps.
-# (even if gitversion.h's file timestamp doesn't change, make will think it
-# did, because of .PHONY...)
-
-.PHONY: gitversion.h.tmp
-.SILENT: gitversion.h gitversion.h.tmp
-GITH=gitversion.h
-gitversion.h.tmp: $(srcdir)/../.git
- @PERL@ $(srcdir)/gitversion.pl $(srcdir) > ${GITH}.tmp
-gitversion.h: gitversion.h.tmp
- { test -f ${GITH} && diff -s -q ${GITH}.tmp ${GITH}; } || cp -v ${GITH}.tmp ${GITH}
-
-else
-.PHONY: gitversion.h
-gitversion.h:
- true
-endif
diff --git a/lib/command.c b/lib/command.c
index f28a55ec6d..09ffa6ce56 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -110,6 +110,7 @@ const char *node_names[] = {
"forwarding", // FORWARDING_NODE,
"protocol", // PROTOCOL_NODE,
"mpls", // MPLS_NODE,
+ "pw", // PW_NODE,
"vty", // VTY_NODE,
"link-params", // LINK_PARAMS_NODE,
"bgp evpn vni", // BGP_EVPN_VNI_NODE,
@@ -1253,6 +1254,7 @@ void cmd_exit(struct vty *vty)
vty_config_unlock(vty);
break;
case INTERFACE_NODE:
+ case PW_NODE:
case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
@@ -1338,6 +1340,7 @@ DEFUN (config_end,
break;
case CONFIG_NODE:
case INTERFACE_NODE:
+ case PW_NODE:
case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
diff --git a/lib/command.h b/lib/command.h
index 533b4b3289..d0c9f0eaf9 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -132,6 +132,7 @@ enum node_type {
FORWARDING_NODE, /* IP forwarding node. */
PROTOCOL_NODE, /* protocol filtering node */
MPLS_NODE, /* MPLS config node */
+ PW_NODE, /* Pseudowire config node */
VTY_NODE, /* Vty node. */
LINK_PARAMS_NODE, /* Link-parameters node */
BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */
@@ -181,6 +182,7 @@ struct cmd_node {
#define CMD_ERR_NO_FILE 11
#define CMD_SUSPEND 12
#define CMD_WARNING_CONFIG_FAILED 13
+#define CMD_NOT_MY_INSTANCE 14
/* Argc max counts. */
#define CMD_ARGC_MAX 25
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 3efa4d5cfc..dc7233c1fe 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -385,7 +385,6 @@ static void cmd_node_names(struct graph_node *gn, struct graph_node *join,
break;
case START_TKN:
- case END_TKN:
case JOIN_TKN:
/* "<foo|bar> WORD" -> word is not "bar" or "foo" */
prevname = NULL;
@@ -405,6 +404,9 @@ static void cmd_node_names(struct graph_node *gn, struct graph_node *join,
cmd_token_varname_set(tailtok, jointok->varname);
}
break;
+
+ case END_TKN:
+ return;
}
for (i = 0; i < vector_active(gn->to); i++) {
diff --git a/lib/command_lex.l b/lib/command_lex.l
index c020d193a1..fddbf7b287 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -49,8 +49,8 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
%option noyywrap
%option nounput
%option noinput
-%option outfile="command_lex.c"
-%option header-file="command_lex.h"
+%option outfile="lib/command_lex.c"
+%option header-file="lib/command_lex.h"
%option prefix="cmd_yy"
%option reentrant
%option bison-bridge
diff --git a/lib/command_parse.y b/lib/command_parse.y
index ba042c33be..1bc8ea1a44 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -33,8 +33,8 @@
/* define api.prefix {cmd_yy} */
/* names for generated header and parser files */
-%defines "command_parse.h"
-%output "command_parse.c"
+%defines "lib/command_parse.h"
+%output "lib/command_parse.c"
/* note: code blocks are output in order, to both .c and .h:
* 1. %code requires
diff --git a/lib/defun_lex.l b/lib/defun_lex.l
index 8aa37a62a2..024445be63 100644
--- a/lib/defun_lex.l
+++ b/lib/defun_lex.l
@@ -85,7 +85,7 @@ SPECIAL [(),]
%option noyywrap
%option noinput
%option nounput
-%option outfile="defun_lex.c"
+%option outfile="lib/defun_lex.c"
%option prefix="def_yy"
%option 8bit
diff --git a/lib/hash.c b/lib/hash.c
index a7714f1569..801871f839 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -94,6 +94,10 @@ static void hash_expand(struct hash *hash)
struct hash_backet *hb, *hbnext, **new_index;
new_size = hash->size * 2;
+
+ if (hash->max_size && new_size > hash->max_size)
+ return;
+
new_index = XCALLOC(MTYPE_HASH_INDEX,
sizeof(struct hash_backet *) * new_size);
if (new_index == NULL)
@@ -354,33 +358,26 @@ DEFUN(show_hash_stats,
/* Summary statistics calculated are:
*
- * - Load factor: This is the number of elements in the table divided by
- * the
- * number of buckets. Since this hash table implementation uses
- * chaining,
- * this value can be greater than 1. This number provides information
- * on
- * how 'full' the table is, but does not provide information on how
- * evenly
- * distributed the elements are. Notably, a load factor >= 1 does not
- * imply
- * that every bucket has an element; with a pathological hash
- * function, all
- * elements could be in a single bucket.
+ * - Load factor: This is the number of elements in the table divided
+ * by the number of buckets. Since this hash table implementation
+ * uses chaining, this value can be greater than 1.
+ * This number provides information on how 'full' the table is, but
+ * does not provide information on how evenly distributed the
+ * elements are.
+ * Notably, a load factor >= 1 does not imply that every bucket has
+ * an element; with a pathological hash function, all elements could
+ * be in a single bucket.
*
* - Full load factor: this is the number of elements in the table
- * divided by
- * the number of buckets that have some elements in them.
+ * divided by the number of buckets that have some elements in them.
*
* - Std. Dev.: This is the standard deviation calculated from the
- * relevant
- * load factor. If the load factor is the mean of number of elements
- * per
- * bucket, the standard deviation measures how much any particular
- * bucket
- * is likely to deviate from the mean. As a rule of thumb this number
- * should be less than 2, and ideally <= 1 for optimal performance. A
- * number larger than 3 generally indicates a poor hash function.
+ * relevant load factor. If the load factor is the mean of number of
+ * elements per bucket, the standard deviation measures how much any
+ * particular bucket is likely to deviate from the mean.
+ * As a rule of thumb this number should be less than 2, and ideally
+ * <= 1 for optimal performance. A number larger than 3 generally
+ * indicates a poor hash function.
*/
double lf; // load factor
@@ -407,7 +404,7 @@ DEFUN(show_hash_stats,
continue;
ssq = (long double)h->stats.ssq;
- x2 = powl(h->count, 2.0);
+ x2 = h->count * h->count;
ldc = (long double)h->count;
full = h->size - h->stats.empty;
lf = h->count / (double)h->size;
diff --git a/lib/hash.h b/lib/hash.h
index 6ce29f0426..236abbbd6a 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -64,6 +64,9 @@ struct hash {
/* Hash table size. Must be power of 2 */
unsigned int size;
+ /* If max_size is 0 there is no limit */
+ unsigned int max_size;
+
/* Key make function. */
unsigned int (*hash_key)(void *);
diff --git a/lib/libospf.h b/lib/libospf.h
index c9483a4c65..45aedb6a7d 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -34,7 +34,7 @@
/* Architectual Constants */
#ifdef DEBUG
-#define OSPF_LS_REFRESH_TIME 60
+#define OSPF_LS_REFRESH_TIME 120
#else
#define OSPF_LS_REFRESH_TIME 1800
#endif
diff --git a/lib/log.c b/lib/log.c
index 28e0865354..63afbf5137 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -857,6 +857,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_DELETE),
DESC_ENTRY(ZEBRA_INTERFACE_UP),
DESC_ENTRY(ZEBRA_INTERFACE_DOWN),
+ DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
@@ -915,6 +916,11 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_MACIP_DEL),
DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD),
DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL),
+ DESC_ENTRY(ZEBRA_PW_ADD),
+ DESC_ENTRY(ZEBRA_PW_DELETE),
+ DESC_ENTRY(ZEBRA_PW_SET),
+ DESC_ENTRY(ZEBRA_PW_UNSET),
+ DESC_ENTRY(ZEBRA_PW_STATUS_UPDATE),
};
#undef DESC_ENTRY
diff --git a/lib/monotime.h b/lib/monotime.h
index 7bd3386498..8e50c1874a 100644
--- a/lib/monotime.h
+++ b/lib/monotime.h
@@ -49,6 +49,10 @@ static inline time_t monotime(struct timeval *tvo)
return ts.tv_sec;
}
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
+#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
+
/* the following two return microseconds, not time_t!
*
* also, they're negative forms of each other, but having both makes the
diff --git a/lib/prefix.c b/lib/prefix.c
index 88b13cd99f..33b6ff1987 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -26,6 +26,7 @@
#include "sockunion.h"
#include "memory.h"
#include "log.h"
+#include "jhash.h"
DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix")
@@ -507,8 +508,9 @@ const char *safi2str(safi_t safi)
return "evpn";
case SAFI_LABELED_UNICAST:
return "labeled-unicast";
+ default:
+ return "unknown";
}
- return NULL;
}
/* If n includes p prefix then return 1 else return 0. */
@@ -1060,7 +1062,7 @@ int prefix_blen(const struct prefix *p)
return IPV6_MAX_BYTELEN;
break;
case AF_ETHERNET:
- return ETHER_ADDR_LEN;
+ return ETH_ALEN;
}
return 0;
}
@@ -1334,3 +1336,15 @@ char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
(uint8_t)mac->octet[4], (uint8_t)mac->octet[5]);
return ptr;
}
+
+unsigned prefix_hash_key(void *pp)
+{
+ struct prefix copy;
+
+ /* make sure *all* unused bits are zero, particularly including
+ * alignment /
+ * padding and unused prefix bytes. */
+ memset(&copy, 0, sizeof(copy));
+ prefix_copy(&copy, (struct prefix *)pp);
+ return jhash(&copy, sizeof(copy), 0x55aa5a5a);
+}
diff --git a/lib/prefix.h b/lib/prefix.h
index ce13dcfa0a..5f2b57ccce 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -34,21 +34,39 @@
#include "sockunion.h"
#include "ipaddr.h"
-#ifndef ETHER_ADDR_LEN
-#ifdef ETHERADDRL
-#define ETHER_ADDR_LEN ETHERADDRL
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+/* for compatibility */
+#if defined(__ICC)
+#define CPP_WARN_STR(X) #X
+#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text))
+
+#elif (defined(__GNUC__) \
+ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
+ || (defined(__clang__) \
+ && (__clang_major__ >= 4 \
+ || (__clang_major__ == 3 && __clang_minor__ >= 5)))
+#define CPP_WARN_STR(X) #X
+#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text))
+
#else
-#define ETHER_ADDR_LEN 6
+#define CPP_WARN(text)
#endif
+
+#ifdef ETHER_ADDR_LEN
+#undef ETHER_ADDR_LEN
#endif
+#define ETHER_ADDR_LEN 6 CPP_WARN("ETHER_ADDR_LEN is being replaced by ETH_ALEN.\\n")
-#define ETHER_ADDR_STRLEN (3*ETHER_ADDR_LEN)
+#define ETHER_ADDR_STRLEN (3*ETH_ALEN)
/*
* there isn't a portable ethernet address type. We define our
* own to simplify internal handling
*/
struct ethaddr {
- u_char octet[ETHER_ADDR_LEN];
+ u_char octet[ETH_ALEN];
} __attribute__((packed));
@@ -323,6 +341,8 @@ extern const char *inet6_ntoa(struct in6_addr);
extern int prefix_str2mac(const char *str, struct ethaddr *mac);
extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size);
+extern unsigned prefix_hash_key(void *pp);
+
static inline int ipv6_martian(struct in6_addr *addr)
{
struct in6_addr localhost_addr;
diff --git a/lib/pw.h b/lib/pw.h
new file mode 100644
index 0000000000..2cfaa47e5d
--- /dev/null
+++ b/lib/pw.h
@@ -0,0 +1,52 @@
+/* Pseudowire definitions
+ * Copyright (C) 2016 Volta Networks, Inc.
+ *
+ * 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
+ */
+
+#ifndef _FRR_PW_H
+#define _FRR_PW_H
+
+/* L2VPN name length. */
+#define L2VPN_NAME_LEN 32
+
+/* Pseudowire type - LDP and BGP use the same values. */
+#define PW_TYPE_ETHERNET_TAGGED 0x0004 /* RFC 4446 */
+#define PW_TYPE_ETHERNET 0x0005 /* RFC 4446 */
+#define PW_TYPE_WILDCARD 0x7FFF /* RFC 4863, RFC 6668 */
+
+/* Pseudowire flags. */
+#define F_PSEUDOWIRE_CWORD 0x01
+
+/* Pseudowire status. */
+#define PW_STATUS_DOWN 0
+#define PW_STATUS_UP 1
+
+/*
+ * Protocol-specific information about the pseudowire.
+ */
+union pw_protocol_fields {
+ struct {
+ struct in_addr lsr_id;
+ uint32_t pwid;
+ char vpn_name[L2VPN_NAME_LEN];
+ } ldp;
+ struct {
+ /* TODO */
+ } bgp;
+};
+
+#endif /* _FRR_PW_H */
diff --git a/lib/sbuf.c b/lib/sbuf.c
new file mode 100644
index 0000000000..37c1e5283d
--- /dev/null
+++ b/lib/sbuf.c
@@ -0,0 +1,107 @@
+/*
+ * Simple string buffer
+ *
+ * Copyright (C) 2017 Christian Franke
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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.
+ *
+ * FRR 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 FRR; 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 "sbuf.h"
+#include "memory.h"
+
+void sbuf_init(struct sbuf *dest, char *buf, size_t size)
+{
+ dest->fixed = (size > 0);
+ if (dest->fixed) {
+ dest->buf = buf;
+ dest->size = size;
+ } else {
+ dest->buf = XMALLOC(MTYPE_TMP, 4096);
+ dest->size = 4096;
+ }
+
+ dest->pos = 0;
+ dest->buf[0] = '\0';
+}
+
+void sbuf_reset(struct sbuf *dest)
+{
+ dest->pos = 0;
+ dest->buf[0] = '\0';
+}
+
+const char *sbuf_buf(struct sbuf *buf)
+{
+ return buf->buf;
+}
+
+void sbuf_free(struct sbuf *buf)
+{
+ if (!buf->fixed)
+ XFREE(MTYPE_TMP, buf->buf);
+}
+
+void sbuf_push(struct sbuf *buf, int indent, const char *format, ...)
+{
+ va_list args;
+ int written;
+
+ if (!buf->fixed) {
+ char dummy;
+ int written1, written2;
+ size_t new_size;
+
+ written1 = snprintf(&dummy, 0, "%*s", indent, "");
+ va_start(args, format);
+ written2 = vsnprintf(&dummy, 0, format, args);
+ va_end(args);
+
+ new_size = buf->size;
+ if (written1 >= 0 && written2 >= 0) {
+ while (buf->pos + written1 + written2 >= new_size)
+ new_size *= 2;
+ if (new_size > buf->size) {
+ buf->buf =
+ XREALLOC(MTYPE_TMP, buf->buf, new_size);
+ buf->size = new_size;
+ }
+ }
+ }
+
+ written = snprintf(buf->buf + buf->pos, buf->size - buf->pos, "%*s",
+ indent, "");
+
+ if (written >= 0)
+ buf->pos += written;
+ if (buf->pos > buf->size)
+ buf->pos = buf->size;
+
+ va_start(args, format);
+ written = vsnprintf(buf->buf + buf->pos, buf->size - buf->pos, format,
+ args);
+ va_end(args);
+
+ if (written >= 0)
+ buf->pos += written;
+ if (buf->pos > buf->size)
+ buf->pos = buf->size;
+
+ if (buf->pos == buf->size)
+ assert(!"Buffer filled up!");
+}
diff --git a/lib/sbuf.h b/lib/sbuf.h
new file mode 100644
index 0000000000..3e49ada6c2
--- /dev/null
+++ b/lib/sbuf.h
@@ -0,0 +1,77 @@
+/*
+ * Simple string buffer
+ *
+ * Copyright (C) 2017 Christian Franke
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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.
+ *
+ * FRR 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef SBUF_H
+#define SBUF_H
+
+/*
+ * sbuf provides a simple string buffer. One application where this comes
+ * in handy is the parsing of binary data: If there is an error in the parsing
+ * process due to invalid input data, printing an error message explaining what
+ * went wrong is definitely useful. However, just printing the actual error,
+ * without any information about the previous parsing steps, is usually not very
+ * helpful.
+ * Using sbuf, the parser can log the whole parsing process into a buffer using
+ * a printf like API. When an error ocurrs, all the information about previous
+ * parsing steps is there in the log, without any need for backtracking, and can
+ * be used to give a detailed and useful error description.
+ * When parsing completes successfully without any error, the log can just be
+ * discarded unless debugging is turned on, to not spam the log.
+ *
+ * For the described usecase, the code would look something like this:
+ *
+ * int sbuf_example(..., char **parser_log)
+ * {
+ * struct sbuf logbuf;
+ *
+ * sbuf_init(&logbuf, NULL, 0);
+ * sbuf_push(&logbuf, 0, "Starting parser\n");
+ *
+ * int rv = do_parse(&logbuf, ...);
+ *
+ * *parser_log = sbuf_buf(&logbuf);
+ *
+ * return 1;
+ * }
+ *
+ * In this case, sbuf_example uses a string buffer with undefined size, which will
+ * be allocated on the heap by sbuf. The caller of sbuf_example is expected to free
+ * the string returned in parser_log.
+ */
+
+struct sbuf {
+ bool fixed;
+ char *buf;
+ size_t size;
+ size_t pos;
+ int indent;
+};
+
+void sbuf_init(struct sbuf *dest, char *buf, size_t size);
+void sbuf_reset(struct sbuf *buf);
+const char *sbuf_buf(struct sbuf *buf);
+void sbuf_free(struct sbuf *buf);
+#include "lib/log.h"
+void sbuf_push(struct sbuf *buf, int indent, const char *format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+
+#endif
diff --git a/lib/sockunion.c b/lib/sockunion.c
index af0054d6b2..559ae37ffb 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -354,13 +354,19 @@ int sockopt_ttl(int family, int sock, int ttl)
return 0;
}
+/*
+ * This function called setsockopt(.., TCP_CORK,...)
+ * Which on linux is a no-op since it is enabled by
+ * default and on BSD it uses TCP_NOPUSH to do
+ * the same thing( which it was not configured to
+ * use). This cleanup of the api occured on 8/1/17
+ * I imagine if after more than 1 year of no-one
+ * complaining, and a major upgrade release we
+ * can deprecate and remove this function call
+ */
int sockopt_cork(int sock, int onoff)
{
-#ifdef TCP_CORK
- return setsockopt(sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
-#else
return 0;
-#endif
}
int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *cap)
diff --git a/lib/subdir.am b/lib/subdir.am
new file mode 100644
index 0000000000..15ce8ec199
--- /dev/null
+++ b/lib/subdir.am
@@ -0,0 +1,263 @@
+#
+# libfrr
+#
+lib_LTLIBRARIES += lib/libfrr.la
+lib_libfrr_la_LDFLAGS = -version-info 0:0:0
+lib_libfrr_la_LIBADD = @LIBCAP@
+
+lib_libfrr_la_SOURCES = \
+ lib/bfd.c \
+ lib/buffer.c \
+ lib/checksum.c \
+ lib/command.c \
+ lib/command_graph.c \
+ lib/command_lex.l \
+ lib/command_match.c \
+ lib/command_parse.y \
+ lib/csv.c \
+ lib/distribute.c \
+ lib/event_counter.c \
+ lib/filter.c \
+ lib/frr_pthread.c \
+ lib/getopt.c \
+ lib/getopt1.c \
+ lib/grammar_sandbox.c \
+ lib/graph.c \
+ lib/hash.c \
+ lib/hook.c \
+ lib/if.c \
+ lib/if_rmap.c \
+ lib/imsg-buffer.c \
+ lib/imsg.c \
+ lib/jhash.c \
+ lib/json.c \
+ lib/keychain.c \
+ lib/libfrr.c \
+ lib/linklist.c \
+ lib/log.c \
+ lib/md5.c \
+ lib/memory.c \
+ lib/memory_vty.c \
+ lib/module.c \
+ lib/network.c \
+ lib/nexthop.c \
+ lib/ns.c \
+ lib/openbsd-tree.c \
+ lib/pid_output.c \
+ lib/plist.c \
+ lib/pqueue.c \
+ lib/prefix.c \
+ lib/privs.c \
+ lib/ptm_lib.c \
+ lib/qobj.c \
+ lib/routemap.c \
+ lib/sbuf.c \
+ lib/sha256.c \
+ lib/sigevent.c \
+ lib/skiplist.c \
+ lib/sockopt.c \
+ lib/sockunion.c \
+ lib/spf_backoff.c \
+ lib/srcdest_table.c \
+ lib/stream.c \
+ lib/strlcat.c \
+ lib/strlcpy.c \
+ lib/systemd.c \
+ lib/table.c \
+ lib/termtable.c \
+ lib/thread.c \
+ lib/vector.c \
+ lib/vrf.c \
+ lib/vty.c \
+ lib/wheel.c \
+ lib/workqueue.c \
+ lib/zclient.c \
+ # end
+
+lib/plist_clippy.c: $(CLIPPY_DEPS)
+lib/plist.lo: lib/plist_clippy.c
+
+pkginclude_HEADERS += \
+ lib/bfd.h \
+ lib/bitfield.h \
+ lib/buffer.h \
+ lib/checksum.h \
+ lib/command.h \
+ lib/command_graph.h \
+ lib/command_match.h \
+ lib/csv.h \
+ lib/distribute.h \
+ lib/event_counter.h \
+ lib/fifo.h \
+ lib/filter.h \
+ lib/frr_pthread.h \
+ lib/frratomic.h \
+ lib/getopt.h \
+ lib/graph.h \
+ lib/hash.h \
+ lib/hook.h \
+ lib/if.h \
+ lib/if_rmap.h \
+ lib/imsg.h \
+ lib/ipaddr.h \
+ lib/jhash.h \
+ lib/json.h \
+ lib/keychain.h \
+ lib/libfrr.h \
+ lib/libospf.h \
+ lib/linklist.h \
+ lib/log.h \
+ lib/md5.h \
+ lib/memory.h \
+ lib/memory_vty.h \
+ lib/module.h \
+ lib/monotime.h \
+ lib/mpls.h \
+ lib/network.h \
+ lib/nexthop.h \
+ lib/ns.h \
+ lib/openbsd-queue.h \
+ lib/openbsd-tree.h \
+ lib/plist.h \
+ lib/pqueue.h \
+ lib/prefix.h \
+ lib/privs.h \
+ lib/ptm_lib.h \
+ lib/pw.h \
+ lib/qobj.h \
+ lib/route_types.h \
+ lib/routemap.h \
+ lib/sbuf.h \
+ lib/sha256.h \
+ lib/sigevent.h \
+ lib/skiplist.h \
+ lib/smux.h \
+ lib/sockopt.h \
+ lib/sockunion.h \
+ lib/spf_backoff.h \
+ lib/srcdest_table.h \
+ lib/stream.h \
+ lib/systemd.h \
+ lib/table.h \
+ lib/termtable.h \
+ lib/thread.h \
+ lib/vector.h \
+ lib/version.h \
+ lib/vlan.h \
+ lib/vrf.h \
+ lib/vrf_int.h \
+ lib/vty.h \
+ lib/vxlan.h \
+ lib/wheel.h \
+ lib/workqueue.h \
+ lib/zassert.h \
+ lib/zclient.h \
+ lib/zebra.h \
+ # end
+
+noinst_HEADERS += \
+ lib/clippy.h \
+ lib/log_int.h \
+ lib/plist_int.h \
+ #end
+
+#
+# SNMP support
+#
+if SNMP
+lib_LTLIBRARIES += lib/libfrrsnmp.la
+endif
+
+lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
+lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
+lib_libfrrsnmp_la_SOURCES = \
+ lib/agentx.c \
+ lib/smux.c \
+ lib/snmp.c \
+ # end
+
+#
+# CLI utilities
+#
+noinst_PROGRAMS += \
+ lib/clippy \
+ lib/grammar_sandbox \
+ # end
+
+lib_grammar_sandbox_SOURCES = \
+ lib/grammar_sandbox_main.c
+lib_grammar_sandbox_LDADD = \
+ lib/libfrr.la
+
+lib_clippy_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/lib
+lib_clippy_CFLAGS = $(PYTHON_CFLAGS)
+lib_clippy_LDADD = $(PYTHON_LIBS)
+lib_clippy_SOURCES = \
+ lib/clippy.c \
+ lib/command_graph.c \
+ lib/command_lex.l \
+ lib/command_parse.y \
+ lib/command_py.c \
+ lib/defun_lex.l \
+ lib/graph.c \
+ lib/memory.c \
+ lib/vector.c \
+ # end
+
+
+#
+# generated sources & extra foo
+#
+EXTRA_DIST += \
+ lib/command_lex.h \
+ lib/gitversion.pl \
+ lib/queue.h \
+ lib/route_types.pl \
+ lib/route_types.txt \
+ # end
+
+BUILT_SOURCES += \
+ lib/command_lex.h \
+ lib/command_parse.h \
+ lib/gitversion.h \
+ lib/route_types.h \
+ # end
+
+## force route_types.h
+$(lib_clippy_OBJECTS): lib/route_types.h
+$(lib_libfrr_la_OBJECTS): lib/route_types.h
+
+AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ @BISON_VERBOSE@
+
+lib/command_lex.h: lib/command_lex.c
+ @if test ! -f $@; then rm -f "lib/command_lex.c"; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) "lib/command_lex.c"; else :; fi
+lib/command_lex.lo: lib/command_parse.h
+lib/command_parse.lo: lib/command_lex.h
+lib/lib_clippy-command_lex.$(OBJEXT): lib/command_parse.h
+lib/lib_clippy-command_parse.$(OBJEXT): lib/command_lex.h
+
+lib/route_types.h: $(top_srcdir)/lib/route_types.txt $(top_srcdir)/lib/route_types.pl
+ @PERL@ $(top_srcdir)/lib/route_types.pl < $(top_srcdir)/lib/route_types.txt > $@
+
+if GIT_VERSION
+# bit of a trick here to always have up-to-date git stamps without triggering
+# unneccessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
+# but if we use that on gitversion.h it'll ripple through the .c file deps.
+# (even if gitversion.h's file timestamp doesn't change, make will think it
+# did, because of .PHONY...)
+
+.PHONY: lib/gitversion.h.tmp
+.SILENT: lib/gitversion.h lib/gitversion.h.tmp
+GITH=lib/gitversion.h
+lib/gitversion.h.tmp: $(top_srcdir)/.git
+ @PERL@ $(top_srcdir)/lib/gitversion.pl $(top_srcdir) > ${GITH}.tmp
+lib/gitversion.h: lib/gitversion.h.tmp
+ { test -f ${GITH} && diff -s -q ${GITH}.tmp ${GITH}; } || cp ${GITH}.tmp ${GITH}
+
+else
+.PHONY: lib/gitversion.h
+lib/gitversion.h:
+ true
+endif
diff --git a/lib/table.c b/lib/table.c
index 2defa4fb62..833adb9a37 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -27,7 +27,6 @@
#include "table.h"
#include "memory.h"
#include "sockunion.h"
-#include "jhash.h"
DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table")
DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node")
@@ -35,18 +34,6 @@ DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node")
static void route_node_delete(struct route_node *);
static void route_table_free(struct route_table *);
-static unsigned route_table_hash_key(void *pp)
-{
- struct prefix copy;
-
- /* make sure *all* unused bits are zero, particularly including
- * alignment /
- * padding and unused prefix bytes. */
- memset(&copy, 0, sizeof(copy));
- prefix_copy(&copy, (struct prefix *)pp);
- return jhash(&copy, sizeof(copy), 0x55aa5a5a);
-}
-
static int route_table_hash_cmp(const void *a, const void *b)
{
const struct prefix *pa = a, *pb = b;
@@ -63,7 +50,7 @@ route_table_init_with_delegate(route_table_delegate_t *delegate)
rt = XCALLOC(MTYPE_ROUTE_TABLE, sizeof(struct route_table));
rt->delegate = delegate;
- rt->hash = hash_create(route_table_hash_key, route_table_hash_cmp,
+ rt->hash = hash_create(prefix_hash_key, route_table_hash_cmp,
"route table hash");
return rt;
}
@@ -88,6 +75,7 @@ static struct route_node *route_node_set(struct route_table *table,
node = route_node_new(table);
prefix_copy(&node->p, prefix);
+ apply_mask(&node->p);
node->table = table;
inserted = hash_get(node->table->hash, node, hash_alloc_intern);
diff --git a/lib/thread.c b/lib/thread.c
index 5db470ef48..4a5c61d036 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -47,6 +47,9 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
write(m->io_pipe[1], &wakebyte, 1); \
} while (0);
+/* max # of thread_fetch() calls before we force a poll() */
+#define MAX_TICK_IO 1000
+
/* control variable for initializer */
pthread_once_t init_once = PTHREAD_ONCE_INIT;
pthread_key_t thread_current;
@@ -337,9 +340,6 @@ static void cancelreq_del(void *cr)
/* initializer, only ever called once */
static void initializer()
{
- if (!masters)
- masters = list_new();
-
pthread_key_create(&thread_current, NULL);
}
@@ -412,9 +412,12 @@ struct thread_master *thread_master_create(const char *name)
rv->handler.copy = XCALLOC(MTYPE_THREAD_MASTER,
sizeof(struct pollfd) * rv->handler.pfdsize);
- /* add to list */
+ /* add to list of threadmasters */
pthread_mutex_lock(&masters_mtx);
{
+ if (!masters)
+ masters = list_new();
+
listnode_add(masters, rv);
}
pthread_mutex_unlock(&masters_mtx);
@@ -548,6 +551,10 @@ void thread_master_free(struct thread_master *m)
pthread_mutex_lock(&masters_mtx);
{
listnode_delete(masters, m);
+ if (masters->count == 0) {
+ list_free (masters);
+ masters = NULL;
+ }
}
pthread_mutex_unlock(&masters_mtx);
@@ -1312,16 +1319,16 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
/* Process any pending cancellation requests */
do_thread_cancel(m);
- /* Post events to ready queue. This must come before the
- * following block
- * since events should occur immediately */
+ /*
+ * Post events to ready queue. This must come before the
+ * following block since events should occur immediately
+ */
thread_process(&m->event);
- /* If there are no tasks on the ready queue, we will poll()
- * until a timer
- * expires or we receive I/O, whichever comes first. The
- * strategy for doing
- * this is:
+ /*
+ * If there are no tasks on the ready queue, we will poll()
+ * until a timer expires or we receive I/O, whichever comes
+ * first. The strategy for doing this is:
*
* - If there are events pending, set the poll() timeout to zero
* - If there are no events pending, but there are timers
@@ -1333,9 +1340,8 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
* - If nothing is pending, it's time for the application to die
*
* In every case except the last, we need to hit poll() at least
- * once per
- * loop to avoid starvation by events */
-
+ * once per loop to avoid starvation by events
+ */
if (m->ready.count == 0)
tw = thread_timer_wait(m->timer, &tv);
@@ -1348,37 +1354,53 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
break;
}
- /* Copy pollfd array + # active pollfds in it. Not necessary to
- * copy
- * the array size as this is fixed. */
+ /*
+ * Copy pollfd array + # active pollfds in it. Not necessary to
+ * copy the array size as this is fixed.
+ */
m->handler.copycount = m->handler.pfdcount;
memcpy(m->handler.copy, m->handler.pfds,
m->handler.copycount * sizeof(struct pollfd));
- pthread_mutex_unlock(&m->mtx);
- {
- num = fd_poll(m, m->handler.copy, m->handler.pfdsize,
- m->handler.copycount, tw);
- }
- pthread_mutex_lock(&m->mtx);
+ /*
+ * Attempt to flush ready queue before going into poll().
+ * This is performance-critical. Think twice before modifying.
+ */
+ if (m->ready.count == 0 || m->tick_since_io >= MAX_TICK_IO) {
+ pthread_mutex_unlock(&m->mtx);
+ {
+ m->tick_since_io = 0;
+ num = fd_poll(m, m->handler.copy,
+ m->handler.pfdsize,
+ m->handler.copycount, tw);
+ }
+ pthread_mutex_lock(&m->mtx);
+
+ /* Handle any errors received in poll() */
+ if (num < 0) {
+ if (errno == EINTR) {
+ pthread_mutex_unlock(&m->mtx);
+ /* loop around to signal handler */
+ continue;
+ }
- /* Handle any errors received in poll() */
- if (num < 0) {
- if (errno == EINTR) {
+ /* else die */
+ zlog_warn("poll() error: %s",
+ safe_strerror(errno));
pthread_mutex_unlock(&m->mtx);
- continue; /* loop around to signal handler */
+ fetch = NULL;
+ break;
}
- /* else die */
- zlog_warn("poll() error: %s", safe_strerror(errno));
- pthread_mutex_unlock(&m->mtx);
- fetch = NULL;
- break;
- }
+ /*
+ * Since we could have received more cancellation
+ * requests during poll(), process those
+ */
+ do_thread_cancel(m);
- /* Since we could have received more cancellation requests
- * during poll(), process those */
- do_thread_cancel(m);
+ } else {
+ m->tick_since_io++;
+ }
/* Post timers to ready queue. */
monotime(&now);
@@ -1388,8 +1410,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
if (num > 0)
thread_process_io(m, num);
- /* If we have a ready task, break the loop and return it to the
- * caller */
+ /* have a ready task ==> return it to caller */
if ((thread = thread_trim_head(&m->ready))) {
fetch = thread_run(m, thread, fetch);
if (fetch->ref)
diff --git a/lib/thread.h b/lib/thread.h
index c830446e10..86bf4df7c0 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -70,6 +70,7 @@ struct cancel_req {
struct thread_master {
char *name;
+ int tick_since_io;
struct thread **read;
struct thread **write;
struct pqueue *timer;
diff --git a/lib/vty.c b/lib/vty.c
index 00579550e4..31fcaf1026 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -306,6 +306,7 @@ struct vty *vty_new()
{
struct vty *new = XCALLOC(MTYPE_VTY, sizeof(struct vty));
+ new->fd = new->wfd = -1;
new->obuf = buffer_new(0); /* Use default buffer size. */
new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ);
new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ);
@@ -683,6 +684,7 @@ static void vty_end_config(struct vty *vty)
break;
case CONFIG_NODE:
case INTERFACE_NODE:
+ case PW_NODE:
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
@@ -1093,6 +1095,7 @@ static void vty_stop_input(struct vty *vty)
break;
case CONFIG_NODE:
case INTERFACE_NODE:
+ case PW_NODE:
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
@@ -2129,16 +2132,21 @@ void vty_close(struct vty *vty)
XFREE(MTYPE_VTY_HIST, vty->hist[i]);
/* Unset vector. */
- vector_unset(vtyvec, vty->fd);
+ if (vty->fd != -1)
+ vector_unset(vtyvec, vty->fd);
if (vty->wfd > 0 && vty->type == VTY_FILE)
fsync(vty->wfd);
- /* Close socket. */
- if (vty->fd > 0) {
+ /* Close socket.
+ * note check is for fd > STDERR_FILENO, not fd != -1.
+ * We never close stdin/stdout/stderr here, because we may be
+ * running in foreground mode with logging to stdout. Also,
+ * additionally, we'd need to replace these fds with /dev/null. */
+ if (vty->wfd > STDERR_FILENO && vty->wfd != vty->fd)
+ close(vty->wfd);
+ if (vty->fd > STDERR_FILENO) {
close(vty->fd);
- if (vty->wfd > 0 && vty->wfd != vty->fd)
- close(vty->wfd);
} else
was_stdio = true;
@@ -2186,13 +2194,14 @@ static void vty_read_file(FILE *confp)
unsigned int line_num = 0;
vty = vty_new();
- vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */
- if (vty->wfd < 0) {
- /* Fine, we couldn't make a new fd. vty_close doesn't close
- * stdout. */
- vty->wfd = STDOUT_FILENO;
- }
- vty->fd = STDIN_FILENO;
+ /* vty_close won't close stderr; if some config command prints
+ * something it'll end up there. (not ideal; it'd be beter if output
+ * from a file-load went to logging instead. Also note that if this
+ * function is called after daemonizing, stderr will be /dev/null.)
+ *
+ * vty->fd will be -1 from vty_new()
+ */
+ vty->wfd = STDERR_FILENO;
vty->type = VTY_FILE;
vty->node = CONFIG_NODE;
@@ -2200,7 +2209,7 @@ static void vty_read_file(FILE *confp)
ret = config_from_file(vty, confp, &line_num);
/* Flush any previous errors before printing messages below */
- buffer_flush_all(vty->obuf, vty->fd);
+ buffer_flush_all(vty->obuf, vty->wfd);
if (!((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO))) {
const char *message = NULL;
diff --git a/lib/vty.h b/lib/vty.h
index 0839f7fb68..0980f73afa 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -166,6 +166,11 @@ static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
#define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \
struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \
VTY_CHECK_CONTEXT(ptr);
+#define VTY_DECLVAR_INSTANCE_CONTEXT(structname, ptr) \
+ if (vty->qobj_index == 0) \
+ return CMD_NOT_MY_INSTANCE; \
+ struct structname *ptr = VTY_GET_CONTEXT(structname); \
+ VTY_CHECK_CONTEXT(ptr);
struct vty_arg {
const char *name;
diff --git a/lib/zclient.c b/lib/zclient.c
index a54d8749a3..893d769e3a 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1834,6 +1834,69 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
return 0;
}
+int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw)
+{
+ struct stream *s;
+
+ /* Reset stream. */
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, command, VRF_DEFAULT);
+ stream_write(s, pw->ifname, IF_NAMESIZE);
+ stream_putl(s, pw->ifindex);
+
+ /* Put type */
+ stream_putl(s, pw->type);
+
+ /* Put nexthop */
+ stream_putl(s, pw->af);
+ switch (pw->af) {
+ case AF_INET:
+ stream_put_in_addr(s, &pw->nexthop.ipv4);
+ break;
+ case AF_INET6:
+ stream_write(s, (u_char *)&pw->nexthop.ipv6, 16);
+ break;
+ default:
+ zlog_err("%s: unknown af", __func__);
+ return -1;
+ }
+
+ /* Put labels */
+ stream_putl(s, pw->local_label);
+ stream_putl(s, pw->remote_label);
+
+ /* Put flags */
+ stream_putc(s, pw->flags);
+
+ /* Protocol specific fields */
+ stream_write(s, &pw->data, sizeof(union pw_protocol_fields));
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zclient_send_message(zclient);
+}
+
+/*
+ * Receive PW status update from Zebra and send it to LDE process.
+ */
+void zebra_read_pw_status_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id,
+ struct zapi_pw_status *pw)
+{
+ struct stream *s;
+
+ memset(pw, 0, sizeof(struct zapi_pw_status));
+ s = zclient->ibuf;
+
+ /* Get data. */
+ stream_get(pw->ifname, s, IF_NAMESIZE);
+ pw->ifindex = stream_getl(s);
+ pw->status = stream_getl(s);
+}
+
/* Zebra client message read function. */
static int zclient_read(struct thread *thread)
{
@@ -2061,6 +2124,11 @@ static int zclient_read(struct thread *thread)
(*zclient->local_macip_del)(command, zclient, length,
vrf_id);
break;
+ case ZEBRA_PW_STATUS_UPDATE:
+ if (zclient->pw_status_update)
+ (*zclient->pw_status_update)(command, zclient, length,
+ vrf_id);
+ break;
default:
break;
}
@@ -2184,3 +2252,23 @@ void zclient_serv_path_set(char *path)
/* it seems that path is unix socket */
zclient_serv_path = path;
}
+
+void zclient_interface_set_master(struct zclient *client,
+ struct interface *master,
+ struct interface *slave)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
+
+ stream_putw(s, master->vrf_id);
+ stream_putl(s, master->ifindex);
+ stream_putw(s, slave->vrf_id);
+ stream_putl(s, slave->ifindex);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(client);
+}
diff --git a/lib/zclient.h b/lib/zclient.h
index efa5c32c16..8a2729543f 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -30,6 +30,12 @@
/* For vrf_bitmap_t. */
#include "vrf.h"
+/* For union g_addr */
+#include "nexthop.h"
+
+/* For union pw_protocol_fields */
+#include "pw.h"
+
/* For input/output buffer to zebra. */
#define ZEBRA_MAX_PACKET_SIZ 4096
@@ -44,6 +50,7 @@ typedef enum {
ZEBRA_INTERFACE_ADDRESS_DELETE,
ZEBRA_INTERFACE_UP,
ZEBRA_INTERFACE_DOWN,
+ ZEBRA_INTERFACE_SET_MASTER,
ZEBRA_IPV4_ROUTE_ADD,
ZEBRA_IPV4_ROUTE_DELETE,
ZEBRA_IPV6_ROUTE_ADD,
@@ -105,6 +112,11 @@ typedef enum {
ZEBRA_MACIP_DEL,
ZEBRA_REMOTE_MACIP_ADD,
ZEBRA_REMOTE_MACIP_DEL,
+ ZEBRA_PW_ADD,
+ ZEBRA_PW_DELETE,
+ ZEBRA_PW_SET,
+ ZEBRA_PW_UNSET,
+ ZEBRA_PW_STATUS_UPDATE,
} zebra_message_types_t;
struct redist_proto {
@@ -186,6 +198,7 @@ struct zclient {
int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t);
int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t);
+ int (*pw_status_update)(int, struct zclient *, uint16_t, vrf_id_t);
};
/* Zebra API message flag. */
@@ -265,6 +278,25 @@ struct zapi_ipv4 {
vrf_id_t vrf_id;
};
+struct zapi_pw {
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ uint8_t protocol;
+};
+
+struct zapi_pw_status {
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ uint32_t status;
+};
+
/* Prototypes of zebra client service functions. */
extern struct zclient *zclient_new(struct thread_master *);
extern void zclient_init(struct zclient *, int, u_short);
@@ -311,6 +343,9 @@ extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size,
u_char *marker, u_char *version,
vrf_id_t *vrf_id, u_int16_t *cmd);
+extern void zclient_interface_set_master(struct zclient *client,
+ struct interface *master,
+ struct interface *slave);
extern struct interface *zebra_interface_add_read(struct stream *, vrf_id_t);
extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t);
extern struct connected *zebra_interface_address_read(int, struct stream *,
@@ -334,6 +369,12 @@ extern int lm_get_label_chunk(struct zclient *zclient, u_char keep,
uint32_t *end);
extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
+extern int zebra_send_pw(struct zclient *zclient, int command,
+ struct zapi_pw *pw);
+extern void zebra_read_pw_status_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id,
+ struct zapi_pw_status *pw);
+
/* IPv6 prefix add and delete function prototype. */
struct zapi_ipv6 {
diff --git a/lib/zebra.h b/lib/zebra.h
index 8e1c4db804..6d64bbd670 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -126,6 +126,13 @@ typedef unsigned char u_int8_t;
#define __APPLE_USE_RFC_3542
#endif
+#ifndef HAVE_LIBCRYPT
+# ifdef HAVE_LIBCRYPTO
+# include <openssl/des.h>
+# define crypt DES_crypt
+# endif
+#endif
+
#include "openbsd-tree.h"
#include <netinet/in.h>
@@ -416,22 +423,15 @@ extern const char *zserv_command_string(unsigned int command);
typedef enum { AFI_IP = 1, AFI_IP6 = 2, AFI_L2VPN = 3, AFI_MAX = 4 } afi_t;
/* Subsequent Address Family Identifier. */
-#define SAFI_UNICAST 1
-#define SAFI_MULTICAST 2
-#define SAFI_MPLS_VPN 3
-#define SAFI_RESERVED_4 4
-#define SAFI_ENCAP 5
-#define SAFI_RESERVED_5 5
-#define SAFI_EVPN 6
-#define SAFI_LABELED_UNICAST 7
-#define SAFI_MAX 8
-
-#define IANA_SAFI_RESERVED 0
-#define IANA_SAFI_UNICAST 1
-#define IANA_SAFI_MULTICAST 2
-#define IANA_SAFI_LABELED_UNICAST 4
-#define IANA_SAFI_ENCAP 7
-#define IANA_SAFI_MPLS_VPN 128
+typedef enum {
+ SAFI_UNICAST = 1,
+ SAFI_MULTICAST = 2,
+ SAFI_MPLS_VPN = 3,
+ SAFI_ENCAP = 4,
+ SAFI_EVPN = 5,
+ SAFI_LABELED_UNICAST = 6,
+ SAFI_MAX = 7
+} safi_t;
/*
* The above AFI and SAFI definitions are for internal use. The protocol
@@ -451,12 +451,15 @@ typedef enum {
IANA_AFI_IP6MR = 129
} iana_afi_t;
-#define IANA_SAFI_RESERVED 0
-#define IANA_SAFI_UNICAST 1
-#define IANA_SAFI_MULTICAST 2
-#define IANA_SAFI_ENCAP 7
-#define IANA_SAFI_EVPN 70
-#define IANA_SAFI_MPLS_VPN 128
+typedef enum {
+ IANA_SAFI_RESERVED = 0,
+ IANA_SAFI_UNICAST = 1,
+ IANA_SAFI_MULTICAST = 2,
+ IANA_SAFI_LABELED_UNICAST = 4,
+ IANA_SAFI_ENCAP = 7,
+ IANA_SAFI_EVPN = 70,
+ IANA_SAFI_MPLS_VPN = 128
+} iana_safi_t;
/* Default Administrative Distance of each protocol. */
#define ZEBRA_KERNEL_DISTANCE_DEFAULT 0
@@ -477,8 +480,6 @@ typedef enum {
#define UNSET_FLAG(V,F) (V) &= ~(F)
#define RESET_FLAG(V) (V) = 0
-typedef u_int8_t safi_t;
-
/* Zebra types. Used in Zserv message header. */
typedef u_int16_t zebra_size_t;
typedef u_int16_t zebra_command_t;
@@ -492,58 +493,70 @@ typedef uint32_t route_tag_t;
static inline afi_t afi_iana2int(iana_afi_t afi)
{
- if (afi == IANA_AFI_IPV4)
+ switch (afi) {
+ case IANA_AFI_IPV4:
return AFI_IP;
- if (afi == IANA_AFI_IPV6)
+ case IANA_AFI_IPV6:
return AFI_IP6;
- if (afi == IANA_AFI_L2VPN)
+ case IANA_AFI_L2VPN:
return AFI_L2VPN;
- return AFI_MAX;
+ default:
+ return AFI_MAX;
+ }
}
static inline iana_afi_t afi_int2iana(afi_t afi)
{
- if (afi == AFI_IP)
+ switch (afi) {
+ case AFI_IP:
return IANA_AFI_IPV4;
- if (afi == AFI_IP6)
+ case AFI_IP6:
return IANA_AFI_IPV6;
- if (afi == AFI_L2VPN)
+ case AFI_L2VPN:
return IANA_AFI_L2VPN;
- return IANA_AFI_RESERVED;
+ default:
+ return IANA_AFI_RESERVED;
+ }
}
-static inline safi_t safi_iana2int(safi_t safi)
+static inline safi_t safi_iana2int(iana_safi_t safi)
{
- if (safi == IANA_SAFI_UNICAST)
+ switch (safi) {
+ case IANA_SAFI_UNICAST:
return SAFI_UNICAST;
- if (safi == IANA_SAFI_MULTICAST)
+ case IANA_SAFI_MULTICAST:
return SAFI_MULTICAST;
- if (safi == IANA_SAFI_MPLS_VPN)
+ case IANA_SAFI_MPLS_VPN:
return SAFI_MPLS_VPN;
- if (safi == IANA_SAFI_ENCAP)
+ case IANA_SAFI_ENCAP:
return SAFI_ENCAP;
- if (safi == IANA_SAFI_EVPN)
+ case IANA_SAFI_EVPN:
return SAFI_EVPN;
- if (safi == IANA_SAFI_LABELED_UNICAST)
+ case IANA_SAFI_LABELED_UNICAST:
return SAFI_LABELED_UNICAST;
- return SAFI_MAX;
+ default:
+ return SAFI_MAX;
+ }
}
-static inline safi_t safi_int2iana(safi_t safi)
+static inline iana_safi_t safi_int2iana(safi_t safi)
{
- if (safi == SAFI_UNICAST)
+ switch (safi) {
+ case SAFI_UNICAST:
return IANA_SAFI_UNICAST;
- if (safi == SAFI_MULTICAST)
+ case SAFI_MULTICAST:
return IANA_SAFI_MULTICAST;
- if (safi == SAFI_MPLS_VPN)
+ case SAFI_MPLS_VPN:
return IANA_SAFI_MPLS_VPN;
- if (safi == SAFI_ENCAP)
+ case SAFI_ENCAP:
return IANA_SAFI_ENCAP;
- if (safi == SAFI_EVPN)
+ case SAFI_EVPN:
return IANA_SAFI_EVPN;
- if (safi == SAFI_LABELED_UNICAST)
+ case SAFI_LABELED_UNICAST:
return IANA_SAFI_LABELED_UNICAST;
- return IANA_SAFI_RESERVED;
+ default:
+ return IANA_SAFI_RESERVED;
+ }
}
#endif /* _ZEBRA_H */
diff --git a/m4/Makefile.am b/m4/Makefile.am
deleted file mode 100644
index 49a29bdf1f..0000000000
--- a/m4/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=Makefile.am README.txt
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index bd884bbc51..3ebdbf27ba 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -289,7 +289,7 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type, i
if (holding_time > 0)
c->new.expires = monotime(NULL) + holding_time;
else if (holding_time < 0)
- c->new.type = NHRP_CACHE_INVALID;
+ nhrp_cache_reset_new(c);
if (c->new.type == NHRP_CACHE_INVALID ||
c->new.type >= NHRP_CACHE_STATIC ||
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
index 7c5d80336c..012d5cd87c 100644
--- a/nhrpd/nhrp_main.c
+++ b/nhrpd/nhrp_main.c
@@ -128,8 +128,8 @@ int main(int argc, char **argv)
/* Library inits. */
master = frr_init();
- nhrp_interface_init();
vrf_init(NULL, NULL, NULL, NULL);
+ nhrp_interface_init();
resolver_init();
/* Run with elevated capabilities, as for all netlink activity
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 89972f8f98..c8a608c657 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -205,17 +205,18 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i
/* Type, flags, message. */
/*type =*/ stream_getc(s);
- /*flags =*/ stream_getc(s);
+ /*instance =*/ stream_getw(s);
+ /*flags =*/ stream_getl(s);
message = stream_getc(s);
/* Prefix */
switch (cmd) {
- case ZEBRA_IPV4_ROUTE_ADD:
- case ZEBRA_IPV4_ROUTE_DELETE:
+ case ZEBRA_REDISTRIBUTE_IPV4_ADD:
+ case ZEBRA_REDISTRIBUTE_IPV4_DEL:
prefix.family = AF_INET;
break;
- case ZEBRA_IPV6_ROUTE_ADD:
- case ZEBRA_IPV6_ROUTE_DELETE:
+ case ZEBRA_REDISTRIBUTE_IPV6_ADD:
+ case ZEBRA_REDISTRIBUTE_IPV6_DEL:
prefix.family = AF_INET6;
break;
default:
@@ -244,7 +245,7 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
/*metric =*/ stream_getl(s);
- added = (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD);
+ added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD);
debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
added ? "add" : "del",
prefix2str(&prefix, buf[0], sizeof buf[0]),
@@ -342,12 +343,23 @@ enum nhrp_route_type nhrp_route_address(struct interface *in_ifp, union sockunio
return NHRP_ROUTE_BLACKHOLE;
}
+static void
+nhrp_zebra_connected (struct zclient *zclient)
+{
+ zclient_send_reg_requests(zclient, VRF_DEFAULT);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
+ ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
+ ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+}
+
void nhrp_zebra_init(void)
{
zebra_rib[AFI_IP] = route_table_init();
zebra_rib[AFI_IP6] = route_table_init();
zclient = zclient_new(master);
+ zclient->zebra_connected = nhrp_zebra_connected;
zclient->interface_add = nhrp_interface_add;
zclient->interface_delete = nhrp_interface_delete;
zclient->interface_up = nhrp_interface_up;
@@ -360,20 +372,6 @@ void nhrp_zebra_init(void)
zclient->redistribute_route_ipv6_del = nhrp_route_read;
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_KERNEL, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_CONNECT, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_STATIC, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_RIP, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_OSPF, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_ISIS, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_BGP, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_KERNEL, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_CONNECT, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_STATIC, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_RIP, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_OSPF, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_ISIS, 0, VRF_DEFAULT);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_BGP, 0, VRF_DEFAULT);
}
void nhrp_zebra_terminate(void)
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 7f8341d0e4..dd3630af16 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -622,7 +622,8 @@ void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
node = route_node_lookup(ospf6->external_id_table, &prefix_id);
assert(node);
node->info = NULL;
- route_unlock_node(node);
+ route_unlock_node(node); /* to free the lookup lock */
+ route_unlock_node(node); /* to free the original lock */
ospf6_route_remove(match, ospf6->external_table);
XFREE(MTYPE_OSPF6_EXTERNAL_INFO, info);
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index e1a431ea07..a0dad9344a 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -509,7 +509,8 @@ struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
/* allocate memory for this LSA */
new_header =
- (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA, lsa_size);
+ (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA_HEADER,
+ lsa_size);
/* copy LSA from original header */
memcpy(new_header, header, lsa_size);
@@ -537,7 +538,7 @@ struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
/* allocate memory for this LSA */
new_header = (struct ospf6_lsa_header *)XMALLOC(
- MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa_header));
+ MTYPE_OSPF6_LSA_HEADER, sizeof(struct ospf6_lsa_header));
/* copy LSA from original header */
memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
@@ -568,7 +569,7 @@ void ospf6_lsa_delete(struct ospf6_lsa *lsa)
THREAD_OFF(lsa->refresh);
/* do free */
- XFREE(MTYPE_OSPF6_LSA, lsa->header);
+ XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
XFREE(MTYPE_OSPF6_LSA, lsa);
}
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 7e08d58791..418f858a32 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -83,8 +83,7 @@ static void _lsdb_count_assert(struct ospf6_lsdb *lsdb)
zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb,
lsdb->count, num);
for (ALL_LSDB(lsdb, debug))
- zlog_debug("%p %p %s lsdb[%p]", debug->prev, debug->next,
- debug->name, debug->lsdb);
+ zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb);
zlog_debug("DUMP END");
assert(num == lsdb->count);
@@ -139,6 +138,8 @@ void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
(*lsdb->hook_add)(lsa);
}
}
+ /* to free the lookup lock in node get*/
+ route_unlock_node(current);
ospf6_lsa_unlock(old);
}
diff --git a/ospf6d/ospf6_memory.c b/ospf6d/ospf6_memory.c
index 133dc2cb3c..56c232d6da 100644
--- a/ospf6d/ospf6_memory.c
+++ b/ospf6d/ospf6_memory.c
@@ -34,6 +34,7 @@ DEFINE_MTYPE(OSPF6D, OSPF6_ROUTE, "OSPF6 route")
DEFINE_MTYPE(OSPF6D, OSPF6_PREFIX, "OSPF6 prefix")
DEFINE_MTYPE(OSPF6D, OSPF6_MESSAGE, "OSPF6 message")
DEFINE_MTYPE(OSPF6D, OSPF6_LSA, "OSPF6 LSA")
+DEFINE_MTYPE(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header")
DEFINE_MTYPE(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary")
DEFINE_MTYPE(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database")
DEFINE_MTYPE(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex")
diff --git a/ospf6d/ospf6_memory.h b/ospf6d/ospf6_memory.h
index 324065c3a1..fe72ee3669 100644
--- a/ospf6d/ospf6_memory.h
+++ b/ospf6d/ospf6_memory.h
@@ -33,6 +33,7 @@ DECLARE_MTYPE(OSPF6_ROUTE)
DECLARE_MTYPE(OSPF6_PREFIX)
DECLARE_MTYPE(OSPF6_MESSAGE)
DECLARE_MTYPE(OSPF6_LSA)
+DECLARE_MTYPE(OSPF6_LSA_HEADER)
DECLARE_MTYPE(OSPF6_LSA_SUMMARY)
DECLARE_MTYPE(OSPF6_LSDB)
DECLARE_MTYPE(OSPF6_VERTEX)
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index e0e9fc9449..bfe583a911 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -178,17 +178,6 @@ void ospf6_nexthop_delete(struct ospf6_nexthop *nh)
XFREE(MTYPE_OSPF6_NEXTHOP, nh);
}
-void ospf6_free_nexthops(struct list *nh_list)
-{
- struct ospf6_nexthop *nh;
- struct listnode *node, *nnode;
-
- if (nh_list) {
- for (ALL_LIST_ELEMENTS(nh_list, node, nnode, nh))
- ospf6_nexthop_delete(nh);
- }
-}
-
void ospf6_clear_nexthops(struct list *nh_list)
{
struct listnode *node;
@@ -340,19 +329,29 @@ int ospf6_route_get_first_nh_index(struct ospf6_route *route)
return (-1);
}
+static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
+{
+ if ((a)->ifindex == (b)->ifindex &&
+ IN6_ARE_ADDR_EQUAL(&(a)->address, &(b)->address))
+ return 1;
+ return 0;
+}
+
struct ospf6_route *ospf6_route_create(void)
{
struct ospf6_route *route;
route = XCALLOC(MTYPE_OSPF6_ROUTE, sizeof(struct ospf6_route));
route->nh_list = list_new();
+ route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
+ route->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
return route;
}
void ospf6_route_delete(struct ospf6_route *route)
{
if (route) {
- ospf6_free_nexthops(route->nh_list);
- list_free(route->nh_list);
+ if (route->nh_list)
+ list_delete(route->nh_list);
XFREE(MTYPE_OSPF6_ROUTE, route);
}
}
@@ -439,6 +438,7 @@ struct ospf6_route *ospf6_route_lookup(struct prefix *prefix,
return NULL;
route = (struct ospf6_route *)node->info;
+ route_unlock_node(node); /* to free the lookup lock */
return route;
}
@@ -583,6 +583,8 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
SET_FLAG(old->flag, OSPF6_ROUTE_ADD);
ospf6_route_table_assert(table);
+ /* to free the lookup lock */
+ route_unlock_node(node);
return old;
}
@@ -628,9 +630,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
if (prev || next) {
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
zlog_debug(
- "%s %p: route add %p: another path: prev %p, next %p",
+ "%s %p: route add %p: another path: prev %p, next %p node refcount %u",
ospf6_route_table_name(table), (void *)table,
- (void *)route, (void *)prev, (void *)next);
+ (void *)route, (void *)prev, (void *)next,
+ node->lock);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
zlog_debug("%s: route add: another path found",
ospf6_route_table_name(table));
@@ -755,9 +758,9 @@ void ospf6_route_remove(struct ospf6_route *route,
prefix2str(&route->prefix, buf, sizeof(buf));
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
- zlog_debug("%s %p: route remove %p: %s",
+ zlog_debug("%s %p: route remove %p: %s rnode refcount %u",
ospf6_route_table_name(table), (void *)table,
- (void *)route, buf);
+ (void *)route, buf, route->rnode->lock);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
zlog_debug("%s: route remove: %s",
ospf6_route_table_name(table), buf);
@@ -768,11 +771,9 @@ void ospf6_route_remove(struct ospf6_route *route,
/* find the route to remove, making sure that the route pointer
is from the route table. */
current = node->info;
- while (current && ospf6_route_is_same(current, route)) {
- if (current == route)
- break;
+ while (current && current != route)
current = current->next;
- }
+
assert(current == route);
/* adjust doubly linked list */
@@ -785,10 +786,14 @@ void ospf6_route_remove(struct ospf6_route *route,
if (route->next && route->next->rnode == node) {
node->info = route->next;
SET_FLAG(route->next->flag, OSPF6_ROUTE_BEST);
- } else
- node->info = NULL; /* should unlock route_node here ? */
+ } else {
+ node->info = NULL;
+ route->rnode = NULL;
+ route_unlock_node(node); /* to free the original lock */
+ }
}
+ route_unlock_node(node); /* to free the lookup lock */
table->count--;
ospf6_route_table_assert(table);
@@ -935,6 +940,7 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t)
void ospf6_route_table_delete(struct ospf6_route_table *table)
{
ospf6_route_remove_all(table);
+ bf_free(table->idspace);
route_table_finish(table->table);
XFREE(MTYPE_OSPF6_ROUTE, table);
}
@@ -1062,6 +1068,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
route->path.u.cost_e2);
+ vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
/* Nexthops */
vty_out(vty, "Nexthop:\n");
for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 69d275f8b1..166074fb70 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -256,7 +256,6 @@ extern void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf,
extern struct ospf6_nexthop *ospf6_nexthop_create(void);
extern void ospf6_nexthop_delete(struct ospf6_nexthop *nh);
-extern void ospf6_free_nexthops(struct list *nh_list);
extern void ospf6_clear_nexthops(struct list *nh_list);
extern int ospf6_num_nexthops(struct list *nh_list);
extern void ospf6_copy_nexthops(struct list *dst, struct list *src);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 86f893bc61..6d589aff8f 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -141,6 +141,7 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
v->nh_list = list_new();
+ v->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
v->parent = NULL;
v->child_list = list_new();
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index c0670012b8..d3d1ffed5e 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -626,7 +626,7 @@ DEFUN (debug_ospf_packet,
if (inst) // user passed instance ID
{
if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
}
int type = 0;
@@ -702,7 +702,7 @@ DEFUN (no_debug_ospf_packet,
if (inst) // user passed instance ID
{
if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
}
int type = 0;
@@ -773,7 +773,7 @@ DEFUN (debug_ospf_ism,
if (inst) // user passed instance ID
{
if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
}
if (vty->node == CONFIG_NODE) {
@@ -824,7 +824,7 @@ DEFUN (no_debug_ospf_ism,
if (inst) // user passed instance ID
{
if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
}
if (vty->node == CONFIG_NODE) {
@@ -991,7 +991,7 @@ DEFUN (no_debug_ospf_instance_nsm,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_nsm_common(vty, 5, argc, argv);
}
@@ -1065,7 +1065,7 @@ DEFUN (debug_ospf_instance_lsa,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
return debug_ospf_lsa_common(vty, 4, argc, argv);
}
@@ -1141,7 +1141,7 @@ DEFUN (no_debug_ospf_instance_lsa,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_lsa_common(vty, 5, argc, argv);
}
@@ -1203,7 +1203,7 @@ DEFUN (debug_ospf_instance_zebra,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
return debug_ospf_zebra_common(vty, 4, argc, argv);
}
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index a2c40923b1..db523bd2a4 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -750,7 +750,7 @@ DEFUN (capability_opaque,
"Enable specific OSPF feature\n"
"Opaque LSA\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
/* Turn on the "master switch" of opaque-lsa capability. */
if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
@@ -779,7 +779,7 @@ DEFUN (no_capability_opaque,
"Enable specific OSPF feature\n"
"Opaque LSA\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
/* Turn off the "master switch" of opaque-lsa capability. */
if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index 8bad51e65e..2470cd2e2b 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -77,6 +77,44 @@
((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \
&& ((ntohs((lsahdr)->length) % sizeof(u_int32_t)) == 0))
+/*
+ * Following section defines generic TLV (type, length, value) macros,
+ * used for various LSA opaque usage e.g. Traffic Engineering.
+ */
+struct tlv_header {
+ u_int16_t type; /* Type of Value */
+ u_int16_t length; /* Length of Value portion only, in bytes */
+};
+
+#define TLV_HDR_SIZE (sizeof(struct tlv_header))
+
+#define TLV_BODY_SIZE(tlvh) \
+ (ROUNDUP(ntohs((tlvh)->length), sizeof(u_int32_t)))
+
+#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
+
+#define TLV_HDR_TOP(lsah) \
+ (struct tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
+
+#define TLV_HDR_NEXT(tlvh) \
+ (struct tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
+
+#define TLV_HDR_SUBTLV(tlvh) \
+ (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE)
+
+#define TLV_DATA(tlvh) (void *)((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 declaration concerns the Opaque LSA management */
+enum lsa_opcode {
+ REORIGINATE_THIS_LSA,
+ REFRESH_THIS_LSA,
+ FLUSH_THIS_LSA
+};
+
/* Prototypes. */
extern void ospf_opaque_init(void);
@@ -108,7 +146,7 @@ extern int ospf_opaque_new_if(struct interface *ifp);
extern int ospf_opaque_del_if(struct interface *ifp);
extern void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status);
extern void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_status);
-extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *);
+extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf);
extern void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp);
extern void ospf_opaque_config_write_debug(struct vty *vty);
extern void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa);
@@ -116,7 +154,7 @@ extern void ospf_opaque_lsa_dump(struct stream *s, u_int16_t length);
extern void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi,
int *init_delay);
-extern struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *,
+extern struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa,
int rt_recalc);
extern struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa);
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index 26d2ed7d13..13013bf8ca 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -58,9 +58,9 @@
#include "ospfd/ospf_ri.h"
#include "ospfd/ospf_te.h"
+/* Store Router Information PCE TLV and SubTLV in network byte order. */
struct ospf_pce_info {
-
- /* Store Router Information PCE TLV and SubTLV in network byte order. */
+ bool enabled;
struct ri_tlv_pce pce_header;
struct ri_pce_subtlv_address pce_address;
struct ri_pce_subtlv_path_scope pce_scope;
@@ -71,15 +71,14 @@ struct ospf_pce_info {
/* Following structure are internal use only. */
struct ospf_router_info {
- status_t status;
+ bool enabled;
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
+#define RIFLG_LSA_ENGAGED 0x1
+#define RIFLG_LSA_FORCED_REFRESH 0x2
u_int32_t flags;
/* area pointer if flooding is Type 10 Null if flooding is AS scope */
@@ -112,7 +111,7 @@ 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_lsa_schedule(enum lsa_opcode opcode);
static void ospf_router_info_register_vty(void);
static void del_pce_info(void *val);
@@ -120,12 +119,13 @@ int ospf_router_info_init(void)
{
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
- OspfRI.status = disabled;
+ OspfRI.enabled = false;
OspfRI.registered = 0;
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
OspfRI.flags = 0;
/* Initialize pce domain and neighbor list */
+ OspfRI.pce_info.enabled = false;
OspfRI.pce_info.pce_domain = list_new();
OspfRI.pce_info.pce_domain->del = del_pce_info;
OspfRI.pce_info.pce_neighbor = list_new();
@@ -141,7 +141,7 @@ static int ospf_router_info_register(u_int8_t scope)
int rc = 0;
if (OspfRI.registered)
- return 0;
+ return rc;
zlog_info("Register Router Information with scope %s(%d)",
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
@@ -165,7 +165,7 @@ static int ospf_router_info_register(u_int8_t scope)
OspfRI.registered = 1;
OspfRI.scope = scope;
- return 0;
+ return rc;
}
static int ospf_router_info_unregister()
@@ -193,7 +193,7 @@ void ospf_router_info_term(void)
OspfRI.pce_info.pce_domain = NULL;
OspfRI.pce_info.pce_neighbor = NULL;
- OspfRI.status = disabled;
+ OspfRI.enabled = false;
ospf_router_info_unregister();
@@ -229,34 +229,36 @@ static int set_pce_header(struct ospf_pce_info *pce)
/* PCE Address */
if (ntohs(pce->pce_address.header.type) != 0)
- length += RI_TLV_SIZE(&pce->pce_address.header);
+ length += 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);
+ length += 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);
+ length += 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);
+ length += TLV_SIZE(&neighbor->header);
}
/* PCE Capabilities */
if (ntohs(pce->pce_cap_flag.header.type) != 0)
- length += RI_TLV_SIZE(&pce->pce_cap_flag.header);
+ length += 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);
+ pce->enabled = true;
} else {
pce->pce_header.header.type = 0;
pce->pce_header.header.length = 0;
+ pce->enabled = false;
}
return length;
@@ -279,8 +281,6 @@ static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
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);
@@ -295,9 +295,6 @@ static void set_pce_domain(u_int16_t type, u_int32_t domain,
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));
@@ -348,9 +345,6 @@ static void set_pce_neighbor(u_int16_t type, u_int32_t domain,
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));
@@ -399,8 +393,6 @@ static void unset_pce_neighbor(u_int16_t type, u_int32_t domain,
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);
@@ -410,12 +402,12 @@ static void set_pce_cap_flag(u_int32_t cap, struct ospf_pce_info *pce)
}
-static void unset_param(struct ri_tlv_header *tlv)
+static void unset_param(struct tlv_header *tlv)
{
tlv->type = 0;
/* Fill the Value to 0 */
- memset((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE(tlv));
+ memset(TLV_DATA(tlv), 0, TLV_BODY_SIZE(tlv));
tlv->length = 0;
return;
@@ -423,14 +415,13 @@ static void unset_param(struct ri_tlv_header *tlv)
static void initialize_params(struct ospf_router_info *ori)
{
- u_int32_t cap;
+ u_int32_t cap = 0;
struct ospf *top;
/*
* Initialize default Router Information Capabilities.
*/
- cap = 0;
- cap = cap | RI_TE_SUPPORT;
+ cap = RI_TE_SUPPORT;
set_router_info_capabilities(&ori->router_cap, cap);
@@ -462,9 +453,6 @@ static void initialize_params(struct ospf_router_info *ori)
| 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;
}
@@ -473,16 +461,15 @@ static int is_mandated_params_set(struct ospf_router_info ori)
int rc = 0;
if (ntohs(ori.router_cap.header.type) == 0)
- goto out;
+ return rc;
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;
+ return rc;
rc = 1;
-out:
return rc;
}
@@ -499,7 +486,6 @@ static void ospf_router_info_ism_change(struct ospf_interface *oi,
static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
int old_state)
{
-
/* So far, nothing to do here. */
return;
}
@@ -508,19 +494,19 @@ static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
* Followings are OSPF protocol processing functions for ROUTER INFORMATION
*------------------------------------------------------------------------*/
-static void build_tlv_header(struct stream *s, struct ri_tlv_header *tlvh)
+static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
{
- stream_put(s, tlvh, sizeof(struct ri_tlv_header));
+ stream_put(s, tlvh, sizeof(struct tlv_header));
return;
}
-static void build_tlv(struct stream *s, struct ri_tlv_header *tlvh)
+static void build_tlv(struct stream *s, struct tlv_header *tlvh)
{
if (ntohs(tlvh->type) != 0) {
build_tlv_header(s, tlvh);
- stream_put(s, tlvh + 1, RI_TLV_BODY_SIZE(tlvh));
+ stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
}
return;
}
@@ -535,9 +521,11 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
/* 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) {
+ set_pce_header (&OspfRI.pce_info);
+
+ /* Add RI PCE TLV if it is set */
+ if (OspfRI.pce_info.enabled) {
/* Build PCE TLV */
build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
@@ -580,7 +568,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
/* 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;
+ return NULL;
}
lsah = (struct lsa_header *)STREAM_DATA(s);
@@ -614,14 +602,14 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
if ((new = ospf_lsa_new()) == NULL) {
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
stream_free(s);
- goto out;
+ return NULL;
}
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;
+ return new;
}
new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
@@ -631,7 +619,6 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
memcpy(new->data, lsah, length);
stream_free(s);
-out:
return new;
}
@@ -648,7 +635,7 @@ static int ospf_router_info_lsa_originate1(void *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;
+ return rc;
}
OspfRI.area = area;
}
@@ -657,7 +644,7 @@ static int ospf_router_info_lsa_originate1(void *arg)
if ((new = ospf_router_info_lsa_new()) == NULL) {
zlog_warn(
"ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
- goto out;
+ return rc;
}
/* Get ospf info */
@@ -668,7 +655,7 @@ static int ospf_router_info_lsa_originate1(void *arg)
zlog_warn(
"ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
ospf_lsa_unlock(&new);
- goto out;
+ return rc;
}
/* Now this Router Info parameter entry has associated LSA. */
@@ -691,7 +678,6 @@ static int ospf_router_info_lsa_originate1(void *arg)
}
rc = 0;
-out:
return rc;
}
@@ -700,17 +686,17 @@ static int ospf_router_info_lsa_originate(void *arg)
int rc = -1;
- if (OspfRI.status == disabled) {
+ if (!OspfRI.enabled) {
zlog_info(
"ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
rc = 0; /* This is not an error case. */
- goto out;
+ return rc;
}
/* 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;
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) {
+ UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH);
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
}
} else {
@@ -720,11 +706,10 @@ static int ospf_router_info_lsa_originate(void *arg)
/* Ok, let's try to originate an LSA */
if (ospf_router_info_lsa_originate1(arg) != 0)
- goto out;
+ return rc;
}
rc = 0;
-out:
return rc;
}
@@ -733,7 +718,7 @@ 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) {
+ if (!OspfRI.enabled) {
/*
* This LSA must have flushed before due to ROUTER INFORMATION
* status change.
@@ -749,21 +734,21 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
zlog_warn(
"ospf_router_info_lsa_refresh: Unsupported Router Information ID");
- goto out;
+ return NULL;
}
/* If the lsa's age reached to MaxAge, start flushing procedure. */
if (IS_LSA_MAXAGE(lsa)) {
- OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
+ UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(lsa);
- goto out;
+ return NULL;
}
/* 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;
+ return NULL;
}
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
@@ -773,7 +758,7 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
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;
+ return new;
}
/* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
@@ -790,11 +775,10 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
ospf_lsa_header_dump(new->data);
}
-out:
return new;
}
-static void ospf_router_info_lsa_schedule(opcode_t opcode)
+static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
{
struct ospf_lsa lsa;
struct lsa_header lsah;
@@ -809,6 +793,13 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "");
+ /* Check LSA flags state coherence */
+ if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) && (opcode != REORIGINATE_THIS_LSA))
+ return;
+
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
top = ospf_lookup();
if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) {
zlog_warn(
@@ -838,7 +829,7 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
ospf_opaque_lsa_refresh_schedule(&lsa);
break;
case FLUSH_THIS_LSA:
- OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
+ UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(&lsa);
break;
default:
@@ -855,7 +846,7 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
*------------------------------------------------------------------------*/
static u_int16_t show_vty_router_cap(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
@@ -865,11 +856,11 @@ static u_int16_t show_vty_router_cap(struct vty *vty,
else
zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_pce_subtlv_address(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_pce_subtlv_address *top =
(struct ri_pce_subtlv_address *)tlvh;
@@ -891,11 +882,11 @@ static u_int16_t show_vty_pce_subtlv_address(struct vty *vty,
ntohl(top->address.value.s_addr));
}
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_pce_subtlv_path_scope *top =
(struct ri_pce_subtlv_path_scope *)tlvh;
@@ -905,11 +896,11 @@ static u_int16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
else
zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_pce_subtlv_domain(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
struct in_addr tmp;
@@ -927,11 +918,11 @@ static u_int16_t show_vty_pce_subtlv_domain(struct vty *vty,
else
zlog_debug(" PCE domain AS: %d", ntohl(top->value));
}
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_pce_subtlv_neighbor *top =
@@ -953,11 +944,11 @@ static u_int16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
zlog_debug(" PCE neighbor AS: %d",
ntohl(top->value));
}
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct ri_pce_subtlv_cap_flag *top =
(struct ri_pce_subtlv_cap_flag *)tlvh;
@@ -969,11 +960,11 @@ static u_int16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
zlog_debug(" PCE Capabilities Flag: 0x%x",
ntohl(top->value));
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
static u_int16_t show_vty_unknown_tlv(struct vty *vty,
- struct ri_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
@@ -982,16 +973,16 @@ static u_int16_t show_vty_unknown_tlv(struct vty *vty,
zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
ntohs(tlvh->type), ntohs(tlvh->length));
- return RI_TLV_SIZE(tlvh);
+ return TLV_SIZE(tlvh);
}
-static u_int16_t show_vty_pce_info(struct vty *vty, struct ri_tlv_header *ri,
+static u_int16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
uint32_t total)
{
- struct ri_tlv_header *tlvh;
+ struct tlv_header *tlvh;
u_int16_t sum = 0;
- for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT(tlvh)) {
+ for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case RI_PCE_SUBTLV_ADDRESS:
sum += show_vty_pce_subtlv_address(vty, tlvh);
@@ -1019,21 +1010,21 @@ static u_int16_t show_vty_pce_info(struct vty *vty, struct ri_tlv_header *ri,
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;
+ struct 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)) {
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ tlvh = 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 += TLV_HDR_SIZE;
sum += show_vty_pce_info(vty, tlvh, length - sum);
break;
default:
@@ -1053,50 +1044,53 @@ static void ospf_router_info_config_write_router(struct vty *vty)
struct ri_pce_subtlv_neighbor *neighbor;
struct in_addr tmp;
- if (OspfRI.status == enabled) {
+ if (OspfRI.enabled) {
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
vty_out(vty, " router-info as\n");
else
vty_out(vty, " router-info area %s\n",
inet_ntoa(OspfRI.area_id));
- if (pce->pce_address.header.type != 0)
- vty_out(vty, " pce address %s\n",
- inet_ntoa(pce->pce_address.address.value));
-
- if (pce->pce_cap_flag.header.type != 0)
- vty_out(vty, " pce flag 0x%x\n",
- ntohl(pce->pce_cap_flag.value));
-
- 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\n",
- inet_ntoa(tmp));
- } else {
- vty_out(vty, " pce domain as %d\n",
- ntohl(domain->value));
+ if (OspfRI.pce_info.enabled) {
+
+ if (pce->pce_address.header.type != 0)
+ vty_out(vty, " pce address %s\n",
+ inet_ntoa(pce->pce_address.address.value));
+
+ if (pce->pce_cap_flag.header.type != 0)
+ vty_out(vty, " pce flag 0x%x\n",
+ ntohl(pce->pce_cap_flag.value));
+
+ 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\n",
+ inet_ntoa(tmp));
+ } else {
+ vty_out(vty, " pce domain as %d\n",
+ ntohl(domain->value));
+ }
}
}
- }
- 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\n",
- inet_ntoa(tmp));
- } else {
- vty_out(vty, " pce neighbor as %d\n",
- ntohl(neighbor->value));
+ 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\n",
+ inet_ntoa(tmp));
+ } else {
+ vty_out(vty, " pce neighbor as %d\n",
+ ntohl(neighbor->value));
+ }
}
}
- }
- if (pce->pce_scope.header.type != 0)
- vty_out(vty, " pce scope 0x%x\n",
- ntohl(OspfRI.pce_info.pce_scope.value));
+ if (pce->pce_scope.header.type != 0)
+ vty_out(vty, " pce scope 0x%x\n",
+ ntohl(OspfRI.pce_info.pce_scope.value));
+ }
}
return;
}
@@ -1118,7 +1112,7 @@ DEFUN (router_info,
u_int8_t scope;
- if (OspfRI.status == enabled)
+ if (OspfRI.enabled)
return CMD_SUCCESS;
/* Check and get Area value if present */
@@ -1137,11 +1131,11 @@ DEFUN (router_info,
/* First start to register Router Information callbacks */
if ((ospf_router_info_register(scope)) != 0) {
zlog_warn(
- "Enable to register Router Information callbacks. Abort!");
+ "Unable to register Router Information callbacks. Abort!");
return CMD_WARNING_CONFIG_FAILED;
}
- OspfRI.status = enabled;
+ OspfRI.enabled = true;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
@@ -1160,7 +1154,10 @@ DEFUN (router_info,
initialize_params(&OspfRI);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED) {
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
+ zlog_debug ("RI-> Refresh LSA following configuration");
+ ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
+ } else {
zlog_debug("RI-> Initial origination following configuration");
ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
}
@@ -1175,26 +1172,26 @@ DEFUN (no_router_info,
"Disable the Router Information functionality\n")
{
- if (OspfRI.status == disabled)
+ if (!OspfRI.enabled)
return CMD_SUCCESS;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("RI-> Router Information: ON -> OFF");
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(FLUSH_THIS_LSA);
/* Unregister the callbacks */
ospf_router_info_unregister();
- OspfRI.status = disabled;
+ OspfRI.enabled = false;
return CMD_SUCCESS;
}
static int ospf_ri_enabled(struct vty *vty)
{
- if (OspfRI.status == enabled)
+ if (OspfRI.enabled)
return 1;
if (vty)
@@ -1229,7 +1226,7 @@ DEFUN (pce_address,
set_pce_address(value, pi);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
}
@@ -1248,7 +1245,7 @@ DEFUN (no_pce_address,
unset_param(&OspfRI.pce_info.pce_address.header);
/* Refresh RI LSA if already engaged */
- if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1279,7 +1276,7 @@ DEFUN (pce_path_scope,
set_pce_path_scope(scope, pi);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
}
@@ -1298,7 +1295,7 @@ DEFUN (no_pce_path_scope,
unset_param(&OspfRI.pce_info.pce_address.header);
/* Refresh RI LSA if already engaged */
- if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1337,7 +1334,7 @@ DEFUN (pce_domain,
set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1367,7 +1364,7 @@ DEFUN (no_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))
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1407,7 +1404,7 @@ DEFUN (pce_neigbhor,
set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1437,7 +1434,7 @@ DEFUN (no_pce_neighbor,
unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1469,7 +1466,7 @@ DEFUN (pce_cap_flag,
set_pce_cap_flag(cap, pce);
/* Refresh RI LSA if already engaged */
- if (OspfRI.flags & RIFLG_LSA_ENGAGED)
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
}
@@ -1487,7 +1484,7 @@ DEFUN (no_pce_cap_flag,
unset_param(&OspfRI.pce_info.pce_cap_flag.header);
/* Refresh RI LSA if already engaged */
- if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
+ if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
@@ -1502,7 +1499,7 @@ DEFUN (show_ip_ospf_router_info,
"Router Information\n")
{
- if (OspfRI.status == enabled) {
+ if (OspfRI.enabled) {
vty_out(vty, "--- Router Information parameters ---\n");
show_vty_router_cap(vty, &OspfRI.router_cap.header);
} else {
@@ -1528,7 +1525,7 @@ DEFUN (show_ip_opsf_router_info_pce,
struct ri_pce_subtlv_domain *domain;
struct ri_pce_subtlv_neighbor *neighbor;
- if (OspfRI.status == enabled) {
+ if (OspfRI.enabled) {
vty_out(vty, "--- PCE parameters ---\n");
if (pce->pce_address.header.type != 0)
diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h
index 50221b25c5..2d90730d93 100644
--- a/ospfd/ospf_ri.h
+++ b/ospfd/ospf_ri.h
@@ -65,21 +65,6 @@
*/
/*
- * 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.
*/
@@ -91,7 +76,7 @@ struct ri_tlv_header {
#define RI_TLV_CAPABILITIES 1
struct ri_tlv_router_cap {
- struct ri_tlv_header header; /* Value length is 4 bytes. */
+ struct tlv_header header; /* Value length is 4 bytes. */
u_int32_t value;
};
@@ -109,23 +94,19 @@ struct ri_tlv_router_cap {
#define RI_TLV_PCE 6
struct ri_tlv_pce {
- struct ri_tlv_header header;
+ struct 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. */
- /* $FRR indent$ */
- /* clang-format off */
+ /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
+ struct tlv_header header;
#define PCE_ADDRESS_LENGTH_IPV4 8
#define PCE_ADDRESS_LENGTH_IPV6 20
struct {
u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */
- /* $FRR indent$ */
- /* clang-format off */
#define PCE_ADDRESS_TYPE_IPV4 1
#define PCE_ADDRESS_TYPE_IPV6 2
u_int16_t reserved;
@@ -136,9 +117,12 @@ struct ri_pce_subtlv_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 */
+ struct tlv_header header; /* Type = 2; Length = 4 bytes. */
+ /*
+ * L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY bits:
+ * see RFC5088 page 9
+ */
+ u_int32_t value;
};
/* PCE Domain Sub-TLV */ /* Optional */
@@ -148,7 +132,7 @@ struct ri_pce_subtlv_path_scope {
#define PCE_DOMAIN_TYPE_AS 2
struct ri_pce_subtlv_domain {
- struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */
+ struct 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;
@@ -157,7 +141,7 @@ struct ri_pce_subtlv_domain {
/* 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. */
+ struct 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;
@@ -177,7 +161,7 @@ struct ri_pce_subtlv_neighbor {
#define PCE_CAP_MULTIPLE_REQ 0x0100
struct ri_pce_subtlv_cap_flag {
- struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */
+ struct tlv_header header; /* Type = 5; Length = n x 4 bytes. */
u_int32_t value;
};
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 4ca6578eae..1c1c76c1af 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -68,9 +68,7 @@
*/
struct ospf_mpls_te OspfMplsTE;
-const char *mode2text[] = {"Disable", "AS", "Area", "Emulate"};
-
-enum oifstate { OI_ANY, OI_DOWN, OI_UP };
+const char *mode2text[] = {"Off", "AS", "Area"};
/*------------------------------------------------------------------------*
* Followings are initialize/terminate functions for MPLS-TE handling.
@@ -106,29 +104,28 @@ int ospf_mpls_te_init(void)
if (rc != 0) {
zlog_warn(
"ospf_mpls_te_init: Failed to register Traffic Engineering functions");
- goto out;
+ return rc;
}
memset(&OspfMplsTE, 0, sizeof(struct ospf_mpls_te));
- OspfMplsTE.status = disabled;
- OspfMplsTE.inter_as = Disable;
+ OspfMplsTE.enabled = false;
+ OspfMplsTE.inter_as = Off;
OspfMplsTE.iflist = list_new();
OspfMplsTE.iflist->del = del_mpls_te_link;
ospf_mpls_te_register_vty();
-out:
return rc;
}
/* Additional register for RFC5392 support */
static int ospf_mpls_te_register(enum inter_as_mode mode)
{
- int rc;
+ int rc = 0;
u_int8_t scope;
- if (OspfMplsTE.inter_as != Disable)
- return 0;
+ if (OspfMplsTE.inter_as != Off)
+ return rc;
if (mode == AS)
scope = OSPF_OPAQUE_AS_LSA;
@@ -147,14 +144,14 @@ static int ospf_mpls_te_register(enum inter_as_mode mode)
return rc;
}
- return 0;
+ return rc;
}
static int ospf_mpls_te_unregister()
{
u_int8_t scope;
- if (OspfMplsTE.inter_as == Disable)
+ if (OspfMplsTE.inter_as == Off)
return 0;
if (OspfMplsTE.inter_as == AS)
@@ -174,10 +171,10 @@ void ospf_mpls_te_term(void)
ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
- OspfMplsTE.status = disabled;
+ OspfMplsTE.enabled = false;
ospf_mpls_te_unregister();
- OspfMplsTE.inter_as = Disable;
+ OspfMplsTE.inter_as = Off;
return;
}
@@ -192,7 +189,7 @@ static void del_mpls_te_link(void *val)
return;
}
-u_int32_t get_mpls_te_instance_value(void)
+static u_int32_t get_mpls_te_instance_value(void)
{
static u_int32_t seqno = 0;
@@ -204,41 +201,6 @@ u_int32_t get_mpls_te_instance_value(void)
return seqno;
}
-static struct ospf_interface *lookup_oi_by_ifp(struct interface *ifp,
- struct ospf_area *area,
- enum oifstate oifstate)
-{
- struct ospf_interface *oi = NULL;
- struct route_node *rn;
-
- for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
- if ((oi = rn->info) == NULL)
- continue;
-
- switch (oifstate) {
- case OI_ANY:
- break;
- case OI_DOWN:
- if (ospf_if_is_enable(oi))
- continue;
- break;
- case OI_UP:
- if (!ospf_if_is_enable(oi))
- continue;
- break;
- default:
- zlog_warn("lookup_oi_by_ifp: Unknown oifstate: %x",
- oifstate);
- goto out;
- }
-
- if (area == NULL || oi->area == area)
- return oi;
- }
-out:
- return NULL;
-}
-
static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
{
struct listnode *node, *nnode;
@@ -267,8 +229,8 @@ static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
}
static void ospf_mpls_te_foreach_area(void (*func)(struct mpls_te_link *lp,
- opcode_t sched_opcode),
- opcode_t sched_opcode)
+ enum lsa_opcode sched_opcode),
+ enum lsa_opcode sched_opcode)
{
struct listnode *node, *nnode;
struct listnode *node2;
@@ -281,8 +243,8 @@ static void ospf_mpls_te_foreach_area(void (*func)(struct mpls_te_link *lp,
continue;
if ((area = lp->area) == NULL)
continue;
- if
- CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE) continue;
+ if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
+ continue;
if (func != NULL)
(*func)(lp, sched_opcode);
@@ -793,14 +755,25 @@ static void update_linkparams(struct mpls_te_link *lp)
static void initialize_linkparams(struct mpls_te_link *lp)
{
struct interface *ifp = lp->ifp;
- struct ospf_interface *oi;
+ struct ospf_interface *oi = NULL;
+ struct route_node *rn;
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) {
+ /* Search OSPF Interface parameters for this interface */
+ for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) {
+
+ if ((oi = rn->info) == NULL)
+ continue;
+
+ if (oi->ifp == ifp)
+ break;
+ }
+
+ if ((oi == NULL) || (oi->ifp != ifp)) {
if (IS_DEBUG_OSPF_TE)
zlog_warn(
"MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
@@ -818,7 +791,7 @@ static void initialize_linkparams(struct mpls_te_link *lp)
set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
/* Set Remote IP addr if Point to Point Interface */
- if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) {
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
struct prefix *pref = CONNECTED_PREFIX(oi->connected);
if (pref != NULL)
set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
@@ -837,21 +810,20 @@ static int is_mandated_params_set(struct mpls_te_link *lp)
if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
zlog_warn(
"MPLS-TE(is_mandated_params_set) Missing Router Address");
- goto out;
+ return rc;
}
if (ntohs(lp->link_type.header.type) == 0) {
zlog_warn("MPLS-TE(is_mandated_params_set) Missing Link Type");
- goto out;
+ return rc;
}
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;
+ return rc;
}
rc = 1;
-out:
return rc;
}
@@ -873,14 +845,14 @@ static int ospf_mpls_te_new_if(struct interface *ifp)
zlog_warn("ospf_mpls_te_new_if: ifp(%p) already in use?",
(void *)ifp);
rc = 0; /* Do nothing here. */
- goto out;
+ return rc;
}
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;
+ return rc;
}
new->instance = get_mpls_te_instance_value();
@@ -909,7 +881,6 @@ static int ospf_mpls_te_new_if(struct interface *ifp)
/* Schedule Opaque-LSA refresh. */ /* XXX */
rc = 0;
-out:
return rc;
}
@@ -934,7 +905,6 @@ static int ospf_mpls_te_del_if(struct interface *ifp)
/* Schedule Opaque-LSA refresh. */ /* XXX */
rc = 0;
- /*out:*/
return rc;
}
@@ -952,10 +922,9 @@ void ospf_mpls_te_update_if(struct interface *ifp)
/* Get Link context from interface */
if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
- if (IS_DEBUG_OSPF_TE)
- zlog_warn(
- "OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
- ifp->name);
+ zlog_warn(
+ "OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
+ ifp->name);
return;
}
@@ -968,20 +937,18 @@ void ospf_mpls_te_update_if(struct interface *ifp)
/* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
* enabled */
- if (OspfMplsTE.status == enabled)
+ if (OspfMplsTE.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);
+ 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);
+ 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;
@@ -1000,14 +967,14 @@ static void 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;
+ return;
}
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));
- goto out;
+ return;
}
#ifdef notyet
if ((lp->area != NULL
@@ -1059,24 +1026,21 @@ static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
!= ntohs(lp->link_id.header.type)
|| ntohl(old_id.value.s_addr)
!= ntohl(lp->link_id.value.s_addr))) {
- 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);
+ 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);
}
break;
default:
lp->link_type.header.type = htons(0);
lp->link_id.header.type = htons(0);
- if
- CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
- ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
+ if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
+ ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
break;
}
-out:
return;
}
@@ -1090,28 +1054,28 @@ static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
* Followings are OSPF protocol processing functions for MPLS-TE.
*------------------------------------------------------------------------*/
-static void build_tlv_header(struct stream *s, struct te_tlv_header *tlvh)
+static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
{
- stream_put(s, tlvh, sizeof(struct te_tlv_header));
+ stream_put(s, tlvh, sizeof(struct tlv_header));
return;
}
static void build_router_tlv(struct stream *s)
{
- struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
+ struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
if (ntohs(tlvh->type) != 0) {
build_tlv_header(s, tlvh);
- stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh));
+ stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
}
return;
}
-static void build_link_subtlv(struct stream *s, struct te_tlv_header *tlvh)
+static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
{
if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
build_tlv_header(s, tlvh);
- stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh));
+ stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
}
return;
}
@@ -1177,7 +1141,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
/* Create a stream for LSA. */
if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
zlog_warn("ospf_mpls_te_lsa_new: stream_new() ?");
- goto out;
+ return NULL;
}
lsah = (struct lsa_header *)STREAM_DATA(s);
@@ -1233,14 +1197,14 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
if ((new = ospf_lsa_new()) == NULL) {
zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
stream_free(s);
- goto out;
+ return NULL;
}
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
- goto out;
+ return new;
}
new->area = area;
@@ -1248,7 +1212,6 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
memcpy(new->data, lsah, length);
stream_free(s);
-out:
return new;
}
@@ -1262,14 +1225,14 @@ static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) {
zlog_warn(
"ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
- goto out;
+ return rc;
}
/* Install this LSA into LSDB. */
if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
zlog_warn("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
ospf_lsa_unlock(&new);
- goto out;
+ return rc;
}
/* Now this link-parameter entry has associated LSA. */
@@ -1291,7 +1254,6 @@ static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
}
rc = 0;
-out:
return rc;
}
@@ -1302,11 +1264,11 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
struct mpls_te_link *lp;
int rc = -1;
- if (OspfMplsTE.status == disabled) {
+ if (!OspfMplsTE.enabled) {
zlog_info(
"ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
rc = 0; /* This is not an error case. */
- goto out;
+ return rc;
}
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
@@ -1321,23 +1283,16 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
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);
- 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 (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
+ if (CHECK_FLAG(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_area: Link(%s) lacks some mandated MPLS-TE parameters.",
@@ -1352,11 +1307,10 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
lp->instance, inet_ntoa(area->area_id),
lp->ifp ? lp->ifp->name : "?");
if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
- goto out;
+ return rc;
}
rc = 0;
-out:
return rc;
}
@@ -1370,14 +1324,14 @@ static int ospf_mpls_te_lsa_originate2(struct ospf *top,
if ((new = ospf_mpls_te_lsa_new(NULL, lp)) == NULL) {
zlog_warn(
"ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
- goto out;
+ return rc;
}
/* 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;
+ return rc;
}
/* Now this Router Info parameter entry has associated LSA. */
@@ -1396,7 +1350,6 @@ static int ospf_mpls_te_lsa_originate2(struct ospf *top,
}
rc = 0;
-out:
return rc;
}
@@ -1408,12 +1361,12 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
struct mpls_te_link *lp;
int rc = -1;
- if ((OspfMplsTE.status == disabled)
- || (OspfMplsTE.inter_as == Disable)) {
+ if ((!OspfMplsTE.enabled)
+ || (OspfMplsTE.inter_as == Off)) {
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;
+ return rc;
}
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
@@ -1422,21 +1375,14 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
|| !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 (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.",
@@ -1462,7 +1408,6 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
}
rc = 0;
-out:
return rc;
}
@@ -1473,7 +1418,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
struct ospf *top;
struct ospf_lsa *new = NULL;
- if (OspfMplsTE.status == disabled) {
+ if (!OspfMplsTE.enabled) {
/*
* This LSA must have flushed before due to MPLS-TE status
* change.
@@ -1504,13 +1449,13 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
if (lp)
UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(lsa);
- goto out;
+ return NULL;
}
/* Create new Opaque-LSA/MPLS-TE instance. */
if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) {
zlog_warn("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
- goto out;
+ return NULL;
}
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
@@ -1526,7 +1471,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
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;
+ return NULL;
}
/* Flood updated LSA through AS or Area depending of the RFC of the link
@@ -1543,11 +1488,10 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
ospf_lsa_header_dump(new->data);
}
-out:
return new;
}
-void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, opcode_t opcode)
+void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
{
struct ospf_lsa lsa;
struct lsa_header lsah;
@@ -1636,7 +1580,7 @@ void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, opcode_t opcode)
*------------------------------------------------------------------------*/
static u_int16_t show_vty_router_addr(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
@@ -1649,7 +1593,7 @@ static u_int16_t show_vty_router_addr(struct vty *vty,
}
static u_int16_t show_vty_link_header(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
@@ -1664,7 +1608,7 @@ static u_int16_t show_vty_link_header(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_link_type(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_link_type *top;
const char *cp = "Unknown";
@@ -1691,7 +1635,7 @@ static u_int16_t show_vty_link_subtlv_link_type(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_link_id(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_link_id *top;
@@ -1705,7 +1649,7 @@ static u_int16_t show_vty_link_subtlv_link_id(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_lclif_ipaddr *top;
int i, n;
@@ -1730,7 +1674,7 @@ static u_int16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_rmtif_ipaddr *top;
int i, n;
@@ -1754,7 +1698,7 @@ static u_int16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_te_metric(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_te_metric *top;
@@ -1770,7 +1714,7 @@ static u_int16_t show_vty_link_subtlv_te_metric(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_max_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_max_bw *top;
float fval;
@@ -1787,7 +1731,7 @@ static u_int16_t show_vty_link_subtlv_max_bw(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_max_rsv_bw *top;
float fval;
@@ -1806,7 +1750,7 @@ static u_int16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_unrsv_bw *top;
float fval1, fval2;
@@ -1837,7 +1781,7 @@ static u_int16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_rsc_clsclr *top;
@@ -1853,7 +1797,7 @@ static u_int16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_lrrid(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_lrrid *top;
@@ -1875,7 +1819,7 @@ static u_int16_t show_vty_link_subtlv_lrrid(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_llri(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_llri *top;
@@ -1897,7 +1841,7 @@ static u_int16_t show_vty_link_subtlv_llri(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_rip(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_rip *top;
@@ -1914,7 +1858,7 @@ static u_int16_t show_vty_link_subtlv_rip(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_ras(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_ras *top;
@@ -1931,7 +1875,7 @@ static u_int16_t show_vty_link_subtlv_ras(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_av_delay(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_av_delay *top;
u_int32_t delay;
@@ -1952,7 +1896,7 @@ static u_int16_t show_vty_link_subtlv_av_delay(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_mm_delay *top;
u_int32_t low, high;
@@ -1974,7 +1918,7 @@ static u_int16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_delay_var(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_delay_var *top;
u_int32_t jitter;
@@ -1991,7 +1935,7 @@ static u_int16_t show_vty_link_subtlv_delay_var(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_pkt_loss *top;
u_int32_t loss;
@@ -2014,7 +1958,7 @@ static u_int16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_res_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_res_bw *top;
float fval;
@@ -2035,7 +1979,7 @@ static u_int16_t show_vty_link_subtlv_res_bw(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_ava_bw *top;
float fval;
@@ -2056,7 +2000,7 @@ static u_int16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
}
static u_int16_t show_vty_link_subtlv_use_bw(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
struct te_link_subtlv_use_bw *top;
float fval;
@@ -2077,7 +2021,7 @@ static u_int16_t show_vty_link_subtlv_use_bw(struct vty *vty,
}
static u_int16_t show_vty_unknown_tlv(struct vty *vty,
- struct te_tlv_header *tlvh)
+ struct tlv_header *tlvh)
{
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
@@ -2090,11 +2034,11 @@ static u_int16_t show_vty_unknown_tlv(struct vty *vty,
}
static u_int16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
- struct te_tlv_header *tlvh0,
+ struct tlv_header *tlvh0,
u_int16_t subtotal,
u_int16_t total)
{
- struct te_tlv_header *tlvh, *next;
+ struct tlv_header *tlvh, *next;
u_int16_t sum = subtotal;
for (tlvh = tlvh0; sum < total;
@@ -2172,9 +2116,9 @@ static u_int16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
{
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
- struct te_tlv_header *tlvh, *next;
+ struct tlv_header *tlvh, *next;
u_int16_t sum, total;
- u_int16_t (*subfunc)(struct vty * vty, struct te_tlv_header * tlvh,
+ u_int16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
u_int16_t subtotal, u_int16_t total) = NULL;
sum = 0;
@@ -2184,7 +2128,7 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
if (subfunc != NULL) {
sum = (*subfunc)(vty, tlvh, sum, total);
- next = (struct te_tlv_header *)((char *)tlvh + sum);
+ next = (struct tlv_header *)((char *)tlvh + sum);
subfunc = NULL;
continue;
}
@@ -2197,7 +2141,7 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
case TE_TLV_LINK:
sum += show_vty_link_header(vty, tlvh);
subfunc = ospf_mpls_te_show_link_subtlv;
- next = tlvh + 1;
+ next = TLV_DATA(tlvh);
break;
default:
sum += show_vty_unknown_tlv(vty, tlvh);
@@ -2210,7 +2154,7 @@ static void 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) {
+ if (OspfMplsTE.enabled) {
vty_out(vty, " mpls-te on\n");
vty_out(vty, " mpls-te router-address %s\n",
inet_ntoa(OspfMplsTE.router_addr.value));
@@ -2235,24 +2179,24 @@ DEFUN (ospf_mpls_te_on,
MPLS_TE_STR
"Enable the MPLS-TE functionality\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *node;
struct mpls_te_link *lp;
- if (OspfMplsTE.status == enabled)
+ if (OspfMplsTE.enabled)
return CMD_SUCCESS;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("MPLS-TE: OFF -> ON");
- OspfMplsTE.status = enabled;
+ OspfMplsTE.enabled = true;
/* Reoriginate RFC3630 & RFC6827 Links */
ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
REORIGINATE_THIS_LSA);
/* Reoriginate LSA if INTER-AS is always on */
- if (OspfMplsTE.inter_as != Disable) {
+ if (OspfMplsTE.inter_as != Off) {
for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
if (IS_INTER_AS(lp->type)) {
ospf_mpls_te_lsa_schedule(lp,
@@ -2271,22 +2215,21 @@ DEFUN (no_ospf_mpls_te,
MPLS_TE_STR
"Disable the MPLS-TE functionality\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *node, *nnode;
struct mpls_te_link *lp;
- if (OspfMplsTE.status == disabled)
+ if (!OspfMplsTE.enabled)
return CMD_SUCCESS;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("MPLS-TE: ON -> OFF");
- OspfMplsTE.status = disabled;
+ OspfMplsTE.enabled = false;
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
- if
- CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
- ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
+ if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
+ ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -2299,7 +2242,7 @@ DEFUN (ospf_mpls_te_router_addr,
"Stable IP address of the advertising router\n"
"MPLS-TE router address in IPv4 address format\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 2;
struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
struct in_addr value;
@@ -2317,8 +2260,8 @@ DEFUN (ospf_mpls_te_router_addr,
set_mpls_te_router_addr(value);
- if (OspfMplsTE.status == disabled)
- goto out;
+ if (!OspfMplsTE.enabled)
+ return CMD_SUCCESS;
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
@@ -2344,7 +2287,7 @@ DEFUN (ospf_mpls_te_router_addr,
ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
REORIGINATE_THIS_LSA);
}
-out:
+
return CMD_SUCCESS;
}
@@ -2356,7 +2299,7 @@ static int set_inter_as_mode(struct vty *vty, const char *mode_name,
struct mpls_te_link *lp;
int format;
- if (OspfMplsTE.status == enabled) {
+ if (OspfMplsTE.enabled) {
/* Read and Check inter_as mode */
if (strcmp(mode_name, "as") == 0)
@@ -2385,7 +2328,7 @@ static int set_inter_as_mode(struct vty *vty, const char *mode_name,
}
/* Enable mode and re-originate LSA if needed */
- if ((OspfMplsTE.inter_as == Disable)
+ if ((OspfMplsTE.inter_as == Off)
&& (mode != OspfMplsTE.inter_as)) {
OspfMplsTE.inter_as = mode;
/* Re-originate all InterAS-TEv2 LSA */
@@ -2451,9 +2394,9 @@ DEFUN (no_ospf_mpls_te_inter_as,
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("MPLS-TE: Inter-AS support OFF");
- if ((OspfMplsTE.status == enabled)
- && (OspfMplsTE.inter_as != Disable)) {
- OspfMplsTE.inter_as = Disable;
+ if ((OspfMplsTE.enabled)
+ && (OspfMplsTE.inter_as != Off)) {
+ OspfMplsTE.inter_as = Off;
/* Flush all Inter-AS LSA */
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
if (IS_INTER_AS(lp->type)
@@ -2476,7 +2419,7 @@ DEFUN (show_ip_ospf_mpls_te_router,
"MPLS-TE information\n"
"MPLS-TE Router parameters\n")
{
- if (OspfMplsTE.status == enabled) {
+ if (OspfMplsTE.enabled) {
vty_out(vty, "--- MPLS-TE router parameters ---\n");
if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
@@ -2492,7 +2435,7 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
{
struct mpls_te_link *lp;
- if ((OspfMplsTE.status == enabled) && HAS_LINK_PARAMS(ifp)
+ if ((OspfMplsTE.enabled) && 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
diff --git a/ospfd/ospf_te.h b/ospfd/ospf_te.h
index 4ee9139a3c..0134214510 100644
--- a/ospfd/ospf_te.h
+++ b/ospfd/ospf_te.h
@@ -78,7 +78,7 @@
#define FLOOD_AS 0x20
#define EMULATED 0x80
-#define IS_STD_TE(x) (x & STD_TE)
+#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)
@@ -95,57 +95,31 @@
#define LPFLG_LSA_FORCED_REFRESH 0x8
/*
- * Following section defines TLV (tag, length, value) structures,
- * used for Traffic Engineering.
- */
-struct te_tlv_header {
- u_int16_t type; /* TE_TLV_XXX (see below) */
- u_int16_t length; /* Value portion only, in octets */
-};
-
-#define TLV_HDR_SIZE (sizeof(struct te_tlv_header))
-
-#define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(u_int32_t)))
-
-#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
-
-#define TLV_HDR_TOP(lsah) \
- (struct te_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
-
-#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 */
#define TE_TLV_ROUTER_ADDR 1
struct te_tlv_router_addr {
- struct te_tlv_header header; /* Value length is 4 octets. */
+ struct tlv_header header; /* Value length is 4 octets. */
struct in_addr value;
};
/* Link TLV */
#define TE_TLV_LINK 2
struct te_tlv_link {
- struct te_tlv_header header;
+ struct tlv_header header;
/* A set of link-sub-TLVs will follow. */
};
+/* Default TE TLV size */
#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 tlv_header header; /* Value length is 1 octet. */
struct {
#define LINK_TYPE_SUBTLV_VALUE_PTP 1
#define LINK_TYPE_SUBTLV_VALUE_MA 2
@@ -157,42 +131,42 @@ struct te_link_subtlv_link_type {
/* 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 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
struct te_link_subtlv_lclif_ipaddr {
- struct te_tlv_header header; /* Value length is 4 x N octets. */
+ struct 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
struct te_link_subtlv_rmtif_ipaddr {
- struct te_tlv_header header; /* Value length is 4 x N octets. */
+ struct 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
struct te_link_subtlv_te_metric {
- struct te_tlv_header header; /* Value length is 4 octets. */
+ struct 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
struct te_link_subtlv_max_bw {
- struct te_tlv_header header; /* Value length is 4 octets. */
+ struct 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
struct te_link_subtlv_max_rsv_bw {
- struct te_tlv_header header; /* Value length is 4 octets. */
+ struct tlv_header header; /* Value length is 4 octets. */
float value; /* bytes/sec */
};
@@ -200,14 +174,14 @@ struct te_link_subtlv_max_rsv_bw {
#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. */
+ struct tlv_header header; /* Value length is 32 octets. */
float value[MAX_CLASS_TYPE]; /* One for each priority level. */
};
/* 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. */
+ struct tlv_header header; /* Value length is 4 octets. */
u_int32_t value; /* Admin. group membership. */
};
@@ -216,7 +190,7 @@ struct te_link_subtlv_rsc_clsclr {
#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 tlv_header header; /* Value length is 8 octets. */
struct in_addr local; /* Local TE Router Identifier */
struct in_addr remote; /* Remote TE Router Identifier */
};
@@ -225,7 +199,7 @@ struct te_link_subtlv_lrrid {
#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. */
+ struct tlv_header header; /* Value length is 8 octets. */
u_int32_t local; /* Link Local Identifier */
u_int32_t remote; /* Link Remote Identifier */
};
@@ -240,14 +214,14 @@ struct te_link_subtlv_llri {
/* 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. */
+ struct 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 tlv_header header; /* Value length is 4 octets. */
struct in_addr value; /* Remote ASBR IP address */
};
@@ -261,63 +235,69 @@ struct te_link_subtlv_rip {
/* 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 */
+ struct tlv_header header; /* Value length is 4 bytes. */
+ /*
+ * delay in micro-seconds only 24 bits => 0 ... 16777215
+ * with Anomalous Bit as Upper most bit
+ */
+ u_int32_t value;
};
/* 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 */
+ struct tlv_header header; /* Value length is 8 bytes. */
+ /*
+ * low delay in micro-seconds only 24 bits => 0 ... 16777215
+ * with Anomalous Bit (A) as Upper most bit
+ */
+ u_int32_t low;
+ /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */
+ u_int32_t high;
};
/* 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 */
+ struct tlv_header header; /* Value length is 4 bytes. */
+ /* interval in micro-seconds only 24 bits => 0 ... 16777215 */
+ u_int32_t value;
};
/* 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 */
+ struct tlv_header header; /* Value length is 4 bytes. */
+ /*
+ * in percentage of total traffic only 24 bits (2^24 - 2)
+ * with Anomalous Bit as Upper most bit
+ */
+ u_int32_t value;
};
/* 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 */
+ struct tlv_header header; /* Value length is 4 bytes. */
+ /* bandwidth in IEEE floating point format with units in bytes/second */
+ float value;
};
/* 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 */
+ struct tlv_header header; /* Value length is 4 octets. */
+ /* bandwidth in IEEE floating point format with units in bytes/second */
+ float value;
};
/* 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 */
+ struct tlv_header header; /* Value length is 4 octets. */
+ /* bandwidth in IEEE floating point format with units in bytes/second */
+ float value;
};
#define TE_LINK_SUBTLV_MAX 34 /* Last SUBTLV + 1 */
@@ -325,20 +305,11 @@ struct te_link_subtlv_use_bw {
/* 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 };
+enum inter_as_mode { Off, AS, Area };
struct te_link_subtlv {
- struct te_tlv_header header;
+ struct tlv_header header;
union {
u_int32_t link_type;
struct in_addr link_id;
@@ -366,7 +337,7 @@ struct te_link_subtlv {
/* Following structure are internal use only. */
struct ospf_mpls_te {
/* Status of MPLS-TE: enable or disbale */
- status_t status;
+ bool enabled;
/* RFC5392 */
enum inter_as_mode inter_as;
@@ -437,8 +408,7 @@ 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 ospf_mpls_te_lsa_schedule(struct mpls_te_link *, enum lsa_opcode);
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);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index a8bfb669af..13d4780db3 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -135,6 +135,7 @@ DEFUN_NOSH (router_ospf,
{
struct ospf *ospf;
u_short instance = 0;
+ int ret = CMD_SUCCESS;
ospf = ospf_lookup();
if (!ospf) {
@@ -147,9 +148,10 @@ DEFUN_NOSH (router_ospf,
/* The following logic to set the vty qobj index is in place to be able
to ignore the commands which dont belong to this instance. */
- if (ospf->instance != instance)
+ if (ospf->instance != instance) {
VTY_PUSH_CONTEXT_NULL(OSPF_NODE);
- else {
+ ret = CMD_NOT_MY_INSTANCE;
+ } else {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("Config command 'router ospf %d' received",
instance);
@@ -158,7 +160,7 @@ DEFUN_NOSH (router_ospf,
ospf_router_id_update(ospf);
}
- return CMD_SUCCESS;
+ return ret;
}
DEFUN (no_router_ospf,
@@ -175,8 +177,9 @@ DEFUN (no_router_ospf,
if (argc > 3)
instance = strtoul(argv[3]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL)
- return CMD_SUCCESS;
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
ospf_finish(ospf);
@@ -191,7 +194,7 @@ DEFUN (ospf_router_id,
"router-id for the OSPF process\n"
"OSPF router-id in IP address format\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 2;
struct listnode *node;
struct ospf_area *area;
@@ -225,7 +228,7 @@ DEFUN_HIDDEN (ospf_router_id_old,
"router-id for the OSPF process\n"
"OSPF router-id in IP address format\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 1;
struct listnode *node;
struct ospf_area *area;
@@ -261,7 +264,7 @@ DEFUN (no_ospf_router_id,
"router-id for the OSPF process\n"
"OSPF router-id in IP address format\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *node;
struct ospf_area *area;
@@ -350,7 +353,7 @@ DEFUN (ospf_passive_interface,
"IPv4 address\n"
"Suppress routing updates on interfaces by default\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 2;
struct interface *ifp;
struct in_addr addr = {.s_addr = INADDR_ANY};
@@ -417,7 +420,7 @@ DEFUN (no_ospf_passive_interface,
"IPv4 address\n"
"Allow routing updates on interfaces by default\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 3;
struct interface *ifp;
struct in_addr addr = {.s_addr = INADDR_ANY};
@@ -478,7 +481,7 @@ DEFUN (ospf_network_area,
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_prefixlen = 1;
int idx_ipv4_number = 3;
struct prefix_ipv4 p;
@@ -520,7 +523,7 @@ DEFUN (no_ospf_network_area,
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_prefixlen = 2;
int idx_ipv4_number = 4;
struct prefix_ipv4 p;
@@ -559,7 +562,7 @@ DEFUN (ospf_area_range,
"User specified metric for this range\n"
"Advertised metric for this range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx_cost = 6;
@@ -591,7 +594,7 @@ DEFUN (ospf_area_range_cost,
"User specified metric for this range\n"
"Advertised metric for this range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx_cost = 5;
@@ -623,7 +626,7 @@ DEFUN (ospf_area_range_not_advertise,
"Area range prefix\n"
"DoNotAdvertise this range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
struct prefix_ipv4 p;
@@ -656,7 +659,7 @@ DEFUN (no_ospf_area_range,
"Advertised metric for this range\n"
"DoNotAdvertise this range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
struct prefix_ipv4 p;
@@ -682,7 +685,7 @@ DEFUN (ospf_area_range_substitute,
"Announce area range as another prefix\n"
"Network prefix to be announced instead of range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx_ipv4_prefixlen_2 = 5;
@@ -713,7 +716,7 @@ DEFUN (no_ospf_area_range_substitute,
"Announce area range as another prefix\n"
"Network prefix to be announced instead of range\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
int idx_ipv4_prefixlen_2 = 6;
@@ -981,7 +984,7 @@ DEFUN (ospf_area_vlink,
"Use MD5 algorithm\n" \
"The OSPF password (key)")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_ipv4 = 3;
struct ospf_vl_config_data vl_config;
@@ -1105,7 +1108,7 @@ DEFUN (no_ospf_area_vlink,
"Use MD5 algorithm\n" \
"The OSPF password (key)")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
int idx_ipv4 = 4;
struct ospf_area *area;
@@ -1204,7 +1207,7 @@ DEFUN (ospf_area_vlink_intervals,
VLINK_HELPSTR_IPADDR
VLINK_HELPSTR_TIME_PARAM)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct ospf_vl_config_data vl_config;
int ret = 0;
@@ -1251,7 +1254,7 @@ DEFUN (no_ospf_area_vlink_intervals,
VLINK_HELPSTR_IPADDR
VLINK_HELPSTR_TIME_PARAM)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct ospf_vl_config_data vl_config;
int ret = 0;
@@ -1300,7 +1303,7 @@ DEFUN (ospf_area_shortcut,
"Enable shortcutting through the area\n"
"Disable shortcutting through the area\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_enable_disable = 3;
struct ospf_area *area;
@@ -1344,7 +1347,7 @@ DEFUN (no_ospf_area_shortcut,
"Deconfigure enabled shortcutting through the area\n"
"Deconfigure disabled shortcutting through the area\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct ospf_area *area;
struct in_addr area_id;
@@ -1371,7 +1374,7 @@ DEFUN (ospf_area_stub,
"OSPF area ID as a decimal value\n"
"Configure OSPF area as stub\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct in_addr area_id;
int ret, format;
@@ -1402,7 +1405,7 @@ DEFUN (ospf_area_stub_no_summary,
"Configure OSPF area as stub\n"
"Do not inject inter-area routes into stub\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct in_addr area_id;
int ret, format;
@@ -1433,7 +1436,7 @@ DEFUN (no_ospf_area_stub,
"OSPF area ID as a decimal value\n"
"Configure OSPF area as stub\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct in_addr area_id;
int format;
@@ -1457,7 +1460,7 @@ DEFUN (no_ospf_area_stub_no_summary,
"Configure OSPF area as stub\n"
"Do not inject inter-area routes into area\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct in_addr area_id;
int format;
@@ -1472,7 +1475,7 @@ DEFUN (no_ospf_area_stub_no_summary,
static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
struct cmd_token **argv, int nosum)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct in_addr area_id;
int ret, format;
@@ -1577,7 +1580,7 @@ DEFUN (no_ospf_area_nssa,
"Configure NSSA-ABR to always translate\n"
"Do not inject inter-area routes into nssa\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct in_addr area_id;
int format;
@@ -1603,7 +1606,7 @@ DEFUN (ospf_area_default_cost,
"Set the summary-default cost of a NSSA or stub area\n"
"Stub's advertised default summary cost\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_number = 3;
struct ospf_area *area;
@@ -1649,7 +1652,7 @@ DEFUN (no_ospf_area_default_cost,
"Set the summary-default cost of a NSSA or stub area\n"
"Stub's advertised default summary cost\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct ospf_area *area;
struct in_addr area_id;
@@ -1695,7 +1698,7 @@ DEFUN (ospf_area_export_list,
"Set the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct ospf_area *area;
struct in_addr area_id;
@@ -1720,7 +1723,7 @@ DEFUN (no_ospf_area_export_list,
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct ospf_area *area;
struct in_addr area_id;
@@ -1747,7 +1750,7 @@ DEFUN (ospf_area_import_list,
"Set the filter for networks from other areas announced to the specified one\n"
"Name of the access-list\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct ospf_area *area;
struct in_addr area_id;
@@ -1772,7 +1775,7 @@ DEFUN (no_ospf_area_import_list,
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct ospf_area *area;
struct in_addr area_id;
@@ -1801,7 +1804,7 @@ DEFUN (ospf_area_filter_list,
"Filter networks sent to this area\n"
"Filter networks sent from this area\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
int idx_word = 4;
int idx_in_out = 5;
@@ -1847,7 +1850,7 @@ DEFUN (no_ospf_area_filter_list,
"Filter networks sent to this area\n"
"Filter networks sent from this area\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
int idx_word = 5;
int idx_in_out = 6;
@@ -1901,7 +1904,7 @@ DEFUN (ospf_area_authentication_message_digest,
"Enable authentication\n"
"Use message-digest authentication\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct ospf_area *area;
struct in_addr area_id;
@@ -1924,7 +1927,7 @@ DEFUN (ospf_area_authentication,
"OSPF area ID as a decimal value\n"
"Enable authentication\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 1;
struct ospf_area *area;
struct in_addr area_id;
@@ -1948,7 +1951,7 @@ DEFUN (no_ospf_area_authentication,
"OSPF area ID as a decimal value\n"
"Enable authentication\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4_number = 2;
struct ospf_area *area;
struct in_addr area_id;
@@ -1978,7 +1981,7 @@ DEFUN (ospf_abr_type,
"Shortcut ABR\n"
"Standard behavior (RFC2328)\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_vendor = 2;
u_char abr_type = OSPF_ABR_UNKNOWN;
@@ -2013,7 +2016,7 @@ DEFUN (no_ospf_abr_type,
"Shortcut ABR\n"
"Standard ABR\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_vendor = 3;
u_char abr_type = OSPF_ABR_UNKNOWN;
@@ -2042,7 +2045,7 @@ DEFUN (ospf_log_adjacency_changes,
"log-adjacency-changes",
"Log changes in adjacency state\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL);
@@ -2055,7 +2058,7 @@ DEFUN (ospf_log_adjacency_changes_detail,
"Log changes in adjacency state\n"
"Log all state changes\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL);
@@ -2068,7 +2071,7 @@ DEFUN (no_ospf_log_adjacency_changes,
NO_STR
"Log changes in adjacency state\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL);
UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
@@ -2082,7 +2085,7 @@ DEFUN (no_ospf_log_adjacency_changes_detail,
"Log changes in adjacency state\n"
"Log all state changes\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
@@ -2094,7 +2097,7 @@ DEFUN (ospf_compatible_rfc1583,
"OSPF compatibility list\n"
"compatible with RFC 1583\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
SET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE);
@@ -2110,7 +2113,7 @@ DEFUN (no_ospf_compatible_rfc1583,
"OSPF compatibility list\n"
"compatible with RFC 1583\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
UNSET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE);
@@ -2132,7 +2135,7 @@ ALIAS(no_ospf_compatible_rfc1583, no_ospf_rfc1583_flag_cmd,
static int ospf_timers_spf_set(struct vty *vty, unsigned int delay,
unsigned int hold, unsigned int max)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->spf_delay = delay;
ospf->spf_holdtime = hold;
@@ -2150,7 +2153,7 @@ DEFUN (ospf_timers_min_ls_interval,
"All LSA types\n"
"Delay (msec) between sending LSAs\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 4;
unsigned int interval;
@@ -2176,54 +2179,12 @@ DEFUN (no_ospf_timers_min_ls_interval,
"All LSA types\n"
"Delay (msec) between sending LSAs\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL;
return CMD_SUCCESS;
}
-
-DEFUN (ospf_timers_min_ls_arrival,
- ospf_timers_min_ls_arrival_cmd,
- "timers lsa arrival (0-1000)",
- "Adjust routing timers\n"
- "Throttling link state advertisement delays\n"
- "OSPF minimum arrival interval delay\n"
- "Delay (msec) between accepted LSAs\n")
-{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
- int idx_number = 3;
- unsigned int arrival;
-
- if (argc < 4) {
- vty_out(vty, "Insufficient arguments\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- arrival = strtoul(argv[idx_number]->arg, NULL, 10);
-
- ospf->min_ls_arrival = arrival;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_timers_min_ls_arrival,
- no_ospf_timers_min_ls_arrival_cmd,
- "no timers lsa arrival [(0-1000)]",
- NO_STR
- "Adjust routing timers\n"
- "Throttling link state advertisement delays\n"
- "OSPF minimum arrival interval delay\n"
- "Delay (msec) between accepted LSAs\n")
-{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
-
- ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
-
- return CMD_SUCCESS;
-}
-
-
DEFUN (ospf_timers_throttle_spf,
ospf_timers_throttle_spf_cmd,
"timers throttle spf (0-600000) (0-600000) (0-600000)",
@@ -2268,32 +2229,21 @@ DEFUN (no_ospf_timers_throttle_spf,
}
-DEFUN (ospf_timers_lsa,
- ospf_timers_lsa_cmd,
+DEFUN (ospf_timers_lsa_min_arrival,
+ ospf_timers_lsa_min_arrival_cmd,
"timers lsa min-arrival (0-600000)",
"Adjust routing timers\n"
"OSPF LSA timers\n"
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
- int idx_number = 3;
- unsigned int minarrival;
-
- if (argc < 4) {
- vty_out(vty, "Insufficient number of arguments\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
-
- ospf->min_ls_arrival = minarrival;
-
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ ospf->min_ls_arrival = strtoul(argv[argc - 1]->arg, NULL, 10);
return CMD_SUCCESS;
}
-DEFUN (no_ospf_timers_lsa,
- no_ospf_timers_lsa_cmd,
+DEFUN (no_ospf_timers_lsa_min_arrival,
+ no_ospf_timers_lsa_min_arrival_cmd,
"no timers lsa min-arrival [(0-600000)]",
NO_STR
"Adjust routing timers\n"
@@ -2301,11 +2251,11 @@ DEFUN (no_ospf_timers_lsa,
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
unsigned int minarrival;
if (argc > 4) {
- minarrival = strtoul(argv[4]->arg, NULL, 10);
+ minarrival = strtoul(argv[argc - 1]->arg, NULL, 10);
if (ospf->min_ls_arrival != minarrival
|| minarrival == OSPF_MIN_LS_ARRIVAL)
@@ -2317,6 +2267,26 @@ DEFUN (no_ospf_timers_lsa,
return CMD_SUCCESS;
}
+/* Deprecated: 08/07/2017 */
+ALIAS_HIDDEN (ospf_timers_lsa_min_arrival,
+ ospf_timers_lsa_arrival_cmd,
+ "timers lsa arrival (0-1000)",
+ "adjust routing timers\n"
+ "throttling link state advertisement delays\n"
+ "ospf minimum arrival interval delay\n"
+ "delay (msec) between accepted lsas\n");
+
+/* Deprecated: 08/07/2017 */
+ALIAS_HIDDEN (no_ospf_timers_lsa_min_arrival,
+ no_ospf_timers_lsa_arrival_cmd,
+ "no timers lsa arrival (0-1000)",
+ NO_STR
+ "adjust routing timers\n"
+ "throttling link state advertisement delays\n"
+ "ospf minimum arrival interval delay\n"
+ "delay (msec) between accepted lsas\n");
+
+
DEFUN (ospf_neighbor,
ospf_neighbor_cmd,
"neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
@@ -2327,7 +2297,7 @@ DEFUN (ospf_neighbor,
"Dead Neighbor Polling interval\n"
"Seconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 1;
int idx_pri = 3;
int idx_poll = 5;
@@ -2364,7 +2334,7 @@ DEFUN (ospf_neighbor_poll_interval,
"OSPF priority of non-broadcast neighbor\n"
"Priority\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 1;
int idx_poll = 3;
int idx_pri = 5;
@@ -2399,7 +2369,7 @@ DEFUN (no_ospf_neighbor,
"Dead Neighbor Polling interval\n"
"Seconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 2;
struct in_addr nbr_addr;
@@ -2421,7 +2391,7 @@ DEFUN (no_ospf_neighbor_poll,
"Neighbor Priority\n"
"Priority\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ipv4 = 2;
struct in_addr nbr_addr;
@@ -2439,7 +2409,7 @@ DEFUN (ospf_refresh_timer,
"Set refresh timer\n"
"Timer value in seconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 2;
unsigned int interval;
@@ -2460,7 +2430,7 @@ DEFUN (no_ospf_refresh_timer,
"Unset refresh timer\n"
"Timer value in seconds\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 3;
unsigned int interval;
@@ -2485,7 +2455,7 @@ DEFUN (ospf_auto_cost_reference_bandwidth,
"Use reference bandwidth method to assign OSPF cost\n"
"The reference bandwidth in terms of Mbits per second\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 2;
u_int32_t refbw;
struct listnode *node;
@@ -2516,7 +2486,7 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth,
"Use reference bandwidth method to assign OSPF cost\n"
"The reference bandwidth in terms of Mbits per second\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *node, *nnode;
struct interface *ifp;
@@ -2541,7 +2511,7 @@ DEFUN (ospf_write_multiplier,
"Write multiplier\n"
"Maximum number of interface serviced per write\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number;
u_int32_t write_oi_count;
@@ -2572,7 +2542,7 @@ DEFUN (no_ospf_write_multiplier,
"Write multiplier\n"
"Maximum number of interface serviced per write\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT;
return CMD_SUCCESS;
@@ -3218,8 +3188,11 @@ DEFUN (show_ip_ospf_instance,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return (show_ip_ospf_common(vty, ospf, uj));
@@ -3654,8 +3627,11 @@ DEFUN (show_ip_ospf_instance_interface,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -3861,8 +3837,11 @@ DEFUN (show_ip_ospf_instance_neighbor,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_common(vty, ospf, uj);
@@ -3982,8 +3961,11 @@ DEFUN (show_ip_ospf_instance_neighbor_all,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_all_common(vty, ospf, uj);
@@ -4075,8 +4057,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_int_common(vty, ospf, 1, argv, uj);
@@ -4462,8 +4447,11 @@ DEFUN (show_ip_ospf_instance_neighbor_id,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_id_common(vty, ospf, 1, argv, uj);
@@ -4551,8 +4539,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_detail_common(vty, ospf, uj);
@@ -4652,8 +4643,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj);
@@ -4757,8 +4751,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail,
u_char uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 1, argv, uj);
@@ -5446,6 +5443,8 @@ DEFUN (show_ip_ospf_instance_database,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
} else {
ospf = ospf_lookup();
}
@@ -5474,8 +5473,11 @@ DEFUN (show_ip_ospf_instance_database_max,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return (show_ip_ospf_database_common(vty, ospf, 1, argc, argv));
@@ -5553,6 +5555,8 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
} else
ospf = ospf_lookup();
@@ -6922,7 +6926,7 @@ DEFUN (ip_ospf_area,
ospf = ospf_lookup();
ospf->if_ospf_cli_count--;
}
- return CMD_SUCCESS;
+ return CMD_NOT_MY_INSTANCE;
}
ret = str2area_id(areaid, &area_id, &format);
@@ -6995,8 +6999,9 @@ DEFUN (no_ip_ospf_area,
if (argv_find(argv, argc, "(1-65535)", &idx))
instance = strtol(argv[idx]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL)
- return CMD_SUCCESS;
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
argv_find(argv, argc, "area", &idx);
@@ -7038,7 +7043,7 @@ DEFUN (ospf_redistribute_source,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_protocol = 1;
int source;
int type = -1;
@@ -7088,7 +7093,7 @@ DEFUN (no_ospf_redistribute_source,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_protocol = 2;
int source;
struct ospf_redist *red;
@@ -7119,7 +7124,7 @@ DEFUN (ospf_redistribute_instance_source,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ospf_table = 1;
int idx_number = 2;
int idx = 3;
@@ -7187,7 +7192,7 @@ DEFUN (no_ospf_redistribute_instance_source,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_ospf_table = 2;
int idx_number = 3;
u_int instance;
@@ -7228,7 +7233,7 @@ DEFUN (ospf_distribute_list_out,
OUT_STR
FRR_REDIST_HELP_STR_OSPFD)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_word = 1;
int source;
@@ -7251,7 +7256,7 @@ DEFUN (no_ospf_distribute_list_out,
OUT_STR
FRR_REDIST_HELP_STR_OSPFD)
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_word = 2;
int source;
@@ -7278,7 +7283,7 @@ DEFUN (ospf_default_information_originate,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int default_originate = DEFAULT_ORIGINATE_ZEBRA;
int type = -1;
int metric = -1;
@@ -7324,7 +7329,7 @@ DEFUN (no_ospf_default_information_originate,
"Route map reference\n"
"Pointer to route-map entries\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct prefix_ipv4 p;
struct ospf_external *ext;
struct ospf_redist *red;
@@ -7355,7 +7360,7 @@ DEFUN (ospf_default_metric,
"Set metric of redistributed routes\n"
"Default metric\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 1;
int metric = -1;
@@ -7374,7 +7379,7 @@ DEFUN (no_ospf_default_metric,
"Set metric of redistributed routes\n"
"Default metric\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->default_metric = -1;
@@ -7388,7 +7393,7 @@ DEFUN (ospf_distance,
"Administrative distance\n"
"OSPF Administrative distance\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 1;
ospf->distance_all = atoi(argv[idx_number]->arg);
@@ -7403,7 +7408,7 @@ DEFUN (no_ospf_distance,
"Administrative distance\n"
"OSPF Administrative distance\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->distance_all = 0;
@@ -7423,7 +7428,7 @@ DEFUN (no_ospf_distance_ospf,
"External routes\n"
"Distance for external routes\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx = 0;
if (!ospf)
@@ -7451,7 +7456,7 @@ DEFUN (ospf_distance_ospf,
"External routes\n"
"Distance for external routes\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx = 0;
if (argv_find(argv, argc, "intra-area", &idx))
@@ -7636,7 +7641,7 @@ DEFUN (ospf_max_metric_router_lsa_admin,
"Advertise own Router-LSA with infinite distance (stub router)\n"
"Administratively applied, for an indefinite period\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *ln;
struct ospf_area *area;
@@ -7662,7 +7667,7 @@ DEFUN (no_ospf_max_metric_router_lsa_admin,
"Advertise own Router-LSA with infinite distance (stub router)\n"
"Administratively applied, for an indefinite period\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *ln;
struct ospf_area *area;
@@ -7691,7 +7696,7 @@ DEFUN (ospf_max_metric_router_lsa_startup,
"Automatically advertise stub Router-LSA on startup of OSPF\n"
"Time (seconds) to advertise self as stub-router\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 3;
unsigned int seconds;
@@ -7716,7 +7721,7 @@ DEFUN (no_ospf_max_metric_router_lsa_startup,
"Automatically advertise stub Router-LSA on startup of OSPF\n"
"Time (seconds) to advertise self as stub-router\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct listnode *ln;
struct ospf_area *area;
@@ -7747,7 +7752,7 @@ DEFUN (ospf_max_metric_router_lsa_shutdown,
"Advertise stub-router prior to full shutdown of OSPF\n"
"Time (seconds) to wait till full shutdown\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 3;
unsigned int seconds;
@@ -7772,7 +7777,7 @@ DEFUN (no_ospf_max_metric_router_lsa_shutdown,
"Advertise stub-router prior to full shutdown of OSPF\n"
"Time (seconds) to wait till full shutdown\n")
{
- VTY_DECLVAR_CONTEXT(ospf, ospf);
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
@@ -8034,8 +8039,11 @@ DEFUN (show_ip_ospf_instance_border_routers,
u_short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_border_routers_common(vty, ospf);
@@ -8095,8 +8103,11 @@ DEFUN (show_ip_ospf_instance_route,
u_short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL
- || !ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (ospf == NULL)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (!ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_route_common(vty, ospf);
@@ -9141,10 +9152,10 @@ void ospf_vty_init(void)
/* LSA timers commands */
install_element(OSPF_NODE, &ospf_timers_min_ls_interval_cmd);
install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd);
- install_element(OSPF_NODE, &ospf_timers_min_ls_arrival_cmd);
- install_element(OSPF_NODE, &no_ospf_timers_min_ls_arrival_cmd);
- install_element(OSPF_NODE, &ospf_timers_lsa_cmd);
- install_element(OSPF_NODE, &no_ospf_timers_lsa_cmd);
+ install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd);
+ install_element(OSPF_NODE, &no_ospf_timers_lsa_min_arrival_cmd);
+ install_element(OSPF_NODE, &ospf_timers_lsa_arrival_cmd);
+ install_element(OSPF_NODE, &no_ospf_timers_lsa_arrival_cmd);
/* refresh timer commands */
install_element(OSPF_NODE, &ospf_refresh_timer_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index c6b0955dab..ec8f1ee852 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -51,6 +51,9 @@
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_te.h"
+DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table")
+DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute")
+
DEFINE_HOOK(ospf_if_update, (struct interface * ifp), (ifp))
DEFINE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp))
@@ -628,7 +631,8 @@ struct ospf_external *ospf_external_add(u_char type, u_short instance)
om->external[type] = list_new();
ext_list = om->external[type];
- ext = (struct ospf_external *)calloc(1, sizeof(struct ospf_external));
+ ext = (struct ospf_external *)XCALLOC(MTYPE_OSPF_EXTERNAL,
+ sizeof(struct ospf_external));
ext->instance = instance;
EXTERNAL_INFO(ext) = route_table_init();
@@ -652,6 +656,7 @@ void ospf_external_del(u_char type, u_short instance)
list_free(om->external[type]);
om->external[type] = NULL;
}
+ XFREE(MTYPE_OSPF_EXTERNAL, ext);
}
}
@@ -687,7 +692,8 @@ struct ospf_redist *ospf_redist_add(struct ospf *ospf, u_char type,
ospf->redist[type] = list_new();
red_list = ospf->redist[type];
- red = (struct ospf_redist *)calloc(1, sizeof(struct ospf_redist));
+ red = (struct ospf_redist *)XCALLOC(MTYPE_OSPF_REDISTRIBUTE,
+ sizeof(struct ospf_redist));
red->instance = instance;
red->dmetric.type = -1;
red->dmetric.value = -1;
@@ -709,6 +715,7 @@ void ospf_redist_del(struct ospf *ospf, u_char type, u_short instance)
list_free(ospf->redist[type]);
ospf->redist[type] = NULL;
}
+ XFREE(MTYPE_OSPF_REDISTRIBUTE, red);
}
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index cee2244dd9..b3553238ef 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -590,6 +590,7 @@ static void ospf_finish_final(struct ospf *ospf)
route_unlock_node(rn);
}
}
+ route_table_finish(ospf->networks);
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
listnode_delete(ospf->areas, area);
@@ -655,6 +656,8 @@ static void ospf_finish_final(struct ospf *ospf)
}
list_delete(ospf->areas);
+ list_delete(ospf->oi_write_q);
+ list_delete(ospf->oiflist);
for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
struct list *ext_list;
@@ -752,6 +755,7 @@ static void ospf_area_free(struct ospf_area *area)
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+ ospf_opaque_type10_lsa_term(area);
ospf_lsdb_delete_all(area->lsdb);
ospf_lsdb_free(area->lsdb);
@@ -976,9 +980,13 @@ int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p,
rn->info = NULL;
route_unlock_node(rn); /* initial reference */
- /* Find interfaces that not configured already. */
+ /* Find interfaces that are not configured already. */
for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
- ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
+
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+ continue;
+
+ ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
}
/* Update connected redistribute. */
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 4142f1a3e9..b49bbdc17d 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -101,7 +101,7 @@ struct ospf_master {
/* Various OSPF global configuration. */
u_char options;
-#define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
+#define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
};
struct ospf_redist {
diff --git a/pimd/Makefile.am b/pimd/Makefile.am
index 0dd6c569dc..f440221d42 100644
--- a/pimd/Makefile.am
+++ b/pimd/Makefile.am
@@ -53,7 +53,8 @@ libpim_a_SOURCES = \
pim_ssmpingd.c pim_int.c pim_rp.c \
pim_static.c pim_br.c pim_register.c pim_routemap.c \
pim_msdp.c pim_msdp_socket.c pim_msdp_packet.c \
- pim_jp_agg.c pim_nht.c pim_ssm.c pim_bfd.c
+ pim_jp_agg.c pim_nht.c pim_ssm.c pim_bfd.c \
+ pim_instance.c
noinst_HEADERS = \
pim_memory.h \
@@ -66,7 +67,7 @@ noinst_HEADERS = \
pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \
pim_static.h pim_br.h pim_register.h \
pim_msdp.h pim_msdp_socket.h pim_msdp_packet.h pim_nht.h \
- pim_jp_agg.h pim_ssm.h pim_bfd.h
+ pim_jp_agg.h pim_ssm.h pim_bfd.h pim_instance.h
pimd_SOURCES = \
pim_main.c $(libpim_a_SOURCES)
diff --git a/pimd/WHY_SSM b/pimd/WHY_SSM
deleted file mode 100644
index 2e8c966f16..0000000000
--- a/pimd/WHY_SSM
+++ /dev/null
@@ -1,32 +0,0 @@
-WHY SSM
-
-Benefis of PIM SSM over PIM SM
-------------------------------
-
-- SSM consumes minimum link bandwidth
-- SSM simplifies multicast address management (specially important for
- inter-domain multicast)
- - SSM (S,G) channels easily provide unique per-application addressing
- - SSM does not require MSDP between PIM domains
-- SSM does not suffer instabilities from traffic-driven SPT switchover
-- SSM is not suscetible to DoS attack from unwanted sources
-- SSM does not use RP. Some RP issues:
- - RP is possible point of failure
- - RP demands redundancy management
- - RP may require PIM dense mode support for RP election
- - RP is possible performance bottleneck
- - RP may demand lots of extra management
-- SSM can be deployed in an existing PIM SM network (only the last hop
- routers need to support IGMPv3)
-- SSM is easier to deploy and maintain
-
-PIM-SSM drawbacks
------------------
-
-- SSM requires IGMPv3 support on both receivers and last-hop routers
-- SSM may be memory intensive when managing (S,G) states for
- many-to-many multicast distribution
-- SSM will keep (S,G) state as long as there are subscriptions from
- receivers, even if the source is not actually sending traffic
-
---EOF--
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index f68c252a35..934fea5a9e 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -47,6 +47,7 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
struct in_addr winner,
struct pim_assert_metric winner_metric)
{
+ struct pim_interface *pim_ifp = ch->interface->info;
int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr);
int metric_changed = !pim_assert_metric_match(
&ch->ifassert_winner_metric, &winner_metric);
@@ -81,7 +82,7 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
ch->ifassert_creation = pim_time_monotonic_sec();
if (winner_changed || metric_changed) {
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
pim_ifchannel_update_could_assert(ch);
pim_ifchannel_update_assert_tracking_desired(ch);
}
@@ -146,7 +147,7 @@ static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,
memset(&sg, 0, sizeof(struct prefix_sg));
sg.src = source_addr;
sg.grp = group_addr;
- ch = pim_ifchannel_add(ifp, &sg, 0);
+ ch = pim_ifchannel_add(ifp, &sg, 0, 0);
if (!ch) {
zlog_warn(
"%s: (S,G)=%s failure creating channel on interface %s",
@@ -404,9 +405,9 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp,
}
/* Metric preference */
- pim_write_uint32(pim_msg_curr,
- rpt_bit_flag ? metric_preference | 0x80000000
- : metric_preference);
+ pim_write_uint32(pim_msg_curr, rpt_bit_flag
+ ? metric_preference | 0x80000000
+ : metric_preference);
pim_msg_curr += 4;
/* Route metric */
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index e4c50a18be..1dfb558f46 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -27,6 +27,7 @@
#include "vty.h"
#include "zclient.h"
+#include "pim_instance.h"
#include "pim_cmd.h"
#include "pim_vty.h"
#include "pim_iface.h"
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 1c9fe40c29..d7e94d11dd 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -27,6 +27,7 @@
#include "plist.h"
#include "hash.h"
#include "nexthop.h"
+#include "vrf.h"
#include "pimd.h"
#include "pim_mroute.h"
@@ -70,6 +71,23 @@ static struct cmd_node interface_node = {
static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
+static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
+ const int argc, int *idx)
+{
+ struct vrf *vrf;
+
+ if (argv_find(argv, argc, "NAME", idx))
+ vrf = vrf_lookup_by_name(argv[*idx]->arg);
+ else
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
+
+ if (!vrf)
+ vty_out(vty, "Specified VRF: %s does not exist\n",
+ argv[*idx]->arg);
+
+ return vrf;
+}
+
static void pim_if_membership_clear(struct interface *ifp)
{
struct pim_interface *pim_ifp;
@@ -158,12 +176,45 @@ static void pim_if_membership_refresh(struct interface *ifp)
pim_ifchannel_delete_on_noinfo(ifp);
}
-static void pim_show_assert(struct vty *vty)
+static void pim_show_assert_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch,
+ time_t now)
+{
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ char winner_str[INET_ADDRSTRLEN];
+ struct in_addr ifaddr;
+ char uptime[10];
+ char timer[10];
+
+ ifaddr = pim_ifp->primary_address;
+
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+ pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str,
+ sizeof(winner_str));
+
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - ch->ifassert_creation);
+ pim_time_timer_to_mmss(timer, sizeof(timer),
+ ch->t_ifassert_timer);
+
+ vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
+ ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
+ ch_grp_str,
+ pim_ifchannel_ifassert_name(ch->ifassert_state),
+ winner_str, uptime, timer);
+}
+
+static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
{
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
- struct listnode *ch_node;
- struct in_addr ifaddr;
+ struct listnode *if_node;
+ struct interface *ifp;
time_t now;
now = pim_time_monotonic_sec();
@@ -171,46 +222,49 @@ static void pim_show_assert(struct vty *vty)
vty_out(vty,
"Interface Address Source Group State Winner Uptime Timer\n");
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
- char winner_str[INET_ADDRSTRLEN];
- char uptime[10];
- char timer[10];
-
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- ifaddr = pim_ifp->primary_address;
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_assert_helper(vty, pim_ifp, ch, now);
+ } /* scan interface channels */
+ }
+}
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
- pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str,
- sizeof(winner_str));
+static void pim_show_assert_internal_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch)
+{
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ struct in_addr ifaddr;
- pim_time_uptime(uptime, sizeof(uptime),
- now - ch->ifassert_creation);
- pim_time_timer_to_mmss(timer, sizeof(timer),
- ch->t_ifassert_timer);
+ ifaddr = pim_ifp->primary_address;
- vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
- ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
- ch_grp_str,
- pim_ifchannel_ifassert_name(ch->ifassert_state),
- winner_str, uptime, timer);
- } /* scan interface channels */
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+ vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
+ ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
+ ch_grp_str,
+ PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
+ pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
+ PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)
+ ? "yes"
+ : "no",
+ pim_macro_assert_tracking_desired_eval(ch) ? "yes"
+ : "no");
}
-static void pim_show_assert_internal(struct vty *vty)
+static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
{
struct pim_interface *pim_ifp;
- struct listnode *ch_node;
+ struct listnode *if_node;
struct pim_ifchannel *ch;
- struct in_addr ifaddr;
+ struct interface *ifp;
vty_out(vty,
"CA: CouldAssert\n"
@@ -220,126 +274,127 @@ static void pim_show_assert_internal(struct vty *vty)
vty_out(vty,
"Interface Address Source Group CA eCA ATD eATD\n");
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- ifaddr = pim_ifp->primary_address;
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_assert_internal_helper(vty, pim_ifp, ch);
+ } /* scan interface channels */
+ }
+}
+
+static void pim_show_assert_metric_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch)
+{
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ char addr_str[INET_ADDRSTRLEN];
+ struct pim_assert_metric am;
+ struct in_addr ifaddr;
+
+ ifaddr = pim_ifp->primary_address;
+
+ am = pim_macro_spt_assert_metric(&ch->upstream->rpf,
+ pim_ifp->primary_address);
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+ pim_inet4_dump("<addr?>", am.ip_address, addr_str,
+ sizeof(addr_str));
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
- ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
- ch_grp_str,
- PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
- pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
- PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)
- ? "yes"
- : "no",
- pim_macro_assert_tracking_desired_eval(ch) ? "yes"
- : "no");
- } /* scan interface channels */
+ vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
+ ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
+ ch_grp_str, am.rpt_bit_flag ? "yes" : "no",
+ am.metric_preference, am.route_metric, addr_str);
}
-static void pim_show_assert_metric(struct vty *vty)
+static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
{
struct pim_interface *pim_ifp;
- struct listnode *ch_node;
+ struct listnode *if_node;
struct pim_ifchannel *ch;
- struct in_addr ifaddr;
+ struct interface *ifp;
vty_out(vty,
"Interface Address Source Group RPT Pref Metric Address \n");
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- ifaddr = pim_ifp->primary_address;
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_assert_metric_helper(vty, pim_ifp, ch);
+ } /* scan interface channels */
+ }
+}
+
+static void pim_show_assert_winner_metric_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch)
+{
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ char addr_str[INET_ADDRSTRLEN];
+ struct pim_assert_metric *am;
+ struct in_addr ifaddr;
+ char pref_str[5];
+ char metr_str[7];
+
+ ifaddr = pim_ifp->primary_address;
+
+ am = &ch->ifassert_winner_metric;
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
- char addr_str[INET_ADDRSTRLEN];
- struct pim_assert_metric am;
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+ pim_inet4_dump("<addr?>", am->ip_address, addr_str,
+ sizeof(addr_str));
- am = pim_macro_spt_assert_metric(&ch->upstream->rpf,
- pim_ifp->primary_address);
+ if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
+ snprintf(pref_str, sizeof(pref_str), "INFI");
+ else
+ snprintf(pref_str, sizeof(pref_str), "%4u",
+ am->metric_preference);
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
- pim_inet4_dump("<addr?>", am.ip_address, addr_str,
- sizeof(addr_str));
+ if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
+ snprintf(metr_str, sizeof(metr_str), "INFI");
+ else
+ snprintf(metr_str, sizeof(metr_str), "%6u",
+ am->route_metric);
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
- ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
- ch_grp_str, am.rpt_bit_flag ? "yes" : "no",
- am.metric_preference, am.route_metric, addr_str);
- } /* scan interface channels */
+ vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
+ ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
+ ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str,
+ metr_str, addr_str);
}
-static void pim_show_assert_winner_metric(struct vty *vty)
+static void pim_show_assert_winner_metric(struct pim_instance *pim,
+ struct vty *vty)
{
+ struct listnode *if_node;
struct pim_interface *pim_ifp;
- struct listnode *ch_node;
struct pim_ifchannel *ch;
- struct in_addr ifaddr;
+ struct interface *ifp;
vty_out(vty,
"Interface Address Source Group RPT Pref Metric Address \n");
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- ifaddr = pim_ifp->primary_address;
-
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
- char addr_str[INET_ADDRSTRLEN];
- struct pim_assert_metric *am;
- char pref_str[5];
- char metr_str[7];
-
- am = &ch->ifassert_winner_metric;
-
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
- pim_inet4_dump("<addr?>", am->ip_address, addr_str,
- sizeof(addr_str));
-
- if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
- snprintf(pref_str, sizeof(pref_str), "INFI");
- else
- snprintf(pref_str, sizeof(pref_str), "%4u",
- am->metric_preference);
-
- if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
- snprintf(metr_str, sizeof(metr_str), "INFI");
- else
- snprintf(metr_str, sizeof(metr_str), "%6u",
- am->route_metric);
-
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
- ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
- ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str,
- metr_str, addr_str);
- } /* scan interface channels */
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_assert_winner_metric_helper(vty, pim_ifp, ch);
+ } /* scan interface channels */
+ }
}
static void json_object_pim_ifp_add(struct json_object *json,
@@ -373,54 +428,63 @@ static void json_object_pim_ifp_add(struct json_object *json,
json_object_boolean_true_add(json, "lanDelayEnabled");
}
-static void pim_show_membership(struct vty *vty, u_char uj)
+static void pim_show_membership_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch,
+ struct json_object *json)
{
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ json_object *json_iface = NULL;
+ json_object *json_row = NULL;
+
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+
+ json_object_object_get_ex(json, ch->interface->name,
+ &json_iface);
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_pim_ifp_add(json_iface, ch->interface);
+ json_object_object_add(json, ch->interface->name,
+ json_iface);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "source", ch_src_str);
+ json_object_string_add(json_row, "group", ch_grp_str);
+ json_object_string_add(
+ json_row, "localMembership",
+ ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
+ ? "NOINFO"
+ : "INCLUDE");
+ json_object_object_add(json_iface, ch_grp_str, json_row);
+
+}
+static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
+{
+ struct listnode *if_node;
struct pim_interface *pim_ifp;
- struct listnode *ch_node;
struct pim_ifchannel *ch;
+ struct interface *ifp;
enum json_type type;
json_object *json = NULL;
- json_object *json_iface = NULL;
- json_object *json_row = NULL;
json_object *json_tmp = NULL;
json = json_object_new_object();
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
-
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
-
- json_object_object_get_ex(json, ch->interface->name,
- &json_iface);
-
- if (!json_iface) {
- json_iface = json_object_new_object();
- json_object_pim_ifp_add(json_iface, ch->interface);
- json_object_object_add(json, ch->interface->name,
- json_iface);
- }
-
- json_row = json_object_new_object();
- json_object_string_add(json_row, "source", ch_src_str);
- json_object_string_add(json_row, "group", ch_grp_str);
- json_object_string_add(
- json_row, "localMembership",
- ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
- ? "NOINFO"
- : "INCLUDE");
- json_object_object_add(json_iface, ch_grp_str, json_row);
- } /* scan interface channels */
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_membership_helper(vty, pim_ifp, ch, json);
+ } /* scan interface channels */
+ }
if (uj) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
@@ -517,7 +581,8 @@ static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp,
vty_out(vty, "\n");
}
-static void igmp_show_interfaces(struct vty *vty, u_char uj)
+static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *node;
struct interface *ifp;
@@ -533,7 +598,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj)
vty_out(vty,
"Interface State Address V Querier Query Timer Uptime\n");
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
struct pim_interface *pim_ifp;
struct listnode *sock_node;
struct igmp_sock *igmp;
@@ -594,7 +659,8 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj)
}
}
-static void igmp_show_interfaces_single(struct vty *vty, const char *ifname,
+static void igmp_show_interfaces_single(struct pim_instance *pim,
+ struct vty *vty, const char *ifname,
u_char uj)
{
struct igmp_sock *igmp;
@@ -607,7 +673,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname,
char other_hhmmss[10];
int found_ifname = 0;
int sqi;
- int mloop;
+ int mloop = 0;
long gmi_msec; /* Group Membership Interval */
long lmqt_msec;
long ohpi_msec;
@@ -623,7 +689,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname,
now = pim_time_monotonic_sec();
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -670,7 +736,11 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname,
qri_msec = pim_ifp->igmp_query_max_response_time_dsec
* 100;
- mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
+ if (pim_ifp->pim_sock_fd >= 0)
+ mloop = pim_socket_mcastloop_get(
+ pim_ifp->pim_sock_fd);
+ else
+ mloop = 0;
if (uj) {
json_row = json_object_new_object();
@@ -793,7 +863,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname,
}
}
-static void igmp_show_interface_join(struct vty *vty)
+static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
{
struct listnode *node;
struct interface *ifp;
@@ -804,7 +874,7 @@ static void igmp_show_interface_join(struct vty *vty)
vty_out(vty,
"Interface Address Source Group Socket Uptime \n");
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
struct pim_interface *pim_ifp;
struct listnode *join_node;
struct igmp_join *ij;
@@ -844,7 +914,8 @@ static void igmp_show_interface_join(struct vty *vty)
} /* for (iflist) */
}
-static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
+static void pim_show_interfaces_single(struct pim_instance *pim,
+ struct vty *vty, const char *ifname,
u_char uj)
{
struct in_addr ifaddr;
@@ -866,7 +937,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
char src_str[INET_ADDRSTRLEN];
char stat_uptime[10];
char uptime[10];
- int mloop;
+ int mloop = 0;
int found_ifname = 0;
int print_header;
json_object *json = NULL;
@@ -884,15 +955,12 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
if (uj)
json = json_object_new_object();
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- if (pim_ifp->pim_sock_fd < 0)
- continue;
-
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
continue;
@@ -908,7 +976,10 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
pim_ifp->pim_hello_period);
pim_time_uptime(stat_uptime, sizeof(stat_uptime),
now - pim_ifp->pim_ifstat_start);
- mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
+ if (pim_ifp->pim_sock_fd >= 0)
+ mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
+ else
+ mloop = 0;
if (uj) {
char pbuf[PREFIX2STR_BUFFER];
@@ -989,7 +1060,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
pim_ifp->pim_dr_election_changes);
// FHR
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode,
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
up)) {
if (ifp == up->rpf.source_nexthop.interface) {
if (up->flags
@@ -1163,11 +1234,10 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
// FHR
print_header = 1;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode,
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
up)) {
- if (strcmp(ifp->name,
- up->rpf.source_nexthop
- .interface->name)
+ if (strcmp(ifp->name, up->rpf.source_nexthop
+ .interface->name)
== 0) {
if (up->flags
& PIM_UPSTREAM_FLAG_MASK_FHR) {
@@ -1263,7 +1333,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname,
}
}
-static void pim_show_interfaces(struct vty *vty, u_char uj)
+static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct interface *ifp;
struct listnode *node;
@@ -1279,20 +1350,17 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
json = json_object_new_object();
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- if (pim_ifp->pim_sock_fd < 0)
- continue;
-
pim_nbrs = pim_ifp->pim_neighbor_list->count;
- pim_ifchannels = pim_ifp->pim_ifchannel_list->count;
+ pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
fhr = 0;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up))
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up))
if (ifp == up->rpf.source_nexthop.interface)
if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
fhr++;
@@ -1359,7 +1427,8 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
json_object_free(json);
}
-static void pim_show_interface_traffic(struct vty *vty, u_char uj)
+static void pim_show_interface_traffic(struct pim_instance *pim,
+ struct vty *vty, u_char uj)
{
struct interface *ifp = NULL;
struct pim_interface *pim_ifp = NULL;
@@ -1381,7 +1450,7 @@ static void pim_show_interface_traffic(struct vty *vty, u_char uj)
"---------------------------------------------------------------------------------------------------------------\n");
}
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -1438,7 +1507,8 @@ static void pim_show_interface_traffic(struct vty *vty, u_char uj)
}
}
-static void pim_show_interface_traffic_single(struct vty *vty,
+static void pim_show_interface_traffic_single(struct pim_instance *pim,
+ struct vty *vty,
const char *ifname, u_char uj)
{
struct interface *ifp = NULL;
@@ -1462,7 +1532,7 @@ static void pim_show_interface_traffic_single(struct vty *vty,
"---------------------------------------------------------------------------------------------------------------\n");
}
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
if (strcmp(ifname, ifp->name))
continue;
@@ -1527,17 +1597,92 @@ static void pim_show_interface_traffic_single(struct vty *vty,
}
}
-static void pim_show_join(struct vty *vty, u_char uj)
+static void pim_show_join_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch,
+ json_object *json,
+ time_t now,
+ u_char uj)
{
- struct pim_interface *pim_ifp;
+ char ch_src_str[INET_ADDRSTRLEN];
+ char ch_grp_str[INET_ADDRSTRLEN];
+ json_object *json_iface = NULL;
+ json_object *json_row = NULL;
+ json_object *json_grp = NULL;
struct in_addr ifaddr;
- struct listnode *ch_node;
+ char uptime[10];
+ char expire[10];
+ char prune[10];
+
+ ifaddr = pim_ifp->primary_address;
+
+ pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
+ sizeof(ch_src_str));
+ pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
+ sizeof(ch_grp_str));
+
+ pim_time_uptime_begin(uptime, sizeof(uptime), now,
+ ch->ifjoin_creation);
+ pim_time_timer_to_mmss(expire, sizeof(expire),
+ ch->t_ifjoin_expiry_timer);
+ pim_time_timer_to_mmss(prune, sizeof(prune),
+ ch->t_ifjoin_prune_pending_timer);
+
+ if (uj) {
+ json_object_object_get_ex(json, ch->interface->name,
+ &json_iface);
+
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_pim_ifp_add(json_iface,
+ ch->interface);
+ json_object_object_add(
+ json, ch->interface->name, json_iface);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "source", ch_src_str);
+ json_object_string_add(json_row, "group", ch_grp_str);
+ json_object_string_add(json_row, "upTime", uptime);
+ json_object_string_add(json_row, "expire", expire);
+ json_object_string_add(json_row, "prune", prune);
+ json_object_string_add(
+ json_row, "channelJoinName",
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state,
+ ch->flags));
+ if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
+ json_object_int_add(json_row, "SGRpt", 1);
+
+ json_object_object_get_ex(json_iface, ch_grp_str,
+ &json_grp);
+ if (!json_grp) {
+ json_grp = json_object_new_object();
+ json_object_object_add(json_grp, ch_src_str,
+ json_row);
+ json_object_object_add(json_iface, ch_grp_str,
+ json_grp);
+ } else
+ json_object_object_add(json_grp, ch_src_str,
+ json_row);
+ } else {
+ vty_out(vty,
+ "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n",
+ ch->interface->name, inet_ntoa(ifaddr),
+ ch_src_str, ch_grp_str,
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state,
+ ch->flags),
+ uptime, expire, prune);
+ }
+}
+
+static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
+{
+ struct listnode *if_node;
+ struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
+ struct interface *ifp;
time_t now;
json_object *json = NULL;
- json_object *json_iface = NULL;
- json_object *json_row = NULL;
- json_object *json_grp = NULL;
now = pim_time_monotonic_sec();
@@ -1547,89 +1692,26 @@ static void pim_show_join(struct vty *vty, u_char uj)
vty_out(vty,
"Interface Address Source Group State Uptime Expire Prune\n");
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) {
-
- pim_ifp = ch->interface->info;
-
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
if (!pim_ifp)
continue;
- ifaddr = pim_ifp->primary_address;
-
- char ch_src_str[INET_ADDRSTRLEN];
- char ch_grp_str[INET_ADDRSTRLEN];
- char uptime[10];
- char expire[10];
- char prune[10];
-
- pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
- sizeof(ch_src_str));
- pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
- sizeof(ch_grp_str));
-
- pim_time_uptime_begin(uptime, sizeof(uptime), now,
- ch->ifjoin_creation);
- pim_time_timer_to_mmss(expire, sizeof(expire),
- ch->t_ifjoin_expiry_timer);
- pim_time_timer_to_mmss(prune, sizeof(prune),
- ch->t_ifjoin_prune_pending_timer);
-
- if (uj) {
- json_object_object_get_ex(json, ch->interface->name,
- &json_iface);
-
- if (!json_iface) {
- json_iface = json_object_new_object();
- json_object_pim_ifp_add(json_iface,
- ch->interface);
- json_object_object_add(
- json, ch->interface->name, json_iface);
- }
-
- json_row = json_object_new_object();
- json_object_string_add(json_row, "source", ch_src_str);
- json_object_string_add(json_row, "group", ch_grp_str);
- json_object_string_add(json_row, "upTime", uptime);
- json_object_string_add(json_row, "expire", expire);
- json_object_string_add(json_row, "prune", prune);
- json_object_string_add(
- json_row, "channelJoinName",
- pim_ifchannel_ifjoin_name(ch->ifjoin_state,
- ch->flags));
- if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
- json_object_int_add(json_row, "SGRpt", 1);
-
- json_object_object_get_ex(json_iface, ch_grp_str,
- &json_grp);
- if (!json_grp) {
- json_grp = json_object_new_object();
- json_object_object_add(json_grp, ch_src_str,
- json_row);
- json_object_object_add(json_iface, ch_grp_str,
- json_grp);
- } else
- json_object_object_add(json_grp, ch_src_str,
- json_row);
- } else {
- vty_out(vty,
- "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n",
- ch->interface->name, inet_ntoa(ifaddr),
- ch_src_str, ch_grp_str,
- pim_ifchannel_ifjoin_name(ch->ifjoin_state,
- ch->flags),
- uptime, expire, prune);
- }
- } /* scan interface channels */
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_join_helper(vty, pim_ifp,
+ ch, json, now, uj);
+ } /* scan interface channels */
+ }
if (uj) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
+ json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
}
-static void pim_show_neighbors_single(struct vty *vty, const char *neighbor,
- u_char uj)
+static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
+ const char *neighbor, u_char uj)
{
struct listnode *node;
struct listnode *neighnode;
@@ -1657,7 +1739,7 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor,
if (uj)
json = json_object_new_object();
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -1838,8 +1920,9 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor,
}
}
-static void pim_show_state(struct vty *vty, const char *src_or_group,
- const char *group, u_char uj)
+static void pim_show_state(struct pim_instance *pim, struct vty *vty,
+ const char *src_or_group, const char *group,
+ u_char uj)
{
struct channel_oil *c_oil;
struct listnode *node;
@@ -1861,7 +1944,7 @@ static void pim_show_state(struct vty *vty, const char *src_or_group,
"\nInstalled Source Group IIF OIL\n");
}
- for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
char grp_str[INET_ADDRSTRLEN];
char src_str[INET_ADDRSTRLEN];
char in_ifname[INTERFACE_NAMSIZ + 1];
@@ -1874,7 +1957,7 @@ static void pim_show_state(struct vty *vty, const char *src_or_group,
sizeof(grp_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
sizeof(src_str));
- ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
+ ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
if (ifp_in)
strcpy(in_ifname, ifp_in->name);
@@ -1956,7 +2039,7 @@ static void pim_show_state(struct vty *vty, const char *src_or_group,
if (ttl < 1)
continue;
- ifp_out = pim_if_find_by_vif_index(oif_vif_index);
+ ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
pim_time_uptime(
oif_uptime, sizeof(oif_uptime),
now - c_oil->oif_creation[oif_vif_index]);
@@ -2039,7 +2122,8 @@ static void pim_show_state(struct vty *vty, const char *src_or_group,
}
}
-static void pim_show_neighbors(struct vty *vty, u_char uj)
+static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *node;
struct listnode *neighnode;
@@ -2063,7 +2147,7 @@ static void pim_show_neighbors(struct vty *vty, u_char uj)
"Interface Neighbor Uptime Holdtime DR Pri\n");
}
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -2121,7 +2205,8 @@ static void pim_show_neighbors(struct vty *vty, u_char uj)
}
}
-static void pim_show_neighbors_secondary(struct vty *vty)
+static void pim_show_neighbors_secondary(struct pim_instance *pim,
+ struct vty *vty)
{
struct listnode *node;
struct interface *ifp;
@@ -2129,7 +2214,7 @@ static void pim_show_neighbors_secondary(struct vty *vty)
vty_out(vty,
"Interface Address Neighbor Secondary \n");
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
struct pim_interface *pim_ifp;
struct in_addr ifaddr;
struct listnode *neighnode;
@@ -2235,7 +2320,8 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
return state_str;
}
-static void pim_show_upstream(struct vty *vty, u_char uj)
+static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *upnode;
struct pim_upstream *up;
@@ -2252,7 +2338,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj)
vty_out(vty,
"Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
char uptime[10];
@@ -2352,81 +2438,100 @@ static void pim_show_upstream(struct vty *vty, u_char uj)
}
}
-static void pim_show_join_desired(struct vty *vty, u_char uj)
+static void pim_show_join_desired_helper(struct pim_instance *pim,
+ struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch,
+ json_object *json,
+ u_char uj)
{
- struct listnode *chnode;
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
+ struct pim_upstream *up = ch->upstream;
+ json_object *json_group = NULL;
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
- json_object *json = NULL;
- json_object *json_group = NULL;
json_object *json_row = NULL;
- if (uj)
- json = json_object_new_object();
- else
- vty_out(vty,
- "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+ pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+ pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
- /* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) {
- /* scan all interfaces */
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
+ if (uj) {
+ json_object_object_get_ex(json, grp_str, &json_group);
- struct pim_upstream *up = ch->upstream;
+ if (!json_group) {
+ json_group = json_object_new_object();
+ json_object_object_add(json, grp_str,
+ json_group);
+ }
- pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
- pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+ json_row = json_object_new_object();
+ json_object_pim_upstream_add(json_row, up);
+ json_object_string_add(json_row, "interface",
+ ch->interface->name);
+ json_object_string_add(json_row, "source", src_str);
+ json_object_string_add(json_row, "group", grp_str);
- if (uj) {
- json_object_object_get_ex(json, grp_str, &json_group);
+ if (pim_macro_ch_lost_assert(ch))
+ json_object_boolean_true_add(json_row,
+ "lostAssert");
- if (!json_group) {
- json_group = json_object_new_object();
- json_object_object_add(json, grp_str,
- json_group);
- }
+ if (pim_macro_chisin_joins(ch))
+ json_object_boolean_true_add(json_row, "joins");
- json_row = json_object_new_object();
- json_object_pim_upstream_add(json_row, up);
- json_object_string_add(json_row, "interface",
- ch->interface->name);
- json_object_string_add(json_row, "source", src_str);
- json_object_string_add(json_row, "group", grp_str);
+ if (pim_macro_chisin_pim_include(ch))
+ json_object_boolean_true_add(json_row,
+ "pimInclude");
- if (pim_macro_ch_lost_assert(ch))
- json_object_boolean_true_add(json_row,
- "lostAssert");
+ if (pim_upstream_evaluate_join_desired(pim, up))
+ json_object_boolean_true_add(
+ json_row, "evaluateJoinDesired");
- if (pim_macro_chisin_joins(ch))
- json_object_boolean_true_add(json_row, "joins");
+ json_object_object_add(json_group, src_str, json_row);
- if (pim_macro_chisin_pim_include(ch))
- json_object_boolean_true_add(json_row,
- "pimInclude");
+ } else {
+ vty_out(vty,
+ "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+ ch->interface->name, src_str, grp_str,
+ pim_macro_ch_lost_assert(ch) ? "yes" : "no",
+ pim_macro_chisin_joins(ch) ? "yes" : "no",
+ pim_macro_chisin_pim_include(ch) ? "yes" : "no",
+ PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(
+ up->flags)
+ ? "yes"
+ : "no",
+ pim_upstream_evaluate_join_desired(pim, up)
+ ? "yes"
+ : "no");
+ }
+}
- if (pim_upstream_evaluate_join_desired(up))
- json_object_boolean_true_add(
- json_row, "evaluateJoinDesired");
+static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
+{
+ struct listnode *if_node;
+ struct pim_interface *pim_ifp;
+ struct pim_ifchannel *ch;
+ struct interface *ifp;
- json_object_object_add(json_group, src_str, json_row);
+ json_object *json = NULL;
- } else {
- vty_out(vty,
- "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
- ch->interface->name, src_str, grp_str,
- pim_macro_ch_lost_assert(ch) ? "yes" : "no",
- pim_macro_chisin_joins(ch) ? "yes" : "no",
- pim_macro_chisin_pim_include(ch) ? "yes" : "no",
- PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(
- up->flags)
- ? "yes"
- : "no",
- pim_upstream_evaluate_join_desired(up) ? "yes"
- : "no");
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+
+ /* scan per-interface (S,G) state */
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
+ continue;
+
+
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ /* scan all interfaces */
+ pim_show_join_desired_helper(pim, vty,
+ pim_ifp, ch,
+ json, uj);
}
}
@@ -2437,7 +2542,8 @@ static void pim_show_join_desired(struct vty *vty, u_char uj)
}
}
-static void pim_show_upstream_rpf(struct vty *vty, u_char uj)
+static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *upnode;
struct pim_upstream *up;
@@ -2451,7 +2557,7 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj)
vty_out(vty,
"Source Group RpfIface RibNextHop RpfAddress \n");
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
char rpf_nexthop_str[PREFIX_STRLEN];
@@ -2547,7 +2653,8 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,
}
}
-static void show_scan_oil_stats(struct vty *vty, time_t now)
+static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
+ time_t now)
{
char uptime_scan_oil[10];
char uptime_mroute_add[10];
@@ -2556,20 +2663,20 @@ static void show_scan_oil_stats(struct vty *vty, time_t now)
pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
qpim_scan_oil_last);
pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
- qpim_mroute_add_last);
+ pim->mroute_add_last);
pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
- qpim_mroute_del_last);
+ pim->mroute_del_last);
vty_out(vty,
"Scan OIL - Last: %s Events: %lld\n"
"MFC Add - Last: %s Events: %lld\n"
"MFC Del - Last: %s Events: %lld\n",
uptime_scan_oil, (long long)qpim_scan_oil_events,
- uptime_mroute_add, (long long)qpim_mroute_add_events,
- uptime_mroute_del, (long long)qpim_mroute_del_events);
+ uptime_mroute_add, (long long)pim->mroute_add_events,
+ uptime_mroute_del, (long long)pim->mroute_del_events);
}
-static void pim_show_rpf(struct vty *vty, u_char uj)
+static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, u_char uj)
{
struct listnode *up_node;
struct pim_upstream *up;
@@ -2588,7 +2695,7 @@ static void pim_show_rpf(struct vty *vty, u_char uj)
"Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
}
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
char rpf_addr_str[PREFIX_STRLEN];
@@ -2648,10 +2755,17 @@ static void pim_show_rpf(struct vty *vty, u_char uj)
}
}
+struct pnc_cache_walk_data {
+ struct vty *vty;
+ struct pim_instance *pim;
+};
+
static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg)
{
struct pim_nexthop_cache *pnc = backet->data;
- struct vty *vty = arg;
+ struct pnc_cache_walk_data *cwd = arg;
+ struct vty *vty = cwd->vty;
+ struct pim_instance *pim = cwd->pim;
struct nexthop *nh_node = NULL;
ifindex_t first_ifindex;
struct interface *ifp = NULL;
@@ -2661,7 +2775,7 @@ static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg)
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
first_ifindex = nh_node->ifindex;
- ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4));
vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL");
@@ -2671,23 +2785,22 @@ static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg)
return CMD_SUCCESS;
}
-static void pim_show_nexthop(struct vty *vty)
+static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
{
+ struct pnc_cache_walk_data cwd;
- if (pimg && !pimg->rpf_hash) {
- vty_out(vty, "no nexthop cache \n");
- return;
- }
-
- vty_out(vty, "Number of registered addresses: %lu \n",
- pimg->rpf_hash->count);
+ cwd.vty = vty;
+ cwd.pim = pim;
+ vty_out(vty, "Number of registered addresses: %lu\n",
+ pim->rpf_hash->count);
vty_out(vty, "Address Interface Nexthop\n");
vty_out(vty, "-------------------------------------------\n");
- hash_walk(pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty);
+ hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
}
-static void igmp_show_groups(struct vty *vty, u_char uj)
+static void igmp_show_groups(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *ifnode;
struct interface *ifp;
@@ -2705,7 +2818,7 @@ static void igmp_show_groups(struct vty *vty, u_char uj)
"Interface Address Group Mode Timer Srcs V Uptime \n");
/* scan interfaces */
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *pim_ifp = ifp->info;
struct listnode *sock_node;
struct igmp_sock *igmp;
@@ -2808,7 +2921,8 @@ static void igmp_show_groups(struct vty *vty, u_char uj)
}
}
-static void igmp_show_group_retransmission(struct vty *vty)
+static void igmp_show_group_retransmission(struct pim_instance *pim,
+ struct vty *vty)
{
struct listnode *ifnode;
struct interface *ifp;
@@ -2817,7 +2931,7 @@ static void igmp_show_group_retransmission(struct vty *vty)
"Interface Address Group RetTimer Counter RetSrcs\n");
/* scan interfaces */
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *pim_ifp = ifp->info;
struct listnode *sock_node;
struct igmp_sock *igmp;
@@ -2873,7 +2987,7 @@ static void igmp_show_group_retransmission(struct vty *vty)
} /* scan interfaces */
}
-static void igmp_show_sources(struct vty *vty)
+static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
{
struct listnode *ifnode;
struct interface *ifp;
@@ -2885,7 +2999,7 @@ static void igmp_show_sources(struct vty *vty)
"Interface Address Group Source Timer Fwd Uptime \n");
/* scan interfaces */
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *pim_ifp = ifp->info;
struct listnode *sock_node;
struct igmp_sock *igmp;
@@ -2949,7 +3063,8 @@ static void igmp_show_sources(struct vty *vty)
} /* scan interfaces */
}
-static void igmp_show_source_retransmission(struct vty *vty)
+static void igmp_show_source_retransmission(struct pim_instance *pim,
+ struct vty *vty)
{
struct listnode *ifnode;
struct interface *ifp;
@@ -2958,7 +3073,7 @@ static void igmp_show_source_retransmission(struct vty *vty)
"Interface Address Group Source Counter\n");
/* scan interfaces */
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *pim_ifp = ifp->info;
struct listnode *sock_node;
struct igmp_sock *igmp;
@@ -3008,30 +3123,30 @@ static void igmp_show_source_retransmission(struct vty *vty)
} /* scan interfaces */
}
-static void clear_igmp_interfaces()
+static void clear_igmp_interfaces(struct pim_instance *pim)
{
struct listnode *ifnode;
struct listnode *ifnextnode;
struct interface *ifp;
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
+ for (ALL_LIST_ELEMENTS(vrf_iflist(pim->vrf_id), ifnode, ifnextnode,
ifp)) {
pim_if_addr_del_all_igmp(ifp);
}
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
+ for (ALL_LIST_ELEMENTS(vrf_iflist(pim->vrf_id), ifnode, ifnextnode,
ifp)) {
pim_if_addr_add_all(ifp);
}
}
-static void clear_pim_interfaces()
+static void clear_pim_interfaces(struct pim_instance *pim)
{
struct listnode *ifnode;
struct listnode *ifnextnode;
struct interface *ifp;
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
+ for (ALL_LIST_ELEMENTS(vrf_iflist(pim->vrf_id), ifnode, ifnextnode,
ifp)) {
if (ifp->info) {
pim_neighbor_delete_all(ifp, "interface cleared");
@@ -3039,43 +3154,57 @@ static void clear_pim_interfaces()
}
}
-static void clear_interfaces()
+static void clear_interfaces(struct pim_instance *pim)
{
- clear_igmp_interfaces();
- clear_pim_interfaces();
+ clear_igmp_interfaces(pim);
+ clear_pim_interfaces(pim);
}
DEFUN (clear_ip_interfaces,
clear_ip_interfaces_cmd,
- "clear ip interfaces",
+ "clear ip interfaces [vrf NAME]",
CLEAR_STR
IP_STR
- "Reset interfaces\n")
+ "Reset interfaces\n"
+ VRF_CMD_HELP_STR)
{
- clear_interfaces();
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ clear_interfaces(vrf->info);
return CMD_SUCCESS;
}
DEFUN (clear_ip_igmp_interfaces,
clear_ip_igmp_interfaces_cmd,
- "clear ip igmp interfaces",
+ "clear ip igmp [vrf NAME] interfaces",
CLEAR_STR
IP_STR
CLEAR_IP_IGMP_STR
+ VRF_CMD_HELP_STR
"Reset IGMP interfaces\n")
{
- clear_igmp_interfaces();
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ clear_igmp_interfaces(vrf->info);
return CMD_SUCCESS;
}
-static void mroute_add_all()
+static void mroute_add_all(struct pim_instance *pim)
{
struct listnode *node;
struct channel_oil *c_oil;
- for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
/* just log warning */
char source_str[INET_ADDRSTRLEN];
@@ -3091,12 +3220,12 @@ static void mroute_add_all()
}
}
-static void mroute_del_all()
+static void mroute_del_all(struct pim_instance *pim)
{
struct listnode *node;
struct channel_oil *c_oil;
- for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) {
/* just log warning */
char source_str[INET_ADDRSTRLEN];
@@ -3114,45 +3243,65 @@ static void mroute_del_all()
DEFUN (clear_ip_mroute,
clear_ip_mroute_cmd,
- "clear ip mroute",
+ "clear ip mroute [vrf NAME]",
CLEAR_STR
IP_STR
- "Reset multicast routes\n")
+ "Reset multicast routes\n"
+ VRF_CMD_HELP_STR)
{
- mroute_del_all();
- mroute_add_all();
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ mroute_del_all(vrf->info);
+ mroute_add_all(vrf->info);
return CMD_SUCCESS;
}
DEFUN (clear_ip_pim_interfaces,
clear_ip_pim_interfaces_cmd,
- "clear ip pim interfaces",
+ "clear ip pim [vrf NAME] interfaces",
CLEAR_STR
IP_STR
CLEAR_IP_PIM_STR
+ VRF_CMD_HELP_STR
"Reset PIM interfaces\n")
{
- clear_pim_interfaces();
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ clear_pim_interfaces(vrf->info);
return CMD_SUCCESS;
}
DEFUN (clear_ip_pim_interface_traffic,
clear_ip_pim_interface_traffic_cmd,
- "clear ip pim interface traffic",
+ "clear ip pim [vrf NAME] interface traffic",
"Reset functions\n"
"IP information\n"
"PIM clear commands\n"
+ VRF_CMD_HELP_STR
"Reset PIM interfaces\n"
"Reset Protocol Packet counters\n")
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
struct listnode *ifnode = NULL;
struct listnode *ifnextnode = NULL;
struct interface *ifp = NULL;
struct pim_interface *pim_ifp = NULL;
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
+ if (!vrf)
+ return CMD_WARNING;
+
+ for (ALL_LIST_ELEMENTS(vrf_iflist(vrf->vrf_id), ifnode, ifnextnode,
ifp)) {
pim_ifp = ifp->info;
@@ -3178,373 +3327,893 @@ DEFUN (clear_ip_pim_interface_traffic,
DEFUN (clear_ip_pim_oil,
clear_ip_pim_oil_cmd,
- "clear ip pim oil",
+ "clear ip pim [vrf NAME] oil",
CLEAR_STR
IP_STR
CLEAR_IP_PIM_STR
+ VRF_CMD_HELP_STR
"Rescan PIM OIL (output interface list)\n")
{
- pim_scan_oil();
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_scan_oil(vrf->info);
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_interface,
show_ip_igmp_interface_cmd,
- "show ip igmp interface [detail|WORD] [json]",
+ "show ip igmp [vrf NAME] interface [detail|WORD] [json]",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
"IGMP interface information\n"
"Detailed output\n"
"interface name\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- int idx = 0;
+
+ if (!vrf)
+ return CMD_WARNING;
if (argv_find(argv, argc, "detail", &idx)
|| argv_find(argv, argc, "WORD", &idx))
- igmp_show_interfaces_single(vty, argv[idx]->arg, uj);
+ igmp_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
else
- igmp_show_interfaces(vty, uj);
+ igmp_show_interfaces(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_igmp_interface_vrf_all,
+ show_ip_igmp_interface_vrf_all_cmd,
+ "show ip igmp vrf all interface [detail|WORD] [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "IGMP interface information\n"
+ "Detailed output\n"
+ "interface name\n"
+ JSON_STR)
+{
+ int idx = 2;
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ if (argv_find(argv, argc, "detail", &idx)
+ || argv_find(argv, argc, "WORD", &idx))
+ igmp_show_interfaces_single(vrf->info, vty,
+ argv[idx]->arg, uj);
+ else
+ igmp_show_interfaces(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_join,
show_ip_igmp_join_cmd,
- "show ip igmp join",
+ "show ip igmp [vrf NAME] join",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
"IGMP static join information\n")
{
- igmp_show_interface_join(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_interface_join(vrf->info, vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_igmp_join_vrf_all,
+ show_ip_igmp_join_vrf_all_cmd,
+ "show ip igmp vrf all join",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "IGMP static join information\n")
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ igmp_show_interface_join(vrf->info, vty);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_groups,
show_ip_igmp_groups_cmd,
- "show ip igmp groups [json]",
+ "show ip igmp [vrf NAME] groups [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ IGMP_GROUP_STR
+ JSON_STR)
+{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+ u_char uj = use_json(argc, argv);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_groups(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_igmp_groups_vrf_all,
+ show_ip_igmp_groups_vrf_all_cmd,
+ "show ip igmp vrf all groups [json]",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
IGMP_GROUP_STR
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- igmp_show_groups(vty, uj);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ igmp_show_groups(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_groups_retransmissions,
show_ip_igmp_groups_retransmissions_cmd,
- "show ip igmp groups retransmissions",
+ "show ip igmp [vrf NAME] groups retransmissions",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
IGMP_GROUP_STR
"IGMP group retransmissions\n")
{
- igmp_show_group_retransmission(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_group_retransmission(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_sources,
show_ip_igmp_sources_cmd,
- "show ip igmp sources",
+ "show ip igmp [vrf NAME] sources",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
IGMP_SOURCE_STR)
{
- igmp_show_sources(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_sources(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_igmp_sources_retransmissions,
show_ip_igmp_sources_retransmissions_cmd,
- "show ip igmp sources retransmissions",
+ "show ip igmp [vrf NAME] sources retransmissions",
SHOW_STR
IP_STR
IGMP_STR
+ VRF_CMD_HELP_STR
IGMP_SOURCE_STR
"IGMP source retransmissions\n")
{
- igmp_show_source_retransmission(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_source_retransmission(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_assert,
show_ip_pim_assert_cmd,
- "show ip pim assert",
+ "show ip pim [vrf NAME] assert",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface assert\n")
{
- pim_show_assert(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_assert(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_assert_internal,
show_ip_pim_assert_internal_cmd,
- "show ip pim assert-internal",
+ "show ip pim [vrf NAME] assert-internal",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface internal assert state\n")
{
- pim_show_assert_internal(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_assert_internal(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_assert_metric,
show_ip_pim_assert_metric_cmd,
- "show ip pim assert-metric",
+ "show ip pim [vrf NAME] assert-metric",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface assert metric\n")
{
- pim_show_assert_metric(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_assert_metric(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_assert_winner_metric,
show_ip_pim_assert_winner_metric_cmd,
- "show ip pim assert-winner-metric",
+ "show ip pim [vrf NAME] assert-winner-metric",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface assert winner metric\n")
{
- pim_show_assert_winner_metric(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_assert_winner_metric(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_interface,
show_ip_pim_interface_cmd,
- "show ip pim interface [detail|WORD] [json]",
+ "show ip pim [vrf NAME] interface [detail|WORD] [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface information\n"
"Detailed output\n"
"interface name\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- int idx = 0;
+
+ if (!vrf)
+ return CMD_WARNING;
if (argv_find(argv, argc, "WORD", &idx)
|| argv_find(argv, argc, "detail", &idx))
- pim_show_interfaces_single(vty, argv[idx]->arg, uj);
-
+ pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
else
- pim_show_interfaces(vty, uj);
+ pim_show_interfaces(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_interface_vrf_all,
+ show_ip_pim_interface_vrf_all_cmd,
+ "show ip pim vrf all interface [detail|WORD] [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM interface information\n"
+ "Detailed output\n"
+ "interface name\n"
+ JSON_STR)
+{
+ int idx = 6;
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ if (argv_find(argv, argc, "WORD", &idx)
+ || argv_find(argv, argc, "detail", &idx))
+ pim_show_interfaces_single(vrf->info, vty,
+ argv[idx]->arg, uj);
+ else
+ pim_show_interfaces(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_join,
show_ip_pim_join_cmd,
- "show ip pim join [json]",
+ "show ip pim [vrf NAME] join [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface join information\n"
JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- pim_show_join(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_join(vrf->info, vty, uj);
return CMD_SUCCESS;
}
+DEFUN (show_ip_pim_join_vrf_all,
+ show_ip_pim_join_vrf_all_cmd,
+ "show ip pim vrf all join [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM interface join information\n"
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_show_join(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_WARNING;
+}
+
DEFUN (show_ip_pim_local_membership,
show_ip_pim_local_membership_cmd,
- "show ip pim local-membership [json]",
+ "show ip pim [vrf NAME] local-membership [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface local-membership\n"
JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- pim_show_membership(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_membership(vrf->info, vty, uj);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_neighbor,
show_ip_pim_neighbor_cmd,
- "show ip pim neighbor [detail|WORD] [json]",
+ "show ip pim [vrf NAME] neighbor [detail|WORD] [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM neighbor information\n"
"Detailed output\n"
"Name of interface or neighbor\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- int idx = 0;
+
+ if (!vrf)
+ return CMD_WARNING;
if (argv_find(argv, argc, "detail", &idx)
|| argv_find(argv, argc, "WORD", &idx))
- pim_show_neighbors_single(vty, argv[idx]->arg, uj);
+ pim_show_neighbors_single(vrf->info, vty, argv[idx]->arg, uj);
else
- pim_show_neighbors(vty, uj);
+ pim_show_neighbors(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_neighbor_vrf_all,
+ show_ip_pim_neighbor_vrf_all_cmd,
+ "show ip pim vrf all neighbor [detail|WORD] [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM neighbor information\n"
+ "Detailed output\n"
+ "Name of interface or neighbor\n"
+ JSON_STR)
+{
+ int idx = 2;
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ if (argv_find(argv, argc, "detail", &idx)
+ || argv_find(argv, argc, "WORD", &idx))
+ pim_show_neighbors_single(vrf->info, vty,
+ argv[idx]->arg, uj);
+ else
+ pim_show_neighbors(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_secondary,
show_ip_pim_secondary_cmd,
- "show ip pim secondary",
+ "show ip pim [vrf NAME] secondary",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM neighbor addresses\n")
{
- pim_show_neighbors_secondary(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_neighbors_secondary(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_state,
show_ip_pim_state_cmd,
- "show ip pim state [A.B.C.D [A.B.C.D]] [json]",
+ "show ip pim [vrf NAME] state [A.B.C.D [A.B.C.D]] [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM state information\n"
"Unicast or Multicast address\n"
"Multicast address\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
const char *src_or_group = NULL;
const char *group = NULL;
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
+
+ if (!vrf)
+ return CMD_WARNING;
+
if (uj)
argc--;
- if (argc == 6) {
- src_or_group = argv[4]->arg;
- group = argv[5]->arg;
- } else if (argc == 5)
- src_or_group = argv[4]->arg;
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ src_or_group = argv[idx]->arg;
+ if (idx + 1 < argc)
+ group = argv[idx + 1]->arg;
+ }
- pim_show_state(vty, src_or_group, group, uj);
+ pim_show_state(vrf->info, vty, src_or_group, group, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_state_vrf_all,
+ show_ip_pim_state_vrf_all_cmd,
+ "show ip pim vrf all state [A.B.C.D [A.B.C.D]] [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM state information\n"
+ "Unicast or Multicast address\n"
+ "Multicast address\n"
+ JSON_STR)
+{
+ const char *src_or_group = NULL;
+ const char *group = NULL;
+ int idx = 2;
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj) {
+ vty_out(vty, "{ ");
+ argc--;
+ }
+
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ src_or_group = argv[idx]->arg;
+ if (idx + 1 < argc)
+ group = argv[idx + 1]->arg;
+ }
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_show_state(vrf->info, vty, src_or_group, group, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_upstream,
show_ip_pim_upstream_cmd,
- "show ip pim upstream [json]",
+ "show ip pim [vrf NAME] upstream [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM upstream information\n"
+ JSON_STR)
+{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+ u_char uj = use_json(argc, argv);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_upstream(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_upstream_vrf_all,
+ show_ip_pim_upstream_vrf_all_cmd,
+ "show ip pim vrf all upstream [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM upstream information\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- pim_show_upstream(vty, uj);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_show_upstream(vrf->info, vty, uj);
+ }
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_upstream_join_desired,
show_ip_pim_upstream_join_desired_cmd,
- "show ip pim upstream-join-desired [json]",
+ "show ip pim [vrf NAME] upstream-join-desired [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM upstream join-desired\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- pim_show_join_desired(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_join_desired(vrf->info, vty, uj);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_upstream_rpf,
show_ip_pim_upstream_rpf_cmd,
- "show ip pim upstream-rpf [json]",
+ "show ip pim [vrf NAME] upstream-rpf [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM upstream source rpf\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- pim_show_upstream_rpf(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_upstream_rpf(vrf->info, vty, uj);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_rp,
show_ip_pim_rp_cmd,
- "show ip pim rp-info [json]",
+ "show ip pim [vrf NAME] rp-info [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM RP information\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- pim_rp_show_information(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_rp_show_information(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_rp_vrf_all,
+ show_ip_pim_rp_vrf_all_cmd,
+ "show ip pim vrf all rp-info [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM RP information\n"
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_rp_show_information(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_rpf,
show_ip_pim_rpf_cmd,
- "show ip pim rpf [json]",
+ "show ip pim [vrf NAME] rpf [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "PIM cached source rpf information\n"
+ JSON_STR)
+{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+ u_char uj = use_json(argc, argv);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_rpf(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_rpf_vrf_all,
+ show_ip_pim_rpf_vrf_all_cmd,
+ "show ip pim vrf all rpf [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM cached source rpf information\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- pim_show_rpf(vty, uj);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_show_rpf(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_nexthop,
show_ip_pim_nexthop_cmd,
- "show ip pim nexthop",
+ "show ip pim [vrf NAME] nexthop",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM cached nexthop rpf information\n")
{
- pim_show_nexthop(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_show_nexthop(vrf->info, vty);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_nexthop_lookup,
show_ip_pim_nexthop_lookup_cmd,
- "show ip pim nexthop-lookup A.B.C.D A.B.C.D",
+ "show ip pim [vrf NAME] nexthop-lookup A.B.C.D A.B.C.D",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM cached nexthop rpf lookup\n"
"Source/RP address\n"
"Multicast Group address\n")
@@ -3559,8 +4228,14 @@ DEFUN (show_ip_pim_nexthop_lookup,
struct pim_nexthop nexthop;
char nexthop_addr_str[PREFIX_STRLEN];
char grp_str[PREFIX_STRLEN];
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
- addr_str = argv[4]->arg;
+ argv_find(argv, argc, "A.B.C.D", &idx);
+ addr_str = argv[idx]->arg;
result = inet_pton(AF_INET, addr_str, &src_addr);
if (result <= 0) {
vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
@@ -3574,7 +4249,7 @@ DEFUN (show_ip_pim_nexthop_lookup,
return CMD_WARNING;
}
- addr_str1 = argv[5]->arg;
+ addr_str1 = argv[idx + 1]->arg;
result = inet_pton(AF_INET, addr_str1, &grp_addr);
if (result <= 0) {
vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
@@ -3588,7 +4263,8 @@ DEFUN (show_ip_pim_nexthop_lookup,
return CMD_WARNING;
}
- if (!pim_rp_set_upstream_addr(&vif_source, src_addr, grp_addr))
+ if (!pim_rp_set_upstream_addr(vrf->info, &vif_source, src_addr,
+ grp_addr))
return CMD_SUCCESS;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
@@ -3600,11 +4276,12 @@ DEFUN (show_ip_pim_nexthop_lookup,
grp.u.prefix4 = grp_addr;
memset(&nexthop, 0, sizeof(nexthop));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, NULL, &pnc)) == 1) {
- // Compute PIM RPF using Cached nexthop
- pim_ecmp_nexthop_search(&pnc, &nexthop, &nht_p, &grp, 0);
- } else
- pim_ecmp_nexthop_lookup(&nexthop, vif_source, &nht_p, &grp, 0);
+ if (pim_find_or_track_nexthop(vrf->info, &nht_p, NULL, NULL, &pnc))
+ pim_ecmp_nexthop_search(vrf->info, &pnc, &nexthop, &nht_p, &grp,
+ 0);
+ else
+ pim_ecmp_nexthop_lookup(vrf->info, &nexthop, vif_source, &nht_p,
+ &grp, 0);
pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
@@ -3617,27 +4294,33 @@ DEFUN (show_ip_pim_nexthop_lookup,
DEFUN (show_ip_pim_interface_traffic,
show_ip_pim_interface_traffic_cmd,
- "show ip pim interface traffic [WORD] [json]",
+ "show ip pim [vrf NAME] interface traffic [WORD] [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM interface information\n"
"Protocol Packet counters\n"
"Interface name\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- int idx = 0;
+
+ if (!vrf)
+ return CMD_WARNING;
if (argv_find(argv, argc, "WORD", &idx))
- pim_show_interface_traffic_single(vty, argv[idx]->arg, uj);
+ pim_show_interface_traffic_single(vrf->info, vty,
+ argv[idx]->arg, uj);
else
- pim_show_interface_traffic(vty, uj);
+ pim_show_interface_traffic(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void show_multicast_interfaces(struct vty *vty)
+static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
{
struct listnode *node;
struct interface *ifp;
@@ -3645,9 +4328,9 @@ static void show_multicast_interfaces(struct vty *vty)
vty_out(vty, "\n");
vty_out(vty,
- "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
+ "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
struct pim_interface *pim_ifp;
struct in_addr ifaddr;
struct sioc_vif_req vreq;
@@ -3660,9 +4343,9 @@ static void show_multicast_interfaces(struct vty *vty)
memset(&vreq, 0, sizeof(vreq));
vreq.vifi = pim_ifp->mroute_vif_index;
- if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) {
+ if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
zlog_warn(
- "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n",
+ "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
(unsigned long)SIOCGETVIFCNT, ifp->name,
pim_ifp->mroute_vif_index, errno,
safe_strerror(errno));
@@ -3670,7 +4353,7 @@ static void show_multicast_interfaces(struct vty *vty)
ifaddr = pim_ifp->primary_address;
- vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
+ vty_out(vty, "%-12s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
pim_ifp->mroute_vif_index, (unsigned long)vreq.icount,
(unsigned long)vreq.ocount, (unsigned long)vreq.ibytes,
@@ -3678,21 +4361,21 @@ static void show_multicast_interfaces(struct vty *vty)
}
}
-DEFUN (show_ip_multicast,
- show_ip_multicast_cmd,
- "show ip multicast",
- SHOW_STR
- IP_STR
- "Multicast global information\n")
+static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
+ struct vty *vty)
{
+ struct vrf *vrf = pim->vrf;
time_t now = pim_time_monotonic_sec();
-
char uptime[10];
- vty_out(vty, "Mroute socket descriptor: %d\n", qpim_mroute_socket_fd);
+ pim = vrf->info;
+
+ vty_out(vty, "Mroute socket descriptor:");
+
+ vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
pim_time_uptime(uptime, sizeof(uptime),
- now - qpim_mroute_socket_creation);
+ now - pim->mroute_socket_creation);
vty_out(vty, "Mroute socket uptime: %s\n", uptime);
vty_out(vty, "\n");
@@ -3716,14 +4399,62 @@ DEFUN (show_ip_multicast,
vty_out(vty, "\n");
- show_scan_oil_stats(vty, now);
+ show_scan_oil_stats(pim, vty, now);
+
+ show_multicast_interfaces(pim, vty);
+}
+
+DEFUN (show_ip_multicast,
+ show_ip_multicast_cmd,
+ "show ip multicast [vrf NAME]",
+ SHOW_STR
+ IP_STR
+ VRF_CMD_HELP_STR
+ "Multicast global information\n")
+{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ pim_cmd_show_ip_multicast_helper(vrf->info, vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_multicast_vrf_all,
+ show_ip_multicast_vrf_all_cmd,
+ "show ip multicast vrf all",
+ SHOW_STR
+ IP_STR
+ VRF_CMD_HELP_STR
+ "Multicast global information\n")
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
- show_multicast_interfaces(vty);
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ pim_cmd_show_ip_multicast_helper(vrf->info, vty);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
return CMD_SUCCESS;
}
-static void show_mroute(struct vty *vty, u_char uj)
+static void show_mroute(struct pim_instance *pim, struct vty *vty, u_char uj)
{
struct listnode *node;
struct channel_oil *c_oil;
@@ -3754,7 +4485,7 @@ static void show_mroute(struct vty *vty, u_char uj)
now = pim_time_monotonic_sec();
/* print list of PIM and IGMP routes */
- for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
found_oif = 0;
first = 1;
if (!c_oil->installed && !uj)
@@ -3764,7 +4495,7 @@ static void show_mroute(struct vty *vty, u_char uj)
sizeof(grp_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
sizeof(src_str));
- ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
+ ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
if (ifp_in)
strcpy(in_ifname, ifp_in->name);
@@ -3817,7 +4548,7 @@ static void show_mroute(struct vty *vty, u_char uj)
if (ttl < 1)
continue;
- ifp_out = pim_if_find_by_vif_index(oif_vif_index);
+ ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
pim_time_uptime(
oif_uptime, sizeof(oif_uptime),
now - c_oil->oif_creation[oif_vif_index]);
@@ -3919,7 +4650,7 @@ static void show_mroute(struct vty *vty, u_char uj)
}
/* Print list of static routes */
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
first = 1;
if (!s_route->c_oil.installed)
@@ -3929,7 +4660,7 @@ static void show_mroute(struct vty *vty, u_char uj)
sizeof(grp_str));
pim_inet4_dump("<source?>", s_route->source, src_str,
sizeof(src_str));
- ifp_in = pim_if_find_by_vif_index(s_route->iif);
+ ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
found_oif = 0;
if (ifp_in)
@@ -3975,7 +4706,7 @@ static void show_mroute(struct vty *vty, u_char uj)
if (ttl < 1)
continue;
- ifp_out = pim_if_find_by_vif_index(oif_vif_index);
+ ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
pim_time_uptime(
oif_uptime, sizeof(oif_uptime),
now
@@ -4019,9 +4750,10 @@ static void show_mroute(struct vty *vty, u_char uj)
json_ifp_out);
} else {
vty_out(vty,
- "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
+ "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
src_str, grp_str, proto, in_ifname,
- out_ifname, ttl, oif_uptime);
+ out_ifname, ttl, oif_uptime,
+ pim->vrf->name);
if (first) {
src_str[0] = '\0';
grp_str[0] = '\0';
@@ -4032,9 +4764,10 @@ static void show_mroute(struct vty *vty, u_char uj)
}
if (!uj && !found_oif) {
- vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
+ vty_out(vty,
+ "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
src_str, grp_str, proto, in_ifname, "none", 0,
- "--:--:--");
+ "--:--:--", pim->vrf->name);
}
}
@@ -4047,18 +4780,57 @@ static void show_mroute(struct vty *vty, u_char uj)
DEFUN (show_ip_mroute,
show_ip_mroute_cmd,
- "show ip mroute [json]",
+ "show ip mroute [vrf NAME] [json]",
SHOW_STR
IP_STR
MROUTE_STR
+ VRF_CMD_HELP_STR
JSON_STR)
{
u_char uj = use_json(argc, argv);
- show_mroute(vty, uj);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ show_mroute(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void show_mroute_count(struct vty *vty)
+DEFUN (show_ip_mroute_vrf_all,
+ show_ip_mroute_vrf_all_cmd,
+ "show ip mroute vrf all [json]",
+ SHOW_STR
+ IP_STR
+ MROUTE_STR
+ VRF_CMD_HELP_STR
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ show_mroute(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
+}
+
+static void show_mroute_count(struct pim_instance *pim, struct vty *vty)
{
struct listnode *node;
struct channel_oil *c_oil;
@@ -4070,7 +4842,7 @@ static void show_mroute_count(struct vty *vty)
"Source Group LastUsed Packets Bytes WrongIf \n");
/* Print PIM and IGMP route counts */
- for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -4090,8 +4862,7 @@ static void show_mroute_count(struct vty *vty)
c_oil->cc.wrong_if);
}
- /* Print static route counts */
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -4114,33 +4885,75 @@ static void show_mroute_count(struct vty *vty)
DEFUN (show_ip_mroute_count,
show_ip_mroute_count_cmd,
- "show ip mroute count",
+ "show ip mroute [vrf NAME] count",
SHOW_STR
IP_STR
MROUTE_STR
+ VRF_CMD_HELP_STR
"Route and packet count data\n")
{
- show_mroute_count(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ show_mroute_count(vrf->info, vty);
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_mroute_count_vrf_all,
+ show_ip_mroute_count_vrf_all_cmd,
+ "show ip mroute vrf all count",
+ SHOW_STR
+ IP_STR
+ MROUTE_STR
+ VRF_CMD_HELP_STR
+ "Route and packet count data\n")
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ show_mroute_count(vrf->info, vty);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
return CMD_SUCCESS;
}
DEFUN (show_ip_rib,
show_ip_rib_cmd,
- "show ip rib A.B.C.D",
+ "show ip rib [vrf NAME] A.B.C.D",
SHOW_STR
IP_STR
RIB_STR
+ VRF_CMD_HELP_STR
"Unicast address\n")
{
- int idx_ipv4 = 3;
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
struct in_addr addr;
const char *addr_str;
struct pim_nexthop nexthop;
char nexthop_addr_str[PREFIX_STRLEN];
int result;
+ if (!vrf)
+ return CMD_WARNING;
+
memset(&nexthop, 0, sizeof(nexthop));
- addr_str = argv[idx_ipv4]->arg;
+ argv_find(argv, argc, "A.B.C.D", &idx);
+ addr_str = argv[idx]->arg;
result = inet_pton(AF_INET, addr_str, &addr);
if (result <= 0) {
vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
@@ -4148,7 +4961,7 @@ DEFUN (show_ip_rib,
return CMD_WARNING;
}
- if (pim_nexthop_lookup(&nexthop, addr, 0)) {
+ if (pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
vty_out(vty,
"Failure querying RIB nexthop for unicast address %s\n",
addr_str);
@@ -4168,7 +4981,7 @@ DEFUN (show_ip_rib,
return CMD_SUCCESS;
}
-static void show_ssmpingd(struct vty *vty)
+static void show_ssmpingd(struct pim_instance *pim, struct vty *vty)
{
struct listnode *node;
struct ssmpingd_sock *ss;
@@ -4177,12 +4990,12 @@ static void show_ssmpingd(struct vty *vty)
vty_out(vty,
"Source Socket Address Port Uptime Requests\n");
- if (!qpim_ssmpingd_list)
+ if (!pim->ssmpingd_list)
return;
now = pim_time_monotonic_sec();
- for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
char source_str[INET_ADDRSTRLEN];
char ss_uptime[10];
struct sockaddr_in bind_addr;
@@ -4212,21 +5025,29 @@ static void show_ssmpingd(struct vty *vty)
DEFUN (show_ip_ssmpingd,
show_ip_ssmpingd_cmd,
- "show ip ssmpingd",
+ "show ip ssmpingd [vrf NAME]",
SHOW_STR
IP_STR
- SHOW_SSMPINGD_STR)
+ SHOW_SSMPINGD_STR
+ VRF_CMD_HELP_STR)
{
- show_ssmpingd(vty);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ show_ssmpingd(vrf->info, vty);
return CMD_SUCCESS;
}
-static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group,
+static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
+ const char *rp, const char *group,
const char *plist)
{
int result;
- result = pim_rp_new(rp, group, plist);
+ result = pim_rp_new(pim, rp, group, plist);
if (result == PIM_MALLOC_FAIL) {
vty_out(vty, "%% Out of memory\n");
@@ -4268,26 +5089,27 @@ static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group,
return CMD_SUCCESS;
}
-static int pim_cmd_spt_switchover(enum pim_spt_switchover spt,
+static int pim_cmd_spt_switchover(struct pim_instance *pim,
+ enum pim_spt_switchover spt,
const char *plist)
{
- pimg->spt.switchover = spt;
+ pim->spt.switchover = spt;
- switch (pimg->spt.switchover) {
+ switch (pim->spt.switchover) {
case PIM_SPT_IMMEDIATE:
- if (pimg->spt.plist)
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+ if (pim->spt.plist)
+ XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
- pim_upstream_add_lhr_star_pimreg();
+ pim_upstream_add_lhr_star_pimreg(pim);
break;
case PIM_SPT_INFINITY:
- pim_upstream_remove_lhr_star_pimreg(plist);
+ pim_upstream_remove_lhr_star_pimreg(pim, plist);
- if (pimg->spt.plist)
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+ if (pim->spt.plist)
+ XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
if (plist)
- pimg->spt.plist =
+ pim->spt.plist =
XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
break;
}
@@ -4303,7 +5125,8 @@ DEFUN (ip_pim_spt_switchover_infinity,
"SPT-Switchover\n"
"Never switch to SPT Tree\n")
{
- return pim_cmd_spt_switchover(PIM_SPT_INFINITY, NULL);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, NULL);
}
DEFUN (ip_pim_spt_switchover_infinity_plist,
@@ -4316,7 +5139,8 @@ DEFUN (ip_pim_spt_switchover_infinity_plist,
"Prefix-List to control which groups to switch\n"
"Prefix-List name\n")
{
- return pim_cmd_spt_switchover(PIM_SPT_INFINITY, argv[5]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, argv[5]->arg);
}
DEFUN (no_ip_pim_spt_switchover_infinity,
@@ -4328,7 +5152,8 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
"SPT_Switchover\n"
"Never switch to SPT Tree\n")
{
- return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
}
DEFUN (no_ip_pim_spt_switchover_infinity_plist,
@@ -4342,7 +5167,8 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
"Prefix-List to control which groups to switch\n"
"Prefix-List name\n")
{
- return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
}
DEFUN (ip_pim_joinprune_time,
@@ -4353,6 +5179,7 @@ DEFUN (ip_pim_joinprune_time,
"Join Prune Send Interval\n"
"Seconds\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_t_periodic = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -4366,6 +5193,7 @@ DEFUN (no_ip_pim_joinprune_time,
"Join Prune Send Interval\n"
"Seconds\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_t_periodic = PIM_DEFAULT_T_PERIODIC;
return CMD_SUCCESS;
}
@@ -4378,6 +5206,7 @@ DEFUN (ip_pim_register_suppress,
"Register Suppress Timer\n"
"Seconds\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_register_suppress_time = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -4391,10 +5220,40 @@ DEFUN (no_ip_pim_register_suppress,
"Register Suppress Timer\n"
"Seconds\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
return CMD_SUCCESS;
}
+DEFUN (ip_pim_rp_keep_alive,
+ ip_pim_rp_keep_alive_cmd,
+ "ip pim rp keep-alive-timer (31-60000)",
+ IP_STR
+ "pim multicast routing\n"
+ "Rendevous Point\n"
+ "Keep alive Timer\n"
+ "Seconds\n")
+{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->rp_keep_alive_time = atoi(argv[4]->arg);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_rp_keep_alive,
+ no_ip_pim_rp_keep_alive_cmd,
+ "no ip pim rp keep-alive-timer (31-60000)",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Rendevous Point\n"
+ "Keep alive Timer\n"
+ "Seconds\n")
+{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->rp_keep_alive_time = PIM_KEEPALIVE_PERIOD;
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_keep_alive,
ip_pim_keep_alive_cmd,
"ip pim keep-alive-timer (31-60000)",
@@ -4403,7 +5262,8 @@ DEFUN (ip_pim_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- qpim_keep_alive_time = atoi(argv[3]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->keep_alive_time = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -4416,7 +5276,8 @@ DEFUN (no_ip_pim_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
return CMD_SUCCESS;
}
@@ -4428,6 +5289,7 @@ DEFUN (ip_pim_packets,
"packets to process at one time per fd\n"
"Number of packets\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_packet_process = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -4441,6 +5303,7 @@ DEFUN (no_ip_pim_packets,
"packets to process at one time per fd\n"
"Number of packets\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
return CMD_SUCCESS;
}
@@ -4452,7 +5315,8 @@ DEFUN (ip_pim_v6_secondary,
"pim multicast routing\n"
"Send v6 secondary addresses\n")
{
- pimg->send_v6_secondary = 1;
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->send_v6_secondary = 1;
return CMD_SUCCESS;
}
@@ -4465,7 +5329,8 @@ DEFUN (no_ip_pim_v6_secondary,
"pim multicast routing\n"
"Send v6 secondary addresses\n")
{
- pimg->send_v6_secondary = 0;
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ pim->send_v6_secondary = 0;
return CMD_SUCCESS;
}
@@ -4479,12 +5344,14 @@ DEFUN (ip_pim_rp,
"ip address of RP\n"
"Group Address range to cover\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
int idx_ipv4 = 3;
if (argc == (idx_ipv4 + 1))
- return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, NULL);
+ return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
+ NULL);
else
- return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg,
+ return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
argv[idx_ipv4 + 1]->arg, NULL);
}
@@ -4498,13 +5365,15 @@ DEFUN (ip_pim_rp_prefix_list,
"group prefix-list filter\n"
"Name of a prefix-list\n")
{
- return pim_rp_cmd_worker(vty, argv[3]->arg, NULL, argv[5]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_rp_cmd_worker(pim, vty, argv[3]->arg, NULL, argv[5]->arg);
}
-static int pim_no_rp_cmd_worker(struct vty *vty, const char *rp,
- const char *group, const char *plist)
+static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
+ const char *rp, const char *group,
+ const char *plist)
{
- int result = pim_rp_del(rp, group, plist);
+ int result = pim_rp_del(pim, rp, group, plist);
if (result == PIM_GROUP_BAD_ADDRESS) {
vty_out(vty, "%% Bad group address specified: %s\n", group);
@@ -4534,13 +5403,14 @@ DEFUN (no_ip_pim_rp,
"ip address of RP\n"
"Group Address range to cover\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
int idx_ipv4 = 4, idx_group = 0;
if (argv_find(argv, argc, "A.B.C.D/M", &idx_group))
- return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg,
+ return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
argv[idx_group]->arg, NULL);
else
- return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL,
+ return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
NULL);
}
@@ -4555,12 +5425,14 @@ DEFUN (no_ip_pim_rp_prefix_list,
"group prefix-list filter\n"
"Name of a prefix-list\n")
{
- return pim_no_rp_cmd_worker(vty, argv[4]->arg, NULL, argv[6]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg);
}
-static int pim_ssm_cmd_worker(struct vty *vty, const char *plist)
+static int pim_ssm_cmd_worker(struct pim_instance *pim, struct vty *vty,
+ const char *plist)
{
- int result = pim_ssm_range_set(VRF_DEFAULT, plist);
+ int result = pim_ssm_range_set(pim, pim->vrf_id, plist);
if (result == PIM_SSM_ERR_NONE)
return CMD_SUCCESS;
@@ -4588,7 +5460,8 @@ DEFUN (ip_pim_ssm_prefix_list,
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
- return pim_ssm_cmd_worker(vty, argv[0]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_ssm_cmd_worker(pim, vty, argv[4]->arg);
}
DEFUN (no_ip_pim_ssm_prefix_list,
@@ -4600,7 +5473,8 @@ DEFUN (no_ip_pim_ssm_prefix_list,
"Source Specific Multicast\n"
"group range prefix-list filter\n")
{
- return pim_ssm_cmd_worker(vty, NULL);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return pim_ssm_cmd_worker(pim, vty, NULL);
}
DEFUN (no_ip_pim_ssm_prefix_list_name,
@@ -4613,19 +5487,21 @@ DEFUN (no_ip_pim_ssm_prefix_list_name,
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
- struct pim_ssm *ssm = pimg->ssm_info;
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ struct pim_ssm *ssm = pim->ssm_info;
- if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg))
- return pim_ssm_cmd_worker(vty, NULL);
+ if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg))
+ return pim_ssm_cmd_worker(pim, vty, NULL);
- vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[0]->arg);
+ vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
-static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)
+static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
+ struct vty *vty, u_char uj)
{
- struct pim_ssm *ssm = pimg->ssm_info;
+ struct pim_ssm *ssm = pim->ssm_info;
const char *range_str =
ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
@@ -4642,20 +5518,28 @@ static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)
DEFUN (show_ip_pim_ssm_range,
show_ip_pim_ssm_range_cmd,
- "show ip pim group-type [json]",
+ "show ip pim [vrf NAME] group-type [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"PIM group type\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- ip_pim_ssm_show_group_range(vty, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ ip_pim_ssm_show_group_range(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj,
+static void ip_pim_ssm_show_group_type(struct pim_instance *pim,
+ struct vty *vty, u_char uj,
const char *group)
{
struct in_addr group_addr;
@@ -4667,7 +5551,8 @@ static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj,
type_str = "invalid";
else {
if (pim_is_group_224_4(group_addr))
- type_str = pim_is_grp_ssm(group_addr) ? "SSM" : "ASM";
+ type_str =
+ pim_is_grp_ssm(pim, group_addr) ? "SSM" : "ASM";
else
type_str = "not-multicast";
}
@@ -4685,16 +5570,24 @@ static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj,
DEFUN (show_ip_pim_group_type,
show_ip_pim_group_type_cmd,
- "show ip pim group-type A.B.C.D [json]",
+ "show ip pim [vrf NAME] group-type A.B.C.D [json]",
SHOW_STR
IP_STR
PIM_STR
+ VRF_CMD_HELP_STR
"multicast group type\n"
"group address\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
u_char uj = use_json(argc, argv);
- ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ argv_find(argv, argc, "A.B.C.D", &idx);
+ ip_pim_ssm_show_group_type(vrf->info, vty, uj, argv[idx]->arg);
return CMD_SUCCESS;
}
@@ -4727,6 +5620,7 @@ DEFUN (ip_ssmpingd,
CONF_SSMPINGD_STR
"Source address\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
int idx_ipv4 = 2;
int result;
struct in_addr source_addr;
@@ -4739,7 +5633,7 @@ DEFUN (ip_ssmpingd,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_ssmpingd_start(source_addr);
+ result = pim_ssmpingd_start(pim, source_addr);
if (result) {
vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n",
source_str, result);
@@ -4757,6 +5651,7 @@ DEFUN (no_ip_ssmpingd,
CONF_SSMPINGD_STR
"Source address\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
int idx_ipv4 = 3;
int result;
struct in_addr source_addr;
@@ -4769,7 +5664,7 @@ DEFUN (no_ip_ssmpingd,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_ssmpingd_stop(source_addr);
+ result = pim_ssmpingd_stop(pim, source_addr);
if (result) {
vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n",
source_str, result);
@@ -4786,6 +5681,7 @@ DEFUN (ip_pim_ecmp,
"pim multicast routing\n"
"Enable PIM ECMP \n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_ecmp_enable = 1;
return CMD_SUCCESS;
@@ -4799,6 +5695,7 @@ DEFUN (no_ip_pim_ecmp,
"pim multicast routing\n"
"Disable PIM ECMP \n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_ecmp_enable = 0;
return CMD_SUCCESS;
@@ -4812,6 +5709,7 @@ DEFUN (ip_pim_ecmp_rebalance,
"Enable PIM ECMP \n"
"Enable PIM ECMP Rebalance\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_ecmp_enable = 1;
qpim_ecmp_rebalance_enable = 1;
@@ -4827,6 +5725,7 @@ DEFUN (no_ip_pim_ecmp_rebalance,
"Disable PIM ECMP \n"
"Disable PIM ECMP Rebalance\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
qpim_ecmp_rebalance_enable = 0;
return CMD_SUCCESS;
@@ -5496,13 +6395,17 @@ DEFUN (interface_ip_pim_sm,
PIM_STR
IFACE_PIM_SM_STR)
{
+ struct pim_interface *pim_ifp;
+
VTY_DECLVAR_CONTEXT(interface, ifp);
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
return CMD_WARNING_CONFIG_FAILED;
}
- pim_if_create_pimreg();
+ pim_ifp = ifp->info;
+
+ pim_if_create_pimreg(pim_ifp->pim);
return CMD_SUCCESS;
}
@@ -5575,6 +6478,8 @@ DEFUN (interface_ip_mroute,
"Group address\n")
{
VTY_DECLVAR_CONTEXT(interface, iif);
+ struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
int idx_interface = 2;
int idx_ipv4 = 3;
struct interface *oif;
@@ -5584,11 +6489,14 @@ DEFUN (interface_ip_mroute,
struct in_addr src_addr;
int result;
+ pim_ifp = iif->info;
+ pim = pim_ifp->pim;
+
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, VRF_DEFAULT);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
if (!oif) {
vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
grp_str = argv[idx_ipv4]->arg;
@@ -5596,14 +6504,14 @@ DEFUN (interface_ip_mroute,
if (result <= 0) {
vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
src_addr.s_addr = INADDR_ANY;
- if (pim_static_add(iif, oif, grp_addr, src_addr)) {
+ if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
vty_out(vty, "Failed to add route\n");
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -5619,6 +6527,8 @@ DEFUN (interface_ip_mroute_source,
"Source address\n")
{
VTY_DECLVAR_CONTEXT(interface, iif);
+ struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
int idx_interface = 2;
int idx_ipv4 = 3;
int idx_ipv4_2 = 4;
@@ -5630,11 +6540,14 @@ DEFUN (interface_ip_mroute_source,
struct in_addr src_addr;
int result;
+ pim_ifp = iif->info;
+ pim = pim_ifp->pim;
+
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, VRF_DEFAULT);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
if (!oif) {
vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
grp_str = argv[idx_ipv4]->arg;
@@ -5642,7 +6555,7 @@ DEFUN (interface_ip_mroute_source,
if (result <= 0) {
vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
src_str = argv[idx_ipv4_2]->arg;
@@ -5650,12 +6563,12 @@ DEFUN (interface_ip_mroute_source,
if (result <= 0) {
vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
- if (pim_static_add(iif, oif, grp_addr, src_addr)) {
+ if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
vty_out(vty, "Failed to add route\n");
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -5671,6 +6584,8 @@ DEFUN (interface_no_ip_mroute,
"Group Address\n")
{
VTY_DECLVAR_CONTEXT(interface, iif);
+ struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
int idx_interface = 3;
int idx_ipv4 = 4;
struct interface *oif;
@@ -5680,11 +6595,14 @@ DEFUN (interface_no_ip_mroute,
struct in_addr src_addr;
int result;
+ pim_ifp = iif->info;
+ pim = pim_ifp->pim;
+
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, VRF_DEFAULT);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
if (!oif) {
vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
grp_str = argv[idx_ipv4]->arg;
@@ -5692,14 +6610,14 @@ DEFUN (interface_no_ip_mroute,
if (result <= 0) {
vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
src_addr.s_addr = INADDR_ANY;
- if (pim_static_del(iif, oif, grp_addr, src_addr)) {
+ if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
vty_out(vty, "Failed to remove route\n");
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -5716,6 +6634,8 @@ DEFUN (interface_no_ip_mroute_source,
"Source Address\n")
{
VTY_DECLVAR_CONTEXT(interface, iif);
+ struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
int idx_interface = 3;
int idx_ipv4 = 4;
int idx_ipv4_2 = 5;
@@ -5727,11 +6647,14 @@ DEFUN (interface_no_ip_mroute_source,
struct in_addr src_addr;
int result;
+ pim_ifp = iif->info;
+ pim = pim_ifp->pim;
+
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, VRF_DEFAULT);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
if (!oif) {
vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
grp_str = argv[idx_ipv4]->arg;
@@ -5739,7 +6662,7 @@ DEFUN (interface_no_ip_mroute_source,
if (result <= 0) {
vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
src_str = argv[idx_ipv4_2]->arg;
@@ -5747,12 +6670,12 @@ DEFUN (interface_no_ip_mroute_source,
if (result <= 0) {
vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
- if (pim_static_del(iif, oif, grp_addr, src_addr)) {
+ if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
vty_out(vty, "Failed to remove route\n");
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -5789,7 +6712,6 @@ DEFUN (interface_ip_pim_hello,
return CMD_SUCCESS;
}
-
DEFUN (interface_no_ip_pim_hello,
interface_no_ip_pim_hello_cmd,
"no ip pim hello [(1-180) (1-180)]",
@@ -6011,6 +6933,28 @@ DEFUN (no_debug_pim,
return CMD_SUCCESS;
}
+DEFUN (debug_pim_nht,
+ debug_pim_nht_cmd,
+ "debug pim nht",
+ DEBUG_STR
+ DEBUG_PIM_STR
+ "Nexthop Tracking\n")
+{
+ PIM_DO_DEBUG_PIM_NHT;
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_pim_nht,
+ no_debug_pim_nht_cmd,
+ "no debug pim nht",
+ NO_STR
+ DEBUG_STR
+ DEBUG_PIM_STR
+ "Nexthop Tracking\n")
+{
+ PIM_DONT_DEBUG_PIM_NHT;
+ return CMD_SUCCESS;
+}
DEFUN (debug_pim_events,
debug_pim_events_cmd,
@@ -6115,7 +7059,6 @@ DEFUN (no_debug_pim_packetdump_send,
return CMD_SUCCESS;
}
-
DEFUN (debug_pim_packetdump_recv,
debug_pim_packetdump_recv_cmd,
"debug pim packet-dump receive",
@@ -6141,7 +7084,6 @@ DEFUN (no_debug_pim_packetdump_recv,
return CMD_SUCCESS;
}
-
DEFUN (debug_pim_trace,
debug_pim_trace_cmd,
"debug pim trace",
@@ -6153,6 +7095,18 @@ DEFUN (debug_pim_trace,
return CMD_SUCCESS;
}
+DEFUN (debug_pim_trace_detail,
+ debug_pim_trace_detail_cmd,
+ "debug pim trace detail",
+ DEBUG_STR
+ DEBUG_PIM_STR
+ DEBUG_PIM_TRACE_STR
+ "Detailed Information\n")
+{
+ PIM_DO_DEBUG_PIM_TRACE_DETAIL;
+ return CMD_SUCCESS;
+}
+
DEFUN (no_debug_pim_trace,
no_debug_pim_trace_cmd,
"no debug pim trace",
@@ -6165,6 +7119,18 @@ DEFUN (no_debug_pim_trace,
return CMD_SUCCESS;
}
+DEFUN (no_debug_pim_trace_detail,
+ no_debug_pim_trace_detail_cmd,
+ "no debug pim trace detail",
+ NO_STR
+ DEBUG_STR
+ DEBUG_PIM_STR
+ DEBUG_PIM_TRACE_STR
+ "Detailed Information\n")
+{
+ PIM_DONT_DEBUG_PIM_TRACE_DETAIL;
+ return CMD_SUCCESS;
+}
DEFUN (debug_ssmpingd,
debug_ssmpingd_cmd,
@@ -6187,7 +7153,6 @@ DEFUN (no_debug_ssmpingd,
return CMD_SUCCESS;
}
-
DEFUN (debug_pim_zebra,
debug_pim_zebra_cmd,
"debug pim zebra",
@@ -6211,7 +7176,6 @@ DEFUN (no_debug_pim_zebra,
return CMD_SUCCESS;
}
-
DEFUN (debug_msdp,
debug_msdp_cmd,
"debug msdp",
@@ -6435,8 +7399,8 @@ ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
"Required min receive interval\n"
"Desired min transmit interval\n")
-static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer,
- const char *local)
+static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
+ const char *peer, const char *local)
{
enum pim_msdp_err result;
struct in_addr peer_addr;
@@ -6456,7 +7420,7 @@ static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_msdp_peer_add(peer_addr, local_addr, "default",
+ result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
NULL /* mp_p */);
switch (result) {
case PIM_MSDP_ERR_NONE:
@@ -6487,10 +7451,12 @@ DEFUN_HIDDEN (ip_msdp_peer,
"Source address for TCP connection\n"
"local ip address\n")
{
- return ip_msdp_peer_cmd_worker(vty, argv[3]->arg, argv[5]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg);
}
-static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer)
+static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
+ const char *peer)
{
enum pim_msdp_err result;
struct in_addr peer_addr;
@@ -6502,7 +7468,7 @@ static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer)
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_msdp_peer_del(peer_addr);
+ result = pim_msdp_peer_del(pim, peer_addr);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6525,10 +7491,12 @@ DEFUN_HIDDEN (no_ip_msdp_peer,
"Delete MSDP peer\n"
"peer ip address\n")
{
- return ip_no_msdp_peer_cmd_worker(vty, argv[4]->arg);
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg);
}
-static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg,
+static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
+ struct vty *vty, const char *mg,
const char *mbr)
{
enum pim_msdp_err result;
@@ -6541,7 +7509,7 @@ static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_msdp_mg_mbr_add(mg, mbr_ip);
+ result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6571,11 +7539,13 @@ DEFUN (ip_msdp_mesh_group_member,
"mesh group member\n"
"peer ip address\n")
{
- return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg,
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg,
argv[5]->arg);
}
-static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty,
+static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
+ struct vty *vty,
const char *mg,
const char *mbr)
{
@@ -6589,7 +7559,7 @@ static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_msdp_mg_mbr_del(mg, mbr_ip);
+ result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6616,11 +7586,13 @@ DEFUN (no_ip_msdp_mesh_group_member,
"mesh group member\n"
"peer ip address\n")
{
- return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg,
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg,
argv[6]->arg);
}
-static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg,
+static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
+ struct vty *vty, const char *mg,
const char *src)
{
enum pim_msdp_err result;
@@ -6633,7 +7605,7 @@ static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg,
return CMD_WARNING_CONFIG_FAILED;
}
- result = pim_msdp_mg_src_add(mg, src_ip);
+ result = pim_msdp_mg_src_add(pim, mg, src_ip);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6661,16 +7633,18 @@ DEFUN (ip_msdp_mesh_group_source,
"mesh group local address\n"
"source ip address for the TCP connection\n")
{
- return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg,
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+ return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg,
argv[5]->arg);
}
-static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty,
+static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
+ struct vty *vty,
const char *mg)
{
enum pim_msdp_err result;
- result = pim_msdp_mg_src_del(mg);
+ result = pim_msdp_mg_src_del(pim, mg);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6684,11 +7658,12 @@ static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty,
return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
}
-static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg)
+static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
+ struct vty *vty, const char *mg)
{
enum pim_msdp_err result;
- result = pim_msdp_mg_del(mg);
+ result = pim_msdp_mg_del(pim, mg);
switch (result) {
case PIM_MSDP_ERR_NONE:
break;
@@ -6713,10 +7688,11 @@ DEFUN (no_ip_msdp_mesh_group_source,
"mesh group source\n"
"mesh group local address\n")
{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
if (argc == 7)
- return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg);
+ return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[6]->arg);
else
- return ip_no_msdp_mesh_group_source_cmd_worker(vty,
+ return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty,
argv[4]->arg);
}
@@ -6729,11 +7705,12 @@ static void print_empty_json_obj(struct vty *vty)
json_object_free(json);
}
-static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj)
+static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *mbrnode;
struct pim_msdp_mg_mbr *mbr;
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
char mbr_str[INET_ADDRSTRLEN];
char src_str[INET_ADDRSTRLEN];
char state_str[PIM_MSDP_STATE_STRLEN];
@@ -6798,20 +7775,61 @@ static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj)
DEFUN (show_ip_msdp_mesh_group,
show_ip_msdp_mesh_group_cmd,
- "show ip msdp mesh-group [json]",
+ "show ip msdp [vrf NAME] mesh-group [json]",
SHOW_STR
IP_STR
MSDP_STR
+ VRF_CMD_HELP_STR
"MSDP mesh-group information\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- ip_msdp_show_mesh_group(vty, uj);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ ip_msdp_show_mesh_group(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void ip_msdp_show_peers(struct vty *vty, u_char uj)
+DEFUN (show_ip_msdp_mesh_group_vrf_all,
+ show_ip_msdp_mesh_group_vrf_all_cmd,
+ "show ip msdp vrf all mesh-group [json]",
+ SHOW_STR
+ IP_STR
+ MSDP_STR
+ VRF_CMD_HELP_STR
+ "MSDP mesh-group information\n"
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ ip_msdp_show_mesh_group(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
+}
+
+static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *mpnode;
struct pim_msdp_peer *mp;
@@ -6831,7 +7849,7 @@ static void ip_msdp_show_peers(struct vty *vty, u_char uj)
"Peer Local State Uptime SaCnt\n");
}
- for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
if (mp->state == PIM_MSDP_ESTABLISHED) {
now = pim_time_monotonic_sec();
pim_time_uptime(timebuf, sizeof(timebuf),
@@ -6864,8 +7882,8 @@ static void ip_msdp_show_peers(struct vty *vty, u_char uj)
}
}
-static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer,
- u_char uj)
+static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
+ const char *peer, u_char uj)
{
struct listnode *mpnode;
struct pim_msdp_peer *mp;
@@ -6884,7 +7902,7 @@ static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer,
json = json_object_new_object();
}
- for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
if (strcmp(peer, "detail") && strcmp(peer, peer_str))
continue;
@@ -6971,28 +7989,81 @@ static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer,
DEFUN (show_ip_msdp_peer_detail,
show_ip_msdp_peer_detail_cmd,
- "show ip msdp peer [detail|A.B.C.D] [json]",
+ "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
SHOW_STR
IP_STR
MSDP_STR
+ VRF_CMD_HELP_STR
"MSDP peer information\n"
"Detailed output\n"
"peer ip address\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- if (uj)
- argc--;
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ char *arg = NULL;
+
+ if (argv_find(argv, argc, "detail", &idx))
+ arg = argv[idx]->text;
+ else if (argv_find(argv, argc, "A.B.C.D", &idx))
+ arg = argv[idx]->arg;
- if (argc > 4)
- ip_msdp_show_peers_detail(vty, argv[4]->arg, uj);
+ if (arg)
+ ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
else
- ip_msdp_show_peers(vty, uj);
+ ip_msdp_show_peers(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void ip_msdp_show_sa(struct vty *vty, u_char uj)
+DEFUN (show_ip_msdp_peer_detail_vrf_all,
+ show_ip_msdp_peer_detail_vrf_all_cmd,
+ "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
+ SHOW_STR
+ IP_STR
+ MSDP_STR
+ VRF_CMD_HELP_STR
+ "MSDP peer information\n"
+ "Detailed output\n"
+ "peer ip address\n"
+ JSON_STR)
+{
+ int idx = 2;
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ if (argv_find(argv, argc, "detail", &idx)
+ || argv_find(argv, argc, "A.B.C.D", &idx))
+ ip_msdp_show_peers_detail(vrf->info, vty,
+ argv[idx]->arg, uj);
+ else
+ ip_msdp_show_peers(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
+}
+
+static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -7014,7 +8085,7 @@ static void ip_msdp_show_sa(struct vty *vty, u_char uj)
"Source Group RP Local SPT Uptime\n");
}
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
now = pim_time_monotonic_sec();
pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
@@ -7059,7 +8130,6 @@ static void ip_msdp_show_sa(struct vty *vty, u_char uj)
}
}
-
if (uj) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
@@ -7133,7 +8203,8 @@ static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
}
}
-static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj)
+static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -7145,7 +8216,7 @@ static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj)
json = json_object_new_object();
}
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
@@ -7161,21 +8232,63 @@ static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj)
DEFUN (show_ip_msdp_sa_detail,
show_ip_msdp_sa_detail_cmd,
- "show ip msdp sa detail [json]",
+ "show ip msdp [vrf NAME] sa detail [json]",
SHOW_STR
IP_STR
MSDP_STR
+ VRF_CMD_HELP_STR
"MSDP active-source information\n"
"Detailed output\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
- ip_msdp_show_sa_detail(vty, uj);
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ ip_msdp_show_sa_detail(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj)
+DEFUN (show_ip_msdp_sa_detail_vrf_all,
+ show_ip_msdp_sa_detail_vrf_all_cmd,
+ "show ip msdp vrf all sa detail [json]",
+ SHOW_STR
+ IP_STR
+ MSDP_STR
+ VRF_CMD_HELP_STR
+ "MSDP active-source information\n"
+ "Detailed output\n"
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ ip_msdp_show_sa_detail(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
+}
+
+static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
+ const char *addr, u_char uj)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -7187,7 +8300,7 @@ static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj)
json = json_object_new_object();
}
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
@@ -7203,8 +8316,8 @@ static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj)
}
}
-static void ip_msdp_show_sa_sg(struct vty *vty, const char *src,
- const char *grp, u_char uj)
+static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
+ const char *src, const char *grp, u_char uj)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -7216,7 +8329,7 @@ static void ip_msdp_show_sa_sg(struct vty *vty, const char *src,
json = json_object_new_object();
}
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
@@ -7234,18 +8347,25 @@ static void ip_msdp_show_sa_sg(struct vty *vty, const char *src,
DEFUN (show_ip_msdp_sa_sg,
show_ip_msdp_sa_sg_cmd,
- "show ip msdp sa [A.B.C.D [A.B.C.D]] [json]",
+ "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
SHOW_STR
IP_STR
MSDP_STR
+ VRF_CMD_HELP_STR
"MSDP active-source information\n"
"source or group ip\n"
"group ip\n"
- "JavaScript Object Notation\n")
+ JSON_STR)
{
u_char uj = use_json(argc, argv);
+ struct vrf *vrf;
+ int idx = 2;
+
+ vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
- int idx = 0;
char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
: NULL;
char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
@@ -7253,16 +8373,16 @@ DEFUN (show_ip_msdp_sa_sg,
: NULL;
if (src_ip && grp_ip)
- ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj);
+ ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
else if (src_ip)
- ip_msdp_show_sa_addr(vty, src_ip, uj);
+ ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
else
- ip_msdp_show_sa(vty, uj);
+ ip_msdp_show_sa(vrf->info, vty, uj);
return CMD_SUCCESS;
}
-void pim_cmd_init()
+void pim_cmd_init(void)
{
install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */
install_node(&interface_node,
@@ -7274,35 +8394,68 @@ void pim_cmd_init()
install_element(CONFIG_NODE, &ip_multicast_routing_cmd);
install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd);
install_element(CONFIG_NODE, &ip_pim_rp_cmd);
+ install_element(VRF_NODE, &ip_pim_rp_cmd);
install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
+ install_element(VRF_NODE, &no_ip_pim_rp_cmd);
install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
+ install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
+ install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
+ install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
+ install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
+ install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
+ install_element(VRF_NODE, &ip_pim_register_suppress_cmd);
install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
+ install_element(VRF_NODE, &no_ip_pim_register_suppress_cmd);
install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
+ install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
+ install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
+ install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
install_element(CONFIG_NODE,
&no_ip_pim_spt_switchover_infinity_plist_cmd);
+ install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
+ install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
+ install_element(VRF_NODE, &no_ip_pim_joinprune_time_cmd);
install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
+ install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
+ install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
+ install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
+ install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
+ install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
+ install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
install_element(CONFIG_NODE, &ip_pim_packets_cmd);
+ install_element(VRF_NODE, &ip_pim_packets_cmd);
install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
+ install_element(VRF_NODE, &no_ip_pim_packets_cmd);
install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
+ install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
+ install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
+ install_element(VRF_NODE, &ip_ssmpingd_cmd);
install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
+ install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
+ install_element(VRF_NODE, &ip_msdp_peer_cmd);
install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
+ install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
+ install_element(VRF_NODE, &ip_pim_ecmp_cmd);
install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
+ install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
+ install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
+ install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
@@ -7337,8 +8490,11 @@ void pim_cmd_init()
install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
@@ -7348,19 +8504,29 @@ void pim_cmd_init()
install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_join_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
install_element(VIEW_NODE, &show_ip_pim_state_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_multicast_cmd);
+ install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_mroute_cmd);
+ install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
+ install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_rib_cmd);
install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
install_element(VIEW_NODE, &show_debugging_pim_cmd);
@@ -7390,6 +8556,8 @@ void pim_cmd_init()
install_element(ENABLE_NODE, &no_debug_static_cmd);
install_element(ENABLE_NODE, &debug_pim_cmd);
install_element(ENABLE_NODE, &no_debug_pim_cmd);
+ install_element(ENABLE_NODE, &debug_pim_nht_cmd);
+ install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
install_element(ENABLE_NODE, &debug_pim_events_cmd);
install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
install_element(ENABLE_NODE, &debug_pim_packets_cmd);
@@ -7400,6 +8568,8 @@ void pim_cmd_init()
install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
install_element(ENABLE_NODE, &debug_pim_trace_cmd);
install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
+ install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
+ install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
@@ -7430,12 +8600,16 @@ void pim_cmd_init()
install_element(CONFIG_NODE, &no_debug_static_cmd);
install_element(CONFIG_NODE, &debug_pim_cmd);
install_element(CONFIG_NODE, &no_debug_pim_cmd);
+ install_element(CONFIG_NODE, &debug_pim_nht_cmd);
+ install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
install_element(CONFIG_NODE, &debug_pim_events_cmd);
install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
install_element(CONFIG_NODE, &debug_pim_packets_cmd);
install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
install_element(CONFIG_NODE, &debug_pim_trace_cmd);
install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
+ install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
+ install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
@@ -7449,14 +8623,22 @@ void pim_cmd_init()
install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
+
install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
+ install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
+ install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
+ install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
+ install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
+ install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
+ install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
+ install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h
index 64751d8682..8867514876 100644
--- a/pimd/pim_cmd.h
+++ b/pimd/pim_cmd.h
@@ -66,4 +66,13 @@
void pim_cmd_init(void);
+/*
+ * Special Macro to allow us to get the correct pim_instance;
+ */
+#define PIM_DECLVAR_CONTEXT(A, B) \
+ struct vrf *A = VTY_GET_CONTEXT(vrf); \
+ struct pim_instance *B = \
+ (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT); \
+ vrf = (vrf) ? vrf : pim->vrf;
+
#endif /* PIM_CMD_H */
diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c
index 2592514f38..138a110d3a 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -395,7 +395,8 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
ifp->name);
}
- pim_upstream_rpf_genid_changed(neigh->source_addr);
+ pim_upstream_rpf_genid_changed(pim_ifp->pim,
+ neigh->source_addr);
pim_neighbor_delete(ifp, neigh, "GenID mismatch");
neigh = pim_neighbor_add(ifp, src_addr, hello_options,
@@ -445,6 +446,8 @@ int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
uint8_t *curr = tlv_buf;
uint8_t *pastend = tlv_buf + tlv_buf_size;
uint8_t *tmp;
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim = pim_ifp->pim;
/*
* Append options
@@ -516,7 +519,7 @@ int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
}
return -4;
}
- if (pimg->send_v6_secondary) {
+ if (pim->send_v6_secondary) {
curr = pim_tlv_append_addrlist_ucast(
curr, pastend, ifp->connected, AF_INET6);
if (!curr) {
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 8201625245..1afcff7cb1 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -29,6 +29,7 @@
#include "hash.h"
#include "pimd.h"
+#include "pim_instance.h"
#include "pim_zebra.h"
#include "pim_iface.h"
#include "pim_igmp.h"
@@ -43,63 +44,87 @@
#include "pim_ssmpingd.h"
#include "pim_rp.h"
#include "pim_nht.h"
-
-struct interface *pim_regiface = NULL;
-struct list *pim_ifchannel_list = NULL;
-static int pim_iface_vif_index[MAXVIFS];
+#include "pim_jp_agg.h"
static void pim_if_igmp_join_del_all(struct interface *ifp);
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
struct in_addr group_addr,
struct in_addr source_addr);
-void pim_if_init(void)
+void pim_if_init(struct pim_instance *pim)
{
int i;
for (i = 0; i < MAXVIFS; i++)
- pim_iface_vif_index[i] = 0;
-
- pim_ifchannel_list = list_new();
- pim_ifchannel_list->cmp =
- (int (*)(void *, void *))pim_ifchannel_compare;
+ pim->iface_vif_index[i] = 0;
}
-void pim_if_terminate(void)
+void pim_if_terminate(struct pim_instance *pim)
{
- if (pim_ifchannel_list)
- list_free(pim_ifchannel_list);
+ // Nothing to do at this moment
+ return;
}
static void *if_list_clean(struct pim_interface *pim_ifp)
{
- if (pim_ifp->igmp_join_list) {
+ struct pim_ifchannel *ch;
+
+ if (pim_ifp->igmp_join_list)
list_delete(pim_ifp->igmp_join_list);
- }
- if (pim_ifp->igmp_socket_list) {
+ if (pim_ifp->igmp_socket_list)
list_delete(pim_ifp->igmp_socket_list);
- }
- if (pim_ifp->pim_neighbor_list) {
+ if (pim_ifp->pim_neighbor_list)
list_delete(pim_ifp->pim_neighbor_list);
- }
if (pim_ifp->upstream_switch_list)
list_delete(pim_ifp->upstream_switch_list);
- if (pim_ifp->pim_ifchannel_list) {
- list_delete(pim_ifp->pim_ifchannel_list);
- }
+ if (pim_ifp->sec_addr_list)
+ list_delete(pim_ifp->sec_addr_list);
- if (pim_ifp->pim_ifchannel_hash)
- hash_free(pim_ifp->pim_ifchannel_hash);
+ while ((ch = RB_ROOT(pim_ifchannel_rb,
+ &pim_ifp->ifchannel_rb)) != NULL)
+ pim_ifchannel_delete(ch);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
return 0;
}
+static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
+{
+ XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
+}
+
+static int pim_sec_addr_comp(const void *p1, const void *p2)
+{
+ const struct pim_secondary_addr *sec1 = p1;
+ const struct pim_secondary_addr *sec2 = p2;
+
+ if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
+ return -1;
+
+ if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
+ return 1;
+
+ if (sec1->addr.family == AF_INET) {
+ if (ntohl(sec1->addr.u.prefix4.s_addr)
+ < ntohl(sec2->addr.u.prefix4.s_addr))
+ return -1;
+
+ if (ntohl(sec1->addr.u.prefix4.s_addr)
+ > ntohl(sec2->addr.u.prefix4.s_addr))
+ return 1;
+ } else {
+ return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
+ sizeof(struct in6_addr));
+ }
+
+ return 0;
+}
+
struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
{
struct pim_interface *pim_ifp;
@@ -114,6 +139,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
}
pim_ifp->options = 0;
+ pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
pim_ifp->mroute_vif_index = -1;
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
@@ -144,15 +170,13 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
pim_ifp->igmp_socket_list = NULL;
pim_ifp->pim_neighbor_list = NULL;
pim_ifp->upstream_switch_list = NULL;
- pim_ifp->pim_ifchannel_list = NULL;
- pim_ifp->pim_ifchannel_hash = NULL;
pim_ifp->pim_generation_id = 0;
/* list of struct igmp_sock */
pim_ifp->igmp_socket_list = list_new();
if (!pim_ifp->igmp_socket_list) {
- zlog_err("%s %s: failure: igmp_socket_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: failure: igmp_socket_list=list_new()",
+ __PRETTY_FUNCTION__);
return if_list_clean(pim_ifp);
}
pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
@@ -160,32 +184,32 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
/* list of struct pim_neighbor */
pim_ifp->pim_neighbor_list = list_new();
if (!pim_ifp->pim_neighbor_list) {
- zlog_err("%s %s: failure: pim_neighbor_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: failure: pim_neighbor_list=list_new()",
+ __PRETTY_FUNCTION__);
return if_list_clean(pim_ifp);
}
pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
pim_ifp->upstream_switch_list = list_new();
if (!pim_ifp->upstream_switch_list) {
- zlog_err("%s %s: failure: upstream_switch_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: failure: upstream_switch_list=list_new()",
+ __PRETTY_FUNCTION__);
return if_list_clean(pim_ifp);
}
+ pim_ifp->upstream_switch_list->del =
+ (void (*)(void *))pim_jp_agg_group_list_free;
+ pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
- /* list of struct pim_ifchannel */
- pim_ifp->pim_ifchannel_list = list_new();
- if (!pim_ifp->pim_ifchannel_list) {
- zlog_err("%s %s: failure: pim_ifchannel_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
+ pim_ifp->sec_addr_list = list_new();
+ if (!pim_ifp->sec_addr_list) {
+ zlog_err("%s: failure: secondary addresslist",
+ __PRETTY_FUNCTION__);
}
- pim_ifp->pim_ifchannel_list->del = (void (*)(void *))pim_ifchannel_free;
- pim_ifp->pim_ifchannel_list->cmp =
- (int (*)(void *, void *))pim_ifchannel_compare;
+ pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
+ pim_ifp->sec_addr_list->cmp =
+ (int (*)(void *, void *))pim_sec_addr_comp;
- pim_ifp->pim_ifchannel_hash =
- hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal, NULL);
+ RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
ifp->info = pim_ifp;
@@ -199,6 +223,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
void pim_if_delete(struct interface *ifp)
{
struct pim_interface *pim_ifp;
+ struct pim_ifchannel *ch;
zassert(ifp);
pim_ifp = ifp->info;
@@ -218,9 +243,11 @@ void pim_if_delete(struct interface *ifp)
list_delete(pim_ifp->igmp_socket_list);
list_delete(pim_ifp->pim_neighbor_list);
list_delete(pim_ifp->upstream_switch_list);
- list_delete(pim_ifp->pim_ifchannel_list);
+ list_delete(pim_ifp->sec_addr_list);
- hash_free(pim_ifp->pim_ifchannel_hash);
+ while ((ch = RB_ROOT(pim_ifchannel_rb,
+ &pim_ifp->ifchannel_rb)) != NULL)
+ pim_ifchannel_delete(ch);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
@@ -230,15 +257,12 @@ void pim_if_delete(struct interface *ifp)
void pim_if_update_could_assert(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *node;
- struct listnode *next_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info;
zassert(pim_ifp);
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node,
- ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
pim_ifchannel_update_could_assert(ch);
}
}
@@ -246,15 +270,12 @@ void pim_if_update_could_assert(struct interface *ifp)
static void pim_if_update_my_assert_metric(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *node;
- struct listnode *next_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info;
zassert(pim_ifp);
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node,
- ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
pim_ifchannel_update_my_assert_metric(ch);
}
}
@@ -331,48 +352,12 @@ static int detect_primary_address_change(struct interface *ifp,
return changed;
}
-static int pim_sec_addr_comp(const void *p1, const void *p2)
-{
- const struct pim_secondary_addr *sec1 = p1;
- const struct pim_secondary_addr *sec2 = p2;
-
- if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
- return -1;
-
- if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
- return 1;
-
- if (sec1->addr.family == AF_INET) {
- if (ntohl(sec1->addr.u.prefix4.s_addr)
- < ntohl(sec2->addr.u.prefix4.s_addr))
- return -1;
-
- if (ntohl(sec1->addr.u.prefix4.s_addr)
- > ntohl(sec2->addr.u.prefix4.s_addr))
- return 1;
- } else {
- return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
- sizeof(struct in6_addr));
- }
-
- return 0;
-}
-
-static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
-{
- XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
-}
-
static struct pim_secondary_addr *
pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
{
struct pim_secondary_addr *sec_addr;
struct listnode *node;
- if (!pim_ifp->sec_addr_list) {
- return NULL;
- }
-
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
if (prefix_cmp(&sec_addr->addr, addr)) {
return sec_addr;
@@ -400,22 +385,9 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
return changed;
}
- if (!pim_ifp->sec_addr_list) {
- pim_ifp->sec_addr_list = list_new();
- pim_ifp->sec_addr_list->del =
- (void (*)(void *))pim_sec_addr_free;
- pim_ifp->sec_addr_list->cmp =
- (int (*)(void *, void *))pim_sec_addr_comp;
- }
-
sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
- if (!sec_addr) {
- if (list_isempty(pim_ifp->sec_addr_list)) {
- list_free(pim_ifp->sec_addr_list);
- pim_ifp->sec_addr_list = NULL;
- }
+ if (!sec_addr)
return changed;
- }
changed = 1;
sec_addr->addr = *addr;
@@ -428,15 +400,10 @@ static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
{
int changed = 0;
- if (!pim_ifp->sec_addr_list) {
- return changed;
- }
if (!list_isempty(pim_ifp->sec_addr_list)) {
changed = 1;
/* remove all nodes and free up the list itself */
list_delete_all_node(pim_ifp->sec_addr_list);
- list_free(pim_ifp->sec_addr_list);
- pim_ifp->sec_addr_list = NULL;
}
return changed;
@@ -451,11 +418,9 @@ static int pim_sec_addr_update(struct interface *ifp)
struct pim_secondary_addr *sec_addr;
int changed = 0;
- if (pim_ifp->sec_addr_list) {
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node,
- sec_addr)) {
- sec_addr->flags |= PIM_SEC_ADDRF_STALE;
- }
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node,
+ sec_addr)) {
+ sec_addr->flags |= PIM_SEC_ADDRF_STALE;
}
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
@@ -476,20 +441,12 @@ static int pim_sec_addr_update(struct interface *ifp)
}
}
- if (pim_ifp->sec_addr_list) {
- /* Drop stale entries */
- for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
- sec_addr)) {
- if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
- pim_sec_addr_del(pim_ifp, sec_addr);
- changed = 1;
- }
- }
-
- /* If the list went empty free it up */
- if (list_isempty(pim_ifp->sec_addr_list)) {
- list_free(pim_ifp->sec_addr_list);
- pim_ifp->sec_addr_list = NULL;
+ /* Drop stale entries */
+ for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
+ sec_addr)) {
+ if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
+ pim_sec_addr_del(pim_ifp, sec_addr);
+ changed = 1;
}
}
@@ -596,8 +553,8 @@ void pim_if_addr_add(struct connected *ifc)
detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
- if (ifc->address->family != AF_INET)
- return;
+ // if (ifc->address->family != AF_INET)
+ // return;
if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
struct igmp_sock *igmp;
@@ -607,8 +564,9 @@ void pim_if_addr_add(struct connected *ifc)
ifaddr);
if (!igmp) {
/* if addr new, add IGMP socket */
- pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
- ifp);
+ if (ifc->address->family == AF_INET)
+ pim_igmp_sock_add(pim_ifp->igmp_socket_list,
+ ifaddr, ifp);
}
/* Replay Static IGMP groups */
@@ -675,9 +633,10 @@ void pim_if_addr_add(struct connected *ifc)
rpf.rpf_addr.family = AF_INET;
rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
- pnc = pim_nexthop_cache_find(&rpf);
+ pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
if (pnc)
- pim_sendmsg_zebra_rnh(zclient, pnc,
+ pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
+ pnc,
ZEBRA_NEXTHOP_REGISTER);
}
} /* pim */
@@ -758,9 +717,6 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
ifp = ifc->ifp;
zassert(ifp);
- if (ifc->address->family != AF_INET)
- return;
-
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(ifc->address, buf, BUFSIZ);
@@ -827,7 +783,7 @@ void pim_if_addr_add_all(struct interface *ifp)
}
pim_ifchannel_scan_forward_start(ifp);
- pim_rp_setup();
+ pim_rp_setup(pim_ifp->pim);
pim_rp_check_on_if_add(pim_ifp);
}
@@ -836,6 +792,8 @@ void pim_if_addr_del_all(struct interface *ifp)
struct connected *ifc;
struct listnode *node;
struct listnode *nextnode;
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+ struct pim_instance *pim = vrf->info;
/* PIM/IGMP enabled ? */
if (!ifp->info)
@@ -850,8 +808,8 @@ void pim_if_addr_del_all(struct interface *ifp)
pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
}
- pim_rp_setup();
- pim_i_am_rp_re_evaluate();
+ pim_rp_setup(pim);
+ pim_i_am_rp_re_evaluate(pim);
}
void pim_if_addr_del_all_igmp(struct interface *ifp)
@@ -902,6 +860,7 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
int v4_addrs = 0;
int v6_addrs = 0;
struct pim_interface *pim_ifp = ifp->info;
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
return pim_ifp->update_source;
@@ -938,7 +897,12 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
*/
if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
struct interface *lo_ifp;
- lo_ifp = if_lookup_by_name("lo", VRF_DEFAULT);
+ // DBS - Come back and check here
+ if (ifp->vrf_id == VRF_DEFAULT)
+ lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
+ else
+ lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
+
if (lo_ifp)
return pim_find_primary_addr(lo_ifp);
}
@@ -950,7 +914,10 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
static int pim_iface_next_vif_index(struct interface *ifp)
{
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim = pim_ifp->pim;
int i;
+
/*
* The pimreg vif is always going to be in index 0
* of the table.
@@ -959,7 +926,7 @@ static int pim_iface_next_vif_index(struct interface *ifp)
return 0;
for (i = 1; i < MAXVIFS; i++) {
- if (pim_iface_vif_index[i] == 0)
+ if (pim->iface_vif_index[i] == 0)
return i;
}
return MAXVIFS;
@@ -1021,7 +988,7 @@ int pim_if_add_vif(struct interface *ifp)
return -5;
}
- pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1;
+ pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
return 0;
}
@@ -1036,57 +1003,26 @@ int pim_if_del_vif(struct interface *ifp)
return -1;
}
- pim_mroute_del_vif(pim_ifp->mroute_vif_index);
+ pim_mroute_del_vif(ifp);
/*
Update vif_index
*/
- pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0;
+ pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
pim_ifp->mroute_vif_index = -1;
return 0;
}
-void pim_if_add_vif_all()
-{
- struct listnode *ifnode;
- struct listnode *ifnextnode;
- struct interface *ifp;
-
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
- ifp)) {
- if (!ifp->info)
- continue;
-
- pim_if_add_vif(ifp);
- }
-}
-
-void pim_if_del_vif_all()
+// DBS - VRF Revist
+struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
+ ifindex_t vif_index)
{
struct listnode *ifnode;
- struct listnode *ifnextnode;
struct interface *ifp;
- for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode,
- ifp)) {
- if (!ifp->info)
- continue;
-
- pim_if_del_vif(ifp);
- }
-}
-
-struct interface *pim_if_find_by_vif_index(ifindex_t vif_index)
-{
- struct listnode *ifnode;
- struct interface *ifp;
-
- if (vif_index == 0)
- return if_lookup_by_name("pimreg", VRF_DEFAULT);
-
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
if (ifp->info) {
struct pim_interface *pim_ifp;
pim_ifp = ifp->info;
@@ -1102,12 +1038,12 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index)
/*
pim_if_add_vif() uses ifindex as vif_index
*/
-int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex)
+int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
{
struct pim_interface *pim_ifp;
struct interface *ifp;
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(ifindex, pim->vrf_id);
if (!ifp || !ifp->info)
return -1;
pim_ifp = ifp->info;
@@ -1496,15 +1432,12 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
struct in_addr neigh_addr)
{
struct pim_interface *pim_ifp;
- struct listnode *node;
- struct listnode *next_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info;
zassert(pim_ifp);
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node,
- ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
/* Is (S,G,I) assert loser ? */
if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
continue;
@@ -1518,24 +1451,23 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
void pim_if_update_join_desired(struct pim_interface *pim_ifp)
{
- struct listnode *ch_node;
struct pim_ifchannel *ch;
/* clear off flag from interface's upstreams */
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
ch->upstream->flags);
}
/* scan per-interface (S,G,I) state on this I interface */
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
struct pim_upstream *up = ch->upstream;
if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
continue;
/* update join_desired for the global (S,G) state */
- pim_upstream_update_join_desired(up);
+ pim_upstream_update_join_desired(pim_ifp->pim, up);
PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
}
}
@@ -1543,16 +1475,13 @@ void pim_if_update_join_desired(struct pim_interface *pim_ifp)
void pim_if_update_assert_tracking_desired(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *node;
- struct listnode *next_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info;
if (!pim_ifp)
return;
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node,
- ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
pim_ifchannel_update_assert_tracking_desired(ch);
}
}
@@ -1562,14 +1491,22 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp)
* The pimreg is a special interface that we have that is not
* quite an inteface but a VIF is created for it.
*/
-void pim_if_create_pimreg(void)
+void pim_if_create_pimreg(struct pim_instance *pim)
{
- if (!pim_regiface) {
- pim_regiface =
- if_create("pimreg", strlen("pimreg"), VRF_DEFAULT);
- pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
+ char pimreg_name[100];
+
+ if (!pim->regiface) {
+ if (pim->vrf_id == VRF_DEFAULT)
+ strcpy(pimreg_name, "pimreg");
+ else
+ sprintf(pimreg_name, "pimreg%d",
+ pim->vrf->data.l.table_id);
- pim_if_new(pim_regiface, 0, 0);
+ pim->regiface = if_create(pimreg_name, strlen(pimreg_name),
+ pim->vrf_id);
+ pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
+
+ pim_if_new(pim->regiface, 0, 0);
}
}
@@ -1596,14 +1533,38 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
return 0;
}
-struct interface *pim_if_lookup_address_vrf(struct in_addr src, vrf_id_t vrf_id)
+int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp)
{
- struct listnode *ifnode;
- struct interface *ifp;
+ if (if_is_loopback(ifp))
+ return 1;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
- if (pim_if_connected_to_source(ifp, src) && ifp->info)
- return ifp;
+ if (strcmp(ifp->name, pim->vrf->name) == 0)
+ return 1;
+
+ return 0;
+}
+
+int pim_if_is_vrf_device(struct interface *ifp)
+{
+ struct vrf *vrf;
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (strncmp(ifp->name, vrf->name, strlen(ifp->name)) == 0)
+ return 1;
}
- return NULL;
+
+ return 0;
+}
+
+int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
+{
+ struct pim_ifchannel *ch;
+ int count = 0;
+
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ count++;
+ }
+
+ return count;
}
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index e742e68f67..ed885ff0e3 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -73,6 +73,8 @@ struct pim_secondary_addr {
struct pim_interface {
uint32_t options; /* bit vector */
ifindex_t mroute_vif_index;
+ struct pim_instance *pim;
+
struct in_addr primary_address; /* remember addr to detect change */
struct list *sec_addr_list; /* list of struct pim_secondary_addr */
struct in_addr update_source; /* user can statically set the primary
@@ -104,8 +106,7 @@ struct pim_interface {
uint16_t pim_override_interval_msec; /* config */
struct list *pim_neighbor_list; /* list of struct pim_neighbor */
struct list *upstream_switch_list;
- struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */
- struct hash *pim_ifchannel_hash;
+ struct pim_ifchannel_rb ifchannel_rb;
/* neighbors without lan_delay */
int pim_number_of_nonlandelay_neighbors;
@@ -138,8 +139,6 @@ struct pim_interface {
struct bfd_info *bfd_info;
};
-extern struct interface *pim_regiface;
-extern struct list *pim_ifchannel_list;
/*
if default_holdtime is set (>= 0), use it;
otherwise default_holdtime is 3.5 * hello_period
@@ -149,8 +148,8 @@ extern struct list *pim_ifchannel_list;
? ((pim_ifp)->pim_hello_period * 7 / 2) \
: ((pim_ifp)->pim_default_holdtime))
-void pim_if_init(void);
-void pim_if_terminate(void);
+void pim_if_init(struct pim_instance *pim);
+void pim_if_terminate(struct pim_instance *pim);
struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim);
void pim_if_delete(struct interface *ifp);
@@ -161,16 +160,15 @@ void pim_if_addr_del_all(struct interface *ifp);
void pim_if_addr_del_all_igmp(struct interface *ifp);
void pim_if_addr_del_all_pim(struct interface *ifp);
-struct interface *pim_if_lookup_address_vrf(struct in_addr src,
- vrf_id_t vrf_id);
-
int pim_if_add_vif(struct interface *ifp);
int pim_if_del_vif(struct interface *ifp);
-void pim_if_add_vif_all(void);
-void pim_if_del_vif_all(void);
+void pim_if_add_vif_all(struct pim_instance *pim);
+void pim_if_del_vif_all(struct pim_instance *pim);
-struct interface *pim_if_find_by_vif_index(ifindex_t vif_index);
-int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex);
+struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
+ ifindex_t vif_index);
+int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim,
+ ifindex_t ifindex);
int pim_if_lan_delay_enabled(struct interface *ifp);
uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp);
@@ -201,9 +199,14 @@ void pim_if_update_join_desired(struct pim_interface *pim_ifp);
void pim_if_update_assert_tracking_desired(struct interface *ifp);
-void pim_if_create_pimreg(void);
+void pim_if_create_pimreg(struct pim_instance *pim);
int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
int pim_update_source_set(struct interface *ifp, struct in_addr source);
+int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp);
+
+int pim_if_is_vrf_device(struct interface *ifp);
+
+int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
#endif /* PIM_IFACE_H */
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index d4916518e7..c91efbd8b6 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -43,7 +43,11 @@
#include "pim_upstream.h"
#include "pim_ssm.h"
-int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
+RB_GENERATE(pim_ifchannel_rb, pim_ifchannel,
+ pim_ifp_rb, pim_ifchannel_compare);
+
+int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
+ const struct pim_ifchannel *ch2)
{
struct pim_interface *pim_ifp1;
struct pim_interface *pim_ifp2;
@@ -100,7 +104,6 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
{
struct pim_interface *pim_ifp = ch->interface->info;
struct pim_ifchannel *child;
- struct listnode *ch_node;
// Basic Sanity that we are not being silly
if ((ch->sg.src.s_addr != INADDR_ANY)
@@ -111,8 +114,7 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
&& (ch->sg.grp.s_addr == INADDR_ANY))
return;
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node,
- child)) {
+ RB_FOREACH(child, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
if ((ch->sg.grp.s_addr != INADDR_ANY)
&& (child->sg.grp.s_addr == ch->sg.grp.s_addr)
&& (child != ch)) {
@@ -171,14 +173,14 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
listnode_delete(ch->upstream->ifchannels, ch);
if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) {
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
}
/* upstream is common across ifchannels, check if upstream's
ifchannel list is empty before deleting upstream_del
ref count will take care of it.
*/
- pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__);
+ pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
ch->upstream = NULL;
THREAD_OFF(ch->t_ifjoin_expiry_timer);
@@ -189,14 +191,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
listnode_delete(ch->parent->sources, ch);
ch->parent = NULL;
}
- /*
- notice that listnode_delete() can't be moved
- into pim_ifchannel_free() because the later is
- called by list_delete_all_node()
- */
- listnode_delete(pim_ifp->pim_ifchannel_list, ch);
- hash_release(pim_ifp->pim_ifchannel_hash, ch);
- listnode_delete(pim_ifchannel_list, ch);
+
+ RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: ifchannel entry %s is deleted ",
@@ -208,17 +204,15 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
void pim_ifchannel_delete_all(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *ifchannel_node;
- struct listnode *ifchannel_nextnode;
- struct pim_ifchannel *ifchannel;
+ struct pim_ifchannel *ch;
pim_ifp = ifp->info;
if (!pim_ifp)
return;
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, ifchannel_node,
- ifchannel_nextnode, ifchannel)) {
- pim_ifchannel_delete(ifchannel);
+ while ((ch = RB_ROOT(pim_ifchannel_rb,
+ &pim_ifp->ifchannel_rb)) != NULL) {
+ pim_ifchannel_delete(ch);
}
}
@@ -234,6 +228,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
enum pim_ifjoin_state new_state)
{
enum pim_ifjoin_state old_state = ch->ifjoin_state;
+ struct pim_interface *pim_ifp = ch->interface->info;
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug(
@@ -266,8 +261,6 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
child)) {
struct channel_oil *c_oil =
child->channel_oil;
- struct pim_interface *pim_ifp =
- ch->interface->info;
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
@@ -280,12 +273,12 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
continue;
if (!pim_upstream_evaluate_join_desired(
- child)) {
+ pim_ifp->pim, child)) {
pim_channel_del_oif(
c_oil, ch->interface,
PIM_OIF_FLAG_PROTO_STAR);
pim_upstream_update_join_desired(
- child);
+ pim_ifp->pim, child);
}
/*
@@ -296,9 +289,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
* if channel. So remove it.
* I think this is dead code now. is it?
*/
- if (!ch
- && c_oil->oil.mfcc_ttls
- [pim_ifp->mroute_vif_index])
+ if (c_oil->oil.mfcc_ttls
+ [pim_ifp->mroute_vif_index])
pim_channel_del_oif(
c_oil, ch->interface,
PIM_OIF_FLAG_PROTO_STAR);
@@ -316,13 +308,13 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
up->sg_str);
if (pim_upstream_evaluate_join_desired(
- child)) {
+ pim_ifp->pim, child)) {
pim_channel_add_oif(
child->channel_oil,
ch->interface,
PIM_OIF_FLAG_PROTO_STAR);
pim_upstream_update_join_desired(
- child);
+ pim_ifp->pim, child);
}
}
}
@@ -344,7 +336,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
*/
ch->ifjoin_creation = pim_time_monotonic_sec();
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
pim_ifchannel_update_could_assert(ch);
pim_ifchannel_update_assert_tracking_desired(ch);
}
@@ -426,7 +418,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
}
lookup.sg = *sg;
- ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup);
+ lookup.interface = ifp;
+ ch = RB_FIND(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, &lookup);
return ch;
}
@@ -434,6 +427,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
static void ifmembership_set(struct pim_ifchannel *ch,
enum pim_ifmembership membership)
{
+ struct pim_interface *pim_ifp = ch->interface->info;
+
if (ch->local_ifmembership == membership)
return;
@@ -447,7 +442,7 @@ static void ifmembership_set(struct pim_ifchannel *ch,
ch->local_ifmembership = membership;
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
pim_ifchannel_update_could_assert(ch);
pim_ifchannel_update_assert_tracking_desired(ch);
}
@@ -456,31 +451,25 @@ static void ifmembership_set(struct pim_ifchannel *ch,
void pim_ifchannel_membership_clear(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *ch_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info;
zassert(pim_ifp);
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb)
ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
- }
}
void pim_ifchannel_delete_on_noinfo(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct listnode *node;
- struct listnode *next_node;
- struct pim_ifchannel *ch;
+ struct pim_ifchannel *ch, *ch_tmp;
pim_ifp = ifp->info;
zassert(pim_ifp);
- for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node,
- ch)) {
+ RB_FOREACH_SAFE(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_tmp)
delete_on_noinfo(ch);
- }
}
/*
@@ -509,7 +498,8 @@ static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch)
}
struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
- struct prefix_sg *sg, int flags)
+ struct prefix_sg *sg,
+ uint8_t source_flags, int up_flags)
{
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
@@ -521,26 +511,19 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
pim_ifp = ifp->info;
- up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__);
- if (!up) {
- zlog_err(
- "%s: could not attach upstream (S,G)=%s on interface %s",
- __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
- return NULL;
- }
-
ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch));
if (!ch) {
zlog_warn(
"%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s",
- __PRETTY_FUNCTION__, up->sg_str, ifp->name);
-
- pim_upstream_del(up, __PRETTY_FUNCTION__);
+ __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
return NULL;
}
ch->flags = 0;
- ch->upstream = up;
+ if ((source_flags & PIM_ENCODE_RPT_BIT)
+ && !(source_flags & PIM_ENCODE_WC_BIT))
+ PIM_IF_FLAG_SET_S_G_RPT(ch->flags);
+
ch->interface = ifp;
ch->sg = *sg;
pim_str_sg_set(sg, ch->sg_str);
@@ -560,6 +543,32 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
ch->t_ifjoin_prune_pending_timer = NULL;
ch->ifjoin_creation = 0;
+ RB_INSERT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
+
+ up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags,
+ __PRETTY_FUNCTION__, ch);
+
+ if (!up) {
+ zlog_err(
+ "%s: could not attach upstream (S,G)=%s on interface %s",
+ __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
+
+ pim_ifchannel_remove_children(ch);
+ if (ch->sources)
+ list_delete(ch->sources);
+
+ THREAD_OFF(ch->t_ifjoin_expiry_timer);
+ THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
+ THREAD_OFF(ch->t_ifassert_timer);
+
+ RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
+ XFREE(MTYPE_PIM_IFCHANNEL, ch);
+ return NULL;
+ }
+ ch->upstream = up;
+
+ listnode_add_sort(up->ifchannels, ch);
+
ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch);
ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch);
@@ -579,13 +588,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
else
PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags);
- /* Attach to list */
- listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
- ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
- listnode_add_sort(pim_ifchannel_list, ch);
-
- listnode_add_sort(up->ifchannels, ch);
-
if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__,
ch->sg_str);
@@ -595,7 +597,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)
{
- pim_forward_stop(ch);
+ pim_forward_stop(ch, !ch_del);
pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO);
if (ch_del)
delete_on_noinfo(ch);
@@ -640,7 +642,8 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
*/
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
if (ch->upstream)
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim,
+ ch->upstream);
/*
ch->ifjoin_state transition to NOINFO state
ch_del is set to 0 for not deleteing from here.
@@ -665,9 +668,10 @@ static void check_recv_upstream(int is_join, struct interface *recv_ifp,
uint8_t source_flags, int holdtime)
{
struct pim_upstream *up;
+ struct pim_interface *pim_ifp = recv_ifp->info;
/* Upstream (S,G) in Joined state ? */
- up = pim_upstream_find(sg);
+ up = pim_upstream_find(pim_ifp->pim, sg);
if (!up)
return;
if (up->join_state != PIM_UPSTREAM_JOINED)
@@ -769,7 +773,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
return;
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+ ch = pim_ifchannel_add(ifp, sg, source_flags,
+ PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
if (!ch)
return;
@@ -808,7 +813,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
PIM_IFJOIN_JOIN);
if (pim_macro_chisin_oiflist(ch)) {
- pim_upstream_inherited_olist(ch->upstream);
+ pim_upstream_inherited_olist(pim_ifp->pim,
+ ch->upstream);
pim_forward_start(ch);
}
/*
@@ -822,7 +828,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
__PRETTY_FUNCTION__);
pim_upstream_keep_alive_timer_start(
- ch->upstream, qpim_keep_alive_time);
+ ch->upstream, pim_ifp->pim->keep_alive_time);
}
break;
case PIM_IFJOIN_JOIN:
@@ -910,7 +916,8 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
return;
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+ ch = pim_ifchannel_add(ifp, sg, source_flags,
+ PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
if (!ch)
return;
@@ -942,7 +949,8 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
&ch->t_ifjoin_prune_pending_timer);
thread_add_timer(master, on_ifjoin_expiry_timer, ch,
holdtime, &ch->t_ifjoin_expiry_timer);
- pim_upstream_update_join_desired(ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim,
+ ch->upstream);
}
break;
case PIM_IFJOIN_PRUNE_PENDING:
@@ -999,6 +1007,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
{
struct pim_ifchannel *ch, *starch;
struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
/* PIM enabled on interface? */
pim_ifp = ifp->info;
@@ -1007,9 +1016,11 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
if (!PIM_IF_TEST_PIM(pim_ifp->options))
return 0;
+ pim = pim_ifp->pim;
+
/* skip (*,G) ch creation if G is of type SSM */
if (sg->src.s_addr == INADDR_ANY) {
- if (pim_is_grp_ssm(sg->grp)) {
+ if (pim_is_grp_ssm(pim, sg->grp)) {
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug(
"%s: local membership (S,G)=%s ignored as group is SSM",
@@ -1019,7 +1030,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
}
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
+ ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
if (!ch) {
return 0;
}
@@ -1027,7 +1038,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
if (sg->src.s_addr == INADDR_ANY) {
- struct pim_upstream *up = pim_upstream_find(sg);
+ struct pim_upstream *up = pim_upstream_find(pim, sg);
struct pim_upstream *child;
struct listnode *up_node;
@@ -1045,14 +1056,15 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
child, ch, starch)) {
pim_channel_add_oif(child->channel_oil, ifp,
PIM_OIF_FLAG_PROTO_STAR);
- pim_upstream_switch(child, PIM_UPSTREAM_JOINED);
+ pim_upstream_switch(pim, child,
+ PIM_UPSTREAM_JOINED);
}
}
- if (pimg->spt.switchover == PIM_SPT_INFINITY) {
- if (pimg->spt.plist) {
+ if (pim->spt.switchover == PIM_SPT_INFINITY) {
+ if (pim->spt.plist) {
struct prefix_list *plist = prefix_list_lookup(
- AFI_IP, pimg->spt.plist);
+ AFI_IP, pim->spt.plist);
struct prefix g;
g.family = AF_INET;
g.prefixlen = IPV4_MAX_PREFIXLEN;
@@ -1061,12 +1073,12 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
if (prefix_list_apply(plist, &g)
== PREFIX_DENY) {
pim_channel_add_oif(
- up->channel_oil, pim_regiface,
+ up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
}
}
} else
- pim_channel_add_oif(up->channel_oil, pim_regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
}
@@ -1093,7 +1105,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
if (sg->src.s_addr == INADDR_ANY) {
- struct pim_upstream *up = pim_upstream_find(sg);
+ struct pim_upstream *up = pim_upstream_find(pim_ifp->pim, sg);
struct pim_upstream *child;
struct listnode *up_node, *up_nnode;
@@ -1261,13 +1273,13 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch)
*/
void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
{
+ struct pim_interface *new_pim_ifp = new_ifp->info;
+ struct pim_instance *pim = new_pim_ifp->pim;
struct listnode *ifnode;
struct interface *ifp;
- struct pim_interface *new_pim_ifp = new_ifp->info;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *loop_pim_ifp = ifp->info;
- struct listnode *ch_node;
struct pim_ifchannel *ch;
if (!loop_pim_ifp)
@@ -1276,8 +1288,7 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
if (new_pim_ifp == loop_pim_ifp)
continue;
- for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->pim_ifchannel_list,
- ch_node, ch)) {
+ RB_FOREACH(ch, pim_ifchannel_rb, &loop_pim_ifp->ifchannel_rb) {
if (ch->ifjoin_state == PIM_IFJOIN_JOIN) {
struct pim_upstream *up = ch->upstream;
if ((!up->channel_oil)
@@ -1370,15 +1381,3 @@ unsigned int pim_ifchannel_hash_key(void *arg)
return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
}
-
-int pim_ifchannel_equal(const void *arg1, const void *arg2)
-{
- const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1;
- const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2;
-
- if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr)
- && (ch1->sg.src.s_addr == ch2->sg.src.s_addr))
- return 1;
-
- return 0;
-}
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index 2260fd451b..cef431c30d 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -80,6 +80,8 @@ struct pim_assert_metric {
Per-interface (S,G) state
*/
struct pim_ifchannel {
+ RB_ENTRY(rb_ifchannel) pim_ifp_rb;
+
struct pim_ifchannel *parent;
struct list *sources;
struct prefix_sg sg;
@@ -108,6 +110,10 @@ struct pim_ifchannel {
struct pim_upstream *upstream;
};
+RB_HEAD(pim_ifchannel_rb, pim_ifchannel);
+RB_PROTOTYPE(pim_ifchannel_rb, pim_ifchannel,
+ pim_ifp_rb, pim_ifchannel_compare);
+
void pim_ifchannel_free(struct pim_ifchannel *ch);
void pim_ifchannel_delete(struct pim_ifchannel *ch);
void pim_ifchannel_delete_all(struct interface *ifp);
@@ -116,7 +122,8 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp);
struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
struct prefix_sg *sg);
struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
- struct prefix_sg *sg, int flags);
+ struct prefix_sg *sg, uint8_t ch_flags,
+ int up_flags);
void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
struct in_addr upstream, struct prefix_sg *sg,
uint8_t source_flags, uint16_t holdtime);
@@ -147,8 +154,8 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
uint8_t source_flags, uint8_t join,
uint8_t starg_alone);
-int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
+int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
+ const struct pim_ifchannel *ch2);
unsigned int pim_ifchannel_hash_key(void *arg);
-int pim_ifchannel_equal(const void *arg1, const void *arg2);
#endif /* PIM_IFCHANNEL_H */
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index c693f30ac2..3a870374c0 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -696,7 +696,7 @@ void igmp_startup_mode_on(struct igmp_sock *igmp)
static void igmp_group_free(struct igmp_group *group)
{
- list_free(group->group_source_list);
+ list_delete(group->group_source_list);
XFREE(MTYPE_PIM_IGMP_GROUP, group);
}
@@ -748,7 +748,7 @@ void igmp_sock_free(struct igmp_sock *igmp)
zassert(igmp->igmp_group_list);
zassert(!listcount(igmp->igmp_group_list));
- list_free(igmp->igmp_group_list);
+ list_delete(igmp->igmp_group_list);
hash_free(igmp->igmp_group_hash);
XFREE(MTYPE_PIM_IGMP_SOCKET, igmp);
@@ -812,6 +812,7 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
{
struct pim_interface *pim_ifp;
struct igmp_sock *igmp;
+ char hash_name[64];
pim_ifp = ifp->info;
@@ -836,8 +837,10 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
}
igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free;
- igmp->igmp_group_hash =
- hash_create(igmp_group_hash_key, igmp_group_hash_equal, NULL);
+ snprintf(hash_name, 64, "IGMP %s hash", ifp->name);
+ igmp->igmp_group_hash = hash_create(igmp_group_hash_key,
+ igmp_group_hash_equal,
+ hash_name);
igmp->fd = fd;
igmp->interface = ifp;
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index 880d840eac..1fc7517e05 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -198,6 +198,7 @@ static void igmp_source_timer_on(struct igmp_group *group,
struct igmp_source *source, long interval_msec)
{
source_timer_off(group, source);
+ struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
if (PIM_DEBUG_IGMP_EVENTS) {
char group_str[INET_ADDRSTRLEN];
@@ -220,7 +221,7 @@ static void igmp_source_timer_on(struct igmp_group *group,
Source timer switched from (T == 0) to (T > 0): enable forwarding.
*/
- igmp_source_forward_start(source);
+ igmp_source_forward_start(pim_ifp->pim, source);
}
void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group,
@@ -310,10 +311,12 @@ static void source_clear_send_flag(struct list *source_list)
*/
static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)
{
+ struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
+
zassert(group->group_filtermode_isexcl);
if (listcount(group->group_source_list) < 1) {
- igmp_anysource_forward_start(group);
+ igmp_anysource_forward_start(pim_ifp->pim, group);
}
}
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
new file mode 100644
index 0000000000..7fc77556ec
--- /dev/null
+++ b/pimd/pim_instance.c
@@ -0,0 +1,218 @@
+/*
+ * PIM for FRR - PIM Instance
+ * Copyright (C) 2017 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * 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
+ */
+#include <zebra.h>
+
+#include "hash.h"
+#include "vrf.h"
+
+#include "pimd.h"
+#include "pim_ssm.h"
+#include "pim_rpf.h"
+#include "pim_rp.h"
+#include "pim_mroute.h"
+#include "pim_oil.h"
+#include "pim_static.h"
+#include "pim_ssmpingd.h"
+#include "pim_vty.h"
+
+static void pim_instance_terminate(struct pim_instance *pim)
+{
+ /* Traverse and cleanup rpf_hash */
+ if (pim->rpf_hash) {
+ hash_clean(pim->rpf_hash, (void *)pim_rp_list_hash_clean);
+ hash_free(pim->rpf_hash);
+ pim->rpf_hash = NULL;
+ }
+
+ if (pim->ssm_info) {
+ pim_ssm_terminate(pim->ssm_info);
+ pim->ssm_info = NULL;
+ }
+
+ if (pim->static_routes)
+ list_delete(pim->static_routes);
+
+ pim_rp_free(pim);
+
+ pim_upstream_terminate(pim);
+
+ pim_oil_terminate(pim);
+
+ pim_if_terminate(pim);
+
+ pim_msdp_exit(pim);
+
+ XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
+}
+
+static struct pim_instance *pim_instance_init(struct vrf *vrf)
+{
+ struct pim_instance *pim;
+ char hash_name[64];
+
+ pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance));
+ if (!pim)
+ return NULL;
+
+ pim_if_init(pim);
+
+ pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
+ pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;
+
+
+ pim->vrf_id = vrf->vrf_id;
+ pim->vrf = vrf;
+
+ pim->spt.switchover = PIM_SPT_IMMEDIATE;
+ pim->spt.plist = NULL;
+
+ pim_msdp_init(pim, master);
+
+ snprintf(hash_name, 64, "PIM %s RPF Hash", vrf->name);
+ pim->rpf_hash = hash_create_size(256, pim_rpf_hash_key,
+ pim_rpf_equal, hash_name);
+
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug("%s: NHT rpf hash init ", __PRETTY_FUNCTION__);
+
+ pim->ssm_info = pim_ssm_init();
+ if (!pim->ssm_info) {
+ pim_instance_terminate(pim);
+ return NULL;
+ }
+
+ pim->static_routes = list_new();
+ if (!pim->static_routes) {
+ zlog_err("%s %s: failure: static_routes=list_new()", __FILE__,
+ __PRETTY_FUNCTION__);
+ pim_instance_terminate(pim);
+ return NULL;
+ }
+ pim->static_routes->del = (void (*)(void *))pim_static_route_free;
+
+ pim->send_v6_secondary = 1;
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ pimg = pim;
+
+ pim_rp_init(pim);
+
+ pim_oil_init(pim);
+
+ pim_upstream_init(pim);
+
+ return pim;
+}
+
+struct pim_instance *pim_get_pim_instance(vrf_id_t vrf_id)
+{
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+
+ if (vrf)
+ return vrf->info;
+
+ return NULL;
+}
+
+static int pim_vrf_new(struct vrf *vrf)
+{
+ struct pim_instance *pim = pim_instance_init(vrf);
+
+ zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
+ if (pim == NULL) {
+ zlog_err("%s %s: pim class init failure ", __FILE__,
+ __PRETTY_FUNCTION__);
+ /*
+ * We will crash and burn otherwise
+ */
+ exit(1);
+ }
+
+ vrf->info = (void *)pim;
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ pimg = pim;
+
+ pim_ssmpingd_init(pim);
+ return 0;
+}
+
+static int pim_vrf_delete(struct vrf *vrf)
+{
+ struct pim_instance *pim = vrf->info;
+
+ zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
+
+ pim_ssmpingd_destroy(pim);
+ pim_instance_terminate(pim);
+ return 0;
+}
+
+/*
+ * Code to turn on the pim instance that
+ * we have created with new
+ */
+static int pim_vrf_enable(struct vrf *vrf)
+{
+ struct pim_instance *pim = (struct pim_instance *)vrf->info;
+
+ zlog_debug("%s: for %s", __PRETTY_FUNCTION__, vrf->name);
+
+ pim_mroute_socket_enable(pim);
+
+ return 0;
+}
+
+static int pim_vrf_disable(struct vrf *vrf)
+{
+ /* Note: This is a callback, the VRF will be deleted by the caller. */
+ return 0;
+}
+
+static int pim_vrf_config_write(struct vty *vty)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim || vrf->vrf_id != VRF_DEFAULT) {
+ vty_out(vty, "vrf %s\n", vrf->name);
+ pim_global_config_write_worker(pim, vty);
+ vty_out(vty, "!\n");
+ }
+ }
+
+ return 0;
+}
+
+void pim_vrf_init(void)
+{
+ vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete);
+
+ vrf_cmd_init(pim_vrf_config_write);
+}
+
+void pim_vrf_terminate(void)
+{
+ vrf_terminate();
+}
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
new file mode 100644
index 0000000000..0e91b4ca01
--- /dev/null
+++ b/pimd/pim_instance.h
@@ -0,0 +1,100 @@
+/*
+ * PIM for FRR - PIM Instance
+ * Copyright (C) 2017 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * 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
+ */
+#ifndef __PIM_INSTANCE_H__
+#define __PIM_INSTANCE_H__
+
+#include "pim_str.h"
+#include "pim_msdp.h"
+
+#if defined(HAVE_LINUX_MROUTE_H)
+#include <linux/mroute.h>
+#else
+/*
+ Below: from <linux/mroute.h>
+*/
+
+#ifndef MAXVIFS
+#define MAXVIFS (256)
+#endif
+#endif
+extern struct pim_instance *pimg; // Pim Global Instance
+
+enum pim_spt_switchover {
+ PIM_SPT_IMMEDIATE,
+ PIM_SPT_INFINITY,
+};
+
+/* Per VRF PIM DB */
+struct pim_instance {
+ vrf_id_t vrf_id;
+ struct vrf *vrf;
+
+ struct {
+ enum pim_spt_switchover switchover;
+ char *plist;
+ } spt;
+
+ struct hash *rpf_hash;
+
+ void *ssm_info; /* per-vrf SSM configuration */
+
+ int send_v6_secondary;
+
+ struct thread *thread;
+ int mroute_socket;
+ int64_t mroute_socket_creation;
+ int64_t mroute_add_events;
+ int64_t mroute_add_last;
+ int64_t mroute_del_events;
+ int64_t mroute_del_last;
+
+ struct interface *regiface;
+
+ // List of static routes;
+ struct list *static_routes;
+
+ // Upstream vrf specific information
+ struct list *upstream_list;
+ struct hash *upstream_hash;
+ struct timer_wheel *upstream_sg_wheel;
+
+ struct list *rp_list;
+
+ int iface_vif_index[MAXVIFS];
+
+ struct list *channel_oil_list;
+ struct hash *channel_oil_hash;
+
+ struct pim_msdp msdp;
+
+ struct list *ssmpingd_list;
+ struct in_addr ssmpingd_group_addr;
+
+ unsigned int keep_alive_time;
+ unsigned int rp_keep_alive_time;
+};
+
+void pim_vrf_init(void);
+void pim_vrf_terminate(void);
+
+struct pim_instance *pim_get_pim_instance(vrf_id_t vrf_id);
+
+#endif
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index 9bc5c2d9cc..c60e5a65aa 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -64,9 +64,9 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
zlog_warn(
"%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
__PRETTY_FUNCTION__, pim_str_sg_dump(sg),
- source_flags & PIM_RPT_BIT_MASK,
- source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime,
- neigh_str, ifp->name);
+ !!(source_flags & PIM_RPT_BIT_MASK),
+ !!(source_flags & PIM_WILDCARD_BIT_MASK), up_str,
+ holdtime, neigh_str, ifp->name);
}
pim_ifp = ifp->info;
@@ -80,14 +80,26 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
*/
if ((source_flags & PIM_RPT_BIT_MASK)
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
- struct pim_rpf *rp = RP(sg->grp);
+ struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp);
/*
* If the RP sent in the message is not
* our RP for the group, drop the message
*/
- if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr)
+ if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) {
+ char received_rp[INET_ADDRSTRLEN];
+ char local_rp[INET_ADDRSTRLEN];
+ pim_inet4_dump("<received?>", sg->src, received_rp,
+ sizeof(received_rp));
+ pim_inet4_dump("<local?>", rp->rpf_addr.u.prefix4,
+ local_rp, sizeof(local_rp));
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_warn(
+ "%s: Specified RP(%s) in join is different than our configured RP(%s)",
+ __PRETTY_FUNCTION__, received_rp,
+ local_rp);
return;
+ }
sg->src.s_addr = INADDR_ANY;
}
@@ -124,7 +136,7 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh,
if ((source_flags & PIM_RPT_BIT_MASK)
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
- struct pim_rpf *rp = RP(sg->grp);
+ struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp);
// Ignoring Prune *,G's at the moment.
if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr)
@@ -294,14 +306,20 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
return -8;
}
- sg_ch = pim_ifchannel_find(ifp, &sg);
-
buf += addr_offset;
starg_alone = 0;
recv_prune(ifp, neigh, msg_holdtime,
msg_upstream_addr.u.prefix4, &sg,
msg_source_flags);
+ /*
+ * So if we are receiving a S,G,RPT prune
+ * before we have any data for that S,G
+ * We need to retrieve the sg_ch after
+ * we parse the prune.
+ */
+ sg_ch = pim_ifchannel_find(ifp, &sg);
+
/* Received SG-RPT Prune delete oif from specific S,G */
if (starg_ch && sg_ch
&& (msg_source_flags & PIM_RPT_BIT_MASK)
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index 16d55d7bf7..8e0b4ab5e8 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -108,6 +108,7 @@ void pim_jp_agg_clear_group(struct list *group)
js->up = NULL;
XFREE(MTYPE_PIM_JP_AGG_SOURCE, js);
}
+ list_delete(jag->sources);
jag->sources = NULL;
listnode_delete(group, jag);
XFREE(MTYPE_PIM_JP_AGG_GROUP, jag);
@@ -215,9 +216,11 @@ void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore)
#ifdef PIM_JP_AGG_DEBUG
struct listnode *node;
struct interface *ifp;
+ struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
+ struct pim_instance *pim = pim_ifp->pim;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
- struct pim_interface *pim_ifp = ifp->info;
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
+ pim_ifp = ifp->info;
struct listnode *nnode;
if (ignore && ifp == up->rpf.source_nexthop.interface)
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index b8e6d8ad3d..c4cab25ae9 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -40,6 +40,7 @@
#include "libfrr.h"
#include "pimd.h"
+#include "pim_instance.h"
#include "pim_version.h"
#include "pim_signals.h"
#include "pim_zebra.h"
@@ -115,7 +116,6 @@ int main(int argc, char **argv, char **envp)
pim_route_map_init();
pim_init();
- pim_msdp_init(master);
/*
* Initialize zclient "update" and "lookup" sockets
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index a92b01ca00..52d240f54b 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -24,6 +24,7 @@
#include "prefix.h"
#include "vty.h"
#include "plist.h"
+#include "sockopt.h"
#include "pimd.h"
#include "pim_rpf.h"
@@ -39,49 +40,82 @@
#include "pim_ifchannel.h"
#include "pim_zlookup.h"
#include "pim_ssm.h"
+#include "pim_sock.h"
-/* GLOBAL VARS */
-static struct thread *qpim_mroute_socket_reader = NULL;
+static void mroute_read_on(struct pim_instance *pim);
-static void mroute_read_on(void);
-
-static int pim_mroute_set(int fd, int enable)
+static int pim_mroute_set(struct pim_instance *pim, int enable)
{
int err;
- int opt = enable ? MRT_INIT : MRT_DONE;
+ int opt;
socklen_t opt_len = sizeof(opt);
- int rcvbuf = 1024 * 1024 * 8;
long flags;
- err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len);
+ /*
+ * We need to create the VRF table for the pim mroute_socket
+ */
+ if (pim->vrf_id != VRF_DEFAULT) {
+ if (pimd_privs.change(ZPRIVS_RAISE))
+ zlog_err(
+ "pim_mroute_socket_enable: could not raise privs, %s",
+ safe_strerror(errno));
+
+ opt = pim->vrf->data.l.table_id;
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_TABLE,
+ &opt, opt_len);
+ if (err) {
+ zlog_warn(
+ "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s",
+ __FILE__, __PRETTY_FUNCTION__,
+ pim->mroute_socket, opt, errno,
+ safe_strerror(errno));
+ return -1;
+ }
+
+ if (pimd_privs.change(ZPRIVS_LOWER))
+ zlog_err(
+ "pim_mroute_socket_enable: could not lower privs, %s",
+ safe_strerror(errno));
+ }
+
+ opt = enable ? MRT_INIT : MRT_DONE;
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &opt, opt_len);
if (err) {
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
- __FILE__, __PRETTY_FUNCTION__, fd,
+ __FILE__, __PRETTY_FUNCTION__, pim->mroute_socket,
enable ? "MRT_INIT" : "MRT_DONE", opt, errno,
safe_strerror(errno));
return -1;
}
- err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
- if (err) {
- zlog_warn(
- "%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s",
- __PRETTY_FUNCTION__, fd, rcvbuf, errno,
- safe_strerror(errno));
+#if defined(HAVE_IP_PKTINFO)
+ if (enable) {
+ /* Linux and Solaris IP_PKTINFO */
+ opt = 1;
+ if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO, &opt,
+ sizeof(opt))) {
+ zlog_warn(
+ "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
+ pim->mroute_socket, errno,
+ safe_strerror(errno));
+ }
}
+#endif
+
+ setsockopt_so_recvbuf(pim->mroute_socket, 1024 * 1024 * 8);
- flags = fcntl(fd, F_GETFL, 0);
+ flags = fcntl(pim->mroute_socket, F_GETFL, 0);
if (flags < 0) {
- zlog_warn("Could not get flags on socket fd:%d %d %s", fd,
- errno, safe_strerror(errno));
- close(fd);
+ zlog_warn("Could not get flags on socket fd:%d %d %s",
+ pim->mroute_socket, errno, safe_strerror(errno));
+ close(pim->mroute_socket);
return -1;
}
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
- zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", fd,
- errno, safe_strerror(errno));
- close(fd);
+ if (fcntl(pim->mroute_socket, F_SETFL, flags | O_NONBLOCK)) {
+ zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s",
+ pim->mroute_socket, errno, safe_strerror(errno));
+ close(pim->mroute_socket);
return -1;
}
@@ -90,7 +124,7 @@ static int pim_mroute_set(int fd, int enable)
int upcalls = IGMPMSG_WRVIFWHOLE;
opt = MRT_PIM;
- err = setsockopt(fd, IPPROTO_IP, opt, &upcalls,
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &upcalls,
sizeof(upcalls));
if (err) {
zlog_warn(
@@ -118,7 +152,7 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
struct pim_rpf *rpg;
struct prefix_sg sg;
- rpg = RP(msg->im_dst);
+ rpg = RP(pim_ifp->pim, msg->im_dst);
/*
* If the incoming interface is unknown OR
* the Interface type is SSM we don't need to
@@ -170,7 +204,7 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
}
PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim_ifp->pim->keep_alive_time);
up->channel_oil->cc.pktcnt++;
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
@@ -178,6 +212,7 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
int vif_index = 0;
vif_index = pim_if_find_vifindex_by_ifindex(
+ pim_ifp->pim,
up->rpf.source_nexthop.interface->ifindex);
up->channel_oil->oil.mfcc_parent = vif_index;
}
@@ -195,23 +230,25 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
const struct ip *ip_hdr;
struct pim_upstream *up;
+ pim_ifp = ifp->info;
+
ip_hdr = (const struct ip *)buf;
memset(&sg, 0, sizeof(struct prefix_sg));
sg.src = ip_hdr->ip_src;
sg.grp = ip_hdr->ip_dst;
- up = pim_upstream_find(&sg);
+ up = pim_upstream_find(pim_ifp->pim, &sg);
if (!up) {
struct prefix_sg star = sg;
star.src.s_addr = INADDR_ANY;
- up = pim_upstream_find(&star);
+ up = pim_upstream_find(pim_ifp->pim, &star);
if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) {
- up = pim_upstream_add(&sg, ifp,
+ up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
- __PRETTY_FUNCTION__);
+ __PRETTY_FUNCTION__, NULL);
if (!up) {
if (PIM_DEBUG_MROUTE)
zlog_debug(
@@ -221,9 +258,10 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
return 0;
}
pim_upstream_keep_alive_timer_start(
- up, qpim_keep_alive_time);
- pim_upstream_inherited_olist(up);
- pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+ up, pim_ifp->pim->keep_alive_time);
+ pim_upstream_inherited_olist(pim_ifp->pim, up);
+ pim_upstream_switch(pim_ifp->pim, up,
+ PIM_UPSTREAM_JOINED);
if (PIM_DEBUG_MROUTE)
zlog_debug("%s: Creating %s upstream on LHR",
@@ -240,7 +278,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
pim_ifp = up->rpf.source_nexthop.interface->info;
- rpg = RP(sg.grp);
+ rpg = RP(pim_ifp->pim, sg.grp);
if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
|| (!(PIM_I_am_DR(pim_ifp)))) {
@@ -255,7 +293,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
* If we've received a register suppress
*/
if (!up->t_rs_timer) {
- if (pim_is_grp_ssm(sg.grp)) {
+ if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) {
if (PIM_DEBUG_PIM_REG)
zlog_debug(
"%s register forward skipped as group is SSM",
@@ -386,6 +424,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
struct prefix_sg sg;
struct channel_oil *oil;
+ pim_ifp = ifp->info;
+
memset(&sg, 0, sizeof(struct prefix_sg));
sg.src = ip_hdr->ip_src;
sg.grp = ip_hdr->ip_dst;
@@ -412,11 +452,11 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
}
#endif
- up = pim_upstream_find(&sg);
+ up = pim_upstream_find(pim_ifp->pim, &sg);
if (up) {
struct pim_upstream *parent;
struct pim_nexthop source;
- struct pim_rpf *rpf = RP(sg.grp);
+ struct pim_rpf *rpf = RP(pim_ifp->pim, sg.grp);
if (!rpf || !rpf->source_nexthop.interface)
return 0;
@@ -426,7 +466,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
* tree, let's check and if so we can safely drop
* it.
*/
- parent = pim_upstream_find(&star_g);
+ parent = pim_upstream_find(pim_ifp->pim, &star_g);
if (parent && parent->rpf.source_nexthop.interface == ifp)
return 0;
@@ -439,23 +479,25 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
*/
if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
// No if channel, but upstream we are at the RP.
- if (pim_nexthop_lookup(&source, up->upstream_register,
- 0)
- == 0)
+ if (pim_nexthop_lookup(pim_ifp->pim, &source,
+ up->upstream_register, 0)
+ == 0) {
pim_register_stop_send(source.interface, &sg,
pim_ifp->primary_address,
up->upstream_register);
+ up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
+ }
if (!up->channel_oil)
up->channel_oil = pim_channel_oil_add(
- &sg, pim_ifp->mroute_vif_index);
- pim_upstream_inherited_olist(up);
+ pim_ifp->pim, &sg,
+ pim_ifp->mroute_vif_index);
+ pim_upstream_inherited_olist(pim_ifp->pim, up);
if (!up->channel_oil->installed)
pim_mroute_add(up->channel_oil,
__PRETTY_FUNCTION__);
- pim_upstream_set_sptbit(up, ifp);
} else {
- if (I_am_RP(up->sg.grp)) {
- if (pim_nexthop_lookup(&source,
+ if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
+ if (pim_nexthop_lookup(pim_ifp->pim, &source,
up->upstream_register, 0)
== 0)
pim_register_stop_send(
@@ -465,20 +507,21 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
}
pim_upstream_keep_alive_timer_start(
- up, qpim_keep_alive_time);
- pim_upstream_inherited_olist(up);
+ up, pim_ifp->pim->keep_alive_time);
+ pim_upstream_inherited_olist(pim_ifp->pim, up);
pim_mroute_msg_wholepkt(fd, ifp, buf);
}
return 0;
}
pim_ifp = ifp->info;
- oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index);
+ oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index);
if (!oil->installed)
pim_mroute_add(oil, __PRETTY_FUNCTION__);
if (pim_if_connected_to_source(ifp, sg.src)) {
- up = pim_upstream_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR,
- __PRETTY_FUNCTION__);
+ up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
+ PIM_UPSTREAM_FLAG_MASK_FHR,
+ __PRETTY_FUNCTION__, NULL);
if (!up) {
if (PIM_DEBUG_MROUTE)
zlog_debug(
@@ -487,11 +530,11 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
return -2;
}
PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim_ifp->pim->keep_alive_time);
up->channel_oil = oil;
up->channel_oil->cc.pktcnt++;
pim_register_join(up);
- pim_upstream_inherited_olist(up);
+ pim_upstream_inherited_olist(pim_ifp->pim, up);
// Send the packet to the RP
pim_mroute_msg_wholepkt(fd, ifp, buf);
@@ -500,7 +543,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
return 0;
}
-int pim_mroute_msg(int fd, const char *buf, int buf_size)
+static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
+ int buf_size, ifindex_t ifindex)
{
struct interface *ifp;
struct pim_interface *pim_ifp;
@@ -523,22 +567,11 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
* the source
* of the IP packet.
*/
- ifp = pim_if_lookup_address_vrf(ip_hdr->ip_src, VRF_DEFAULT);
-
- if (!ifp) {
- if (PIM_DEBUG_MROUTE_DETAIL) {
- pim_inet4_dump("<src?>", ip_hdr->ip_src,
- ip_src_str, sizeof(ip_src_str));
- pim_inet4_dump("<dst?>", ip_hdr->ip_dst,
- ip_dst_str, sizeof(ip_dst_str));
+ ifp = if_lookup_by_index(ifindex, pim->vrf_id);
- zlog_warn(
- "%s: igmp kernel upcall could not find usable interface for %s -> %s",
- __PRETTY_FUNCTION__, ip_src_str,
- ip_dst_str);
- }
+ if (!ifp || !ifp->info)
return 0;
- }
+
pim_ifp = ifp->info;
ifaddr = pim_find_primary_addr(ifp);
igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
@@ -551,9 +584,9 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
sizeof(ip_dst_str));
zlog_warn(
- "%s: igmp kernel upcall on %s(%p) for %s -> %s",
- __PRETTY_FUNCTION__, ifp->name, igmp,
- ip_src_str, ip_dst_str);
+ "%s(%s): igmp kernel upcall on %s(%p) for %s -> %s",
+ __PRETTY_FUNCTION__, pim->vrf->name, ifp->name,
+ igmp, ip_src_str, ip_dst_str);
}
if (igmp)
pim_igmp_packet(igmp, (char *)buf, buf_size);
@@ -573,7 +606,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
} else {
msg = (const struct igmpmsg *)buf;
- ifp = pim_if_find_by_vif_index(msg->im_vif);
+ ifp = pim_if_find_by_vif_index(pim, msg->im_vif);
if (!ifp)
return 0;
@@ -586,24 +619,27 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
"%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d",
__PRETTY_FUNCTION__,
igmpmsgtype2str[msg->im_msgtype],
- msg->im_msgtype, ip_hdr->ip_p, fd, src_str,
- grp_str, ifp->name, msg->im_vif, buf_size);
+ msg->im_msgtype, ip_hdr->ip_p,
+ pim->mroute_socket, src_str, grp_str, ifp->name,
+ msg->im_vif, buf_size);
}
switch (msg->im_msgtype) {
case IGMPMSG_WRONGVIF:
- return pim_mroute_msg_wrongvif(fd, ifp, msg);
+ return pim_mroute_msg_wrongvif(pim->mroute_socket, ifp,
+ msg);
break;
case IGMPMSG_NOCACHE:
- return pim_mroute_msg_nocache(fd, ifp, msg);
+ return pim_mroute_msg_nocache(pim->mroute_socket, ifp,
+ msg);
break;
case IGMPMSG_WHOLEPKT:
- return pim_mroute_msg_wholepkt(fd, ifp,
+ return pim_mroute_msg_wholepkt(pim->mroute_socket, ifp,
(const char *)msg);
break;
case IGMPMSG_WRVIFWHOLE:
- return pim_mroute_msg_wrvifwhole(fd, ifp,
- (const char *)msg);
+ return pim_mroute_msg_wrvifwhole(
+ pim->mroute_socket, ifp, (const char *)msg);
break;
default:
break;
@@ -615,18 +651,20 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size)
static int mroute_read(struct thread *t)
{
+ struct pim_instance *pim;
static long long count;
char buf[10000];
int result = 0;
int cont = 1;
- int fd;
int rd;
-
- fd = THREAD_FD(t);
+ ifindex_t ifindex;
+ pim = THREAD_ARG(t);
while (cont) {
- rd = read(fd, buf, sizeof(buf));
- if (rd < 0) {
+ rd = pim_socket_recvfromto(pim->mroute_socket, (uint8_t *)buf,
+ sizeof(buf), NULL, NULL, NULL, NULL,
+ &ifindex);
+ if (rd <= 0) {
if (errno == EINTR)
continue;
if (errno == EWOULDBLOCK || errno == EAGAIN)
@@ -634,13 +672,14 @@ static int mroute_read(struct thread *t)
if (PIM_DEBUG_MROUTE)
zlog_warn(
- "%s: failure reading fd=%d: errno=%d: %s",
- __PRETTY_FUNCTION__, fd, errno,
+ "%s: failure reading rd=%d: fd=%d: errno=%d: %s",
+ __PRETTY_FUNCTION__, rd,
+ pim->mroute_socket, errno,
safe_strerror(errno));
goto done;
}
- result = pim_mroute_msg(fd, buf, rd);
+ result = pim_mroute_msg(pim, buf, rd, ifindex);
count++;
if (count % qpim_packet_process == 0)
@@ -648,23 +687,23 @@ static int mroute_read(struct thread *t)
}
/* Keep reading */
done:
- mroute_read_on();
+ mroute_read_on(pim);
return result;
}
-static void mroute_read_on()
+static void mroute_read_on(struct pim_instance *pim)
{
- thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd,
- &qpim_mroute_socket_reader);
+ thread_add_read(master, mroute_read, pim, pim->mroute_socket,
+ &pim->thread);
}
-static void mroute_read_off()
+static void mroute_read_off(struct pim_instance *pim)
{
- THREAD_OFF(qpim_mroute_socket_reader);
+ THREAD_OFF(pim->thread);
}
-int pim_mroute_socket_enable()
+int pim_mroute_socket_enable(struct pim_instance *pim)
{
int fd;
@@ -674,6 +713,11 @@ int pim_mroute_socket_enable()
fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
+#ifdef SO_BINDTODEVICE
+ setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, pim->vrf->name,
+ strlen(pim->vrf->name));
+#endif
+
if (pimd_privs.change(ZPRIVS_LOWER))
zlog_err("pim_mroute_socket_enable: could not lower privs, %s",
safe_strerror(errno));
@@ -684,39 +728,40 @@ int pim_mroute_socket_enable()
return -2;
}
- if (pim_mroute_set(fd, 1)) {
+ pim->mroute_socket = fd;
+ if (pim_mroute_set(pim, 1)) {
zlog_warn(
"Could not enable mroute on socket fd=%d: errno=%d: %s",
fd, errno, safe_strerror(errno));
close(fd);
+ pim->mroute_socket = -1;
return -3;
}
- qpim_mroute_socket_fd = fd;
+ pim->mroute_socket_creation = pim_time_monotonic_sec();
- qpim_mroute_socket_creation = pim_time_monotonic_sec();
- mroute_read_on();
+ mroute_read_on(pim);
return 0;
}
-int pim_mroute_socket_disable()
+int pim_mroute_socket_disable(struct pim_instance *pim)
{
- if (pim_mroute_set(qpim_mroute_socket_fd, 0)) {
+ if (pim_mroute_set(pim, 0)) {
zlog_warn(
"Could not disable mroute on socket fd=%d: errno=%d: %s",
- qpim_mroute_socket_fd, errno, safe_strerror(errno));
+ pim->mroute_socket, errno, safe_strerror(errno));
return -2;
}
- if (close(qpim_mroute_socket_fd)) {
+ if (close(pim->mroute_socket)) {
zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s",
- qpim_mroute_socket_fd, errno, safe_strerror(errno));
+ pim->mroute_socket, errno, safe_strerror(errno));
return -3;
}
- mroute_read_off();
- qpim_mroute_socket_fd = -1;
+ mroute_read_off(pim);
+ pim->mroute_socket = -1;
return 0;
}
@@ -733,6 +778,11 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr,
struct vifctl vc;
int err;
+ if (PIM_DEBUG_MROUTE)
+ zlog_debug("%s: Add Vif %d (%s[%s])", __PRETTY_FUNCTION__,
+ pim_ifp->mroute_vif_index,
+ ifp->name, pim_ifp->pim->vrf->name);
+
memset(&vc, 0, sizeof(vc));
vc.vifc_vifi = pim_ifp->mroute_vif_index;
#ifdef VIFF_USE_IFINDEX
@@ -757,7 +807,7 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr,
}
#endif
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF,
+ err = setsockopt(pim_ifp->pim->mroute_socket, IPPROTO_IP, MRT_ADD_VIF,
(void *)&vc, sizeof(vc));
if (err) {
char ifaddr_str[INET_ADDRSTRLEN];
@@ -766,38 +816,38 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr,
sizeof(ifaddr_str));
zlog_warn(
- "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s",
- __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd,
- ifp->ifindex, ifaddr_str, flags, errno,
- safe_strerror(errno));
+ "%s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s",
+ __PRETTY_FUNCTION__,
+ pim_ifp->pim->mroute_socket, ifp->ifindex, ifaddr_str,
+ flags, errno, safe_strerror(errno));
return -2;
}
return 0;
}
-int pim_mroute_del_vif(int vif_index)
+int pim_mroute_del_vif(struct interface *ifp)
{
+ struct pim_interface *pim_ifp = ifp->info;
struct vifctl vc;
int err;
- if (PIM_DEBUG_MROUTE) {
- struct interface *ifp = pim_if_find_by_vif_index(vif_index);
- zlog_debug("%s %s: Del Vif %d (%s) ", __FILE__,
- __PRETTY_FUNCTION__, vif_index,
- ifp ? ifp->name : "NULL");
- }
+ if (PIM_DEBUG_MROUTE)
+ zlog_debug("%s: Del Vif %d (%s[%s])", __PRETTY_FUNCTION__,
+ pim_ifp->mroute_vif_index,
+ ifp->name, pim_ifp->pim->vrf->name);
memset(&vc, 0, sizeof(vc));
- vc.vifc_vifi = vif_index;
+ vc.vifc_vifi = pim_ifp->mroute_vif_index;
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF,
+ err = setsockopt(pim_ifp->pim->mroute_socket, IPPROTO_IP, MRT_DEL_VIF,
(void *)&vc, sizeof(vc));
if (err) {
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s",
- __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd,
- vif_index, errno, safe_strerror(errno));
+ __FILE__, __PRETTY_FUNCTION__,
+ pim_ifp->pim->mroute_socket, pim_ifp->mroute_vif_index,
+ errno, safe_strerror(errno));
return -2;
}
@@ -806,12 +856,13 @@ int pim_mroute_del_vif(int vif_index)
int pim_mroute_add(struct channel_oil *c_oil, const char *name)
{
+ struct pim_instance *pim = c_oil->pim;
int err;
int orig = 0;
int orig_iif_vif = 0;
- qpim_mroute_add_last = pim_time_monotonic_sec();
- ++qpim_mroute_add_events;
+ pim->mroute_add_last = pim_time_monotonic_sec();
+ ++pim->mroute_add_events;
/* Do not install route if incoming interface is undefined. */
if (c_oil->oil.mfcc_parent >= MAXVIFS) {
@@ -846,14 +897,14 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
orig_iif_vif = c_oil->oil.mfcc_parent;
c_oil->oil.mfcc_parent = 0;
}
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC,
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC,
&c_oil->oil, sizeof(c_oil->oil));
if (!err && !c_oil->installed
&& c_oil->oil.mfcc_origin.s_addr != INADDR_ANY
&& orig_iif_vif != 0) {
c_oil->oil.mfcc_parent = orig_iif_vif;
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC,
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC,
&c_oil->oil, sizeof(c_oil->oil));
}
@@ -863,14 +914,15 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
if (err) {
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s",
- __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd,
+ __FILE__, __PRETTY_FUNCTION__, pim->mroute_socket,
errno, safe_strerror(errno));
return -2;
}
if (PIM_DEBUG_MROUTE) {
char buf[1000];
- zlog_debug("%s(%s), Added Route: %s", __PRETTY_FUNCTION__, name,
+ zlog_debug("%s(%s), vrf %s Added Route: %s", __PRETTY_FUNCTION__, name,
+ pim->vrf->name,
pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
}
@@ -880,10 +932,11 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
int pim_mroute_del(struct channel_oil *c_oil, const char *name)
{
+ struct pim_instance *pim = c_oil->pim;
int err;
- qpim_mroute_del_last = pim_time_monotonic_sec();
- ++qpim_mroute_del_events;
+ pim->mroute_del_last = pim_time_monotonic_sec();
+ ++pim->mroute_del_events;
if (!c_oil->installed) {
if (PIM_DEBUG_MROUTE) {
@@ -897,22 +950,23 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name)
return -2;
}
- err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC,
+ err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_DEL_MFC,
&c_oil->oil, sizeof(c_oil->oil));
if (err) {
if (PIM_DEBUG_MROUTE)
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s",
__FILE__, __PRETTY_FUNCTION__,
- qpim_mroute_socket_fd, errno,
+ pim->mroute_socket, errno,
safe_strerror(errno));
return -2;
}
if (PIM_DEBUG_MROUTE) {
char buf[1000];
- zlog_debug("%s(%s), Deleted Route: %s", __PRETTY_FUNCTION__,
- name, pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
+ zlog_debug("%s(%s), vrf %s Deleted Route: %s", __PRETTY_FUNCTION__,
+ name, pim->vrf->name,
+ pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
}
// Reset kernel installed flag
@@ -923,6 +977,7 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name)
void pim_mroute_update_counters(struct channel_oil *c_oil)
{
+ struct pim_instance *pim = c_oil->pim;
struct sioc_sg_req sgreq;
c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
@@ -930,7 +985,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
c_oil->cc.oldwrong_if = c_oil->cc.wrong_if;
if (!c_oil->installed) {
- c_oil->cc.lastused = 100 * qpim_keep_alive_time;
+ c_oil->cc.lastused = 100 * pim->keep_alive_time;
if (PIM_DEBUG_MROUTE) {
struct prefix_sg sg;
@@ -949,7 +1004,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
sgreq.grp = c_oil->oil.mfcc_mcastgrp;
pim_zlookup_sg_statistics(c_oil);
- if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
+ if (ioctl(pim->mroute_socket, SIOCGETSGCNT, &sgreq)) {
if (PIM_DEBUG_MROUTE) {
struct prefix_sg sg;
diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h
index eb6c40b676..bd71acbf82 100644
--- a/pimd/pim_mroute.h
+++ b/pimd/pim_mroute.h
@@ -67,6 +67,10 @@
#define MRT_PIM (MRT_BASE+8) /* enable PIM code */
#endif
+#ifndef MRT_TABLE
+#define MRT_TABLE (209) /* Specify mroute table ID */
+#endif
+
#ifndef HAVE_VIFI_T
typedef unsigned short vifi_t;
#endif
@@ -163,17 +167,15 @@ struct igmpmsg {
Above: from <linux/mroute.h>
*/
-int pim_mroute_socket_enable(void);
-int pim_mroute_socket_disable(void);
+int pim_mroute_socket_enable(struct pim_instance *pim);
+int pim_mroute_socket_disable(struct pim_instance *pim);
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_del_vif(struct interface *ifp);
int pim_mroute_add(struct channel_oil *c_oil, const char *name);
int pim_mroute_del(struct channel_oil *c_oil, const char *name);
-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_msdp.c b/pimd/pim_msdp.c
index 0f653e70a4..4b049d90ad 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -37,12 +37,13 @@
#include "pim_str.h"
#include "pim_time.h"
#include "pim_upstream.h"
+#include "pim_oil.h"
#include "pim_msdp.h"
#include "pim_msdp_packet.h"
#include "pim_msdp_socket.h"
-struct pim_msdp pim_msdp, *msdp = &pim_msdp;
+// struct pim_msdp pim_msdp, *msdp = &pim_msdp;
static void pim_msdp_peer_listen(struct pim_msdp_peer *mp);
static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start);
@@ -50,8 +51,8 @@ static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start);
static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp,
bool start);
static void pim_msdp_peer_free(struct pim_msdp_peer *mp);
-static void pim_msdp_enable(void);
-static void pim_msdp_sa_adv_timer_setup(bool start);
+static void pim_msdp_enable(struct pim_instance *pim);
+static void pim_msdp_sa_adv_timer_setup(struct pim_instance *pim, bool start);
static void pim_msdp_sa_deref(struct pim_msdp_sa *sa,
enum pim_msdp_sa_flags flags);
static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2);
@@ -69,21 +70,23 @@ static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa,
/* RFC-3618:Sec-5.1 - global active source advertisement timer */
static int pim_msdp_sa_adv_timer_cb(struct thread *t)
{
+ struct pim_instance *pim = THREAD_ARG(t);
+
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP SA advertisment timer expired");
}
- pim_msdp_sa_adv_timer_setup(true /* start */);
- pim_msdp_pkt_sa_tx();
+ pim_msdp_sa_adv_timer_setup(pim, true /* start */);
+ pim_msdp_pkt_sa_tx(pim);
return 0;
}
-static void pim_msdp_sa_adv_timer_setup(bool start)
+static void pim_msdp_sa_adv_timer_setup(struct pim_instance *pim, bool start)
{
- THREAD_OFF(msdp->sa_adv_timer);
+ THREAD_OFF(pim->msdp.sa_adv_timer);
if (start) {
- thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL,
- PIM_MSDP_SA_ADVERTISMENT_TIME,
- &msdp->sa_adv_timer);
+ thread_add_timer(pim->msdp.master, pim_msdp_sa_adv_timer_cb,
+ pim, PIM_MSDP_SA_ADVERTISMENT_TIME,
+ &pim->msdp.sa_adv_timer);
}
}
@@ -105,7 +108,8 @@ static void pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start)
{
THREAD_OFF(sa->sa_state_timer);
if (start) {
- thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa,
+ thread_add_timer(sa->pim->msdp.master,
+ pim_msdp_sa_state_timer_cb, sa,
PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer);
}
}
@@ -121,7 +125,7 @@ static void pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa)
if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) {
PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags);
sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG;
- pim_upstream_del(up, __PRETTY_FUNCTION__);
+ pim_upstream_del(sa->pim, up, __PRETTY_FUNCTION__);
sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG;
}
@@ -138,7 +142,7 @@ static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa,
return false;
}
/* check if we are RP */
- if (!I_am_RP(sa->sg.grp)) {
+ if (!I_am_RP(sa->pim, sa->sg.grp)) {
return false;
}
@@ -149,7 +153,7 @@ static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa,
memset(&sg, 0, sizeof(sg));
sg.grp = sa->sg.grp;
- xg_up = pim_upstream_find(&sg);
+ xg_up = pim_upstream_find(sa->pim, &sg);
}
if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) {
/* join desired will be true for such (*, G) entries so we will
@@ -186,7 +190,7 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
return;
}
- up = pim_upstream_find(&sa->sg);
+ up = pim_upstream_find(sa->pim, &sa->sg);
if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) {
/* somehow we lost track of the upstream ptr? best log it */
sa->up = up;
@@ -199,14 +203,14 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
/* RFC3618: "RP triggers a (S, G) join event towards the data source
* as if a JP message was rxed addressed to the RP itself." */
- up = pim_upstream_add(&sa->sg, NULL /* iif */,
+ up = pim_upstream_add(sa->pim, &sa->sg, NULL /* iif */,
PIM_UPSTREAM_FLAG_MASK_SRC_MSDP,
- __PRETTY_FUNCTION__);
+ __PRETTY_FUNCTION__, NULL);
sa->up = up;
if (up) {
/* update inherited oil */
- pim_upstream_inherited_olist(up);
+ pim_upstream_inherited_olist(sa->pim, up);
/* should we also start the kat in parallel? we will need it
* when the
* SA ages out */
@@ -227,7 +231,8 @@ static void pim_msdp_sa_free(struct pim_msdp_sa *sa)
XFREE(MTYPE_PIM_MSDP_SA, sa);
}
-static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg,
+static struct pim_msdp_sa *pim_msdp_sa_new(struct pim_instance *pim,
+ struct prefix_sg *sg,
struct in_addr rp)
{
struct pim_msdp_sa *sa;
@@ -239,19 +244,20 @@ static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg,
return NULL;
}
+ sa->pim = pim;
sa->sg = *sg;
pim_str_sg_set(sg, sa->sg_str);
sa->rp = rp;
sa->uptime = pim_time_monotonic_sec();
/* insert into misc tables for easy access */
- sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern);
+ sa = hash_get(pim->msdp.sa_hash, sa, hash_alloc_intern);
if (!sa) {
zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__);
pim_msdp_sa_free(sa);
return NULL;
}
- listnode_add_sort(msdp->sa_list, sa);
+ listnode_add_sort(pim->msdp.sa_list, sa);
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP SA %s created", sa->sg_str);
@@ -260,25 +266,27 @@ static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg,
return sa;
}
-static struct pim_msdp_sa *pim_msdp_sa_find(struct prefix_sg *sg)
+static struct pim_msdp_sa *pim_msdp_sa_find(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
struct pim_msdp_sa lookup;
lookup.sg = *sg;
- return hash_lookup(msdp->sa_hash, &lookup);
+ return hash_lookup(pim->msdp.sa_hash, &lookup);
}
-static struct pim_msdp_sa *pim_msdp_sa_add(struct prefix_sg *sg,
+static struct pim_msdp_sa *pim_msdp_sa_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
struct in_addr rp)
{
struct pim_msdp_sa *sa;
- sa = pim_msdp_sa_find(sg);
+ sa = pim_msdp_sa_find(pim, sg);
if (sa) {
return sa;
}
- return pim_msdp_sa_new(sg, rp);
+ return pim_msdp_sa_new(pim, sg, rp);
}
static void pim_msdp_sa_del(struct pim_msdp_sa *sa)
@@ -291,8 +299,8 @@ static void pim_msdp_sa_del(struct pim_msdp_sa *sa)
pim_msdp_sa_state_timer_setup(sa, false /* start */);
/* remove the entry from various tables */
- listnode_delete(msdp->sa_list, sa);
- hash_release(msdp->sa_hash, sa);
+ listnode_delete(sa->pim->msdp.sa_list, sa);
+ hash_release(sa->pim->msdp.sa_hash, sa);
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP SA %s deleted", sa->sg_str);
@@ -315,7 +323,7 @@ static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa,
/* any time the peer ip changes also update the rp address */
if (PIM_INADDR_ISNOT_ANY(sa->peer)) {
- old_mp = pim_msdp_peer_find(sa->peer);
+ old_mp = pim_msdp_peer_find(sa->pim, sa->peer);
if (old_mp && old_mp->sa_cnt) {
--old_mp->sa_cnt;
}
@@ -349,8 +357,8 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa,
zlog_debug("MSDP SA %s local reference removed",
sa->sg_str);
}
- if (msdp->local_cnt)
- --msdp->local_cnt;
+ if (sa->pim->msdp.local_cnt)
+ --sa->pim->msdp.local_cnt;
}
}
@@ -382,12 +390,12 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa,
}
}
-void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
- struct in_addr rp)
+void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
+ struct prefix_sg *sg, struct in_addr rp)
{
struct pim_msdp_sa *sa;
- sa = pim_msdp_sa_add(sg, rp);
+ sa = pim_msdp_sa_add(pim, sg, rp);
if (!sa) {
return;
}
@@ -412,7 +420,7 @@ void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
} else {
if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {
sa->flags |= PIM_MSDP_SAF_LOCAL;
- ++msdp->local_cnt;
+ ++sa->pim->msdp.local_cnt;
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP SA %s added locally",
sa->sg_str);
@@ -438,7 +446,9 @@ void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
*/
static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up)
{
- if (!(msdp->flags & PIM_MSDPF_ENABLE)) {
+ struct pim_instance *pim = up->channel_oil->pim;
+
+ if (!(pim->msdp.flags & PIM_MSDPF_ENABLE)) {
return false;
}
@@ -447,7 +457,7 @@ static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up)
return false;
}
- if (!I_am_RP(up->sg.grp)) {
+ if (!I_am_RP(pim, up->sg.grp)) {
/* we are not RP for the group */
return false;
}
@@ -462,18 +472,19 @@ static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up)
return false;
}
-static void pim_msdp_sa_local_add(struct prefix_sg *sg)
+static void pim_msdp_sa_local_add(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
struct in_addr rp;
rp.s_addr = 0;
- pim_msdp_sa_ref(NULL /* mp */, sg, rp);
+ pim_msdp_sa_ref(pim, NULL /* mp */, sg, rp);
}
-void pim_msdp_sa_local_del(struct prefix_sg *sg)
+void pim_msdp_sa_local_del(struct pim_instance *pim, struct prefix_sg *sg)
{
struct pim_msdp_sa *sa;
- sa = pim_msdp_sa_find(sg);
+ sa = pim_msdp_sa_find(pim, sg);
if (sa) {
pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL);
}
@@ -481,11 +492,12 @@ void pim_msdp_sa_local_del(struct prefix_sg *sg)
/* we need to be very cautious with this API as SA del too can trigger an
* upstream del and we will get stuck in a simple loop */
-static void pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg)
+static void pim_msdp_sa_local_del_on_up_del(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
struct pim_msdp_sa *sa;
- sa = pim_msdp_sa_find(sg);
+ sa = pim_msdp_sa_find(pim, sg);
if (sa) {
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP local sa %s del on up del",
@@ -543,32 +555,34 @@ static void pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg)
*/
void pim_msdp_sa_local_update(struct pim_upstream *up)
{
+ struct pim_instance *pim = up->channel_oil->pim;
+
if (pim_msdp_sa_local_add_ok(up)) {
- pim_msdp_sa_local_add(&up->sg);
+ pim_msdp_sa_local_add(pim, &up->sg);
} else {
- pim_msdp_sa_local_del(&up->sg);
+ pim_msdp_sa_local_del(pim, &up->sg);
}
}
-static void pim_msdp_sa_local_setup(void)
+static void pim_msdp_sa_local_setup(struct pim_instance *pim)
{
struct pim_upstream *up;
struct listnode *up_node;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
pim_msdp_sa_local_update(up);
}
}
/* whenever the RP changes we need to re-evaluate the "local" SA-cache */
/* XXX: needs to be tested */
-void pim_msdp_i_am_rp_changed(void)
+void pim_msdp_i_am_rp_changed(struct pim_instance *pim)
{
struct listnode *sanode;
struct listnode *nextnode;
struct pim_msdp_sa *sa;
- if (!(msdp->flags & PIM_MSDPF_ENABLE)) {
+ if (!(pim->msdp.flags & PIM_MSDPF_ENABLE)) {
/* if the feature is not enabled do nothing */
return;
}
@@ -578,16 +592,16 @@ void pim_msdp_i_am_rp_changed(void)
}
/* mark all local entries as stale */
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
if (sa->flags & PIM_MSDP_SAF_LOCAL) {
sa->flags |= PIM_MSDP_SAF_STALE;
}
}
/* re-setup local SA entries */
- pim_msdp_sa_local_setup();
+ pim_msdp_sa_local_setup(pim);
- for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) {
+ for (ALL_LIST_ELEMENTS(pim->msdp.sa_list, sanode, nextnode, sa)) {
/* purge stale SA entries */
if (sa->flags & PIM_MSDP_SAF_STALE) {
/* clear the stale flag; the entry may be kept even
@@ -609,7 +623,8 @@ void pim_msdp_i_am_rp_changed(void)
/* We track the join state of (*, G) entries. If G has sources in the SA-cache
* we need to setup or teardown SPT when the JoinDesired status changes for
* (*, G) */
-void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up)
+void pim_msdp_up_join_state_changed(struct pim_instance *pim,
+ struct pim_upstream *xg_up)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -626,7 +641,7 @@ void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up)
/* XXX: Need to maintain SAs per-group to avoid all this unnecessary
* walking */
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) {
continue;
}
@@ -634,7 +649,7 @@ void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up)
}
}
-static void pim_msdp_up_xg_del(struct prefix_sg *sg)
+static void pim_msdp_up_xg_del(struct pim_instance *pim, struct prefix_sg *sg)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
@@ -650,7 +665,7 @@ static void pim_msdp_up_xg_del(struct prefix_sg *sg)
/* XXX: Need to maintain SAs per-group to avoid all this unnecessary
* walking */
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
if (sa->sg.grp.s_addr != sg->grp.s_addr) {
continue;
}
@@ -658,15 +673,15 @@ static void pim_msdp_up_xg_del(struct prefix_sg *sg)
}
}
-void pim_msdp_up_del(struct prefix_sg *sg)
+void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg)
{
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP up %s del", pim_str_sg_dump(sg));
}
if (sg->src.s_addr == INADDR_ANY) {
- pim_msdp_up_xg_del(sg);
+ pim_msdp_up_xg_del(pim, sg);
} else {
- pim_msdp_sa_local_del_on_up_del(sg);
+ pim_msdp_sa_local_del_on_up_del(pim, sg);
}
}
@@ -797,7 +812,7 @@ static void pim_msdp_peer_listen(struct pim_msdp_peer *mp)
* first listening peer is configured; but don't bother tearing it down
* when
* all the peers go down */
- pim_msdp_sock_listen();
+ pim_msdp_sock_listen(mp->pim);
}
/* 11.2.A4 and 11.2.A5: transition active or passive peer to
@@ -913,12 +928,14 @@ static int pim_msdp_peer_hold_timer_cb(struct thread *t)
pim_msdp_peer_reset_tcp_conn(mp, "ht-expired");
return 0;
}
+
static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start)
{
+ struct pim_instance *pim = mp->pim;
THREAD_OFF(mp->hold_timer);
if (start) {
- thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp,
- PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer);
+ thread_add_timer(pim->msdp.master, pim_msdp_peer_hold_timer_cb,
+ mp, PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer);
}
}
@@ -942,7 +959,8 @@ static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start)
{
THREAD_OFF(mp->ka_timer);
if (start) {
- thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp,
+ thread_add_timer(mp->pim->msdp.master,
+ pim_msdp_peer_ka_timer_cb, mp,
PIM_MSDP_PEER_KA_TIME, &mp->ka_timer);
}
}
@@ -1005,9 +1023,9 @@ static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start)
{
THREAD_OFF(mp->cr_timer);
if (start) {
- thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp,
- PIM_MSDP_PEER_CONNECT_RETRY_TIME,
- &mp->cr_timer);
+ thread_add_timer(
+ mp->pim->msdp.master, pim_msdp_peer_cr_timer_cb, mp,
+ PIM_MSDP_PEER_CONNECT_RETRY_TIME, &mp->cr_timer);
}
}
@@ -1043,14 +1061,15 @@ static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr)
}
/* 11.2.A1: create a new peer and transition state to listen or connecting */
-static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr,
+static enum pim_msdp_err pim_msdp_peer_new(struct pim_instance *pim,
+ struct in_addr peer_addr,
struct in_addr local_addr,
const char *mesh_group_name,
struct pim_msdp_peer **mp_p)
{
struct pim_msdp_peer *mp;
- pim_msdp_enable();
+ pim_msdp_enable(pim);
mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp));
if (!mp) {
@@ -1059,12 +1078,13 @@ static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr,
return PIM_MSDP_ERR_OOM;
}
+ mp->pim = pim;
mp->peer = peer_addr;
pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str));
pim_msdp_addr2su(&mp->su_peer, mp->peer);
mp->local = local_addr;
/* XXX: originator_id setting needs to move to the mesh group */
- msdp->originator_id = local_addr;
+ pim->msdp.originator_id = local_addr;
pim_msdp_addr2su(&mp->su_local, mp->local);
mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name);
mp->state = PIM_MSDP_INACTIVE;
@@ -1080,8 +1100,8 @@ static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr,
mp->obuf = stream_fifo_new();
/* insert into misc tables for easy access */
- mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern);
- listnode_add_sort(msdp->peer_list, mp);
+ mp = hash_get(pim->msdp.peer_hash, mp, hash_alloc_intern);
+ listnode_add_sort(pim->msdp.peer_list, mp);
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP peer %s created", mp->key_str);
@@ -1101,16 +1121,18 @@ static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr,
return PIM_MSDP_ERR_NONE;
}
-struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr)
+struct pim_msdp_peer *pim_msdp_peer_find(struct pim_instance *pim,
+ struct in_addr peer_addr)
{
struct pim_msdp_peer lookup;
lookup.peer = peer_addr;
- return hash_lookup(msdp->peer_hash, &lookup);
+ return hash_lookup(pim->msdp.peer_hash, &lookup);
}
/* add peer configuration if it doesn't already exist */
-enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr,
+enum pim_msdp_err pim_msdp_peer_add(struct pim_instance *pim,
+ struct in_addr peer_addr,
struct in_addr local_addr,
const char *mesh_group_name,
struct pim_msdp_peer **mp_p)
@@ -1133,7 +1155,7 @@ enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr,
return PIM_MSDP_ERR_SIP_EQ_DIP;
}
- mp = pim_msdp_peer_find(peer_addr);
+ mp = pim_msdp_peer_find(pim, peer_addr);
if (mp) {
if (mp_p) {
*mp_p = mp;
@@ -1141,7 +1163,8 @@ enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr,
return PIM_MSDP_ERR_PEER_EXISTS;
}
- return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p);
+ return pim_msdp_peer_new(pim, peer_addr, local_addr, mesh_group_name,
+ mp_p);
}
/* release all mem associated with a peer */
@@ -1168,8 +1191,8 @@ static enum pim_msdp_err pim_msdp_peer_do_del(struct pim_msdp_peer *mp)
pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */);
/* remove the session from various tables */
- listnode_delete(msdp->peer_list, mp);
- hash_release(msdp->peer_hash, mp);
+ listnode_delete(mp->pim->msdp.peer_list, mp);
+ hash_release(mp->pim->msdp.peer_hash, mp);
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP peer %s deleted", mp->key_str);
@@ -1181,11 +1204,12 @@ static enum pim_msdp_err pim_msdp_peer_do_del(struct pim_msdp_peer *mp)
return PIM_MSDP_ERR_NONE;
}
-enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr)
+enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim,
+ struct in_addr peer_addr)
{
struct pim_msdp_peer *mp;
- mp = pim_msdp_peer_find(peer_addr);
+ mp = pim_msdp_peer_find(pim, peer_addr);
if (!mp) {
return PIM_MSDP_ERR_NO_PEER;
}
@@ -1223,7 +1247,7 @@ static int pim_msdp_peer_comp(const void *p1, const void *p2)
}
/************************** Mesh group management **************************/
-static void pim_msdp_mg_free(struct pim_msdp_mg *mg)
+static void pim_msdp_mg_free(struct pim_instance *pim, struct pim_msdp_mg *mg)
{
/* If the mesh-group has valid member or src_ip don't delete it */
if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) {
@@ -1237,10 +1261,10 @@ static void pim_msdp_mg_free(struct pim_msdp_mg *mg)
XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
if (mg->mbr_list)
- list_free(mg->mbr_list);
+ list_delete(mg->mbr_list);
XFREE(MTYPE_PIM_MSDP_MG, mg);
- msdp->mg = NULL;
+ pim->msdp.mg = NULL;
}
static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name)
@@ -1265,9 +1289,10 @@ static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name)
return mg;
}
-enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name)
+enum pim_msdp_err pim_msdp_mg_del(struct pim_instance *pim,
+ const char *mesh_group_name)
{
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
struct pim_msdp_mg_mbr *mbr;
if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) {
@@ -1284,22 +1309,23 @@ enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name)
mg->src_ip.s_addr = INADDR_ANY;
/* free up the mesh-group */
- pim_msdp_mg_free(mg);
+ pim_msdp_mg_free(pim, mg);
return PIM_MSDP_ERR_NONE;
}
-static enum pim_msdp_err pim_msdp_mg_add(const char *mesh_group_name)
+static enum pim_msdp_err pim_msdp_mg_add(struct pim_instance *pim,
+ const char *mesh_group_name)
{
- if (msdp->mg) {
- if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) {
+ if (pim->msdp.mg) {
+ if (!strcmp(pim->msdp.mg->mesh_group_name, mesh_group_name)) {
return PIM_MSDP_ERR_NONE;
}
/* currently only one mesh-group can exist at a time */
return PIM_MSDP_ERR_MAX_MESH_GROUPS;
}
- msdp->mg = pim_msdp_mg_new(mesh_group_name);
- if (!msdp->mg) {
+ pim->msdp.mg = pim_msdp_mg_new(mesh_group_name);
+ if (!pim->msdp.mg) {
return PIM_MSDP_ERR_OOM;
}
@@ -1325,17 +1351,18 @@ static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr)
XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr);
}
-static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct in_addr mbr_ip)
+static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct pim_instance *pim,
+ struct in_addr mbr_ip)
{
struct pim_msdp_mg_mbr *mbr;
struct listnode *mbr_node;
- if (!msdp->mg) {
+ if (!pim->msdp.mg) {
return NULL;
}
/* we can move this to a hash but considering that number of peers in
* a mesh-group that seems like bit of an overkill */
- for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.mg->mbr_list, mbr_node, mbr)) {
if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) {
return mbr;
}
@@ -1343,20 +1370,21 @@ static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct in_addr mbr_ip)
return mbr;
}
-enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name,
+enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr mbr_ip)
{
int rc;
struct pim_msdp_mg_mbr *mbr;
struct pim_msdp_mg *mg;
- rc = pim_msdp_mg_add(mesh_group_name);
+ rc = pim_msdp_mg_add(pim, mesh_group_name);
if (rc != PIM_MSDP_ERR_NONE) {
return rc;
}
- mg = msdp->mg;
- mbr = pim_msdp_mg_mbr_find(mbr_ip);
+ mg = pim->msdp.mg;
+ mbr = pim_msdp_mg_mbr_find(pim, mbr_ip);
if (mbr) {
return PIM_MSDP_ERR_MG_MBR_EXISTS;
}
@@ -1366,7 +1394,7 @@ enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name,
zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
sizeof(*mbr));
/* if there are no references to the mg free it */
- pim_msdp_mg_free(mg);
+ pim_msdp_mg_free(pim, mg);
return PIM_MSDP_ERR_OOM;
}
mbr->mbr_ip = mbr_ip;
@@ -1374,7 +1402,7 @@ enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name,
/* if valid SIP has been configured add peer session */
if (mg->src_ip.s_addr != INADDR_ANY) {
- pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name,
+ pim_msdp_peer_add(pim, mbr_ip, mg->src_ip, mesh_group_name,
&mbr->mp);
}
@@ -1409,33 +1437,34 @@ static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg,
}
}
-enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name,
+enum pim_msdp_err pim_msdp_mg_mbr_del(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr mbr_ip)
{
struct pim_msdp_mg_mbr *mbr;
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) {
return PIM_MSDP_ERR_NO_MG;
}
- mbr = pim_msdp_mg_mbr_find(mbr_ip);
+ mbr = pim_msdp_mg_mbr_find(pim, mbr_ip);
if (!mbr) {
return PIM_MSDP_ERR_NO_MG_MBR;
}
pim_msdp_mg_mbr_do_del(mg, mbr);
/* if there are no references to the mg free it */
- pim_msdp_mg_free(mg);
+ pim_msdp_mg_free(pim, mg);
return PIM_MSDP_ERR_NONE;
}
-static void pim_msdp_mg_src_do_del(void)
+static void pim_msdp_mg_src_do_del(struct pim_instance *pim)
{
struct pim_msdp_mg_mbr *mbr;
struct listnode *mbr_node;
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
/* SIP is being removed - tear down all active peer sessions */
for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) {
@@ -1450,9 +1479,10 @@ static void pim_msdp_mg_src_do_del(void)
}
}
-enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name)
+enum pim_msdp_err pim_msdp_mg_src_del(struct pim_instance *pim,
+ const char *mesh_group_name)
{
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) {
return PIM_MSDP_ERR_NO_MG;
@@ -1460,14 +1490,15 @@ enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name)
if (mg->src_ip.s_addr != INADDR_ANY) {
mg->src_ip.s_addr = INADDR_ANY;
- pim_msdp_mg_src_do_del();
+ pim_msdp_mg_src_do_del(pim);
/* if there are no references to the mg free it */
- pim_msdp_mg_free(mg);
+ pim_msdp_mg_free(pim, mg);
}
return PIM_MSDP_ERR_NONE;
}
-enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name,
+enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr src_ip)
{
int rc;
@@ -1476,23 +1507,23 @@ enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name,
struct pim_msdp_mg *mg;
if (src_ip.s_addr == INADDR_ANY) {
- pim_msdp_mg_src_del(mesh_group_name);
+ pim_msdp_mg_src_del(pim, mesh_group_name);
return PIM_MSDP_ERR_NONE;
}
- rc = pim_msdp_mg_add(mesh_group_name);
+ rc = pim_msdp_mg_add(pim, mesh_group_name);
if (rc != PIM_MSDP_ERR_NONE) {
return rc;
}
- mg = msdp->mg;
+ mg = pim->msdp.mg;
if (mg->src_ip.s_addr != INADDR_ANY) {
- pim_msdp_mg_src_do_del();
+ pim_msdp_mg_src_do_del(pim);
}
mg->src_ip = src_ip;
for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) {
- pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name,
+ pim_msdp_peer_add(pim, mbr->mbr_ip, mg->src_ip, mesh_group_name,
&mbr->mp);
}
@@ -1506,11 +1537,12 @@ enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name,
}
/*********************** MSDP feature APIs *********************************/
-int pim_msdp_config_write(struct vty *vty)
+int pim_msdp_config_write_helper(struct pim_instance *pim, struct vty *vty,
+ const char *spaces)
{
struct listnode *mbrnode;
struct pim_msdp_mg_mbr *mbr;
- struct pim_msdp_mg *mg = msdp->mg;
+ struct pim_msdp_mg *mg = pim->msdp.mg;
char mbr_str[INET_ADDRSTRLEN];
char src_str[INET_ADDRSTRLEN];
int count = 0;
@@ -1521,65 +1553,83 @@ int pim_msdp_config_write(struct vty *vty)
if (mg->src_ip.s_addr != INADDR_ANY) {
pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str));
- vty_out(vty, "ip msdp mesh-group %s source %s\n",
+ vty_out(vty, "%sip msdp mesh-group %s source %s\n", spaces,
mg->mesh_group_name, src_str);
++count;
}
for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
- vty_out(vty, "ip msdp mesh-group %s member %s\n",
+ vty_out(vty, "%sip msdp mesh-group %s member %s\n", spaces,
mg->mesh_group_name, mbr_str);
++count;
}
return count;
}
+int pim_msdp_config_write(struct vty *vty)
+{
+ return pim_msdp_config_write_helper(pimg, vty, "");
+}
+
/* Enable feature including active/periodic timers etc. on the first peer
* config. Till then MSDP should just stay quiet. */
-static void pim_msdp_enable(void)
+static void pim_msdp_enable(struct pim_instance *pim)
{
- if (msdp->flags & PIM_MSDPF_ENABLE) {
+ if (pim->msdp.flags & PIM_MSDPF_ENABLE) {
/* feature is already enabled */
return;
}
- msdp->flags |= PIM_MSDPF_ENABLE;
- msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE);
- pim_msdp_sa_adv_timer_setup(true /* start */);
+ pim->msdp.flags |= PIM_MSDPF_ENABLE;
+ pim->msdp.work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE);
+ pim_msdp_sa_adv_timer_setup(pim, true /* start */);
/* setup sa cache based on local sources */
- pim_msdp_sa_local_setup();
+ pim_msdp_sa_local_setup(pim);
}
/* MSDP init */
-void pim_msdp_init(struct thread_master *master)
+void pim_msdp_init(struct pim_instance *pim, struct thread_master *master)
{
- msdp->master = master;
+ pim->msdp.master = master;
+ char hash_name[64];
- msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make,
- pim_msdp_peer_hash_eq, NULL);
- msdp->peer_list = list_new();
- msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free;
- msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp;
+ snprintf(hash_name, 64, "PIM %s MSDP Peer Hash", pim->vrf->name);
+ pim->msdp.peer_hash = hash_create(pim_msdp_peer_hash_key_make,
+ pim_msdp_peer_hash_eq, hash_name);
+ pim->msdp.peer_list = list_new();
+ pim->msdp.peer_list->del = (void (*)(void *))pim_msdp_peer_free;
+ pim->msdp.peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp;
- msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make,
- pim_msdp_sa_hash_eq, NULL);
- msdp->sa_list = list_new();
- msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free;
- msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp;
+ snprintf(hash_name, 64, "PIM %s MSDP SA Hash", pim->vrf->name);
+ pim->msdp.sa_hash = hash_create(pim_msdp_sa_hash_key_make,
+ pim_msdp_sa_hash_eq, hash_name);
+ pim->msdp.sa_list = list_new();
+ pim->msdp.sa_list->del = (void (*)(void *))pim_msdp_sa_free;
+ pim->msdp.sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp;
}
/* counterpart to MSDP init; XXX: unused currently */
-void pim_msdp_exit(void)
+void pim_msdp_exit(struct pim_instance *pim)
{
/* XXX: stop listener and delete all peer sessions */
- if (msdp->peer_hash) {
- hash_free(msdp->peer_hash);
- msdp->peer_hash = NULL;
+ if (pim->msdp.peer_hash) {
+ hash_free(pim->msdp.peer_hash);
+ pim->msdp.peer_hash = NULL;
+ }
+
+ if (pim->msdp.peer_list) {
+ list_delete(pim->msdp.peer_list);
+ pim->msdp.peer_list = NULL;
+ }
+
+ if (pim->msdp.sa_hash) {
+ hash_free(pim->msdp.sa_hash);
+ pim->msdp.sa_hash = NULL;
}
- if (msdp->peer_list) {
- list_free(msdp->peer_list);
- msdp->peer_list = NULL;
+ if (pim->msdp.sa_list) {
+ list_delete(pim->msdp.sa_list);
+ pim->msdp.sa_list = NULL;
}
}
diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h
index 66e5457df4..0627ee5f47 100644
--- a/pimd/pim_msdp.h
+++ b/pimd/pim_msdp.h
@@ -69,11 +69,13 @@ enum pim_msdp_sa_flags {
PIM_MSDP_SAF_PEER = (1 << 1),
PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER),
PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on
- * misc pim events such as RP change */
+ * misc pim events such as RP change */
PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3)
};
struct pim_msdp_sa {
+ struct pim_instance *pim;
+
struct prefix_sg sg;
char sg_str[PIM_SG_LEN];
struct in_addr rp; /* Last RP address associated with this SA */
@@ -97,6 +99,8 @@ enum pim_msdp_peer_flags {
};
struct pim_msdp_peer {
+ struct pim_instance *pim;
+
/* configuration */
struct in_addr local;
struct in_addr peer;
@@ -203,24 +207,30 @@ struct pim_msdp {
};
#define PIM_MSDP_PEER_READ_ON(mp) \
- thread_add_read(msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read)
+ thread_add_read(mp->pim->msdp.master, pim_msdp_read, mp, mp->fd, \
+ &mp->t_read)
#define PIM_MSDP_PEER_WRITE_ON(mp) \
- thread_add_write(msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write)
+ thread_add_write(mp->pim->msdp.master, pim_msdp_write, mp, mp->fd, \
+ &mp->t_write)
#define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read)
#define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write)
-extern struct pim_msdp *msdp;
-void pim_msdp_init(struct thread_master *master);
-void pim_msdp_exit(void);
-enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local,
+// struct pim_msdp *msdp;
+struct pim_instance;
+void pim_msdp_init(struct pim_instance *pim, struct thread_master *master);
+void pim_msdp_exit(struct pim_instance *pim);
+enum pim_msdp_err pim_msdp_peer_add(struct pim_instance *pim,
+ struct in_addr peer, struct in_addr local,
const char *mesh_group_name,
struct pim_msdp_peer **mp_p);
-enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr);
+enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim,
+ struct in_addr peer_addr);
char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf,
int buf_size);
-struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr);
+struct pim_msdp_peer *pim_msdp_peer_find(struct pim_instance *pim,
+ struct in_addr peer_addr);
void pim_msdp_peer_established(struct pim_msdp_peer *mp);
void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp);
void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state);
@@ -229,21 +239,29 @@ int pim_msdp_write(struct thread *thread);
char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size,
bool long_format);
int pim_msdp_config_write(struct vty *vty);
+int pim_msdp_config_write_helper(struct pim_instance *pim, struct vty *vty,
+ const char *spaces);
void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp);
-void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
- struct in_addr rp);
+void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
+ struct prefix_sg *sg, struct in_addr rp);
void pim_msdp_sa_local_update(struct pim_upstream *up);
-void pim_msdp_sa_local_del(struct prefix_sg *sg);
-void pim_msdp_i_am_rp_changed(void);
+void pim_msdp_sa_local_del(struct pim_instance *pim, struct prefix_sg *sg);
+void pim_msdp_i_am_rp_changed(struct pim_instance *pim);
bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp);
-void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up);
-void pim_msdp_up_del(struct prefix_sg *sg);
-enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name,
+void pim_msdp_up_join_state_changed(struct pim_instance *pim,
+ struct pim_upstream *xg_up);
+void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg);
+enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr mbr_ip);
-enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name,
+enum pim_msdp_err pim_msdp_mg_mbr_del(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr mbr_ip);
-enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name);
-enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name,
+enum pim_msdp_err pim_msdp_mg_src_del(struct pim_instance *pim,
+ const char *mesh_group_name);
+enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim,
+ const char *mesh_group_name,
struct in_addr src_ip);
-enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name);
+enum pim_msdp_err pim_msdp_mg_del(struct pim_instance *pim,
+ const char *mesh_group_name);
#endif
diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c
index 01ce293e36..11efc158e9 100644
--- a/pimd/pim_msdp_packet.c
+++ b/pimd/pim_msdp_packet.c
@@ -310,7 +310,8 @@ void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp)
pim_msdp_pkt_send(mp, s);
}
-static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp)
+static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_instance *pim,
+ struct pim_msdp_peer *mp)
{
struct stream *s;
@@ -318,7 +319,7 @@ static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp)
/* don't tx anything unless a session is established */
return;
}
- s = stream_dup(msdp->work_obuf);
+ s = stream_dup(pim->msdp.work_obuf);
if (s) {
pim_msdp_pkt_send(mp, s);
mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT;
@@ -326,63 +327,66 @@ static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp)
}
/* push the stream into the obuf fifo of all the peers */
-static void pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp)
+static void pim_msdp_pkt_sa_push(struct pim_instance *pim,
+ struct pim_msdp_peer *mp)
{
struct listnode *mpnode;
if (mp) {
- pim_msdp_pkt_sa_push_to_one_peer(mp);
+ pim_msdp_pkt_sa_push_to_one_peer(pim, mp);
} else {
- for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push",
mp->key_str);
}
- pim_msdp_pkt_sa_push_to_one_peer(mp);
+ pim_msdp_pkt_sa_push_to_one_peer(pim, mp);
}
}
}
-static int pim_msdp_pkt_sa_fill_hdr(int local_cnt)
+static int pim_msdp_pkt_sa_fill_hdr(struct pim_instance *pim, int local_cnt)
{
int curr_tlv_ecnt;
- stream_reset(msdp->work_obuf);
+ stream_reset(pim->msdp.work_obuf);
curr_tlv_ecnt = local_cnt > PIM_MSDP_SA_MAX_ENTRY_CNT
? PIM_MSDP_SA_MAX_ENTRY_CNT
: local_cnt;
local_cnt -= curr_tlv_ecnt;
- stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE);
- stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt));
- stream_putc(msdp->work_obuf, curr_tlv_ecnt);
- stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr);
+ stream_putc(pim->msdp.work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE);
+ stream_putw(pim->msdp.work_obuf,
+ PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt));
+ stream_putc(pim->msdp.work_obuf, curr_tlv_ecnt);
+ stream_put_ipv4(pim->msdp.work_obuf, pim->msdp.originator_id.s_addr);
return local_cnt;
}
static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa)
{
- stream_put3(msdp->work_obuf, 0 /* reserved */);
- stream_putc(msdp->work_obuf, 32 /* sprefix len */);
- stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr);
- stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr);
+ stream_put3(sa->pim->msdp.work_obuf, 0 /* reserved */);
+ stream_putc(sa->pim->msdp.work_obuf, 32 /* sprefix len */);
+ stream_put_ipv4(sa->pim->msdp.work_obuf, sa->sg.grp.s_addr);
+ stream_put_ipv4(sa->pim->msdp.work_obuf, sa->sg.src.s_addr);
}
-static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp)
+static void pim_msdp_pkt_sa_gen(struct pim_instance *pim,
+ struct pim_msdp_peer *mp)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
int sa_count;
- int local_cnt = msdp->local_cnt;
+ int local_cnt = pim->msdp.local_cnt;
sa_count = 0;
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug(" sa gen %d", local_cnt);
}
- local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt);
+ local_cnt = pim_msdp_pkt_sa_fill_hdr(pim, local_cnt);
- for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {
/* current implementation of MSDP is for anycast i.e.
* full mesh. so
@@ -394,31 +398,31 @@ static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp)
pim_msdp_pkt_sa_fill_one(sa);
++sa_count;
if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) {
- pim_msdp_pkt_sa_push(mp);
+ pim_msdp_pkt_sa_push(pim, mp);
/* reset headers */
sa_count = 0;
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug(" sa gen for remainder %d",
local_cnt);
}
- local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt);
+ local_cnt = pim_msdp_pkt_sa_fill_hdr(pim, local_cnt);
}
}
if (sa_count) {
- pim_msdp_pkt_sa_push(mp);
+ pim_msdp_pkt_sa_push(pim, mp);
}
return;
}
-static void pim_msdp_pkt_sa_tx_done(void)
+static void pim_msdp_pkt_sa_tx_done(struct pim_instance *pim)
{
struct listnode *mpnode;
struct pim_msdp_peer *mp;
/* if SA were sent to the peers we restart ka timer and avoid
* unnecessary ka noise */
- for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) {
mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT;
pim_msdp_peer_pkt_txed(mp);
@@ -426,25 +430,25 @@ static void pim_msdp_pkt_sa_tx_done(void)
}
}
-void pim_msdp_pkt_sa_tx(void)
+void pim_msdp_pkt_sa_tx(struct pim_instance *pim)
{
- pim_msdp_pkt_sa_gen(NULL /* mp */);
- pim_msdp_pkt_sa_tx_done();
+ pim_msdp_pkt_sa_gen(pim, NULL /* mp */);
+ pim_msdp_pkt_sa_tx_done(pim);
}
void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa)
{
- pim_msdp_pkt_sa_fill_hdr(1 /* cnt */);
+ pim_msdp_pkt_sa_fill_hdr(sa->pim, 1 /* cnt */);
pim_msdp_pkt_sa_fill_one(sa);
- pim_msdp_pkt_sa_push(NULL);
- pim_msdp_pkt_sa_tx_done();
+ pim_msdp_pkt_sa_push(sa->pim, NULL);
+ pim_msdp_pkt_sa_tx_done(sa->pim);
}
/* when a connection is first established we push all SAs immediately */
void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp)
{
- pim_msdp_pkt_sa_gen(mp);
- pim_msdp_pkt_sa_tx_done();
+ pim_msdp_pkt_sa_gen(mp->pim, mp);
+ pim_msdp_pkt_sa_tx_done(mp->pim);
}
static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp)
@@ -484,7 +488,7 @@ static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp)
if (PIM_DEBUG_MSDP_PACKETS) {
zlog_debug(" sg %s", pim_str_sg_dump(&sg));
}
- pim_msdp_sa_ref(mp, &sg, rp);
+ pim_msdp_sa_ref(mp->pim, mp, &sg, rp);
}
static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len)
diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h
index 986fa3b32a..d922fa50df 100644
--- a/pimd/pim_msdp_packet.h
+++ b/pimd/pim_msdp_packet.h
@@ -64,7 +64,7 @@
void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp);
int pim_msdp_read(struct thread *thread);
-void pim_msdp_pkt_sa_tx(void);
+void pim_msdp_pkt_sa_tx(struct pim_instance *pim);
void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa);
void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp);
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index 0ce0971012..9473462e63 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -24,8 +24,11 @@
#include <lib/sockunion.h>
#include <lib/thread.h>
#include <lib/vty.h>
+#include <lib/if.h>
+#include <lib/vrf.h>
#include "pimd.h"
+#include "pim_sock.h"
#include "pim_msdp.h"
#include "pim_msdp_socket.h"
@@ -56,7 +59,7 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
static int pim_msdp_sock_accept(struct thread *thread)
{
union sockunion su;
- struct pim_msdp_listener *listener = THREAD_ARG(thread);
+ struct pim_instance *pim = THREAD_ARG(thread);
int accept_sock;
int msdp_sock;
struct pim_msdp_peer *mp;
@@ -70,9 +73,9 @@ static int pim_msdp_sock_accept(struct thread *thread)
zlog_err("accept_sock is negative value %d", accept_sock);
return -1;
}
- listener->thread = NULL;
- thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock,
- &listener->thread);
+ pim->msdp.listener.thread = NULL;
+ thread_add_read(master, pim_msdp_sock_accept, pim, accept_sock,
+ &pim->msdp.listener.thread);
/* accept client connection. */
msdp_sock = sockunion_accept(accept_sock, &su);
@@ -83,9 +86,9 @@ static int pim_msdp_sock_accept(struct thread *thread)
}
/* see if have peer config for this */
- mp = pim_msdp_peer_find(su.sin.sin_addr);
+ mp = pim_msdp_peer_find(pim, su.sin.sin_addr);
if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) {
- ++msdp->rejected_accepts;
+ ++pim->msdp.rejected_accepts;
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_err("msdp peer connection refused from %s",
sockunion2str(&su, buf, SU_ADDRSTRLEN));
@@ -117,15 +120,15 @@ static int pim_msdp_sock_accept(struct thread *thread)
}
/* global listener for the MSDP well know TCP port */
-int pim_msdp_sock_listen(void)
+int pim_msdp_sock_listen(struct pim_instance *pim)
{
int sock;
int socklen;
struct sockaddr_in sin;
int rc;
- struct pim_msdp_listener *listener = &msdp->listener;
+ struct pim_msdp_listener *listener = &pim->msdp.listener;
- if (msdp->flags & PIM_MSDPF_LISTENER) {
+ if (pim->msdp.flags & PIM_MSDPF_LISTENER) {
/* listener already setup */
return 0;
}
@@ -147,6 +150,17 @@ int pim_msdp_sock_listen(void)
sockopt_reuseaddr(sock);
sockopt_reuseport(sock);
+ if (pim->vrf_id != VRF_DEFAULT) {
+ struct interface *ifp =
+ if_lookup_by_name(pim->vrf->name, pim->vrf_id);
+ if (!ifp) {
+ zlog_err("%s: Unable to lookup vrf interface: %s",
+ __PRETTY_FUNCTION__, pim->vrf->name);
+ return -1;
+ }
+ pim_socket_bind(sock, ifp);
+ }
+
if (pimd_privs.change(ZPRIVS_RAISE)) {
zlog_err("pim_msdp_socket: could not raise privs, %s",
safe_strerror(errno));
@@ -178,10 +192,10 @@ int pim_msdp_sock_listen(void)
listener->fd = sock;
memcpy(&listener->su, &sin, socklen);
listener->thread = NULL;
- thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock,
+ thread_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock,
&listener->thread);
- msdp->flags |= PIM_MSDPF_LISTENER;
+ pim->msdp.flags |= PIM_MSDPF_LISTENER;
return 0;
}
@@ -214,6 +228,17 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
return -1;
}
+ if (mp->pim->vrf_id != VRF_DEFAULT) {
+ struct interface *ifp =
+ if_lookup_by_name(mp->pim->vrf->name, mp->pim->vrf_id);
+ if (!ifp) {
+ zlog_err("%s: Unable to lookup vrf interface: %s",
+ __PRETTY_FUNCTION__, mp->pim->vrf->name);
+ return -1;
+ }
+ pim_socket_bind(mp->fd, ifp);
+ }
+
set_nonblocking(mp->fd);
/* Set socket send buffer size */
diff --git a/pimd/pim_msdp_socket.h b/pimd/pim_msdp_socket.h
index 0abcd57da0..8f46683dff 100644
--- a/pimd/pim_msdp_socket.h
+++ b/pimd/pim_msdp_socket.h
@@ -19,6 +19,6 @@
#ifndef PIM_MSDP_SOCKET_H
#define PIM_MSDP_SOCKET_H
-int pim_msdp_sock_listen(void);
+int pim_msdp_sock_listen(struct pim_instance *pim);
int pim_msdp_sock_connect(struct pim_msdp_peer *mp);
#endif
diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c
index 04f1f4846f..5d4ddf14e8 100644
--- a/pimd/pim_msg.c
+++ b/pimd/pim_msg.c
@@ -36,6 +36,7 @@
#include "pim_rpf.h"
#include "pim_register.h"
#include "pim_jp_agg.h"
+#include "pim_oil.h"
void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size,
uint8_t pim_msg_type)
@@ -104,6 +105,9 @@ size_t pim_msg_get_jp_group_size(struct list *sources)
struct pim_jp_sources *js;
size_t size = 0;
+ if (!sources)
+ return 0;
+
size += sizeof(struct pim_encoded_group_ipv4);
size += 4; // Joined sources (2) + Pruned Sources (2)
@@ -195,7 +199,8 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
grp->prunes++;
if (source->up->sg.src.s_addr == INADDR_ANY) {
- struct pim_rpf *rpf = pim_rp_g(source->up->sg.grp);
+ struct pim_instance *pim = source->up->channel_oil->pim;
+ struct pim_rpf *rpf = pim_rp_g(pim, source->up->sg.grp);
bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT
| PIM_ENCODE_RPT_BIT;
stosend = rpf->rpf_addr.u.prefix4;
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 70341a3754..04e3e10ff3 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -545,7 +545,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
else
pim_hello_restart_triggered(neigh->interface);
- pim_upstream_find_new_rpf();
+ pim_upstream_find_new_rpf(pim_ifp->pim);
/* RNH can send nexthop update prior to PIM neibhor UP
in that case nexthop cache would not consider this neighbor
@@ -553,9 +553,9 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
Upon PIM neighbor UP, iterate all RPs and update
nexthop cache with this neighbor.
*/
- pim_resolve_rp_nh();
+ pim_resolve_rp_nh(pim_ifp->pim);
- pim_rp_setup();
+ pim_rp_setup(pim_ifp->pim);
pim_neighbor_rpf_update();
return neigh;
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index f8bf2ac77c..f7fa9993ad 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -44,7 +44,7 @@
* pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
* command to Zebra.
*/
-void pim_sendmsg_zebra_rnh(struct zclient *zclient,
+void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
struct pim_nexthop_cache *pnc, int command)
{
struct stream *s;
@@ -58,7 +58,7 @@ void pim_sendmsg_zebra_rnh(struct zclient *zclient,
p = &(pnc->rpf.rpf_addr);
s = zclient->obuf;
stream_reset(s);
- zclient_create_header(s, command, VRF_DEFAULT);
+ zclient_create_header(s, command, pim->vrf_id);
/* get update for all routes for a prefix */
stream_putc(s, 0);
@@ -81,19 +81,21 @@ void pim_sendmsg_zebra_rnh(struct zclient *zclient,
zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
- if (PIM_DEBUG_TRACE) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[PREFIX2STR_BUFFER];
prefix2str(p, buf, sizeof(buf));
- zlog_debug("%s: NHT %sregistered addr %s with Zebra ret:%d ",
- __PRETTY_FUNCTION__,
- (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de",
- buf, ret);
+ zlog_debug(
+ "%s: NHT %sregistered addr %s(%s) with Zebra ret:%d ",
+ __PRETTY_FUNCTION__,
+ (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf,
+ pim->vrf->name, ret);
}
return;
}
-struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf)
+struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_instance *pim,
+ struct pim_rpf *rpf)
{
struct pim_nexthop_cache *pnc = NULL;
struct pim_nexthop_cache lookup;
@@ -102,14 +104,17 @@ struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf)
lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen;
lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr;
- pnc = hash_lookup(pimg->rpf_hash, &lookup);
+ pnc = hash_lookup(pim->rpf_hash, &lookup);
return pnc;
}
-struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr)
+static struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_instance *pim,
+ struct pim_rpf *rpf_addr)
{
struct pim_nexthop_cache *pnc;
+ char hash_name[64];
+ char buf1[64];
pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE,
sizeof(struct pim_nexthop_cache));
@@ -122,31 +127,31 @@ struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr)
pnc->rpf.rpf_addr.u.prefix4.s_addr =
rpf_addr->rpf_addr.u.prefix4.s_addr;
- pnc = hash_get(pimg->rpf_hash, pnc, hash_alloc_intern);
+ pnc = hash_get(pim->rpf_hash, pnc, hash_alloc_intern);
pnc->rp_list = list_new();
pnc->rp_list->cmp = pim_rp_list_cmp;
- pnc->upstream_list = list_new();
- pnc->upstream_list->cmp = pim_upstream_compare;
-
- if (PIM_DEBUG_ZEBRA) {
- char rpf_str[PREFIX_STRLEN];
- pim_addr_dump("<nht?>", &rpf_addr->rpf_addr, rpf_str,
- sizeof(rpf_str));
- zlog_debug(
- "%s: NHT hash node, RP and UP lists allocated for %s ",
- __PRETTY_FUNCTION__, rpf_str);
- }
+ snprintf(hash_name, 64, "PNC %s(%s) Upstream Hash",
+ prefix2str(&pnc->rpf.rpf_addr, buf1, 64),
+ pim->vrf->name);
+ pnc->upstream_hash = hash_create_size(8192, pim_upstream_hash_key,
+ pim_upstream_equal,
+ hash_name);
return pnc;
}
-/* This API is used to Register an address with Zebra
- ret 1 means nexthop cache is found.
-*/
-int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up,
- struct rp_info *rp,
+/*
+ * pim_find_or_track_nexthop
+ *
+ * This API is used to Register an address with Zebra
+ *
+ * 1 -> Success
+ * 0 -> Failure
+ */
+int pim_find_or_track_nexthop(struct pim_instance *pim, struct prefix *addr,
+ struct pim_upstream *up, struct rp_info *rp,
struct pim_nexthop_cache *out_pnc)
{
struct pim_nexthop_cache *pnc = NULL;
@@ -160,50 +165,36 @@ int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up,
rpf.rpf_addr.prefixlen = addr->prefixlen;
rpf.rpf_addr.u.prefix4 = addr->u.prefix4;
- pnc = pim_nexthop_cache_find(&rpf);
+ pnc = pim_nexthop_cache_find(pim, &rpf);
if (!pnc) {
- pnc = pim_nexthop_cache_add(&rpf);
- if (pnc)
- pim_sendmsg_zebra_rnh(zclient, pnc,
- ZEBRA_NEXTHOP_REGISTER);
- else {
+ pnc = pim_nexthop_cache_add(pim, &rpf);
+ if (!pnc) {
char rpf_str[PREFIX_STRLEN];
pim_addr_dump("<nht-pnc?>", addr, rpf_str,
sizeof(rpf_str));
zlog_warn("%s: pnc node allocation failed. addr %s ",
__PRETTY_FUNCTION__, rpf_str);
- return -1;
+ return 0;
+ }
+ pim_sendmsg_zebra_rnh(pim, zclient, pnc,
+ ZEBRA_NEXTHOP_REGISTER);
+ if (PIM_DEBUG_PIM_NHT) {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(addr, buf, sizeof(buf));
+ zlog_debug(
+ "%s: NHT cache and zebra notification added for %s(%s)",
+ __PRETTY_FUNCTION__, buf, pim->vrf->name);
}
}
if (rp != NULL) {
ch_node = listnode_lookup(pnc->rp_list, rp);
- if (ch_node == NULL) {
- if (PIM_DEBUG_ZEBRA) {
- char rp_str[PREFIX_STRLEN];
- pim_addr_dump("<rp?>", &rp->rp.rpf_addr, rp_str,
- sizeof(rp_str));
- zlog_debug(
- "%s: Add RP %s node to pnc cached list",
- __PRETTY_FUNCTION__, rp_str);
- }
+ if (ch_node == NULL)
listnode_add_sort(pnc->rp_list, rp);
- }
}
- if (up != NULL) {
- ch_node = listnode_lookup(pnc->upstream_list, up);
- if (ch_node == NULL) {
- if (PIM_DEBUG_ZEBRA) {
- char buf[PREFIX2STR_BUFFER];
- prefix2str(addr, buf, sizeof(buf));
- zlog_debug(
- "%s: Add upstream %s node to pnc cached list, rpf %s",
- __PRETTY_FUNCTION__, up->sg_str, buf);
- }
- listnode_add_sort(pnc->upstream_list, up);
- }
- }
+ if (up != NULL)
+ up = hash_get(pnc->upstream_hash, up, hash_alloc_intern);
if (pnc && CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID)) {
memcpy(out_pnc, pnc, sizeof(struct pim_nexthop_cache));
@@ -213,8 +204,8 @@ int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up,
return 0;
}
-void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up,
- struct rp_info *rp)
+void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
+ struct pim_upstream *up, struct rp_info *rp)
{
struct pim_nexthop_cache *pnc = NULL;
struct pim_nexthop_cache lookup;
@@ -224,28 +215,31 @@ void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up,
/* Remove from RPF hash if it is the last entry */
lookup.rpf.rpf_addr = *addr;
- pnc = hash_lookup(pimg->rpf_hash, &lookup);
+ pnc = hash_lookup(pim->rpf_hash, &lookup);
if (pnc) {
if (rp)
listnode_delete(pnc->rp_list, rp);
if (up)
- listnode_delete(pnc->upstream_list, up);
+ hash_release(pnc->upstream_hash, up);
- if (PIM_DEBUG_ZEBRA)
+ if (PIM_DEBUG_PIM_NHT) {
+ char buf[PREFIX_STRLEN];
+ prefix2str(addr, buf, sizeof buf);
zlog_debug(
- "%s: NHT rp_list count:%d upstream_list count:%d ",
- __PRETTY_FUNCTION__, pnc->rp_list->count,
- pnc->upstream_list->count);
+ "%s: NHT %s(%s) rp_list count:%d upstream count:%ld",
+ __PRETTY_FUNCTION__, buf, pim->vrf->name,
+ pnc->rp_list->count, pnc->upstream_hash->count);
+ }
if (pnc->rp_list->count == 0
- && pnc->upstream_list->count == 0) {
- pim_sendmsg_zebra_rnh(zclient, pnc,
+ && pnc->upstream_hash->count == 0) {
+ pim_sendmsg_zebra_rnh(pim, zclient, pnc,
ZEBRA_NEXTHOP_UNREGISTER);
list_delete(pnc->rp_list);
- list_delete(pnc->upstream_list);
+ hash_free(pnc->upstream_hash);
- hash_release(pimg->rpf_hash, pnc);
+ hash_release(pim->rpf_hash, pnc);
if (pnc->nexthop)
nexthops_free(pnc->nexthop);
XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc);
@@ -254,7 +248,8 @@ void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up,
}
/* Update RP nexthop info based on Nexthop update received from Zebra.*/
-int pim_update_rp_nh(struct pim_nexthop_cache *pnc)
+static int pim_update_rp_nh(struct pim_instance *pim,
+ struct pim_nexthop_cache *pnc)
{
struct listnode *node = NULL;
struct rp_info *rp_info = NULL;
@@ -266,25 +261,12 @@ int pim_update_rp_nh(struct pim_nexthop_cache *pnc)
continue;
// Compute PIM RPF using cached nexthop
- ret = pim_ecmp_nexthop_search(pnc, &rp_info->rp.source_nexthop,
- &rp_info->rp.rpf_addr,
- &rp_info->group, 1);
-
- if (PIM_DEBUG_TRACE) {
- char rp_str[PREFIX_STRLEN];
- pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp_str,
- sizeof(rp_str));
- zlog_debug(
- "%s: NHT update, nexthop for RP %s is interface %s ",
- __PRETTY_FUNCTION__, rp_str,
- rp_info->rp.source_nexthop.interface->name);
- }
+ ret = pim_ecmp_nexthop_search(
+ pim, pnc, &rp_info->rp.source_nexthop,
+ &rp_info->rp.rpf_addr, &rp_info->group, 1);
}
- if (ret)
- return 0;
-
- return 1;
+ return !ret;
}
/* This API is used to traverse nexthop cache of RPF addr
@@ -292,152 +274,148 @@ int pim_update_rp_nh(struct pim_nexthop_cache *pnc)
unresolved state and due to event like pim neighbor
UP event if it can be resolved.
*/
-void pim_resolve_upstream_nh(struct prefix *nht_p)
+void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p)
{
struct nexthop *nh_node = NULL;
struct pim_nexthop_cache pnc;
struct pim_neighbor *nbr = NULL;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(nht_p, NULL, NULL, &pnc)) == 1) {
- for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
- if (nh_node->gate.ipv4.s_addr == 0) {
- struct interface *ifp1 = if_lookup_by_index(
- nh_node->ifindex, VRF_DEFAULT);
- nbr = pim_neighbor_find_if(ifp1);
- if (nbr) {
- nh_node->gate.ipv4 = nbr->source_addr;
- if (PIM_DEBUG_TRACE) {
- char str[PREFIX_STRLEN];
- char str1[INET_ADDRSTRLEN];
- pim_inet4_dump("<nht_nbr?>",
- nbr->source_addr,
- str1,
- sizeof(str1));
- pim_addr_dump("<nht_addr?>",
- nht_p, str,
- sizeof(str));
- zlog_debug(
- "%s: addr %s new nexthop addr %s interface %s",
- __PRETTY_FUNCTION__,
- str, str1, ifp1->name);
- }
- }
- }
+ if (!pim_find_or_track_nexthop(pim, nht_p, NULL, NULL, &pnc))
+ return;
+
+ for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
+ if (nh_node->gate.ipv4.s_addr != 0)
+ continue;
+
+ struct interface *ifp1 =
+ if_lookup_by_index(nh_node->ifindex, pim->vrf_id);
+ nbr = pim_neighbor_find_if(ifp1);
+ if (!nbr)
+ continue;
+
+ nh_node->gate.ipv4 = nbr->source_addr;
+ if (PIM_DEBUG_PIM_NHT) {
+ char str[PREFIX_STRLEN];
+ char str1[INET_ADDRSTRLEN];
+ pim_inet4_dump("<nht_nbr?>", nbr->source_addr, str1,
+ sizeof(str1));
+ pim_addr_dump("<nht_addr?>", nht_p, str, sizeof(str));
+ zlog_debug(
+ "%s: addr %s new nexthop addr %s interface %s",
+ __PRETTY_FUNCTION__, str, str1, ifp1->name);
}
}
}
/* Update Upstream nexthop info based on Nexthop update received from Zebra.*/
-static int pim_update_upstream_nh(struct pim_nexthop_cache *pnc)
+static int pim_update_upstream_nh_helper(struct hash_backet *backet, void *arg)
{
- struct listnode *up_node;
- struct listnode *ifnode;
- struct listnode *up_nextnode;
- struct listnode *node;
- struct pim_upstream *up = NULL;
- struct interface *ifp = NULL;
+ struct pim_instance *pim = (struct pim_instance *)arg;
+ struct pim_upstream *up = (struct pim_upstream *)backet->data;
int vif_index = 0;
- for (ALL_LIST_ELEMENTS(pnc->upstream_list, up_node, up_nextnode, up)) {
- enum pim_rpf_result rpf_result;
- struct pim_rpf old;
+ enum pim_rpf_result rpf_result;
+ struct pim_rpf old;
- old.source_nexthop.interface = up->rpf.source_nexthop.interface;
- rpf_result = pim_rpf_update(up, &old, 0);
- if (rpf_result == PIM_RPF_FAILURE)
- continue;
+ old.source_nexthop.interface = up->rpf.source_nexthop.interface;
+ rpf_result = pim_rpf_update(pim, up, &old, 0);
+ if (rpf_result == PIM_RPF_FAILURE)
+ return HASHWALK_CONTINUE;
- /* update kernel multicast forwarding cache (MFC) */
- if (up->channel_oil) {
- ifindex_t ifindex =
- up->rpf.source_nexthop.interface->ifindex;
- vif_index = pim_if_find_vifindex_by_ifindex(ifindex);
- /* Pass Current selected NH vif index to mroute download
- */
- if (vif_index)
- pim_scan_individual_oil(up->channel_oil,
- vif_index);
- else {
- if (PIM_DEBUG_ZEBRA)
- zlog_debug(
- "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
- __PRETTY_FUNCTION__, up->sg_str,
- up->rpf.source_nexthop
- .interface->name);
- }
+ /* update kernel multicast forwarding cache (MFC) */
+ if (up->channel_oil) {
+ ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
+
+ vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
+ /* Pass Current selected NH vif index to mroute download
+ */
+ if (vif_index)
+ pim_scan_individual_oil(up->channel_oil, vif_index);
+ else {
+ if (PIM_DEBUG_PIM_NHT)
+ zlog_debug(
+ "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
+ __PRETTY_FUNCTION__, up->sg_str,
+ up->rpf.source_nexthop.interface->name);
}
+ }
- if (rpf_result == PIM_RPF_CHANGED) {
- struct pim_neighbor *nbr;
+ if (rpf_result == PIM_RPF_CHANGED) {
+ struct pim_neighbor *nbr;
- nbr = pim_neighbor_find(old.source_nexthop.interface,
- old.rpf_addr.u.prefix4);
- if (nbr)
- pim_jp_agg_remove_group(nbr->upstream_jp_agg,
- up);
+ nbr = pim_neighbor_find(old.source_nexthop.interface,
+ old.rpf_addr.u.prefix4);
+ if (nbr)
+ pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+ /*
+ * We have detected a case where we might need to rescan
+ * the inherited o_list so do it.
+ */
+ if (up->channel_oil
+ && up->channel_oil->oil_inherited_rescan) {
+ pim_upstream_inherited_olist_decide(pim, up);
+ up->channel_oil->oil_inherited_rescan = 0;
+ }
+
+ if (up->join_state == PIM_UPSTREAM_JOINED) {
/*
- * We have detected a case where we might need to rescan
- * the inherited o_list so do it.
+ * If we come up real fast we can be here
+ * where the mroute has not been installed
+ * so install it.
*/
if (up->channel_oil
- && up->channel_oil->oil_inherited_rescan) {
- pim_upstream_inherited_olist_decide(up);
- up->channel_oil->oil_inherited_rescan = 0;
- }
+ && !up->channel_oil->installed)
+ pim_mroute_add(up->channel_oil,
+ __PRETTY_FUNCTION__);
- if (up->join_state == PIM_UPSTREAM_JOINED) {
- /*
- * If we come up real fast we can be here
- * where the mroute has not been installed
- * so install it.
- */
- if (up->channel_oil
- && !up->channel_oil->installed)
- pim_mroute_add(up->channel_oil,
- __PRETTY_FUNCTION__);
-
- /*
- RFC 4601: 4.5.7. Sending (S,G) Join/Prune
- Messages
-
- Transitions from Joined State
-
- RPF'(S,G) changes not due to an Assert
-
- The upstream (S,G) state machine remains in
- Joined
- state. Send Join(S,G) to the new upstream
- neighbor, which is
- the new value of RPF'(S,G). Send Prune(S,G)
- to the old
- upstream neighbor, which is the old value of
- RPF'(S,G). Set
- the Join Timer (JT) to expire after
- t_periodic seconds.
- */
- pim_jp_agg_switch_interface(&old, &up->rpf, up);
-
- pim_upstream_join_timer_restart(up, &old);
- } /* up->join_state == PIM_UPSTREAM_JOINED */
-
- /* FIXME can join_desired actually be changed by
- pim_rpf_update()
- returning PIM_RPF_CHANGED ? */
- pim_upstream_update_join_desired(up);
-
- } /* PIM_RPF_CHANGED */
-
- if (PIM_DEBUG_TRACE) {
- zlog_debug("%s: NHT upstream %s old ifp %s new ifp %s",
- __PRETTY_FUNCTION__, up->sg_str,
- old.source_nexthop.interface->name,
- up->rpf.source_nexthop.interface->name);
- }
- } /* for (pnc->upstream_list) */
+ /*
+ * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
+ *
+ * Transitions from Joined State
+ *
+ * RPF'(S,G) changes not due to an Assert
+ *
+ * The upstream (S,G) state machine remains in Joined
+ * state. Send Join(S,G) to the new upstream
+ * neighbor, which is the new value of RPF'(S,G).
+ * Send Prune(S,G) to the old upstream neighbor, which
+ * is the old value of RPF'(S,G). Set the Join
+ * Timer (JT) to expire after t_periodic seconds.
+ */
+ pim_jp_agg_switch_interface(&old, &up->rpf, up);
+
+ pim_upstream_join_timer_restart(up, &old);
+ } /* up->join_state == PIM_UPSTREAM_JOINED */
+
+ /*
+ * FIXME can join_desired actually be changed by
+ * pim_rpf_update() returning PIM_RPF_CHANGED ?
+ */
+ pim_upstream_update_join_desired(pim, up);
+
+ } /* PIM_RPF_CHANGED */
+
+ if (PIM_DEBUG_PIM_NHT) {
+ zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
+ __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
+ old.source_nexthop.interface->name,
+ up->rpf.source_nexthop.interface->name);
+ }
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp))
+ return HASHWALK_CONTINUE;
+}
+
+static int pim_update_upstream_nh(struct pim_instance *pim,
+ struct pim_nexthop_cache *pnc)
+{
+ struct listnode *node, *ifnode;
+ struct interface *ifp;
+
+ hash_walk(pnc->upstream_hash, pim_update_upstream_nh_helper, pim);
+
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp))
if (ifp->info) {
struct pim_interface *pim_ifp = ifp->info;
struct pim_iface_upstream_switch *us;
@@ -475,19 +453,11 @@ uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp)
}
hash_val = jhash_2words(g, s, 101);
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
- char buf[PREFIX2STR_BUFFER];
- char bufg[PREFIX2STR_BUFFER];
- prefix2str(src, buf, sizeof(buf));
- if (grp)
- prefix2str(grp, bufg, sizeof(bufg));
- zlog_debug("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__,
- buf, grp ? bufg : "", hash_val);
- }
return hash_val;
}
-int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
+int pim_ecmp_nexthop_search(struct pim_instance *pim,
+ struct pim_nexthop_cache *pnc,
struct pim_nexthop *nexthop, struct prefix *src,
struct prefix *grp, int neighbor_needed)
{
@@ -499,7 +469,7 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
uint8_t nh_iter = 0, found = 0;
if (!pnc || !pnc->nexthop_num || !nexthop)
- return -1;
+ return 0;
// Current Nexthop is VALID, check to stay on the current path.
if (nexthop->interface && nexthop->interface->info
@@ -517,9 +487,12 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
// If the current nexthop is not valid, candidate to
// choose new Nexthop.
for (nh_node = pnc->nexthop; nh_node;
- nh_node = nh_node->next)
+ nh_node = nh_node->next) {
curr_route_valid = (nexthop->interface->ifindex
== nh_node->ifindex);
+ if (curr_route_valid)
+ break;
+ }
if (curr_route_valid
&& !pim_if_connected_to_source(nexthop->interface,
@@ -529,12 +502,12 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
nexthop->mrib_nexthop_addr.u.prefix4);
if (!nbr
&& !if_is_loopback(nexthop->interface)) {
- if (PIM_DEBUG_TRACE)
+ if (PIM_DEBUG_PIM_NHT)
zlog_debug(
"%s: current nexthop does not have nbr ",
__PRETTY_FUNCTION__);
} else {
- if (PIM_DEBUG_TRACE) {
+ if (PIM_DEBUG_PIM_NHT) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>",
src->u.prefix4,
@@ -546,9 +519,10 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
grp_str,
sizeof(grp_str));
zlog_debug(
- "%s: (%s, %s) current nexthop %s is valid, skipping new path selection",
+ "%s: (%s,%s)(%s) current nexthop %s is valid, skipping new path selection",
__PRETTY_FUNCTION__,
src_str, grp_str,
+ pim->vrf->name,
nexthop->interface->name);
}
return 0;
@@ -560,24 +534,22 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
// PIM ECMP flag is enable then choose ECMP path.
hash_val = pim_compute_ecmp_hash(src, grp);
mod_val = hash_val % pnc->nexthop_num;
- if (PIM_DEBUG_PIM_TRACE_DETAIL)
- zlog_debug("%s: hash_val %u mod_val %u ",
- __PRETTY_FUNCTION__, hash_val, mod_val);
}
for (nh_node = pnc->nexthop; nh_node && (found == 0);
nh_node = nh_node->next) {
first_ifindex = nh_node->ifindex;
- ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
if (!ifp) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", src->u.prefix4,
addr_str, sizeof(addr_str));
zlog_debug(
- "%s %s: could not find interface for ifindex %d (address %s)",
+ "%s %s: could not find interface for ifindex %d (address %s(%s))",
__FILE__, __PRETTY_FUNCTION__,
- first_ifindex, addr_str);
+ first_ifindex, addr_str,
+ pim->vrf->name);
}
if (nh_iter == mod_val)
mod_val++; // Select nexthpath
@@ -585,14 +557,15 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
continue;
}
if (!ifp->info) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", src->u.prefix4,
addr_str, sizeof(addr_str));
zlog_debug(
- "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
+ "%s: multicast not enabled on input interface %s(%s) (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name,
- first_ifindex, addr_str);
+ pim->vrf->name, first_ifindex,
+ addr_str);
}
if (nh_iter == mod_val)
mod_val++; // Select nexthpath
@@ -603,14 +576,12 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
if (neighbor_needed
&& !pim_if_connected_to_source(ifp, src->u.prefix4)) {
nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4);
- if (PIM_DEBUG_PIM_TRACE_DETAIL)
- zlog_debug("ifp name: %s, pim nbr: %p",
- ifp->name, nbr);
if (!nbr && !if_is_loopback(ifp)) {
- if (PIM_DEBUG_ZEBRA)
+ if (PIM_DEBUG_PIM_NHT)
zlog_debug(
- "%s: pim nbr not found on input interface %s",
- __PRETTY_FUNCTION__, ifp->name);
+ "%s: pim nbr not found on input interface %s(%s)",
+ __PRETTY_FUNCTION__, ifp->name,
+ pim->vrf->name);
if (nh_iter == mod_val)
mod_val++; // Select nexthpath
nh_iter++;
@@ -630,7 +601,7 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
nexthop->last_lookup_time = pim_time_monotonic_usec();
nexthop->nbr = nbr;
found = 1;
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[INET_ADDRSTRLEN];
char buf2[INET_ADDRSTRLEN];
char buf3[INET_ADDRSTRLEN];
@@ -643,19 +614,19 @@ int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
nexthop->mrib_nexthop_addr.u.prefix4,
buf, sizeof(buf));
zlog_debug(
- "%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d",
+ "%s: (%s,%s)(%s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d",
__PRETTY_FUNCTION__, buf2, buf3,
- ifp->name, buf, mod_val, nh_iter,
- qpim_ecmp_enable);
+ pim->vrf->name, ifp->name, buf, mod_val,
+ nh_iter, qpim_ecmp_enable);
}
}
nh_iter++;
}
if (found)
- return 0;
+ return 1;
else
- return -1;
+ return 0;
}
/* This API is used to parse Registered address nexthop update coming from Zebra
@@ -676,8 +647,8 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
struct pim_neighbor *nbr = NULL;
struct interface *ifp = NULL;
struct interface *ifp1 = NULL;
- struct pim_interface *pim_ifp = NULL;
- char str[INET_ADDRSTRLEN];
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+ struct pim_instance *pim = vrf->info;
s = zclient->ibuf;
memset(&p, 0, sizeof(struct prefix));
@@ -698,9 +669,9 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
rpf.rpf_addr.family = p.family;
rpf.rpf_addr.prefixlen = p.prefixlen;
rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr;
- pnc = pim_nexthop_cache_find(&rpf);
+ pnc = pim_nexthop_cache_find(pim, &rpf);
if (!pnc) {
- if (PIM_DEBUG_TRACE) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&rpf.rpf_addr, buf, sizeof(buf));
zlog_debug(
@@ -746,31 +717,12 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
stream_get(&nexthop->gate.ipv6, s, 16);
nexthop->ifindex = stream_getl(s);
ifp1 = if_lookup_by_index(nexthop->ifindex,
- VRF_DEFAULT);
+ pim->vrf_id);
nbr = pim_neighbor_find_if(ifp1);
/* Overwrite with Nbr address as NH addr */
- if (nbr) {
+ if (nbr)
nexthop->gate.ipv4 = nbr->source_addr;
- if (PIM_DEBUG_TRACE) {
- pim_inet4_dump("<nht_nbr?>",
- nbr->source_addr,
- str,
- sizeof(str));
- zlog_debug(
- "%s: NHT using pim nbr addr %s interface %s as rpf",
- __PRETTY_FUNCTION__,
- str, ifp1->name);
- }
- } else {
- if (PIM_DEBUG_TRACE) {
- pim_ifp = ifp1->info;
- zlog_debug(
- "%s: NHT pim nbr not found on interface %s nbr count:%d ",
- __PRETTY_FUNCTION__,
- ifp1->name,
- pim_ifp->pim_neighbor_list
- ->count);
- }
+ else {
// Mark nexthop address to 0 until PIM
// Nbr is resolved.
nexthop->gate.ipv4.s_addr =
@@ -783,24 +735,15 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
break;
}
- if (PIM_DEBUG_TRACE) {
- char p_str[PREFIX2STR_BUFFER];
- prefix2str(&p, p_str, sizeof(p_str));
- zlog_debug(
- "%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ",
- __PRETTY_FUNCTION__, p_str, i + 1,
- inet_ntoa(nexthop->gate.ipv4),
- nexthop->type, distance, metric);
- }
-
- ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(nexthop->ifindex, pim->vrf_id);
if (!ifp) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[NEXTHOP_STRLEN];
zlog_debug(
- "%s: could not find interface for ifindex %d (addr %s)",
+ "%s: could not find interface for ifindex %d(%s) (addr %s)",
__PRETTY_FUNCTION__,
nexthop->ifindex,
+ pim->vrf->name,
nexthop2str(nexthop, buf,
sizeof(buf)));
}
@@ -808,12 +751,25 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
continue;
}
+ if (PIM_DEBUG_PIM_NHT) {
+ char p_str[PREFIX2STR_BUFFER];
+ prefix2str(&p, p_str, sizeof(p_str));
+ zlog_debug(
+ "%s: NHT addr %s(%s) %d-nhop via %s(%s) type %d distance:%u metric:%u ",
+ __PRETTY_FUNCTION__, p_str,
+ pim->vrf->name, i + 1,
+ inet_ntoa(nexthop->gate.ipv4),
+ ifp->name, nexthop->type, distance,
+ metric);
+ }
+
if (!ifp->info) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[NEXTHOP_STRLEN];
zlog_debug(
- "%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
+ "%s: multicast not enabled on input interface %s(%s) (ifindex=%d, addr %s)",
__PRETTY_FUNCTION__, ifp->name,
+ pim->vrf->name,
nexthop->ifindex,
nexthop2str(nexthop, buf,
sizeof(buf)));
@@ -847,27 +803,28 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
pnc->nexthop = NULL;
}
- if (PIM_DEBUG_TRACE) {
+ if (PIM_DEBUG_PIM_NHT) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf));
zlog_debug(
- "%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d",
- __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num,
- vrf_id, listcount(pnc->upstream_list),
+ "%s: NHT Update for %s(%s) num_nh %d num_pim_nh %d vrf:%d up %ld rp %d",
+ __PRETTY_FUNCTION__, buf, pim->vrf->name, nexthop_num,
+ pnc->nexthop_num, vrf_id, pnc->upstream_hash->count,
listcount(pnc->rp_list));
}
pim_rpf_set_refresh_time();
if (listcount(pnc->rp_list))
- pim_update_rp_nh(pnc);
- if (listcount(pnc->upstream_list))
- pim_update_upstream_nh(pnc);
+ pim_update_rp_nh(pim, pnc);
+ if (pnc->upstream_hash->count)
+ pim_update_upstream_nh(pim, pnc);
return 0;
}
-int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
+int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
+ struct pim_nexthop *nexthop, struct in_addr addr,
struct prefix *src, struct prefix *grp,
int neighbor_needed)
{
@@ -880,32 +837,35 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
uint8_t i = 0;
uint32_t hash_val = 0, mod_val = 0;
- if (PIM_DEBUG_TRACE) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s: Looking up: %s, last lookup time: %lld",
- __PRETTY_FUNCTION__, addr_str,
+ zlog_debug("%s: Looking up: %s(%s), last lookup time: %lld",
+ __PRETTY_FUNCTION__, addr_str, pim->vrf->name,
nexthop->last_lookup_time);
}
memset(nexthop_tab, 0,
sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM);
- num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr,
- PIM_NEXTHOP_LOOKUP_MAX);
+ num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
+ addr, PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1) {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_warn(
- "%s %s: could not find nexthop ifindex for address %s",
- __FILE__, __PRETTY_FUNCTION__, addr_str);
- return -1;
+ if (PIM_DEBUG_PIM_NHT) {
+ char addr_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+ zlog_warn(
+ "%s: could not find nexthop ifindex for address %s(%s)",
+ __PRETTY_FUNCTION__, addr_str,
+ pim->vrf->name);
+ }
+ return 0;
}
// If PIM ECMP enable then choose ECMP path.
if (qpim_ecmp_enable) {
hash_val = pim_compute_ecmp_hash(src, grp);
mod_val = hash_val % num_ifindex;
- if (PIM_DEBUG_PIM_TRACE_DETAIL)
+ if (PIM_DEBUG_PIM_NHT_DETAIL)
zlog_debug("%s: hash_val %u mod_val %u",
__PRETTY_FUNCTION__, hash_val, mod_val);
}
@@ -913,16 +873,17 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
while (!found && (i < num_ifindex)) {
first_ifindex = nexthop_tab[i].ifindex;
- ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
if (!ifp) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: could not find interface for ifindex %d (address %s)",
+ "%s %s: could not find interface for ifindex %d (address %s(%s))",
__FILE__, __PRETTY_FUNCTION__,
- first_ifindex, addr_str);
+ first_ifindex, addr_str,
+ pim->vrf->name);
}
if (i == mod_val)
mod_val++;
@@ -931,14 +892,15 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
}
if (!ifp->info) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
+ "%s: multicast not enabled on input interface %s(%s) (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name,
- first_ifindex, addr_str);
+ pim->vrf->name, first_ifindex,
+ addr_str);
}
if (i == mod_val)
mod_val++;
@@ -948,29 +910,29 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) {
nbr = pim_neighbor_find(
ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
- if (PIM_DEBUG_PIM_TRACE_DETAIL)
- zlog_debug("ifp name: %s, pim nbr: %p",
- ifp->name, nbr);
+ if (PIM_DEBUG_PIM_NHT_DETAIL)
+ zlog_debug("ifp name: %s(%s), pim nbr: %p",
+ ifp->name, pim->vrf->name, nbr);
if (!nbr && !if_is_loopback(ifp)) {
if (i == mod_val)
mod_val++;
i++;
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr,
addr_str,
sizeof(addr_str));
zlog_debug(
- "%s: NBR not found on input interface %s (RPF for source %s)",
+ "%s: NBR not found on input interface %s(%s) (RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name,
- addr_str);
+ pim->vrf->name, addr_str);
}
continue;
}
}
if (i == mod_val) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char nexthop_str[PREFIX_STRLEN];
char addr_str[INET_ADDRSTRLEN];
pim_addr_dump("<nexthop?>",
@@ -979,9 +941,9 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: found nhop %s for addr %s interface %s metric %d dist %d",
- __FILE__, __PRETTY_FUNCTION__,
- nexthop_str, addr_str, ifp->name,
+ "%s: found nhop %s for addr %s interface %s(%s) metric %d dist %d",
+ __PRETTY_FUNCTION__, nexthop_str,
+ addr_str, ifp->name, pim->vrf->name,
nexthop_tab[i].route_metric,
nexthop_tab[i].protocol_distance);
}
@@ -1000,13 +962,15 @@ int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
}
i++;
}
+
if (found)
- return 0;
+ return 1;
else
- return -1;
+ return 0;
}
-int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src,
+int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
+ struct in_addr addr, struct prefix *src,
struct prefix *grp)
{
struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
@@ -1017,16 +981,16 @@ int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src,
memset(nexthop_tab, 0,
sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM);
- num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr,
- PIM_NEXTHOP_LOOKUP_MAX);
+ num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
+ addr, PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: could not find nexthop ifindex for address %s",
- __FILE__, __PRETTY_FUNCTION__, addr_str);
+ "%s: could not find nexthop ifindex for address %s(%s)",
+ __PRETTY_FUNCTION__, addr_str, pim->vrf->name);
}
return -1;
}
@@ -1035,32 +999,33 @@ int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src,
if (qpim_ecmp_enable) {
hash_val = pim_compute_ecmp_hash(src, grp);
mod_val = hash_val % num_ifindex;
- if (PIM_DEBUG_PIM_TRACE_DETAIL)
+ if (PIM_DEBUG_PIM_NHT_DETAIL)
zlog_debug("%s: hash_val %u mod_val %u",
__PRETTY_FUNCTION__, hash_val, mod_val);
}
first_ifindex = nexthop_tab[mod_val].ifindex;
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
zlog_debug(
- "%s %s: found nexthop ifindex=%d (interface %s) for address %s",
- __FILE__, __PRETTY_FUNCTION__, first_ifindex,
- ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str);
+ "%s: found nexthop ifindex=%d (interface %s(%s)) for address %s",
+ __PRETTY_FUNCTION__, first_ifindex,
+ ifindex2ifname(first_ifindex, pim->vrf_id),
+ pim->vrf->name, addr_str);
}
- vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
+ vif_index = pim_if_find_vifindex_by_ifindex(pim, first_ifindex);
if (vif_index < 0) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: low vif_index=%d < 1 nexthop for address %s",
- __FILE__, __PRETTY_FUNCTION__, vif_index,
+ "%s: low vif_index=%d(%s) < 1 nexthop for address %s",
+ __PRETTY_FUNCTION__, vif_index, pim->vrf->name,
addr_str);
}
return -2;
diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h
index fb8d836235..72ed777bf7 100644
--- a/pimd/pim_nht.h
+++ b/pimd/pim_nht.h
@@ -43,29 +43,31 @@ struct pim_nexthop_cache {
#define PIM_NEXTHOP_VALID (1 << 0)
struct list *rp_list;
- struct list *upstream_list;
+ struct hash *upstream_hash;
};
int pim_parse_nexthop_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id);
-int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up,
- struct rp_info *rp,
+int pim_find_or_track_nexthop(struct pim_instance *pim, struct prefix *addr,
+ struct pim_upstream *up, struct rp_info *rp,
struct pim_nexthop_cache *out_pnc);
-void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up,
- struct rp_info *rp);
-struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr);
-struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf);
+void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
+ struct pim_upstream *up, struct rp_info *rp);
+struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_instance *pim,
+ struct pim_rpf *rpf);
uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp);
-int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc,
+int pim_ecmp_nexthop_search(struct pim_instance *pim,
+ struct pim_nexthop_cache *pnc,
struct pim_nexthop *nexthop, struct prefix *src,
struct prefix *grp, int neighbor_needed);
-int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
+int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
+ struct pim_nexthop *nexthop, struct in_addr addr,
struct prefix *src, struct prefix *grp,
int neighbor_needed);
-void pim_sendmsg_zebra_rnh(struct zclient *zclient,
+void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
struct pim_nexthop_cache *pnc, int command);
-int pim_update_rp_nh(struct pim_nexthop_cache *pnc);
-void pim_resolve_upstream_nh(struct prefix *nht_p);
-int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src,
+void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p);
+int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
+ struct in_addr addr, struct prefix *src,
struct prefix *grp);
#endif
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index aeef0ff4ec..9ab0709d3e 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -32,8 +32,8 @@
#include "pim_iface.h"
#include "pim_time.h"
-struct list *pim_channel_oil_list = NULL;
-struct hash *pim_channel_oil_hash = NULL;
+// struct list *pim_channel_oil_list = NULL;
+// struct hash *pim_channel_oil_hash = NULL;
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
{
@@ -99,31 +99,36 @@ static unsigned int pim_oil_hash_key(void *arg)
oil->oil.mfcc_origin.s_addr, 0);
}
-void pim_oil_init(void)
+void pim_oil_init(struct pim_instance *pim)
{
- pim_channel_oil_hash =
- hash_create_size(8192, pim_oil_hash_key, pim_oil_equal, NULL);
+ char hash_name[64];
- pim_channel_oil_list = list_new();
- if (!pim_channel_oil_list) {
+ snprintf(hash_name, 64, "PIM %s Oil Hash", pim->vrf->name);
+ pim->channel_oil_hash = hash_create_size(8192,
+ pim_oil_hash_key,
+ pim_oil_equal,
+ hash_name);
+
+ pim->channel_oil_list = list_new();
+ if (!pim->channel_oil_list) {
zlog_err("%s %s: failure: channel_oil_list=list_new()",
__FILE__, __PRETTY_FUNCTION__);
return;
}
- pim_channel_oil_list->del = (void (*)(void *))pim_channel_oil_free;
- pim_channel_oil_list->cmp =
+ pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free;
+ pim->channel_oil_list->cmp =
(int (*)(void *, void *))pim_channel_oil_compare;
}
-void pim_oil_terminate(void)
+void pim_oil_terminate(struct pim_instance *pim)
{
- if (pim_channel_oil_list)
- list_free(pim_channel_oil_list);
- pim_channel_oil_list = NULL;
+ if (pim->channel_oil_list)
+ list_delete(pim->channel_oil_list);
+ pim->channel_oil_list = NULL;
- if (pim_channel_oil_hash)
- hash_free(pim_channel_oil_hash);
- pim_channel_oil_hash = NULL;
+ if (pim->channel_oil_hash)
+ hash_free(pim->channel_oil_hash);
+ pim->channel_oil_hash = NULL;
}
void pim_channel_oil_free(struct channel_oil *c_oil)
@@ -131,7 +136,8 @@ void pim_channel_oil_free(struct channel_oil *c_oil)
XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil);
}
-static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg)
+static struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
struct channel_oil *c_oil = NULL;
struct channel_oil lookup;
@@ -139,18 +145,19 @@ static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg)
lookup.oil.mfcc_mcastgrp = sg->grp;
lookup.oil.mfcc_origin = sg->src;
- c_oil = hash_lookup(pim_channel_oil_hash, &lookup);
+ c_oil = hash_lookup(pim->channel_oil_hash, &lookup);
return c_oil;
}
-struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
+struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
int input_vif_index)
{
struct channel_oil *c_oil;
struct interface *ifp;
- c_oil = pim_find_channel_oil(sg);
+ c_oil = pim_find_channel_oil(pim, sg);
if (c_oil) {
if (c_oil->oil.mfcc_parent != input_vif_index) {
c_oil->oil_inherited_rescan = 1;
@@ -165,11 +172,11 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
c_oil->oil.mfcc_parent = input_vif_index;
++c_oil->oil_ref_count;
c_oil->up = pim_upstream_find(
- sg); // channel might be present prior to upstream
+ pim, sg); // channel might be present prior to upstream
return c_oil;
}
- ifp = pim_if_find_by_vif_index(input_vif_index);
+ ifp = pim_if_find_by_vif_index(pim, input_vif_index);
if (!ifp) {
/* warning only */
zlog_warn(
@@ -186,14 +193,15 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
c_oil->oil.mfcc_mcastgrp = sg->grp;
c_oil->oil.mfcc_origin = sg->src;
- c_oil = hash_get(pim_channel_oil_hash, c_oil, hash_alloc_intern);
+ c_oil = hash_get(pim->channel_oil_hash, c_oil, hash_alloc_intern);
c_oil->oil.mfcc_parent = input_vif_index;
c_oil->oil_ref_count = 1;
c_oil->installed = 0;
- c_oil->up = pim_upstream_find(sg);
+ c_oil->up = pim_upstream_find(pim, sg);
+ c_oil->pim = pim;
- listnode_add_sort(pim_channel_oil_list, c_oil);
+ listnode_add_sort(pim->channel_oil_list, c_oil);
return c_oil;
}
@@ -209,8 +217,8 @@ void pim_channel_oil_del(struct channel_oil *c_oil)
* called by list_delete_all_node()
*/
c_oil->up = NULL;
- listnode_delete(pim_channel_oil_list, c_oil);
- hash_release(pim_channel_oil_hash, c_oil);
+ listnode_delete(c_oil->pim->channel_oil_list, c_oil);
+ hash_release(c_oil->pim->channel_oil_hash, c_oil);
pim_channel_oil_free(c_oil);
}
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index f537062c7a..1168ba0a8f 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -67,6 +67,8 @@ struct channel_counts {
*/
struct channel_oil {
+ struct pim_instance *pim;
+
struct mfcctl oil;
int installed;
int oil_inherited_rescan;
@@ -80,11 +82,12 @@ struct channel_oil {
extern struct list *pim_channel_oil_list;
-void pim_oil_init(void);
-void pim_oil_terminate(void);
+void pim_oil_init(struct pim_instance *pim);
+void pim_oil_terminate(struct pim_instance *pim);
void pim_channel_oil_free(struct channel_oil *c_oil);
-struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
+struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
int input_vif_index);
void pim_channel_oil_del(struct channel_oil *c_oil);
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index 21892f3477..ffe5d52a15 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -238,7 +238,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
pim_msg_len - PIM_MSG_HEADER_LEN);
break;
case PIM_MSG_TYPE_REG_STOP:
- return pim_register_stop_recv(pim_msg + PIM_MSG_HEADER_LEN,
+ return pim_register_stop_recv(ifp, pim_msg + PIM_MSG_HEADER_LEN,
pim_msg_len - PIM_MSG_HEADER_LEN);
break;
case PIM_MSG_TYPE_JOIN_PRUNE:
@@ -286,7 +286,7 @@ static void pim_sock_read_on(struct interface *ifp);
static int pim_sock_read(struct thread *t)
{
- struct interface *ifp;
+ struct interface *ifp, *orig_ifp;
struct pim_interface *pim_ifp;
int fd;
struct sockaddr_in from;
@@ -300,7 +300,7 @@ static int pim_sock_read(struct thread *t)
static long long count = 0;
int cont = 1;
- ifp = THREAD_ARG(t);
+ orig_ifp = ifp = THREAD_ARG(t);
fd = THREAD_FD(t);
pim_ifp = ifp->info;
@@ -320,36 +320,20 @@ static int pim_sock_read(struct thread *t)
goto done;
}
-#ifdef PIM_CHECK_RECV_IFINDEX_SANITY
- /* ifindex sanity check */
- if (ifindex != (int)ifp->ifindex) {
- char from_str[INET_ADDRSTRLEN];
- char to_str[INET_ADDRSTRLEN];
- struct interface *recv_ifp;
-
- if (!inet_ntop(AF_INET, &from.sin_addr, from_str,
- sizeof(from_str)))
- sprintf(from_str, "<from?>");
- if (!inet_ntop(AF_INET, &to.sin_addr, to_str,
- sizeof(to_str)))
- sprintf(to_str, "<to?>");
-
- recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
- if (recv_ifp) {
- zassert(ifindex == (int)recv_ifp->ifindex);
- }
-
-#ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
- zlog_warn(
- "Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
- from_str, to_str, fd, ifindex,
- recv_ifp ? recv_ifp->name : "<if-notfound>",
- ifp->ifindex, ifp->name);
-#endif
+ /*
+ * What? So with vrf's the incoming packet is received
+ * on the vrf interface but recvfromto above returns
+ * the right ifindex, so just use it. We know
+ * it's the right interface because we bind to it
+ */
+ ifp = if_lookup_by_index(ifindex, pim_ifp->pim->vrf_id);
+ if (!ifp || !ifp->info) {
+ if (PIM_DEBUG_PIM_PACKETS)
+ zlog_debug(
+ "%s: Received incoming pim packet on interface not yet configured for pim",
+ __PRETTY_FUNCTION__);
goto done;
}
-#endif
-
int fail = pim_pim_packet(ifp, buf, len);
if (fail) {
if (PIM_DEBUG_PIM_PACKETS)
@@ -366,7 +350,7 @@ static int pim_sock_read(struct thread *t)
result = 0; /* good */
done:
- pim_sock_read_on(ifp);
+ pim_sock_read_on(orig_ifp);
if (result) {
++pim_ifp->pim_ifstat_hello_recvfail;
@@ -667,13 +651,9 @@ static int hello_send(struct interface *ifp, uint16_t holdtime)
static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
{
- struct pim_interface *pim_ifp;
-
- zassert(ifp);
- pim_ifp = ifp->info;
- zassert(pim_ifp);
+ struct pim_interface *pim_ifp = ifp->info;
- if (if_is_loopback(ifp))
+ if (pim_if_is_loopback(pim_ifp->pim, ifp))
return 0;
if (hello_send(ifp, holdtime)) {
@@ -695,9 +675,7 @@ static void hello_resched(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- zassert(ifp);
pim_ifp = ifp->info;
- zassert(pim_ifp);
if (PIM_DEBUG_PIM_HELLO) {
zlog_debug("Rescheduling %d sec hello on interface %s",
@@ -718,7 +696,6 @@ static int on_pim_hello_send(struct thread *t)
struct interface *ifp;
ifp = THREAD_ARG(t);
-
pim_ifp = ifp->info;
/*
@@ -745,9 +722,7 @@ void pim_hello_restart_now(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- zassert(ifp);
pim_ifp = ifp->info;
- zassert(pim_ifp);
/*
* Reset next hello timer
@@ -775,9 +750,13 @@ void pim_hello_restart_triggered(struct interface *ifp)
int triggered_hello_delay_msec;
int random_msec;
- zassert(ifp);
pim_ifp = ifp->info;
- zassert(pim_ifp);
+
+ /*
+ * No need to ever start loopback or vrf device hello's
+ */
+ if (pim_if_is_loopback(pim_ifp->pim, ifp))
+ return;
/*
* There exists situations where we have the a RPF out this
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 1cbe1dcf7f..a393d0bbda 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -48,14 +48,16 @@ struct thread *send_test_packet_timer = NULL;
void pim_register_join(struct pim_upstream *up)
{
- if (pim_is_grp_ssm(up->sg.grp)) {
+ struct pim_instance *pim = up->channel_oil->pim;
+
+ if (pim_is_grp_ssm(pim, up->sg.grp)) {
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug("%s register setup skipped as group is SSM",
up->sg_str);
return;
}
- pim_channel_add_oif(up->channel_oil, pim_regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
}
@@ -109,8 +111,10 @@ void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg,
++pinfo->pim_ifstat_reg_stop_send;
}
-int pim_register_stop_recv(uint8_t *buf, int buf_size)
+int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
{
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim = pim_ifp->pim;
struct pim_upstream *upstream = NULL;
struct prefix source;
struct prefix_sg sg;
@@ -123,7 +127,7 @@ int pim_register_stop_recv(uint8_t *buf, int buf_size)
pim_parse_addr_ucast(&source, buf, buf_size);
sg.src = source.u.prefix4;
- upstream = pim_upstream_find(&sg);
+ upstream = pim_upstream_find(pim, &sg);
if (!upstream) {
return 0;
}
@@ -138,7 +142,7 @@ int pim_register_stop_recv(uint8_t *buf, int buf_size)
break;
case PIM_REG_JOIN:
upstream->reg_state = PIM_REG_PRUNE;
- pim_channel_del_oif(upstream->channel_oil, pim_regiface,
+ pim_channel_del_oif(upstream->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
pim_upstream_start_register_stop_timer(upstream, 0);
break;
@@ -270,10 +274,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
int i_am_rp = 0;
struct pim_interface *pim_ifp = NULL;
+ pim_ifp = ifp->info;
+
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
- if (!pim_rp_check_is_my_ip_address(ip_hdr->ip_dst, dest_addr)) {
+ if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, ip_hdr->ip_dst,
+ dest_addr)) {
if (PIM_DEBUG_PIM_REG) {
char dest[INET_ADDRSTRLEN];
@@ -285,8 +292,6 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
return 0;
}
- pim_ifp = ifp->info;
- zassert(pim_ifp);
++pim_ifp->pim_ifstat_reg_recv;
/*
@@ -319,7 +324,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
sg.src = ip_hdr->ip_src;
sg.grp = ip_hdr->ip_dst;
- i_am_rp = I_am_RP(sg.grp);
+ i_am_rp = I_am_RP(pim_ifp->pim, sg.grp);
if (PIM_DEBUG_PIM_REG) {
char src_str[INET_ADDRSTRLEN];
@@ -330,8 +335,9 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
}
- if (i_am_rp && (dest_addr.s_addr
- == ((RP(sg.grp))->rpf_addr.u.prefix4.s_addr))) {
+ if (i_am_rp
+ && (dest_addr.s_addr
+ == ((RP(pim_ifp->pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
sentRegisterStop = 0;
if (*bits & PIM_REGISTER_BORDER_BIT) {
@@ -355,25 +361,50 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
}
}
- struct pim_upstream *upstream = pim_upstream_find(&sg);
+ struct pim_upstream *upstream =
+ pim_upstream_find(pim_ifp->pim, &sg);
/*
* If we don't have a place to send ignore the packet
*/
if (!upstream) {
upstream = pim_upstream_add(
- &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
- __PRETTY_FUNCTION__);
+ pim_ifp->pim, &sg, ifp,
+ PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
+ __PRETTY_FUNCTION__, NULL);
if (!upstream) {
zlog_warn("Failure to create upstream state");
return 1;
}
upstream->upstream_register = src_addr;
+ } else {
+ /*
+ * If the FHR has set a very very fast register timer
+ * there exists a possibility that the incoming NULL
+ * register
+ * is happening before we set the spt bit. If so
+ * Do a quick check to update the counters and
+ * then set the spt bit as appropriate
+ */
+ if (upstream->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
+ pim_mroute_update_counters(
+ upstream->channel_oil);
+ /*
+ * Have we seen packets?
+ */
+ if (upstream->channel_oil->cc.oldpktcnt
+ < upstream->channel_oil->cc.pktcnt)
+ pim_upstream_set_sptbit(
+ upstream,
+ upstream->rpf.source_nexthop
+ .interface);
+ }
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || ((SwitchToSptDesired(&sg))
- && pim_upstream_inherited_olist(upstream) == 0)) {
+ || ((SwitchToSptDesired(pim_ifp->pim, &sg))
+ && pim_upstream_inherited_olist(pim_ifp->pim, upstream)
+ == 0)) {
// pim_scan_individual_oil (upstream->channel_oil);
pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
sentRegisterStop = 1;
@@ -383,13 +414,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
upstream->sptbit);
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || (SwitchToSptDesired(&sg))) {
+ || (SwitchToSptDesired(pim_ifp->pim, &sg))) {
if (sentRegisterStop) {
pim_upstream_keep_alive_timer_start(
- upstream, qpim_rp_keep_alive_time);
+ upstream, pim_ifp->pim->rp_keep_alive_time);
} else {
pim_upstream_keep_alive_timer_start(
- upstream, qpim_keep_alive_time);
+ upstream, pim_ifp->pim->keep_alive_time);
}
}
diff --git a/pimd/pim_register.h b/pimd/pim_register.h
index ad3deb2b24..906d093bb7 100644
--- a/pimd/pim_register.h
+++ b/pimd/pim_register.h
@@ -30,7 +30,7 @@
#define PIM_MSG_REGISTER_LEN (8)
#define PIM_MSG_REGISTER_STOP_LEN (4)
-int pim_register_stop_recv(uint8_t *buf, int buf_size);
+int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size);
int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
struct in_addr src_addr, uint8_t *tlv_buf,
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 2fe0143a87..05592992a9 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -45,8 +45,20 @@
#include "pim_nht.h"
-static struct list *qpim_rp_list = NULL;
-static struct rp_info *tail = NULL;
+/* Cleanup pim->rpf_hash each node data */
+void pim_rp_list_hash_clean(void *data)
+{
+ struct pim_nexthop_cache *pnc = (struct pim_nexthop_cache *)data;
+
+ list_delete(pnc->rp_list);
+ pnc->rp_list = NULL;
+
+ hash_clean(pnc->upstream_hash, NULL);
+ hash_free(pnc->upstream_hash);
+ pnc->upstream_hash = NULL;
+
+ XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc);
+}
static void pim_rp_info_free(struct rp_info *rp_info)
{
@@ -81,46 +93,49 @@ int pim_rp_list_cmp(void *v1, void *v2)
return 0;
}
-void pim_rp_init(void)
+void pim_rp_init(struct pim_instance *pim)
{
struct rp_info *rp_info;
- qpim_rp_list = list_new();
- qpim_rp_list->del = (void (*)(void *))pim_rp_info_free;
- qpim_rp_list->cmp = pim_rp_list_cmp;
+ pim->rp_list = list_new();
+ pim->rp_list->del = (void (*)(void *))pim_rp_info_free;
+ pim->rp_list->cmp = pim_rp_list_cmp;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
if (!rp_info)
return;
- str2prefix("224.0.0.0/4", &rp_info->group);
+ if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
+ XFREE(MTYPE_PIM_RP, rp_info);
+ return;
+ }
rp_info->group.family = AF_INET;
rp_info->rp.rpf_addr.family = AF_INET;
rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN;
rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
- tail = rp_info;
- listnode_add(qpim_rp_list, rp_info);
+ listnode_add(pim->rp_list, rp_info);
}
-void pim_rp_free(void)
+void pim_rp_free(struct pim_instance *pim)
{
- if (qpim_rp_list)
- list_delete(qpim_rp_list);
- qpim_rp_list = NULL;
+ if (pim->rp_list)
+ list_delete(pim->rp_list);
+ pim->rp_list = NULL;
}
/*
* Given an RP's prefix-list, return the RP's rp_info for that prefix-list
*/
-static struct rp_info *pim_rp_find_prefix_list(struct in_addr rp,
+static struct rp_info *pim_rp_find_prefix_list(struct pim_instance *pim,
+ struct in_addr rp,
const char *plist)
{
struct listnode *node;
struct rp_info *rp_info;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr
&& rp_info->plist && strcmp(rp_info->plist, plist) == 0) {
return rp_info;
@@ -133,12 +148,12 @@ static struct rp_info *pim_rp_find_prefix_list(struct in_addr rp,
/*
* Return true if plist is used by any rp_info
*/
-static int pim_rp_prefix_list_used(const char *plist)
+static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist)
{
struct listnode *node;
struct rp_info *rp_info;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) {
return 1;
}
@@ -151,13 +166,14 @@ static int pim_rp_prefix_list_used(const char *plist)
* Given an RP's address, return the RP's rp_info that is an exact match for
* 'group'
*/
-static struct rp_info *pim_rp_find_exact(struct in_addr rp,
+static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
+ struct in_addr rp,
struct prefix *group)
{
struct listnode *node;
struct rp_info *rp_info;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr
&& prefix_same(&rp_info->group, group))
return rp_info;
@@ -169,13 +185,14 @@ static struct rp_info *pim_rp_find_exact(struct in_addr rp,
/*
* Given a group, return the rp_info for that group
*/
-static struct rp_info *pim_rp_find_match_group(struct prefix *group)
+static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
+ struct prefix *group)
{
struct listnode *node;
struct rp_info *rp_info;
struct prefix_list *plist;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->plist) {
plist = prefix_list_lookup(AFI_IP, rp_info->plist);
@@ -198,18 +215,19 @@ static struct rp_info *pim_rp_find_match_group(struct prefix *group)
*
* This is a placeholder function for now.
*/
-static void pim_rp_refresh_group_to_rp_mapping()
+static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim)
{
- pim_msdp_i_am_rp_changed();
+ pim_msdp_i_am_rp_changed(pim);
}
-void pim_rp_prefix_list_update(struct prefix_list *plist)
+void pim_rp_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *plist)
{
struct listnode *node;
struct rp_info *rp_info;
int refresh_needed = 0;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->plist
&& strcmp(rp_info->plist, prefix_list_name(plist)) == 0) {
refresh_needed = 1;
@@ -218,7 +236,7 @@ void pim_rp_prefix_list_update(struct prefix_list *plist)
}
if (refresh_needed)
- pim_rp_refresh_group_to_rp_mapping();
+ pim_rp_refresh_group_to_rp_mapping(pim);
}
static int pim_rp_check_interface_addrs(struct rp_info *rp_info,
@@ -244,13 +262,14 @@ static int pim_rp_check_interface_addrs(struct rp_info *rp_info,
return 0;
}
-static void pim_rp_check_interfaces(struct rp_info *rp_info)
+static void pim_rp_check_interfaces(struct pim_instance *pim,
+ struct rp_info *rp_info)
{
struct listnode *node;
struct interface *ifp;
rp_info->i_am_rp = 0;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp)
@@ -262,7 +281,8 @@ static void pim_rp_check_interfaces(struct rp_info *rp_info)
}
}
-int pim_rp_new(const char *rp, const char *group_range, const char *plist)
+int pim_rp_new(struct pim_instance *pim, const char *rp,
+ const char *group_range, const char *plist)
{
int result = 0;
struct rp_info *rp_info;
@@ -302,7 +322,7 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
/*
* Return if the prefix-list is already configured for this RP
*/
- if (pim_rp_find_prefix_list(rp_info->rp.rpf_addr.u.prefix4,
+ if (pim_rp_find_prefix_list(pim, rp_info->rp.rpf_addr.u.prefix4,
plist)) {
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_SUCCESS;
@@ -311,7 +331,7 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
/*
* Barf if the prefix-list is already configured for an RP
*/
- if (pim_rp_prefix_list_used(plist)) {
+ if (pim_rp_prefix_list_used(pim, plist)) {
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_RP_PFXLIST_IN_USE;
}
@@ -319,16 +339,16 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
/*
* Free any existing rp_info entries for this RP
*/
- for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode,
+ for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
tmp_rp_info)) {
if (rp_info->rp.rpf_addr.u.prefix4.s_addr
== tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) {
if (tmp_rp_info->plist)
- pim_rp_del(rp, NULL,
+ pim_rp_del(pim, rp, NULL,
tmp_rp_info->plist);
else
pim_rp_del(
- rp,
+ pim, rp,
prefix2str(&tmp_rp_info->group,
buffer, BUFSIZ),
NULL);
@@ -337,8 +357,11 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist);
} else {
- str2prefix("224.0.0.0/4", &group_all);
- rp_all = pim_rp_find_match_group(&group_all);
+ if (!str2prefix("224.0.0.0/4", &group_all)) {
+ XFREE(MTYPE_PIM_RP, rp_info);
+ return PIM_GROUP_BAD_ADDRESS;
+ }
+ rp_all = pim_rp_find_match_group(pim, &group_all);
/*
* Barf if group is a non-multicast subnet
@@ -351,13 +374,13 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
/*
* Remove any prefix-list rp_info entries for this RP
*/
- for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode,
+ for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
tmp_rp_info)) {
if (tmp_rp_info->plist
&& rp_info->rp.rpf_addr.u.prefix4.s_addr
== tmp_rp_info->rp.rpf_addr.u.prefix4
.s_addr) {
- pim_rp_del(rp, NULL, tmp_rp_info->plist);
+ pim_rp_del(pim, rp, NULL, tmp_rp_info->plist);
}
}
@@ -384,31 +407,29 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
__PRETTY_FUNCTION__, buf, buf1);
}
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_all,
- &pnc))
- == 1) {
- // Compute PIM RPF using Cached nexthop
- if ((pim_ecmp_nexthop_search(
- &pnc, &rp_all->rp.source_nexthop,
- &nht_p, &rp_all->group, 1))
- != 0)
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
+ &pnc)) {
+ if (!pim_ecmp_nexthop_search(
+ pim, &pnc,
+ &rp_all->rp.source_nexthop, &nht_p,
+ &rp_all->group, 1))
return PIM_RP_NO_PATH;
} else {
if (pim_nexthop_lookup(
- &rp_all->rp.source_nexthop,
+ pim, &rp_all->rp.source_nexthop,
rp_all->rp.rpf_addr.u.prefix4, 1)
!= 0)
return PIM_RP_NO_PATH;
}
- pim_rp_check_interfaces(rp_all);
- pim_rp_refresh_group_to_rp_mapping();
+ pim_rp_check_interfaces(pim, rp_all);
+ pim_rp_refresh_group_to_rp_mapping(pim);
return PIM_SUCCESS;
}
/*
* Return if the group is already configured for this RP
*/
- if (pim_rp_find_exact(rp_info->rp.rpf_addr.u.prefix4,
+ if (pim_rp_find_exact(pim, rp_info->rp.rpf_addr.u.prefix4,
&rp_info->group)) {
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_SUCCESS;
@@ -417,7 +438,7 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
/*
* Barf if this group is already covered by some other RP
*/
- tmp_rp_info = pim_rp_find_match_group(&rp_info->group);
+ tmp_rp_info = pim_rp_find_match_group(pim, &rp_info->group);
if (tmp_rp_info) {
if (tmp_rp_info->plist) {
@@ -440,7 +461,7 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
}
}
- listnode_add_sort(qpim_rp_list, rp_info);
+ listnode_add_sort(pim->rp_list, rp_info);
/* Register addr with Zebra NHT */
nht_p.family = AF_INET;
@@ -456,25 +477,25 @@ int pim_rp_new(const char *rp, const char *group_range, const char *plist)
}
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) == 1) {
- // Compute PIM RPF using Cached nexthop
- if (pim_ecmp_nexthop_search(&pnc, &rp_info->rp.source_nexthop,
- &nht_p, &rp_info->group, 1)
- != 0)
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, &pnc)) {
+ if (!pim_ecmp_nexthop_search(pim, &pnc,
+ &rp_info->rp.source_nexthop,
+ &nht_p, &rp_info->group, 1))
return PIM_RP_NO_PATH;
} else {
- if (pim_nexthop_lookup(&rp_info->rp.source_nexthop,
+ if (pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
rp_info->rp.rpf_addr.u.prefix4, 1)
!= 0)
return PIM_RP_NO_PATH;
}
- pim_rp_check_interfaces(rp_info);
- pim_rp_refresh_group_to_rp_mapping();
+ pim_rp_check_interfaces(pim, rp_info);
+ pim_rp_refresh_group_to_rp_mapping(pim);
return PIM_SUCCESS;
}
-int pim_rp_del(const char *rp, const char *group_range, const char *plist)
+int pim_rp_del(struct pim_instance *pim, const char *rp,
+ const char *group_range, const char *plist)
{
struct prefix group;
struct in_addr rp_addr;
@@ -497,9 +518,9 @@ int pim_rp_del(const char *rp, const char *group_range, const char *plist)
return PIM_RP_BAD_ADDRESS;
if (plist)
- rp_info = pim_rp_find_prefix_list(rp_addr, plist);
+ rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist);
else
- rp_info = pim_rp_find_exact(rp_addr, &group);
+ rp_info = pim_rp_find_exact(pim, rp_addr, &group);
if (!rp_info)
return PIM_RP_NOT_FOUND;
@@ -519,10 +540,10 @@ int pim_rp_del(const char *rp, const char *group_range, const char *plist)
zlog_debug("%s: Deregister RP addr %s with Zebra ",
__PRETTY_FUNCTION__, buf);
}
- pim_delete_tracked_nexthop(&nht_p, NULL, rp_info);
+ pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info);
str2prefix("224.0.0.0/4", &g_all);
- rp_all = pim_rp_find_match_group(&g_all);
+ rp_all = pim_rp_find_match_group(pim, &g_all);
if (rp_all == rp_info) {
rp_all->rp.rpf_addr.family = AF_INET;
@@ -531,20 +552,19 @@ int pim_rp_del(const char *rp, const char *group_range, const char *plist)
return PIM_SUCCESS;
}
- listnode_delete(qpim_rp_list, rp_info);
- pim_rp_refresh_group_to_rp_mapping();
+ listnode_delete(pim->rp_list, rp_info);
+ pim_rp_refresh_group_to_rp_mapping(pim);
return PIM_SUCCESS;
}
-int pim_rp_setup(void)
+void pim_rp_setup(struct pim_instance *pim)
{
struct listnode *node;
struct rp_info *rp_info;
- int ret = 0;
struct prefix nht_p;
struct pim_nexthop_cache pnc;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
continue;
@@ -552,15 +572,11 @@ int pim_rp_setup(void)
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc))
- == 1) {
- // Compute PIM RPF using Cached nexthop
- if ((pim_ecmp_nexthop_search(
- &pnc, &rp_info->rp.source_nexthop, &nht_p,
- &rp_info->group, 1))
- != 0)
- ret++;
- } else {
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, &pnc))
+ pim_ecmp_nexthop_search(pim, &pnc,
+ &rp_info->rp.source_nexthop,
+ &nht_p, &rp_info->group, 1);
+ else {
if (PIM_DEBUG_ZEBRA) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&nht_p, buf, sizeof(buf));
@@ -568,22 +584,14 @@ int pim_rp_setup(void)
"%s: NHT Local Nexthop not found for RP %s ",
__PRETTY_FUNCTION__, buf);
}
- if (pim_nexthop_lookup(&rp_info->rp.source_nexthop,
- rp_info->rp.rpf_addr.u.prefix4,
- 1)
- != 0) {
+ if (!pim_nexthop_lookup(
+ pim, &rp_info->rp.source_nexthop,
+ rp_info->rp.rpf_addr.u.prefix4, 1))
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"Unable to lookup nexthop for rp specified");
- ret++;
- }
}
}
-
- if (ret)
- return 0;
-
- return 1;
}
/*
@@ -595,11 +603,12 @@ void pim_rp_check_on_if_add(struct pim_interface *pim_ifp)
struct listnode *node;
struct rp_info *rp_info;
bool i_am_rp_changed = false;
+ struct pim_instance *pim = pim_ifp->pim;
- if (qpim_rp_list == NULL)
+ if (pim->rp_list == NULL)
return;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
continue;
@@ -623,29 +632,29 @@ void pim_rp_check_on_if_add(struct pim_interface *pim_ifp)
}
if (i_am_rp_changed) {
- pim_msdp_i_am_rp_changed();
+ pim_msdp_i_am_rp_changed(pim);
}
}
/* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses
* are removed. Removing numbers is an uncommon event in an active network
* so I have made no attempt to optimize it. */
-void pim_i_am_rp_re_evaluate(void)
+void pim_i_am_rp_re_evaluate(struct pim_instance *pim)
{
struct listnode *node;
struct rp_info *rp_info;
bool i_am_rp_changed = false;
int old_i_am_rp;
- if (qpim_rp_list == NULL)
+ if (pim->rp_list == NULL)
return;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
continue;
old_i_am_rp = rp_info->i_am_rp;
- pim_rp_check_interfaces(rp_info);
+ pim_rp_check_interfaces(pim, rp_info);
if (old_i_am_rp != rp_info->i_am_rp) {
i_am_rp_changed = true;
@@ -665,7 +674,7 @@ void pim_i_am_rp_re_evaluate(void)
}
if (i_am_rp_changed) {
- pim_msdp_i_am_rp_changed();
+ pim_msdp_i_am_rp_changed(pim);
}
}
@@ -675,7 +684,7 @@ void pim_i_am_rp_re_evaluate(void)
*
* Since we only have static RP, all groups are part of this RP
*/
-int pim_rp_i_am_rp(struct in_addr group)
+int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
{
struct prefix g;
struct rp_info *rp_info;
@@ -685,7 +694,7 @@ int pim_rp_i_am_rp(struct in_addr group)
g.prefixlen = 32;
g.u.prefix4 = group;
- rp_info = pim_rp_find_match_group(&g);
+ rp_info = pim_rp_find_match_group(pim, &g);
if (rp_info)
return rp_info->i_am_rp;
@@ -698,7 +707,7 @@ int pim_rp_i_am_rp(struct in_addr group)
*
* Return the RP that the Group belongs too.
*/
-struct pim_rpf *pim_rp_g(struct in_addr group)
+struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
{
struct prefix g;
struct rp_info *rp_info;
@@ -708,7 +717,7 @@ struct pim_rpf *pim_rp_g(struct in_addr group)
g.prefixlen = 32;
g.u.prefix4 = group;
- rp_info = pim_rp_find_match_group(&g);
+ rp_info = pim_rp_find_match_group(pim, &g);
if (rp_info) {
struct prefix nht_p;
@@ -727,13 +736,11 @@ struct pim_rpf *pim_rp_g(struct in_addr group)
__PRETTY_FUNCTION__, buf, buf1);
}
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc))
- == 1) {
- // Compute PIM RPF using Cached nexthop
- pim_ecmp_nexthop_search(&pnc,
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, &pnc))
+ pim_ecmp_nexthop_search(pim, &pnc,
&rp_info->rp.source_nexthop,
&nht_p, &rp_info->group, 1);
- } else {
+ else {
if (PIM_DEBUG_ZEBRA) {
char buf[PREFIX2STR_BUFFER];
char buf1[PREFIX2STR_BUFFER];
@@ -744,7 +751,7 @@ struct pim_rpf *pim_rp_g(struct in_addr group)
__PRETTY_FUNCTION__, buf, buf1);
}
pim_rpf_set_refresh_time();
- pim_nexthop_lookup(&rp_info->rp.source_nexthop,
+ pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
rp_info->rp.rpf_addr.u.prefix4, 1);
}
return (&rp_info->rp);
@@ -762,8 +769,8 @@ struct pim_rpf *pim_rp_g(struct in_addr group)
* then return failure.
*
*/
-int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source,
- struct in_addr group)
+int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
+ struct in_addr source, struct in_addr group)
{
struct rp_info *rp_info;
struct prefix g;
@@ -773,7 +780,7 @@ int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source,
g.prefixlen = 32;
g.u.prefix4 = group;
- rp_info = pim_rp_find_match_group(&g);
+ rp_info = pim_rp_find_match_group(pim, &g);
if ((pim_rpf_addr_is_inaddr_none(&rp_info->rp))
&& (source.s_addr == INADDR_ANY)) {
@@ -789,7 +796,8 @@ int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source,
return 1;
}
-int pim_rp_config_write(struct vty *vty)
+int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
+ const char *spaces)
{
struct listnode *node;
struct rp_info *rp_info;
@@ -797,18 +805,18 @@ int pim_rp_config_write(struct vty *vty)
char group_buffer[32];
int count = 0;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
continue;
if (rp_info->plist)
- vty_out(vty, "ip pim rp %s prefix-list %s\n",
+ vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces,
inet_ntop(AF_INET,
&rp_info->rp.rpf_addr.u.prefix4,
rp_buffer, 32),
rp_info->plist);
else
- vty_out(vty, "ip pim rp %s %s\n",
+ vty_out(vty, "%sip pim rp %s %s\n", spaces,
inet_ntop(AF_INET,
&rp_info->rp.rpf_addr.u.prefix4,
rp_buffer, 32),
@@ -819,7 +827,8 @@ int pim_rp_config_write(struct vty *vty)
return count;
}
-int pim_rp_check_is_my_ip_address(struct in_addr group,
+int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+ struct in_addr group,
struct in_addr dest_addr)
{
struct rp_info *rp_info;
@@ -830,25 +839,26 @@ int pim_rp_check_is_my_ip_address(struct in_addr group,
g.prefixlen = 32;
g.u.prefix4 = group;
- rp_info = pim_rp_find_match_group(&g);
+ rp_info = pim_rp_find_match_group(pim, &g);
/*
* See if we can short-cut some?
* This might not make sense if we ever leave a static RP
* type of configuration.
* Note - Premature optimization might bite our patooeys' here.
*/
- if (I_am_RP(group)) {
+ if (I_am_RP(pim, group)) {
if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)
return 1;
}
- if (if_lookup_exact_address(&dest_addr, AF_INET, VRF_DEFAULT))
+ if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf_id))
return 1;
return 0;
}
-void pim_rp_show_information(struct vty *vty, u_char uj)
+void pim_rp_show_information(struct pim_instance *pim, struct vty *vty,
+ u_char uj)
{
struct rp_info *rp_info;
struct rp_info *prev_rp_info = NULL;
@@ -864,7 +874,7 @@ void pim_rp_show_information(struct vty *vty, u_char uj)
vty_out(vty,
"RP address group/prefix-list OIF I am RP\n");
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) {
char buf[48];
@@ -954,7 +964,7 @@ void pim_rp_show_information(struct vty *vty, u_char uj)
}
}
-void pim_resolve_rp_nh(void)
+void pim_resolve_rp_nh(struct pim_instance *pim)
{
struct listnode *node = NULL;
struct rp_info *rp_info = NULL;
@@ -963,7 +973,7 @@ void pim_resolve_rp_nh(void)
struct pim_nexthop_cache pnc;
struct pim_neighbor *nbr = NULL;
- for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
continue;
@@ -971,43 +981,32 @@ void pim_resolve_rp_nh(void)
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc))
- == 1) {
- for (nh_node = pnc.nexthop; nh_node;
- nh_node = nh_node->next) {
- if (nh_node->gate.ipv4.s_addr == 0) {
- nbr = pim_neighbor_find_if(
- if_lookup_by_index(
- nh_node->ifindex,
- VRF_DEFAULT));
- if (nbr) {
- nh_node->gate.ipv4 =
- nbr->source_addr;
- if (PIM_DEBUG_TRACE) {
- char str[PREFIX_STRLEN];
- char str1
- [INET_ADDRSTRLEN];
- struct interface *ifp1 =
- if_lookup_by_index(
- nh_node->ifindex,
- VRF_DEFAULT);
- pim_inet4_dump(
- "<nht_nbr?>",
- nbr->source_addr,
- str1,
- sizeof(str1));
- pim_addr_dump(
- "<nht_addr?>",
- &nht_p, str,
- sizeof(str));
- zlog_debug(
- "%s: addr %s new nexthop addr %s interface %s",
- __PRETTY_FUNCTION__,
- str, str1,
- ifp1->name);
- }
- }
- }
+ if (!pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info,
+ &pnc))
+ continue;
+
+ for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
+ if (nh_node->gate.ipv4.s_addr != 0)
+ continue;
+
+ struct interface *ifp1 = if_lookup_by_index(
+ nh_node->ifindex, pim->vrf_id);
+ nbr = pim_neighbor_find_if(ifp1);
+ if (!nbr)
+ continue;
+
+ nh_node->gate.ipv4 = nbr->source_addr;
+ if (PIM_DEBUG_TRACE) {
+ char str[PREFIX_STRLEN];
+ char str1[INET_ADDRSTRLEN];
+ pim_inet4_dump("<nht_nbr?>", nbr->source_addr,
+ str1, sizeof(str1));
+ pim_addr_dump("<nht_addr?>", &nht_p, str,
+ sizeof(str));
+ zlog_debug(
+ "%s: addr %s new nexthop addr %s interface %s",
+ __PRETTY_FUNCTION__, str, str1,
+ ifp1->name);
}
}
}
diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h
index 7a7c26593e..e07d65137f 100644
--- a/pimd/pim_rp.h
+++ b/pimd/pim_rp.h
@@ -34,33 +34,41 @@ struct rp_info {
char *plist;
};
-void pim_rp_init(void);
-void pim_rp_free(void);
+void pim_rp_init(struct pim_instance *pim);
+void pim_rp_free(struct pim_instance *pim);
-int pim_rp_new(const char *rp, const char *group, const char *plist);
-int pim_rp_del(const char *rp, const char *group, const char *plist);
-void pim_rp_prefix_list_update(struct prefix_list *plist);
+void pim_rp_list_hash_clean(void *data);
-int pim_rp_config_write(struct vty *vty);
+int pim_rp_new(struct pim_instance *pim, const char *rp, const char *group,
+ const char *plist);
+int pim_rp_del(struct pim_instance *pim, const char *rp, const char *group,
+ const char *plist);
+void pim_rp_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *plist);
-int pim_rp_setup(void);
+int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
+ const char *spaces);
-int pim_rp_i_am_rp(struct in_addr group);
+void pim_rp_setup(struct pim_instance *pim);
+
+int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group);
void pim_rp_check_on_if_add(struct pim_interface *pim_ifp);
-void pim_i_am_rp_re_evaluate(void);
+void pim_i_am_rp_re_evaluate(struct pim_instance *pim);
-int pim_rp_check_is_my_ip_address(struct in_addr group,
+int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+ struct in_addr group,
struct in_addr dest_addr);
-int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source,
- struct in_addr group);
+int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
+ struct in_addr source, struct in_addr group);
-struct pim_rpf *pim_rp_g(struct in_addr group);
+struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group);
-#define I_am_RP(G) pim_rp_i_am_rp ((G))
-#define RP(G) pim_rp_g ((G))
+#define I_am_RP(P, G) pim_rp_i_am_rp ((P), (G))
+#define RP(P, G) pim_rp_g ((P), (G))
-void pim_rp_show_information(struct vty *vty, u_char uj);
-void pim_resolve_rp_nh(void);
+void pim_rp_show_information(struct pim_instance *pim, struct vty *vty,
+ u_char uj);
+void pim_resolve_rp_nh(struct pim_instance *pim);
int pim_rp_list_cmp(void *v1, void *v2);
#endif
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 4d0652c27e..36c6c894ef 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -24,6 +24,7 @@
#include "log.h"
#include "prefix.h"
#include "memory.h"
+#include "jhash.h"
#include "pimd.h"
#include "pim_rpf.h"
@@ -34,6 +35,7 @@
#include "pim_ifchannel.h"
#include "pim_time.h"
#include "pim_nht.h"
+#include "pim_oil.h"
static long long last_route_change_time = -1;
long long nexthop_lookups_avoided = 0;
@@ -48,8 +50,8 @@ void pim_rpf_set_refresh_time(void)
__PRETTY_FUNCTION__, last_route_change_time);
}
-int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
- int neighbor_needed)
+int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
+ struct in_addr addr, int neighbor_needed)
{
struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
struct pim_neighbor *nbr = NULL;
@@ -91,8 +93,8 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
memset(nexthop_tab, 0,
sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM);
- num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr,
- PIM_NEXTHOP_LOOKUP_MAX);
+ num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
+ addr, PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
@@ -105,7 +107,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
while (!found && (i < num_ifindex)) {
first_ifindex = nexthop_tab[i].ifindex;
- ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
if (!ifp) {
if (PIM_DEBUG_ZEBRA) {
char addr_str[INET_ADDRSTRLEN];
@@ -186,14 +188,14 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1,
|| (nh1->mrib_route_metric != nh2->mrib_route_metric);
}
-enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
+enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
+ struct pim_upstream *up, struct pim_rpf *old,
uint8_t is_new)
{
struct pim_rpf *rpf = &up->rpf;
struct pim_rpf saved;
struct prefix nht_p;
struct pim_nexthop_cache pnc;
- int ret = 0;
struct prefix src, grp;
saved.source_nexthop = rpf->source_nexthop;
@@ -218,27 +220,23 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((ret = pim_find_or_track_nexthop(&nht_p, up, NULL, &pnc)) == 1) {
+ if (pim_find_or_track_nexthop(pim, &nht_p, up, NULL, &pnc)) {
if (pnc.nexthop_num) {
- // Compute PIM RPF using Cached nexthop
- if (pim_ecmp_nexthop_search(
- &pnc, &up->rpf.source_nexthop, &src, &grp,
+ if (!pim_ecmp_nexthop_search(
+ pim, &pnc, &up->rpf.source_nexthop, &src,
+ &grp,
!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)
&& !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(
up->flags)))
-
- {
return PIM_RPF_FAILURE;
- }
}
} else {
- if (pim_ecmp_nexthop_lookup(
- &rpf->source_nexthop, up->upstream_addr, &src, &grp,
- !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)
- && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(
- up->flags))) {
+ if (!pim_ecmp_nexthop_lookup(
+ pim, &rpf->source_nexthop, up->upstream_addr, &src,
+ &grp, !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)
+ && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(
+ up->flags)))
return PIM_RPF_FAILURE;
- }
}
rpf->rpf_addr.family = AF_INET;
@@ -267,7 +265,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
rpf->source_nexthop.mrib_route_metric);
}
- pim_upstream_update_join_desired(up);
+ pim_upstream_update_join_desired(pim, up);
pim_upstream_update_could_assert(up);
pim_upstream_update_my_assert_metric(up);
}
@@ -396,3 +394,20 @@ int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2)
return 0;
}
+
+unsigned int pim_rpf_hash_key(void *arg)
+{
+ struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg;
+
+ return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0);
+}
+
+int pim_rpf_equal(const void *arg1, const void *arg2)
+{
+ const struct pim_nexthop_cache *r1 =
+ (const struct pim_nexthop_cache *)arg1;
+ const struct pim_nexthop_cache *r2 =
+ (const struct pim_nexthop_cache *)arg2;
+
+ return prefix_same(&r1->rpf.rpf_addr, &r2->rpf.rpf_addr);
+}
diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h
index 0833143563..86032f1c29 100644
--- a/pimd/pim_rpf.h
+++ b/pimd/pim_rpf.h
@@ -58,9 +58,13 @@ struct pim_upstream;
extern long long nexthop_lookups_avoided;
-int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr,
- int neighbor_needed);
-enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
+unsigned int pim_rpf_hash_key(void *arg);
+int pim_rpf_equal(const void *arg1, const void *arg2);
+
+int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
+ struct in_addr addr, int neighbor_needed);
+enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
+ struct pim_upstream *up, struct pim_rpf *old,
uint8_t is_new);
int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c
index 3046e94299..8d270e6205 100644
--- a/pimd/pim_ssm.c
+++ b/pimd/pim_ssm.c
@@ -29,7 +29,7 @@
#include "pim_ssm.h"
#include "pim_zebra.h"
-static void pim_ssm_range_reevaluate(void)
+static void pim_ssm_range_reevaluate(struct pim_instance *pim)
{
/* 1. Setup register state for (S,G) entries if G has changed from SSM
* to
@@ -47,13 +47,14 @@ static void pim_ssm_range_reevaluate(void)
* will
* disappear in time for SSM groups.
*/
- pim_upstream_register_reevaluate();
+ pim_upstream_register_reevaluate(pim);
igmp_source_forward_reevaluate_all();
}
-void pim_ssm_prefix_list_update(struct prefix_list *plist)
+void pim_ssm_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *plist)
{
- struct pim_ssm *ssm = pimg->ssm_info;
+ struct pim_ssm *ssm = pim->ssm_info;
if (!ssm->plist_name
|| strcmp(ssm->plist_name, prefix_list_name(plist))) {
@@ -61,7 +62,7 @@ void pim_ssm_prefix_list_update(struct prefix_list *plist)
return;
}
- pim_ssm_range_reevaluate();
+ pim_ssm_range_reevaluate(pim);
}
static int pim_is_grp_standard_ssm(struct prefix *group)
@@ -77,7 +78,7 @@ static int pim_is_grp_standard_ssm(struct prefix *group)
return prefix_match(&group_ssm, group);
}
-int pim_is_grp_ssm(struct in_addr group_addr)
+int pim_is_grp_ssm(struct pim_instance *pim, struct in_addr group_addr)
{
struct pim_ssm *ssm;
struct prefix group;
@@ -88,7 +89,7 @@ int pim_is_grp_ssm(struct in_addr group_addr)
group.u.prefix4 = group_addr;
group.prefixlen = 32;
- ssm = pimg->ssm_info;
+ ssm = pim->ssm_info;
if (!ssm->plist_name) {
return pim_is_grp_standard_ssm(&group);
}
@@ -100,15 +101,16 @@ int pim_is_grp_ssm(struct in_addr group_addr)
return (prefix_list_apply(plist, &group) == PREFIX_PERMIT);
}
-int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name)
+int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id,
+ const char *plist_name)
{
struct pim_ssm *ssm;
int change = 0;
- if (vrf_id != VRF_DEFAULT)
+ if (vrf_id != pim->vrf_id)
return PIM_SSM_ERR_NO_VRF;
- ssm = pimg->ssm_info;
+ ssm = pim->ssm_info;
if (plist_name) {
if (ssm->plist_name) {
if (!strcmp(ssm->plist_name, plist_name))
@@ -125,17 +127,16 @@ int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name)
}
if (change)
- pim_ssm_range_reevaluate();
+ pim_ssm_range_reevaluate(pim);
return PIM_SSM_ERR_NONE;
}
-void *pim_ssm_init(vrf_id_t vrf_id)
+void *pim_ssm_init(void)
{
struct pim_ssm *ssm;
ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm));
- ssm->vrf_id = vrf_id;
return ssm;
}
diff --git a/pimd/pim_ssm.h b/pimd/pim_ssm.h
index 9e89d0c80c..7235ade8dc 100644
--- a/pimd/pim_ssm.h
+++ b/pimd/pim_ssm.h
@@ -29,13 +29,14 @@ enum pim_ssm_err {
};
struct pim_ssm {
- vrf_id_t vrf_id;
char *plist_name; /* prefix list of group ranges */
};
-void pim_ssm_prefix_list_update(struct prefix_list *plist);
-int pim_is_grp_ssm(struct in_addr group_addr);
-int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name);
-void *pim_ssm_init(vrf_id_t vrf_id);
+void pim_ssm_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *plist);
+int pim_is_grp_ssm(struct pim_instance *pim, struct in_addr group_addr);
+int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id,
+ const char *plist_name);
+void *pim_ssm_init(void);
void pim_ssm_terminate(struct pim_ssm *ssm);
#endif
diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c
index 406183db86..9e90a34687 100644
--- a/pimd/pim_ssmpingd.c
+++ b/pimd/pim_ssmpingd.c
@@ -36,35 +36,36 @@ enum { PIM_SSMPINGD_REQUEST = 'Q', PIM_SSMPINGD_REPLY = 'A' };
static void ssmpingd_read_on(struct ssmpingd_sock *ss);
-void pim_ssmpingd_init()
+void pim_ssmpingd_init(struct pim_instance *pim)
{
int result;
- zassert(!qpim_ssmpingd_list);
+ zassert(!pim->ssmpingd_list);
result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP,
- &qpim_ssmpingd_group_addr);
+ &pim->ssmpingd_group_addr);
zassert(result > 0);
}
-void pim_ssmpingd_destroy()
+void pim_ssmpingd_destroy(struct pim_instance *pim)
{
- if (qpim_ssmpingd_list) {
- list_free(qpim_ssmpingd_list);
- qpim_ssmpingd_list = 0;
+ if (pim->ssmpingd_list) {
+ list_delete(pim->ssmpingd_list);
+ pim->ssmpingd_list = 0;
}
}
-static struct ssmpingd_sock *ssmpingd_find(struct in_addr source_addr)
+static struct ssmpingd_sock *ssmpingd_find(struct pim_instance *pim,
+ struct in_addr source_addr)
{
struct listnode *node;
struct ssmpingd_sock *ss;
- if (!qpim_ssmpingd_list)
+ if (!pim->ssmpingd_list)
return 0;
- for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss))
+ for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss))
if (source_addr.s_addr == ss->source_addr.s_addr)
return ss;
@@ -202,7 +203,6 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl)
static void ssmpingd_delete(struct ssmpingd_sock *ss)
{
zassert(ss);
- zassert(qpim_ssmpingd_list);
THREAD_OFF(ss->t_sock_read);
@@ -217,7 +217,7 @@ static void ssmpingd_delete(struct ssmpingd_sock *ss)
/* warning only */
}
- listnode_delete(qpim_ssmpingd_list, ss);
+ listnode_delete(ss->pim->ssmpingd_list, ss);
ssmpingd_free(ss);
}
@@ -272,7 +272,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss)
return -1;
}
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(ifindex, ss->pim->vrf_id);
if (buf[0] != PIM_SSMPINGD_REQUEST) {
char source_str[INET_ADDRSTRLEN];
@@ -315,7 +315,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss)
ssmpingd_sendto(ss, buf, len, from);
/* multicast reply */
- from.sin_addr = qpim_ssmpingd_group_addr;
+ from.sin_addr = ss->pim->ssmpingd_group_addr;
ssmpingd_sendto(ss, buf, len, from);
return 0;
@@ -342,20 +342,21 @@ static void ssmpingd_read_on(struct ssmpingd_sock *ss)
&ss->t_sock_read);
}
-static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr)
+static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim,
+ struct in_addr source_addr)
{
struct ssmpingd_sock *ss;
int sock_fd;
- if (!qpim_ssmpingd_list) {
- qpim_ssmpingd_list = list_new();
- if (!qpim_ssmpingd_list) {
+ if (!pim->ssmpingd_list) {
+ pim->ssmpingd_list = list_new();
+ if (!pim->ssmpingd_list) {
zlog_err(
"%s %s: failure: qpim_ssmpingd_list=list_new()",
__FILE__, __PRETTY_FUNCTION__);
return 0;
}
- qpim_ssmpingd_list->del = (void (*)(void *))ssmpingd_free;
+ pim->ssmpingd_list->del = (void (*)(void *))ssmpingd_free;
}
sock_fd =
@@ -380,24 +381,25 @@ static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr)
return 0;
}
+ ss->pim = pim;
ss->sock_fd = sock_fd;
ss->t_sock_read = NULL;
ss->source_addr = source_addr;
ss->creation = pim_time_monotonic_sec();
ss->requests = 0;
- listnode_add(qpim_ssmpingd_list, ss);
+ listnode_add(pim->ssmpingd_list, ss);
ssmpingd_read_on(ss);
return ss;
}
-int pim_ssmpingd_start(struct in_addr source_addr)
+int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr)
{
struct ssmpingd_sock *ss;
- ss = ssmpingd_find(source_addr);
+ ss = ssmpingd_find(pim, source_addr);
if (ss) {
/* silently ignore request to recreate entry */
return 0;
@@ -411,7 +413,7 @@ int pim_ssmpingd_start(struct in_addr source_addr)
__PRETTY_FUNCTION__, source_str);
}
- ss = ssmpingd_new(source_addr);
+ ss = ssmpingd_new(pim, source_addr);
if (!ss) {
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", source_addr, source_str,
@@ -424,11 +426,11 @@ int pim_ssmpingd_start(struct in_addr source_addr)
return 0;
}
-int pim_ssmpingd_stop(struct in_addr source_addr)
+int pim_ssmpingd_stop(struct pim_instance *pim, struct in_addr source_addr)
{
struct ssmpingd_sock *ss;
- ss = ssmpingd_find(source_addr);
+ ss = ssmpingd_find(pim, source_addr);
if (!ss) {
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", source_addr, source_str,
diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h
index 89fb320a76..fafdd7ade1 100644
--- a/pimd/pim_ssmpingd.h
+++ b/pimd/pim_ssmpingd.h
@@ -27,6 +27,8 @@
#include "pim_iface.h"
struct ssmpingd_sock {
+ struct pim_instance *pim;
+
int sock_fd; /* socket */
struct thread *t_sock_read; /* thread for reading socket */
struct in_addr source_addr; /* source address */
@@ -34,9 +36,9 @@ struct ssmpingd_sock {
int64_t requests; /* counter */
};
-void pim_ssmpingd_init(void);
-void pim_ssmpingd_destroy(void);
-int pim_ssmpingd_start(struct in_addr source_addr);
-int pim_ssmpingd_stop(struct in_addr source_addr);
+void pim_ssmpingd_init(struct pim_instance *pim);
+void pim_ssmpingd_destroy(struct pim_instance *pim);
+int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr);
+int pim_ssmpingd_stop(struct pim_instance *pim, struct in_addr source_addr);
#endif /* PIM_SSMPINGD_H */
diff --git a/pimd/pim_static.c b/pimd/pim_static.c
index 7c9aca47a7..3d44a01c78 100644
--- a/pimd/pim_static.c
+++ b/pimd/pim_static.c
@@ -74,8 +74,9 @@ static struct static_route *static_route_new(unsigned int iif, unsigned int oif,
}
-int pim_static_add(struct interface *iif, struct interface *oif,
- struct in_addr group, struct in_addr source)
+int pim_static_add(struct pim_instance *pim, struct interface *iif,
+ struct interface *oif, struct in_addr group,
+ struct in_addr source)
{
struct listnode *node = NULL;
struct static_route *s_route = NULL;
@@ -101,8 +102,11 @@ int pim_static_add(struct interface *iif, struct interface *oif,
return -4;
}
#endif
+ if (iif->vrf_id != oif->vrf_id) {
+ return -3;
+ }
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
if (s_route->group.s_addr == group.s_addr
&& s_route->source.s_addr == source.s_addr) {
if (s_route->iif == iif_index
@@ -181,9 +185,11 @@ int pim_static_add(struct interface *iif, struct interface *oif,
* match */
if (!node) {
s_route = static_route_new(iif_index, oif_index, group, source);
- listnode_add(qpim_static_route_list, s_route);
+ listnode_add(pim->static_routes, s_route);
}
+ s_route->c_oil.pim = pim;
+
if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) {
char gifaddr_str[INET_ADDRSTRLEN];
char sifaddr_str[INET_ADDRSTRLEN];
@@ -203,7 +209,7 @@ int pim_static_add(struct interface *iif, struct interface *oif,
} else {
/* we never stored off a copy, so it must have been a
* fresh new route */
- listnode_delete(qpim_static_route_list, s_route);
+ listnode_delete(pim->static_routes, s_route);
pim_static_route_free(s_route);
}
@@ -235,8 +241,9 @@ int pim_static_add(struct interface *iif, struct interface *oif,
return 0;
}
-int pim_static_del(struct interface *iif, struct interface *oif,
- struct in_addr group, struct in_addr source)
+int pim_static_del(struct pim_instance *pim, struct interface *iif,
+ struct interface *oif, struct in_addr group,
+ struct in_addr source)
{
struct listnode *node = NULL;
struct listnode *nextnode = NULL;
@@ -253,8 +260,7 @@ int pim_static_del(struct interface *iif, struct interface *oif,
return -2;
}
- for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode,
- s_route)) {
+ for (ALL_LIST_ELEMENTS(pim->static_routes, node, nextnode, s_route)) {
if (s_route->iif == iif_index
&& s_route->group.s_addr == group.s_addr
&& s_route->source.s_addr == source.s_addr
@@ -293,8 +299,7 @@ int pim_static_del(struct interface *iif, struct interface *oif,
s_route->c_oil.oif_creation[oif_index] = 0;
if (s_route->c_oil.oil_ref_count <= 0) {
- listnode_delete(qpim_static_route_list,
- s_route);
+ listnode_delete(pim->static_routes, s_route);
pim_static_route_free(s_route);
}
@@ -332,7 +337,8 @@ int pim_static_del(struct interface *iif, struct interface *oif,
return 0;
}
-int pim_static_write_mroute(struct vty *vty, struct interface *ifp)
+int pim_static_write_mroute(struct pim_instance *pim, struct vty *vty,
+ struct interface *ifp)
{
struct pim_interface *pim_ifp = ifp->info;
struct listnode *node;
@@ -344,7 +350,7 @@ int pim_static_write_mroute(struct vty *vty, struct interface *ifp)
if (!pim_ifp)
return 0;
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, sroute)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sroute)) {
pim_inet4_dump("<ifaddr?>", sroute->group, gbuf, sizeof(gbuf));
pim_inet4_dump("<ifaddr?>", sroute->source, sbuf, sizeof(sbuf));
if (sroute->iif == pim_ifp->mroute_vif_index) {
@@ -352,7 +358,8 @@ int pim_static_write_mroute(struct vty *vty, struct interface *ifp)
for (i = 0; i < MAXVIFS; i++)
if (sroute->oif_ttls[i]) {
struct interface *oifp =
- pim_if_find_by_vif_index(i);
+ pim_if_find_by_vif_index(pim,
+ i);
if (sroute->source.s_addr == 0)
vty_out(vty,
" ip mroute %s %s\n",
diff --git a/pimd/pim_static.h b/pimd/pim_static.h
index 1114f4b67b..953ec0a70a 100644
--- a/pimd/pim_static.h
+++ b/pimd/pim_static.h
@@ -36,10 +36,13 @@ struct static_route {
void pim_static_route_free(struct static_route *s_route);
-int pim_static_add(struct interface *iif, struct interface *oif,
- struct in_addr group, struct in_addr source);
-int pim_static_del(struct interface *iif, struct interface *oif,
- struct in_addr group, struct in_addr source);
-int pim_static_write_mroute(struct vty *vty, struct interface *ifp);
+int pim_static_add(struct pim_instance *pim, struct interface *iif,
+ struct interface *oif, struct in_addr group,
+ struct in_addr source);
+int pim_static_del(struct pim_instance *pim, struct interface *iif,
+ struct interface *oif, struct in_addr group,
+ struct in_addr source);
+int pim_static_write_mroute(struct pim_instance *pim, struct vty *vty,
+ struct interface *ifp);
#endif /* PIM_STATIC_H_ */
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 0ddd04c38c..95d1a840ff 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -54,10 +54,6 @@
#include "pim_nht.h"
#include "pim_ssm.h"
-struct hash *pim_upstream_hash = NULL;
-struct list *pim_upstream_list = NULL;
-struct timer_wheel *pim_upstream_sg_wheel = NULL;
-
static void join_timer_stop(struct pim_upstream *up);
static void
pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);
@@ -67,7 +63,8 @@ pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);
* remove the parent pointer from
* those pointing at us
*/
-static void pim_upstream_remove_children(struct pim_upstream *up)
+static void pim_upstream_remove_children(struct pim_instance *pim,
+ struct pim_upstream *up)
{
struct pim_upstream *child;
@@ -79,7 +76,8 @@ static void pim_upstream_remove_children(struct pim_upstream *up)
listnode_delete(up->sources, child);
if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) {
PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags);
- child = pim_upstream_del(child, __PRETTY_FUNCTION__);
+ child = pim_upstream_del(pim, child,
+ __PRETTY_FUNCTION__);
}
if (child)
child->parent = NULL;
@@ -93,7 +91,8 @@ static void pim_upstream_remove_children(struct pim_upstream *up)
* Find the children that would point
* at us.
*/
-static void pim_upstream_find_new_children(struct pim_upstream *up)
+static void pim_upstream_find_new_children(struct pim_instance *pim,
+ struct pim_upstream *up)
{
struct pim_upstream *child;
struct listnode *ch_node;
@@ -106,7 +105,7 @@ static void pim_upstream_find_new_children(struct pim_upstream *up)
&& (up->sg.grp.s_addr == INADDR_ANY))
return;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, ch_node, child)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, ch_node, child)) {
if ((up->sg.grp.s_addr != INADDR_ANY)
&& (child->sg.grp.s_addr == up->sg.grp.s_addr)
&& (child != up)) {
@@ -121,7 +120,8 @@ static void pim_upstream_find_new_children(struct pim_upstream *up)
* If we have a (S,G), find the (*,G)
* If we have a (*,G), find the (*,*)
*/
-static struct pim_upstream *pim_upstream_find_parent(struct pim_upstream *child)
+static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,
+ struct pim_upstream *child)
{
struct prefix_sg any = child->sg;
struct pim_upstream *up = NULL;
@@ -130,7 +130,7 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_upstream *child)
if ((child->sg.src.s_addr != INADDR_ANY)
&& (child->sg.grp.s_addr != INADDR_ANY)) {
any.src.s_addr = INADDR_ANY;
- up = pim_upstream_find(&any);
+ up = pim_upstream_find(pim, &any);
if (up)
listnode_add(up->sources, child);
@@ -153,12 +153,14 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
/* Detaching from channel_oil, channel_oil may exist post del,
but upstream would not keep reference of it
*/
+ up->channel_oil->up = NULL;
pim_channel_oil_del(up->channel_oil);
up->channel_oil = NULL;
}
}
-struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
+struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
+ struct pim_upstream *up, const char *name)
{
bool notify_msdp = false;
struct prefix nht_p;
@@ -194,11 +196,11 @@ struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
up->rpf.source_nexthop.interface = NULL;
if (up->sg.src.s_addr != INADDR_ANY) {
- wheel_remove_item(pim_upstream_sg_wheel, up);
+ wheel_remove_item(pim->upstream_sg_wheel, up);
notify_msdp = true;
}
- pim_upstream_remove_children(up);
+ pim_upstream_remove_children(pim, up);
if (up->sources)
list_delete(up->sources);
up->sources = NULL;
@@ -217,11 +219,11 @@ struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
listnode_delete(up->parent->sources, up);
up->parent = NULL;
- listnode_delete(pim_upstream_list, up);
- hash_release(pim_upstream_hash, up);
+ listnode_delete(pim->upstream_list, up);
+ hash_release(pim->upstream_hash, up);
if (notify_msdp) {
- pim_msdp_up_del(&up->sg);
+ pim_msdp_up_del(pim, &up->sg);
}
/* Deregister addr with Zebra NHT */
@@ -234,7 +236,7 @@ struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
__PRETTY_FUNCTION__, up->sg_str, buf);
}
- pim_delete_tracked_nexthop(&nht_p, up, NULL);
+ pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
pim_upstream_free(up);
@@ -442,7 +444,7 @@ static void forward_off(struct pim_upstream *up)
/* scan per-interface (S,G) state */
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
- pim_forward_stop(ch);
+ pim_forward_stop(ch, false);
} /* scan iface channel list */
}
@@ -469,12 +471,12 @@ static int pim_upstream_could_register(struct pim_upstream *up)
/* Source registration is supressed for SSM groups. When the SSM range changes
* we re-revaluate register setup for existing upstream entries */
-void pim_upstream_register_reevaluate(void)
+void pim_upstream_register_reevaluate(struct pim_instance *pim)
{
struct listnode *upnode;
struct pim_upstream *up;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
/* If FHR is set CouldRegister is True. Also check if the flow
* is actually active; if it is not kat setup will trigger
* source
@@ -482,7 +484,7 @@ void pim_upstream_register_reevaluate(void)
if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer)
continue;
- if (pim_is_grp_ssm(up->sg.grp)) {
+ if (pim_is_grp_ssm(pim, up->sg.grp)) {
/* clear the register state for SSM groups */
if (up->reg_state != PIM_REG_NOINFO) {
if (PIM_DEBUG_PIM_EVENTS)
@@ -491,7 +493,7 @@ void pim_upstream_register_reevaluate(void)
up->sg_str);
/* remove regiface from the OIL if it is there*/
pim_channel_del_oif(up->channel_oil,
- pim_regiface,
+ pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_NOINFO;
}
@@ -503,7 +505,7 @@ void pim_upstream_register_reevaluate(void)
"Register %s as G is now ASM",
up->sg_str);
pim_channel_add_oif(up->channel_oil,
- pim_regiface,
+ pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
}
@@ -511,7 +513,7 @@ void pim_upstream_register_reevaluate(void)
}
}
-void pim_upstream_switch(struct pim_upstream *up,
+void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
enum pim_upstream_state new_state)
{
enum pim_upstream_state old_state = up->join_state;
@@ -533,14 +535,14 @@ void pim_upstream_switch(struct pim_upstream *up,
if (old_state != PIM_UPSTREAM_JOINED) {
int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags);
forward_on(up);
- pim_msdp_up_join_state_changed(up);
+ pim_msdp_up_join_state_changed(pim, up);
if (pim_upstream_could_register(up)) {
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
if (!old_fhr
&& PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(
up->flags)) {
pim_upstream_keep_alive_timer_start(
- up, qpim_keep_alive_time);
+ up, pim->keep_alive_time);
pim_register_join(up);
}
} else {
@@ -554,13 +556,13 @@ void pim_upstream_switch(struct pim_upstream *up,
forward_off(up);
if (old_state == PIM_UPSTREAM_JOINED)
- pim_msdp_up_join_state_changed(up);
+ pim_msdp_up_join_state_changed(pim, up);
/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
RP.
If I am RP for G then send S,G prune to its IIF. */
if (pim_upstream_is_sg_rpt(up) && up->parent
- && !I_am_RP(up->sg.grp)) {
+ && !I_am_RP(pim, up->sg.grp)) {
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug(
"%s: *,G IIF %s S,G IIF %s ",
@@ -598,8 +600,11 @@ int pim_upstream_compare(void *arg1, void *arg2)
return 0;
}
-static struct pim_upstream *
-pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
+static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
+ struct prefix_sg *sg,
+ struct interface *incoming,
+ int flags,
+ struct pim_ifchannel *ch)
{
enum pim_rpf_result rpf_result;
struct pim_interface *pim_ifp;
@@ -614,25 +619,29 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
up->sg = *sg;
pim_str_sg_set(sg, up->sg_str);
- up = hash_get(pim_upstream_hash, up, hash_alloc_intern);
- if (!pim_rp_set_upstream_addr(&up->upstream_addr, sg->src, sg->grp)) {
+ if (ch)
+ ch->upstream = up;
+
+ up = hash_get(pim->upstream_hash, up, hash_alloc_intern);
+ if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
+ sg->grp)) {
if (PIM_DEBUG_TRACE)
zlog_debug("%s: Received a (*,G) with no RP configured",
__PRETTY_FUNCTION__);
- hash_release(pim_upstream_hash, up);
+ hash_release(pim->upstream_hash, up);
XFREE(MTYPE_PIM_UPSTREAM, up);
return NULL;
}
- up->parent = pim_upstream_find_parent(up);
+ up->parent = pim_upstream_find_parent(pim, up);
if (up->sg.src.s_addr == INADDR_ANY) {
up->sources = list_new();
up->sources->cmp = pim_upstream_compare;
} else
up->sources = NULL;
- pim_upstream_find_new_children(up);
+ pim_upstream_find_new_children(pim, up);
up->flags = flags;
up->ref_count = 1;
up->t_join_timer = NULL;
@@ -660,9 +669,9 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
if (up->sg.src.s_addr != INADDR_ANY)
- wheel_add_item(pim_upstream_sg_wheel, up);
+ wheel_add_item(pim->upstream_sg_wheel, up);
- rpf_result = pim_rpf_update(up, NULL, 1);
+ rpf_result = pim_rpf_update(pim, up, NULL, 1);
if (rpf_result == PIM_RPF_FAILURE) {
struct prefix nht_p;
@@ -674,7 +683,7 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4 = up->upstream_addr;
- pim_delete_tracked_nexthop(&nht_p, up, NULL);
+ pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
if (up->parent) {
listnode_delete(up->parent->sources, up);
@@ -682,13 +691,13 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
}
if (up->sg.src.s_addr != INADDR_ANY)
- wheel_remove_item(pim_upstream_sg_wheel, up);
+ wheel_remove_item(pim->upstream_sg_wheel, up);
- pim_upstream_remove_children(up);
+ pim_upstream_remove_children(pim, up);
if (up->sources)
list_delete(up->sources);
- hash_release(pim_upstream_hash, up);
+ hash_release(pim->upstream_hash, up);
XFREE(MTYPE_PIM_UPSTREAM, up);
return NULL;
}
@@ -697,9 +706,9 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
pim_ifp = up->rpf.source_nexthop.interface->info;
if (pim_ifp)
up->channel_oil = pim_channel_oil_add(
- &up->sg, pim_ifp->mroute_vif_index);
+ pim, &up->sg, pim_ifp->mroute_vif_index);
}
- listnode_add_sort(pim_upstream_list, up);
+ listnode_add_sort(pim->upstream_list, up);
if (PIM_DEBUG_TRACE) {
zlog_debug(
@@ -711,13 +720,14 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
return up;
}
-struct pim_upstream *pim_upstream_find(struct prefix_sg *sg)
+struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
struct pim_upstream lookup;
struct pim_upstream *up = NULL;
lookup.sg = *sg;
- up = hash_lookup(pim_upstream_hash, &lookup);
+ up = hash_lookup(pim->upstream_hash, &lookup);
return up;
}
@@ -726,8 +736,11 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
int flags, const char *name)
{
struct pim_upstream *up;
+ struct pim_interface *pim_ifp;
+
+ pim_ifp = incoming->info;
- up = pim_upstream_find(sg);
+ up = pim_upstream_find(pim_ifp->pim, sg);
if (up) {
if (!(up->flags & flags)) {
@@ -740,7 +753,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
up->ref_count);
}
} else
- up = pim_upstream_add(sg, incoming, flags, name);
+ up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
+ NULL);
return up;
}
@@ -755,18 +769,21 @@ void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
up->ref_count);
}
-struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
+struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
struct interface *incoming, int flags,
- const char *name)
+ const char *name,
+ struct pim_ifchannel *ch)
{
struct pim_upstream *up = NULL;
int found = 0;
- up = pim_upstream_find(sg);
+
+ up = pim_upstream_find(pim, sg);
if (up) {
pim_upstream_ref(up, flags, name);
found = 1;
} else {
- up = pim_upstream_new(sg, incoming, flags);
+ up = pim_upstream_new(pim, sg, incoming, flags, ch);
}
if (PIM_DEBUG_TRACE) {
@@ -842,7 +859,8 @@ int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
See also pim_upstream_update_join_desired() below.
*/
-int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
+int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
+ struct pim_upstream *up)
{
struct interface *ifp;
struct listnode *node;
@@ -850,7 +868,7 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
struct pim_upstream *starup = up->parent;
int ret = 0;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
if (!ifp->info)
continue;
@@ -874,14 +892,15 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
/*
See also pim_upstream_evaluate_join_desired() above.
*/
-void pim_upstream_update_join_desired(struct pim_upstream *up)
+void pim_upstream_update_join_desired(struct pim_instance *pim,
+ struct pim_upstream *up)
{
int was_join_desired; /* boolean */
int is_join_desired; /* boolean */
was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags);
- is_join_desired = pim_upstream_evaluate_join_desired(up);
+ is_join_desired = pim_upstream_evaluate_join_desired(pim, up);
if (is_join_desired)
PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags);
else
@@ -889,13 +908,13 @@ void pim_upstream_update_join_desired(struct pim_upstream *up)
/* switched from false to true */
if (is_join_desired && !was_join_desired) {
- pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
return;
}
/* switched from true to false */
if (!is_join_desired && was_join_desired) {
- pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
return;
}
}
@@ -909,7 +928,8 @@ void pim_upstream_update_join_desired(struct pim_upstream *up)
Join Timer is set to expire in more than t_override seconds, reset
it so that it expires after t_override seconds.
*/
-void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr)
+void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
+ struct in_addr neigh_addr)
{
struct listnode *up_node;
struct listnode *up_nextnode;
@@ -918,7 +938,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr)
/*
* Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
*/
- for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
+ for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
if (PIM_DEBUG_TRACE) {
char neigh_str[INET_ADDRSTRLEN];
@@ -1020,7 +1040,8 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
/* When kat is stopped CouldRegister goes to false so we need to
* transition the (S, G) on FHR to NI state and remove reg tunnel
* from the OIL */
-static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up)
+static void pim_upstream_fhr_kat_expiry(struct pim_instance *pim,
+ struct pim_upstream *up)
{
if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
return;
@@ -1032,7 +1053,7 @@ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up)
/* stop reg-stop timer */
THREAD_OFF(up->t_rs_timer);
/* remove regiface from the OIL if it is there*/
- pim_channel_del_oif(up->channel_oil, pim_regiface,
+ pim_channel_del_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
/* clear the register state */
up->reg_state = PIM_REG_NOINFO;
@@ -1065,10 +1086,12 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
static int pim_upstream_keep_alive_timer(struct thread *t)
{
struct pim_upstream *up;
+ struct pim_instance *pim;
up = THREAD_ARG(t);
+ pim = up->channel_oil->pim;
- if (I_am_RP(up->sg.grp)) {
+ if (I_am_RP(pim, up->sg.grp)) {
pim_br_clear_pmbr(&up->sg);
/*
* We need to do more here :)
@@ -1077,19 +1100,19 @@ static int pim_upstream_keep_alive_timer(struct thread *t)
}
/* source is no longer active - pull the SA from MSDP's cache */
- pim_msdp_sa_local_del(&up->sg);
+ pim_msdp_sa_local_del(pim, &up->sg);
/* if entry was created because of activity we need to deref it */
if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
- pim_upstream_fhr_kat_expiry(up);
+ pim_upstream_fhr_kat_expiry(pim, up);
if (PIM_DEBUG_TRACE)
zlog_debug("kat expired on %s; remove stream reference",
up->sg_str);
PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
- pim_upstream_del(up, __PRETTY_FUNCTION__);
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
- pim_upstream_del(up, __PRETTY_FUNCTION__);
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
}
return 0;
@@ -1114,12 +1137,11 @@ void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
/* MSDP on RP needs to know if a source is registerable to this RP */
static int pim_upstream_msdp_reg_timer(struct thread *t)
{
- struct pim_upstream *up;
-
- up = THREAD_ARG(t);
+ struct pim_upstream *up = THREAD_ARG(t);
+ struct pim_instance *pim = up->channel_oil->pim;
/* source is no longer active - pull the SA from MSDP's cache */
- pim_msdp_sa_local_del(&up->sg);
+ pim_msdp_sa_local_del(pim, &up->sg);
return 1;
}
void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
@@ -1159,9 +1181,10 @@ void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
* SwitchToSptDesired(S,G) return true once a single packet has been
* received for the source and group.
*/
-int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg)
+int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
- if (I_am_RP(sg->grp))
+ if (I_am_RP(pim, sg->grp))
return 1;
return 0;
@@ -1295,10 +1318,12 @@ const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str)
static int pim_upstream_register_stop_timer(struct thread *t)
{
struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
struct pim_upstream *up;
struct pim_rpf *rpg;
struct ip ip_hdr;
up = THREAD_ARG(t);
+ pim = up->channel_oil->pim;
if (PIM_DEBUG_TRACE) {
char state_str[PIM_REG_STATE_STR_LEN];
@@ -1310,7 +1335,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
switch (up->reg_state) {
case PIM_REG_JOIN_PENDING:
up->reg_state = PIM_REG_JOIN;
- pim_channel_add_oif(up->channel_oil, pim_regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
break;
case PIM_REG_JOIN:
@@ -1330,14 +1355,21 @@ static int pim_upstream_register_stop_timer(struct thread *t)
if (((up->channel_oil->cc.lastused / 100)
> PIM_KEEPALIVE_PERIOD)
- && (I_am_RP(up->sg.grp))) {
+ && (I_am_RP(pim_ifp->pim, up->sg.grp))) {
if (PIM_DEBUG_TRACE)
zlog_debug(
"%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while",
__PRETTY_FUNCTION__);
return 0;
}
- rpg = RP(up->sg.grp);
+ rpg = RP(pim_ifp->pim, up->sg.grp);
+ if (!rpg) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug(
+ "%s: Cannot send register for %s no RPF to the RP",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return 0;
+ }
memset(&ip_hdr, 0, sizeof(struct ip));
ip_hdr.ip_p = PIM_IP_PROTO_PIM;
ip_hdr.ip_hl = 5;
@@ -1380,7 +1412,8 @@ void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
&up->t_rs_timer);
}
-int pim_upstream_inherited_olist_decide(struct pim_upstream *up)
+int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
+ struct pim_upstream *up)
{
struct interface *ifp;
struct pim_interface *pim_ifp = NULL;
@@ -1397,10 +1430,10 @@ int pim_upstream_inherited_olist_decide(struct pim_upstream *up)
__PRETTY_FUNCTION__, up->sg_str);
}
if (pim_ifp && !up->channel_oil)
- up->channel_oil =
- pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index);
+ up->channel_oil = pim_channel_oil_add(
+ pim, &up->sg, pim_ifp->mroute_vif_index);
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
if (!ifp->info)
continue;
@@ -1445,9 +1478,10 @@ int pim_upstream_inherited_olist_decide(struct pim_upstream *up)
* return 1 if there are any output interfaces
* return 0 if there are not any output interfaces
*/
-int pim_upstream_inherited_olist(struct pim_upstream *up)
+int pim_upstream_inherited_olist(struct pim_instance *pim,
+ struct pim_upstream *up)
{
- int output_intf = pim_upstream_inherited_olist_decide(up);
+ int output_intf = pim_upstream_inherited_olist_decide(pim, up);
/*
* If we have output_intf switch state to Join and work like normal
@@ -1456,7 +1490,7 @@ int pim_upstream_inherited_olist(struct pim_upstream *up)
* incoming packets so we don't bother the other stuff!
*/
if (output_intf)
- pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
else
forward_on(up);
@@ -1474,7 +1508,7 @@ int pim_upstream_empty_inherited_olist(struct pim_upstream *up)
* set and see if the new neighbor allows
* the join to be sent
*/
-void pim_upstream_find_new_rpf(void)
+void pim_upstream_find_new_rpf(struct pim_instance *pim)
{
struct listnode *up_node;
struct listnode *up_nextnode;
@@ -1483,36 +1517,36 @@ void pim_upstream_find_new_rpf(void)
/*
* Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
*/
- for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
+ for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
if (PIM_DEBUG_TRACE)
zlog_debug(
"Upstream %s without a path to send join, checking",
up->sg_str);
- pim_rpf_update(up, NULL, 1);
+ pim_rpf_update(pim, up, NULL, 1);
}
}
}
-static unsigned int pim_upstream_hash_key(void *arg)
+unsigned int pim_upstream_hash_key(void *arg)
{
struct pim_upstream *up = (struct pim_upstream *)arg;
return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0);
}
-void pim_upstream_terminate(void)
+void pim_upstream_terminate(struct pim_instance *pim)
{
- if (pim_upstream_list)
- list_delete(pim_upstream_list);
- pim_upstream_list = NULL;
+ if (pim->upstream_list)
+ list_delete(pim->upstream_list);
+ pim->upstream_list = NULL;
- if (pim_upstream_hash)
- hash_free(pim_upstream_hash);
- pim_upstream_hash = NULL;
+ if (pim->upstream_hash)
+ hash_free(pim->upstream_hash);
+ pim->upstream_hash = NULL;
}
-static int pim_upstream_equal(const void *arg1, const void *arg2)
+int pim_upstream_equal(const void *arg1, const void *arg2)
{
const struct pim_upstream *up1 = (const struct pim_upstream *)arg1;
const struct pim_upstream *up2 = (const struct pim_upstream *)arg2;
@@ -1540,6 +1574,8 @@ static int pim_upstream_equal(const void *arg1, const void *arg2)
*/
static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
{
+ struct pim_instance *pim = up->channel_oil->pim;
+
/* "iif == RPF_interface(S)" check has to be done by the kernel or hw
* so we will skip that here */
if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
@@ -1559,7 +1595,7 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
* MUST be
* removed to handle spt turn-arounds correctly in a 3-tier clos
*/
- if (I_am_RP(up->sg.grp))
+ if (I_am_RP(pim, up->sg.grp))
return true;
}
@@ -1573,9 +1609,10 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
static void pim_upstream_sg_running(void *arg)
{
struct pim_upstream *up = (struct pim_upstream *)arg;
+ struct pim_instance *pim = up->channel_oil->pim;
// No packet can have arrived here if this is the case
- if (!up->channel_oil || !up->channel_oil->installed) {
+ if (!up->channel_oil->installed) {
if (PIM_DEBUG_TRACE)
zlog_debug("%s: %s is not installed in mroute",
__PRETTY_FUNCTION__, up->sg_str);
@@ -1595,7 +1632,7 @@ static void pim_upstream_sg_running(void *arg)
zlog_debug(
"%s: Handling unscanned inherited_olist for %s",
__PRETTY_FUNCTION__, up->sg_str);
- pim_upstream_inherited_olist_decide(up);
+ pim_upstream_inherited_olist_decide(pim, up);
up->channel_oil->oil_inherited_rescan = 0;
}
pim_mroute_update_counters(up->channel_oil);
@@ -1628,9 +1665,9 @@ static void pim_upstream_sg_running(void *arg)
PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
pim_upstream_fhr_kat_start(up);
}
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
@@ -1638,29 +1675,30 @@ static void pim_upstream_sg_running(void *arg)
return;
}
-void pim_upstream_add_lhr_star_pimreg(void)
+void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
{
struct pim_upstream *up;
struct listnode *node;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) {
if (up->sg.src.s_addr != INADDR_ANY)
continue;
if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags))
continue;
- pim_channel_add_oif(up->channel_oil, pim_regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
}
}
-void pim_upstream_spt_prefix_list_update(struct prefix_list *pl)
+void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *pl)
{
const char *pname = prefix_list_name(pl);
- if (pimg->spt.plist && strcmp(pimg->spt.plist, pname) == 0) {
- pim_upstream_remove_lhr_star_pimreg(pname);
+ if (pim->spt.plist && strcmp(pim->spt.plist, pname) == 0) {
+ pim_upstream_remove_lhr_star_pimreg(pim, pname);
}
}
@@ -1676,7 +1714,8 @@ void pim_upstream_spt_prefix_list_update(struct prefix_list *pl)
* the interface
*
*/
-void pim_upstream_remove_lhr_star_pimreg(const char *nlist)
+void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
+ const char *nlist)
{
struct pim_upstream *up;
struct listnode *node;
@@ -1689,7 +1728,7 @@ void pim_upstream_remove_lhr_star_pimreg(const char *nlist)
g.family = AF_INET;
g.prefixlen = IPV4_MAX_PREFIXLEN;
- for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) {
if (up->sg.src.s_addr != INADDR_ANY)
continue;
@@ -1697,30 +1736,35 @@ void pim_upstream_remove_lhr_star_pimreg(const char *nlist)
continue;
if (!nlist) {
- pim_channel_del_oif(up->channel_oil, pim_regiface,
+ pim_channel_del_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
continue;
}
g.u.prefix4 = up->sg.grp;
apply_new = prefix_list_apply(np, &g);
if (apply_new == PREFIX_DENY)
- pim_channel_add_oif(up->channel_oil, pim_regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
else
- pim_channel_del_oif(up->channel_oil, pim_regiface,
+ pim_channel_del_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_IGMP);
}
}
-void pim_upstream_init(void)
+void pim_upstream_init(struct pim_instance *pim)
{
- pim_upstream_sg_wheel =
+ char hash_name[64];
+
+ pim->upstream_sg_wheel =
wheel_init(master, 31000, 100, pim_upstream_hash_key,
pim_upstream_sg_running);
- pim_upstream_hash = hash_create_size(8192, pim_upstream_hash_key,
- pim_upstream_equal, NULL);
- pim_upstream_list = list_new();
- pim_upstream_list->del = (void (*)(void *))pim_upstream_free;
- pim_upstream_list->cmp = pim_upstream_compare;
+ snprintf(hash_name, 64, "PIM %s Upstream Hash",
+ pim->vrf->name);
+ pim->upstream_hash = hash_create_size(8192, pim_upstream_hash_key,
+ pim_upstream_equal, hash_name);
+
+ pim->upstream_list = list_new();
+ pim->upstream_list->del = (void (*)(void *))pim_upstream_free;
+ pim->upstream_list->cmp = pim_upstream_compare;
}
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index b6a9729f0f..b75a5b9df3 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -119,7 +119,7 @@ struct pim_upstream {
*/
struct thread *t_rs_timer;
#define PIM_REGISTER_SUPPRESSION_PERIOD (60)
-#define PIM_REGISTER_PROBE_PERIOD (15)
+#define PIM_REGISTER_PROBE_PERIOD (5)
/*
* KAT(S,G)
@@ -137,26 +137,29 @@ struct pim_upstream {
int64_t state_transition; /* Record current state uptime */
};
-struct list *pim_upstream_list;
-struct hash *pim_upstream_hash;
-
void pim_upstream_free(struct pim_upstream *up);
-struct pim_upstream *pim_upstream_find(struct prefix_sg *sg);
+struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
+ struct prefix_sg *sg);
struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
struct interface *ifp, int flags,
const char *name);
-struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
+struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
struct interface *ifp, int flags,
- const char *name);
+ const char *name,
+ struct pim_ifchannel *ch);
void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name);
-struct pim_upstream *pim_upstream_del(struct pim_upstream *up,
+struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
+ struct pim_upstream *up,
const char *name);
-int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
+int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
+ struct pim_upstream *up);
int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
struct pim_ifchannel *ch,
struct pim_ifchannel *starch);
-void pim_upstream_update_join_desired(struct pim_upstream *up);
+void pim_upstream_update_join_desired(struct pim_instance *pim,
+ struct pim_upstream *up);
void pim_upstream_join_suppress(struct pim_upstream *up,
struct in_addr rpf_addr, int holdtime);
@@ -166,7 +169,8 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
void pim_upstream_join_timer_restart(struct pim_upstream *up,
struct pim_rpf *old);
-void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr);
+void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
+ struct in_addr neigh_addr);
void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
struct interface *old_rpf_ifp);
@@ -176,8 +180,9 @@ void pim_upstream_update_my_assert_metric(struct pim_upstream *up);
void pim_upstream_keep_alive_timer_start(struct pim_upstream *up,
uint32_t time);
-int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg);
-#define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg)
+int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
+ struct prefix_sg *sg);
+#define SwitchToSptDesired(pim, sg) pim_upstream_switch_to_spt_desired (pim, sg)
int pim_upstream_is_sg_rpt(struct pim_upstream *up);
void pim_upstream_set_sptbit(struct pim_upstream *up,
@@ -188,29 +193,36 @@ void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
void pim_upstream_send_join(struct pim_upstream *up);
-void pim_upstream_switch(struct pim_upstream *up,
+void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
enum pim_upstream_state new_state);
const char *pim_upstream_state2str(enum pim_upstream_state join_state);
#define PIM_REG_STATE_STR_LEN 12
const char *pim_reg_state2str(enum pim_reg_state state, char *state_str);
-int pim_upstream_inherited_olist_decide(struct pim_upstream *up);
-int pim_upstream_inherited_olist(struct pim_upstream *up);
+int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
+ struct pim_upstream *up);
+int pim_upstream_inherited_olist(struct pim_instance *pim,
+ struct pim_upstream *up);
int pim_upstream_empty_inherited_olist(struct pim_upstream *up);
-void pim_upstream_find_new_rpf(void);
+void pim_upstream_find_new_rpf(struct pim_instance *pim);
void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up);
-void pim_upstream_init(void);
-void pim_upstream_terminate(void);
+void pim_upstream_init(struct pim_instance *pim);
+void pim_upstream_terminate(struct pim_instance *pim);
void join_timer_start(struct pim_upstream *up);
int pim_upstream_compare(void *arg1, void *arg2);
-void pim_upstream_register_reevaluate(void);
+void pim_upstream_register_reevaluate(struct pim_instance *pim);
+
+void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim);
+void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
+ const char *nlist);
-void pim_upstream_add_lhr_star_pimreg(void);
-void pim_upstream_remove_lhr_star_pimreg(const char *nlist);
+void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
+ struct prefix_list *pl);
-void pim_upstream_spt_prefix_list_update(struct prefix_list *pl);
+unsigned int pim_upstream_hash_key(void *arg);
+int pim_upstream_equal(const void *arg1, const void *arg2);
#endif /* PIM_UPSTREAM_H */
diff --git a/pimd/pim_util.c b/pimd/pim_util.c
index c2e4b2a462..820117a03a 100644
--- a/pimd/pim_util.c
+++ b/pimd/pim_util.c
@@ -107,7 +107,8 @@ int pim_is_group_224_0_0_0_24(struct in_addr group_addr)
struct prefix group;
if (first) {
- str2prefix("224.0.0.0/24", &group_224);
+ if (!str2prefix("224.0.0.0/24", &group_224))
+ return 0;
first = 0;
}
@@ -125,7 +126,8 @@ int pim_is_group_224_4(struct in_addr group_addr)
struct prefix group;
if (first) {
- str2prefix("224.0.0.0/4", &group_all);
+ if (!str2prefix("224.0.0.0/4", &group_all))
+ return 0;
first = 0;
}
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index a787767911..8914f6eb00 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -139,74 +139,92 @@ int pim_debug_config_write(struct vty *vty)
++writes;
}
+ if (PIM_DEBUG_PIM_NHT) {
+ vty_out(vty, "debug pim nht\n");
+ ++writes;
+ }
+
return writes;
}
-int pim_global_config_write(struct vty *vty)
+int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
{
int writes = 0;
- struct pim_ssm *ssm = pimg->ssm_info;
+ struct pim_ssm *ssm = pim->ssm_info;
+ char spaces[10];
+
+ if (pim->vrf_id == VRF_DEFAULT)
+ sprintf(spaces, "%s", "");
+ else
+ sprintf(spaces, "%s", " ");
- writes += pim_msdp_config_write(vty);
+ writes += pim_msdp_config_write_helper(pim, vty, spaces);
- if (!pimg->send_v6_secondary) {
- vty_out(vty, "no ip pim send-v6-secondary\n");
+ if (!pim->send_v6_secondary) {
+ vty_out(vty, "%sno ip pim send-v6-secondary\n", spaces);
++writes;
}
- writes += pim_rp_config_write(vty);
+ writes += pim_rp_config_write(pim, vty, spaces);
if (qpim_register_suppress_time
!= PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) {
- vty_out(vty, "ip pim register-suppress-time %d\n",
+ vty_out(vty, "%sip pim register-suppress-time %d\n", spaces,
qpim_register_suppress_time);
++writes;
}
if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) {
- vty_out(vty, "ip pim join-prune-interval %d\n",
+ vty_out(vty, "%sip pim join-prune-interval %d\n", spaces,
qpim_t_periodic);
++writes;
}
- if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) {
- vty_out(vty, "ip pim keep-alive-timer %d\n",
- qpim_keep_alive_time);
+ if (pim->keep_alive_time != PIM_KEEPALIVE_PERIOD) {
+ vty_out(vty, "%sip pim keep-alive-timer %d\n", spaces,
+ pim->keep_alive_time);
+ ++writes;
+ }
+ if (pim->rp_keep_alive_time != (unsigned int)PIM_RP_KEEPALIVE_PERIOD) {
+ vty_out(vty, "%sip pim rp keep-alive-timer %d\n", spaces,
+ pim->rp_keep_alive_time);
++writes;
}
if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) {
- vty_out(vty, "ip pim packets %d\n", qpim_packet_process);
+ vty_out(vty, "%sip pim packets %d\n", spaces,
+ qpim_packet_process);
++writes;
}
if (ssm->plist_name) {
- vty_out(vty, "ip pim ssm prefix-list %s\n", ssm->plist_name);
+ vty_out(vty, "%sip pim ssm prefix-list %s\n", spaces,
+ ssm->plist_name);
++writes;
}
- if (pimg->spt.switchover == PIM_SPT_INFINITY) {
- if (pimg->spt.plist)
+ if (pim->spt.switchover == PIM_SPT_INFINITY) {
+ if (pim->spt.plist)
vty_out(vty,
- "ip pim spt-switchover infinity-and-beyond prefix-list %s\n",
- pimg->spt.plist);
+ "%sip pim spt-switchover infinity-and-beyond prefix-list %s\n",
+ spaces, pim->spt.plist);
else
vty_out(vty,
- "ip pim spt-switchover infinity-and-beyond\n");
+ "%sip pim spt-switchover infinity-and-beyond\n",
+ spaces);
++writes;
}
if (qpim_ecmp_rebalance_enable) {
- vty_out(vty, "ip pim ecmp rebalance\n");
+ vty_out(vty, "%sip pim ecmp rebalance\n", spaces);
++writes;
} else if (qpim_ecmp_enable) {
- vty_out(vty, "ip pim ecmp\n");
+ vty_out(vty, "%sip pim ecmp\n", spaces);
++writes;
}
- if (qpim_ssmpingd_list) {
+ if (pim->ssmpingd_list) {
struct listnode *node;
struct ssmpingd_sock *ss;
- vty_out(vty, "!\n");
++writes;
- for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) {
+ for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", ss->source_addr, source_str,
sizeof(source_str));
- vty_out(vty, "ip ssmpingd %s\n", source_str);
+ vty_out(vty, "%sip ssmpingd %s\n", spaces, source_str);
++writes;
}
}
@@ -214,112 +232,140 @@ int pim_global_config_write(struct vty *vty)
return writes;
}
+int pim_global_config_write(struct vty *vty)
+{
+ return pim_global_config_write_worker(pimg, vty);
+}
+
int pim_interface_config_write(struct vty *vty)
{
- int writes = 0;
+ struct pim_instance *pim;
struct listnode *node;
struct interface *ifp;
+ struct vrf *vrf;
+ int writes = 0;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
+ continue;
- /* IF name */
- vty_out(vty, "interface %s\n", ifp->name);
- ++writes;
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
- if (ifp->info) {
- struct pim_interface *pim_ifp = ifp->info;
+ /* IF name */
+ if (vrf->vrf_id == VRF_DEFAULT)
+ vty_out(vty, "interface %s\n", ifp->name);
+ else
+ vty_out(vty, "interface %s vrf %s\n", ifp->name,
+ vrf->name);
+ ++writes;
- if (PIM_IF_TEST_PIM(pim_ifp->options)) {
- vty_out(vty, " ip pim sm\n");
- ++writes;
- }
+ if (ifp->info) {
+ struct pim_interface *pim_ifp = ifp->info;
- /* IF ip pim drpriority */
- if (pim_ifp->pim_dr_priority
- != PIM_DEFAULT_DR_PRIORITY) {
- vty_out(vty, " ip pim drpriority %u\n",
- pim_ifp->pim_dr_priority);
- ++writes;
- }
+ if (PIM_IF_TEST_PIM(pim_ifp->options)) {
+ vty_out(vty, " ip pim sm\n");
+ ++writes;
+ }
- /* IF ip pim hello */
- if (pim_ifp->pim_hello_period
- != PIM_DEFAULT_HELLO_PERIOD) {
- vty_out(vty, " ip pim hello %d",
- pim_ifp->pim_hello_period);
- if (pim_ifp->pim_default_holdtime != -1)
- vty_out(vty, " %d",
- pim_ifp->pim_default_holdtime);
- vty_out(vty, "\n");
- }
+ /* IF ip pim drpriority */
+ if (pim_ifp->pim_dr_priority
+ != PIM_DEFAULT_DR_PRIORITY) {
+ vty_out(vty, " ip pim drpriority %u\n",
+ pim_ifp->pim_dr_priority);
+ ++writes;
+ }
- /* update source */
- if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", pim_ifp->update_source,
- src_str, sizeof(src_str));
- vty_out(vty, " ip pim use-source %s\n",
- src_str);
- ++writes;
- }
+ /* IF ip pim hello */
+ if (pim_ifp->pim_hello_period
+ != PIM_DEFAULT_HELLO_PERIOD) {
+ vty_out(vty, " ip pim hello %d",
+ pim_ifp->pim_hello_period);
+ if (pim_ifp->pim_default_holdtime != -1)
+ vty_out(vty, " %d",
+ pim_ifp->pim_default_holdtime);
+ vty_out(vty, "\n");
+ }
- /* IF ip igmp */
- if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
- vty_out(vty, " ip igmp\n");
- ++writes;
- }
+ /* update source */
+ if (PIM_INADDR_ISNOT_ANY(
+ pim_ifp->update_source)) {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>",
+ pim_ifp->update_source,
+ src_str,
+ sizeof(src_str));
+ vty_out(vty, " ip pim use-source %s\n",
+ src_str);
+ ++writes;
+ }
- /* ip igmp version */
- if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) {
- vty_out(vty, " ip igmp version %d\n",
- pim_ifp->igmp_version);
- ++writes;
- }
+ /* IF ip igmp */
+ if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
+ vty_out(vty, " ip igmp\n");
+ ++writes;
+ }
- /* IF ip igmp query-interval */
- if (pim_ifp->igmp_default_query_interval
- != IGMP_GENERAL_QUERY_INTERVAL) {
- vty_out(vty, " ip igmp query-interval %d\n",
- pim_ifp->igmp_default_query_interval);
- ++writes;
- }
+ /* ip igmp version */
+ if (pim_ifp->igmp_version
+ != IGMP_DEFAULT_VERSION) {
+ vty_out(vty, " ip igmp version %d\n",
+ pim_ifp->igmp_version);
+ ++writes;
+ }
- /* IF ip igmp query-max-response-time */
- if (pim_ifp->igmp_query_max_response_time_dsec
- != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) {
- vty_out(vty,
- " ip igmp query-max-response-time %d\n",
- pim_ifp->igmp_query_max_response_time_dsec);
- ++writes;
- }
+ /* IF ip igmp query-interval */
+ if (pim_ifp->igmp_default_query_interval
+ != IGMP_GENERAL_QUERY_INTERVAL) {
+ vty_out(vty,
+ " ip igmp query-interval %d\n",
+ pim_ifp->igmp_default_query_interval);
+ ++writes;
+ }
- /* IF ip igmp join */
- if (pim_ifp->igmp_join_list) {
- struct listnode *node;
- struct igmp_join *ij;
- for (ALL_LIST_ELEMENTS_RO(
- pim_ifp->igmp_join_list, node,
- ij)) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<grp?>", ij->group_addr,
- group_str,
- sizeof(group_str));
- inet_ntop(AF_INET, &ij->source_addr,
- source_str,
- sizeof(source_str));
- vty_out(vty, " ip igmp join %s %s\n",
- group_str, source_str);
+ /* IF ip igmp query-max-response-time */
+ if (pim_ifp->igmp_query_max_response_time_dsec
+ != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) {
+ vty_out(vty,
+ " ip igmp query-max-response-time %d\n",
+ pim_ifp->igmp_query_max_response_time_dsec);
++writes;
}
- }
- writes += pim_static_write_mroute(vty, ifp);
+ /* IF ip igmp join */
+ if (pim_ifp->igmp_join_list) {
+ struct listnode *node;
+ struct igmp_join *ij;
+ for (ALL_LIST_ELEMENTS_RO(
+ pim_ifp->igmp_join_list,
+ node, ij)) {
+ char group_str[INET_ADDRSTRLEN];
+ char source_str
+ [INET_ADDRSTRLEN];
+ pim_inet4_dump(
+ "<grp?>",
+ ij->group_addr,
+ group_str,
+ sizeof(group_str));
+ inet_ntop(AF_INET,
+ &ij->source_addr,
+ source_str,
+ sizeof(source_str));
+ vty_out(vty,
+ " ip igmp join %s %s\n",
+ group_str, source_str);
+ ++writes;
+ }
+ }
+
+ writes +=
+ pim_static_write_mroute(pim, vty, ifp);
+ pim_bfd_write_config(vty, ifp);
+ }
+ vty_out(vty, "!\n");
+ ++writes;
}
- vty_out(vty, "!\n");
- ++writes;
- /* PIM BFD write */
- pim_bfd_write_config(vty, ifp);
}
return writes;
diff --git a/pimd/pim_vty.h b/pimd/pim_vty.h
index 54bab623dc..aef90cacc3 100644
--- a/pimd/pim_vty.h
+++ b/pimd/pim_vty.h
@@ -24,6 +24,7 @@
int pim_debug_config_write(struct vty *vty);
int pim_global_config_write(struct vty *vty);
+int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty);
int pim_interface_config_write(struct vty *vty);
#endif /* PIM_VTY_H */
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index c5cca7d1b4..7b060aef4b 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -80,8 +80,8 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -89,6 +89,23 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
if (if_is_operative(ifp))
pim_if_addr_add_all(ifp);
+ /*
+ * If we are a vrf device that is up, open up the pim_socket for
+ * listening
+ * to incoming pim messages irrelevant if the user has configured us
+ * for pim or not.
+ */
+ if (pim_if_is_vrf_device(ifp)) {
+ struct pim_interface *pim_ifp;
+
+ if (!ifp->info) {
+ pim_ifp = pim_if_new(ifp, 0, 0);
+ ifp->info = pim_ifp;
+ }
+
+ pim_sock_add(ifp);
+ }
+
return 0;
}
@@ -113,8 +130,8 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -129,6 +146,7 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
+ uint32_t table_id;
/*
zebra api notifies interface up/down events by using the same call
@@ -140,8 +158,8 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -154,6 +172,23 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
pim_if_addr_add_all(ifp);
}
+ /*
+ * If we have a pimreg device callback and it's for a specific
+ * table set the master appropriately
+ */
+ if (sscanf(ifp->name, "pimreg%d", &table_id) == 1) {
+ struct vrf *vrf;
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if ((table_id == vrf->data.l.table_id)
+ && (ifp->vrf_id != vrf->vrf_id)) {
+ struct interface *master = if_lookup_by_name(
+ vrf->name, vrf->vrf_id);
+ zclient_interface_set_master(zclient, master,
+ ifp);
+ }
+ }
+ }
return 0;
}
@@ -172,8 +207,8 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -252,11 +287,11 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
- zlog_debug("%s: %s connected IP address %s flags %u %s",
- __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags,
- CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
- ? "secondary"
- : "primary");
+ zlog_debug("%s: %s(%d) connected IP address %s flags %u %s",
+ __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
+ c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
+ ? "secondary"
+ : "primary");
#ifdef PIM_DEBUG_IFADDR_DUMP
dump_if_address(c->ifp);
@@ -292,8 +327,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
struct listnode *ifnode;
struct interface *ifp;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode,
- ifp)) {
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
if (!if_is_loopback(ifp) && if_is_operative(ifp))
pim_if_addr_add_all(ifp);
}
@@ -307,6 +341,8 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
{
struct connected *c;
struct prefix *p;
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+ struct pim_instance *pim = vrf->info;
/*
zebra api notifies address adds/dels events by using the same call
@@ -326,8 +362,8 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
zlog_debug(
- "%s: %s disconnected IP address %s flags %u %s",
- __PRETTY_FUNCTION__, c->ifp->name, buf,
+ "%s: %s(%d) disconnected IP address %s flags %u %s",
+ __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags,
CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
? "secondary"
@@ -339,8 +375,8 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
}
pim_if_addr_del(c, 0);
- pim_rp_setup();
- pim_i_am_rp_re_evaluate();
+ pim_rp_setup(pim);
+ pim_i_am_rp_re_evaluate(pim);
}
connected_free(c);
@@ -355,99 +391,128 @@ static void scan_upstream_rpf_cache()
struct listnode *node;
struct pim_upstream *up;
struct interface *ifp;
+ struct vrf *vrf;
+ struct pim_instance *pim;
- for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
- enum pim_rpf_result rpf_result;
- struct pim_rpf old;
- struct prefix nht_p;
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
+ continue;
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
- pim_resolve_upstream_nh(&nht_p);
+ for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode,
+ up)) {
+ enum pim_rpf_result rpf_result;
+ struct pim_rpf old;
+ struct prefix nht_p;
- old.source_nexthop.interface = up->rpf.source_nexthop.interface;
- old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
- rpf_result = pim_rpf_update(up, &old, 0);
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+ pim_resolve_upstream_nh(pim, &nht_p);
- if (rpf_result == PIM_RPF_FAILURE)
- continue;
+ old.source_nexthop.interface =
+ up->rpf.source_nexthop.interface;
+ old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
+ rpf_result = pim_rpf_update(pim, up, &old, 0);
- if (rpf_result == PIM_RPF_CHANGED) {
- struct pim_neighbor *nbr;
-
- nbr = pim_neighbor_find(old.source_nexthop.interface,
- old.rpf_addr.u.prefix4);
- if (nbr)
- pim_jp_agg_remove_group(nbr->upstream_jp_agg,
- up);
-
- /*
- * We have detected a case where we might need to rescan
- * the inherited o_list so do it.
- */
- if (up->channel_oil->oil_inherited_rescan) {
- pim_upstream_inherited_olist_decide(up);
- up->channel_oil->oil_inherited_rescan = 0;
- }
+ if (rpf_result == PIM_RPF_FAILURE)
+ continue;
- if (up->join_state == PIM_UPSTREAM_JOINED) {
- /*
- * If we come up real fast we can be here
- * where the mroute has not been installed
- * so install it.
- */
- if (!up->channel_oil->installed)
- pim_mroute_add(up->channel_oil,
- __PRETTY_FUNCTION__);
+ if (rpf_result == PIM_RPF_CHANGED) {
+ struct pim_neighbor *nbr;
+
+ nbr = pim_neighbor_find(
+ old.source_nexthop.interface,
+ old.rpf_addr.u.prefix4);
+ if (nbr)
+ pim_jp_agg_remove_group(
+ nbr->upstream_jp_agg, up);
/*
- * RFC 4601: 4.5.7. Sending (S,G) Join/Prune
- * Messages
- *
- * Transitions from Joined State
- *
- * RPF'(S,G) changes not due to an Assert
- *
- * The upstream (S,G) state machine remains in
- * Joined
- * state. Send Join(S,G) to the new upstream
- * neighbor, which is
- * the new value of RPF'(S,G). Send Prune(S,G)
- * to the old
- * upstream neighbor, which is the old value of
- * RPF'(S,G). Set
- * the Join Timer (JT) to expire after
- * t_periodic seconds.
+ * We have detected a case where we might need
+ * to rescan
+ * the inherited o_list so do it.
*/
- pim_jp_agg_switch_interface(&old, &up->rpf, up);
-
- pim_upstream_join_timer_restart(up, &old);
- } /* up->join_state == PIM_UPSTREAM_JOINED */
+ if (up->channel_oil->oil_inherited_rescan) {
+ pim_upstream_inherited_olist_decide(pim,
+ up);
+ up->channel_oil->oil_inherited_rescan =
+ 0;
+ }
- /* FIXME can join_desired actually be changed by
- pim_rpf_update()
- returning PIM_RPF_CHANGED ? */
- pim_upstream_update_join_desired(up);
+ if (up->join_state == PIM_UPSTREAM_JOINED) {
+ /*
+ * If we come up real fast we can be
+ * here
+ * where the mroute has not been
+ * installed
+ * so install it.
+ */
+ if (!up->channel_oil->installed)
+ pim_mroute_add(
+ up->channel_oil,
+ __PRETTY_FUNCTION__);
+
+ /*
+ * RFC 4601: 4.5.7. Sending (S,G)
+ * Join/Prune Messages
+ *
+ * Transitions from Joined State
+ *
+ * RPF'(S,G) changes not due to an
+ * Assert
+ *
+ * The upstream (S,G) state machine
+ * remains in Joined
+ * state. Send Join(S,G) to the new
+ * upstream neighbor, which is
+ * the new value of RPF'(S,G). Send
+ * Prune(S,G) to the old
+ * upstream neighbor, which is the old
+ * value of RPF'(S,G). Set
+ * the Join Timer (JT) to expire after
+ * t_periodic seconds.
+ */
+ pim_jp_agg_switch_interface(
+ &old, &up->rpf, up);
+
+ pim_upstream_join_timer_restart(up,
+ &old);
+ } /* up->join_state == PIM_UPSTREAM_JOINED */
+
+ /* FIXME can join_desired actually be changed by
+ pim_rpf_update()
+ returning PIM_RPF_CHANGED ? */
+ pim_upstream_update_join_desired(pim, up);
+
+ } /* PIM_RPF_CHANGED */
+
+ } /* for (qpim_upstream_list) */
+ }
- } /* PIM_RPF_CHANGED */
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
+ continue;
- } /* for (qpim_upstream_list) */
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp))
+ if (ifp->info) {
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_iface_upstream_switch *us;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp))
- if (ifp->info) {
- struct pim_interface *pim_ifp = ifp->info;
- struct pim_iface_upstream_switch *us;
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list,
- node, us)) {
- struct pim_rpf rpf;
- rpf.source_nexthop.interface = ifp;
- rpf.rpf_addr.u.prefix4 = us->address;
- pim_joinprune_send(&rpf, us->us);
- pim_jp_agg_clear_group(us->us);
+ for (ALL_LIST_ELEMENTS_RO(
+ pim_ifp->upstream_switch_list,
+ node, us)) {
+ struct pim_rpf rpf;
+ rpf.source_nexthop.interface = ifp;
+ rpf.rpf_addr.u.prefix4 = us->address;
+ pim_joinprune_send(&rpf, us->us);
+ pim_jp_agg_clear_group(us->us);
+ }
}
- }
+ }
}
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
@@ -456,7 +521,8 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
int input_iface_vif_index;
int old_vif_index;
- if (!pim_rp_set_upstream_addr(&vif_source, c_oil->oil.mfcc_origin,
+ if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
+ c_oil->oil.mfcc_origin,
c_oil->oil.mfcc_mcastgrp))
return;
@@ -480,11 +546,11 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
group_str, sizeof(group_str));
zlog_debug(
- "%s: channel_oil (%s, %s) upstream info is not present.",
+ "%s: channel_oil (%s,%s) upstream info is not present.",
__PRETTY_FUNCTION__, source_str, group_str);
}
input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
- vif_source, &src, &grp);
+ c_oil->pim, vif_source, &src, &grp);
}
if (input_iface_vif_index < 1) {
@@ -513,10 +579,10 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
}
if (PIM_DEBUG_ZEBRA) {
- struct interface *old_iif =
- pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
- struct interface *new_iif =
- pim_if_find_by_vif_index(input_iface_vif_index);
+ struct interface *old_iif = pim_if_find_by_vif_index(
+ c_oil->pim, c_oil->oil.mfcc_parent);
+ struct interface *new_iif = pim_if_find_by_vif_index(
+ c_oil->pim, input_iface_vif_index);
char source_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
@@ -532,8 +598,8 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
/* new iif loops to existing oif ? */
if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
- struct interface *new_iif =
- pim_if_find_by_vif_index(input_iface_vif_index);
+ struct interface *new_iif = pim_if_find_by_vif_index(
+ c_oil->pim, input_iface_vif_index);
if (PIM_DEBUG_ZEBRA) {
char source_str[INET_ADDRSTRLEN];
@@ -558,10 +624,10 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
if (PIM_DEBUG_MROUTE) {
/* just log warning */
- struct interface *old_iif =
- pim_if_find_by_vif_index(old_vif_index);
- struct interface *new_iif =
- pim_if_find_by_vif_index(input_iface_vif_index);
+ struct interface *old_iif = pim_if_find_by_vif_index(
+ c_oil->pim, old_vif_index);
+ struct interface *new_iif = pim_if_find_by_vif_index(
+ c_oil->pim, input_iface_vif_index);
char source_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
@@ -580,28 +646,44 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
}
}
-void pim_scan_oil()
+void pim_scan_oil(struct pim_instance *pim_matcher)
{
struct listnode *node;
struct listnode *nextnode;
struct channel_oil *c_oil;
ifindex_t ifindex;
int vif_index = 0;
+ struct vrf *vrf;
+ struct pim_instance *pim;
qpim_scan_oil_last = pim_time_monotonic_sec();
++qpim_scan_oil_events;
- for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) {
- if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
- ifindex = c_oil->up->rpf.source_nexthop
- .interface->ifindex;
- vif_index = pim_if_find_vifindex_by_ifindex(ifindex);
- /* Pass Current selected NH vif index to mroute download
- */
- if (vif_index)
- pim_scan_individual_oil(c_oil, vif_index);
- } else
- pim_scan_individual_oil(c_oil, 0);
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
+ continue;
+
+ if (pim_matcher && pim != pim_matcher)
+ continue;
+
+ for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode,
+ c_oil)) {
+ if (c_oil->up
+ && c_oil->up->rpf.source_nexthop.interface) {
+ ifindex = c_oil->up->rpf.source_nexthop
+ .interface->ifindex;
+ vif_index = pim_if_find_vifindex_by_ifindex(
+ pim, ifindex);
+ /* Pass Current selected NH vif index to mroute
+ * download */
+ if (vif_index)
+ pim_scan_individual_oil(c_oil,
+ vif_index);
+ } else
+ pim_scan_individual_oil(c_oil, 0);
+ }
}
}
@@ -611,7 +693,7 @@ static int on_rpf_cache_refresh(struct thread *t)
scan_upstream_rpf_cache();
/* update kernel multicast forwarding cache (MFC) */
- pim_scan_oil();
+ pim_scan_oil(NULL);
qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
++qpim_rpf_cache_refresh_events;
@@ -649,22 +731,13 @@ static void pim_zebra_connected(struct zclient *zclient)
/* Send the client registration */
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
- zclient_send_reg_requests(zclient, VRF_DEFAULT);
+ zclient_send_reg_requests(zclient, pimg->vrf_id);
}
void pim_zebra_init(void)
{
int i;
-#ifdef HAVE_TCP_ZEBRA
- zlog_notice(
- "zclient update contacting ZEBRA daemon at socket TCP %s,%d",
- "127.0.0.1", ZEBRA_PORT);
-#else
- zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s",
- zclient_serv_path_get());
-#endif
-
/* Socket for receiving updates from Zebra daemon */
zclient = zclient_new(master);
@@ -689,7 +762,7 @@ void pim_zebra_init(void)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default)
continue;
- vrf_bitmap_set(zclient->redist[AFI_IP][i], VRF_DEFAULT);
+ vrf_bitmap_set(zclient->redist[AFI_IP][i], pimg->vrf_id);
;
if (PIM_DEBUG_PIM_TRACE) {
zlog_debug("%s: requesting redistribution for %s (%i)",
@@ -700,7 +773,7 @@ void pim_zebra_init(void)
/* Request default information */
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
- VRF_DEFAULT);
+ pimg->vrf_id);
if (PIM_DEBUG_PIM_TRACE) {
zlog_info("%s: requesting default information redistribution",
@@ -713,7 +786,8 @@ void pim_zebra_init(void)
zclient_lookup_new();
}
-void igmp_anysource_forward_start(struct igmp_group *group)
+void igmp_anysource_forward_start(struct pim_instance *pim,
+ struct igmp_group *group)
{
struct igmp_source *source;
struct in_addr src_addr = {.s_addr = 0};
@@ -728,7 +802,7 @@ void igmp_anysource_forward_start(struct igmp_group *group)
return;
}
- igmp_source_forward_start(source);
+ igmp_source_forward_start(pim, source);
}
void igmp_anysource_forward_stop(struct igmp_group *group)
@@ -741,7 +815,8 @@ void igmp_anysource_forward_stop(struct igmp_group *group)
igmp_source_forward_stop(source);
}
-static void igmp_source_forward_reevaluate_one(struct igmp_source *source)
+static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
+ struct igmp_source *source)
{
struct prefix_sg sg;
struct igmp_group *group = source->source_group;
@@ -756,7 +831,7 @@ static void igmp_source_forward_reevaluate_one(struct igmp_source *source)
sg.grp = group->group_addr;
ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
- if (pim_is_grp_ssm(group->group_addr)) {
+ if (pim_is_grp_ssm(pim, group->group_addr)) {
/* If SSM group withdraw local membership */
if (ch
&& (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
@@ -785,39 +860,51 @@ void igmp_source_forward_reevaluate_all(void)
{
struct listnode *ifnode;
struct interface *ifp;
+ struct vrf *vrf;
+ struct pim_instance *pim;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
- struct pim_interface *pim_ifp = ifp->info;
- struct listnode *sock_node;
- struct igmp_sock *igmp;
-
- if (!pim_ifp)
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
continue;
- /* scan igmp sockets */
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
- igmp)) {
- struct listnode *grpnode;
- struct igmp_group *grp;
-
- /* scan igmp groups */
- for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
- grpnode, grp)) {
- struct listnode *srcnode;
- struct igmp_source *src;
-
- /* scan group sources */
- for (ALL_LIST_ELEMENTS_RO(
- grp->group_source_list, srcnode,
- src)) {
- igmp_source_forward_reevaluate_one(src);
- } /* scan group sources */
- } /* scan igmp groups */
- } /* scan igmp sockets */
- } /* scan interfaces */
+ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode,
+ ifp)) {
+ struct pim_interface *pim_ifp = ifp->info;
+ struct listnode *sock_node;
+ struct igmp_sock *igmp;
+
+ if (!pim_ifp)
+ continue;
+
+ /* scan igmp sockets */
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list,
+ sock_node, igmp)) {
+ struct listnode *grpnode;
+ struct igmp_group *grp;
+
+ /* scan igmp groups */
+ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
+ grpnode, grp)) {
+ struct listnode *srcnode;
+ struct igmp_source *src;
+
+ /* scan group sources */
+ for (ALL_LIST_ELEMENTS_RO(
+ grp->group_source_list,
+ srcnode, src)) {
+ igmp_source_forward_reevaluate_one(
+ pim, src);
+ } /* scan group sources */
+ } /* scan igmp groups */
+ } /* scan igmp sockets */
+ } /* scan interfaces */
+ }
}
-void igmp_source_forward_start(struct igmp_source *source)
+void igmp_source_forward_start(struct pim_instance *pim,
+ struct igmp_source *source)
{
struct igmp_group *group;
struct prefix_sg sg;
@@ -849,13 +936,12 @@ void igmp_source_forward_start(struct igmp_source *source)
struct in_addr vif_source;
struct pim_interface *pim_oif;
struct prefix nht_p, src, grp;
- int ret = 0;
struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop;
struct pim_upstream *up = NULL;
- if (!pim_rp_set_upstream_addr(&vif_source, source->source_addr,
- sg.grp))
+ if (!pim_rp_set_upstream_addr(pim, &vif_source,
+ source->source_addr, sg.grp))
return;
/* Register addr with Zebra NHT */
@@ -871,22 +957,21 @@ void igmp_source_forward_start(struct igmp_source *source)
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = sg.grp;
- if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL,
- &out_pnc))
- == 1) {
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
+ &out_pnc)) {
if (out_pnc.nexthop_num) {
- up = pim_upstream_find(&sg);
- memset(&nexthop, 0, sizeof(struct pim_nexthop));
+ up = pim_upstream_find(pim, &sg);
+ memset(&nexthop, 0, sizeof(nexthop));
if (up)
memcpy(&nexthop,
&up->rpf.source_nexthop,
sizeof(struct pim_nexthop));
- // Compute PIM RPF using Cached nexthop
- pim_ecmp_nexthop_search(&out_pnc, &nexthop,
+ pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop,
&src, &grp, 0);
if (nexthop.interface)
input_iface_vif_index =
pim_if_find_vifindex_by_ifindex(
+ pim,
nexthop.interface->ifindex);
} else {
if (PIM_DEBUG_ZEBRA) {
@@ -906,8 +991,8 @@ void igmp_source_forward_start(struct igmp_source *source)
}
} else
input_iface_vif_index =
- pim_ecmp_fib_lookup_if_vif_index(vif_source,
- &src, &grp);
+ pim_ecmp_fib_lookup_if_vif_index(
+ pim, vif_source, &src, &grp);
if (PIM_DEBUG_ZEBRA) {
char buf2[INET_ADDRSTRLEN];
@@ -966,7 +1051,7 @@ void igmp_source_forward_start(struct igmp_source *source)
}
source->source_channel_oil =
- pim_channel_oil_add(&sg, input_iface_vif_index);
+ pim_channel_oil_add(pim, &sg, input_iface_vif_index);
if (!source->source_channel_oil) {
if (PIM_DEBUG_IGMP_TRACE) {
zlog_debug(
@@ -1072,6 +1157,11 @@ void pim_forward_start(struct pim_ifchannel *ch)
struct pim_upstream *up = ch->upstream;
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
int input_iface_vif_index = 0;
+ struct pim_instance *pim;
+ struct pim_interface *pim_ifp;
+
+ pim_ifp = ch->interface->info;
+ pim = pim_ifp->pim;
if (PIM_DEBUG_PIM_TRACE) {
char source_str[INET_ADDRSTRLEN];
@@ -1096,7 +1186,6 @@ void pim_forward_start(struct pim_ifchannel *ch)
|| (up->channel_oil
&& up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
struct prefix nht_p, src, grp;
- int ret = 0;
struct pim_nexthop_cache out_pnc;
/* Register addr with Zebra NHT */
@@ -1108,9 +1197,8 @@ void pim_forward_start(struct pim_ifchannel *ch)
grp.u.prefix4 = up->sg.grp;
memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
- if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL,
- &out_pnc))
- == 1) {
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
+ &out_pnc)) {
if (out_pnc.nexthop_num) {
src.family = AF_INET;
src.prefixlen = IPV4_MAX_BITLEN;
@@ -1121,11 +1209,12 @@ void pim_forward_start(struct pim_ifchannel *ch)
grp.u.prefix4 = up->sg.grp;
// Compute PIM RPF using Cached nexthop
if (pim_ecmp_nexthop_search(
- &out_pnc, &up->rpf.source_nexthop,
- &src, &grp, 0)
- == 0)
+ pim, &out_pnc,
+ &up->rpf.source_nexthop, &src, &grp,
+ 0))
input_iface_vif_index =
pim_if_find_vifindex_by_ifindex(
+ pim,
up->rpf.source_nexthop
.interface->ifindex);
else {
@@ -1154,7 +1243,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
} else
input_iface_vif_index =
pim_ecmp_fib_lookup_if_vif_index(
- up->upstream_addr, &src, &grp);
+ pim, up->upstream_addr, &src, &grp);
if (input_iface_vif_index < 1) {
if (PIM_DEBUG_PIM_TRACE) {
@@ -1169,16 +1258,16 @@ void pim_forward_start(struct pim_ifchannel *ch)
return;
}
if (PIM_DEBUG_TRACE) {
- struct interface *in_intf =
- pim_if_find_by_vif_index(input_iface_vif_index);
+ struct interface *in_intf = pim_if_find_by_vif_index(
+ pim, input_iface_vif_index);
zlog_debug(
"%s: Update channel_oil IIF %s VIFI %d entry %s ",
__PRETTY_FUNCTION__,
in_intf ? in_intf->name : "NIL",
input_iface_vif_index, up->sg_str);
}
- up->channel_oil =
- pim_channel_oil_add(&up->sg, input_iface_vif_index);
+ up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+ input_iface_vif_index);
if (!up->channel_oil) {
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
@@ -1195,17 +1284,21 @@ void pim_forward_start(struct pim_ifchannel *ch)
pim_channel_add_oif(up->channel_oil, ch->interface, mask);
}
-void pim_forward_stop(struct pim_ifchannel *ch)
+void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
{
struct pim_upstream *up = ch->upstream;
if (PIM_DEBUG_PIM_TRACE) {
- zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__,
- ch->sg_str, ch->interface->name);
+ zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
+ __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name,
+ install_it, up->channel_oil->installed);
}
pim_channel_del_oif(up->channel_oil, ch->interface,
PIM_OIF_FLAG_PROTO_PIM);
+
+ if (install_it && !up->channel_oil->installed)
+ pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
}
void pim_zebra_zclient_update(struct vty *vty)
diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h
index 9b5450d66a..d9b17cb82d 100644
--- a/pimd/pim_zebra.h
+++ b/pimd/pim_zebra.h
@@ -30,17 +30,19 @@ void pim_zebra_init(void);
void pim_zebra_zclient_update(struct vty *vty);
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index);
-void pim_scan_oil(void);
+void pim_scan_oil(struct pim_instance *pim_matcher);
-void igmp_anysource_forward_start(struct igmp_group *group);
+void igmp_anysource_forward_start(struct pim_instance *pim,
+ struct igmp_group *group);
void igmp_anysource_forward_stop(struct igmp_group *group);
-void igmp_source_forward_start(struct igmp_source *source);
+void igmp_source_forward_start(struct pim_instance *pim,
+ struct igmp_source *source);
void igmp_source_forward_stop(struct igmp_source *source);
void igmp_source_forward_reevaluate_all(void);
void pim_forward_start(struct pim_ifchannel *ch);
-void pim_forward_stop(struct pim_ifchannel *ch);
+void pim_forward_stop(struct pim_ifchannel *ch, bool install_it);
void sched_rpf_cache_refresh(void);
struct zclient *pim_zebra_zclient_get(void);
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 027b18e123..df8ad4e428 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -135,13 +135,13 @@ void zclient_lookup_new(void)
__PRETTY_FUNCTION__);
}
-static int zclient_read_nexthop(struct zclient *zlookup,
+static int zclient_read_nexthop(struct pim_instance *pim,
+ struct zclient *zlookup,
struct pim_zlookup_nexthop nexthop_tab[],
const int tab_size, struct in_addr addr)
{
int num_ifindex = 0;
struct stream *s;
- const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */
uint16_t length;
u_char marker;
u_char version;
@@ -153,10 +153,11 @@ static int zclient_read_nexthop(struct zclient *zlookup,
int nexthop_num;
int i, err;
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
+ if (PIM_DEBUG_PIM_NHT_DETAIL) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str);
+ zlog_debug("%s: addr=%s(%s)", __PRETTY_FUNCTION__, addr_str,
+ pim->vrf->name);
}
s = zlookup->ibuf;
@@ -166,19 +167,11 @@ static int zclient_read_nexthop(struct zclient *zlookup,
err = zclient_read_header(s, zlookup->sock, &length, &marker,
&version, &vrf_id, &command);
if (err < 0) {
- zlog_err("%s %s: zclient_read_header() failed",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: zclient_read_header() failed",
+ __PRETTY_FUNCTION__);
zclient_lookup_failed(zlookup);
return -1;
}
-
- if (length < MIN_LEN) {
- zlog_err(
- "%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d",
- __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN);
- zclient_lookup_failed(zlookup);
- return -2;
- }
}
raddr.s_addr = stream_get_ipv4(s);
@@ -188,8 +181,9 @@ static int zclient_read_nexthop(struct zclient *zlookup,
char raddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str));
- zlog_warn("%s: address mismatch: addr=%s raddr=%s",
- __PRETTY_FUNCTION__, addr_str, raddr_str);
+ zlog_warn("%s: address mismatch: addr=%s(%s) raddr=%s",
+ __PRETTY_FUNCTION__, addr_str, pim->vrf->name,
+ raddr_str);
/* warning only */
}
@@ -198,8 +192,9 @@ static int zclient_read_nexthop(struct zclient *zlookup,
nexthop_num = stream_getc(s);
if (nexthop_num < 1) {
- zlog_err("%s: socket %d bad nexthop_num=%d", __func__,
- zlookup->sock, nexthop_num);
+ if (PIM_DEBUG_PIM_NHT_DETAIL)
+ zlog_debug("%s: socket %d bad nexthop_num=%d", __func__,
+ zlookup->sock, nexthop_num);
return -6;
}
@@ -214,9 +209,9 @@ static int zclient_read_nexthop(struct zclient *zlookup,
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_warn(
- "%s %s: found too many nexthop ifindexes (%d > %d) for address %s",
- __FILE__, __PRETTY_FUNCTION__,
- (num_ifindex + 1), tab_size, addr_str);
+ "%s: found too many nexthop ifindexes (%d > %d) for address %s(%s)",
+ __PRETTY_FUNCTION__, (num_ifindex + 1),
+ tab_size, addr_str, pim->vrf->name);
return num_ifindex;
}
switch (nexthop_type) {
@@ -256,17 +251,17 @@ static int zclient_read_nexthop(struct zclient *zlookup,
* If we are sending v6 secondary assume we receive v6
* secondary
*/
- if (pimg->send_v6_secondary)
+ if (pim->send_v6_secondary)
nbr = pim_neighbor_find_by_secondary(
if_lookup_by_index(
nexthop_tab[num_ifindex]
.ifindex,
- VRF_DEFAULT),
+ vrf_id),
&p);
else
nbr = pim_neighbor_find_if(if_lookup_by_index(
nexthop_tab[num_ifindex].ifindex,
- VRF_DEFAULT));
+ vrf_id));
if (nbr) {
nexthop_tab[num_ifindex].nexthop_addr.family =
AF_INET;
@@ -283,9 +278,9 @@ static int zclient_read_nexthop(struct zclient *zlookup,
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_warn(
- "%s %s: found non-ifindex nexthop type=%d for address %s",
- __FILE__, __PRETTY_FUNCTION__,
- nexthop_type, addr_str);
+ "%s: found non-ifindex nexthop type=%d for address %s(%s)",
+ __PRETTY_FUNCTION__, nexthop_type,
+ addr_str, pim->vrf->name);
}
break;
}
@@ -294,51 +289,61 @@ static int zclient_read_nexthop(struct zclient *zlookup,
return num_ifindex;
}
-static int zclient_lookup_nexthop_once(struct pim_zlookup_nexthop nexthop_tab[],
+static int zclient_lookup_nexthop_once(struct pim_instance *pim,
+ struct pim_zlookup_nexthop nexthop_tab[],
const int tab_size, struct in_addr addr)
{
struct stream *s;
int ret;
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
+ if (PIM_DEBUG_PIM_NHT_DETAIL) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str);
+ zlog_debug("%s: addr=%s(%s)", __PRETTY_FUNCTION__, addr_str,
+ pim->vrf->name);
}
/* Check socket. */
if (zlookup->sock < 0) {
- zlog_err("%s %s: zclient lookup socket is not connected",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: zclient lookup socket is not connected",
+ __PRETTY_FUNCTION__);
zclient_lookup_failed(zlookup);
return -1;
}
+ if (pim->vrf->vrf_id == VRF_UNKNOWN) {
+ zlog_err(
+ "%s: VRF: %s does not fully exist yet, delaying lookup",
+ __PRETTY_FUNCTION__, pim->vrf->name);
+ return -1;
+ }
+
s = zlookup->obuf;
stream_reset(s);
- zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT);
+ zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, pim->vrf_id);
stream_put_in_addr(s, &addr);
stream_putw_at(s, 0, stream_get_endp(s));
ret = writen(zlookup->sock, s->data, stream_get_endp(s));
if (ret < 0) {
zlog_err(
- "%s %s: writen() failure: %d writing to zclient lookup socket",
- __FILE__, __PRETTY_FUNCTION__, errno);
+ "%s: writen() failure: %d writing to zclient lookup socket",
+ __PRETTY_FUNCTION__, errno);
zclient_lookup_failed(zlookup);
return -2;
}
if (ret == 0) {
- zlog_err("%s %s: connection closed on zclient lookup socket",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: connection closed on zclient lookup socket",
+ __PRETTY_FUNCTION__);
zclient_lookup_failed(zlookup);
return -3;
}
- return zclient_read_nexthop(zlookup, nexthop_tab, tab_size, addr);
+ return zclient_read_nexthop(pim, zlookup, nexthop_tab, tab_size, addr);
}
-int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
+int zclient_lookup_nexthop(struct pim_instance *pim,
+ struct pim_zlookup_nexthop nexthop_tab[],
const int tab_size, struct in_addr addr,
int max_lookup)
{
@@ -353,17 +358,17 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
int first_ifindex;
struct prefix nexthop_addr;
- num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, tab_size,
- addr);
+ num_ifindex = zclient_lookup_nexthop_once(pim, nexthop_tab,
+ tab_size, addr);
if (num_ifindex < 1) {
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s",
- __FILE__, __PRETTY_FUNCTION__, lookup,
- max_lookup, addr_str);
+ "%s: lookup=%d/%d: could not find nexthop ifindex for address %s(%s)",
+ __PRETTY_FUNCTION__, lookup, max_lookup,
+ addr_str, pim->vrf->name);
}
return -1;
}
@@ -393,16 +398,16 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
if (lookup > 0) {
/* Report non-recursive success after first
* lookup */
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr,
addr_str,
sizeof(addr_str));
zlog_debug(
- "%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d",
- __FILE__, __PRETTY_FUNCTION__,
- lookup, max_lookup,
- first_ifindex, addr_str,
+ "%s: lookup=%d/%d: found non-recursive ifindex=%d for address %s(%s) dist=%d met=%d",
+ __PRETTY_FUNCTION__, lookup,
+ max_lookup, first_ifindex,
+ addr_str, pim->vrf->name,
nexthop_tab[0]
.protocol_distance,
nexthop_tab[0].route_metric);
@@ -420,7 +425,7 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
return num_ifindex;
}
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
char nexthop_str[PREFIX_STRLEN];
pim_inet4_dump("<addr?>", addr, addr_str,
@@ -428,9 +433,9 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str,
sizeof(nexthop_str));
zlog_debug(
- "%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d",
- __FILE__, __PRETTY_FUNCTION__, lookup,
- max_lookup, nexthop_str, addr_str,
+ "%s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s(%s) dist=%d met=%d",
+ __PRETTY_FUNCTION__, lookup, max_lookup,
+ nexthop_str, addr_str, pim->vrf->name,
nexthop_tab[0].protocol_distance,
nexthop_tab[0].route_metric);
}
@@ -441,13 +446,13 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
} /* for (max_lookup) */
- if (PIM_DEBUG_ZEBRA) {
+ if (PIM_DEBUG_PIM_NHT) {
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
zlog_warn(
- "%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s",
- __FILE__, __PRETTY_FUNCTION__, lookup, max_lookup,
- addr_str);
+ "%s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s(%s)",
+ __PRETTY_FUNCTION__, lookup, max_lookup, addr_str,
+ pim->vrf->name);
}
return -2;
@@ -472,7 +477,7 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
int count = 0;
int ret;
struct interface *ifp =
- pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
+ pim_if_find_by_vif_index(c_oil->pim, c_oil->oil.mfcc_parent);
if (PIM_DEBUG_ZEBRA) {
struct prefix_sg more;
@@ -480,15 +485,16 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
more.src = c_oil->oil.mfcc_origin;
more.grp = c_oil->oil.mfcc_mcastgrp;
zlog_debug(
- "Sending Request for New Channel Oil Information(%s) VIIF %d",
- pim_str_sg_dump(&more), c_oil->oil.mfcc_parent);
+ "Sending Request for New Channel Oil Information(%s) VIIF %d(%s)",
+ pim_str_sg_dump(&more), c_oil->oil.mfcc_parent,
+ c_oil->pim->vrf->name);
}
if (!ifp)
return -1;
stream_reset(s);
- zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT);
+ zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, c_oil->pim->vrf_id);
stream_put_in_addr(s, &c_oil->oil.mfcc_origin);
stream_put_in_addr(s, &c_oil->oil.mfcc_mcastgrp);
stream_putl(s, ifp->ifindex);
@@ -498,8 +504,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
ret = writen(zlookup->sock, s->data, count);
if (ret <= 0) {
zlog_err(
- "%s %s: writen() failure: %d writing to zclient lookup socket",
- __FILE__, __PRETTY_FUNCTION__, errno);
+ "%s: writen() failure: %d writing to zclient lookup socket",
+ __PRETTY_FUNCTION__, errno);
return -1;
}
@@ -516,8 +522,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
err = zclient_read_header(s, zlookup->sock, &length, &marker,
&version, &vrf_id, &command);
if (err < 0) {
- zlog_err("%s %s: zclient_read_header() failed",
- __FILE__, __PRETTY_FUNCTION__);
+ zlog_err("%s: zclient_read_header() failed",
+ __PRETTY_FUNCTION__);
zclient_lookup_failed(zlookup);
return -1;
}
@@ -527,18 +533,22 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
sg.grp.s_addr = stream_get_ipv4(s);
if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr
|| sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) {
- zlog_err("%s: Received wrong %s information",
- __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
+ if (PIM_DEBUG_ZEBRA) {
+ struct prefix_sg more;
+
+ more.src = c_oil->oil.mfcc_origin;
+ more.grp = c_oil->oil.mfcc_mcastgrp;
+ zlog_err(
+ "%s: Received wrong %s(%s) information requested",
+ __PRETTY_FUNCTION__, pim_str_sg_dump(&more),
+ c_oil->pim->vrf->name);
+ }
zclient_lookup_failed(zlookup);
return -3;
}
stream_get(&lastused, s, sizeof(lastused));
- ret = stream_getl(s);
-
- if (PIM_DEBUG_ZEBRA)
- zlog_debug("Received %lld for %s success: %d", lastused,
- pim_str_sg_dump(&sg), ret);
+ stream_getl(s);
c_oil->cc.lastused = lastused;
diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h
index d168464ce5..f8a2d59f68 100644
--- a/pimd/pim_zlookup.h
+++ b/pimd/pim_zlookup.h
@@ -36,7 +36,8 @@ struct pim_zlookup_nexthop {
void zclient_lookup_new(void);
void zclient_lookup_free(void);
-int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
+int zclient_lookup_nexthop(struct pim_instance *pim,
+ struct pim_zlookup_nexthop nexthop_tab[],
const int tab_size, struct in_addr addr,
int max_lookup);
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 89b235bed1..9a8e92cbb2 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -31,19 +31,15 @@
#include "pimd.h"
#include "pim_cmd.h"
-#include "pim_iface.h"
-#include "pim_zebra.h"
#include "pim_str.h"
#include "pim_oil.h"
#include "pim_pim.h"
-#include "pim_upstream.h"
-#include "pim_rpf.h"
#include "pim_ssmpingd.h"
#include "pim_static.h"
#include "pim_rp.h"
#include "pim_ssm.h"
#include "pim_zlookup.h"
-#include "pim_nht.h"
+#include "pim_zebra.h"
const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS;
const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS;
@@ -52,8 +48,6 @@ const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS;
struct thread_master *master = NULL;
uint32_t qpim_debugs = 0;
-int qpim_mroute_socket_fd = -1;
-int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */
int qpim_t_periodic =
PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
struct pim_assert_metric qpim_infinite_assert_metric;
@@ -62,17 +56,8 @@ struct thread *qpim_rpf_cache_refresher = NULL;
int64_t qpim_rpf_cache_refresh_requests = 0;
int64_t qpim_rpf_cache_refresh_events = 0;
int64_t qpim_rpf_cache_refresh_last = 0;
-struct list *qpim_ssmpingd_list = NULL;
-struct in_addr qpim_ssmpingd_group_addr;
int64_t qpim_scan_oil_events = 0;
int64_t qpim_scan_oil_last = 0;
-int64_t qpim_mroute_add_events = 0;
-int64_t qpim_mroute_add_last = 0;
-int64_t qpim_mroute_del_events = 0;
-int64_t qpim_mroute_del_last = 0;
-struct list *qpim_static_route_list = NULL;
-unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
-signed int qpim_rp_keep_alive_time = 0;
int64_t qpim_nexthop_lookups = 0;
int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
uint8_t qpim_ecmp_enable = 0;
@@ -82,134 +67,25 @@ struct pim_instance *pimg = NULL;
int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
-static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi);
-static void pim_instance_terminate(void);
-
-static int pim_vrf_new(struct vrf *vrf)
-{
- zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
- return 0;
-}
-
-static int pim_vrf_delete(struct vrf *vrf)
-{
- zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
- return 0;
-}
-
-static int pim_vrf_enable(struct vrf *vrf)
-{
-
- if (!vrf) // unexpected
- return -1;
-
- if (vrf->vrf_id == VRF_DEFAULT) {
- pimg = pim_instance_init(VRF_DEFAULT, AFI_IP);
- if (pimg == NULL) {
- zlog_err("%s %s: pim class init failure ", __FILE__,
- __PRETTY_FUNCTION__);
- /*
- * We will crash and burn otherwise
- */
- exit(1);
- }
-
- pimg->send_v6_secondary = 1;
- }
- return 0;
-}
-
-static int pim_vrf_disable(struct vrf *vrf)
-{
- if (vrf->vrf_id == VRF_DEFAULT)
- return 0;
-
- if (vrf->vrf_id == VRF_DEFAULT)
- pim_instance_terminate();
-
- /* Note: This is a callback, the VRF will be deleted by the caller. */
- return 0;
-}
-
-void pim_vrf_init(void)
-{
- vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete);
-}
-
-static void pim_vrf_terminate(void)
-{
- vrf_terminate();
-}
-
-/* Key generate for pim->rpf_hash */
-static unsigned int pim_rpf_hash_key(void *arg)
-{
- struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg;
-
- return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0);
-}
-
-/* Compare pim->rpf_hash node data */
-static int pim_rpf_equal(const void *arg1, const void *arg2)
-{
- const struct pim_nexthop_cache *r1 =
- (const struct pim_nexthop_cache *)arg1;
- const struct pim_nexthop_cache *r2 =
- (const struct pim_nexthop_cache *)arg2;
-
- return prefix_same(&r1->rpf.rpf_addr, &r2->rpf.rpf_addr);
-}
-
-/* Cleanup pim->rpf_hash each node data */
-static void pim_rp_list_hash_clean(void *data)
-{
- struct pim_nexthop_cache *pnc;
-
- pnc = (struct pim_nexthop_cache *)data;
- if (pnc->rp_list->count)
- list_delete_all_node(pnc->rp_list);
- if (pnc->upstream_list->count)
- list_delete_all_node(pnc->upstream_list);
-}
-
void pim_prefix_list_update(struct prefix_list *plist)
{
- pim_rp_prefix_list_update(plist);
- pim_ssm_prefix_list_update(plist);
- pim_upstream_spt_prefix_list_update(plist);
-}
+ struct pim_instance *pim;
+ struct vrf *vrf;
-static void pim_instance_terminate(void)
-{
- /* Traverse and cleanup rpf_hash */
- if (pimg->rpf_hash) {
- hash_clean(pimg->rpf_hash, (void *)pim_rp_list_hash_clean);
- hash_free(pimg->rpf_hash);
- pimg->rpf_hash = NULL;
- }
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ pim = vrf->info;
+ if (!pim)
+ continue;
- if (pimg->ssm_info) {
- pim_ssm_terminate(pimg->ssm_info);
- pimg->ssm_info = NULL;
+ pim_rp_prefix_list_update(pim, plist);
+ pim_ssm_prefix_list_update(pim, plist);
+ pim_upstream_spt_prefix_list_update(pim, plist);
}
-
- XFREE(MTYPE_PIM_PIM_INSTANCE, pimg);
}
static void pim_free()
{
- pim_ssmpingd_destroy();
-
- pim_oil_terminate();
-
- pim_upstream_terminate();
-
- if (qpim_static_route_list)
- list_free(qpim_static_route_list);
-
- pim_if_terminate();
- pim_rp_free();
-
pim_route_map_terminate();
zclient_lookup_free();
@@ -217,41 +93,8 @@ static void pim_free()
zprivs_terminate(&pimd_privs);
}
-static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi)
-{
- struct pim_instance *pim;
-
- pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance));
- if (!pim)
- return NULL;
-
- pim->vrf_id = vrf_id;
- pim->afi = afi;
-
- pim->spt.switchover = PIM_SPT_IMMEDIATE;
- pim->spt.plist = NULL;
-
- pim->rpf_hash =
- hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal, NULL);
-
- if (PIM_DEBUG_ZEBRA)
- zlog_debug("%s: NHT rpf hash init ", __PRETTY_FUNCTION__);
-
- pim->ssm_info = pim_ssm_init(vrf_id);
- if (!pim->ssm_info) {
- pim_instance_terminate();
- return NULL;
- }
-
- return pim;
-}
-
void pim_init()
{
- qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;
-
- pim_rp_init();
-
if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) {
zlog_err(
"%s %s: could not solve %s to group address: errno=%d: %s",
@@ -261,21 +104,6 @@ void pim_init()
return;
}
- pim_oil_init();
-
- pim_upstream_init();
-
- qpim_static_route_list = list_new();
- if (!qpim_static_route_list) {
- zlog_err("%s %s: failure: static_route_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return;
- }
- qpim_static_route_list->del = (void (*)(void *))pim_static_route_free;
-
- pim_mroute_socket_enable();
-
-
/*
RFC 4601: 4.6.3. Assert Metrics
@@ -290,9 +118,7 @@ void pim_init()
qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX;
qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY;
- pim_if_init();
pim_cmd_init();
- pim_ssmpingd_init();
}
void pim_terminate()
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 7934bce2d4..ed51db3dee 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -27,6 +27,7 @@
#include "vty.h"
#include "plist.h"
+#include "pim_instance.h"
#include "pim_str.h"
#include "pim_memory.h"
#include "pim_assert.h"
@@ -106,6 +107,8 @@
#define PIM_MASK_MSDP_EVENTS (1 << 19)
#define PIM_MASK_MSDP_PACKETS (1 << 20)
#define PIM_MASK_MSDP_INTERNAL (1 << 21)
+#define PIM_MASK_PIM_NHT (1 << 22)
+#define PIM_MASK_PIM_NHT_DETAIL (1 << 23)
/* PIM error codes */
#define PIM_SUCCESS 0
@@ -128,8 +131,6 @@ const char *const PIM_ALL_IGMP_ROUTERS;
extern struct thread_master *master;
extern struct zebra_privs_t pimd_privs;
uint32_t qpim_debugs;
-int qpim_mroute_socket_fd;
-int64_t qpim_mroute_socket_creation; /* timestamp of creation */
struct in_addr qpim_all_pim_routers_addr;
int qpim_t_periodic; /* Period between Join/Prune Messages */
struct pim_assert_metric qpim_infinite_assert_metric;
@@ -138,18 +139,9 @@ struct thread *qpim_rpf_cache_refresher;
int64_t qpim_rpf_cache_refresh_requests;
int64_t qpim_rpf_cache_refresh_events;
int64_t qpim_rpf_cache_refresh_last;
-struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */
-struct in_addr qpim_ssmpingd_group_addr;
int64_t qpim_scan_oil_events;
int64_t qpim_scan_oil_last;
-int64_t qpim_mroute_add_events;
-int64_t qpim_mroute_add_last;
-int64_t qpim_mroute_del_events;
-int64_t qpim_mroute_del_last;
int64_t qpim_nexthop_lookups;
-struct list *qpim_static_route_list; /* list of routes added statically */
-extern unsigned int qpim_keep_alive_time;
-extern signed int qpim_rp_keep_alive_time;
extern int qpim_packet_process;
extern uint8_t qpim_ecmp_enable;
extern uint8_t qpim_ecmp_rebalance_enable;
@@ -189,6 +181,8 @@ extern int32_t qpim_register_probe_time;
#define PIM_DEBUG_MSDP_EVENTS (qpim_debugs & PIM_MASK_MSDP_EVENTS)
#define PIM_DEBUG_MSDP_PACKETS (qpim_debugs & PIM_MASK_MSDP_PACKETS)
#define PIM_DEBUG_MSDP_INTERNAL (qpim_debugs & PIM_MASK_MSDP_INTERNAL)
+#define PIM_DEBUG_PIM_NHT (qpim_debugs & PIM_MASK_PIM_NHT)
+#define PIM_DEBUG_PIM_NHT_DETAIL (qpim_debugs & PIM_MASK_PIM_NHT_DETAIL)
#define PIM_DEBUG_EVENTS (qpim_debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS | PIM_MASK_MSDP_EVENTS))
#define PIM_DEBUG_PACKETS (qpim_debugs & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS | PIM_MASK_MSDP_PACKETS))
@@ -199,6 +193,7 @@ extern int32_t qpim_register_probe_time;
#define PIM_DO_DEBUG_PIM_PACKETDUMP_SEND (qpim_debugs |= PIM_MASK_PIM_PACKETDUMP_SEND)
#define PIM_DO_DEBUG_PIM_PACKETDUMP_RECV (qpim_debugs |= PIM_MASK_PIM_PACKETDUMP_RECV)
#define PIM_DO_DEBUG_PIM_TRACE (qpim_debugs |= PIM_MASK_PIM_TRACE)
+#define PIM_DO_DEBUG_PIM_TRACE_DETAIL (qpim_debugs |= PIM_MASK_PIM_TRACE_DETAIL)
#define PIM_DO_DEBUG_IGMP_EVENTS (qpim_debugs |= PIM_MASK_IGMP_EVENTS)
#define PIM_DO_DEBUG_IGMP_PACKETS (qpim_debugs |= PIM_MASK_IGMP_PACKETS)
#define PIM_DO_DEBUG_IGMP_TRACE (qpim_debugs |= PIM_MASK_IGMP_TRACE)
@@ -214,12 +209,14 @@ extern int32_t qpim_register_probe_time;
#define PIM_DO_DEBUG_MSDP_EVENTS (qpim_debugs |= PIM_MASK_MSDP_EVENTS)
#define PIM_DO_DEBUG_MSDP_PACKETS (qpim_debugs |= PIM_MASK_MSDP_PACKETS)
#define PIM_DO_DEBUG_MSDP_INTERNAL (qpim_debugs |= PIM_MASK_MSDP_INTERNAL)
+#define PIM_DO_DEBUG_PIM_NHT (qpim_debugs |= PIM_MASK_PIM_NHT)
#define PIM_DONT_DEBUG_PIM_EVENTS (qpim_debugs &= ~PIM_MASK_PIM_EVENTS)
#define PIM_DONT_DEBUG_PIM_PACKETS (qpim_debugs &= ~PIM_MASK_PIM_PACKETS)
#define PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND (qpim_debugs &= ~PIM_MASK_PIM_PACKETDUMP_SEND)
#define PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV (qpim_debugs &= ~PIM_MASK_PIM_PACKETDUMP_RECV)
#define PIM_DONT_DEBUG_PIM_TRACE (qpim_debugs &= ~PIM_MASK_PIM_TRACE)
+#define PIM_DONT_DEBUG_PIM_TRACE_DETAIL (qpim_debugs &= ~PIM_MASK_PIM_TRACE_DETAIL)
#define PIM_DONT_DEBUG_IGMP_EVENTS (qpim_debugs &= ~PIM_MASK_IGMP_EVENTS)
#define PIM_DONT_DEBUG_IGMP_PACKETS (qpim_debugs &= ~PIM_MASK_IGMP_PACKETS)
#define PIM_DONT_DEBUG_IGMP_TRACE (qpim_debugs &= ~PIM_MASK_IGMP_TRACE)
@@ -235,37 +232,13 @@ extern int32_t qpim_register_probe_time;
#define PIM_DONT_DEBUG_MSDP_EVENTS (qpim_debugs &= ~PIM_MASK_MSDP_EVENTS)
#define PIM_DONT_DEBUG_MSDP_PACKETS (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS)
#define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL)
-
-enum pim_spt_switchover {
- PIM_SPT_IMMEDIATE,
- PIM_SPT_INFINITY,
-};
-
-/* Per VRF PIM DB */
-struct pim_instance {
- afi_t afi;
- vrf_id_t vrf_id;
-
- struct {
- enum pim_spt_switchover switchover;
- char *plist;
- } spt;
-
- struct hash *rpf_hash;
-
- void *ssm_info; /* per-vrf SSM configuration */
-
- int send_v6_secondary;
-};
-
-extern struct pim_instance *pimg; // Pim Global Instance
+#define PIM_DONT_DEBUG_PIM_NHT (qpim_debugs &= ~PIM_MASK_PIM_NHT)
void pim_init(void);
void pim_terminate(void);
extern void pim_route_map_init(void);
extern void pim_route_map_terminate(void);
-void pim_vrf_init(void);
void pim_prefix_list_update(struct prefix_list *plist);
#endif /* PIMD_H */
diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c
index 14ec9fb02b..3d104e7c7c 100644
--- a/pimd/test_igmpv3_join.c
+++ b/pimd/test_igmpv3_join.c
@@ -138,7 +138,8 @@ int main(int argc, const char *argv[])
printf("%s: waiting...\n", prog_name);
- getchar();
+ if (getchar() == EOF)
+ fprintf(stderr, "getchar failure\n");
close(fd);
diff --git a/pkgsrc/Makefile.am b/pkgsrc/Makefile.am
deleted file mode 100644
index 622fbf0748..0000000000
--- a/pkgsrc/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-rcdir=@pkgsrcrcdir@
-
-rc_SCRIPTS = bgpd.sh ospf6d.sh ospfd.sh ripd.sh ripngd.sh zebra.sh
diff --git a/python/Makefile.am b/python/Makefile.am
deleted file mode 100644
index 4ad1e36b59..0000000000
--- a/python/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-EXTRA_DIST = \
- clidef.py \
- clippy/__init__.py
diff --git a/qpb/.gitignore b/qpb/.gitignore
index b133c52a42..17e90443e9 100644
--- a/qpb/.gitignore
+++ b/qpb/.gitignore
@@ -1,4 +1,4 @@
-Makefile
+!Makefile
Makefile.in
*.o
tags
diff --git a/qpb/Makefile b/qpb/Makefile
new file mode 100644
index 0000000000..2237def02c
--- /dev/null
+++ b/qpb/Makefile
@@ -0,0 +1,10 @@
+all: ALWAYS
+ @$(MAKE) -s -C .. fpm/libfrr_pb.la
+%: ALWAYS
+ @$(MAKE) -s -C .. fpm/$@
+
+Makefile:
+ #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/qpb/Makefile.am b/qpb/Makefile.am
deleted file mode 100644
index e5951b2be9..0000000000
--- a/qpb/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-include ../common.am
-
-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
-
-PROTOBUF_INCLUDES=-I$(top_srcdir)
-PROTOBUF_PACKAGE = qpb
-
-lib_LTLIBRARIES = libfrr_pb.la
-libfrr_pb_la_LDFLAGS = -version-info 0:0:0
-
-if HAVE_PROTOBUF
-protobuf_srcs = \
- qpb_allocator.c
-
-protobuf_srcs_nodist = \
- qpb.pb-c.c
-endif
-
-libfrr_pb_la_SOURCES = \
- linear_allocator.h \
- qpb.h \
- qpb.c \
- qpb_allocator.h \
- $(protobuf_srcs)
-
-nodist_libfrr_pb_la_SOURCES = $(protobuf_srcs_nodist)
-
-CLEANFILES = $(Q_CLEANFILES)
-BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
-EXTRA_DIST = qpb.proto
diff --git a/qpb/qpb.proto b/qpb/qpb.proto
index a1595a9abd..c06debb954 100644
--- a/qpb/qpb.proto
+++ b/qpb/qpb.proto
@@ -20,6 +20,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+syntax = "proto2";
+
/*
* Protobuf definitions pertaining to the Quagga/FRR Protobuf component.
*/
@@ -87,4 +89,4 @@ enum Protocol {
ISIS = 8;
BGP = 9;
OTHER = 10;
-} \ No newline at end of file
+}
diff --git a/qpb/qpb_allocator.c b/qpb/qpb_allocator.c
index 8b0ee941a5..7e5ba5b0ce 100644
--- a/qpb/qpb_allocator.c
+++ b/qpb/qpb_allocator.c
@@ -42,8 +42,7 @@ static void _qpb_free(void *allocator_data, void *ptr)
linear_allocator_free(allocator_data, ptr);
}
-static ProtobufCAllocator allocator_template = {_qpb_alloc, _qpb_free, NULL,
- 8192, NULL};
+static ProtobufCAllocator allocator_template = {_qpb_alloc, _qpb_free, NULL};
/*
* qpb_allocator_init_linear
diff --git a/qpb/subdir.am b/qpb/subdir.am
new file mode 100644
index 0000000000..71e501b9c2
--- /dev/null
+++ b/qpb/subdir.am
@@ -0,0 +1,26 @@
+if HAVE_PROTOBUF
+lib_LTLIBRARIES += qpb/libfrr_pb.la
+endif
+
+qpb_libfrr_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
+ $(Q_PROTOBUF_C_CLIENT_INCLUDES)
+qpb_libfrr_pb_la_LDFLAGS = -version-info 0:0:0
+
+qpb_libfrr_pb_la_SOURCES = \
+ qpb/linear_allocator.h \
+ qpb/qpb.h \
+ qpb/qpb.c \
+ qpb/qpb_allocator.h \
+ # end
+
+if HAVE_PROTOBUF
+qpb_libfrr_pb_la_SOURCES += qpb/qpb_allocator.c
+nodist_qpb_libfrr_pb_la_SOURCES = qpb/qpb.pb-c.c
+BUILT_SOURCES += qpb/qpb.pb-c.c
+CLEANFILES += \
+ qpb/qpb.pb-c.c \
+ qpb/qpb.pb-c.h \
+ # end
+endif
+
+EXTRA_DIST += qpb/qpb.proto
diff --git a/redhat/Makefile.am b/redhat/Makefile.am
deleted file mode 100644
index 74856cfd82..0000000000
--- a/redhat/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-
-EXTRA_DIST = frr.init frr.service daemons \
- frr.logrotate frr.pam frr.spec \
- README.rpm_build.md
-
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 674ccb2d6f..b23249e04e 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -168,7 +168,8 @@ Requires(pre): initscripts >= 5.60
%endif
Provides: routingdaemon = %{version}-%{release}
BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Obsoletes: bird gated mrt zebra frr-sysvinit
+Obsoletes: gated mrt zebra frr-sysvinit
+Conflicts: bird
%description
FRRouting is a free software that manages TCP/IP based routing
diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c
index 763bfc142c..0a6337bf76 100644
--- a/ripd/rip_peer.c
+++ b/ripd/rip_peer.c
@@ -143,10 +143,6 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
uptime -= peer->uptime;
tm = gmtime(&uptime);
-/* Making formatted timer strings. */
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
if (uptime < ONE_DAY_SECOND)
snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
tm->tm_sec);
diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c
index 2a412f9b64..cd46d97402 100644
--- a/ripngd/ripng_peer.c
+++ b/ripngd/ripng_peer.c
@@ -151,10 +151,6 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
uptime -= peer->uptime;
tm = gmtime(&uptime);
-/* Making formatted timer strings. */
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
if (uptime < ONE_DAY_SECOND)
snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
tm->tm_sec);
diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am
deleted file mode 100644
index a8220670d1..0000000000
--- a/snapcraft/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-EXTRA_DIST = snapcraft.yaml \
- README.snap_build.md \
- README.usage.md \
- extra_version_info.txt \
- scripts \
- defaults \
- helpers \
- snap
diff --git a/tests/.gitignore b/tests/.gitignore
index 6d54ae155b..113bdea098 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -25,6 +25,8 @@ __pycache__
/bgpd/test_ecommunity
/bgpd/test_mp_attr
/bgpd/test_mpath
+/isisd/test_fuzz_isis_tlv
+/isisd/test_fuzz_isis_tlv_tests.h
/lib/cli/test_cli
/lib/cli/test_commands
/lib/cli/test_commands_defun.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 43003e7075..0c31c0441a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -24,6 +24,13 @@ else
TESTS_BGPD =
endif
+if ISISD
+TESTS_ISISD = \
+ isisd/test_fuzz_isis_tlv
+else
+TESTS_ISISD =
+endif
+
if OSPF6D
TESTS_OSPF6D = \
ospf6d/test_lsdb \
@@ -61,6 +68,7 @@ check_PROGRAMS = \
lib/cli/test_cli \
lib/cli/test_commands \
$(TESTS_BGPD) \
+ $(TESTS_ISISD) \
$(TESTS_OSPF6D) \
# end
@@ -75,7 +83,12 @@ lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c
< ../vtysh/vtysh_cmd.c \
> "$@"
-BUILT_SOURCES = lib/cli/test_commands_defun.c
+isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+ gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
+
+BUILT_SOURCES = \
+ lib/cli/test_commands_defun.c \
+ isisd/test_fuzz_isis_tlv_tests.h
noinst_HEADERS = \
./helpers/c/prng.h \
@@ -110,11 +123,14 @@ bgpd_test_capability_SOURCES = bgpd/test_capability.c
bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
+isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
+isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd
ospf6d_test_lsdb_SOURCES = ospf6d/test_lsdb.c lib/cli/common_cli.c
ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@
BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm
+ISISD_TEST_LDADD = ../isisd/libisis.a $(ALL_TESTS_LDADD)
OSPF6_TEST_LDADD = ../ospf6d/libospf6.a $(ALL_TESTS_LDADD)
lib_test_buffer_LDADD = $(ALL_TESTS_LDADD)
@@ -140,6 +156,7 @@ bgpd_test_capability_LDADD = $(BGP_TEST_LDADD)
bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
+isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
EXTRA_DIST = \
@@ -151,6 +168,8 @@ EXTRA_DIST = \
bgpd/test_mpath.py \
helpers/python/frrsix.py \
helpers/python/frrtest.py \
+ isisd/test_fuzz_isis_tlv.py \
+ isisd/test_fuzz_isis_tlv_tests.h.gz \
lib/cli/test_commands.in \
lib/cli/test_commands.py \
lib/cli/test_commands.refout \
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index 9ec2b5df19..e8700a8b4a 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -170,7 +170,7 @@ static struct test_segment mp_segments[] = {
/* 8 */
{
"MP6",
- "MP IP4/MPLS-laveled VPN",
+ "MP IP4/MPLS-labeled VPN",
{CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80},
6,
SHOULD_PARSE,
diff --git a/tests/bgpd/test_capability.py b/tests/bgpd/test_capability.py
index 4cb650092b..872fcb6d12 100644
--- a/tests/bgpd/test_capability.py
+++ b/tests/bgpd/test_capability.py
@@ -8,7 +8,7 @@ TestCapability.okfail("MPv6: MP IPv6/Uni")
TestCapability.okfail("MP2: MP IP/Multicast")
TestCapability.okfail("MP3: MP IP6/MPLS-labeled VPN")
TestCapability.okfail("MP5: MP IP6/MPLS-VPN")
-TestCapability.okfail("MP6: MP IP4/MPLS-laveled VPN")
+TestCapability.okfail("MP6: MP IP4/MPLS-labeled VPN")
TestCapability.okfail("MP8: MP unknown AFI/SAFI")
TestCapability.okfail("MP-short: MP IP4/Unicast, length too short (< minimum)")
TestCapability.okfail("MP-overflow: MP IP4/Unicast, length too long")
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index 7c0afa1b92..30d5fdd6cd 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -1059,7 +1059,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
if (!parse_ret) {
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
/* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_int2iana(nlri.afi, nlri.safi, &pkt_afi,
diff --git a/tests/isisd/.gitignore b/tests/isisd/.gitignore
new file mode 100644
index 0000000000..e124221296
--- /dev/null
+++ b/tests/isisd/.gitignore
@@ -0,0 +1 @@
+/*_afl/*
diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c
new file mode 100644
index 0000000000..6727e663f5
--- /dev/null
+++ b/tests/isisd/test_fuzz_isis_tlv.c
@@ -0,0 +1,188 @@
+#include "test_fuzz_isis_tlv_tests.h"
+
+#include <zebra.h>
+
+#include "memory.h"
+#include "sbuf.h"
+#include "stream.h"
+#include "thread.h"
+
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlvs.h"
+
+#define TEST_STREAM_SIZE 1500
+
+struct thread_master *master;
+int isis_sock_init(struct isis_circuit *circuit);
+int isis_sock_init(struct isis_circuit *circuit)
+{
+ return 0;
+}
+
+static bool atexit_registered;
+
+static void show_meminfo_at_exit(void)
+{
+ log_memstats_stderr("isis fuzztest");
+}
+
+static int comp_line(const void *p1, const void *p2)
+{
+ return strcmp(*(char * const *)p1, *(char * const *)p2);
+}
+
+static char *sortlines(char *in)
+{
+ size_t line_count = 1;
+ size_t rv_len = strlen(in) + 1;
+ size_t rv_pos = 0;
+ char *rv = XMALLOC(MTYPE_TMP, rv_len);
+
+ for (char *c = in; *c; c++) {
+ if (*c == '\n')
+ line_count++;
+ }
+
+ if (line_count == 1) {
+ strncpy(rv, in, rv_len);
+ return rv;
+ }
+
+ char **lines = XCALLOC(MTYPE_TMP, sizeof(char *)*line_count);
+ char *saveptr = NULL;
+ size_t i = 0;
+
+ for (char *line = strtok_r(in, "\n", &saveptr); line;
+ line = strtok_r(NULL, "\n", &saveptr)) {
+ lines[i++] = line;
+ assert(i <= line_count);
+ }
+
+ line_count = i;
+
+ qsort(lines, line_count, sizeof(char *), comp_line);
+
+ for (i = 0; i < line_count; i++) {
+ int printf_rv = snprintf(rv + rv_pos, rv_len - rv_pos, "%s\n", lines[i]);
+ assert(printf_rv >= 0);
+ rv_pos += printf_rv;
+ }
+
+ XFREE(MTYPE_TMP, lines);
+ return rv;
+}
+
+static int test(FILE *input, FILE *output)
+{
+ struct stream *s = stream_new(TEST_STREAM_SIZE);
+ char buf[TEST_STREAM_SIZE];
+ size_t bytes_read = 0;
+
+ if (!atexit_registered) {
+ atexit(show_meminfo_at_exit);
+ atexit_registered = true;
+ }
+
+ while (STREAM_WRITEABLE(s) && !feof(input)) {
+ bytes_read = fread(buf, 1, STREAM_WRITEABLE(s), input);
+ if (bytes_read == 0)
+ break;
+ stream_put(s, buf, bytes_read);
+ }
+
+ if (bytes_read && !feof(input)) {
+ fprintf(output, "Too much input data.\n");
+ stream_free(s);
+ return 1;
+ }
+
+ stream_set_getp(s, 0);
+ struct isis_tlvs *tlvs;
+ const char *log;
+ int rv = isis_unpack_tlvs(STREAM_READABLE(s), s, &tlvs, &log);
+
+ if (rv) {
+ fprintf(output, "Could not unpack TLVs:\n%s\n", log);
+ isis_free_tlvs(tlvs);
+ stream_free(s);
+ return 2;
+ }
+
+ fprintf(output, "Unpack log:\n%s", log);
+ const char *s_tlvs = isis_format_tlvs(tlvs);
+ fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
+
+ struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
+ isis_free_tlvs(tlvs);
+
+ struct stream *s2 = stream_new(TEST_STREAM_SIZE);
+
+ if (isis_pack_tlvs(tlv_copy, s2, (size_t)-1, false, false)) {
+ fprintf(output, "Could not pack TLVs.\n");
+ assert(0);
+ }
+
+ stream_set_getp(s2, 0);
+ rv = isis_unpack_tlvs(STREAM_READABLE(s2), s2, &tlvs, &log);
+ if (rv) {
+ fprintf(output, "Could not unpack own TLVs:\n%s\n", log);
+ assert(0);
+ }
+
+ char *orig_tlvs = XSTRDUP(MTYPE_TMP, s_tlvs);
+ s_tlvs = isis_format_tlvs(tlvs);
+
+ if (strcmp(orig_tlvs, s_tlvs)) {
+ fprintf(output,
+ "Deserialized and Serialized LSP seem to differ.\n");
+ fprintf(output, "Re-Unpacked TLVs:\n%s", s_tlvs);
+ assert(0);
+ }
+
+ isis_free_tlvs(tlv_copy);
+ stream_free(s);
+ stream_free(s2);
+
+ struct list *fragments = isis_fragment_tlvs(tlvs, 550);
+ isis_free_tlvs(tlvs);
+ if (!fragments) {
+ XFREE(MTYPE_TMP, orig_tlvs);
+ return 0;
+ }
+
+ s = stream_new(550);
+
+ struct sbuf fragment_format;
+ sbuf_init(&fragment_format, NULL, 0);
+
+ struct listnode *node;
+ for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) {
+ stream_reset(s);
+ int rv = isis_pack_tlvs(tlvs, s, (size_t)-1, false, false);
+ if (rv) {
+ fprintf(output, "Could not pack fragment, too large.\n");
+ assert(0);
+ }
+ sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs));
+ isis_free_tlvs(tlvs);
+ }
+ list_delete(fragments);
+ stream_free(s);
+
+ char *fragment_content = sortlines((char *)sbuf_buf(&fragment_format));
+ sbuf_free(&fragment_format);
+ char *orig_tlv_content = sortlines(orig_tlvs);
+ XFREE(MTYPE_TMP, orig_tlvs);
+
+ if (strcmp(fragment_content, orig_tlv_content)) {
+ fprintf(output, "Fragmented and unfragmented LSP seem to differ.\n");
+ fprintf(output, "Original:\n%s\nFragmented:\n%s\n",
+ orig_tlv_content, fragment_content);
+ assert(0);
+ }
+
+ XFREE(MTYPE_TMP, fragment_content);
+ XFREE(MTYPE_TMP, orig_tlv_content);
+
+ return 0;
+}
diff --git a/tests/isisd/test_fuzz_isis_tlv.py b/tests/isisd/test_fuzz_isis_tlv.py
new file mode 100644
index 0000000000..60938472b5
--- /dev/null
+++ b/tests/isisd/test_fuzz_isis_tlv.py
@@ -0,0 +1,6 @@
+import frrtest
+
+class TestFuzzIsisTLV(frrtest.TestMultiOut):
+ program = './test_fuzz_isis_tlv'
+
+TestFuzzIsisTLV.exit_cleanly()
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
new file mode 100644
index 0000000000..3eb0205a5d
--- /dev/null
+++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
Binary files differ
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 8b66ba2564..d179ed1d99 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -147,6 +147,7 @@ vtysh_cmd_FILES = $(vtysh_scan) \
$(top_srcdir)/zebra/zebra_fpm.c \
$(top_srcdir)/zebra/zebra_ptm.c \
$(top_srcdir)/zebra/zebra_mpls_vty.c \
+ $(top_srcdir)/zebra/zebra_pw.c \
$(top_srcdir)/watchfrr/watchfrr_vty.c \
$(BGP_VNC_RFAPI_SRC) $(BGP_VNC_RFP_SRC)
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index ca280c5872..f33c7b9603 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -85,7 +85,7 @@ foreach (@ARGV) {
$protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD";
}
elsif ($file =~ /lib\/vrf\.c$/) {
- $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_EIGRPD|VTYSH_BABELD";
+ $protocol = "VTYSH_ALL";
}
elsif ($file =~ /lib\/filter\.c$/) {
$protocol = "VTYSH_ALL";
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index f6a2c92586..76c42173da 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -218,15 +218,27 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
{
struct vtysh_client *client;
int rc, rc_all = CMD_SUCCESS;
+ int correct_instance = 0, wrong_instance = 0;
for (client = head_client; client; client = client->next) {
rc = vtysh_client_run(client, line, fp, callback, cbarg);
+ if (rc == CMD_NOT_MY_INSTANCE) {
+ wrong_instance++;
+ continue;
+ }
+ correct_instance++;
if (rc != CMD_SUCCESS) {
if (!continue_on_err)
return rc;
rc_all = rc;
}
}
+ if (wrong_instance && !correct_instance && fp) {
+ fprintf(fp,
+ "%% [%s]: command ignored as it targets an instance that is not running\n",
+ head_client->name);
+ rc_all = CMD_WARNING_CONFIG_FAILED;
+ }
return rc_all;
}
@@ -911,6 +923,10 @@ static struct cmd_node interface_node = {
INTERFACE_NODE, "%s(config-if)# ",
};
+static struct cmd_node pw_node = {
+ PW_NODE, "%s(config-pw)# ",
+};
+
static struct cmd_node ns_node = {
NS_NODE, "%s(config-logical-router)# ",
};
@@ -1406,6 +1422,7 @@ static int vtysh_exit(struct vty *vty)
vty->node = ENABLE_NODE;
break;
case INTERFACE_NODE:
+ case PW_NODE:
case NS_NODE:
case VRF_NODE:
case ZEBRA_NODE:
@@ -1659,6 +1676,15 @@ DEFUNSH(VTYSH_INTERFACE, vtysh_interface, vtysh_interface_cmd,
return CMD_SUCCESS;
}
+DEFUNSH(VTYSH_ZEBRA, vtysh_pseudowire, vtysh_pseudowire_cmd,
+ "pseudowire IFNAME",
+ "Static pseudowire configuration\n"
+ "Pseudowire name\n")
+{
+ vty->node = PW_NODE;
+ return CMD_SUCCESS;
+}
+
/* TODO Implement "no interface command in isisd. */
DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D
| VTYSH_EIGRPD,
@@ -2909,6 +2935,7 @@ void vtysh_init_vty(void)
install_node(&bgp_node, NULL);
install_node(&rip_node, NULL);
install_node(&interface_node, NULL);
+ install_node(&pw_node, NULL);
install_node(&link_params_node, NULL);
install_node(&ns_node, NULL);
install_node(&vrf_node, NULL);
@@ -3081,6 +3108,10 @@ void vtysh_init_vty(void)
install_element(LINK_PARAMS_NODE, &vtysh_exit_interface_cmd);
install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd);
+ install_element(PW_NODE, &vtysh_end_all_cmd);
+ install_element(PW_NODE, &vtysh_exit_interface_cmd);
+ install_element(PW_NODE, &vtysh_quit_interface_cmd);
+
install_element(NS_NODE, &vtysh_end_all_cmd);
install_element(CONFIG_NODE, &vtysh_ns_cmd);
@@ -3156,6 +3187,7 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &vtysh_interface_cmd);
install_element(CONFIG_NODE, &vtysh_no_interface_cmd);
install_element(CONFIG_NODE, &vtysh_no_interface_vrf_cmd);
+ install_element(CONFIG_NODE, &vtysh_pseudowire_cmd);
install_element(INTERFACE_NODE, &vtysh_link_params_cmd);
install_element(ENABLE_NODE, &vtysh_show_running_config_cmd);
install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd);
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index bef4b82d3f..b0866ec7f3 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -47,7 +47,7 @@ DECLARE_MGROUP(MVTYSH)
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD|VTYSH_EIGRPD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD
#define VTYSH_NS VTYSH_ZEBRA
-#define VTYSH_VRF VTYSH_ZEBRA
+#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD
/* vtysh local configuration file. */
#define VTYSH_DEFAULT_CONFIG "vtysh.conf"
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 74509d1ec8..43aff0e3a5 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -181,6 +181,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
default:
if (strncmp(line, "interface", strlen("interface")) == 0)
config = config_get(INTERFACE_NODE, line);
+ else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
+ config = config_get(PW_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)
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index 1aa25b41d0..6adb25f322 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -684,9 +684,11 @@ static void daemon_send_ready(void)
fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w");
fclose(fp);
+#if defined HAVE_SYSTEMD
zlog_notice(
"Watchfrr: Notifying Systemd we are up and running");
systemd_send_started(master, 0);
+#endif
sent = 1;
}
}
diff --git a/zebra/.gitignore b/zebra/.gitignore
index d0a7528539..7a1321e546 100644
--- a/zebra/.gitignore
+++ b/zebra/.gitignore
@@ -1,4 +1,4 @@
-Makefile
+!Makefile
Makefile.in
*.o
zebra
diff --git a/zebra/Makefile b/zebra/Makefile
new file mode 100644
index 0000000000..625a7168eb
--- /dev/null
+++ b/zebra/Makefile
@@ -0,0 +1,10 @@
+all: ALWAYS
+ @$(MAKE) -s -C .. zebra/zebra
+%: ALWAYS
+ @$(MAKE) -s -C .. zebra/$@
+
+Makefile:
+ #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/zebra/Makefile.am b/zebra/Makefile.am
deleted file mode 100644
index 67031ea361..0000000000
--- a/zebra/Makefile.am
+++ /dev/null
@@ -1,96 +0,0 @@
-include ../common.am
-
-## Process this file with automake to produce Makefile.in.
-
-AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
-INSTALL_SDATA=@INSTALL@ -m 600
-
-LIBCAP = @LIBCAP@
-
-ipforward = @IPFORWARD@
-if_method = @IF_METHOD@
-rt_method = @RT_METHOD@
-rtread_method = @RTREAD_METHOD@
-kernel_method = @KERNEL_METHOD@
-ioctl_method = @IOCTL_METHOD@
-mpls_method = @MPLS_METHOD@
-
-otherobj = $(ioctl_method) $(ipforward) $(if_method) \
- $(rt_method) $(rtread_method) $(kernel_method) $(mpls_method)
-
-AM_CFLAGS = $(WERROR)
-
-sbin_PROGRAMS = zebra
-module_LTLIBRARIES =
-
-zebra_SOURCES = \
- zebra_memory.c \
- zserv.c main.c interface.c connected.c zebra_rib.c zebra_routemap.c \
- redistribute.c debug.c rtadv.c zebra_vty.c \
- irdp_main.c irdp_interface.c irdp_packet.c router-id.c \
- zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
- zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
- zebra_mroute.c \
- label_manager.c \
- zebra_l2.c \
- zebra_vxlan.c \
- # end
-
-zebra_vty.o: zebra_vty_clippy.c
-
-noinst_HEADERS = \
- zebra_memory.h \
- 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_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_static.h zebra_mpls.h \
- kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h \
- zebra_l2.h zebra_vxlan_private.h zebra_vxlan.h
-
-zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP)
-
-zebra_DEPENDENCIES = $(otherobj)
-
-if SNMP
-module_LTLIBRARIES += zebra_snmp.la
-endif
-zebra_snmp_la_SOURCES = zebra_snmp.c
-zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
-zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
-zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la
-
-if FPM
-module_LTLIBRARIES += zebra_fpm.la
-endif
-zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
-zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS)
-zebra_fpm_la_SOURCES = zebra_fpm.c
-if HAVE_NETLINK
-zebra_fpm_la_SOURCES += zebra_fpm_netlink.c
-endif
-if HAVE_PROTOBUF
-zebra_fpm_la_SOURCES += zebra_fpm_protobuf.c
-if DEV_BUILD
-zebra_fpm_la_SOURCES += zebra_fpm_dt.c
-endif
-endif
-
-
-EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \
- if_sysctl.c ipforward_proc.c \
- ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \
- rt_socket.c rtread_netlink.c rtread_sysctl.c \
- rtread_getmsg.c kernel_socket.c kernel_netlink.c \
- ioctl.c ioctl_solaris.c \
- zebra_mpls_netlink.c zebra_mpls_openbsd.c zebra_mpls_null.c \
- GNOME-SMI GNOME-PRODUCT-ZEBRA-MIB
-
-client : client_main.o ../lib/libfrr.la
- $(CC) -g -o client client_main.o ../liblzebra.la $(LIBS) $(LIB_IPV6)
-
-frrconfdir = $(sysconfdir)
-
-examplesdir = $(exampledir)
-dist_examples_DATA = zebra.conf.sample
diff --git a/zebra/debug.c b/zebra/debug.c
index 6aedea1e39..25f47bc51a 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -32,6 +32,7 @@ unsigned long zebra_debug_fpm;
unsigned long zebra_debug_nht;
unsigned long zebra_debug_mpls;
unsigned long zebra_debug_vxlan;
+unsigned long zebra_debug_pw;
DEFUN (show_debugging_zebra,
show_debugging_zebra_cmd,
@@ -82,6 +83,8 @@ DEFUN (show_debugging_zebra,
vty_out(vty, " Zebra next-hop tracking debugging is on\n");
if (IS_ZEBRA_DEBUG_MPLS)
vty_out(vty, " Zebra MPLS debugging is on\n");
+ if (IS_ZEBRA_DEBUG_PW)
+ vty_out(vty, " Zebra pseudowire debugging is on\n");
return CMD_SUCCESS;
}
@@ -130,6 +133,21 @@ DEFUN (debug_zebra_vxlan,
return CMD_WARNING;
}
+DEFUN (debug_zebra_pw,
+ debug_zebra_pw_cmd,
+ "[no] debug zebra pseudowires",
+ "Negate a command or set its defaults\n"
+ DEBUG_STR
+ "Zebra configuration\n"
+ "Debug option set for zebra pseudowires\n")
+{
+ if (strmatch(argv[0]->text, "no"))
+ UNSET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW);
+ else
+ SET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW);
+ return CMD_WARNING;
+}
+
DEFUN (debug_zebra_packet,
debug_zebra_packet_cmd,
"debug zebra packet [<recv|send>] [detail]",
@@ -419,6 +437,10 @@ static int config_write_debug(struct vty *vty)
vty_out(vty, "debug zebra vxlan\n");
write++;
}
+ if (IS_ZEBRA_DEBUG_PW) {
+ vty_out(vty, "debug zebra pseudowires\n");
+ write++;
+ }
return write;
}
@@ -431,6 +453,7 @@ void zebra_debug_init(void)
zebra_debug_fpm = 0;
zebra_debug_mpls = 0;
zebra_debug_vxlan = 0;
+ zebra_debug_pw = 0;
install_node(&debug_node, config_write_debug);
@@ -440,6 +463,7 @@ void zebra_debug_init(void)
install_element(ENABLE_NODE, &debug_zebra_nht_cmd);
install_element(ENABLE_NODE, &debug_zebra_mpls_cmd);
install_element(ENABLE_NODE, &debug_zebra_vxlan_cmd);
+ install_element(ENABLE_NODE, &debug_zebra_pw_cmd);
install_element(ENABLE_NODE, &debug_zebra_packet_cmd);
install_element(ENABLE_NODE, &debug_zebra_kernel_cmd);
install_element(ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd);
@@ -459,6 +483,7 @@ void zebra_debug_init(void)
install_element(CONFIG_NODE, &debug_zebra_nht_cmd);
install_element(CONFIG_NODE, &debug_zebra_mpls_cmd);
install_element(CONFIG_NODE, &debug_zebra_vxlan_cmd);
+ install_element(CONFIG_NODE, &debug_zebra_pw_cmd);
install_element(CONFIG_NODE, &debug_zebra_packet_cmd);
install_element(CONFIG_NODE, &debug_zebra_kernel_cmd);
install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd);
diff --git a/zebra/debug.h b/zebra/debug.h
index b52bb7d0e9..987f9d0125 100644
--- a/zebra/debug.h
+++ b/zebra/debug.h
@@ -44,6 +44,8 @@
#define ZEBRA_DEBUG_VXLAN 0x01
+#define ZEBRA_DEBUG_PW 0x01
+
/* Debug related macro. */
#define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT)
@@ -66,6 +68,7 @@
#define IS_ZEBRA_DEBUG_NHT (zebra_debug_nht & ZEBRA_DEBUG_NHT)
#define IS_ZEBRA_DEBUG_MPLS (zebra_debug_mpls & ZEBRA_DEBUG_MPLS)
#define IS_ZEBRA_DEBUG_VXLAN (zebra_debug_vxlan & ZEBRA_DEBUG_VXLAN)
+#define IS_ZEBRA_DEBUG_PW (zebra_debug_pw & ZEBRA_DEBUG_PW)
extern unsigned long zebra_debug_event;
extern unsigned long zebra_debug_packet;
@@ -75,6 +78,7 @@ extern unsigned long zebra_debug_fpm;
extern unsigned long zebra_debug_nht;
extern unsigned long zebra_debug_mpls;
extern unsigned long zebra_debug_vxlan;
+extern unsigned long zebra_debug_pw;
extern void zebra_debug_init(void);
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index 2d5d604a8b..a65fcb2b8c 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef OPEN_BSD
+
#include "if.h"
#include "sockunion.h"
#include "prefix.h"
@@ -328,3 +330,5 @@ void interface_list(struct zebra_ns *zns)
ifaddr_proc_ipv6();
#endif /* HAVE_PROC_NET_IF_INET6 */
}
+
+#endif /* OPEN_BSD */
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index fce36ebc1d..3d53194593 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef SUNOS_5
+
#include "if.h"
#include "sockunion.h"
#include "prefix.h"
@@ -358,3 +360,5 @@ struct connected *if_lookup_linklocal(struct interface *ifp)
return NULL;
}
+
+#endif /* SUNOS_5 */
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index acec2db526..a46657dd2e 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+
/* The following definition is to workaround an issue in the Linux kernel
* header files with redefinition of 'struct in6_addr' in both
* netinet/in.h and linux/in6.h.
@@ -768,6 +770,33 @@ int interface_lookup_netlink(struct zebra_ns *zns)
return 0;
}
+int kernel_interface_set_master(struct interface *master,
+ struct interface *slave)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifa;
+ char buf[NL_PKT_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof req);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_SETLINK;
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+
+ req.ifa.ifi_index = slave->ifindex;
+
+ addattr_l(&req.n, sizeof req, IFLA_MASTER, &master->ifindex, 4);
+ addattr_l(&req.n, sizeof req, IFLA_LINK, &slave->ifindex, 4);
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
+}
+
/* Interface address modification. */
static int netlink_address(int cmd, int family, struct interface *ifp,
struct connected *ifc)
@@ -1218,3 +1247,5 @@ void interface_list(struct zebra_ns *zns)
{
interface_lookup_netlink(zns);
}
+
+#endif /* GNU_LINUX */
diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c
index 99b0f9d942..39b7204e8e 100644
--- a/zebra/if_sysctl.c
+++ b/zebra/if_sysctl.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#if !defined(GNU_LINUX) && !defined(OPEN_BSD) && !defined(SUNOS_5)
+
#include "if.h"
#include "sockunion.h"
#include "prefix.h"
@@ -134,3 +136,5 @@ void interface_list(struct zebra_ns *zns)
/* Free sysctl buffer. */
XFREE(MTYPE_TMP, ref);
}
+
+#endif /* !defined(GNU_LINUX) && !defined(OPEN_BSD) && !defined(SUNOS_5) */
diff --git a/zebra/interface.c b/zebra/interface.c
index 03ddf8d386..c4d0363994 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -48,6 +48,7 @@
#include "zebra/rt_netlink.h"
#include "zebra/interface.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_static.h"
#define ZEBRA_PTM_SUPPORT
@@ -119,8 +120,6 @@ static int if_zebra_new_hook(struct interface *ifp)
route_table_init_with_delegate(&zebra_if_table_delegate);
ifp->info = zebra_if;
-
- zebra_vrf_static_route_interface_fixup(ifp);
return 0;
}
@@ -510,6 +509,8 @@ void if_add_update(struct interface *ifp)
zlog_debug(
"interface %s vrf %u index %d becomes active.",
ifp->name, ifp->vrf_id, ifp->ifindex);
+
+ static_ifindex_update(ifp, true);
} else {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s vrf %u index %d is added.",
@@ -675,6 +676,8 @@ void if_delete_update(struct interface *ifp)
zlog_debug("interface %s vrf %u index %d is now inactive.",
ifp->name, ifp->vrf_id, ifp->ifindex);
+ static_ifindex_update(ifp, false);
+
/* Delete connected routes from the kernel. */
if_delete_connected(ifp);
@@ -714,6 +717,8 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
old_vrf_id = ifp->vrf_id;
+ static_ifindex_update(ifp, false);
+
/* Uninstall connected routes. */
if_uninstall_connected(ifp);
@@ -737,6 +742,8 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
/* Install connected routes (in new VRF). */
if_install_connected(ifp);
+ static_ifindex_update(ifp, true);
+
/* Due to connected route change, schedule RIB processing for both old
* and new VRF.
*/
@@ -745,8 +752,6 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
ifp->vrf_id, ifp->name);
rib_update(old_vrf_id, RIB_UPDATE_IF_CHANGE);
rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
-
- zebra_vrf_static_route_interface_fixup(ifp);
}
static void ipv6_ll_address_to_mac(struct in6_addr *address, u_char *mac)
@@ -859,8 +864,6 @@ void if_up(struct interface *ifp)
ifp->vrf_id, ifp->name);
rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
- zebra_vrf_static_route_interface_fixup(ifp);
-
/* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
* are checked to see if (remote) neighbor entries need to be installed
* on them for ARP suppression.
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 72d98943ef..835f1f4934 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -33,6 +33,8 @@
#include "zebra/rt.h"
#include "zebra/interface.h"
+#ifndef SUNOS_5
+
#ifdef HAVE_BSD_LINK_DETECT
#include <net/if_media.h>
#endif /* HAVE_BSD_LINK_DETECT*/
@@ -563,3 +565,5 @@ int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
#endif /* HAVE_STRUCT_IN6_ALIASREQ */
#endif /* LINUX_IPV6 */
+
+#endif /* !SUNOS_5 */
diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c
index df1554ae6f..e8b65925f8 100644
--- a/zebra/ioctl_solaris.c
+++ b/zebra/ioctl_solaris.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef SUNOS_5
+
#include "linklist.h"
#include "if.h"
#include "prefix.h"
@@ -398,3 +400,5 @@ int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
return 0;
}
+
+#endif /* SUNOS_5 */
diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c
index c3dcdda55f..2834eeeb9c 100644
--- a/zebra/ipforward_proc.c
+++ b/zebra/ipforward_proc.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+
#include "log.h"
#include "privs.h"
@@ -193,3 +195,5 @@ int ipforward_ipv6_off(void)
return ipforward_ipv6();
}
+
+#endif /* GNU_LINUX */
diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c
index 0d6b7dac03..123cf1bd08 100644
--- a/zebra/ipforward_solaris.c
+++ b/zebra/ipforward_solaris.c
@@ -20,6 +20,9 @@
*/
#include <zebra.h>
+
+#ifdef SUNOS_5
+
#include "log.h"
#include "prefix.h"
@@ -153,3 +156,5 @@ int ipforward_ipv6_off(void)
(void)solaris_nd_set("ip6_forwarding", 0);
return ipforward_ipv6();
}
+
+#endif /* SUNOS_5 */
diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c
index 00be92bb6d..36212a0132 100644
--- a/zebra/ipforward_sysctl.c
+++ b/zebra/ipforward_sysctl.c
@@ -19,6 +19,9 @@
*/
#include <zebra.h>
+
+#if !defined(GNU_LINUX) && !defined(SUNOS_5)
+
#include "privs.h"
#include "zebra/ipforward.h"
@@ -147,3 +150,5 @@ int ipforward_ipv6_off(void)
zlog_err("Can't lower privileges");
return ip6forwarding;
}
+
+#endif /* !defined(GNU_LINUX) && !defined(SUNOS_5) */
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 7fc2d61332..015e11b3a5 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -20,6 +20,8 @@
#include <zebra.h>
+#ifdef HAVE_NETLINK
+
#include "linklist.h"
#include "if.h"
#include "log.h"
@@ -260,8 +262,9 @@ static int netlink_information_fetch(struct sockaddr_nl *snl,
return netlink_neigh_change(snl, h, ns_id);
break;
default:
- zlog_warn("Unknown netlink nlmsg_type %d vrf %u\n",
- h->nlmsg_type, ns_id);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Unknown netlink nlmsg_type %d vrf %u\n",
+ h->nlmsg_type, ns_id);
break;
}
return 0;
@@ -826,3 +829,5 @@ void kernel_terminate(struct zebra_ns *zns)
zns->netlink_cmd.sock = -1;
}
}
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 4b63a3eb04..5ca6a488c3 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -19,6 +19,9 @@
*/
#include <zebra.h>
+
+#ifndef HAVE_NETLINK
+
#include <net/if_types.h>
#ifdef __OpenBSD__
#include <netmpls/mpls.h>
@@ -624,6 +627,7 @@ int ifm_read(struct if_msghdr *ifm)
#ifdef HAVE_NET_RT_IFLIST
ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */
+ ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: interface %s index %d", __func__, ifp->name,
@@ -1376,3 +1380,5 @@ void kernel_terminate(struct zebra_ns *zns)
{
return;
}
+
+#endif /* !HAVE_NETLINK */
diff --git a/zebra/main.c b/zebra/main.c
index 27a6f3e027..f0bdafa353 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -299,6 +299,7 @@ int main(int argc, char **argv)
zebra_mpls_init();
zebra_mpls_vty_init();
+ zebra_pw_vty_init();
/* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
diff --git a/zebra/rib.h b/zebra/rib.h
index eca2be5eee..de941bcbbe 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -89,6 +89,7 @@ struct route_entry {
#define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2
#define ROUTE_ENTRY_CHANGED 0x4
#define ROUTE_ENTRY_SELECTED_FIB 0x8
+#define ROUTE_ENTRY_LABELS_CHANGED 0x10
/* Nexthop information. */
u_char nexthop_num;
diff --git a/zebra/rt.h b/zebra/rt.h
index 81dffdf441..f5f0fa195b 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -36,13 +36,14 @@ extern int kernel_route_rib(struct prefix *, struct prefix *,
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);
-
+extern int kernel_interface_set_master(struct interface *master,
+ struct interface *slave);
extern int kernel_add_lsp(zebra_lsp_t *);
extern int kernel_upd_lsp(zebra_lsp_t *);
extern int kernel_del_lsp(zebra_lsp_t *);
extern int mpls_kernel_init(void);
-extern int kernel_get_ipmr_sg_stats(void *mroute);
+extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index c02774ca64..192fffd29c 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -19,6 +19,9 @@
*/
#include <zebra.h>
+
+#ifdef HAVE_NETLINK
+
#include <net/if_arp.h>
/* Hack for GNU libc version 2. */
@@ -503,6 +506,7 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
char gbuf[40];
char oif_list[256] = "\0";
vrf_id_t vrf = ns_id;
+ int table;
if (mroute)
m = mroute;
@@ -518,6 +522,13 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
memset(tb, 0, sizeof tb);
netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
+ if (tb[RTA_TABLE])
+ table = *(int *)RTA_DATA(tb[RTA_TABLE]);
+ else
+ table = rtm->rtm_table;
+
+ vrf = vrf_lookup_by_table(table);
+
if (tb[RTA_IIF])
iif = *(int *)RTA_DATA(tb[RTA_IIF]);
@@ -558,10 +569,12 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
sprintf(temp, "%s ", ifp->name);
strcat(oif_list, temp);
}
+ struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf);
ifp = if_lookup_by_index(iif, vrf);
- zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
- nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
- ifp->name, oif_list, m->lastused);
+ zlog_debug(
+ "MCAST VRF: %s(%d) %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
+ zvrf->vrf->name, vrf, nl_msg_type_to_str(h->nlmsg_type),
+ sbuf, gbuf, ifp->name, oif_list, m->lastused);
}
return 0;
}
@@ -1503,7 +1516,7 @@ skip:
0);
}
-int kernel_get_ipmr_sg_stats(void *in)
+int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
{
int suc = 0;
struct mcast_route_data *mr = (struct mcast_route_data *)in;
@@ -1523,13 +1536,14 @@ int kernel_get_ipmr_sg_stats(void *in)
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
- req.ndm.ndm_family = AF_INET;
+ req.ndm.ndm_family = RTNL_FAMILY_IPMR;
req.n.nlmsg_type = RTM_GETROUTE;
addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
+ addattr_l(&req.n, sizeof(req), RTA_TABLE, &zvrf->table_id, 4);
suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
&zns->netlink_cmd, zns, 0);
@@ -1690,17 +1704,17 @@ static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
return 0;
}
- if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
+ if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
zlog_warn(
- "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
+ "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
- RTA_PAYLOAD(tb[NDA_LLADDR]));
+ (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
return 0;
}
- memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
+ memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
vid_present = 1;
@@ -2019,18 +2033,18 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
if (h->nlmsg_type == RTM_NEWNEIGH) {
if (tb[NDA_LLADDR]) {
- if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
+ if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
zlog_warn(
- "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
+ "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
- RTA_PAYLOAD(tb[NDA_LLADDR]));
+ (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
return 0;
}
mac_present = 1;
- memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
+ memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
}
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
@@ -2442,3 +2456,5 @@ void clear_nhlfe_installed(zebra_lsp_t *lsp)
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
}
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 827d398704..4e4d726b46 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -20,6 +20,9 @@
*/
#include <zebra.h>
+
+#ifndef HAVE_NETLINK
+
#ifdef __OpenBSD__
#include <netmpls/mpls.h>
#endif
@@ -406,7 +409,7 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
return 0;
}
-extern int kernel_get_ipmr_sg_stats(void *mroute)
+extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute)
{
return 0;
}
@@ -443,3 +446,11 @@ int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{
return 0;
}
+
+extern int kernel_interface_set_master(struct interface *master,
+ struct interface *slave)
+{
+ return 0;
+}
+
+#endif /* !HAVE_NETLINK */
diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c
index 5384231f88..1bba003a0a 100644
--- a/zebra/rtread_getmsg.c
+++ b/zebra/rtread_getmsg.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef SUNOS_5
+
#include "prefix.h"
#include "log.h"
#include "if.h"
@@ -258,3 +260,5 @@ void neigh_read(struct zebra_ns *zns)
void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
}
+
+#endif /* SUNOS_5 */
diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c
index 304f441367..f38cba65e7 100644
--- a/zebra/rtread_netlink.c
+++ b/zebra/rtread_netlink.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+
#include "vty.h"
#include "zebra/zserv.h"
#include "zebra/rt_netlink.h"
@@ -50,3 +52,5 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
netlink_neigh_read_for_vlan(zns, vlan_if);
}
+
+#endif /* GNU_LINUX */
diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c
index d3e2eb6fac..53ed0e7906 100644
--- a/zebra/rtread_sysctl.c
+++ b/zebra/rtread_sysctl.c
@@ -21,6 +21,8 @@
#include <zebra.h>
+#if !defined(GNU_LINUX) && !defined(SUNOS_5)
+
#include "memory.h"
#include "zebra_memory.h"
#include "log.h"
@@ -90,3 +92,5 @@ void neigh_read(struct zebra_ns *zns)
void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
}
+
+#endif /* !defined(GNU_LINUX) && !defined(SUNOS_5) */
diff --git a/zebra/subdir.am b/zebra/subdir.am
new file mode 100644
index 0000000000..0391cab9fd
--- /dev/null
+++ b/zebra/subdir.am
@@ -0,0 +1,133 @@
+#
+# zebra
+#
+
+if ZEBRA
+sbin_PROGRAMS += zebra/zebra
+dist_examples_DATA += zebra/zebra.conf.sample
+
+if SNMP
+module_LTLIBRARIES += zebra/zebra_snmp.la
+endif
+if FPM
+module_LTLIBRARIES += zebra/zebra_fpm.la
+endif
+
+## endif ZEBRA
+endif
+
+zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP)
+zebra_zebra_SOURCES = \
+ zebra/connected.c \
+ zebra/debug.c \
+ zebra/if_ioctl.c \
+ zebra/if_ioctl_solaris.c \
+ zebra/if_netlink.c \
+ zebra/if_sysctl.c \
+ zebra/interface.c \
+ zebra/ioctl.c \
+ zebra/ioctl_solaris.c \
+ zebra/ipforward_proc.c \
+ zebra/ipforward_solaris.c \
+ zebra/ipforward_sysctl.c \
+ zebra/irdp_interface.c \
+ zebra/irdp_main.c \
+ zebra/irdp_packet.c \
+ zebra/kernel_netlink.c \
+ zebra/kernel_socket.c \
+ zebra/label_manager.c \
+ zebra/main.c \
+ zebra/redistribute.c \
+ zebra/router-id.c \
+ zebra/rt_netlink.c \
+ zebra/rt_socket.c \
+ zebra/rtadv.c \
+ zebra/rtread_getmsg.c \
+ zebra/rtread_netlink.c \
+ zebra/rtread_sysctl.c \
+ zebra/zebra_l2.c \
+ zebra/zebra_memory.c \
+ zebra/zebra_mpls.c \
+ zebra/zebra_mpls_netlink.c \
+ zebra/zebra_mpls_openbsd.c \
+ zebra/zebra_mpls_null.c \
+ zebra/zebra_mpls_vty.c \
+ zebra/zebra_mroute.c \
+ zebra/zebra_ns.c \
+ zebra/zebra_ptm.c \
+ zebra/zebra_ptm_redistribute.c \
+ zebra/zebra_pw.c \
+ zebra/zebra_rib.c \
+ zebra/zebra_rnh.c \
+ zebra/zebra_routemap.c \
+ zebra/zebra_static.c \
+ zebra/zebra_vrf.c \
+ zebra/zebra_vty.c \
+ zebra/zebra_vxlan.c \
+ zebra/zserv.c \
+ # end
+
+zebra/zebra_vty_clippy.c: $(CLIPPY_DEPS)
+zebra/zebra_vty.$(OBJEXT): zebra/zebra_vty_clippy.c
+
+noinst_HEADERS += \
+ zebra/connected.h \
+ zebra/debug.h \
+ zebra/if_netlink.h \
+ zebra/interface.h \
+ zebra/ioctl.h \
+ zebra/ioctl_solaris.h \
+ zebra/ipforward.h \
+ zebra/irdp.h \
+ zebra/kernel_netlink.h \
+ zebra/kernel_socket.h \
+ zebra/label_manager.h \
+ zebra/redistribute.h \
+ zebra/rib.h \
+ zebra/router-id.h \
+ zebra/rt.h \
+ zebra/rt_netlink.h \
+ zebra/rtadv.h \
+ zebra/zebra_fpm_private.h \
+ zebra/zebra_l2.h \
+ zebra/zebra_memory.h \
+ zebra/zebra_mpls.h \
+ zebra/zebra_mroute.h \
+ zebra/zebra_ns.h \
+ zebra/zebra_ptm.h \
+ zebra/zebra_ptm_redistribute.h \
+ zebra/zebra_pw.h \
+ zebra/zebra_rnh.h \
+ zebra/zebra_routemap.h \
+ zebra/zebra_static.h \
+ zebra/zebra_vrf.h \
+ zebra/zebra_vxlan.h \
+ zebra/zebra_vxlan_private.h \
+ zebra/zserv.h \
+ # end
+
+zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c
+zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
+zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+zebra_zebra_snmp_la_LIBADD = lib/libfrrsnmp.la
+
+zebra_zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+zebra_zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS)
+zebra_zebra_fpm_la_SOURCES = zebra/zebra_fpm.c
+zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_netlink.c
+if HAVE_PROTOBUF
+zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_protobuf.c
+if DEV_BUILD
+zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
+endif
+endif
+
+EXTRA_DIST += \
+ zebra/GNOME-SMI \
+ zebra/GNOME-PRODUCT-ZEBRA-MIB \
+ # end
+
+# -- unmaintained --
+# noinst_PROGRAMS += zebra/client
+# zebra_client_SOURCES = zebra/client_main.c
+# zebra_client_LDADD = lib/libfrr.la
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 862049cb85..28f7956639 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -24,6 +24,8 @@
#include <zebra.h>
+#ifdef HAVE_NETLINK
+
#include "log.h"
#include "rib.h"
#include "vty.h"
@@ -457,3 +459,5 @@ int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re,
return netlink_route_info_encode(ri, in_buf, in_buf_len);
}
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index e44e5d2e6b..d1ab2dbb85 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2222,7 +2222,7 @@ found:
return 0;
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
- SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED);
+ SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
rib_queue_add(rn);
return 0;
@@ -2405,7 +2405,7 @@ void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi)
nexthop_del_labels(nexthop);
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
SET_FLAG(re->status,
- ROUTE_ENTRY_NEXTHOPS_CHANGED);
+ ROUTE_ENTRY_LABELS_CHANGED);
update = 1;
}
diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c
index c5053563b9..8b30783a9a 100644
--- a/zebra/zebra_mpls_netlink.c
+++ b/zebra/zebra_mpls_netlink.c
@@ -19,6 +19,9 @@
*/
#include <zebra.h>
+
+#ifdef HAVE_NETLINK
+
#include "zebra/rt.h"
#include "zebra/rt_netlink.h"
#include "zebra/zebra_mpls.h"
@@ -105,3 +108,5 @@ int mpls_kernel_init(void)
return 0;
};
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c
index a9da5c29c6..e4dc570fd9 100644
--- a/zebra/zebra_mpls_null.c
+++ b/zebra/zebra_mpls_null.c
@@ -22,6 +22,8 @@
#include "zebra/rt.h"
#include "zebra/zebra_mpls.h"
+#if !defined(HAVE_NETLINK) && !defined(OPEN_BSD)
+
int kernel_add_lsp(zebra_lsp_t *lsp)
{
return 0;
@@ -38,3 +40,5 @@ int mpls_kernel_init(void)
{
return -1;
};
+
+#endif /* !defined(HAVE_NETLINK) && !defined(OPEN_BSD) */
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index fc1df9227f..119cd5b700 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -19,6 +19,9 @@
*/
#include <zebra.h>
+
+#ifdef OPEN_BSD
+
#include <netmpls/mpls.h>
#include "zebra/rt.h"
#include "zebra/zebra_mpls.h"
@@ -34,6 +37,7 @@ extern struct zebra_privs_t zserv_privs;
struct {
u_int32_t rtseq;
int fd;
+ int ioctl_fd;
} kr_state;
static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
@@ -327,6 +331,85 @@ int kernel_del_lsp(zebra_lsp_t *lsp)
return ret;
}
+static int kmpw_install(struct zebra_pw *pw)
+{
+ struct ifreq ifr;
+ struct ifmpwreq imr;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
+
+ memset(&imr, 0, sizeof(imr));
+ switch (pw->type) {
+ case PW_TYPE_ETHERNET:
+ imr.imr_type = IMR_TYPE_ETHERNET;
+ break;
+ case PW_TYPE_ETHERNET_TAGGED:
+ imr.imr_type = IMR_TYPE_ETHERNET_TAGGED;
+ break;
+ default:
+ zlog_err("%s: unhandled pseudowire type (%#X)", __func__,
+ pw->type);
+ return -1;
+ }
+
+ if (pw->flags & F_PSEUDOWIRE_CWORD)
+ imr.imr_flags |= IMR_FLAG_CONTROLWORD;
+
+ /* pseudowire nexthop */
+ memset(&ss, 0, sizeof(ss));
+ switch (pw->af) {
+ case AF_INET:
+ sa_in->sin_family = AF_INET;
+ sa_in->sin_len = sizeof(struct sockaddr_in);
+ sa_in->sin_addr = pw->nexthop.ipv4;
+ break;
+ case AF_INET6:
+ sa_in6->sin6_family = AF_INET6;
+ sa_in6->sin6_len = sizeof(struct sockaddr_in6);
+ sa_in6->sin6_addr = pw->nexthop.ipv6;
+ break;
+ default:
+ zlog_err("%s: unhandled pseudowire address-family (%u)",
+ __func__, pw->af);
+ return -1;
+ }
+ memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss,
+ sizeof(imr.imr_nexthop));
+
+ /* pseudowire local/remote labels */
+ imr.imr_lshim.shim_label = pw->local_label;
+ imr.imr_rshim.shim_label = pw->remote_label;
+
+ /* ioctl */
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&imr;
+ if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
+ zlog_err("ioctl SIOCSETMPWCFG: %s", safe_strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int kmpw_uninstall(struct zebra_pw *pw)
+{
+ struct ifreq ifr;
+ struct ifmpwreq imr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ memset(&imr, 0, sizeof(imr));
+ strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&imr;
+ if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
+ zlog_err("ioctl SIOCSETMPWCFG: %s", safe_strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
#define MAX_RTSOCK_BUF 128 * 1024
int mpls_kernel_init(void)
{
@@ -338,6 +421,12 @@ int mpls_kernel_init(void)
return -1;
}
+ if ((kr_state.ioctl_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0))
+ == -1) {
+ zlog_warn("%s: ioctl socket", __func__);
+ return -1;
+ }
+
/* grow receive buffer, don't wanna miss messages */
optlen = sizeof(default_rcvbuf);
if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
@@ -356,5 +445,11 @@ int mpls_kernel_init(void)
kr_state.rtseq = 1;
+ /* register hook to install/uninstall pseudowires */
+ hook_register(pw_install, kmpw_install);
+ hook_register(pw_uninstall, kmpw_uninstall);
+
return 0;
}
+
+#endif /* OPEN_BSD */
diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c
index c00498171d..c4d674df23 100644
--- a/zebra/zebra_mroute.c
+++ b/zebra/zebra_mroute.c
@@ -30,6 +30,7 @@
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_mroute.h"
#include "zebra/rt.h"
+#include "zebra/debug.h"
int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length,
struct zebra_vrf *zvrf)
@@ -38,18 +39,22 @@ int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length,
struct stream *s;
int suc;
- char sbuf[40];
- char gbuf[40];
-
memset(&mroute, 0, sizeof(mroute));
stream_get(&mroute.sg.src, client->ibuf, 4);
stream_get(&mroute.sg.grp, client->ibuf, 4);
mroute.ifindex = stream_getl(client->ibuf);
- strcpy(sbuf, inet_ntoa(mroute.sg.src));
- strcpy(gbuf, inet_ntoa(mroute.sg.grp));
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char sbuf[40];
+ char gbuf[40];
+
+ strcpy(sbuf, inet_ntoa(mroute.sg.src));
+ strcpy(gbuf, inet_ntoa(mroute.sg.grp));
+
+ zlog_debug("Asking for (%s,%s) mroute information", sbuf, gbuf);
+ }
- suc = kernel_get_ipmr_sg_stats(&mroute);
+ suc = kernel_get_ipmr_sg_stats(zvrf, &mroute);
s = client->obuf;
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
new file mode 100644
index 0000000000..4f1d8b0915
--- /dev/null
+++ b/zebra/zebra_pw.c
@@ -0,0 +1,533 @@
+/* Zebra PW code
+ * Copyright (C) 2016 Volta Networks, Inc.
+ *
+ * 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
+ */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+#include "thread.h"
+#include "command.h"
+#include "vrf.h"
+
+#include "zebra/debug.h"
+#include "zebra/rib.h"
+#include "zebra/zserv.h"
+#include "zebra/zebra_rnh.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_pw.h"
+
+DEFINE_MTYPE_STATIC(LIB, PW, "Pseudowire")
+
+DEFINE_QOBJ_TYPE(zebra_pw)
+
+DEFINE_HOOK(pw_install, (struct zebra_pw * pw), (pw))
+DEFINE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
+
+#define MPLS_NO_LABEL MPLS_INVALID_LABEL
+
+extern struct zebra_t zebrad;
+
+static int zebra_pw_enabled(struct zebra_pw *);
+static void zebra_pw_install(struct zebra_pw *);
+static void zebra_pw_uninstall(struct zebra_pw *);
+static int zebra_pw_install_retry(struct thread *);
+static int zebra_pw_check_reachability(struct zebra_pw *);
+static void zebra_pw_update_status(struct zebra_pw *, int);
+
+static inline int zebra_pw_compare(const struct zebra_pw *a,
+ const struct zebra_pw *b)
+{
+ return (strcmp(a->ifname, b->ifname));
+}
+
+RB_GENERATE(zebra_pw_head, zebra_pw, pw_entry, zebra_pw_compare)
+RB_GENERATE(zebra_static_pw_head, zebra_pw, static_pw_entry, zebra_pw_compare)
+
+struct zebra_pw *zebra_pw_add(struct zebra_vrf *zvrf, const char *ifname,
+ uint8_t protocol, struct zserv *client)
+{
+ struct zebra_pw *pw;
+
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_debug("%u: adding pseudowire %s protocol %s",
+ zvrf_id(zvrf), ifname, zebra_route_string(protocol));
+
+ pw = XCALLOC(MTYPE_PW, sizeof(*pw));
+ strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
+ pw->protocol = protocol;
+ pw->vrf_id = zvrf_id(zvrf);
+ pw->client = client;
+ pw->status = PW_STATUS_UP;
+ pw->local_label = MPLS_NO_LABEL;
+ pw->remote_label = MPLS_NO_LABEL;
+ pw->flags = F_PSEUDOWIRE_CWORD;
+
+ RB_INSERT(zebra_pw_head, &zvrf->pseudowires, pw);
+ if (pw->protocol == ZEBRA_ROUTE_STATIC) {
+ RB_INSERT(zebra_static_pw_head, &zvrf->static_pseudowires, pw);
+ QOBJ_REG(pw, zebra_pw);
+ }
+
+ return pw;
+}
+
+void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw)
+{
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_debug("%u: deleting pseudowire %s protocol %s", pw->vrf_id,
+ pw->ifname, zebra_route_string(pw->protocol));
+
+ /* remove nexthop tracking */
+ zebra_deregister_rnh_pseudowire(pw->vrf_id, pw);
+
+ /* uninstall */
+ if (pw->status == PW_STATUS_UP)
+ hook_call(pw_uninstall, pw);
+ else if (pw->install_retry_timer)
+ THREAD_TIMER_OFF(pw->install_retry_timer);
+
+ /* unlink and release memory */
+ RB_REMOVE(zebra_pw_head, &zvrf->pseudowires, pw);
+ if (pw->protocol == ZEBRA_ROUTE_STATIC)
+ RB_REMOVE(zebra_static_pw_head, &zvrf->static_pseudowires, pw);
+ XFREE(MTYPE_PW, pw);
+}
+
+void zebra_pw_change(struct zebra_pw *pw, ifindex_t ifindex, int type, int af,
+ union g_addr *nexthop, uint32_t local_label,
+ uint32_t remote_label, uint8_t flags,
+ union pw_protocol_fields *data)
+{
+ zebra_deregister_rnh_pseudowire(pw->vrf_id, pw);
+
+ pw->ifindex = ifindex;
+ pw->type = type;
+ pw->af = af;
+ pw->nexthop = *nexthop;
+ pw->local_label = local_label;
+ pw->remote_label = remote_label;
+ pw->flags = flags;
+ pw->data = *data;
+
+ if (zebra_pw_enabled(pw))
+ zebra_register_rnh_pseudowire(pw->vrf_id, pw);
+ else
+ zebra_pw_uninstall(pw);
+}
+
+struct zebra_pw *zebra_pw_find(struct zebra_vrf *zvrf, const char *ifname)
+{
+ struct zebra_pw pw;
+ strlcpy(pw.ifname, ifname, sizeof(pw.ifname));
+ return (RB_FIND(zebra_pw_head, &zvrf->pseudowires, &pw));
+}
+
+static int zebra_pw_enabled(struct zebra_pw *pw)
+{
+ if (pw->protocol == ZEBRA_ROUTE_STATIC) {
+ if (pw->local_label == MPLS_NO_LABEL
+ || pw->remote_label == MPLS_NO_LABEL || pw->af == AF_UNSPEC)
+ return 0;
+ return 1;
+ } else
+ return pw->enabled;
+}
+
+void zebra_pw_update(struct zebra_pw *pw)
+{
+ if (zebra_pw_check_reachability(pw) < 0) {
+ zebra_pw_uninstall(pw);
+ /* wait for NHT and try again later */
+ } else {
+ /*
+ * Install or reinstall the pseudowire (e.g. to update
+ * parameters like the nexthop or the use of the control word).
+ */
+ zebra_pw_install(pw);
+ }
+}
+
+static void zebra_pw_install(struct zebra_pw *pw)
+{
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_debug("%u: installing pseudowire %s protocol %s",
+ pw->vrf_id, pw->ifname,
+ zebra_route_string(pw->protocol));
+
+ if (hook_call(pw_install, pw)) {
+ zebra_pw_install_failure(pw);
+ return;
+ }
+
+ if (pw->status == PW_STATUS_DOWN)
+ zebra_pw_update_status(pw, PW_STATUS_UP);
+}
+
+static void zebra_pw_uninstall(struct zebra_pw *pw)
+{
+ if (pw->status == PW_STATUS_DOWN)
+ return;
+
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_debug("%u: uninstalling pseudowire %s protocol %s",
+ pw->vrf_id, pw->ifname,
+ zebra_route_string(pw->protocol));
+
+ /* ignore any possible error */
+ hook_call(pw_uninstall, pw);
+
+ if (zebra_pw_enabled(pw))
+ zebra_pw_update_status(pw, PW_STATUS_DOWN);
+}
+
+/*
+ * Installation of the pseudowire in the kernel or hardware has failed. This
+ * function will notify the pseudowire client about the failure and schedule
+ * to retry the installation later. This function can be called by an external
+ * agent that performs the pseudowire installation in an asynchronous way.
+ */
+void zebra_pw_install_failure(struct zebra_pw *pw)
+{
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_debug(
+ "%u: failed installing pseudowire %s, "
+ "scheduling retry in %u seconds",
+ pw->vrf_id, pw->ifname, PW_INSTALL_RETRY_INTERVAL);
+
+ /* schedule to retry later */
+ THREAD_TIMER_OFF(pw->install_retry_timer);
+ thread_add_timer(zebrad.master, zebra_pw_install_retry, pw,
+ PW_INSTALL_RETRY_INTERVAL, &pw->install_retry_timer);
+
+ zebra_pw_update_status(pw, PW_STATUS_DOWN);
+}
+
+static int zebra_pw_install_retry(struct thread *thread)
+{
+ struct zebra_pw *pw = THREAD_ARG(thread);
+
+ pw->install_retry_timer = NULL;
+ zebra_pw_install(pw);
+
+ return 0;
+}
+
+static void zebra_pw_update_status(struct zebra_pw *pw, int status)
+{
+ pw->status = status;
+ if (pw->client)
+ zsend_pw_update(pw->client, pw);
+}
+
+static int zebra_pw_check_reachability(struct zebra_pw *pw)
+{
+ struct route_entry *re;
+ struct nexthop *nexthop;
+
+ /* TODO: consider GRE/L2TPv3 tunnels in addition to MPLS LSPs */
+
+ /* find route to the remote end of the pseudowire */
+ re = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id,
+ &pw->nexthop, NULL);
+ if (!re) {
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_warn("%s: no route found for %s", __func__,
+ pw->ifname);
+ return -1;
+ }
+
+ /*
+ * Need to ensure that there's a label binding for all nexthops.
+ * Otherwise, ECMP for this route could render the pseudowire unusable.
+ */
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ if (!nexthop->nh_label) {
+ if (IS_ZEBRA_DEBUG_PW)
+ zlog_warn("%s: unlabeled route for %s",
+ __func__, pw->ifname);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void zebra_pw_client_close(struct zserv *client)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ struct zebra_pw *pw, *tmp;
+
+ RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
+ {
+ zvrf = vrf->info;
+ RB_FOREACH_SAFE(pw, zebra_pw_head, &zvrf->pseudowires, tmp)
+ {
+ if (pw->client != client)
+ continue;
+ zebra_pw_del(zvrf, pw);
+ }
+ }
+}
+
+void zebra_pw_init(struct zebra_vrf *zvrf)
+{
+ RB_INIT(zebra_pw_head, &zvrf->pseudowires);
+ RB_INIT(zebra_static_pw_head, &zvrf->static_pseudowires);
+}
+
+void zebra_pw_exit(struct zebra_vrf *zvrf)
+{
+ struct zebra_pw *pw;
+
+ while ((pw = RB_ROOT(zebra_pw_head, &zvrf->pseudowires)) != NULL)
+ zebra_pw_del(zvrf, pw);
+}
+
+DEFUN_NOSH (pseudowire_if,
+ pseudowire_if_cmd,
+ "[no] pseudowire IFNAME",
+ NO_STR
+ "Static pseudowire configuration\n"
+ "Pseudowire name\n")
+{
+ struct zebra_vrf *zvrf;
+ struct zebra_pw *pw;
+ int idx = 0;
+ const char *ifname;
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return CMD_WARNING;
+
+ argv_find(argv, argc, "IFNAME", &idx);
+ ifname = argv[idx]->arg;
+ pw = zebra_pw_find(zvrf, ifname);
+ if (pw && pw->protocol != ZEBRA_ROUTE_STATIC) {
+ vty_out(vty, "%% Pseudowire is not static\n");
+ return CMD_WARNING;
+ }
+
+ if (argv_find(argv, argc, "no", &idx)) {
+ if (!pw)
+ return CMD_SUCCESS;
+ zebra_pw_del(zvrf, pw);
+ }
+
+ if (!pw)
+ pw = zebra_pw_add(zvrf, ifname, ZEBRA_ROUTE_STATIC, NULL);
+ VTY_PUSH_CONTEXT(PW_NODE, pw);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (pseudowire_labels,
+ pseudowire_labels_cmd,
+ "[no] mpls label local (16-1048575) remote (16-1048575)",
+ NO_STR
+ "MPLS L2VPN PW command\n"
+ "MPLS L2VPN static labels\n"
+ "Local pseudowire label\n"
+ "Local pseudowire label\n"
+ "Remote pseudowire label\n"
+ "Remote pseudowire label\n")
+{
+ VTY_DECLVAR_CONTEXT(zebra_pw, pw);
+ int idx = 0;
+ mpls_label_t local_label, remote_label;
+
+ if (argv_find(argv, argc, "no", &idx)) {
+ local_label = MPLS_NO_LABEL;
+ remote_label = MPLS_NO_LABEL;
+ } else {
+ argv_find(argv, argc, "local", &idx);
+ local_label = atoi(argv[idx + 1]->arg);
+ argv_find(argv, argc, "remote", &idx);
+ remote_label = atoi(argv[idx + 1]->arg);
+ }
+
+ zebra_pw_change(pw, pw->ifindex, pw->type, pw->af, &pw->nexthop,
+ local_label, remote_label, pw->flags, &pw->data);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (pseudowire_neighbor,
+ pseudowire_neighbor_cmd,
+ "[no] neighbor <A.B.C.D|X:X::X:X>",
+ NO_STR
+ "Specify the IPv4 or IPv6 address of the remote endpoint\n"
+ "IPv4 address\n"
+ "IPv6 address\n")
+{
+ VTY_DECLVAR_CONTEXT(zebra_pw, pw);
+ int idx = 0;
+ const char *address;
+ int af;
+ union g_addr nexthop;
+
+ af = AF_UNSPEC;
+ memset(&nexthop, 0, sizeof(nexthop));
+
+ if (!argv_find(argv, argc, "no", &idx)) {
+ argv_find(argv, argc, "neighbor", &idx);
+ address = argv[idx + 1]->arg;
+
+ if (inet_pton(AF_INET, address, &nexthop.ipv4) == 1)
+ af = AF_INET;
+ else if (inet_pton(AF_INET6, address, &nexthop.ipv6) == 1)
+ af = AF_INET6;
+ else {
+ vty_out(vty, "%% Malformed address\n");
+ return CMD_WARNING;
+ }
+ }
+
+ zebra_pw_change(pw, pw->ifindex, pw->type, af, &nexthop,
+ pw->local_label, pw->remote_label, pw->flags,
+ &pw->data);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (pseudowire_control_word,
+ pseudowire_control_word_cmd,
+ "[no] control-word <exclude|include>",
+ NO_STR
+ "Control-word options\n"
+ "Exclude control-word in pseudowire packets\n"
+ "Include control-word in pseudowire packets\n")
+{
+ VTY_DECLVAR_CONTEXT(zebra_pw, pw);
+ int idx = 0;
+ uint8_t flags = 0;
+
+ if (argv_find(argv, argc, "no", &idx))
+ flags = F_PSEUDOWIRE_CWORD;
+ else {
+ argv_find(argv, argc, "control-word", &idx);
+ if (argv[idx + 1]->text[0] == 'i')
+ flags = F_PSEUDOWIRE_CWORD;
+ }
+
+ zebra_pw_change(pw, pw->ifindex, pw->type, pw->af, &pw->nexthop,
+ pw->local_label, pw->remote_label, flags, &pw->data);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_pseudowires,
+ show_pseudowires_cmd,
+ "show pseudowires",
+ SHOW_STR
+ "Pseudowires")
+{
+ struct zebra_vrf *zvrf;
+ struct zebra_pw *pw;
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return 0;
+
+ vty_out(vty, "%-16s %-24s %-12s %-8s %-10s\n", "Interface", "Neighbor",
+ "Labels", "Protocol", "Status");
+
+ RB_FOREACH(pw, zebra_pw_head, &zvrf->pseudowires)
+ {
+ char buf_nbr[INET6_ADDRSTRLEN];
+ char buf_labels[64];
+
+ inet_ntop(pw->af, &pw->nexthop, buf_nbr, sizeof(buf_nbr));
+
+ if (pw->local_label != MPLS_NO_LABEL
+ && pw->remote_label != MPLS_NO_LABEL)
+ snprintf(buf_labels, sizeof(buf_labels), "%u/%u",
+ pw->local_label, pw->remote_label);
+ else
+ snprintf(buf_labels, sizeof(buf_labels), "-");
+
+ vty_out(vty, "%-16s %-24s %-12s %-8s %-10s\n", pw->ifname,
+ (pw->af != AF_UNSPEC) ? buf_nbr : "-", buf_labels,
+ zebra_route_string(pw->protocol),
+ (zebra_pw_enabled(pw) && pw->status == PW_STATUS_UP)
+ ? "UP"
+ : "DOWN");
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* Pseudowire configuration write function. */
+static int zebra_pw_config(struct vty *vty)
+{
+ int write = 0;
+ struct zebra_vrf *zvrf;
+ struct zebra_pw *pw;
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return 0;
+
+ RB_FOREACH(pw, zebra_static_pw_head, &zvrf->static_pseudowires)
+ {
+ vty_out(vty, "pseudowire %s\n", pw->ifname);
+ if (pw->local_label != MPLS_NO_LABEL
+ && pw->remote_label != MPLS_NO_LABEL)
+ vty_out(vty, " mpls label local %u remote %u\n",
+ pw->local_label, pw->remote_label);
+ else
+ vty_out(vty,
+ " ! Incomplete config, specify the static "
+ "MPLS labels\n");
+
+ if (pw->af != AF_UNSPEC) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(pw->af, &pw->nexthop, buf, sizeof(buf));
+ vty_out(vty, " neighbor %s\n", buf);
+ } else
+ vty_out(vty,
+ " ! Incomplete config, specify a neighbor "
+ "address\n");
+
+ if (!(pw->flags & F_PSEUDOWIRE_CWORD))
+ vty_out(vty, " control-word exclude\n");
+
+ vty_out(vty, "!\n");
+ write = 1;
+ }
+
+ return write;
+}
+
+static struct cmd_node pw_node = {
+ PW_NODE, "%s(config-pw)# ", 1,
+};
+
+void zebra_pw_vty_init(void)
+{
+ install_node(&pw_node, zebra_pw_config);
+ install_default(PW_NODE);
+
+ install_element(CONFIG_NODE, &pseudowire_if_cmd);
+ install_element(PW_NODE, &pseudowire_labels_cmd);
+ install_element(PW_NODE, &pseudowire_neighbor_cmd);
+ install_element(PW_NODE, &pseudowire_control_word_cmd);
+
+ install_element(VIEW_NODE, &show_pseudowires_cmd);
+}
diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h
new file mode 100644
index 0000000000..417d26fe65
--- /dev/null
+++ b/zebra/zebra_pw.h
@@ -0,0 +1,75 @@
+/* Zebra PW code
+ * Copyright (C) 2016 Volta Networks, Inc.
+ *
+ * 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
+ */
+
+#ifndef ZEBRA_PW_H_
+#define ZEBRA_PW_H_
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include "hook.h"
+#include "qobj.h"
+
+#define PW_INSTALL_RETRY_INTERVAL 30
+
+struct zebra_pw {
+ RB_ENTRY(zebra_pw) pw_entry, static_pw_entry;
+ vrf_id_t vrf_id;
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ int enabled;
+ int status;
+ uint8_t protocol;
+ struct zserv *client;
+ struct rnh *rnh;
+ struct thread *install_retry_timer;
+ QOBJ_FIELDS
+};
+DECLARE_QOBJ_TYPE(zebra_pw)
+
+RB_HEAD(zebra_pw_head, zebra_pw);
+RB_PROTOTYPE(zebra_pw_head, zebra_pw, pw_entry, zebra_pw_compare);
+
+RB_HEAD(zebra_static_pw_head, zebra_pw);
+RB_PROTOTYPE(zebra_static_pw_head, zebra_pw, static_pw_entry, zebra_pw_compare);
+
+DECLARE_HOOK(pw_install, (struct zebra_pw * pw), (pw))
+DECLARE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
+
+struct zebra_pw *zebra_pw_add(struct zebra_vrf *, const char *, uint8_t,
+ struct zserv *);
+void zebra_pw_del(struct zebra_vrf *, struct zebra_pw *);
+void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *,
+ uint32_t, uint32_t, uint8_t, union pw_protocol_fields *);
+struct zebra_pw *zebra_pw_find(struct zebra_vrf *, const char *);
+void zebra_pw_update(struct zebra_pw *);
+void zebra_pw_install_failure(struct zebra_pw *);
+void zebra_pw_client_close(struct zserv *);
+void zebra_pw_init(struct zebra_vrf *);
+void zebra_pw_exit(struct zebra_vrf *);
+void zebra_pw_vty_init(void);
+
+#endif /* ZEBRA_PW_H_ */
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 98508aaa89..e61c2e7b0e 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -505,6 +505,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
}
resolved = 1;
}
+ if (resolved && set)
+ re->nexthop_mtu = match->mtu;
return resolved;
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
@@ -2237,13 +2239,12 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
continue;
if (same->type == re->type && same->instance == re->instance
- && same->table == re->table
- && same->type != ZEBRA_ROUTE_CONNECT)
+ && same->table == re->table && !RIB_SYSTEM_ROUTE(same))
break;
}
/* If this route is kernel route, set FIB flag to the route. */
- if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT)
+ if (RIB_SYSTEM_ROUTE(re))
for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
@@ -2467,11 +2468,11 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
continue;
if (re->instance != instance)
continue;
- if (re->type != ZEBRA_ROUTE_CONNECT) {
+ if (!RIB_SYSTEM_ROUTE(re)) {
same = re;
break;
}
- /* Duplicate connected route comes in. */
+ /* Duplicate system route comes in. */
else if ((nexthop = re->nexthop)
&& nexthop->type == NEXTHOP_TYPE_IFINDEX
&& nexthop->ifindex == ifindex
@@ -2515,7 +2516,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
route_entry_nexthop_ifindex_add(re, ifindex);
/* If this route is kernel route, set FIB flag to the route. */
- if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
+ if (RIB_SYSTEM_ROUTE(re))
for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 8a326c27fc..77cfa9860f 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -126,6 +126,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
rnh->client_list = list_new();
rnh->vrf_id = vrfid;
rnh->zebra_static_route_list = list_new();
+ rnh->zebra_pseudowire_list = list_new();
route_lock_node(rn);
rn->info = rnh;
rnh->node = rn;
@@ -161,6 +162,7 @@ void zebra_free_rnh(struct rnh *rnh)
rnh->flags |= ZEBRA_NHT_DELETED;
list_free(rnh->client_list);
list_free(rnh->zebra_static_route_list);
+ list_free(rnh->zebra_pseudowire_list);
free_state(rnh->vrf_id, rnh->state, rnh->node);
XFREE(MTYPE_RNH, rnh);
}
@@ -210,7 +212,8 @@ void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
}
listnode_delete(rnh->client_list, client);
if (list_isempty(rnh->client_list)
- && list_isempty(rnh->zebra_static_route_list))
+ && list_isempty(rnh->zebra_static_route_list)
+ && list_isempty(rnh->zebra_pseudowire_list))
zebra_delete_rnh(rnh, type);
}
@@ -237,7 +240,8 @@ void zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh,
listnode_delete(rnh->zebra_static_route_list, static_rn);
if (list_isempty(rnh->client_list)
- && list_isempty(rnh->zebra_static_route_list))
+ && list_isempty(rnh->zebra_static_route_list)
+ && list_isempty(rnh->zebra_pseudowire_list))
zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
}
@@ -284,6 +288,58 @@ void zebra_deregister_rnh_static_nexthops(vrf_id_t vrf_id,
}
}
+/* XXX move this utility function elsewhere? */
+static void addr2hostprefix(int af, const union g_addr *addr,
+ struct prefix *prefix)
+{
+ switch (af) {
+ case AF_INET:
+ prefix->family = AF_INET;
+ prefix->prefixlen = IPV4_MAX_BITLEN;
+ prefix->u.prefix4 = addr->ipv4;
+ break;
+ case AF_INET6:
+ prefix->family = AF_INET6;
+ prefix->prefixlen = IPV6_MAX_BITLEN;
+ prefix->u.prefix6 = addr->ipv6;
+ break;
+ default:
+ zlog_warn("%s: unknown address family %d", __func__, af);
+ break;
+ }
+}
+
+void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
+{
+ struct prefix nh;
+ struct rnh *rnh;
+
+ addr2hostprefix(pw->af, &pw->nexthop, &nh);
+ rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE);
+ if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
+ listnode_add(rnh->zebra_pseudowire_list, pw);
+ pw->rnh = rnh;
+ zebra_evaluate_rnh(vrf_id, pw->af, 1, RNH_NEXTHOP_TYPE, &nh);
+ }
+}
+
+void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
+{
+ struct rnh *rnh;
+
+ rnh = pw->rnh;
+ if (!rnh)
+ return;
+
+ listnode_delete(rnh->zebra_pseudowire_list, pw);
+ pw->rnh = NULL;
+
+ if (list_isempty(rnh->client_list)
+ && list_isempty(rnh->zebra_static_route_list)
+ && list_isempty(rnh->zebra_pseudowire_list))
+ zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
+}
+
/* Apply the NHT route-map for a client to the route (and nexthops)
* resolving a NH.
*/
@@ -595,6 +651,15 @@ static void zebra_rnh_process_static_routes(vrf_id_t vrfid, int family,
}
}
+static void zebra_rnh_process_pseudowires(vrf_id_t vrfid, struct rnh *rnh)
+{
+ struct zebra_pw *pw;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(rnh->zebra_pseudowire_list, node, pw))
+ zebra_pw_update(pw);
+}
+
/*
* See if a tracked nexthop entry has undergone any change, and if so,
* take appropriate action; this involves notifying any clients and/or
@@ -636,6 +701,9 @@ static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force,
/* Process static routes attached to this nexthop */
zebra_rnh_process_static_routes(vrfid, family, nrn, rnh, prn,
rnh->state);
+
+ /* Process pseudowires attached to this nexthop */
+ zebra_rnh_process_pseudowires(vrfid, rnh);
}
}
@@ -694,8 +762,10 @@ static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family,
re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn);
- if (re)
+ if (re) {
UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED);
+ UNSET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+ }
}
/* Evaluate all tracked entries (nexthops or routes for import into BGP)
@@ -815,6 +885,7 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
state = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
state->type = re->type;
+ state->distance = re->distance;
state->metric = re->metric;
route_entry_copy_nexthops(state, re->nexthop);
@@ -830,13 +901,17 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
if ((!r1 && r2) || (r1 && !r2))
return 1;
+ if (r1->distance != r2->distance)
+ return 1;
+
if (r1->metric != r2->metric)
return 1;
if (r1->nexthop_num != r2->nexthop_num)
return 1;
- if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED))
+ if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)
+ || CHECK_FLAG(r1->status, ROUTE_ENTRY_LABELS_CHANGED))
return 1;
return 0;
@@ -999,5 +1074,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
if (!list_isempty(rnh->zebra_static_route_list))
vty_out(vty, " zebra%s",
rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : "");
+ if (!list_isempty(rnh->zebra_pseudowire_list))
+ vty_out(vty, " zebra[pseudowires]");
vty_out(vty, "\n");
}
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index f8d89ec8ca..7e183684da 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -42,6 +42,8 @@ struct rnh {
struct list *
zebra_static_route_list; /* static routes dependent on this NH
*/
+ struct list
+ *zebra_pseudowire_list; /* pseudowires dependent on this NH */
struct route_node *node;
int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client
*/
@@ -67,6 +69,8 @@ extern void zebra_deregister_rnh_static_nexthops(vrf_id_t,
struct route_node *rn);
extern void zebra_deregister_rnh_static_nh(vrf_id_t, struct prefix *,
struct route_node *);
+extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
+extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_type_t type);
extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force,
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 0176b36840..c738cde0ac 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -256,7 +256,7 @@ DEFUN (no_match_ip_nexthop_prefix_len,
DEFUN (match_source_protocol,
match_source_protocol_cmd,
- "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>",
+ "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>",
MATCH_STR
"Match protocol via which the route was learnt\n"
"BGP protocol\n"
@@ -265,6 +265,10 @@ DEFUN (match_source_protocol,
"RIPNG protocol\n"
"ISIS protocol\n"
"OSPF6 protocol\n"
+ "PIM protocol\n"
+ "NHRP protocol\n"
+ "EIGRP protocol\n"
+ "BABEL protocol\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
@@ -284,7 +288,7 @@ DEFUN (match_source_protocol,
DEFUN (no_match_source_protocol,
no_match_source_protocol_cmd,
- "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>]",
+ "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]",
NO_STR
MATCH_STR
"No match protocol via which the route was learnt\n"
@@ -294,6 +298,10 @@ DEFUN (no_match_source_protocol,
"RIPNG protocol\n"
"ISIS protocol\n"
"OSPF6 protocol\n"
+ "PIM protocol\n"
+ "NHRP protocol\n"
+ "EIGRP protocol\n"
+ "BABEL protocol\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c
index 6cebae997c..dba228ea35 100644
--- a/zebra/zebra_static.c
+++ b/zebra/zebra_static.c
@@ -24,6 +24,7 @@
#include <lib/nexthop.h>
#include <lib/memory.h>
#include <lib/srcdest_table.h>
+#include <lib/if.h>
#include "vty.h"
#include "zebra/debug.h"
@@ -81,11 +82,11 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.u.prefix4 = si->addr.ipv4;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
break;
- case STATIC_IPV4_GATEWAY_IFINDEX:
+ case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
re, &si->addr.ipv4, NULL, si->ifindex);
break;
- case STATIC_IFINDEX:
+ case STATIC_IFNAME:
nexthop = route_entry_nexthop_ifindex_add(re,
si->ifindex);
break;
@@ -100,7 +101,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.u.prefix6 = si->addr.ipv6;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
+ case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &si->addr.ipv6, si->ifindex);
break;
@@ -156,11 +157,11 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.u.prefix4 = si->addr.ipv4;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
break;
- case STATIC_IPV4_GATEWAY_IFINDEX:
+ case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
re, &si->addr.ipv4, NULL, si->ifindex);
break;
- case STATIC_IFINDEX:
+ case STATIC_IFNAME:
nexthop = route_entry_nexthop_ifindex_add(re,
si->ifindex);
break;
@@ -175,7 +176,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.u.prefix6 = si->addr.ipv6;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
+ case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &si->addr.ipv6, si->ifindex);
break;
@@ -214,6 +215,9 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
}
}
+/* this works correctly with IFNAME<>IFINDEX because a static route on a
+ * non-active interface will have IFINDEX_INTERNAL and thus compare false
+ */
static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
{
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
@@ -225,12 +229,12 @@ static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
&& IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
return 1;
else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
- && si->type == STATIC_IPV4_GATEWAY_IFINDEX
+ && si->type == STATIC_IPV4_GATEWAY_IFNAME
&& IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
&& nexthop->ifindex == si->ifindex)
return 1;
else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
- && si->type == STATIC_IFINDEX
+ && si->type == STATIC_IFNAME
&& nexthop->ifindex == si->ifindex)
return 1;
else if (nexthop->type == NEXTHOP_TYPE_IPV6
@@ -238,7 +242,7 @@ static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
&& IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6))
return 1;
else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
- && si->type == STATIC_IPV6_GATEWAY_IFINDEX
+ && si->type == STATIC_IPV6_GATEWAY_IFNAME
&& IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)
&& nexthop->ifindex == si->ifindex)
return 1;
@@ -360,7 +364,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
struct prefix_ipv6 *src_p, union g_addr *gate,
- ifindex_t ifindex, const char *ifname, u_char flags,
+ const char *ifname, u_char flags,
route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
struct static_nh_label *snh_label)
{
@@ -376,15 +380,15 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
if (!gate
&& (type == STATIC_IPV4_GATEWAY
- || type == STATIC_IPV4_GATEWAY_IFINDEX
+ || type == STATIC_IPV4_GATEWAY_IFNAME
|| type == STATIC_IPV6_GATEWAY
- || type == STATIC_IPV6_GATEWAY_IFINDEX))
+ || type == STATIC_IPV6_GATEWAY_IFNAME))
return -1;
- if (!ifindex
- && (type == STATIC_IFINDEX
- || type == STATIC_IPV4_GATEWAY_IFINDEX
- || type == STATIC_IPV6_GATEWAY_IFINDEX))
+ if (!ifname
+ && (type == STATIC_IFNAME
+ || type == STATIC_IPV4_GATEWAY_IFNAME
+ || type == STATIC_IPV6_GATEWAY_IFNAME))
return -1;
/* Lookup static route prefix. */
@@ -397,7 +401,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
&& IPV4_ADDR_SAME(gate, &si->addr.ipv4))
|| (afi == AFI_IP6
&& IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
- && (!ifindex || ifindex == si->ifindex)) {
+ && (!strcmp (ifname ? ifname : "", si->ifname))) {
if ((distance == si->distance) && (tag == si->tag)
&& !memcmp(&si->snh_label, snh_label,
sizeof(struct static_nh_label))
@@ -411,7 +415,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
/* Distance or tag or label changed, delete existing first. */
if (update)
- static_delete_route(afi, safi, type, p, src_p, gate, ifindex,
+ static_delete_route(afi, safi, type, p, src_p, gate, ifname,
update->tag, update->distance, zvrf,
&update->snh_label);
@@ -423,20 +427,20 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
si->flags = flags;
si->tag = tag;
si->vrf_id = zvrf_id(zvrf);
- si->ifindex = ifindex;
- if (si->ifindex)
- strcpy(si->ifname, ifname);
+ if (ifname)
+ strlcpy(si->ifname, ifname, sizeof(si->ifname));
+ si->ifindex = IFINDEX_INTERNAL;
switch (type) {
case STATIC_IPV4_GATEWAY:
- case STATIC_IPV4_GATEWAY_IFINDEX:
+ case STATIC_IPV4_GATEWAY_IFNAME:
si->addr.ipv4 = gate->ipv4;
break;
case STATIC_IPV6_GATEWAY:
- case STATIC_IPV6_GATEWAY_IFINDEX:
+ case STATIC_IPV6_GATEWAY_IFNAME:
si->addr.ipv6 = gate->ipv6;
break;
- case STATIC_IFINDEX:
+ case STATIC_IFNAME:
break;
}
@@ -471,15 +475,25 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
si->prev = pp;
si->next = cp;
- /* Install into rib. */
- static_install_route(afi, safi, p, src_p, si);
+ /* check whether interface exists in system & install if it does */
+ if (!ifname)
+ static_install_route(afi, safi, p, src_p, si);
+ else {
+ struct interface *ifp;
+
+ ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
+ if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
+ si->ifindex = ifp->ifindex;
+ static_install_route(afi, safi, p, src_p, si);
+ }
+ }
return 1;
}
int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
struct prefix_ipv6 *src_p, union g_addr *gate,
- ifindex_t ifindex, route_tag_t tag, u_char distance,
+ const char *ifname, route_tag_t tag, u_char distance,
struct zebra_vrf *zvrf,
struct static_nh_label *snh_label)
{
@@ -504,7 +518,7 @@ int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
&& IPV4_ADDR_SAME(gate, &si->addr.ipv4))
|| (afi == AFI_IP6
&& IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
- && (!ifindex || ifindex == si->ifindex)
+ && (!strcmp(ifname ? ifname : "", si->ifname))
&& (!tag || (tag == si->tag))
&& (!snh_label->num_labels
|| !memcmp(&si->snh_label, snh_label,
@@ -517,8 +531,9 @@ int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
return 0;
}
- /* Install into rib. */
- static_uninstall_route(afi, safi, p, src_p, si);
+ /* Uninstall from rib. */
+ if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL)
+ static_uninstall_route(afi, safi, p, src_p, si);
/* Unlink static route from linked list. */
if (si->prev)
@@ -536,3 +551,49 @@ int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
return 1;
}
+
+static void static_ifindex_update_af(struct interface *ifp, bool up,
+ afi_t afi, safi_t safi)
+{
+ struct route_table *stable;
+ struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ struct route_node *rn;
+ struct static_route *si;
+ struct prefix *p, *src_pp;
+ struct prefix_ipv6 *src_p;
+
+ stable = zebra_vrf_static_table(afi, safi, zvrf);
+ if (!stable)
+ return;
+
+ for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
+ srcdest_rnode_prefixes(rn, &p, &src_pp);
+ src_p = (struct prefix_ipv6 *)src_pp;
+
+ for (si = rn->info; si; si = si->next) {
+ if (!si->ifname[0])
+ continue;
+ if (up) {
+ if (strcmp(si->ifname, ifp->name))
+ continue;
+ si->ifindex = ifp->ifindex;
+ static_install_route(afi, safi, p, src_p, si);
+ } else {
+ if (si->ifindex != ifp->ifindex)
+ continue;
+ static_uninstall_route(afi, safi, p, src_p,
+ si);
+ si->ifindex = IFINDEX_INTERNAL;
+ }
+ }
+ }
+}
+
+/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
+void static_ifindex_update(struct interface *ifp, bool up)
+{
+ static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
+ static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
+ static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
+ static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
+}
diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h
index 885774895f..6ab47094a1 100644
--- a/zebra/zebra_static.h
+++ b/zebra/zebra_static.h
@@ -30,12 +30,12 @@ struct static_nh_label {
};
typedef enum {
- STATIC_IFINDEX,
+ STATIC_IFNAME,
STATIC_IPV4_GATEWAY,
- STATIC_IPV4_GATEWAY_IFINDEX,
+ STATIC_IPV4_GATEWAY_IFNAME,
STATIC_BLACKHOLE,
STATIC_IPV6_GATEWAY,
- STATIC_IPV6_GATEWAY_IFINDEX,
+ STATIC_IPV6_GATEWAY_IFNAME,
} zebra_static_types;
/* Static route information. */
@@ -84,16 +84,18 @@ extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
struct prefix_ipv6 *src_p, union g_addr *gate,
- ifindex_t ifindex, const char *ifname, u_char flags,
+ const char *ifname, u_char flags,
route_tag_t tag, u_char distance,
struct zebra_vrf *zvrf,
struct static_nh_label *snh_label);
extern int static_delete_route(afi_t, safi_t safi, u_char type,
struct prefix *p, struct prefix_ipv6 *src_p,
- union g_addr *gate, ifindex_t ifindex,
+ union g_addr *gate, const char *ifname,
route_tag_t tag, u_char distance,
struct zebra_vrf *zvrf,
struct static_nh_label *snh_label);
+extern void static_ifindex_update(struct interface *ifp, bool up);
+
#endif
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index feca13d3a2..ff140bad67 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -95,51 +95,6 @@ static int zebra_vrf_new(struct vrf *vrf)
return 0;
}
-/*
- * Moving an interface amongst different vrf's
- * causes the interface to get a new ifindex
- * so we need to find static routes with
- * the old ifindex and replace with new
- * ifindex to insert back into the table
- */
-void zebra_vrf_static_route_interface_fixup(struct interface *ifp)
-{
- afi_t afi;
- safi_t safi;
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
- struct route_table *stable = NULL;
- struct route_node *rn = NULL;
- struct static_route *si = NULL;
-
- if (!zvrf)
- return;
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- stable = zvrf->stable[afi][safi];
- if (stable)
- for (rn = route_top(stable); rn;
- rn = route_next(rn)) {
- if (rn->info) {
- si = rn->info;
- if ((strcmp(si->ifname,
- ifp->name)
- == 0)
- && (si->ifindex
- != ifp->ifindex)) {
- si->ifindex =
- ifp->ifindex;
- static_install_route(
- afi, safi,
- &rn->p, NULL,
- si);
- }
- }
- }
- }
- }
-}
-
/* Callback upon enabling a VRF. */
static int zebra_vrf_enable(struct vrf *vrf)
{
@@ -248,6 +203,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
zebra_vxlan_close_tables(zvrf);
zebra_mpls_close_tables(zvrf);
+ zebra_pw_exit(zvrf);
for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp))
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
@@ -417,6 +373,7 @@ struct zebra_vrf *zebra_vrf_alloc(void)
zebra_vxlan_init_tables(zvrf);
zebra_mpls_init_tables(zvrf);
+ zebra_pw_init(zvrf);
return zvrf;
}
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index eb0687bf8a..dca53bb9f3 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -23,6 +23,7 @@
#define __ZEBRA_RIB_H__
#include <zebra/zebra_ns.h>
+#include <zebra/zebra_pw.h>
/* MPLS (Segment Routing) global block */
typedef struct mpls_srgb_t_ {
@@ -89,6 +90,10 @@ struct zebra_vrf {
/* MPLS Segment Routing Global block */
mpls_srgb_t mpls_srgb;
+ /* Pseudowires. */
+ struct zebra_pw_head pseudowires;
+ struct zebra_static_pw_head static_pseudowires;
+
/* MPLS processing flags */
u_int16_t mpls_flags;
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
@@ -124,7 +129,6 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi,
vrf_id_t vrf_id,
u_int32_t table_id);
-extern void zebra_vrf_static_route_interface_fixup(struct interface *ifp);
extern void zebra_vrf_update_all(struct zserv *client);
extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id);
extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index e8b82ecf90..e260338131 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -55,9 +55,6 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
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
-
/* VNI range as per RFC 7432 */
#define CMD_VNI_RANGE "(1-16777215)"
@@ -80,7 +77,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
u_char flag = 0;
route_tag_t tag = 0;
struct zebra_vrf *zvrf;
- unsigned int ifindex = 0;
u_char type;
struct static_nh_label snh_label;
@@ -207,26 +203,15 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
gatep = &gate;
}
- if (ifname) {
- struct interface *ifp;
- ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
- if (!ifp) {
- vty_out(vty, "%% Malformed Interface name %s\n",
- ifname);
- ifindex = IFINDEX_DELETED;
- } else
- ifindex = ifp->ifindex;
- }
-
if (gate_str == NULL && ifname == NULL)
type = STATIC_BLACKHOLE;
else if (gate_str && ifname) {
if (afi == AFI_IP)
- type = STATIC_IPV4_GATEWAY_IFINDEX;
+ type = STATIC_IPV4_GATEWAY_IFNAME;
else
- type = STATIC_IPV6_GATEWAY_IFINDEX;
+ type = STATIC_IPV6_GATEWAY_IFNAME;
} else if (ifname)
- type = STATIC_IFINDEX;
+ type = STATIC_IFNAME;
else {
if (afi == AFI_IP)
type = STATIC_IPV4_GATEWAY;
@@ -235,10 +220,10 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
}
if (!negate)
- static_add_route(afi, safi, type, &p, src_p, gatep, ifindex,
- ifname, flag, tag, distance, zvrf, &snh_label);
+ static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
+ flag, tag, distance, zvrf, &snh_label);
else
- static_delete_route(afi, safi, type, &p, src_p, gatep, ifindex,
+ static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
tag, distance, zvrf, &snh_label);
return CMD_SUCCESS;
@@ -540,6 +525,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
break;
}
+ if (re->nexthop_mtu)
+ vty_out(vty, ", mtu %u", re->nexthop_mtu);
+
/* Label information */
if (nexthop->nh_label
&& nexthop->nh_label->num_labels) {
@@ -586,8 +574,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
- if (re->type != ZEBRA_ROUTE_CONNECT
- && re->type != ZEBRA_ROUTE_KERNEL) {
+ if (re->type != ZEBRA_ROUTE_CONNECT) {
json_object_int_add(json_route, "distance",
re->distance);
json_object_int_add(json_route, "metric", re->metric);
@@ -774,8 +761,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
srcdest_rnode2str(rn, buf, sizeof buf));
/* Distance and metric display. */
- if (re->type != ZEBRA_ROUTE_CONNECT
- && re->type != ZEBRA_ROUTE_KERNEL)
+ if (re->type != ZEBRA_ROUTE_CONNECT)
len += vty_out(vty, " [%d/%d]", re->distance,
re->metric);
} else
@@ -1704,7 +1690,7 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
&si->addr.ipv6, buf,
sizeof buf));
break;
- case STATIC_IFINDEX:
+ case STATIC_IFNAME:
vty_out(vty, " %s", si->ifname);
break;
/* blackhole and Null0 mean the same thing */
@@ -1714,7 +1700,7 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
else
vty_out(vty, " Null0");
break;
- case STATIC_IPV4_GATEWAY_IFINDEX:
+ case STATIC_IPV4_GATEWAY_IFNAME:
vty_out(vty, " %s %s",
inet_ntop(AF_INET,
&si->addr.ipv4, buf,
@@ -1722,7 +1708,7 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
ifindex2ifname(si->ifindex,
si->vrf_id));
break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
+ case STATIC_IPV6_GATEWAY_IFNAME:
vty_out(vty, " %s %s",
inet_ntop(AF_INET6,
&si->addr.ipv6, buf,
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index c96f073064..7d265af309 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -469,7 +469,7 @@ static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
zserv_create_header(s, cmd, zvrf_id(zvrf));
stream_putl(s, vni);
- stream_put(s, macaddr->octet, ETHER_ADDR_LEN);
+ stream_put(s, macaddr->octet, ETH_ALEN);
if (ip) {
ipa_len = 0;
if (IS_IPADDR_V4(ip))
@@ -776,18 +776,9 @@ static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt)
static unsigned int mac_hash_keymake(void *p)
{
zebra_mac_t *pmac = p;
- char *pnt = (char *)pmac->macaddr.octet;
- unsigned int key = 0;
- int c = 0;
+ const void *pnt = (void *)pmac->macaddr.octet;
- key += pnt[c];
- key += pnt[c + 1];
- key += pnt[c + 2];
- key += pnt[c + 3];
- key += pnt[c + 4];
- key += pnt[c + 5];
-
- return (key);
+ return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
}
/*
@@ -805,7 +796,7 @@ static int mac_cmp(const void *p1, const void *p2)
return 0;
return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet,
- ETHER_ADDR_LEN)
+ ETH_ALEN)
== 0);
}
@@ -832,7 +823,7 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
zebra_mac_t *mac = NULL;
memset(&tmp_mac, 0, sizeof(zebra_mac_t));
- memcpy(&tmp_mac.macaddr, macaddr, ETHER_ADDR_LEN);
+ memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
assert(mac);
@@ -940,7 +931,7 @@ static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
zebra_mac_t *pmac;
memset(&tmp, 0, sizeof(tmp));
- memcpy(&tmp.macaddr, mac, ETHER_ADDR_LEN);
+ memcpy(&tmp.macaddr, mac, ETH_ALEN);
pmac = hash_lookup(zvni->mac_table, &tmp);
return pmac;
@@ -1976,7 +1967,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
if (n) {
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
if (memcmp(n->emac.octet, macaddr->octet,
- ETHER_ADDR_LEN)
+ ETH_ALEN)
== 0) {
if (n->ifindex == ifp->ifindex)
/* we're not interested in whatever has
@@ -2022,7 +2013,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- memcpy(&n->emac, macaddr, ETHER_ADDR_LEN);
+ memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex;
/* Inform BGP if required. */
@@ -2062,14 +2053,14 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
n = NULL;
memset(&ip, 0, sizeof(ip));
vni = (vni_t)stream_getl(s);
- stream_get(&macaddr.octet, s, ETHER_ADDR_LEN);
+ stream_get(&macaddr.octet, s, ETH_ALEN);
ipa_len = stream_getl(s);
if (ipa_len) {
ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
: IPADDR_V6;
stream_get(&ip.ip.addr, s, ipa_len);
}
- l += 4 + ETHER_ADDR_LEN + 4 + ipa_len;
+ l += 4 + ETH_ALEN + 4 + ipa_len;
vtep_ip.s_addr = stream_get_ipv4(s);
l += IPV4_MAX_BYTELEN;
@@ -2148,7 +2139,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
*/
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
&& (memcmp(n->emac.octet, macaddr.octet,
- ETHER_ADDR_LEN)
+ ETH_ALEN)
== 0)) {
zvni_neigh_uninstall(zvni, n);
zvni_neigh_del(zvni, n);
@@ -2205,14 +2196,14 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
n = NULL;
memset(&ip, 0, sizeof(ip));
vni = (vni_t)stream_getl(s);
- stream_get(&macaddr.octet, s, ETHER_ADDR_LEN);
+ stream_get(&macaddr.octet, s, ETH_ALEN);
ipa_len = stream_getl(s);
if (ipa_len) {
ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
: IPADDR_V6;
stream_get(&ip.ip.addr, s, ipa_len);
}
- l += 4 + ETHER_ADDR_LEN + 4 + ipa_len;
+ l += 4 + ETH_ALEN + 4 + ipa_len;
vtep_ip.s_addr = stream_get_ipv4(s);
l += IPV4_MAX_BYTELEN;
@@ -2363,7 +2354,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
/* Set "remote" forwarding info. */
UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
/* TODO: Handle MAC change. */
- memcpy(&n->emac, &macaddr, ETHER_ADDR_LEN);
+ memcpy(&n->emac, &macaddr, ETH_ALEN);
n->r_vtep_ip = vtep_ip;
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 3bc5f83f64..bdb7755b63 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -55,6 +55,7 @@
#include "zebra/zebra_mroute.h"
#include "zebra/label_manager.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/rt.h"
/* Event list of zebra. */
enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
@@ -1084,6 +1085,27 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p,
return zebra_server_send_message(client);
}
+/*
+ * Function used by Zebra to send a PW status update to LDP daemon
+ */
+int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zserv_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
+ stream_write(s, pw->ifname, IF_NAMESIZE);
+ stream_putl(s, pw->ifindex);
+ stream_putl(s, pw->status);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client);
+}
+
/* Register zebra server interface information. Send current all
interface and address information. */
static int zread_interface_add(struct zserv *client, u_short length,
@@ -1876,14 +1898,12 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length,
if (command == ZEBRA_MPLS_LABELS_ADD) {
mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate,
ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate,
- ifindex, distance, out_label);
+ mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
} else if (command == ZEBRA_MPLS_LABELS_DELETE) {
mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate,
- ifindex, distance, out_label);
+ mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
}
}
/* Send response to a label manager connect request to client */
@@ -2038,6 +2058,97 @@ static void zread_label_manager_request(int cmd, struct zserv *client,
}
}
+static int zread_pseudowire(int command, struct zserv *client, u_short length,
+ vrf_id_t vrf_id)
+{
+ struct stream *s;
+ struct zebra_vrf *zvrf;
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ uint8_t protocol;
+ struct zebra_pw *pw;
+
+ zvrf = vrf_info_lookup(vrf_id);
+ if (!zvrf)
+ return -1;
+
+ /* Get input stream. */
+ s = client->ibuf;
+
+ /* Get data. */
+ stream_get(ifname, s, IF_NAMESIZE);
+ ifindex = stream_getl(s);
+ type = stream_getl(s);
+ af = stream_getl(s);
+ switch (af) {
+ case AF_INET:
+ nexthop.ipv4.s_addr = stream_get_ipv4(s);
+ break;
+ case AF_INET6:
+ stream_get(&nexthop.ipv6, s, 16);
+ break;
+ default:
+ return -1;
+ }
+ local_label = stream_getl(s);
+ remote_label = stream_getl(s);
+ flags = stream_getc(s);
+ stream_get(&data, s, sizeof(data));
+ protocol = client->proto;
+
+ pw = zebra_pw_find(zvrf, ifname);
+ switch (command) {
+ case ZEBRA_PW_ADD:
+ if (pw) {
+ zlog_warn("%s: pseudowire %s already exists [%s]",
+ __func__, ifname,
+ zserv_command_string(command));
+ return -1;
+ }
+
+ zebra_pw_add(zvrf, ifname, protocol, client);
+ break;
+ case ZEBRA_PW_DELETE:
+ if (!pw) {
+ zlog_warn("%s: pseudowire %s not found [%s]", __func__,
+ ifname, zserv_command_string(command));
+ return -1;
+ }
+
+ zebra_pw_del(zvrf, pw);
+ break;
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ if (!pw) {
+ zlog_warn("%s: pseudowire %s not found [%s]", __func__,
+ ifname, zserv_command_string(command));
+ return -1;
+ }
+
+ switch (command) {
+ case ZEBRA_PW_SET:
+ pw->enabled = 1;
+ break;
+ case ZEBRA_PW_UNSET:
+ pw->enabled = 0;
+ break;
+ }
+
+ zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label,
+ remote_label, flags, &data);
+ break;
+ }
+
+ return 0;
+}
+
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
static void zebra_client_close_cleanup_rnh(struct zserv *client)
{
@@ -2082,6 +2193,9 @@ static void zebra_client_close(struct zserv *client)
zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
client);
+ /* Remove pseudowires associated with this client */
+ zebra_pw_client_close(client);
+
/* Close file descriptor. */
if (client->sock) {
unsigned long nroutes;
@@ -2164,6 +2278,31 @@ static void zebra_client_create(int sock)
zebra_vrf_update_all(client);
}
+static int zread_interface_set_master(struct zserv *client, int sock,
+ u_short length)
+{
+ struct interface *master;
+ struct interface *slave;
+ struct stream *s = client->ibuf;
+ int ifindex;
+ vrf_id_t vrf_id;
+
+ vrf_id = stream_getw(s);
+ ifindex = stream_getl(s);
+ master = if_lookup_by_index(ifindex, vrf_id);
+
+ vrf_id = stream_getw(s);
+ ifindex = stream_getl(s);
+ slave = if_lookup_by_index(ifindex, vrf_id);
+
+ if (!master || !slave)
+ return 0;
+
+ kernel_interface_set_master(master, slave);
+
+ return 1;
+}
+
/* Handler of zebra service request. */
static int zebra_client_read(struct thread *thread)
{
@@ -2407,6 +2546,15 @@ static int zebra_client_read(struct thread *thread)
case ZEBRA_REMOTE_MACIP_DEL:
zebra_vxlan_remote_macip_del(client, sock, length, zvrf);
break;
+ case ZEBRA_INTERFACE_SET_MASTER:
+ zread_interface_set_master(client, sock, length);
+ break;
+ case ZEBRA_PW_ADD:
+ case ZEBRA_PW_DELETE:
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ zread_pseudowire(command, client, length, vrf_id);
+ break;
default:
zlog_info("Zebra received unknown command %d", command);
break;
@@ -2618,10 +2766,6 @@ static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
now -= *time1;
tm = gmtime(&now);
-/* Making formatted timer strings. */
-#define ONE_DAY_SECOND 60*60*24
-#define ONE_WEEK_SECOND 60*60*24*7
-
if (now < ONE_DAY_SECOND)
snprintf(buf, buflen, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
tm->tm_sec);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index a2cf5d9f41..f661572d53 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -30,6 +30,8 @@
#include "zclient.h"
#include "zebra/zebra_ns.h"
+#include "zebra/zebra_pw.h"
+
/* Default port information. */
#define ZEBRA_VTY_PORT 2601
@@ -175,6 +177,7 @@ extern int zsend_interface_vrf_update(struct zserv *, struct interface *,
vrf_id_t);
extern int zsend_interface_link_params(struct zserv *, struct interface *);
+extern int zsend_pw_update(struct zserv *, struct zebra_pw *);
extern pid_t pid;