From 7c900c2d5d5973a455f9438f2c6a90f0a0983dc5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 May 2016 13:31:51 -0400 Subject: [PATCH 001/226] cumulus: Increase netlink socket buffer size Ticket: CM-10950 Signed-off-by: Donald Sharp Reviewed-by: Vivek Venkatraman --- cumulus/etc/quagga/debian.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/etc/quagga/debian.conf b/cumulus/etc/quagga/debian.conf index ed2fdd985a..0b7819e1ed 100644 --- a/cumulus/etc/quagga/debian.conf +++ b/cumulus/etc/quagga/debian.conf @@ -4,7 +4,7 @@ # Check /etc/pam.d/quagga if you intend to use "vtysh"! # vtysh_enable=yes -zebra_options=" -s 16777216 --daemon -A 127.0.0.1" +zebra_options=" -s 90000000 --daemon -A 127.0.0.1" bgpd_options=" --daemon -A 127.0.0.1" ospfd_options=" --daemon -A 127.0.0.1" ospf6d_options=" --daemon -A ::1" From afe50908f91349ff94d4dd3a76058be63b1070a3 Mon Sep 17 00:00:00 2001 From: vivek Date: Wed, 18 May 2016 14:08:55 -0700 Subject: [PATCH 002/226] Quagga: Make sure order of route-maps in list and hash table matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quick create/delete actions on a route-map can result in the same route-map entity having multiple entries created for it — because BGP hasn't run the update processing to complete prior delete action. The route-map is present in both a hash table as well as a linked list and the order in each is different. This can lead to problems when the BGP route-map update processing runs and finds the same route-map entity present for deletion multiple times. For example, while processing instance-2 of rmap-A, the code may end up freeing the hash bucket corresponding to instance-1 of rmap-A. The fix works by ensuring the list is ordered the same way as the hash buckets. Signed-off-by: Vivek Venkatraman Reviewed-by: Daniel Walton Reviewed-by: Donald Sharp Reviewed-by: Shrijeet Mukherjee Ticket: CM-10023 Reviewed By: CCR-4747 Testing Done: manual, bgp-smoke --- lib/routemap.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/routemap.c b/lib/routemap.c index 733e61c99b..c3afcb896d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -163,13 +163,23 @@ route_map_add (const char *name) /* Add map to the hash */ hash_get(route_map_master_hash, map, hash_alloc_intern); - map->next = NULL; - map->prev = list->tail; - if (list->tail) - list->tail->next = map; - else - list->head = map; - list->tail = map; + /* Add new entry to the head of the list to match how it is added in the + * hash table. This is to ensure that if the same route-map has been + * created more than once and then marked for deletion (which can happen + * if prior deletions haven't completed as BGP hasn't yet done the + * route-map processing), the order of the entities is the same in both + * the list and the hash table. Otherwise, since there is nothing to + * distinguish between the two entries, the wrong entry could get freed. + * TODO: This needs to be re-examined to handle it better - e.g., revive + * a deleted entry if the route-map is created again. + */ + map->prev = NULL; + map->next = list->head; + if (list->head) + list->head->prev = map; + list->head = map; + if (!list->tail) + list->tail = map; /* Execute hook. */ if (route_map_master.add_hook) From f6da66a913bcae1d3f75c55f24e72e97288af619 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 May 2016 09:56:35 -0400 Subject: [PATCH 003/226] lib: Fix some poll semantics Two Fixes: 1) When a fd has both read and write as a .events. (POLLHUP | POLLIN | POLLOUT) and a thread_cancel_read_write call is executed from a protocol, the code was blindly removing the fd from consideration at all. 2) POLLNVAL was being evaluated before POLLIN|POLLOUT were being evaluated. While I didn't see a case of POLLNVAL being included with other .revent flags I decided to move the POLLNVAL and POLLHUP handling to the same section of code. Additionally the function thread_cancel_read_write was poorly named and let me to poorly implement the poll version of it. I've renamed the function thread_cancel_read_or_write in an attempt to make this problem moot in the future. Ticket: CM-11027 Signed-off-by: Donald Sharp --- lib/thread.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index ab4764dfb1..a2a42e43c8 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1046,7 +1046,7 @@ funcname_thread_add_event (struct thread_master *m, } static void -thread_cancel_read_write (struct thread *thread) +thread_cancel_read_or_write (struct thread *thread, short int state) { #if defined(HAVE_POLL) nfds_t i; @@ -1054,12 +1054,17 @@ thread_cancel_read_write (struct thread *thread) for (i=0;imaster->handler.pfdcount;++i) if (thread->master->handler.pfds[i].fd == thread->u.fd) { + thread->master->handler.pfds[i].events &= ~(state); + /* remove thread fds from pfd list */ - memmove(thread->master->handler.pfds+i, - thread->master->handler.pfds+i+1, - (thread->master->handler.pfdsize-i-1) * sizeof(struct pollfd)); - i--; - thread->master->handler.pfdcount--; + if (thread->master->handler.pfds[i].events == 0) + { + memmove(thread->master->handler.pfds+i, + thread->master->handler.pfds+i+1, + (thread->master->handler.pfdsize-i-1) * sizeof(struct pollfd)); + thread->master->handler.pfdcount--; + return; + } } #endif @@ -1077,11 +1082,19 @@ thread_cancel (struct thread *thread) switch (thread->type) { case THREAD_READ: - thread_cancel_read_write (thread); +#if defined (HAVE_POLL) + thread_cancel_read_or_write (thread, POLLIN | POLLHUP); +#else + thread_cancel_read_or_write (thread, 0); +#endif thread_array = thread->master->read; break; case THREAD_WRITE: - thread_cancel_read_write (thread); +#if defined (HAVE_POLL) + thread_cancel_read_or_write (thread, POLLOUT | POLLHUP); +#else + thread_cancel_read_or_write (thread, 0); +#endif thread_array = thread->master->write; break; case THREAD_TIMER: @@ -1254,16 +1267,6 @@ check_pollfds(struct thread_master *m, fd_set *readfd, int num) continue; ready++; - /* remove fd from list on POLLNVAL */ - if (m->handler.pfds[i].revents & POLLNVAL) - { - memmove(m->handler.pfds+i, - m->handler.pfds+i+1, - (m->handler.pfdsize-i-1) * sizeof(struct pollfd)); - m->handler.pfdcount--; - i--; - continue; - } /* POLLIN / POLLOUT process event */ if (m->handler.pfds[i].revents & POLLIN) @@ -1271,8 +1274,9 @@ check_pollfds(struct thread_master *m, fd_set *readfd, int num) if (m->handler.pfds[i].revents & POLLOUT) thread_process_fds_helper(m, m->write[m->handler.pfds[i].fd], NULL, POLLOUT, i); - /* remove fd from list on POLLHUP after other event is processed */ - if (m->handler.pfds[i].revents & POLLHUP) + /* remove fd from list on POLLNVAL */ + if (m->handler.pfds[i].revents & POLLNVAL || + m->handler.pfds[i].revents & POLLHUP) { memmove(m->handler.pfds+i, m->handler.pfds+i+1, From 116bd4e9ff9a8df4b6c66b3e674f21d8000d8e41 Mon Sep 17 00:00:00 2001 From: radhika Date: Sat, 21 May 2016 01:16:14 -0700 Subject: [PATCH 004/226] BGP:Fix for BFD sessions not getting replayed after quagga restart Signed-off-by: Radhika Mahankali Reviewed-by: Donald Sharp Reviewed-by: Kanna Rajagopal Ticket: CM-11055 Reviewed By: CCR-4773 Testing Done: Unit, PTM smoke, BGP neighbor smoke Issue: bgpd is not replaying the BFD registrations to PTM after quagga restart. Root Cause: This problem happens when BFD configuration is part of the peer group template. Currently, the BFD configuration is being copied to the peer from template as part of the AF (address family) configuration. But, when the saved config is used after the quagga restart the peer group template is applied to the peer before the AF configuration is configured for the template. Due to this the BFD configuration never gets copied from the template to the peer and the BGP peers have no BFD configuration after the restart Sample config which failed: router bgp 100 bgp router-id 10.10.0.1 no bgp default ipv4-unicast bgp bestpath as-path multipath-relax neighbor dpeergrp_2 peer-group neighbor dpeergrp_2 remote-as 100 neighbor dpeergrp_2 bfd neighbor dpeergrp_2 advertisement-interval 1 neighbor dpeergrp_2 timers connect 1 neighbor dpeergrp_4 peer-group neighbor dpeergrp_4 remote-as 400 neighbor dpeergrp_4 bfd neighbor dpeergrp_4 advertisement-interval 1 neighbor dpeergrp_4 timers connect 1 neighbor swp2s0.1 interface peer-group dpeergrp_2 neighbor swp18s3.1 interface peer-group dpeergrp_4 ! address-family ipv4 unicast redistribute connected route-map redist neighbor dpeergrp_2 activate neighbor dpeergrp_2 next-hop-self neighbor dpeergrp_2 default-originate neighbor dpeergrp_2 soft-reconfiguration inbound neighbor dpeergrp_4 activate neighbor dpeergrp_4 next-hop-self neighbor dpeergrp_4 default-originate neighbor dpeergrp_4 soft-reconfiguration inbound maximum-paths 14 exit-address-family Fix: Moved the BFD config copy from the peer group AF config copy function to the main peer group config copy function. --- bgpd/bgpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2f7c584c2d..ed76cfcf60 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2196,6 +2196,8 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer) } peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if); } + + bgp_bfd_peer_group2peer_copy(conf, peer); } static void @@ -2340,8 +2342,6 @@ peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer, pfilter->usmap.name = NULL; pfilter->usmap.map = NULL; } - - bgp_bfd_peer_group2peer_copy(conf, peer); } /* Peer group's remote AS configuration. */ From 99d8325e9a43d70531b83c68864736c009a60c04 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 May 2016 17:22:24 -0400 Subject: [PATCH 005/226] zebra: Fix zebra to exit on recvmsg buffer overrun When zebra receives a recvmsg buffer from the kernel silently exit so that watchquagga will notice and then restart zebra. Ticket: CM-11130 Signed-off-by: Donald Sharp Reviewed-by: Vivek Venkatraman --- zebra/rt_netlink.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 50a269dbc6..e52fcd4342 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -327,6 +327,12 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, break; zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s", nl->name, safe_strerror(errno)); + /* + * In this case we are screwed. + * There is no good way to + * recover zebra at this point. + */ + exit (-1); continue; } From d236e0b80a40d57198ad661f085ac0e57489a86c Mon Sep 17 00:00:00 2001 From: Don Slice Date: Fri, 10 Jun 2016 06:58:03 -0700 Subject: [PATCH 006/226] bgpd: remove vrf->iflist deleted to avoid a crash Ticket: CM-11327 Signed-off-by: Don Slice Reviewed-by: Donald Sharp Testing Done: Manual testing, bgp-min, vrf-min, bgp-smoke, vrf-smoke all successful When bgp was configured in a vrf and then deleted, the vrf->iflist was being deleted from the vrf. Since the vrf itself was not deleted, it was assumed in later calls that the vrf->iflist was still there and when it was referenced, the crash occurred. --- bgpd/bgpd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ed76cfcf60..f23cc13725 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7251,7 +7251,6 @@ bgp_if_finish (struct bgp *bgp) for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) bgp_connected_delete (bgp, c); } - vrf_iflist_terminate (bgp->vrf_id); } void From f104b1d98c5e298aa0946ad376899210082cc05a Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Fri, 4 Sep 2015 14:25:13 +0100 Subject: [PATCH 007/226] distro: fix redhat/quagga.spec.in * quagga.spec.in: Add default for with_pimd macro. Remove ancient condtional on quagga_buildreqs. More recent rpmbuild complains about too many levels of recursion in quagga_buildreqs, so use %{expand:..}. Actually use quagga_buildreqs in BuildRequires! groff is needed for build. texi2html --number argument has disappeared, split into 2. Acked-by: Donald Sharp (cherry picked from commit e07068c838142a127da8821afd660f075f7c35f8) --- redhat/quagga.spec.in | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index a9b0312165..a49f48096a 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -20,6 +20,7 @@ %{!?with_irdp: %define with_irdp 1 } %{!?with_rtadv: %define with_rtadv 1 } %{!?with_isisd: %define with_isisd 1 } +%{!?with_pimd: %define with_pimd 1 } %{!?with_shared: %define with_shared 1 } %{!?with_multipath: %define with_multipath 64 } %{!?quagga_user: %define quagga_user quagga } @@ -44,23 +45,24 @@ %{!?dist: %define dist %{default_dist}} # as distros change packages we depend on, our Requires have to change, sadly. -%define quagga_buildreqs texi2html texinfo tetex autoconf pam-devel -%define quagga_buildreqs %{quagga_buildreqs} patch libcap-devel +%define quagga_buildreqs texi2html texinfo autoconf pam-devel +%define quagga_buildreqs %{expand:%{quagga_buildreqs}} patch libcap-devel # FC4 and 5 split texi2html out of tetex package. -%if "%dist" != "fc2" || "%dist" != "fc3" -%define quagga_buildreqs %{quagga_buildreqs} texi2html -%endif +%define quagga_buildreqs %{expand:%{quagga_buildreqs}} texi2html -# pam_stack is deprecated in FC5 +# pam_stack was deprecated in FC5 # default to pam_stack, default should be changed later. %if "%dist" == "fc4" || "%dist" == "fc3" %define quagga_pam_source quagga.pam.stack %else %define quagga_pam_source quagga.pam %endif -############################################################################ +# man page probably needs groff for groff_ms macros +%define quagga_buildreqs %{expand:%{quagga_buildreqs}} groff + +############################################################################ # misc internal defines %{!?quagga_uid: %define quagga_uid 92 } @@ -103,7 +105,7 @@ Requires(pre): net-snmp BuildRequires: readline readline-devel ncurses ncurses-devel Requires(pre): ncurses %endif -BuildRequires: texinfo tetex autoconf pam-devel patch libcap-devel tetex +BuildRequires: %{quagga_buildreqs} # Initscripts > 5.60 is required for IPv6 support Requires(pre): initscripts >= 5.60 Requires(pre): ncurses pam @@ -223,7 +225,7 @@ developing OSPF-API and quagga applications. make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" pushd doc -texi2html -number quagga.texi +texi2html --number-footnotes --number-sections quagga.texi popd %install @@ -446,6 +448,10 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Fri Sep 4 2015 Paul Jakma - %{version} +- buildreq updates +- add a default define for with_pimd + * Thu Sep 12 2005 Paul Jakma - Steal some changes from Fedora spec file: - Add with_rtadv variable From a5ca204764a9323dc75f57eaeb1a1387b8c5d606 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 11 Feb 2016 13:54:23 +0000 Subject: [PATCH 008/226] distro/redhat/rpm: remove with_ipv6, package pimd binary, remove pam stack * redhat/quagga.spec.in: remove with_ipv6, it should just be the norm now. The actual pimd binary wasn't being packaged, fix. Remove deprecated pam.stack support. * redhat/quagga.pam.stack: ancient, nuke. * Makefile.am: ditto (cherry picked from commit 283d5d7f2fa12c3d33dc17962154665a9993b2c5) --- redhat/Makefile.am | 2 +- redhat/quagga.pam.stack | 26 -------------------------- redhat/quagga.spec.in | 36 +++++++++++++----------------------- 3 files changed, 14 insertions(+), 50 deletions(-) delete mode 100644 redhat/quagga.pam.stack diff --git a/redhat/Makefile.am b/redhat/Makefile.am index 9612e91484..3ec1fb73ac 100644 --- a/redhat/Makefile.am +++ b/redhat/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = bgpd.init bgpd.service isisd.init \ isisd.service ospf6d.init ospf6d.service ospfd.init ospfd.service \ - quagga.logrotate quagga.pam quagga.pam.stack quagga.spec \ + quagga.logrotate quagga.pam quagga.spec \ quagga.sysconfig ripd.init ripd.service ripngd.init ripngd.service \ watchquagga.init zebra.init zebra.service diff --git a/redhat/quagga.pam.stack b/redhat/quagga.pam.stack deleted file mode 100644 index 8ddc2bbe33..0000000000 --- a/redhat/quagga.pam.stack +++ /dev/null @@ -1,26 +0,0 @@ -#%PAM-1.0 -# - -##### if running quagga as root: -# Only allow root (and possibly wheel) to use this because enable access -# is unrestricted. -auth sufficient /lib/security/$ISA/pam_rootok.so - -# Uncomment the following line to implicitly trust users in the "wheel" group. -#auth sufficient /lib/security/$ISA/pam_wheel.so trust use_uid -# Uncomment the following line to require a user to be in the "wheel" group. -#auth required /lib/security/$ISA/pam_wheel.so use_uid -########################################################### - -# If using quagga privileges and with a seperate group for vty access, then -# access can be controlled via the vty access group, and pam can simply -# check for valid user/password, eg: -# -# only allow local users. -#auth required /lib/security/$ISA/pam_securetty.so -#auth required /lib/security/$ISA/pam_stack.so service=system-auth -#auth required /lib/security/$ISA/pam_nologin.so -#account required /lib/security/$ISA/pam_stack.so service=system-auth -#password required /lib/security/$ISA/pam_stack.so service=system-auth -#session required /lib/security/$ISA/pam_stack.so service=system-auth -#session optional /lib/security/$ISA/pam_console.so diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index a49f48096a..746922a03a 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -3,6 +3,9 @@ # Some can be overriden on rpmbuild commandline with: # rpmbuild --define 'variable value' # +# E.g. rpmbuild --define 'release_rev 02' may be useful if building +# rpms again and again on the same day, so the newer rpms can be installed. +# bumping the number each time. ####################### Quagga configure options ######################### # with-feature options @@ -14,7 +17,6 @@ %{!?with_tcp_zebra: %define with_tcp_zebra 0 } %{!?with_vtysh: %define with_vtysh 1 } %{!?with_pam: %define with_pam 1 } -%{!?with_ipv6: %define with_ipv6 1 } %{!?with_ospfclient: %define with_ospfclient 1 } %{!?with_ospfapi: %define with_ospfapi 1 } %{!?with_irdp: %define with_irdp 1 } @@ -51,14 +53,6 @@ # FC4 and 5 split texi2html out of tetex package. %define quagga_buildreqs %{expand:%{quagga_buildreqs}} texi2html -# pam_stack was deprecated in FC5 -# default to pam_stack, default should be changed later. -%if "%dist" == "fc4" || "%dist" == "fc3" -%define quagga_pam_source quagga.pam.stack -%else -%define quagga_pam_source quagga.pam -%endif - # man page probably needs groff for groff_ms macros %define quagga_buildreqs %{expand:%{quagga_buildreqs}} groff @@ -69,11 +63,7 @@ %{!?quagga_gid: %define quagga_gid 92 } %define daemon_list zebra ripd ospfd bgpd -%if %{with_ipv6} %define daemonv6_list ripngd ospf6d -%else -%define daemonv6_list "" -%endif %if %{with_isisd} %define daemon_other isisd @@ -161,9 +151,6 @@ developing OSPF-API and quagga applications. %if !%{with_shared} --disable-shared \ %endif -%if %{with_ipv6} - --enable-ipv6 \ -%endif %if %{with_snmp} --enable-snmp \ %endif @@ -247,7 +234,7 @@ for daemon in %{all_daemons} ; do $RPM_BUILD_ROOT/etc/rc.d/init.d/${daemon} fi done -install -m644 %{zeb_rh_src}/%{quagga_pam_source} \ +install -m644 %{zeb_rh_src}/quagga.pam \ $RPM_BUILD_ROOT/etc/pam.d/quagga install -m644 %{zeb_rh_src}/quagga.logrotate \ $RPM_BUILD_ROOT/etc/logrotate.d/quagga @@ -291,14 +278,10 @@ zebra_spec_add_service () zebra_spec_add_service zebrasrv 2600/tcp "zebra service" zebra_spec_add_service zebra 2601/tcp "zebra vty" zebra_spec_add_service ripd 2602/tcp "RIPd vty" -%if %{with_ipv6} zebra_spec_add_service ripngd 2603/tcp "RIPngd vty" -%endif zebra_spec_add_service ospfd 2604/tcp "OSPFd vty" zebra_spec_add_service bgpd 2605/tcp "BGPd vty" -%if %{with_ipv6} zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty" -%endif %if %{with_ospfapi} zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" %endif @@ -405,9 +388,10 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/ripd %{_sbindir}/bgpd %{_sbindir}/watchquagga -%if %{with_ipv6} %{_sbindir}/ripngd %{_sbindir}/ospf6d +%if %{with_pimd} +%{_sbindir}/pimd %endif %if %{with_isisd} %{_sbindir}/isisd @@ -448,6 +432,12 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Fri Sep 4 2015 Paul Jakma - %{version} +- package the pimd binary +- remove with_ipv6 conditionals, always build v6 +- Fix UTF-8 char in spec changelog +- remove quagga.pam.stack, long deprecated. + * Fri Sep 4 2015 Paul Jakma - %{version} - buildreq updates - add a default define for with_pimd @@ -584,7 +574,7 @@ rm -rf $RPM_BUILD_ROOT * Thu Aug 09 2001 Elliot Lee 0.91a-6 - Fix bug #51336 -* Wed Aug 1 2001 Trond Eivind Glomsrřd 0.91a-5 +* Wed Aug 1 2001 Trond Eivind Glomsrød 0.91a-5 - Use generic initscript strings instead of initscript specific ( "Starting foo: " -> "Starting $prog:" ) From 3144257787e69c960fa6c4bbb8b6f06199bf41e8 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 29 Oct 2015 22:15:42 -0700 Subject: [PATCH 009/226] distro/redhat: Update to support CentOS/RHEL/Fedora, upstart/init/systemd * redhat/quagga.spec.in: Update to support CentOS, RHEL and Fedora, and support the various init systems across different versions of these distros, e.g. upstart/init/systemd. Clean up various warnings from rpmlint. Remove configure options that are gone. A few edits and commit message by: Paul Jakma / (cherry picked from commit a5efdb60905049e1224a020b78dd9699bdd15b29) Conflicts: redhat/Makefile.am --- redhat/Makefile.am | 3 +- redhat/README.rpm_build.md | 128 +++++++++++ redhat/quagga.spec.in | 437 +++++++++++++++++++++++++------------ 3 files changed, 423 insertions(+), 145 deletions(-) create mode 100644 redhat/README.rpm_build.md diff --git a/redhat/Makefile.am b/redhat/Makefile.am index 3ec1fb73ac..695d7eae84 100644 --- a/redhat/Makefile.am +++ b/redhat/Makefile.am @@ -3,4 +3,5 @@ EXTRA_DIST = bgpd.init bgpd.service isisd.init \ isisd.service ospf6d.init ospf6d.service ospfd.init ospfd.service \ quagga.logrotate quagga.pam quagga.spec \ quagga.sysconfig ripd.init ripd.service ripngd.init ripngd.service \ - watchquagga.init zebra.init zebra.service + watchquagga.init zebra.init zebra.service \ + README.rpm_build.md diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md new file mode 100644 index 0000000000..3e8fa05306 --- /dev/null +++ b/redhat/README.rpm_build.md @@ -0,0 +1,128 @@ +Building your own Quagga RPM +============================ +(Tested on CentOS 6, CentOS 7 and Fedora 22.) + +1. Install the following packages to build the RPMs: + + yum install git autoconf automake libtool make gawk readline-devel \ + texinfo dejagnu net-snmp-devel groff rpm-build net-snmp-devel \ + libcap-devel texi2html + + (use `dnf install` on new Fedora instead of `yum install `) + +2. Checkout Quagga under a **unpriviledged** user account + + git clone git://git.savannah.nongnu.org/quagga.git quagga + +3. Run Bootstrap and make distribution tar.gz + + cd quagga + ./bootstrap.sh + ./configure --with-pkg-extra-version=-MyRPMVersion + make dist + + Note: configure parameters are not important for the RPM building - except the + `with-pkg-extra-version` if you want to give the RPM a specific name to + mark your own unoffical build + +4. Create RPM directory structure and populate with sources + + mkdir rpmbuild + mkdir rpmbuild/SOURCES + mkdir rpmbuild/SPECS + cp redhat/*.spec rpmbuild/SPECS/ + cp quagga*.tar.gz rpmbuild/SOURCES/ + +5. Edit rpm/SPECS/quagga.spec with configuration as needed + Look at the beginning of the file and adjust the following parameters to enable + or disable features as required: + + ################# Quagga configure options #################### + # with-feature options + %{!?with_snmp: %global with_snmp 1 } + %{!?with_vtysh: %global with_vtysh 1 } + %{!?with_ospf_te: %global with_ospf_te 1 } + %{!?with_opaque_lsa: %global with_opaque_lsa 1 } + %{!?with_tcp_zebra: %global with_tcp_zebra 0 } + %{!?with_vtysh: %global with_vtysh 1 } + %{!?with_pam: %global with_pam 1 } + %{!?with_ospfclient: %global with_ospfclient 1 } + %{!?with_ospfapi: %global with_ospfapi 1 } + %{!?with_irdp: %global with_irdp 1 } + %{!?with_rtadv: %global with_rtadv 1 } + %{!?with_isisd: %global with_isisd 1 } + %{!?with_pimd: %global with_pimd 1 } + %{!?with_shared: %global with_shared 1 } + %{!?with_multipath: %global with_multipath 64 } + %{!?quagga_user: %global quagga_user quagga } + %{!?vty_group: %global vty_group quaggavt } + %{!?with_fpm: %global with_fpm 0 } + %{!?with_watchquagga: %global with_watchquagga 1 } + +6. Build the RPM + + rpmbuild --define "_topdir `pwd`/rpmbuild" -ba rpmbuild/SPECS/quagga.spec + +DONE. + +If all works correctly, then you should end up with the RPMs under `rpmbuild/RPMS` +and the Source RPM under `rpmbuild/SRPMS` + + +Enabling daemons after installation of the package: +--------------------------------------------------- + +### init.d based systems (ie CentOS 6): + +1. Enable the daemons as needed to run after boot (Zebra is mandatory) + + chkconfig zebra on + chkconfig ospfd on + chkconfig ospf6d on + chkconfig bgpd on + ... etc + +2. If you want to run `watchquagga`, then configure `/etc/sysconfig/quagga` + and uncomment the line with the daemons for `watchquagga` to monitor, + then enable watchquagga + + chkconfig watchquagga on + +3. Check your firewall / IPtables to make sure the routing protocols are +allowed. + +4. Start the daemons (or reboot) + + service zebra start + service bgpd start + service ospfd start + ... etc + +Configuration is stored in `/etc/quagga/*.conf` files. + + +### systemd based systems (ie CentOS 7, Fedora 22) + +1. Enable the daemons as needed to run after boot (Zebra is mandatory) + + systemctl enable zebra + systemctl enable ospfd + systemctl enable ospf6d + systemctl enable bgpd + ... etc + + Note: There is no watchquagga on systemd based systems. Systemd contains + the functionality of monitoring and restarting daemons. + +2. Check your firewall / IPtables to make sure the routing protocols are +allowed. + +3. Start the daemons (or reboot) + + systemctl start zebra + systemctl start bgpd + systemctl start ospfd + ... etc + +Configuration is stored in `/etc/quagga/*.conf` files. + diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index 746922a03a..13fdc07983 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -2,6 +2,7 @@ # # Some can be overriden on rpmbuild commandline with: # rpmbuild --define 'variable value' +# (use any value, ie 1 for flag "with_XXXX" definitions) # # E.g. rpmbuild --define 'release_rev 02' may be useful if building # rpms again and again on the same day, so the newer rpms can be installed. @@ -9,107 +10,141 @@ ####################### Quagga configure options ######################### # with-feature options -%{!?with_snmp: %define with_snmp 1 } -%{!?with_vtysh: %define with_vtysh 1 } -%{!?with_ospf_te: %define with_ospf_te 1 } -%{!?with_nssa: %define with_nssa 1 } -%{!?with_opaque_lsa: %define with_opaque_lsa 1 } -%{!?with_tcp_zebra: %define with_tcp_zebra 0 } -%{!?with_vtysh: %define with_vtysh 1 } -%{!?with_pam: %define with_pam 1 } -%{!?with_ospfclient: %define with_ospfclient 1 } -%{!?with_ospfapi: %define with_ospfapi 1 } -%{!?with_irdp: %define with_irdp 1 } -%{!?with_rtadv: %define with_rtadv 1 } -%{!?with_isisd: %define with_isisd 1 } -%{!?with_pimd: %define with_pimd 1 } -%{!?with_shared: %define with_shared 1 } -%{!?with_multipath: %define with_multipath 64 } -%{!?quagga_user: %define quagga_user quagga } -%{!?vty_group: %define vty_group quaggavty } +%{!?with_snmp: %global with_snmp 1 } +%{!?with_vtysh: %global with_vtysh 1 } +%{!?with_tcp_zebra: %global with_tcp_zebra 0 } +%{!?with_vtysh: %global with_vtysh 1 } +%{!?with_pam: %global with_pam 1 } +%{!?with_ospfclient: %global with_ospfclient 1 } +%{!?with_ospfapi: %global with_ospfapi 1 } +%{!?with_irdp: %global with_irdp 1 } +%{!?with_rtadv: %global with_rtadv 1 } +%{!?with_isisd: %global with_isisd 1 } +%{!?with_pimd: %global with_pimd 1 } +%{!?with_shared: %global with_shared 1 } +%{!?with_multipath: %global with_multipath 64 } +%{!?quagga_user: %global quagga_user quagga } +%{!?vty_group: %global vty_group quaggavt } +%{!?with_fpm: %global with_fpm 0 } +%{!?with_watchquagga: %global with_watchquagga 1 } # path defines %define _sysconfdir /etc/quagga -%define zeb_src %{_builddir}/%{name}-%{version} +%define zeb_src %{_builddir}/%{name}-%{quaggaversion} %define zeb_rh_src %{zeb_src}/redhat %define zeb_docs %{zeb_src}/doc # defines for configure -%define _libexecdir %{_exec_prefix}/libexec/quagga -%define _libdir %{_exec_prefix}/%{_lib}/quagga -%define _includedir %{_prefix}/include %define _localstatedir /var/run/quagga ############################################################################ -####################### distro specific tweaks ############################# -# default distro. Override with rpmbuild -D "dist XXX" -%{expand: %%define default_dist %(rpm -q --qf 'fc%%{VERSION}' fedora-release | grep -v 'not installed')} -%{!?dist: %define dist %{default_dist}} +#### Version String tweak +# Remove invalid characters form version string and replace with _ +%{expand: %%define rpmversion %(echo '@VERSION@' | tr [:blank:]- _ )} +%define quaggaversion @VERSION@ -# as distros change packages we depend on, our Requires have to change, sadly. -%define quagga_buildreqs texi2html texinfo autoconf pam-devel -%define quagga_buildreqs %{expand:%{quagga_buildreqs}} patch libcap-devel +#### Check version of texi2html +# Old versions don't support "--number-footnotes" option. +%{expand: %%global texi2htmlversion %(rpm -q --qf '%%{VERSION}' texi2html | cut -d. -f1 )} -# FC4 and 5 split texi2html out of tetex package. -%define quagga_buildreqs %{expand:%{quagga_buildreqs}} texi2html +#### Check for systemd or init.d (upstart) +# Check for init.d (upstart) as used in CentOS 6 or systemd (ie CentOS 7) +%{expand: %%global initsystem %(if [[ `/sbin/init --version 2> /dev/null` =~ upstart ]]; then echo upstart; elif [[ `systemctl` =~ -\.mount ]]; then echo systemd; fi)} +# +# If init system is systemd, then always disable watchquagga +# +%if "%{initsystem}" == "systemd" + # Note: For systems with systemd, watchquagga will NOT be built. Systemd + # takes over the role of restarting crashed processes. Value will + # be overwritten with 0 below for systemd independent on the setting here + %global with_watchquagga 0 +%endif -# man page probably needs groff for groff_ms macros -%define quagga_buildreqs %{expand:%{quagga_buildreqs}} groff - -############################################################################ +# if FPM is enabled, then enable tcp_zebra as well +# +%if %{with_fpm} + %global with_tcp_zebra 1 +%endif # misc internal defines %{!?quagga_uid: %define quagga_uid 92 } %{!?quagga_gid: %define quagga_gid 92 } +%{!?vty_gid: %define vty_gid 85 } + %define daemon_list zebra ripd ospfd bgpd %define daemonv6_list ripngd ospf6d %if %{with_isisd} -%define daemon_other isisd +%define daemon_isisd isisd %else -%define daemon_other "" +%define daemon_isisd "" %endif -%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_other} watchquagga +%if %{with_pimd} +%define daemon_pimd pimd +%else +%define daemon_pimd "" +%endif + +%if %{with_watchquagga} +%define daemon_watchquagga watchquagga +%else +%define daemon_watchquagga "" +%endif + +%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_isisd} %{daemon_pimd} %{daemon_watchquagga} # allow build dir to be kept -%{!?keep_build: %define keep_build 0 } +%{!?keep_build: %global keep_build 0 } #release sub-revision (the two digits after the CONFDATE) %{!?release_rev: %define release_rev 01 } Summary: Routing daemon -Name: quagga -Version: @VERSION@ -Release: @CONFDATE@%{release_rev} -License: GPL -Group: System Environment/Daemons -Source0: http://www.quagga.net/snapshots/cvs/%{name}-%{version}.tar.gz -URL: http://www.quagga.net +Name: quagga +Version: %{rpmversion} +Release: @CONFDATE@%{release_rev}%{?dist} +License: GPLv2+ +Group: System Environment/Daemons +Source0: http://download.savannah.gnu.org/releases/quagga/%{name}-%{quaggaversion}.tar.gz +URL: http://www.quagga.net +Requires: ncurses +Requires(pre): /sbin/install-info +Requires(preun): /sbin/install-info +Requires(post): /sbin/install-info +BuildRequires: texi2html texinfo autoconf patch libcap-devel groff %if %{with_snmp} BuildRequires: net-snmp-devel -Requires(pre): net-snmp +Requires: net-snmp %endif %if %{with_vtysh} BuildRequires: readline readline-devel ncurses ncurses-devel -Requires(pre): ncurses +Requires: ncurses %endif -BuildRequires: %{quagga_buildreqs} +%if %{with_pam} +BuildRequires: pam-devel +Requires: pam +%endif +%if "%{initsystem}" == "systemd" +BuildRequires: systemd +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +%else # Initscripts > 5.60 is required for IPv6 support Requires(pre): initscripts >= 5.60 -Requires(pre): ncurses pam -Requires(pre): /sbin/install-info -Provides: routingdaemon -BuildRoot: %{_tmppath}/%{name}-%{version}-root -Obsoletes: bird gated mrt zebra +%endif +Provides: routingdaemon = %{version}-%{release} +BuildRoot: %{_tmppath}/%{name}-%{version}-root +Obsoletes: bird gated mrt zebra quagga-sysvinit %description Quagga is a free software that manages TCP/IP based routing protocol. It takes multi-server and multi-thread approach to resolve the current complexity of the Internet. -Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, and RIPng. +Quagga supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng and PIM. Quagga is intended to be used as a Route Server and a Route Reflector. It is not a toolkit, it provides full routing power under a new architecture. @@ -127,13 +162,14 @@ Contributed/3rd party tools which may be of use with quagga. %package devel Summary: Header and object files for quagga development Group: System Environment/Daemons +Requires: %{name} = %{version}-%{release} %description devel The quagga-devel package contains the header and object files neccessary for developing OSPF-API and quagga applications. %prep -%setup -q +%setup -q -n quagga-%{quaggaversion} %build @@ -148,6 +184,11 @@ developing OSPF-API and quagga applications. #CFLAGS="${CFLAGS} -Wpacked -Wpadded" %configure \ + --sysconfdir=%{_sysconfdir} \ + --libdir=%{_libdir} \ + --libexecdir=%{_libexecdir} \ + --localstatedir=%{_localstatedir} \ + --disable-werror \ %if !%{with_shared} --disable-shared \ %endif @@ -160,15 +201,6 @@ developing OSPF-API and quagga applications. %if %{with_tcp_zebra} --enable-tcp-zebra \ %endif -%if %{with_nssa} - --enable-nssa \ -%endif -%if %{with_opaque_lsa} - --enable-opaque-lsa \ -%endif -%if %{with_ospf_te} - --enable-ospf-te \ -%endif %if %{with_vtysh} --enable-vtysh \ %endif @@ -200,57 +232,79 @@ developing OSPF-API and quagga applications. %if %{with_pam} --with-libpam \ %endif -%if %quagga_user +%if 0%{?quagga_user:1} --enable-user=%quagga_user \ --enable-group=%quagga_user \ %endif -%if %vty_group +%if 0%{?vty_group:1} --enable-vty-group=%vty_group \ %endif ---enable-netlink --enable-gcc-rdynamic +%if %{with_fpm} + --enable-fpm \ +%else + --disable-fpm \ +%endif +%if %{with_watchquagga} + --enable-watchquagga \ +%else + --disable-watchquagga \ +%endif + --enable-gcc-rdynamic make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" pushd doc +%if %{texi2htmlversion} < 5 +texi2html --number-sections quagga.texi +%else texi2html --number-footnotes --number-sections quagga.texi +%endif popd %install -rm -rf $RPM_BUILD_ROOT - -install -d $RPM_BUILD_ROOT/etc/{rc.d/init.d,sysconfig,logrotate.d,pam.d} \ - $RPM_BUILD_ROOT/var/log/quagga $RPM_BUILD_ROOT%{_infodir} - -make install \ - DESTDIR=$RPM_BUILD_ROOT +mkdir -p %{buildroot}/etc/{quagga,sysconfig,logrotate.d,pam.d} \ + %{buildroot}/var/log/quagga %{buildroot}%{_infodir} +make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install # Remove this file, as it is uninstalled and causes errors when building on RH9 -rm -rf $RPM_BUILD_ROOT/usr/share/info/dir +rm -rf %{buildroot}/usr/share/info/dir -# install etc sources +# install /etc sources +%if "%{initsystem}" == "systemd" +mkdir -p %{buildroot}%{_unitdir} +for daemon in %{all_daemons} ; do + if [ x"${daemon}" != x"" ] ; then + install %{zeb_rh_src}/${daemon}.service \ + %{buildroot}%{_unitdir}/${daemon}.service + fi +done +%else +mkdir -p %{buildroot}/etc/rc.d/init.d for daemon in %{all_daemons} ; do if [ x"${daemon}" != x"" ] ; then install %{zeb_rh_src}/${daemon}.init \ - $RPM_BUILD_ROOT/etc/rc.d/init.d/${daemon} + %{buildroot}/etc/rc.d/init.d/${daemon} fi done +%endif + install -m644 %{zeb_rh_src}/quagga.pam \ - $RPM_BUILD_ROOT/etc/pam.d/quagga + %{buildroot}/etc/pam.d/quagga install -m644 %{zeb_rh_src}/quagga.logrotate \ - $RPM_BUILD_ROOT/etc/logrotate.d/quagga + %{buildroot}/etc/logrotate.d/quagga install -m644 %{zeb_rh_src}/quagga.sysconfig \ - $RPM_BUILD_ROOT/etc/sysconfig/quagga -install -d -m750 $RPM_BUILD_ROOT/var/run/quagga + %{buildroot}/etc/sysconfig/quagga +install -d -m750 %{buildroot}/var/run/quagga %pre # add vty_group -%if %vty_group +%if 0%{?vty_group:1} if getent group %vty_group > /dev/null ; then : ; else \ - /usr/sbin/groupadd -r %vty_group > /dev/null || : ; fi + /usr/sbin/groupadd -r -g %vty_gid %vty_group > /dev/null || : ; fi %endif # add quagga user and group -%if %quagga_user +%if 0%{?quagga_user:1} # Ensure that quagga_gid gets correctly allocated if getent group %quagga_user >/dev/null; then : ; else \ /usr/sbin/groupadd -g %quagga_gid %quagga_user > /dev/null || : ; \ @@ -289,77 +343,145 @@ zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" zebra_spec_add_service isisd 2608/tcp "ISISd vty" %endif -for daemon in %daemon_list ; do +%if "%{initsystem}" == "systemd" +for daemon in %all_daemons ; do + %systemd_post ${daemon}.service +done +%else +for daemon in %all_daemons ; do /sbin/chkconfig --add ${daemon} done +%endif /sbin/install-info %{_infodir}/quagga.info.gz %{_infodir}/dir # Create dummy files if they don't exist so basic functions can be used. if [ ! -e %{_sysconfdir}/zebra.conf ]; then echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf -%if %{quagga_user} - chown %quagga_user:%quagga_user %{_sysconfdir}/zebra.conf +%if 0%{?quagga_user:1} + chown %quagga_user:%quagga_user %{_sysconfdir}/zebra.conf* %endif chmod 640 %{_sysconfdir}/zebra.conf fi +for daemon in %{all_daemons} ; do + if [ ! -e %{_sysconfdir}/${daemon}.conf ]; then + touch %{_sysconfdir}/${daemon}.conf + %if 0%{?quagga_user:1} + chown %quagga_user:%quagga_user %{_sysconfdir}/${daemon}.conf* + %endif + fi +done +%if %{with_watchquagga} + # No config for watchquagga - this is part of /etc/sysconfig/quagga + rm -f %{_sysconfdir}/watchquagga.* +%endif + if [ ! -e %{_sysconfdir}/vtysh.conf ]; then touch %{_sysconfdir}/vtysh.conf chmod 640 %{_sysconfdir}/vtysh.conf +%if 0%{?vty_group:1} + chown quagga:%{vty_group} %{_sysconfdir}/vtysh.conf* +%endif fi %postun if [ "$1" -ge 1 ]; then # Find out which daemons need to be restarted. for daemon in %all_daemons ; do - if [ -f /var/lock/subsys/$daemon ]; then - eval restart_$daemon=yes + if [ -f /var/lock/subsys/${daemon} ]; then + eval restart_${daemon}=yes else - eval restart_$daemon=no + eval restart_${daemon}=no fi done # Rename restart flags for daemons handled specially. running_zebra="$restart_zebra" restart_zebra=no - running_watchquagga="$restart_watchquagga" - restart_watchquagga=no - # Stop watchquagga first. - [ "$running_watchquagga" = yes ] && \ - /etc/rc.d/init.d/watchquagga stop >/dev/null 2>&1 - # Stop all daemons other than zebra and watchquagga. - for daemon in %all_daemons ; do - eval restart=\$restart_${daemon} - [ "$restart" = yes ] && \ - /etc/rc.d/init.d/$daemon stop >/dev/null 2>&1 - done - # Restart zebra. - [ "$running_zebra" = yes ] && \ - /etc/rc.d/init.d/zebra restart >/dev/null 2>&1 - # Start all daemons other than zebra and watchquagga. - for daemon in %all_daemons ; do - eval restart=\$restart_${daemon} - [ "$restart" = yes ] && \ - /etc/rc.d/init.d/$daemon start >/dev/null 2>&1 - done - # Start watchquagga last. - # Avoid postun scriptlet error if watchquagga is not running. - [ "$running_watchquagga" = yes ] && \ - /etc/rc.d/init.d/watchquagga start >/dev/null 2>&1 || : + %if %{with_watchquagga} + running_watchquagga="$restart_watchquagga" + restart_watchquagga=no + %endif + + %if "%{initsystem}" == "systemd" + ## + ## Systemd Version + ## + # No watchquagga for systemd version + # + # Stop all daemons other than zebra. + for daemon in %all_daemons ; do + eval restart=\$restart_${daemon} + [ "$restart" = yes ] && \ + %systemd_postun ${daemon}.service + done + # Restart zebra. + [ "$running_zebra" = yes ] && \ + %systemd_postun_with_restart $daemon.service + # Start all daemons other than zebra. + for daemon in %all_daemons ; do + eval restart=\$restart_${daemon} + [ "$restart" = yes ] && \ + %systemd_post ${daemon}.service + done + %else + ## + ## init.d Version + ## + %if %{with_watchquagga} + # Stop watchquagga first. + [ "$running_watchquagga" = yes ] && \ + /etc/rc.d/init.d/watchquagga stop >/dev/null 2>&1 + %endif + # Stop all daemons other than zebra and watchquagga. + for daemon in %all_daemons ; do + eval restart=\$restart_${daemon} + [ "$restart" = yes ] && \ + /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1 + done + # Restart zebra. + [ "$running_zebra" = yes ] && \ + /etc/rc.d/init.d/zebra restart >/dev/null 2>&1 + # Start all daemons other than zebra and watchquagga. + for daemon in %all_daemons ; do + eval restart=\$restart_${daemon} + [ "$restart" = yes ] && \ + /etc/rc.d/init.d/${daemon} start >/dev/null 2>&1 + done + %if %{with_watchquagga} + # Start watchquagga last. + # Avoid postun scriptlet error if watchquagga is not running. + [ "$running_watchquagga" = yes ] && \ + /etc/rc.d/init.d/watchquagga start >/dev/null 2>&1 || : + %endif + %endif fi -/sbin/install-info --delete %{_infodir}/quagga.info.gz %{_infodir}/dir %preun -if [ "$1" = "0" ]; then - for daemon in %all_daemons ; do - /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1 - /sbin/chkconfig --del ${daemon} - done - /sbin/install-info --delete %{_infodir}/quagga.info.gz %{_infodir}/dir -fi +%if "%{initsystem}" == "systemd" + ## + ## Systemd Version + ## + if [ "$1" = "0" ]; then + for daemon in %all_daemons ; do + %systemd_preun ${daemon}.service + done + fi +%else + ## + ## init.d Version + ## + if [ "$1" = "0" ]; then + for daemon in %all_daemons ; do + /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1 + /sbin/chkconfig --del ${daemon} + done + fi +%endif +/sbin/install-info --delete %{_infodir}/quagga.info.gz %{_infodir}/dir %clean -%if !%{keep_build} -rm -rf $RPM_BUILD_ROOT +%if !0%{?keep_build:1} +rm -rf %{buildroot} %endif %files @@ -368,26 +490,27 @@ rm -rf $RPM_BUILD_ROOT %doc doc/quagga.html %doc doc/mpls %doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES TODO -%if %{quagga_user} +%if 0%{?quagga_user:1} %dir %attr(751,%quagga_user,%quagga_user) %{_sysconfdir} %dir %attr(750,%quagga_user,%quagga_user) /var/log/quagga %dir %attr(751,%quagga_user,%quagga_user) /var/run/quagga %else %dir %attr(750,root,root) %{_sysconfdir} %dir %attr(750,root,root) /var/log/quagga -%dir %attr(755,root,root) /usr/share/info %dir %attr(750,root,root) /var/run/quagga %endif -%if %{vty_group} +%if 0%{?vty_group:1} %attr(750,%quagga_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample %endif -%{_infodir}/*info* +%{_infodir}/quagga.info.gz %{_mandir}/man*/* %{_sbindir}/zebra %{_sbindir}/ospfd %{_sbindir}/ripd %{_sbindir}/bgpd -%{_sbindir}/watchquagga +%if %{with_watchquagga} + %{_sbindir}/watchquagga +%endif %{_sbindir}/ripngd %{_sbindir}/ospf6d %if %{with_pimd} @@ -396,17 +519,33 @@ rm -rf $RPM_BUILD_ROOT %if %{with_isisd} %{_sbindir}/isisd %endif -%dir %attr(755,root,root) %{_libdir} %if %{with_shared} -%dir %{_libdir} -%{_libdir}/lib*.so -%{_libdir}/lib*.so.* +%attr(755,root,root) %{_libdir}/lib*.so +%attr(755,root,root) %{_libdir}/lib*.so.* %endif %if %{with_vtysh} %{_bindir}/* %endif %config /etc/quagga/[!v]* -%config /etc/rc.d/init.d/* +%if "%{initsystem}" == "systemd" + %config %{_unitdir}/*.service +%else + %config /etc/rc.d/init.d/zebra + %if %{with_watchquagga} + %config /etc/rc.d/init.d/watchquagga + %endif + %config /etc/rc.d/init.d/ripd + %config /etc/rc.d/init.d/ospfd + %config /etc/rc.d/init.d/bgpd + %config /etc/rc.d/init.d/ripngd + %config /etc/rc.d/init.d/ospf6d + %if %{with_isisd} + %config /etc/rc.d/init.d/isisd + %endif + %if %{with_pimd} + %config /etc/rc.d/init.d/pimd + %endif +%endif %config(noreplace) /etc/sysconfig/quagga %config(noreplace) /etc/pam.d/quagga %config(noreplace) %attr(640,root,root) /etc/logrotate.d/* @@ -432,17 +571,27 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog -* Fri Sep 4 2015 Paul Jakma - %{version} -- package the pimd binary +* Thu Feb 11 2016 Paul Jakma - %{version} - remove with_ipv6 conditionals, always build v6 - Fix UTF-8 char in spec changelog - remove quagga.pam.stack, long deprecated. -* Fri Sep 4 2015 Paul Jakma - %{version} +* Thu Oct 22 2015 Martin Winter +- Cleanup configure: remove --enable-ipv6 (default now), --enable-nssa, + --enable-netlink +- Remove support for old fedora 4/5 +- Fix for package nameing +- Fix Weekdays of previous changelogs (bogus dates) +- Add conditional logic to only build tex footnotes with supported texi2html +- Added pimd to files section and fix double listing of /var/lib*/quagga +- Numerous fixes to unify upstart/systemd startup into same spec file +- Only allow use of watchquagga for non-systemd systems. no need with systemd + +* Fri Sep 4 2015 Paul Jakma - buildreq updates - add a default define for with_pimd -* Thu Sep 12 2005 Paul Jakma +* Mon Sep 12 2005 Paul Jakma - Steal some changes from Fedora spec file: - Add with_rtadv variable - Test for groups/users with getent before group/user adding @@ -495,7 +644,7 @@ rm -rf $RPM_BUILD_ROOT - add user with fixed UID/GID (RH) - create user with shell /sbin/nologin rather than /bin/false (RH) - stop daemons on uninstall (RH) -- delete info file on %preun, not %postun to avoid deletion on upgrade. (RH) +- delete info file on preun, not postun to avoid deletion on upgrade. (RH) - isisd added - cleanup tasks carried out for every daemon @@ -507,10 +656,10 @@ rm -rf $RPM_BUILD_ROOT - Renamed to Quagga - Sync to Quagga release 0.96 -* Tue Mar 20 2003 Paul Jakma +* Thu Mar 20 2003 Paul Jakma - zebra privileges support -* Mon Mar 18 2003 Paul Jakma +* Tue Mar 18 2003 Paul Jakma - Fix mem leak in 'show thread cpu' - Ralph Keller's OSPF-API - Amir: Fix configure.ac for net-snmp @@ -534,7 +683,7 @@ rm -rf $RPM_BUILD_ROOT - Added conditionals for building with(out) IPv6, vtysh, RIP, BGP - Fixed up some build requirements (patch) - Added conditional build requirements for vtysh / snmp -- Added conditional to %files for %_bindir depending on vtysh +- Added conditional to files for _bindir depending on vtysh * Mon Nov 11 2002 Paul Jakma - update to latest CVS @@ -574,7 +723,7 @@ rm -rf $RPM_BUILD_ROOT * Thu Aug 09 2001 Elliot Lee 0.91a-6 - Fix bug #51336 -* Wed Aug 1 2001 Trond Eivind Glomsrød 0.91a-5 +* Wed Aug 1 2001 Trond Eivind Glomsrød 0.91a-5 - Use generic initscript strings instead of initscript specific ( "Starting foo: " -> "Starting $prog:" ) From c161bb748218a54d24abbb84ffce61eede2c8f97 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 5 Jun 2016 16:39:31 -0400 Subject: [PATCH 010/226] redhat: Cleanup redhat options. Start the cleanup of the redhat .spec file: 1) Remove snmp, it's hopelessly broken. 2) Multiple with_vtysh lines. 3) Fix vty group to be quaggavty Signed-off-by: Donald Sharp --- redhat/quagga.spec.in | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index 13fdc07983..13d7606d1c 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -10,10 +10,8 @@ ####################### Quagga configure options ######################### # with-feature options -%{!?with_snmp: %global with_snmp 1 } %{!?with_vtysh: %global with_vtysh 1 } %{!?with_tcp_zebra: %global with_tcp_zebra 0 } -%{!?with_vtysh: %global with_vtysh 1 } %{!?with_pam: %global with_pam 1 } %{!?with_ospfclient: %global with_ospfclient 1 } %{!?with_ospfapi: %global with_ospfapi 1 } @@ -24,7 +22,7 @@ %{!?with_shared: %global with_shared 1 } %{!?with_multipath: %global with_multipath 64 } %{!?quagga_user: %global quagga_user quagga } -%{!?vty_group: %global vty_group quaggavt } +%{!?vty_group: %global vty_group quaggavty } %{!?with_fpm: %global with_fpm 0 } %{!?with_watchquagga: %global with_watchquagga 1 } @@ -114,10 +112,6 @@ Requires(pre): /sbin/install-info Requires(preun): /sbin/install-info Requires(post): /sbin/install-info BuildRequires: texi2html texinfo autoconf patch libcap-devel groff -%if %{with_snmp} -BuildRequires: net-snmp-devel -Requires: net-snmp -%endif %if %{with_vtysh} BuildRequires: readline readline-devel ncurses ncurses-devel Requires: ncurses @@ -192,9 +186,6 @@ developing OSPF-API and quagga applications. %if !%{with_shared} --disable-shared \ %endif -%if %{with_snmp} - --enable-snmp \ -%endif %if %{with_multipath} --enable-multipath=%{with_multipath} \ %endif From 75e801b7d9b6e810936213c39eefb35dd2b3713d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 5 Jun 2016 18:02:24 -0400 Subject: [PATCH 011/226] doc: Add quagga.1 to the distribution The quagga.1 file was not part of the distribution and was not being included in the dist tar ball which caused rpm builds to fail. Signed-off-by: Donald Sharp Conflicts: doc/Makefile.am --- doc/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index 96aee59d5c..36991bfa48 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -105,7 +105,7 @@ endif EXTRA_DIST = BGP-TypeCode draft-zebra-00.ms draft-zebra-00.txt \ bgpd.8 isisd.8 ospf6d.8 ospfclient.8 ospfd.8 ripd.8 \ - ripngd.8 vtysh.1 watchquagga.8 zebra.8 \ + ripngd.8 vtysh.1 watchquagga.8 zebra.8 quagga.1\ mpls/ChangeLog.opaque.txt mpls/cli_summary.txt \ mpls/opaque_lsa.txt mpls/ospfd.conf \ $(figures_sources) $(figures_png) $(figures_txt) From 8c05b72b5a3714b714f0883937f796fccc664955 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 5 Jun 2016 18:04:14 -0400 Subject: [PATCH 012/226] redhat: Cleanup some unneeded parameters In the Quagga.spec file we have these fixes: 1) rpmversion was being defined but never used in it's scope. Made it global so it couldbe properly referenced. 2) Use texi2html to tell you it's version instead of rpm Note for the future to convert to mock we will need to find a different methodology to handle this. 3) vtysh/isisd and pimd are turned on by default No need to call them out. Signed-off-by: Donald Sharp Conflicts: redhat/quagga.spec.in --- redhat/quagga.spec.in | 58 ++++++++++--------------------------------- 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index 13d7606d1c..c20b5597b0 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -10,15 +10,12 @@ ####################### Quagga configure options ######################### # with-feature options -%{!?with_vtysh: %global with_vtysh 1 } %{!?with_tcp_zebra: %global with_tcp_zebra 0 } %{!?with_pam: %global with_pam 1 } %{!?with_ospfclient: %global with_ospfclient 1 } %{!?with_ospfapi: %global with_ospfapi 1 } %{!?with_irdp: %global with_irdp 1 } %{!?with_rtadv: %global with_rtadv 1 } -%{!?with_isisd: %global with_isisd 1 } -%{!?with_pimd: %global with_pimd 1 } %{!?with_shared: %global with_shared 1 } %{!?with_multipath: %global with_multipath 64 } %{!?quagga_user: %global quagga_user quagga } @@ -38,12 +35,12 @@ #### Version String tweak # Remove invalid characters form version string and replace with _ -%{expand: %%define rpmversion %(echo '@VERSION@' | tr [:blank:]- _ )} +%{expand: %%global rpmversion %(echo '@VERSION@' | tr [:blank:]- _ )} %define quaggaversion @VERSION@ #### Check version of texi2html # Old versions don't support "--number-footnotes" option. -%{expand: %%global texi2htmlversion %(rpm -q --qf '%%{VERSION}' texi2html | cut -d. -f1 )} +%{expand: %%global texi2htmlversion %(/usr/bin/texi2html --version | cut -d. -f1)} #### Check for systemd or init.d (upstart) # Check for init.d (upstart) as used in CentOS 6 or systemd (ie CentOS 7) @@ -69,21 +66,7 @@ %{!?quagga_gid: %define quagga_gid 92 } %{!?vty_gid: %define vty_gid 85 } -%define daemon_list zebra ripd ospfd bgpd - -%define daemonv6_list ripngd ospf6d - -%if %{with_isisd} -%define daemon_isisd isisd -%else -%define daemon_isisd "" -%endif - -%if %{with_pimd} -%define daemon_pimd pimd -%else -%define daemon_pimd "" -%endif +%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospfd6d %if %{with_watchquagga} %define daemon_watchquagga watchquagga @@ -91,7 +74,7 @@ %define daemon_watchquagga "" %endif -%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_isisd} %{daemon_pimd} %{daemon_watchquagga} +%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_watchquagga} # allow build dir to be kept %{!?keep_build: %global keep_build 0 } @@ -112,10 +95,8 @@ Requires(pre): /sbin/install-info Requires(preun): /sbin/install-info Requires(post): /sbin/install-info BuildRequires: texi2html texinfo autoconf patch libcap-devel groff -%if %{with_vtysh} BuildRequires: readline readline-devel ncurses ncurses-devel Requires: ncurses -%endif %if %{with_pam} BuildRequires: pam-devel Requires: pam @@ -192,9 +173,7 @@ developing OSPF-API and quagga applications. %if %{with_tcp_zebra} --enable-tcp-zebra \ %endif -%if %{with_vtysh} --enable-vtysh \ -%endif %if %{with_ospfclient} --enable-ospfclient=yes \ %else @@ -215,11 +194,6 @@ developing OSPF-API and quagga applications. %else --enable-rtadv=no \ %endif -%if %{with_isisd} - --enable-isisd \ -%else - --disable-isisd \ -%endif %if %{with_pam} --with-libpam \ %endif @@ -240,7 +214,14 @@ developing OSPF-API and quagga applications. %else --disable-watchquagga \ %endif +<<<<<<< HEAD --enable-gcc-rdynamic +======= + --enable-gcc-rdynamic \ + --enable-isisd=yes \ + --enable-systemd=yes \ + --enable-poll=yes +>>>>>>> 5713748... rebase me make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" @@ -330,9 +311,7 @@ zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty" %if %{with_ospfapi} zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" %endif -%if %{with_isisd} zebra_spec_add_service isisd 2608/tcp "ISISd vty" -%endif %if "%{initsystem}" == "systemd" for daemon in %all_daemons ; do @@ -504,19 +483,12 @@ rm -rf %{buildroot} %endif %{_sbindir}/ripngd %{_sbindir}/ospf6d -%if %{with_pimd} -%{_sbindir}/pimd -%endif -%if %{with_isisd} %{_sbindir}/isisd -%endif %if %{with_shared} %attr(755,root,root) %{_libdir}/lib*.so %attr(755,root,root) %{_libdir}/lib*.so.* %endif -%if %{with_vtysh} %{_bindir}/* -%endif %config /etc/quagga/[!v]* %if "%{initsystem}" == "systemd" %config %{_unitdir}/*.service @@ -530,12 +502,8 @@ rm -rf %{buildroot} %config /etc/rc.d/init.d/bgpd %config /etc/rc.d/init.d/ripngd %config /etc/rc.d/init.d/ospf6d - %if %{with_isisd} - %config /etc/rc.d/init.d/isisd - %endif - %if %{with_pimd} - %config /etc/rc.d/init.d/pimd - %endif + %config /etc/rc.d/init.d/isisd + %config /etc/rc.d/init.d/pimd %endif %config(noreplace) /etc/sysconfig/quagga %config(noreplace) /etc/pam.d/quagga From 97da92655c3de967742564ca6d27485688fc61f1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 4 Jun 2016 19:55:21 -0400 Subject: [PATCH 013/226] configure: Ensure systemd development is present If a users specifies that they should use systemd then ensure that the systemd can be compiled against it. Signed-off-by: Donald Sharp Conflicts: configure.ac --- configure.ac | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 30fa7bd023..6719580976 100755 --- a/configure.ac +++ b/configure.ac @@ -328,10 +328,16 @@ if test x"${enable_time_check}" != x"no" ; then fi fi -if test "${enable_systemd}" = "yes" ; then - AC_DEFINE(HAVE_SYSTEMD,,Compile systemd support in) - LIBS="$LIBS -lsystemd " -fi +case "${enable_systemd}" in + "no") ;; + "yes") + AC_CHECK_LIB(systemd, sd_notify, LIBS="$LIBS -lsystemd") + if test $ac_cv_lib_systemd_sd_notify = no; then + AC_MSG_ERROR([enable systemd has been specified but systemd development env not found on your system]) + fi + ;; + "*") ;; +esac if test "${enable_poll}" = "yes" ; then AC_DEFINE(HAVE_POLL,,Compile systemd support in) From c2f4c19cdc46601a651d620fa78b8e0186b23f34 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 4 Jun 2016 19:55:22 -0400 Subject: [PATCH 014/226] configure: Auto pick-up the correct json env Fix the code to allow Quagga to automatically compile with the correct json library. Signed-off-by: Donald Sharp Conflicts: configure.ac --- configure.ac | 8 ++++++-- lib/json.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6719580976..78d3cda268 100755 --- a/configure.ac +++ b/configure.ac @@ -49,8 +49,6 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow AC_SUBST(pkgsrcdir) AC_SUBST(pkgsrcrcdir) -LIBS="$LIBS -L/usr/include/json/ -ljson" - dnl ------------ dnl Check CFLAGS dnl ------------ @@ -314,6 +312,12 @@ if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then CFLAGS="${CFLAGS} -Wpacked -Wpadded" fi +AC_CHECK_HEADERS(json-c/json.h) +AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c") +if test $ac_cv_lib_json_c_json_object_get = no; then + AC_MSG_ERROR([lib json is needed to compile]) +fi + if test x"${enable_gcc_rdynamic}" != x"no" ; then if test x"${enable_gcc_rdynamic}" = x"yes" -o x"$COMPILER" = x"GCC"; then LDFLAGS="${LDFLAGS} -rdynamic" diff --git a/lib/json.h b/lib/json.h index e69b10acd2..561f7cc405 100644 --- a/lib/json.h +++ b/lib/json.h @@ -22,7 +22,11 @@ #ifndef _QUAGGA_JSON_H #define _QUAGGA_JSON_H +#if defined(HAVE_JSON_C_JSON_H) +#include +#else #include +#endif extern int use_json(const int argc, const char *argv[]); extern void json_object_string_add(struct json_object* obj, const char *key, From 909344ea4006f9975336c1019c4a42ca47fcd952 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 4 Jun 2016 19:55:23 -0400 Subject: [PATCH 015/226] debian: Remove obsoleted configure options. configure.ac has moved on, catch debian up with it. Signed-off-by: Donald Sharp --- debian/rules | 8 -------- 1 file changed, 8 deletions(-) diff --git a/debian/rules b/debian/rules index 0b859d6585..e5e3ad8c11 100755 --- a/debian/rules +++ b/debian/rules @@ -38,13 +38,6 @@ override_dh_auto_configure: --sbindir=/usr/lib/quagga \ --sysconfdir=/etc/quagga \ $(USE_SNMP) \ - --enable-vtysh \ - --enable-isisd \ - --enable-watchquagga \ - --enable-ospf-te \ - --enable-opaque-lsa \ - --enable-ipv6 \ - --enable-ospfclient=yes \ --enable-ospfapi=yes \ --enable-multipath=256 \ --enable-user=quagga \ @@ -52,7 +45,6 @@ override_dh_auto_configure: --enable-vty-group=quaggavty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-werror \ --enable-gcc-rdynamic \ --with-libpam \ From fb8211bbae660361bd57bdf97e9f4deb0af5ceb9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 12:54:39 -0400 Subject: [PATCH 016/226] redhat: V6 compilation is on by default Let's not call it out as a separate item anymore. Signed-off-by: Donald Sharp (cherry picked from commit 341969b3db27bd384dc453ec0e6b4a9a6513ab8f) --- redhat/quagga.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index c20b5597b0..0e689b420a 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -74,7 +74,7 @@ %define daemon_watchquagga "" %endif -%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_watchquagga} +%define all_daemons %{daemon_list} %{daemon_watchquagga} # allow build dir to be kept %{!?keep_build: %global keep_build 0 } From 48eefa681673d6f3ccd7dc247fdae3487b2f5bd4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 19:00:24 -0400 Subject: [PATCH 017/226] redhat: Changes to allow Cumulus start/stop methodology Change the redhat .spec and control files to allow redhat systemd interaction to be the same as the debian style. This will allow users to use Quagga consistently across platforms. Signed-off-by: Donald Sharp Conflicts: redhat/Makefile.am --- redhat/Makefile.am | 8 +++---- redhat/bgpd.service | 14 ------------- redhat/isisd.service | 14 ------------- redhat/ospf6d.service | 14 ------------- redhat/ospfd.service | 14 ------------- redhat/quagga.spec.in | 49 +++++++++++++++++++++++-------------------- redhat/ripd.service | 14 ------------- redhat/ripngd.service | 14 ------------- redhat/zebra.service | 14 ------------- 9 files changed, 30 insertions(+), 125 deletions(-) delete mode 100644 redhat/bgpd.service delete mode 100644 redhat/isisd.service delete mode 100644 redhat/ospf6d.service delete mode 100644 redhat/ospfd.service delete mode 100644 redhat/ripd.service delete mode 100644 redhat/ripngd.service delete mode 100644 redhat/zebra.service diff --git a/redhat/Makefile.am b/redhat/Makefile.am index 695d7eae84..b52cc3150a 100644 --- a/redhat/Makefile.am +++ b/redhat/Makefile.am @@ -1,7 +1,7 @@ -EXTRA_DIST = bgpd.init bgpd.service isisd.init \ - isisd.service ospf6d.init ospf6d.service ospfd.init ospfd.service \ +EXTRA_DIST = bgpd.init isisd.init \ + ospf6d.init ospfd.init \ quagga.logrotate quagga.pam quagga.spec \ - quagga.sysconfig ripd.init ripd.service ripngd.init ripngd.service \ - watchquagga.init zebra.init zebra.service \ + quagga.sysconfig ripd.init ripngd.init \ + watchquagga.init zebra.init \ README.rpm_build.md diff --git a/redhat/bgpd.service b/redhat/bgpd.service deleted file mode 100644 index 5040284dbb..0000000000 --- a/redhat/bgpd.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=BGP routing daemon -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/bgpd.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/bgpd -d $BGPD_OPTS -f /etc/quagga/bgpd.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/isisd.service b/redhat/isisd.service deleted file mode 100644 index 4cdf67d67e..0000000000 --- a/redhat/isisd.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=IS-IS routing daemon -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/isisd.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/isisd -d $ISISD_OPTS -f /etc/quagga/isisd.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/ospf6d.service b/redhat/ospf6d.service deleted file mode 100644 index 3c9c466899..0000000000 --- a/redhat/ospf6d.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=OSPF routing daemon for IPv6 -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/ospf6d.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/ospf6d -d $OSPF6D_OPTS -f /etc/quagga/ospf6d.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/ospfd.service b/redhat/ospfd.service deleted file mode 100644 index 5e3de23935..0000000000 --- a/redhat/ospfd.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=OSPF routing daemon -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/ospfd.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/ospfd -d $OSPFD_OPTS -f /etc/quagga/ospfd.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index 0e689b420a..253fd7c0a0 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -11,13 +11,13 @@ ####################### Quagga configure options ######################### # with-feature options %{!?with_tcp_zebra: %global with_tcp_zebra 0 } -%{!?with_pam: %global with_pam 1 } +%{!?with_pam: %global with_pam 0 } %{!?with_ospfclient: %global with_ospfclient 1 } %{!?with_ospfapi: %global with_ospfapi 1 } %{!?with_irdp: %global with_irdp 1 } %{!?with_rtadv: %global with_rtadv 1 } %{!?with_shared: %global with_shared 1 } -%{!?with_multipath: %global with_multipath 64 } +%{!?with_multipath: %global with_multipath 256 } %{!?quagga_user: %global quagga_user quagga } %{!?vty_group: %global vty_group quaggavty } %{!?with_fpm: %global with_fpm 0 } @@ -25,9 +25,12 @@ # path defines %define _sysconfdir /etc/quagga +%define _sbindir /usr/lib/quagga %define zeb_src %{_builddir}/%{name}-%{quaggaversion} %define zeb_rh_src %{zeb_src}/redhat %define zeb_docs %{zeb_src}/doc +%define quagga_tools %{zeb_src}/tools +%define cumulus_dir %{zeb_src}/cumulus/etc # defines for configure %define _localstatedir /var/run/quagga @@ -52,7 +55,7 @@ # Note: For systems with systemd, watchquagga will NOT be built. Systemd # takes over the role of restarting crashed processes. Value will # be overwritten with 0 below for systemd independent on the setting here - %global with_watchquagga 0 + %global with_watchquagga 1 %endif # if FPM is enabled, then enable tcp_zebra as well @@ -62,9 +65,9 @@ %endif # misc internal defines -%{!?quagga_uid: %define quagga_uid 92 } -%{!?quagga_gid: %define quagga_gid 92 } -%{!?vty_gid: %define vty_gid 85 } +%{!?quagga_uid: %global quagga_uid 92 } +%{!?quagga_gid: %global quagga_gid 92 } +%{!?vty_gid: %global vty_gid 85 } %define daemon_list zebra ripd ospfd bgpd isisd ripngd ospfd6d @@ -80,7 +83,7 @@ %{!?keep_build: %global keep_build 0 } #release sub-revision (the two digits after the CONFDATE) -%{!?release_rev: %define release_rev 01 } +%{!?release_rev: %global release_rev 01 } Summary: Routing daemon Name: quagga @@ -159,6 +162,7 @@ developing OSPF-API and quagga applications. #CFLAGS="${CFLAGS} -Wpacked -Wpadded" %configure \ + --sbindir=%{_sbindir} \ --sysconfdir=%{_sysconfdir} \ --libdir=%{_libdir} \ --libexecdir=%{_libexecdir} \ @@ -214,14 +218,10 @@ developing OSPF-API and quagga applications. %else --disable-watchquagga \ %endif -<<<<<<< HEAD - --enable-gcc-rdynamic -======= --enable-gcc-rdynamic \ --enable-isisd=yes \ --enable-systemd=yes \ --enable-poll=yes ->>>>>>> 5713748... rebase me make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" @@ -234,22 +234,19 @@ texi2html --number-footnotes --number-sections quagga.texi popd %install -mkdir -p %{buildroot}/etc/{quagga,sysconfig,logrotate.d,pam.d} \ +mkdir -p %{buildroot}/etc/{quagga,sysconfig,logrotate.d,pam.d,default} \ %{buildroot}/var/log/quagga %{buildroot}%{_infodir} make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install # Remove this file, as it is uninstalled and causes errors when building on RH9 rm -rf %{buildroot}/usr/share/info/dir + # install /etc sources %if "%{initsystem}" == "systemd" mkdir -p %{buildroot}%{_unitdir} -for daemon in %{all_daemons} ; do - if [ x"${daemon}" != x"" ] ; then - install %{zeb_rh_src}/${daemon}.service \ - %{buildroot}%{_unitdir}/${daemon}.service - fi -done +install %{quagga_tools}/quagga.service \ + %{buildroot}%{_unitdir}/quagga.service %else mkdir -p %{buildroot}/etc/rc.d/init.d for daemon in %{all_daemons} ; do @@ -260,12 +257,13 @@ for daemon in %{all_daemons} ; do done %endif +install %{cumulus_dir}/quagga/debian.conf %{buildroot}/etc/quagga +install %{cumulus_dir}/quagga/daemons %{buildroot}/etc/quagga +install -m644 %{cumulus_dir}/default/quagga %{buildroot}/etc/default install -m644 %{zeb_rh_src}/quagga.pam \ %{buildroot}/etc/pam.d/quagga install -m644 %{zeb_rh_src}/quagga.logrotate \ %{buildroot}/etc/logrotate.d/quagga -install -m644 %{zeb_rh_src}/quagga.sysconfig \ - %{buildroot}/etc/sysconfig/quagga install -d -m750 %{buildroot}/var/run/quagga %pre @@ -315,7 +313,7 @@ zebra_spec_add_service isisd 2608/tcp "ISISd vty" %if "%{initsystem}" == "systemd" for daemon in %all_daemons ; do - %systemd_post ${daemon}.service + %systemd_post quagga.service done %else for daemon in %all_daemons ; do @@ -478,6 +476,11 @@ rm -rf %{buildroot} %{_sbindir}/ospfd %{_sbindir}/ripd %{_sbindir}/bgpd +%{_sbindir}/ssd +%{_sbindir}/quagga +%{_sbindir}/quagga-reload.py +%{_sbindir}/quagga-reload.pyc +%{_sbindir}/quagga-reload.pyo %if %{with_watchquagga} %{_sbindir}/watchquagga %endif @@ -491,7 +494,7 @@ rm -rf %{buildroot} %{_bindir}/* %config /etc/quagga/[!v]* %if "%{initsystem}" == "systemd" - %config %{_unitdir}/*.service + %config %{_unitdir}/quagga.service %else %config /etc/rc.d/init.d/zebra %if %{with_watchquagga} @@ -505,7 +508,7 @@ rm -rf %{buildroot} %config /etc/rc.d/init.d/isisd %config /etc/rc.d/init.d/pimd %endif -%config(noreplace) /etc/sysconfig/quagga +%config(noreplace) /etc/default/quagga %config(noreplace) /etc/pam.d/quagga %config(noreplace) %attr(640,root,root) /etc/logrotate.d/* diff --git a/redhat/ripd.service b/redhat/ripd.service deleted file mode 100644 index d35dc47a12..0000000000 --- a/redhat/ripd.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=RIP routing daemon -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/ripd.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/ripd -d $RIPD_OPTS -f /etc/quagga/ripd.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/ripngd.service b/redhat/ripngd.service deleted file mode 100644 index 567e88806c..0000000000 --- a/redhat/ripngd.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=RIP routing daemon for IPv6 -BindTo=zebra.service -After=syslog.target network.target zebra.service -ConditionPathExists=/etc/quagga/ripngd.conf - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/quagga -ExecStart=/usr/sbin/ripngd -d $RIPNGD_OPTS -f /etc/quagga/ripngd.conf -Restart=on-abort - -[Install] -WantedBy=network.target diff --git a/redhat/zebra.service b/redhat/zebra.service deleted file mode 100644 index 27c3a5229f..0000000000 --- a/redhat/zebra.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=GNU Zebra routing manager -After=syslog.target network.target -ConditionPathExists=/etc/quagga/zebra.conf - -[Service] -Type=forking -EnvironmentFile=-/etc/sysconfig/quagga -ExecStartPre=/sbin/ip route flush proto zebra -ExecStart=/usr/sbin/zebra -d $ZEBRA_OPTS -f /etc/quagga/zebra.conf -Restart=on-abort - -[Install] -WantedBy=network.target From 62cd657cddfb82b0f2efa1091817fee91bbd111a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 19:05:17 -0400 Subject: [PATCH 018/226] cumulus: Changes to make this code work for redhat Modify code base to allow rpm building. Signed-off-by: Donald Sharp --- cumulus/.gitignore | 2 + cumulus/Makefile.am | 5 + .../etc/default/quagga | 0 cumulus/start-stop-daemon.c | 1058 +++++++++++++++++ 4 files changed, 1065 insertions(+) create mode 100644 cumulus/.gitignore create mode 100644 cumulus/Makefile.am rename debian/quagga.default => cumulus/etc/default/quagga (100%) create mode 100644 cumulus/start-stop-daemon.c diff --git a/cumulus/.gitignore b/cumulus/.gitignore new file mode 100644 index 0000000000..2a198f5d45 --- /dev/null +++ b/cumulus/.gitignore @@ -0,0 +1,2 @@ +*.o +ssd diff --git a/cumulus/Makefile.am b/cumulus/Makefile.am new file mode 100644 index 0000000000..852af344af --- /dev/null +++ b/cumulus/Makefile.am @@ -0,0 +1,5 @@ + +sbin_PROGRAMS = ssd +EXTRA_DIST = etc/quagga/debian.conf etc/quagga/daemons etc/default/quagga + +ssd_SOURCES = start-stop-daemon.c diff --git a/debian/quagga.default b/cumulus/etc/default/quagga similarity index 100% rename from debian/quagga.default rename to cumulus/etc/default/quagga diff --git a/cumulus/start-stop-daemon.c b/cumulus/start-stop-daemon.c new file mode 100644 index 0000000000..e317bb801c --- /dev/null +++ b/cumulus/start-stop-daemon.c @@ -0,0 +1,1058 @@ +/* + * A rewrite of the original Debian's start-stop-daemon Perl script + * in C (faster - it is executed many times during system startup). + * + * Written by Marek Michalkiewicz , + * public domain. Based conceptually on start-stop-daemon.pl, by Ian + * Jackson . May be used and distributed + * freely for any purpose. Changes by Christian Schwarz + * , to make output conform to the Debian + * Console Message Standard, also placed in public domain. Minor + * changes by Klee Dienes , also placed in the Public + * Domain. + * + * Changes by Ben Collins , added --chuid, --background + * and --make-pidfile options, placed in public domain aswell. + * + * Port to OpenBSD by Sontri Tomo Huynh + * and Andreas Schuldei + * + * Changes by Ian Jackson: added --retry (and associated rearrangements). + * + * Modified for Gentoo rc-scripts by Donny Davies : + * I removed the BSD/Hurd/OtherOS stuff, added #include + * and stuck in a #define VERSION "1.9.18". Now it compiles without + * the whole automake/config.h dance. + */ + +#ifdef HAVE_LXC +#define _GNU_SOURCE +#include +#endif /* HAVE_LXC */ + +#include +#define VERSION "1.9.18" + +#define MIN_POLL_INTERVAL 20000 /*us*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int testmode = 0; +static int quietmode = 0; +static int exitnodo = 1; +static int start = 0; +static int stop = 0; +static int background = 0; +static int mpidfile = 0; +static int signal_nr = 15; +static const char *signal_str = NULL; +static int user_id = -1; +static int runas_uid = -1; +static int runas_gid = -1; +static const char *userspec = NULL; +static char *changeuser = NULL; +static const char *changegroup = NULL; +static char *changeroot = NULL; +static const char *cmdname = NULL; +static char *execname = NULL; +static char *startas = NULL; +static const char *pidfile = NULL; +static char what_stop[1024]; +static const char *schedule_str = NULL; +static const char *progname = ""; +static int nicelevel = 0; + +static struct stat exec_stat; + +struct pid_list { + struct pid_list *next; + pid_t pid; +}; + +static struct pid_list *found = NULL; +static struct pid_list *killed = NULL; + +struct schedule_item { + enum { sched_timeout, sched_signal, sched_goto, sched_forever } type; + int value; /* seconds, signal no., or index into array */ + /* sched_forever is only seen within parse_schedule and callees */ +}; + +static int schedule_length; +static struct schedule_item *schedule = NULL; + +LIST_HEAD(namespace_head, namespace); + +struct namespace { + LIST_ENTRY(namespace) list; + char *path; + int nstype; +}; + +static struct namespace_head namespace_head; + +static void *xmalloc(int size); +static void push(struct pid_list **list, pid_t pid); +static void do_help(void); +static void parse_options(int argc, char * const *argv); +static int pid_is_user(pid_t pid, uid_t uid); +static int pid_is_cmd(pid_t pid, const char *name); +static void check(pid_t pid); +static void do_pidfile(const char *name); +static void do_stop(int signal_nr, int quietmode, + int *n_killed, int *n_notkilled, int retry_nr); +static int pid_is_exec(pid_t pid, const struct stat *esb); + +#ifdef __GNUC__ +static void fatal(const char *format, ...) + __attribute__((noreturn, format(printf, 1, 2))); +static void badusage(const char *msg) + __attribute__((noreturn)); +#else +static void fatal(const char *format, ...); +static void badusage(const char *msg); +#endif + +/* This next part serves only to construct the TVCALC macro, which + * is used for doing arithmetic on struct timeval's. It works like this: + * TVCALC(result, expression); + * where result is a struct timeval (and must be an lvalue) and + * expression is the single expression for both components. In this + * expression you can use the special values TVELEM, which when fed a + * const struct timeval* gives you the relevant component, and + * TVADJUST. TVADJUST is necessary when subtracting timevals, to make + * it easier to renormalise. Whenver you subtract timeval elements, + * you must make sure that TVADJUST is added to the result of the + * subtraction (before any resulting multiplication or what have you). + * TVELEM must be linear in TVADJUST. + */ +typedef long tvselector(const struct timeval*); +static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; } +static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; } +#define TVCALC_ELEM(result, expr, sec, adj) \ +{ \ + const long TVADJUST = adj; \ + long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \ + (result).tv_##sec = (expr); \ +} +#define TVCALC(result,expr) \ +do { \ + TVCALC_ELEM(result, expr, sec, (-1)); \ + TVCALC_ELEM(result, expr, usec, (+1000000)); \ + (result).tv_sec += (result).tv_usec / 1000000; \ + (result).tv_usec %= 1000000; \ +} while(0) + + +static void +fatal(const char *format, ...) +{ + va_list arglist; + + fprintf(stderr, "%s: ", progname); + va_start(arglist, format); + vfprintf(stderr, format, arglist); + va_end(arglist); + putc('\n', stderr); + exit(2); +} + + +static void * +xmalloc(int size) +{ + void *ptr; + + ptr = malloc(size); + if (ptr) + return ptr; + fatal("malloc(%d) failed", size); +} + +static void +xgettimeofday(struct timeval *tv) +{ + if (gettimeofday(tv,0) != 0) + fatal("gettimeofday failed: %s", strerror(errno)); +} + +static void +push(struct pid_list **list, pid_t pid) +{ + struct pid_list *p; + + p = xmalloc(sizeof(*p)); + p->next = *list; + p->pid = pid; + *list = p; +} + +static void +clear(struct pid_list **list) +{ + struct pid_list *here, *next; + + for (here = *list; here != NULL; here = next) { + next = here->next; + free(here); + } + + *list = NULL; +} + +static char * +next_dirname(const char *s) +{ + char *cur; + + cur = (char *)s; + + if (*cur != '\0') { + for (; *cur != '/'; ++cur) + if (*cur == '\0') + return cur; + + for (; *cur == '/'; ++cur) + ; + } + + return cur; +} + +static void +add_namespace(const char *path) +{ + int nstype; + const char *nsdirname, *nsname, *cur; + struct namespace *namespace; + + cur = (char *)path; + nsdirname = nsname = ""; + + while ((cur = next_dirname(cur))[0] != '\0') { + nsdirname = nsname; + nsname = cur; + } + + if (!memcmp(nsdirname, "ipcns/", strlen("ipcns/"))) + nstype = CLONE_NEWIPC; + else if (!memcmp(nsdirname, "netns/", strlen("netns/"))) + nstype = CLONE_NEWNET; + else if (!memcmp(nsdirname, "utcns/", strlen("utcns/"))) + nstype = CLONE_NEWUTS; + else + badusage("invalid namepspace path"); + + namespace = xmalloc(sizeof(*namespace)); + namespace->path = (char *)path; + namespace->nstype = nstype; + LIST_INSERT_HEAD(&namespace_head, namespace, list); +} + +#ifdef HAVE_LXC +static void +set_namespaces() +{ + struct namespace *namespace; + int fd; + + LIST_FOREACH(namespace, &namespace_head, list) { + if ((fd = open(namespace->path, O_RDONLY)) == -1) + fatal("open namespace %s: %s", namespace->path, strerror(errno)); + if (setns(fd, namespace->nstype) == -1) + fatal("setns %s: %s", namespace->path, strerror(errno)); + } +} +#else +static void +set_namespaces() +{ + if (!LIST_EMPTY(&namespace_head)) + fatal("LCX namespaces not supported"); +} +#endif + +static void +do_help(void) +{ + printf( +"start-stop-daemon " VERSION " for Debian - small and fast C version written by\n" +"Marek Michalkiewicz , public domain.\n" +"\n" +"Usage:\n" +" start-stop-daemon -S|--start options ... -- arguments ...\n" +" start-stop-daemon -K|--stop options ...\n" +" start-stop-daemon -H|--help\n" +" start-stop-daemon -V|--version\n" +"\n" +"Options (at least one of --exec|--pidfile|--user is required):\n" +" -x|--exec program to start/check if it is running\n" +" -p|--pidfile pid file to check\n" +" -c|--chuid \n" +" change to this user/group before starting process\n" +" -u|--user | stop processes owned by this user\n" +" -n|--name stop processes with this name\n" +" -s|--signal signal to send (default TERM)\n" +" -a|--startas program to start (default is )\n" +" -N|--nicelevel add incr to the process's nice level\n" +" -b|--background force the process to detach\n" +" -m|--make-pidfile create the pidfile before starting\n" +" -R|--retry check whether processes die, and retry\n" +" -t|--test test mode, don't do anything\n" +" -o|--oknodo exit status 0 (not 1) if nothing done\n" +" -q|--quiet be more quiet\n" +" -v|--verbose be more verbose\n" +"Retry is |//... where is one of\n" +" -|[-] send that signal\n" +" wait that many seconds\n" +" forever repeat remainder forever\n" +"or may be just , meaning //KILL/\n" +"\n" +"Exit status: 0 = done 1 = nothing done (=> 0 if --oknodo)\n" +" 3 = trouble 2 = with --retry, processes wouldn't die\n"); +} + + +static void +badusage(const char *msg) +{ + if (msg) + fprintf(stderr, "%s: %s\n", progname, msg); + fprintf(stderr, "Try `%s --help' for more information.\n", progname); + exit(3); +} + +struct sigpair { + const char *name; + int signal; +}; + +const struct sigpair siglist[] = { + { "ABRT", SIGABRT }, + { "ALRM", SIGALRM }, + { "FPE", SIGFPE }, + { "HUP", SIGHUP }, + { "ILL", SIGILL }, + { "INT", SIGINT }, + { "KILL", SIGKILL }, + { "PIPE", SIGPIPE }, + { "QUIT", SIGQUIT }, + { "SEGV", SIGSEGV }, + { "TERM", SIGTERM }, + { "USR1", SIGUSR1 }, + { "USR2", SIGUSR2 }, + { "CHLD", SIGCHLD }, + { "CONT", SIGCONT }, + { "STOP", SIGSTOP }, + { "TSTP", SIGTSTP }, + { "TTIN", SIGTTIN }, + { "TTOU", SIGTTOU } +}; + +static int parse_integer (const char *string, int *value_r) { + unsigned long ul; + char *ep; + + if (!string[0]) + return -1; + + ul= strtoul(string,&ep,10); + if (ul > INT_MAX || *ep != '\0') + return -1; + + *value_r= ul; + return 0; +} + +static int parse_signal (const char *signal_str, int *signal_nr) +{ + unsigned int i; + + if (parse_integer(signal_str, signal_nr) == 0) + return 0; + + for (i = 0; i < sizeof (siglist) / sizeof (siglist[0]); i++) { + if (strcmp (signal_str, siglist[i].name) == 0) { + *signal_nr = siglist[i].signal; + return 0; + } + } + return -1; +} + +static void +parse_schedule_item(const char *string, struct schedule_item *item) { + const char *after_hyph; + + if (!strcmp(string,"forever")) { + item->type = sched_forever; + } else if (isdigit(string[0])) { + item->type = sched_timeout; + if (parse_integer(string, &item->value) != 0) + badusage("invalid timeout value in schedule"); + } else if ((after_hyph = string + (string[0] == '-')) && + parse_signal(after_hyph, &item->value) == 0) { + item->type = sched_signal; + } else { + badusage("invalid schedule item (must be [-], " + "-, or `forever'"); + } +} + +static void +parse_schedule(const char *schedule_str) { + char item_buf[20]; + const char *slash; + int count, repeatat; + ptrdiff_t str_len; + + count = 0; + for (slash = schedule_str; *slash; slash++) + if (*slash == '/') + count++; + + schedule_length = (count == 0) ? 4 : count+1; + schedule = xmalloc(sizeof(*schedule) * schedule_length); + + if (count == 0) { + schedule[0].type = sched_signal; + schedule[0].value = signal_nr; + parse_schedule_item(schedule_str, &schedule[1]); + if (schedule[1].type != sched_timeout) { + badusage ("--retry takes timeout, or schedule list" + " of at least two items"); + } + schedule[2].type = sched_signal; + schedule[2].value = SIGKILL; + schedule[3]= schedule[1]; + } else { + count = 0; + repeatat = -1; + while (schedule_str != NULL) { + slash = strchr(schedule_str,'/'); + str_len = slash ? slash - schedule_str : (ptrdiff_t)strlen(schedule_str); + if (str_len >= (ptrdiff_t)sizeof(item_buf)) + badusage("invalid schedule item: far too long" + " (you must delimit items with slashes)"); + memcpy(item_buf, schedule_str, str_len); + item_buf[str_len] = 0; + schedule_str = slash ? slash+1 : NULL; + + parse_schedule_item(item_buf, &schedule[count]); + if (schedule[count].type == sched_forever) { + if (repeatat >= 0) + badusage("invalid schedule: `forever'" + " appears more than once"); + repeatat = count; + continue; + } + count++; + } + if (repeatat >= 0) { + schedule[count].type = sched_goto; + schedule[count].value = repeatat; + count++; + } + assert(count == schedule_length); + } +} + +static void +parse_options(int argc, char * const *argv) +{ + static struct option longopts[] = { + { "help", 0, NULL, 'H'}, + { "stop", 0, NULL, 'K'}, + { "start", 0, NULL, 'S'}, + { "version", 0, NULL, 'V'}, + { "startas", 1, NULL, 'a'}, + { "name", 1, NULL, 'n'}, + { "oknodo", 0, NULL, 'o'}, + { "pidfile", 1, NULL, 'p'}, + { "quiet", 0, NULL, 'q'}, + { "signal", 1, NULL, 's'}, + { "test", 0, NULL, 't'}, + { "user", 1, NULL, 'u'}, + { "chroot", 1, NULL, 'r'}, + { "namespace", 1, NULL, 'd'}, + { "verbose", 0, NULL, 'v'}, + { "exec", 1, NULL, 'x'}, + { "chuid", 1, NULL, 'c'}, + { "nicelevel", 1, NULL, 'N'}, + { "background", 0, NULL, 'b'}, + { "make-pidfile", 0, NULL, 'm'}, + { "retry", 1, NULL, 'R'}, + { NULL, 0, NULL, 0} + }; + int c; + + for (;;) { + c = getopt_long(argc, argv, "HKSVa:n:op:qr:d:s:tu:vx:c:N:bmR:", + longopts, (int *) 0); + if (c == -1) + break; + switch (c) { + case 'H': /* --help */ + do_help(); + exit(0); + case 'K': /* --stop */ + stop = 1; + break; + case 'S': /* --start */ + start = 1; + break; + case 'V': /* --version */ + printf("start-stop-daemon " VERSION "\n"); + exit(0); + case 'a': /* --startas */ + startas = optarg; + break; + case 'n': /* --name */ + cmdname = optarg; + break; + case 'o': /* --oknodo */ + exitnodo = 0; + break; + case 'p': /* --pidfile */ + pidfile = optarg; + break; + case 'q': /* --quiet */ + quietmode = 1; + break; + case 's': /* --signal */ + signal_str = optarg; + break; + case 't': /* --test */ + testmode = 1; + break; + case 'u': /* --user | */ + userspec = optarg; + break; + case 'v': /* --verbose */ + quietmode = -1; + break; + case 'x': /* --exec */ + execname = optarg; + break; + case 'c': /* --chuid | */ + /* we copy the string just in case we need the + * argument later. */ + changeuser = strdup(optarg); + changeuser = strtok(changeuser, ":"); + changegroup = strtok(NULL, ":"); + break; + case 'r': /* --chroot /new/root */ + changeroot = optarg; + break; + case 'd': /* --namespace /.../||/name */ + add_namespace(optarg); + break; + case 'N': /* --nice */ + nicelevel = atoi(optarg); + break; + case 'b': /* --background */ + background = 1; + break; + case 'm': /* --make-pidfile */ + mpidfile = 1; + break; + case 'R': /* --retry | */ + schedule_str = optarg; + break; + default: + badusage(NULL); /* message printed by getopt */ + } + } + + if (signal_str != NULL) { + if (parse_signal (signal_str, &signal_nr) != 0) + badusage("signal value must be numeric or name" + " of signal (KILL, INTR, ...)"); + } + + if (schedule_str != NULL) { + parse_schedule(schedule_str); + } + + if (start == stop) + badusage("need one of --start or --stop"); + + if (!execname && !pidfile && !userspec && !cmdname) + badusage("need at least one of --exec, --pidfile, --user or --name"); + + if (!startas) + startas = execname; + + if (start && !startas) + badusage("--start needs --exec or --startas"); + + if (mpidfile && pidfile == NULL) + badusage("--make-pidfile is only relevant with --pidfile"); + + if (background && !start) + badusage("--background is only relevant with --start"); + +} + +static int +pid_is_exec(pid_t pid, const struct stat *esb) +{ + struct stat sb; + char buf[32]; + + sprintf(buf, "/proc/%d/exe", pid); + if (stat(buf, &sb) != 0) + return 0; + return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino); +} + + +static int +pid_is_user(pid_t pid, uid_t uid) +{ + struct stat sb; + char buf[32]; + + sprintf(buf, "/proc/%d", pid); + if (stat(buf, &sb) != 0) + return 0; + return (sb.st_uid == uid); +} + + +static int +pid_is_cmd(pid_t pid, const char *name) +{ + char buf[32]; + FILE *f; + int c; + + sprintf(buf, "/proc/%d/stat", pid); + f = fopen(buf, "r"); + if (!f) + return 0; + while ((c = getc(f)) != EOF && c != '(') + ; + if (c != '(') { + fclose(f); + return 0; + } + /* this hopefully handles command names containing ')' */ + while ((c = getc(f)) != EOF && c == *name) + name++; + fclose(f); + return (c == ')' && *name == '\0'); +} + + +static void +check(pid_t pid) +{ + if (execname && !pid_is_exec(pid, &exec_stat)) + return; + if (userspec && !pid_is_user(pid, user_id)) + return; + if (cmdname && !pid_is_cmd(pid, cmdname)) + return; + push(&found, pid); +} + +static void +do_pidfile(const char *name) +{ + FILE *f; + pid_t pid; + + f = fopen(name, "r"); + if (f) { + if (fscanf(f, "%d", &pid) == 1) + check(pid); + fclose(f); + } else if (errno != ENOENT) + fatal("open pidfile %s: %s", name, strerror(errno)); + +} + +/* WTA: this needs to be an autoconf check for /proc/pid existance. + */ +static void +do_procinit(void) +{ + DIR *procdir; + struct dirent *entry; + int foundany; + pid_t pid; + + procdir = opendir("/proc"); + if (!procdir) + fatal("opendir /proc: %s", strerror(errno)); + + foundany = 0; + while ((entry = readdir(procdir)) != NULL) { + if (sscanf(entry->d_name, "%d", &pid) != 1) + continue; + foundany++; + check(pid); + } + closedir(procdir); + if (!foundany) + fatal("nothing in /proc - not mounted?"); +} + +static void +do_findprocs(void) +{ + clear(&found); + + if (pidfile) + do_pidfile(pidfile); + else + do_procinit(); +} + +/* return 1 on failure */ +static void +do_stop(int signal_nr, int quietmode, int *n_killed, int *n_notkilled, int retry_nr) +{ + struct pid_list *p; + + do_findprocs(); + + *n_killed = 0; + *n_notkilled = 0; + + if (!found) + return; + + clear(&killed); + + for (p = found; p; p = p->next) { + if (testmode) + printf("Would send signal %d to %d.\n", + signal_nr, p->pid); + else if (kill(p->pid, signal_nr) == 0) { + push(&killed, p->pid); + (*n_killed)++; + } else { + printf("%s: warning: failed to kill %d: %s\n", + progname, p->pid, strerror(errno)); + (*n_notkilled)++; + } + } + if (quietmode < 0 && killed) { + printf("Stopped %s (pid", what_stop); + for (p = killed; p; p = p->next) + printf(" %d", p->pid); + putchar(')'); + if (retry_nr > 0) + printf(", retry #%d", retry_nr); + printf(".\n"); + } +} + + +static void +set_what_stop(const char *str) +{ + strncpy(what_stop, str, sizeof(what_stop)); + what_stop[sizeof(what_stop)-1] = '\0'; +} + +static int +run_stop_schedule(void) +{ + int r, position, n_killed, n_notkilled, value, ratio, anykilled, retry_nr; + struct timeval stopat, before, after, interval, maxinterval; + + if (testmode) { + if (schedule != NULL) { + printf("Ignoring --retry in test mode\n"); + schedule = NULL; + } + } + + if (cmdname) + set_what_stop(cmdname); + else if (execname) + set_what_stop(execname); + else if (pidfile) + sprintf(what_stop, "process in pidfile `%.200s'", pidfile); + else if (userspec) + sprintf(what_stop, "process(es) owned by `%.200s'", userspec); + else + fatal("internal error, please report"); + + anykilled = 0; + retry_nr = 0; + + if (schedule == NULL) { + do_stop(signal_nr, quietmode, &n_killed, &n_notkilled, 0); + if (n_notkilled > 0 && quietmode <= 0) + printf("%d pids were not killed\n", n_notkilled); + if (n_killed) + anykilled = 1; + goto x_finished; + } + + for (position = 0; position < schedule_length; ) { + value= schedule[position].value; + n_notkilled = 0; + + switch (schedule[position].type) { + + case sched_goto: + position = value; + continue; + + case sched_signal: + do_stop(value, quietmode, &n_killed, &n_notkilled, retry_nr++); + if (!n_killed) + goto x_finished; + else + anykilled = 1; + goto next_item; + + case sched_timeout: + /* We want to keep polling for the processes, to see if they've exited, + * or until the timeout expires. + * + * This is a somewhat complicated algorithm to try to ensure that we + * notice reasonably quickly when all the processes have exited, but + * don't spend too much CPU time polling. In particular, on a fast + * machine with quick-exiting daemons we don't want to delay system + * shutdown too much, whereas on a slow one, or where processes are + * taking some time to exit, we want to increase the polling + * interval. + * + * The algorithm is as follows: we measure the elapsed time it takes + * to do one poll(), and wait a multiple of this time for the next + * poll. However, if that would put us past the end of the timeout + * period we wait only as long as the timeout period, but in any case + * we always wait at least MIN_POLL_INTERVAL (20ms). The multiple + * (`ratio') starts out as 2, and increases by 1 for each poll to a + * maximum of 10; so we use up to between 30% and 10% of the + * machine's resources (assuming a few reasonable things about system + * performance). + */ + xgettimeofday(&stopat); + stopat.tv_sec += value; + ratio = 1; + for (;;) { + xgettimeofday(&before); + if (timercmp(&before,&stopat,>)) + goto next_item; + + do_stop(0, 1, &n_killed, &n_notkilled, 0); + if (!n_killed) + goto x_finished; + + xgettimeofday(&after); + + if (!timercmp(&after,&stopat,<)) + goto next_item; + + if (ratio < 10) + ratio++; + + TVCALC(interval, ratio * (TVELEM(&after) - TVELEM(&before) + TVADJUST)); + TVCALC(maxinterval, TVELEM(&stopat) - TVELEM(&after) + TVADJUST); + + if (timercmp(&interval,&maxinterval,>)) + interval = maxinterval; + + if (interval.tv_sec == 0 && + interval.tv_usec <= MIN_POLL_INTERVAL) + interval.tv_usec = MIN_POLL_INTERVAL; + + r = select(0,0,0,0,&interval); + if (r < 0 && errno != EINTR) + fatal("select() failed for pause: %s", + strerror(errno)); + } + + default: + assert(!"schedule[].type value must be valid"); + + } + + next_item: + position++; + } + + if (quietmode <= 0) + printf("Program %s, %d process(es), refused to die.\n", + what_stop, n_killed); + + return 2; + +x_finished: + if (!anykilled) { + if (quietmode <= 0) + printf("No %s found running; none killed.\n", what_stop); + return exitnodo; + } else { + return 0; + } +} + +/* +int main(int argc, char **argv) NONRETURNING; +*/ + +int +main(int argc, char **argv) +{ + progname = argv[0]; + + LIST_INIT(&namespace_head); + + parse_options(argc, argv); + argc -= optind; + argv += optind; + + if (execname && stat(execname, &exec_stat)) + fatal("stat %s: %s", execname, strerror(errno)); + + if (userspec && sscanf(userspec, "%d", &user_id) != 1) { + struct passwd *pw; + + pw = getpwnam(userspec); + if (!pw) + fatal("user `%s' not found\n", userspec); + + user_id = pw->pw_uid; + } + + if (changegroup && sscanf(changegroup, "%d", &runas_gid) != 1) { + struct group *gr = getgrnam(changegroup); + if (!gr) + fatal("group `%s' not found\n", changegroup); + runas_gid = gr->gr_gid; + } + if (changeuser && sscanf(changeuser, "%d", &runas_uid) != 1) { + struct passwd *pw = getpwnam(changeuser); + if (!pw) + fatal("user `%s' not found\n", changeuser); + runas_uid = pw->pw_uid; + if (changegroup == NULL) { /* pass the default group of this user */ + changegroup = ""; /* just empty */ + runas_gid = pw->pw_gid; + } + } + + if (stop) { + int i = run_stop_schedule(); + exit(i); + } + + do_findprocs(); + + if (found) { + if (quietmode <= 0) + printf("%s already running.\n", execname); + exit(exitnodo); + } + if (testmode) { + printf("Would start %s ", startas); + while (argc-- > 0) + printf("%s ", *argv++); + if (changeuser != NULL) { + printf(" (as user %s[%d]", changeuser, runas_uid); + if (changegroup != NULL) + printf(", and group %s[%d])", changegroup, runas_gid); + else + printf(")"); + } + if (changeroot != NULL) + printf(" in directory %s", changeroot); + if (nicelevel) + printf(", and add %i to the priority", nicelevel); + printf(".\n"); + exit(0); + } + if (quietmode < 0) + printf("Starting %s...\n", startas); + *--argv = startas; + if (changeroot != NULL) { + if (chdir(changeroot) < 0) + fatal("Unable to chdir() to %s", changeroot); + if (chroot(changeroot) < 0) + fatal("Unable to chroot() to %s", changeroot); + } + if (changeuser != NULL) { + if (setgid(runas_gid)) + fatal("Unable to set gid to %d", runas_gid); + if (initgroups(changeuser, runas_gid)) + fatal("Unable to set initgroups() with gid %d", runas_gid); + if (setuid(runas_uid)) + fatal("Unable to set uid to %s", changeuser); + } + + if (background) { /* ok, we need to detach this process */ + int i, fd; + if (quietmode < 0) + printf("Detatching to start %s...", startas); + i = fork(); + if (i<0) { + fatal("Unable to fork.\n"); + } + if (i) { /* parent */ + if (quietmode < 0) + printf("done.\n"); + exit(0); + } + /* child continues here */ + /* now close all extra fds */ + for (i=getdtablesize()-1; i>=0; --i) close(i); + /* change tty */ + fd = open("/dev/tty", O_RDWR); + ioctl(fd, TIOCNOTTY, 0); + close(fd); + chdir("/"); + umask(022); /* set a default for dumb programs */ + setpgid(0,0); /* set the process group */ + fd=open("/dev/null", O_RDWR); /* stdin */ + dup(fd); /* stdout */ + dup(fd); /* stderr */ + } + if (nicelevel) { + errno = 0; + if (nice(nicelevel) < 0 && errno) + fatal("Unable to alter nice level by %i: %s", nicelevel, + strerror(errno)); + } + if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */ + FILE *pidf = fopen(pidfile, "w"); + pid_t pidt = getpid(); + if (pidf == NULL) + fatal("Unable to open pidfile `%s' for writing: %s", pidfile, + strerror(errno)); + fprintf(pidf, "%d\n", pidt); + fclose(pidf); + } + set_namespaces(); + execv(startas, argv); + fatal("Unable to start %s: %s", startas, strerror(errno)); +} From 4481b5b894f8bcb4d6da51742e8e69ca13b1ca3d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 19:07:49 -0400 Subject: [PATCH 019/226] debian: Modifications to allow redhat to work properly Modify the control files to allow redhat to build properly. Signed-off-by: Donald Sharp --- debian/quagga.install | 2 +- {debian => tools}/quagga.service | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {debian => tools}/quagga.service (100%) diff --git a/debian/quagga.install b/debian/quagga.install index ec1f0b275f..6a70be9925 100644 --- a/debian/quagga.install +++ b/debian/quagga.install @@ -18,5 +18,5 @@ usr/share/man/man8/isisd.8 usr/share/man/man8/watchquagga.8 usr/share/snmp/mibs/ cumulus/etc/* etc/ -debian/*.service lib/systemd/system +tools/*.service lib/systemd/system debian/quagga.conf usr/lib/tmpfiles.d diff --git a/debian/quagga.service b/tools/quagga.service similarity index 100% rename from debian/quagga.service rename to tools/quagga.service From 29366ffbe13cf2356baaff0bd981d55408dcc619 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 19:08:43 -0400 Subject: [PATCH 020/226] tools: Use the now included start-stop-daemon Redhat does not have a way to run the start-stop-daemon. This code is widely available on the internet and very small. Use the compiled start-stop-daemon(ssd) if it is included with the system. Signed-off-by: Donald Sharp --- tools/quagga | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/quagga b/tools/quagga index cf9aa661d9..19ce0b3952 100755 --- a/tools/quagga +++ b/tools/quagga @@ -27,6 +27,13 @@ RELOAD_SCRIPT=/usr/lib/quagga/quagga-reload.py . /lib/lsb/init-functions +if [ -f /usr/lib/quagga/ssd ]; then + SSD=/usr/lib/quagga/ssd +else + SSD=`which start-stop-daemon` +fi + +echo ${SSD} # Print the name of the pidfile. pidfile() { @@ -107,7 +114,7 @@ start() echo -n " $1" fi - start-stop-daemon \ + ${SSD} \ --start \ --pidfile=`pidfile $1` \ --exec "$D_PATH/$1" \ @@ -120,7 +127,7 @@ start() return; fi - start-stop-daemon \ + ${SSD} \ --start \ --pidfile=`pidfile $1-$2` \ --exec "$D_PATH/$1" \ @@ -133,7 +140,7 @@ start() return; fi - start-stop-daemon \ + ${SSD} \ --start \ --pidfile=`pidfile $1` \ --exec "$D_PATH/$1" \ @@ -159,7 +166,7 @@ stop() else PIDFILE=`pidfile $inst` PID=`cat $PIDFILE 2>/dev/null` - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1" + ${SSD} --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1" # # Now we have to wait until $DAEMON has _really_ stopped. # @@ -322,7 +329,7 @@ stop_prio() fi for pidfile in $file_list_suffix.pid; do PID=`cat $pidfile 2>/dev/null` - start-stop-daemon --stop --quiet --oknodo --pidfile "$pidfile" + ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" echo -n "." rm -rf "$pidfile" done @@ -374,7 +381,7 @@ start_prio() # to MI version if started "$daemon_name"; then PIDFILE=`pidfile $daemon_name` - start-stop-daemon \ + ${SSD} \ --stop --quiet --oknodo \ --pidfile "$PIDFILE" \ --exec "$D_PATH/$daemon_name" @@ -395,7 +402,7 @@ start_prio() # single instance to MI version eval "file_list_suffix="$V_PATH"/"$daemon_name-*"" for pidfile in $file_list_suffix.pid; do - start-stop-daemon --stop --quiet --oknodo --pidfile "$pidfile" + ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" echo -n "." rm -rf "$pidfile" done From 9d92810cf1516568b0b5cef6077c9603c7636bfb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Jun 2016 19:10:17 -0400 Subject: [PATCH 021/226] quagga: Modify code to build properly in tools and cumulus The tools and cumulus directories were not properly being included for the 'make dist' step to allow for proper distribution of code. Signed-off-by: Donald Sharp Conflicts: Makefile.am --- Makefile.am | 4 ++-- configure.ac | 2 ++ tools/Makefile.am | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tools/Makefile.am diff --git a/Makefile.am b/Makefile.am index 7e01a22d1a..4f3835b0ff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,11 +2,11 @@ SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \ @ISISD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \ - redhat @SOLARIS@ tests + redhat @SOLARIS@ tests tools cumulus DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d \ isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \ - solaris + solaris tools cumulus EXTRA_DIST = aclocal.m4 SERVICES TODO REPORTING-BUGS INSTALL.quagga.txt \ update-autotools \ diff --git a/configure.ac b/configure.ac index 78d3cda268..113c1619f8 100755 --- a/configure.ac +++ b/configure.ac @@ -1750,6 +1750,8 @@ AC_CONFIG_FILES([Makefile lib/Makefile zebra/Makefile ripd/Makefile tests/bgpd.tests/Makefile tests/libzebra.tests/Makefile redhat/Makefile + tools/Makefile + cumulus/Makefile pkgsrc/Makefile redhat/quagga.spec lib/version.h diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000000..125bfee2c2 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,4 @@ +sbin_SCRIPTS = quagga-reload.py quagga + +EXTRA_DIST = quagga.service quagga-reload.py quagga + From e77e22d21e8833ec167951e2a5e8f6ca5c9e7346 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Jun 2016 15:06:37 -0400 Subject: [PATCH 022/226] redhat: Fix runtime dependency and quaggavty group 1) Fix runtime to depend on initscripts 2) Fix quagga user to get quaggavty group Signed-off-by: Donald Sharp --- redhat/quagga.spec.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/redhat/quagga.spec.in b/redhat/quagga.spec.in index 253fd7c0a0..cadc1fb8c9 100644 --- a/redhat/quagga.spec.in +++ b/redhat/quagga.spec.in @@ -99,7 +99,7 @@ Requires(preun): /sbin/install-info Requires(post): /sbin/install-info BuildRequires: texi2html texinfo autoconf patch libcap-devel groff BuildRequires: readline readline-devel ncurses ncurses-devel -Requires: ncurses +Requires: ncurses initscripts %if %{with_pam} BuildRequires: pam-devel Requires: pam @@ -284,7 +284,11 @@ if getent passwd %quagga_user >/dev/null ; then : ; else \ -M -r -s /sbin/nologin -c "Quagga routing suite" \ -d %_localstatedir %quagga_user 2> /dev/null || : ; \ fi +%if 0%{?vty_group:1} +/usr/sbin/usermod -a -G %vty_group %quagga_user %endif +%endif + %post # zebra_spec_add_service From 03718c3d128a15aa56b1ed55e02ffa2f75d44232 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Jun 2016 12:31:42 -0400 Subject: [PATCH 023/226] debian: Fix rules file Fix the rules file to put back isis and vtysh Signed-off-by: Donald Sharp --- debian/rules | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/rules b/debian/rules index e5e3ad8c11..7a48448068 100755 --- a/debian/rules +++ b/debian/rules @@ -39,6 +39,8 @@ override_dh_auto_configure: --sysconfdir=/etc/quagga \ $(USE_SNMP) \ --enable-ospfapi=yes \ + --enable-vtysh=yes \ + --enable-isisd=yes \ --enable-multipath=256 \ --enable-user=quagga \ --enable-group=quagga \ From 530d701611dc489161af6f34547174d147655a5a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Jun 2016 14:53:53 -0400 Subject: [PATCH 024/226] configure.ac: Add back HAVE_SYSTEMD When the change was made to add some additional code to make sure systemd was actually installed on the system, the HAVE_SYSTEMD #define was accidently removed. Signed-off-by: Donald Sharp --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 113c1619f8..8758d9d3c1 100755 --- a/configure.ac +++ b/configure.ac @@ -338,6 +338,8 @@ case "${enable_systemd}" in AC_CHECK_LIB(systemd, sd_notify, LIBS="$LIBS -lsystemd") if test $ac_cv_lib_systemd_sd_notify = no; then AC_MSG_ERROR([enable systemd has been specified but systemd development env not found on your system]) + else + AC_DEFINE(HAVE_SYSTEMD,,Compile systemd support in) fi ;; "*") ;; From 6776485deef32900c119a61d43faecb515d3b20b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 20 Jun 2016 08:21:00 -0400 Subject: [PATCH 025/226] quagga: Allow compile time determination of v6 RR semantics The patches to allow kernel v6 Route Replacement semantics to work correctly are on a very recent kernel. If you are compiling on a linux kernel where it's broken, just compile with --disable-rr-semantics. Signed-off-by: Donald Sharp (cherry picked from commit 76981cd383e4bed69454bcc4151a0aae89e8ca84) --- configure.ac | 6 ++++++ zebra/rt_netlink.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/configure.ac b/configure.ac index 8758d9d3c1..8338ad1462 100755 --- a/configure.ac +++ b/configure.ac @@ -304,6 +304,8 @@ AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)])) AC_ARG_ENABLE(cumulus, [ --enable-cumulus enable Cumulus Switch Special Extensions]) +AC_ARG_ENABLE(rr-semantics, + AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics])) if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes" @@ -345,6 +347,10 @@ case "${enable_systemd}" in "*") ;; esac +if test "${enable_rr_semantics}" != "no" ; then + AC_DEFINE(HAVE_V6_RR_SEMANTICS,, Compile in v6 Route Replacement Semantics) +fi + if test "${enable_poll}" = "yes" ; then AC_DEFINE(HAVE_POLL,,Compile systemd support in) fi diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e52fcd4342..1f7b1a9cff 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2390,7 +2390,12 @@ kernel_add_ipv6 (struct prefix *p, struct rib *rib) int kernel_update_ipv6 (struct prefix *p, struct rib *rib) { +#if defined (HAVE_V6_RR_SEMANTICS) return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6, 1); +#else + kernel_delete_ipv6 (p, rib); + return kernel_add_ipv6 (p, rib); +#endif } int From 2376c3f225ee601e2e025e1813006ab79c3fd0a6 Mon Sep 17 00:00:00 2001 From: radhika Date: Tue, 21 Jun 2016 03:39:58 -0700 Subject: [PATCH 026/226] bfd: Fix for missing BFD client regs/deregs from quagga clients Ticket: CM-11256 Signed-off-by: Radhika Mahankali Reviewed-by: Donald Sharp Reviewed-by: Kanna Rajagopal Testing: Unit, PTM smoke, OSPF smoke, BGP Smoke Issue: BFD client registrations are not being sent to PTM from BGP/OSPF clients when the quagga clients have no BFD configuration. This can create stale BFD sessions in PTM when BFD is removed from quagga configuration before quagga is restarted. BFD client de-registrations from BGP/OSPF also go missing sometimes when quagga is restarted. This also will cause stale BFD sessions in PTM. Root Cause: BFD client registrations were being sent at the time of BGP/OSPF daemon initialization. But, they were being sent to zebra before the socket connection between zebra and BGP/OSPF was established. This causes the missing BFD client registrations. BFD client de-registrations are sent from zebra when zebra detects socket close for BGP/OSPF daemons. Based on the timing, the de-registrations may happen after socket between PTM and zebra is closed. This will result in missing de-registrations. Fix: Moved sending of BFD client registration messages to zebra connected callback to make sure that they are sent after the BGP/OSPF daemons connect with zebra. Added BFD client de-registrations for BGP/OSPF to be also sent when zebra daemon gets restart signal. They are sent from the signal handler only if it was not already handled in zebra client socket close callback. --- bgpd/bgp_bfd.c | 3 --- bgpd/bgp_zebra.c | 5 ++++- ospf6d/ospf6_bfd.c | 3 --- ospf6d/ospf6_zebra.c | 4 ++++ ospfd/ospf_bfd.c | 3 --- ospfd/ospf_zebra.c | 4 ++++ zebra/zebra_ptm.c | 32 ++++++++++++++++++++++---------- zebra/zebra_ptm.h | 5 ++++- zebra/zserv.c | 2 +- 9 files changed, 39 insertions(+), 22 deletions(-) diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index b64fbee04d..b8b0053695 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -711,7 +711,4 @@ bgp_bfd_init(void) install_element (BGP_NODE, &no_neighbor_bfd_cmd); install_element (BGP_NODE, &no_neighbor_bfd_val_cmd); install_element (BGP_NODE, &no_neighbor_bfd_type_cmd); - - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 457f865bea..102e38e4be 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "queue.h" #include "memory.h" #include "lib/json.h" +#include "lib/bfd.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" @@ -43,7 +44,6 @@ Boston, MA 02111-1307, USA. */ #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_nht.h" -#include "bgpd/bgp_bfd.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -2053,6 +2053,9 @@ bgp_zebra_connected (struct zclient *zclient) bgp_zebra_instance_register (bgp); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* TODO - What if we have peers and networks configured, do we have to * kick-start them? */ diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index 503c7e0cd7..f9bb6f0031 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -420,7 +420,4 @@ ospf6_bfd_init(void) install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd); install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd); install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd); - - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); } diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 9c738233b4..3137a33c50 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -28,6 +28,7 @@ #include "stream.h" #include "zclient.h" #include "memory.h" +#include "lib/bfd.h" #include "ospf6_proto.h" #include "ospf6_top.h" @@ -654,6 +655,9 @@ DEFUN (no_redistribute_ospf6, static void ospf6_zebra_connected (struct zclient *zclient) { + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + zclient_send_reg_requests (zclient, VRF_DEFAULT); } diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index ec486c4688..c87bcb0afb 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -452,7 +452,4 @@ ospf_bfd_init(void) install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_bfd_param_cmd); - - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index ffdfd750d2..16cd2d2479 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -34,6 +34,7 @@ #include "filter.h" #include "plist.h" #include "log.h" +#include "lib/bfd.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -1557,6 +1558,9 @@ ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or) static void ospf_zebra_connected (struct zclient *zclient) { + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + zclient_send_reg_requests (zclient, VRF_DEFAULT); } diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index bf6afb0216..931fc73e43 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -131,11 +131,13 @@ zebra_ptm_init (void) void zebra_ptm_finish(void) { - if (ptm_cb.ptm_sock != -1) - close(ptm_cb.ptm_sock); + int proto; - if (ptm_cb.wb) - buffer_free(ptm_cb.wb); + for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) + if (CHECK_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) + zebra_ptm_bfd_client_deregister(proto); + + buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); if (ptm_cb.out_data) free(ptm_cb.out_data); @@ -150,6 +152,12 @@ zebra_ptm_finish(void) thread_cancel (ptm_cb.t_write); if (ptm_cb.t_timer) thread_cancel (ptm_cb.t_timer); + + if (ptm_cb.wb) + buffer_free(ptm_cb.wb); + + if (ptm_cb.ptm_sock != -1) + close(ptm_cb.ptm_sock); } static int @@ -999,24 +1007,26 @@ zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length) zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, ptm_cb.out_data); zebra_ptm_send_message(ptm_cb.out_data, data_len); + + SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); return 0; } /* BFD client deregister */ void -zebra_ptm_bfd_client_deregister (struct zserv *client) +zebra_ptm_bfd_client_deregister (int proto) { void *out_ctxt; char tmp_buf[64]; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP - && client->proto != ZEBRA_ROUTE_OSPF6) + if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP + && proto != ZEBRA_ROUTE_OSPF6) return; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_client_deregister msg for client %s", - zebra_route_string(client->proto)); + zlog_err("bfd_client_deregister msg for client %s", + zebra_route_string(proto)); if (ptm_cb.ptm_sock == -1) { @@ -1030,7 +1040,7 @@ zebra_ptm_bfd_client_deregister (struct zserv *client) sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + sprintf(tmp_buf, "%s", zebra_route_string(proto)); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); @@ -1039,7 +1049,9 @@ zebra_ptm_bfd_client_deregister (struct zserv *client) if (IS_ZEBRA_DEBUG_SEND) zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); + UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); } int diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 27c0e42f99..71c85d9094 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -27,6 +27,8 @@ extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_MAX_SOCKBUF 3200 /* 25B *128 ports */ #define ZEBRA_PTM_SEND_MAX_SOCKBUF 512 +#define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */ + /* Zebra ptm context block */ struct zebra_ptm_cb { @@ -44,6 +46,7 @@ struct zebra_ptm_cb int ptm_enable; int pid; + u_int8_t client_flags[ZEBRA_ROUTE_MAX]; }; #define ZEBRA_PTM_STATUS_DOWN 0 @@ -72,5 +75,5 @@ int zebra_ptm_bfd_client_register (struct zserv *client, int sock, void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp); -void zebra_ptm_bfd_client_deregister (struct zserv *client); +void zebra_ptm_bfd_client_deregister (int proto); #endif diff --git a/zebra/zserv.c b/zebra/zserv.c index d6de0792e1..1529bc286c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1752,7 +1752,7 @@ static void zebra_client_close (struct zserv *client) { /* Send client de-registration to BFD */ - zebra_ptm_bfd_client_deregister(client); + zebra_ptm_bfd_client_deregister(client->proto); /* Cleanup any registered nexthops - across all VRFs. */ zebra_client_close_cleanup_rnh (client); From 39dcf9acd87b18ab00f9f71ec15fdd89fff4b3c8 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 21 Jun 2016 14:24:29 +0000 Subject: [PATCH 027/226] Fix build warnings in start-stop-daemon.c Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-11484 --- cumulus/start-stop-daemon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cumulus/start-stop-daemon.c b/cumulus/start-stop-daemon.c index e317bb801c..ea63fbc217 100644 --- a/cumulus/start-stop-daemon.c +++ b/cumulus/start-stop-daemon.c @@ -107,7 +107,7 @@ LIST_HEAD(namespace_head, namespace); struct namespace { LIST_ENTRY(namespace) list; - char *path; + const char *path; int nstype; }; @@ -222,12 +222,12 @@ clear(struct pid_list **list) *list = NULL; } -static char * +static const char * next_dirname(const char *s) { - char *cur; + const char *cur; - cur = (char *)s; + cur = (const char *)s; if (*cur != '\0') { for (; *cur != '/'; ++cur) @@ -248,7 +248,7 @@ add_namespace(const char *path) const char *nsdirname, *nsname, *cur; struct namespace *namespace; - cur = (char *)path; + cur = (const char *)path; nsdirname = nsname = ""; while ((cur = next_dirname(cur))[0] != '\0') { @@ -266,7 +266,7 @@ add_namespace(const char *path) badusage("invalid namepspace path"); namespace = xmalloc(sizeof(*namespace)); - namespace->path = (char *)path; + namespace->path = (const char *)path; namespace->nstype = nstype; LIST_INSERT_HEAD(&namespace_head, namespace, list); } From ab5f8310801f1870a7c5c22e1595e4452c558ddb Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 21 Jun 2016 14:52:43 +0000 Subject: [PATCH 028/226] quagga-reload.py thinks the BGP ASN changed when it did not Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-11463 --- tools/quagga-reload.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 27fc3830c6..9c0cbb48d6 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -567,7 +567,11 @@ def compare_context_objects(newconf, running): if running_ctx_keys not in newconf.contexts: # Check if bgp's local ASN has changed. If yes, just restart it - if "router bgp" in running_ctx_keys[0]: + # We check that the len is 1 here so that we only look at ('router bgp 10') + # and not ('router bgp 10', 'address-family ipv4 unicast'). The + # latter could cause a false restart_bgpd positive if ipv4 unicast is in + # running but not in newconf. + if "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) == 1: restart_bgpd = True continue From 655f79c9d2352c4c57b883aad0da6cd4528f4dde Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Wed, 6 Jul 2016 06:50:23 -0700 Subject: [PATCH 029/226] Don't print 'neighbor activate' if its default for IPv4 unicast AFI/SAFI Ticket: CM-11460 Reviewed By: CCR-4927 Testing Done: Quagga's default "show running" model is to only print the non-default config. Historically, IPv4 unicast has always had a default 'activate' model unless its been configured otherwise. In 3.0, we introduced a print of the 'activate' statement for IPv4 unicast independent of whether it was the default or not. This causes quagga reload to break as the user doesn't configure 'activate' for IPv4 unicast, and so any config changes will also not have it. However 'show running' will display it, causing quagga reload to think that the AFI/SAFI has been deactivated and bounce the sessions incorrectly. This patch reverts to the original quagga behavior/model of not printing the 'activate' line for IPv4 unicast if its the default. --- bgpd/bgpd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index f23cc13725..ca72d2403a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6621,9 +6621,17 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, { if (peer->afc[afi][safi]) { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s activate%s", - addr, VTY_NEWLINE); + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) + { + if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + { + vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE); + } + } + else + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s activate%s", + addr, VTY_NEWLINE); } } From 5b1207f72c67b65a60959945bb4250409bb8460f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 11:31:45 -0400 Subject: [PATCH 030/226] pimd: Stale IGMP groups left behind When a toin IGMPv3 join is received, the code was always auto creating the igmp group associated with the received packet. The RFC clearly states though that if a INCLUDE is received for a group with 0 sources and we have received nothing the igmpv3 packet should be ignored. Ticket: CM-11260 Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 8 +++----- pimd/pim_igmp.h | 2 ++ pimd/pim_igmpv3.c | 25 ++++++++++++++++++++----- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 6df835e252..440d648723 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -46,9 +46,6 @@ static void group_timer_off(struct igmp_group *group); -static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr); - static int igmp_sock_open(struct in_addr ifaddr, int ifindex, uint32_t pim_options) { int fd; @@ -1358,8 +1355,9 @@ void igmp_group_timer_on(struct igmp_group *group, group, interval_msec); } -static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr) +struct igmp_group * +find_group_by_addr (struct igmp_sock *igmp, + struct in_addr group_addr) { struct igmp_group *group; struct listnode *node; diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index ab396159e3..c6685c2837 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -162,6 +162,8 @@ struct igmp_group { int64_t last_igmp_v2_report_dsec; }; +struct igmp_group *find_group_by_addr (struct igmp_sock *igmp, + struct in_addr group_addr); struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr); diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 0a6b6b3795..7300e6c6b4 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -834,11 +834,26 @@ void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, sources); - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } + /* + * If the requested filter mode is INCLUDE *and* the requested source + * list is empty, then the entry corresponding to the requested + * interface and multicast address is deleted if present. If no such + * entry is present, the request is ignored. + */ + if (num_sources) + { + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + } + else + { + group = find_group_by_addr (igmp, group_addr); + if (!group) + return; + } if (group->group_filtermode_isexcl) { /* EXCLUDE mode */ From 9867746afefbead8d36cda32a0453f51e4f34362 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 15:09:25 -0400 Subject: [PATCH 031/226] pimd: Refactor 'struct static_route' to use channel_oil The 'struct static_route' data structure duplicated a decent bit of what is the in the struct channel_oil. Refactor. This will set us up for further cleanup. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 23 +++++++++--------- pimd/pim_static.c | 62 ++++++++++++++++++++++++----------------------- pimd/pim_static.h | 4 +-- pimd/pim_vty.c | 1 + pimd/pimd.h | 1 - 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 68446572eb..3924758ddb 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -30,6 +30,7 @@ #include "zclient.h" #include "pimd.h" +#include "pim_mroute.h" #include "pim_cmd.h" #include "pim_iface.h" #include "pim_vty.h" @@ -1637,12 +1638,12 @@ static void static_mroute_add_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_add(&s_route->mc)) { + if (pim_mroute_add(&s_route->c_oil.oil)) { /* just log warning */ char source_str[100]; char group_str[100]; - pim_inet4_dump("", s_route->mc.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", __FILE__, __PRETTY_FUNCTION__, source_str, group_str); @@ -1656,12 +1657,12 @@ static void static_mroute_del_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_del(&s_route->mc)) { + if (pim_mroute_del(&s_route->c_oil.oil)) { /* just log warning */ char source_str[100]; char group_str[100]; - pim_inet4_dump("", s_route->mc.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", __FILE__, __PRETTY_FUNCTION__, source_str, group_str); @@ -2256,7 +2257,7 @@ static void show_mroute(struct vty *vty) ifp_in = pim_if_find_by_vif_index(s_route->iif); ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->creation[oif_vif_index]); + pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); proto[0] = '\0'; strcat(proto, "S"); @@ -2340,11 +2341,11 @@ static void show_mroute_count(struct vty *vty) struct sioc_sg_req sgreq; memset(&sgreq, 0, sizeof(sgreq)); - sgreq.src = s_route->mc.mfcc_origin; - sgreq.grp = s_route->mc.mfcc_mcastgrp; + sgreq.src = s_route->c_oil.oil.mfcc_origin; + sgreq.grp = s_route->c_oil.oil.mfcc_mcastgrp; - pim_inet4_dump("", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", s_route->mc.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { int e = errno; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 47a34daf48..84b026be11 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -24,16 +24,17 @@ #include "vty.h" #include "if.h" - -#include "pim_static.h" -#include "pim_time.h" -#include "pim_str.h" -#include "pimd.h" -#include "pim_iface.h" #include "log.h" #include "memory.h" #include "linklist.h" +#include "pimd.h" +#include "pim_oil.h" +#include "pim_static.h" +#include "pim_time.h" +#include "pim_str.h" +#include "pim_iface.h" + void pim_static_route_free(struct static_route *s_route) { XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); @@ -66,12 +67,12 @@ static struct static_route *static_route_new(unsigned int iif, s_route->source = source; s_route->iif = iif; s_route->oif_ttls[oif] = 1; - s_route->oif_count = 1; - s_route->mc.mfcc_origin = source; - s_route->mc.mfcc_mcastgrp = group; - s_route->mc.mfcc_parent = iif; - s_route->mc.mfcc_ttls[oif] = 1; - s_route->creation[oif] = pim_time_monotonic_sec(); + s_route->c_oil.oil_ref_count = 1; + s_route->c_oil.oil.mfcc_origin = source; + s_route->c_oil.oil.mfcc_mcastgrp = group; + s_route->c_oil.oil.mfcc_parent = iif; + s_route->c_oil.oil.mfcc_ttls[oif] = 1; + s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); return s_route; } @@ -138,30 +139,30 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr /* Route exists and has the same input interface, but adding a new output interface */ if (s_route->iif == iif_index) { s_route->oif_ttls[oif_index] = 1; - s_route->mc.mfcc_ttls[oif_index] = 1; - s_route->creation[oif_index] = pim_time_monotonic_sec(); - ++s_route->oif_count; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); + ++s_route->c_oil.oil_ref_count; } else { /* input interface changed */ s_route->iif = iif_index; - s_route->mc.mfcc_parent = iif_index; + s_route->c_oil.oil.mfcc_parent = iif_index; #ifdef PIM_ENFORCE_LOOPFREE_MFC /* check to make sure the new input was not an old output */ if (s_route->oif_ttls[iif_index]) { s_route->oif_ttls[iif_index] = 0; - s_route->creation[iif_index] = 0; - s_route->mc.mfcc_ttls[iif_index] = 0; - --s_route->oif_count; + s_route->c_oil.oif_creation[iif_index] = 0; + s_route->c_oil.oil.mfcc_ttls[iif_index] = 0; + --s_route->c_oil.oil_ref_count; } #endif /* now add the new output, if it is new */ if (!s_route->oif_ttls[oif_index]) { s_route->oif_ttls[oif_index] = 1; - s_route->creation[oif_index] = pim_time_monotonic_sec(); - s_route->mc.mfcc_ttls[oif_index] = 1; - ++s_route->oif_count; + s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; } } @@ -175,7 +176,7 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr listnode_add(qpim_static_route_list, s_route); } - if (pim_mroute_add(&(s_route->mc))) + if (pim_mroute_add(&s_route->c_oil.oil)) { char gifaddr_str[100]; char sifaddr_str[100]; @@ -245,11 +246,12 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr s_route->source.s_addr == source.s_addr && s_route->oif_ttls[oif_index]) { s_route->oif_ttls[oif_index] = 0; - s_route->mc.mfcc_ttls[oif_index] = 0; - --s_route->oif_count; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; + --s_route->c_oil.oil_ref_count; /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ - if (s_route->oif_count <= 0 ? pim_mroute_del(&s_route->mc) : pim_mroute_add(&s_route->mc)) { + if (s_route->c_oil.oil_ref_count <= 0 ? + pim_mroute_del(&s_route->c_oil.oil) : pim_mroute_add(&s_route->c_oil.oil)) { char gifaddr_str[100]; char sifaddr_str[100]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); @@ -262,15 +264,15 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr sifaddr_str); s_route->oif_ttls[oif_index] = 1; - s_route->mc.mfcc_ttls[oif_index] = 1; - ++s_route->oif_count; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; return -1; } - s_route->creation[oif_index] = 0; + s_route->c_oil.oif_creation[oif_index] = 0; - if (s_route->oif_count <= 0) { + if (s_route->c_oil.oil_ref_count <= 0) { listnode_delete(qpim_static_route_list, s_route); pim_static_route_free(s_route); } diff --git a/pimd/pim_static.h b/pimd/pim_static.h index b3be09e913..ff89fb150e 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -32,11 +32,9 @@ struct static_route { struct in_addr group; struct in_addr source; + struct channel_oil c_oil; unsigned int iif; unsigned char oif_ttls[MAXVIFS]; - int oif_count; - struct mfcctl mc; - time_t creation[MAXVIFS]; }; void pim_static_route_free(struct static_route *s_route); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index beb0622a3f..f1c8930856 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -33,6 +33,7 @@ #include "pim_str.h" #include "pim_ssmpingd.h" #include "pim_pim.h" +#include "pim_oil.h" #include "pim_static.h" int pim_debug_config_write(struct vty *vty) diff --git a/pimd/pimd.h b/pimd/pimd.h index c5fec76675..0a376aa905 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -25,7 +25,6 @@ #include -#include "pim_mroute.h" #include "pim_assert.h" #define PIMD_PROGNAME "pimd" From c171d6d8c9a607d0f3525b515e75c3fc1b91577a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 15:16:53 -0400 Subject: [PATCH 032/226] pimd: Refactor pim_mroute_add and _del The struct mfcctl should not be passed around. Pass around the channel oil instead. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 8 ++++---- pimd/pim_mroute.c | 18 +++++++++--------- pimd/pim_mroute.h | 4 ++-- pimd/pim_oil.c | 2 +- pimd/pim_static.c | 4 ++-- pimd/pim_zebra.c | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3924758ddb..4e168bda0d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1600,7 +1600,7 @@ static void mroute_add_all() struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - if (pim_mroute_add(&c_oil->oil)) { + if (pim_mroute_add(c_oil)) { /* just log warning */ char source_str[100]; char group_str[100]; @@ -1619,7 +1619,7 @@ static void mroute_del_all() struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - if (pim_mroute_del(&c_oil->oil)) { + if (pim_mroute_del(c_oil)) { /* just log warning */ char source_str[100]; char group_str[100]; @@ -1638,7 +1638,7 @@ static void static_mroute_add_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_add(&s_route->c_oil.oil)) { + if (pim_mroute_add(&s_route->c_oil)) { /* just log warning */ char source_str[100]; char group_str[100]; @@ -1657,7 +1657,7 @@ static void static_mroute_del_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_del(&s_route->c_oil.oil)) { + if (pim_mroute_del(&s_route->c_oil)) { /* just log warning */ char source_str[100]; char group_str[100]; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8048d4b3c7..1b13d90869 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -557,7 +557,7 @@ int pim_mroute_del_vif(int vif_index) return 0; } -int pim_mroute_add(struct mfcctl *mc) +int pim_mroute_add(struct channel_oil *c_oil) { int err; int orig = 0; @@ -575,17 +575,17 @@ int pim_mroute_add(struct mfcctl *mc) * vif to be part of the outgoing list * in the case of a (*,G). */ - if (mc->mfcc_origin.s_addr == INADDR_ANY) + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { - orig = mc->mfcc_ttls[mc->mfcc_parent]; - mc->mfcc_ttls[mc->mfcc_parent] = 1; + orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; } err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - mc, sizeof(*mc)); + &c_oil->oil, sizeof(c_oil->oil)); - if (mc->mfcc_origin.s_addr == INADDR_ANY) - mc->mfcc_ttls[mc->mfcc_parent] = orig; + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; if (err) { int e = errno; @@ -600,7 +600,7 @@ int pim_mroute_add(struct mfcctl *mc) return 0; } -int pim_mroute_del(struct mfcctl *mc) +int pim_mroute_del (struct channel_oil *c_oil) { int err; @@ -613,7 +613,7 @@ int pim_mroute_del(struct mfcctl *mc) return -1; } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, mc, sizeof(*mc)); + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); if (err) { int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index c1ce012e2d..25532614ac 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -169,8 +169,8 @@ int pim_mroute_socket_disable(void); int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags); int pim_mroute_del_vif(int vif_index); -int pim_mroute_add(struct mfcctl *mc); -int pim_mroute_del(struct mfcctl *mc); +int pim_mroute_add(struct channel_oil *c_oil); +int pim_mroute_del(struct channel_oil *c_oil); int pim_mroute_msg(int fd, const char *buf, int buf_size); diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 8755818c0f..3d9b7d11fe 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -253,7 +253,7 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL; - if (pim_mroute_add(&channel_oil->oil)) { + if (pim_mroute_add(channel_oil)) { if (PIM_DEBUG_MROUTE) { char group_str[100]; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 84b026be11..1931f1ee6c 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -176,7 +176,7 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr listnode_add(qpim_static_route_list, s_route); } - if (pim_mroute_add(&s_route->c_oil.oil)) + if (pim_mroute_add(&s_route->c_oil)) { char gifaddr_str[100]; char sifaddr_str[100]; @@ -251,7 +251,7 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ if (s_route->c_oil.oil_ref_count <= 0 ? - pim_mroute_del(&s_route->c_oil.oil) : pim_mroute_add(&s_route->c_oil.oil)) { + pim_mroute_del(&s_route->c_oil) : pim_mroute_add(&s_route->c_oil)) { char gifaddr_str[100]; char sifaddr_str[100]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b19b3941b1..47515bcbca 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -448,7 +448,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil) zlog_debug ("FF"); /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(&c_oil->oil)) + if (pim_mroute_add(c_oil)) { /* just log warning */ struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); @@ -900,7 +900,7 @@ static int del_oif(struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - if (pim_mroute_add(&channel_oil->oil)) { + if (pim_mroute_add(channel_oil)) { char group_str[100]; char source_str[100]; pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); @@ -917,7 +917,7 @@ static int del_oif(struct channel_oil *channel_oil, --channel_oil->oil_size; if (channel_oil->oil_size < 1) { - if (pim_mroute_del(&channel_oil->oil)) { + if (pim_mroute_del(channel_oil)) { /* just log a warning in case of failure */ char group_str[100]; char source_str[100]; From 58302dc7247b014fa7bae96380cc3c9b0e6c7815 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 15:22:10 -0400 Subject: [PATCH 033/226] pimd: Track if the mroute is installed or not Track whether or not if a mroute has been installed or not. If not don't display information about it. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 12 ++++++++++++ pimd/pim_mroute.c | 3 +++ pimd/pim_oil.c | 1 + pimd/pim_oil.h | 1 + 4 files changed, 17 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4e168bda0d..f27e3ff76d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2190,6 +2190,9 @@ static void show_mroute(struct vty *vty) char source_str[100]; int oif_vif_index; + if (!c_oil->installed) + continue; + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); @@ -2240,6 +2243,9 @@ static void show_mroute(struct vty *vty) char source_str[100]; int oif_vif_index; + if (!s_route->c_oil.installed) + continue; + pim_inet4_dump("", s_route->group, group_str, sizeof(group_str)); pim_inet4_dump("", s_route->source, source_str, sizeof(source_str)); @@ -2305,6 +2311,9 @@ static void show_mroute_count(struct vty *vty) char source_str[100]; struct sioc_sg_req sgreq; + if (!c_oil->installed) + continue; + memset(&sgreq, 0, sizeof(sgreq)); sgreq.src = c_oil->oil.mfcc_origin; sgreq.grp = c_oil->oil.mfcc_mcastgrp; @@ -2340,6 +2349,9 @@ static void show_mroute_count(struct vty *vty) char source_str[100]; struct sioc_sg_req sgreq; + if (!s_route->c_oil.installed) + continue; + memset(&sgreq, 0, sizeof(sgreq)); sgreq.src = s_route->c_oil.oil.mfcc_origin; sgreq.grp = s_route->c_oil.oil.mfcc_mcastgrp; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 1b13d90869..4d9a9d0b7e 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -597,6 +597,7 @@ int pim_mroute_add(struct channel_oil *c_oil) return -2; } + c_oil->installed = 1; return 0; } @@ -624,5 +625,7 @@ int pim_mroute_del (struct channel_oil *c_oil) return -2; } + c_oil->installed = 0; + return 0; } diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 3d9b7d11fe..96f9ef2b62 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -79,6 +79,7 @@ static struct channel_oil *channel_oil_new(struct in_addr group_addr, c_oil->oil.mfcc_origin = source_addr; c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil_ref_count = 1; + c_oil->installed = 0; zassert(c_oil->oil_size == 0); diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index f0a14a9baa..143f2345f9 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -59,6 +59,7 @@ struct channel_oil { struct mfcctl oil; + int installed; int oil_size; int oil_ref_count; time_t oif_creation[MAXVIFS]; From 60cd0356857757bd096cfb0607903ff090990ba9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 15:25:11 -0400 Subject: [PATCH 034/226] pimd: multicast route not removed from kernel when the if goes down When a multicast route's rpf changes( for whatever reason ) (*,G) routes were never updating properly. This is because we were attempting to fing the path to the *, instead of the RP. Modify the code to check if we are attempting to find a * route and use the RP instead. Ticket: CM-11736 Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 47515bcbca..efab00e227 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -387,18 +387,27 @@ static void scan_upstream_rpf_cache() void pim_scan_individual_oil (struct channel_oil *c_oil) { + struct in_addr vif_source; + int input_iface_vif_index; int old_vif_index; - int input_iface_vif_index = fib_lookup_if_vif_index(c_oil->oil.mfcc_origin); + if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin)) + return; + + input_iface_vif_index = fib_lookup_if_vif_index (vif_source); if (input_iface_vif_index < 1) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: could not find input interface for (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); + if (PIM_DEBUG_ZEBRA) + { + char source_str[100]; + char group_str[100]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); + zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, + source_str, group_str); + } + pim_mroute_del (c_oil); return; } From cc146ecc00f96137027cc909a78e83f8ec02c08c Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 12 Jul 2016 20:10:05 +0000 Subject: [PATCH 035/226] quagga-reload.py needs a --stdout option Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-11791 --- tools/quagga-reload.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 9c0cbb48d6..9650822d1e 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -624,13 +624,14 @@ if __name__ == '__main__': group.add_argument('--reload', action='store_true', help='Apply the deltas', default=False) group.add_argument('--test', action='store_true', help='Show the deltas', default=False) parser.add_argument('--debug', action='store_true', help='Enable debugs', default=False) + parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False) parser.add_argument('filename', help='Location of new quagga config file') args = parser.parse_args() # Logging # For --test log to stdout # For --reload log to /var/log/quagga/quagga-reload.log - if args.test: + if args.test or args.stdout: logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)5s: %(message)s') elif args.reload: From 63fa10b5958ff47e2571eefeb360a5e8db48ac22 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 12 Jul 2016 21:13:24 +0000 Subject: [PATCH 036/226] bgpd: Disallow ebgp-multihop on swpX peers Disallow setting ebgp-multihop on peers directly connected via an interface. Signed-off-by: Quentin Young --- bgpd/bgp_vty.c | 6 ++++++ bgpd/bgpd.h | 1 + 2 files changed, 7 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5dff63e8c2..b1a3116be3 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -304,6 +304,9 @@ bgp_vty_return (struct vty *vty, int ret) case BGP_ERR_INVALID_FOR_DYNAMIC_PEER: str = "Operation not allowed on a dynamic neighbor"; break; + case BGP_ERR_INVALID_FOR_DIRECT_PEER: + str = "Operation not allowed on a directly connected neighbor"; + break; } if (str) { @@ -4434,6 +4437,9 @@ peer_ebgp_multihop_set_vty (struct vty *vty, const char *ip_str, if (! peer) return CMD_WARNING; + if (peer->conf_if) + return bgp_vty_return (vty, BGP_ERR_INVALID_FOR_DIRECT_PEER); + if (! ttl_str) ttl = MAXTTL; else diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 0c6aa6b21a..2acdaed331 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1120,6 +1120,7 @@ enum bgp_clear_type #define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -31 #define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -32 #define BGP_ERR_MAX -33 +#define BGP_ERR_INVALID_FOR_DIRECT_PEER -34 /* * Enumeration of different policy kinds a peer can be configured with. From 3667e8a081ee4e036c1ffb7cf8f14477c051478f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Jul 2016 11:41:41 -0400 Subject: [PATCH 037/226] pimd: Add generic function to retrieve mroute stats Add a generic function to retrieve mroute statistics from the kernel. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 53 +++++++---------------------------------------- pimd/pim_mroute.c | 39 ++++++++++++++++++++++++++++++++++ pimd/pim_mroute.h | 1 + pimd/pim_oil.h | 12 +++++++++++ 4 files changed, 60 insertions(+), 45 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f27e3ff76d..13cc305274 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -22,8 +22,6 @@ #include -#include - #include "command.h" #include "if.h" #include "prefix.h" @@ -2309,37 +2307,21 @@ static void show_mroute_count(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { char group_str[100]; char source_str[100]; - struct sioc_sg_req sgreq; if (!c_oil->installed) continue; - memset(&sgreq, 0, sizeof(sgreq)); - sgreq.src = c_oil->oil.mfcc_origin; - sgreq.grp = c_oil->oil.mfcc_mcastgrp; + pim_mroute_update_counters (c_oil); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { - int e = errno; - vty_out(vty, - "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s", - (unsigned long)SIOCGETSGCNT, - source_str, - group_str, - e, - safe_strerror(e), - VTY_NEWLINE); - continue; - } - vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s", source_str, group_str, - sgreq.pktcnt, - sgreq.bytecnt, - sgreq.wrong_if, + c_oil->cc.pktcnt, + c_oil->cc.bytecnt, + c_oil->cc.wrong_if, VTY_NEWLINE); } @@ -2347,40 +2329,21 @@ static void show_mroute_count(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { char group_str[100]; char source_str[100]; - struct sioc_sg_req sgreq; if (!s_route->c_oil.installed) continue; - memset(&sgreq, 0, sizeof(sgreq)); - sgreq.src = s_route->c_oil.oil.mfcc_origin; - sgreq.grp = s_route->c_oil.oil.mfcc_mcastgrp; + pim_mroute_update_counters (&s_route->c_oil); pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); - if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { - int e = errno; - vty_out(vty, - "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s", - /* note that typeof ioctl defs can vary across platforms, from - * int, to unsigned int, to long unsigned int - */ - (unsigned long)SIOCGETSGCNT, - source_str, - group_str, - e, - safe_strerror(e), - VTY_NEWLINE); - continue; - } - vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s", source_str, group_str, - sgreq.pktcnt, - sgreq.bytecnt, - sgreq.wrong_if, + s_route->c_oil.cc.pktcnt, + s_route->c_oil.cc.bytecnt, + s_route->c_oil.cc.wrong_if, VTY_NEWLINE); } } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 4d9a9d0b7e..b5463fac59 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -143,6 +143,8 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } + pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + up->channel_oil = pim_channel_oil_add(msg->im_dst, msg->im_src, pim_ifp->mroute_vif_index); @@ -629,3 +631,40 @@ int pim_mroute_del (struct channel_oil *c_oil) return 0; } + +void +pim_mroute_update_counters (struct channel_oil *c_oil) +{ + struct sioc_sg_req sgreq; + + memset (&sgreq, 0, sizeof(sgreq)); + sgreq.src = c_oil->oil.mfcc_origin; + sgreq.grp = c_oil->oil.mfcc_mcastgrp; + + c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; + c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; + c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + + if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) + { + char group_str[100]; + char source_str[100]; + + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); + pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + + zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s", + (unsigned long)SIOCGETSGCNT, + source_str, + group_str, + errno, + safe_strerror(errno)); + return; + } + + c_oil->cc.pktcnt = sgreq.pktcnt; + c_oil->cc.bytecnt = sgreq.bytecnt; + c_oil->cc.wrong_if = sgreq.wrong_if; + + return; +} diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 25532614ac..176fb81cbc 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -174,4 +174,5 @@ int pim_mroute_del(struct channel_oil *c_oil); int pim_mroute_msg(int fd, const char *buf, int buf_size); +void pim_mroute_update_counters (struct channel_oil *c_oil); #endif /* PIM_MROUTE_H */ diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 143f2345f9..c63c026c0f 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -50,6 +50,17 @@ #define PIM_OIF_PIM_REGISTER_VIF (MAXVIFS - 1) #define PIM_MAX_USABLE_VIFS (MAXVIFS - 2) + +struct channel_counts +{ + unsigned long pktcnt; + unsigned long oldpktcnt; + unsigned long bytecnt; + unsigned long oldbytecnt; + unsigned long wrong_if; + unsigned long oldwrong_if; +}; + /* qpim_channel_oil_list holds a list of struct channel_oil. @@ -64,6 +75,7 @@ struct channel_oil { int oil_ref_count; time_t oif_creation[MAXVIFS]; uint32_t oif_flags[MAXVIFS]; + struct channel_counts cc; }; void pim_channel_oil_free(struct channel_oil *c_oil); From 4669ffbb00bf6d6a90dcb6adecd9d85a30a244fb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Jul 2016 12:46:09 -0400 Subject: [PATCH 038/226] pimd: Remove some extraneous hexdump's On every kernel upcall we are dumping the packet. Stop that. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index b5463fac59..e1da3c6101 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -314,7 +314,6 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) pim_inet4_dump("", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d", __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); - //zlog_hexdump(buf, buf_size); } return 0; } @@ -346,7 +345,6 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) return pim_mroute_msg_nocache(fd, ifp, msg, src_str, grp_str); break; case IGMPMSG_WHOLEPKT: - zlog_hexdump(buf, buf_size); return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg, src_str, grp_str); break; default: From 25a335e0cadc62946c615a102a6cbf2d2ec6ba55 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Jul 2016 14:22:42 -0400 Subject: [PATCH 039/226] pimd: Allow (S,G) pimreg route to time out When a kernel upcall happens for nocache we create a (S,G) route to be installed into the kernel. This code modification starts the ability to time out the mroute if we stop receiving mcast packets. Ticket: CM-11793 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 1 + pimd/pim_upstream.c | 29 +++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index e1da3c6101..ab3742438d 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -156,6 +156,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } return 0; } + up->channel_oil->cc.pktcnt++; pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_SOURCE); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cb2619abb7..8267885756 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -59,7 +59,7 @@ static void upstream_channel_oil_detach(struct pim_upstream *up) { if (up->channel_oil) { pim_channel_oil_del(up->channel_oil); - up->channel_oil = 0; + up->channel_oil = NULL; } } @@ -715,12 +715,29 @@ pim_upstream_keep_alive_timer (struct thread *t) up = THREAD_ARG(t); - pim_br_clear_pmbr (up->source_addr, up->group_addr); - /* - * We need to do more here :) - * But this is the start. - */ + if (I_am_RP (up->group_addr)) + { + pim_br_clear_pmbr (up->source_addr, up->group_addr); + /* + * We need to do more here :) + * But this is the start. + */ + } + else + { + pim_mroute_update_counters (up->channel_oil); + if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) + { + pim_mroute_del (up->channel_oil); + pim_upstream_delete (up); + } + else + { + up->t_ka_timer = NULL; + pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + } + } return 1; } From 86d1f7c49c84b823da91d347ca62afc785618991 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 20:11:15 -0400 Subject: [PATCH 040/226] pimd: Some Initial Groundwork for register stop Signed-off-by: Donald Sharp --- pimd/pim_register.h | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 7f3cdea3a2..039c0006e0 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -29,6 +29,7 @@ #define PIM_REGISTER_NR_BIT 0x40000000 #define PIM_MSG_REGISTER_LEN (8) +#define PIM_MSG_REGISTER_STOP_LEN (4) void pim_register_send_test_packet_start (struct in_addr source, struct in_addr group, From 4416b1f6c2d8b8a08a34ad19a22f24c30a922fff Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 20:13:32 -0400 Subject: [PATCH 041/226] pimd: Refactor some encode/decode functions Some encode/decode functions are needed in multiple places. Start the refactoring to be able to use them in a more generic manner. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 8 +-- pimd/pim_join.c | 39 +++-------- pimd/pim_tlv.c | 173 ++++++++++++++++++++-------------------------- pimd/pim_tlv.h | 18 ++--- 4 files changed, 93 insertions(+), 145 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 9f9c9e66f0..d3df6a1102 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -258,9 +258,7 @@ int pim_assert_recv(struct interface *ifp, /* Parse assert group addr */ - offset = pim_parse_addr_group(ifp->name, src_addr, - &msg_group_addr, - curr, curr_size); + offset = pim_parse_addr_group (&msg_group_addr, curr, curr_size); if (offset < 1) { char src_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); @@ -275,9 +273,7 @@ int pim_assert_recv(struct interface *ifp, /* Parse assert source addr */ - offset = pim_parse_addr_ucast(ifp->name, src_addr, - &msg_source_addr, - curr, curr_size); + offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size); if (offset < 1) { char src_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index f3b5e78ada..3852b423f0 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -127,14 +127,8 @@ int pim_joinprune_recv(struct interface *ifp, /* Parse ucast addr */ - addr_offset = pim_parse_addr_ucast(ifp->name, src_addr, - &msg_upstream_addr, - buf, pastend - buf); -#if 0 - zlog_warn("%s: pim_parse_addr_ucast addr_offset=%d", - __PRETTY_FUNCTION__, - addr_offset); -#endif + addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, + buf, pastend - buf); if (addr_offset < 1) { char src_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); @@ -197,14 +191,8 @@ int pim_joinprune_recv(struct interface *ifp, uint16_t msg_num_pruned_sources; int source; - addr_offset = pim_parse_addr_group(ifp->name, src_addr, - &msg_group_addr, - buf, pastend - buf); -#if 0 - zlog_warn("%s: pim_parse_addr_group addr_offset=%d", - __PRETTY_FUNCTION__, - addr_offset); -#endif + addr_offset = pim_parse_addr_group (&msg_group_addr, + buf, pastend - buf); if (addr_offset < 1) { return -5; } @@ -243,15 +231,9 @@ int pim_joinprune_recv(struct interface *ifp, /* Scan joined sources */ for (source = 0; source < msg_num_joined_sources; ++source) { - addr_offset = pim_parse_addr_source(ifp->name, src_addr, - &msg_source_addr, - &msg_source_flags, - buf, pastend - buf); -#if 0 - zlog_warn("%s: pim_parse_addr_source addr_offset=%d", - __PRETTY_FUNCTION__, - addr_offset); -#endif + addr_offset = pim_parse_addr_source (&msg_source_addr, + &msg_source_flags, + buf, pastend - buf); if (addr_offset < 1) { return -7; } @@ -267,10 +249,9 @@ int pim_joinprune_recv(struct interface *ifp, /* Scan pruned sources */ for (source = 0; source < msg_num_pruned_sources; ++source) { - addr_offset = pim_parse_addr_source(ifp->name, src_addr, - &msg_source_addr, - &msg_source_flags, - buf, pastend - buf); + addr_offset = pim_parse_addr_source (&msg_source_addr, + &msg_source_flags, + buf, pastend - buf); if (addr_offset < 1) { return -8; } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 0c768be122..38f6de9fea 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -97,6 +97,25 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) +static int +pim_encode_unicast_address (uint8_t *buf, struct prefix *p) +{ + switch (p->family) + { + case AF_INET: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ + ++buf; + *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ + ++buf; + memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); + return ucast_ipv4_encoding_len; + break; + default: + return 0; + break; + } +} + uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, struct list *ifconnected) @@ -121,22 +140,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, for (; node; node = listnextnode(node)) { struct connected *ifc = listgetdata(node); struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; + int l_encode; if ((curr + ucast_ipv4_encoding_len) > buf_pastend) return 0; - /* Write encoded unicast IPv4 address */ - *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - ++curr; - *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ - ++curr; - memcpy(curr, &p->u.prefix4, sizeof(struct in_addr)); - curr += sizeof(struct in_addr); - - option_len += ucast_ipv4_encoding_len; + l_encode = pim_encode_unicast_address (curr, p); + curr += l_encode; + option_len += l_encode; } if (PIM_DEBUG_PIM_TRACE_DETAIL) { @@ -340,10 +351,10 @@ int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, return 0; } -int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, - struct prefix *p, - const uint8_t *buf, - int buf_size) +int +pim_parse_addr_ucast (struct prefix *p, + const uint8_t *buf, + int buf_size) { const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ const uint8_t *addr; @@ -352,12 +363,9 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, int type; if (buf_size < ucast_encoding_min_len) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d from %s on %s", + zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d", __PRETTY_FUNCTION__, - buf_size, ucast_encoding_min_len, - src_str, ifname); + buf_size, ucast_encoding_min_len); return -1; } @@ -367,24 +375,19 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, family = *addr++; type = *addr++; + if (type) { + zlog_warn("%s: unknown unicast address encoding type=%d", + __PRETTY_FUNCTION__, + type); + return -2; + } + switch (family) { case PIM_MSG_ADDRESS_FAMILY_IPV4: - if (type) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s", - __PRETTY_FUNCTION__, - type, src_str, ifname); - return -2; - } - if ((addr + sizeof(struct in_addr)) > pastend) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu from %s on %s", + zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu", __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr), - src_str, ifname); + pastend - addr, sizeof(struct in_addr)); return -3; } @@ -396,11 +399,9 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, break; default: { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s", + zlog_warn("%s: unknown unicast address encoding family=%d from", __PRETTY_FUNCTION__, - family, src_str, ifname); + family); return -4; } } @@ -408,10 +409,10 @@ int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, return addr - buf; } -int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, - struct prefix *p, - const uint8_t *buf, - int buf_size) +int +pim_parse_addr_group (struct prefix *p, + const uint8_t *buf, + int buf_size) { const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ const uint8_t *addr; @@ -421,12 +422,9 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, int mask_len; if (buf_size < grp_encoding_min_len) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s", + zlog_warn("%s: group address encoding overflow: left=%d needed=%d", __PRETTY_FUNCTION__, - buf_size, grp_encoding_min_len, - src_str, ifname); + buf_size, grp_encoding_min_len); return -1; } @@ -442,21 +440,15 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, switch (family) { case PIM_MSG_ADDRESS_FAMILY_IPV4: if (type) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown group address encoding type=%d from %s on %s", - __PRETTY_FUNCTION__, - type, src_str, ifname); + zlog_warn("%s: unknown group address encoding type=%d from", + __PRETTY_FUNCTION__, type); return -2; } if ((addr + sizeof(struct in_addr)) > pastend) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from %s on %s", + zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from", __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr), - src_str, ifname); + pastend - addr, sizeof(struct in_addr)); return -3; } @@ -469,11 +461,8 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, break; default: { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown group address encoding family=%d from %s on %s", - __PRETTY_FUNCTION__, - family, src_str, ifname); + zlog_warn("%s: unknown group address encoding family=%d from", + __PRETTY_FUNCTION__, family); return -4; } } @@ -481,12 +470,11 @@ int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, return addr - buf; } -int pim_parse_addr_source(const char *ifname, - struct in_addr src_addr, - struct prefix *p, - uint8_t *flags, - const uint8_t *buf, - int buf_size) +int +pim_parse_addr_source(struct prefix *p, + uint8_t *flags, + const uint8_t *buf, + int buf_size) { const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ const uint8_t *addr; @@ -496,12 +484,9 @@ int pim_parse_addr_source(const char *ifname, int mask_len; if (buf_size < src_encoding_min_len) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s", + zlog_warn("%s: source address encoding overflow: left=%d needed=%d", __PRETTY_FUNCTION__, - buf_size, src_encoding_min_len, - src_str, ifname); + buf_size, src_encoding_min_len); return -1; } @@ -513,25 +498,20 @@ int pim_parse_addr_source(const char *ifname, *flags = *addr++; mask_len = *addr++; + if (type) { + zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", + __PRETTY_FUNCTION__, + type, + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + return -2; + } + switch (family) { case PIM_MSG_ADDRESS_FAMILY_IPV4: - if (type) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown source address encoding type=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x", - __PRETTY_FUNCTION__, - type, src_str, ifname, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return -2; - } - if ((addr + sizeof(struct in_addr)) > pastend) { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu from %s on %s", + zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu", __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr), - src_str, ifname); + pastend - addr, sizeof(struct in_addr)); return -3; } @@ -550,10 +530,8 @@ int pim_parse_addr_source(const char *ifname, received with any other mask length. */ if (p->prefixlen != 32) { - char src_str[100]; - pim_inet4_dump("", p->u.prefix4, src_str, sizeof(src_str)); - zlog_warn("%s: IPv4 bad source address mask: %s/%d", - __PRETTY_FUNCTION__, src_str, p->prefixlen); + zlog_warn("%s: IPv4 bad source address mask: %d", + __PRETTY_FUNCTION__, p->prefixlen); return -4; } @@ -562,11 +540,9 @@ int pim_parse_addr_source(const char *ifname, break; default: { - char src_str[100]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: unknown source address encoding family=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x", + zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", __PRETTY_FUNCTION__, - family, src_str, ifname, + family, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); return -5; } @@ -606,8 +582,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, /* Parse ucast addr */ - addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp, - addr, pastend - addr); + addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); if (addr_offset < 1) { char src_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index b802cf8977..59d49954e7 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -115,17 +115,13 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, uint16_t option_len, const uint8_t *tlv_curr); -int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr, - struct prefix *p, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, - struct prefix *p, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_source(const char *ifname, - struct in_addr src_addr, - struct prefix *p, +int pim_parse_addr_ucast (struct prefix *p, + const uint8_t *buf, + int buf_size); +int pim_parse_addr_group (struct prefix *p, + const uint8_t *buf, + int buf_size); +int pim_parse_addr_source(struct prefix *p, uint8_t *flags, const uint8_t *buf, int buf_size); From 7fb21a9f987c06edd11a23fed0999ef36d7fe685 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Thu, 14 Jul 2016 13:04:47 +0000 Subject: [PATCH 042/226] bgpd: Make ASN optional for `no router bgp` When there is one BGP router instance, `no router bgp` may be used to deconfigure it without specifying its ASN Signed-off-by: Quentin Young --- bgpd/bgp_vty.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b1a3116be3..e62a225b0f 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -745,17 +745,39 @@ DEFUN (no_router_bgp, struct bgp *bgp; const char *name = NULL; - VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX); - if (argc == 3) - name = argv[2]; - - /* Lookup bgp structure. */ - bgp = bgp_lookup (as, name); - if (! bgp) + // "no router bgp" without an ASN + if (argc < 1) { - vty_out (vty, "%% Can't find BGP instance%s", VTY_NEWLINE); - return CMD_WARNING; + //Pending: Make VRF option available for ASN less config + bgp = bgp_get_default(); + + if (bgp == NULL) + { + vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (listcount(bm->bgp) > 1) + { + vty_out (vty, "%% Multiple BGP processes are configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX); + + if (argc == 3) + name = argv[2]; + + /* Lookup bgp structure. */ + bgp = bgp_lookup (as, name); + if (! bgp) + { + vty_out (vty, "%% Can't find BGP instance%s", VTY_NEWLINE); + return CMD_WARNING; + } } bgp_delete (bgp); @@ -773,6 +795,13 @@ ALIAS (no_router_bgp, "BGP view\nBGP VRF\n" "View/VRF name\n") +ALIAS (no_router_bgp, + no_router_bgp_noasn_cmd, + "no router bgp", + NO_STR + ROUTER_STR + BGP_STR) + /* BGP router-id. */ DEFUN (bgp_router_id, @@ -14382,6 +14411,7 @@ bgp_vty_init (void) /* "no router bgp" commands. */ install_element (CONFIG_NODE, &no_router_bgp_cmd); install_element (CONFIG_NODE, &no_router_bgp_instance_cmd); + install_element (CONFIG_NODE, &no_router_bgp_noasn_cmd); /* "bgp router-id" commands. */ install_element (BGP_NODE, &bgp_router_id_cmd); From 633e504d0a87cbaac2a700ceb667be04281064bf Mon Sep 17 00:00:00 2001 From: Don Slice Date: Fri, 15 Jul 2016 06:33:48 -0700 Subject: [PATCH 043/226] zebra: Eliminate use of imported arp entries as next-hops for other routes Ticket: CM-8228 Signed-off-by: Donald Slice Reviewed By: Testing Done: Manual testing succesful. bgp-min and ospf-smoke successful. redistribute-neighbor-smoke has the same failures as the base image. Problem was due to considering imported /32 arp entries as elible next-hops for other routes (in this case a static route.) This confuses the rib since this next-hop is considered both recursive and onlink. Disallowed the use of this imported arp entry in next-hop determination. --- zebra/zebra_rib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index d70f528f5a..8a2728a890 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -405,6 +405,10 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, { if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) continue; + + /* if the next hop is imported from another table, skip it */ + if (match->type == ZEBRA_ROUTE_TABLE) + continue; if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) break; } From 347914a0a785993200cb04ae3cbf8ff9a9104d60 Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Wed, 13 Jul 2016 15:31:27 -0700 Subject: [PATCH 044/226] Simplify BGP unnumbered configuration by eliminating the unessential. To make BGP configuration as simple as possible, assume the capability extended-nexthop to be default for interface neighbors. Also allow the ability to specify remote-as on the same line as neighbor interface to make BGP unnumbered configuration a single line. One corner case. This is the first feature for which the default for a member is different from the default for a peer-group. Since advertising the capability is only done for interface neighbors, the capability is not set for the peer-group, but is automatically set for interface neighbors that belong to that peer-group. So, if you want to disable the advertisement of this capability for an interface neighbor, you must do it per each interface neighbor. The patch is more complicated than it needs to be due to the handling of quagga reload and appropriate updates to the show running output. Ticket: CM-11830 Reviewed By: CCR-4958 Testing Done: Usual coterie, including manual --- bgpd/bgp_vty.c | 93 ++++++++++++++++++++++++++++++++++++++---- bgpd/bgpd.c | 74 ++++++++++++++++++++++++++------- tools/quagga-reload.py | 50 +++++++++++++++++++++++ 3 files changed, 193 insertions(+), 24 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index cc6d3d2339..4db0043d73 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2691,9 +2691,11 @@ DEFUN (neighbor_remote_as, static int peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, - safi_t safi, int v6only, const char *peer_group_name) + safi_t safi, int v6only, const char *peer_group_name, + const char *as_str) { - as_t as; + as_t as = 0; + int as_type = AS_UNSPECIFIED; struct bgp *bgp; struct peer *peer; struct peer_group *group; @@ -2709,14 +2711,34 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, return CMD_WARNING; } + if (as_str) + { + if (strncmp(as_str, "internal", strlen("internal")) == 0) + { + as_type = AS_INTERNAL; + } + else if (strncmp(as_str, "external", strlen("external")) == 0) + { + as_type = AS_EXTERNAL; + } + else + { + /* Get AS number. */ + VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX); + as_type = AS_SPECIFIED; + } + } + peer = peer_lookup_by_conf_if (bgp, conf_if); if (!peer) { if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, 0, 0, NULL); + peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, 0, 0, + NULL); else - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, afi, safi, NULL); + peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, afi, safi, + NULL); if (peer && v6only) SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); @@ -2727,7 +2749,10 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, * gets deleted later etc.) */ if (peer->ifp) - bgp_zebra_initiate_radv (bgp, peer); + { + bgp_zebra_initiate_radv (bgp, peer); + } + peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); } else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) || (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) @@ -2774,9 +2799,11 @@ DEFUN (neighbor_interface_config, "Enable BGP on interface\n") { if (argc == 2) - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + argv[1], NULL); else - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + NULL, NULL); } ALIAS (neighbor_interface_config, @@ -2797,9 +2824,11 @@ DEFUN (neighbor_interface_config_v6only, "Enable BGP with v6 link-local only\n") { if (argc == 2) - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + argv[1], NULL); else - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + NULL, NULL); } ALIAS (neighbor_interface_config_v6only, @@ -2812,6 +2841,30 @@ ALIAS (neighbor_interface_config_v6only, "Member of the peer-group\n" "peer-group name\n") +DEFUN (neighbor_interface_config_remote_as, + neighbor_interface_config_remote_as_cmd, + "neighbor WORD interface remote-as (" CMD_AS_RANGE "|external|internal)", + NEIGHBOR_STR + "Interface name or neighbor tag\n" + "Enable BGP on interface\n" + AS_STR) +{ + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + NULL, argv[1]); +} + +DEFUN (neighbor_interface_v6only_config_remote_as, + neighbor_interface_v6only_config_remote_as_cmd, + "neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|external|internal)", + NEIGHBOR_STR + "Interface name or neighbor tag\n" + "Enable BGP on interface\n" + AS_STR) +{ + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + NULL, argv[1]); +} + DEFUN (neighbor_peer_group, neighbor_peer_group_cmd, "neighbor WORD peer-group", @@ -2962,6 +3015,24 @@ ALIAS (no_neighbor_interface_config, "Member of the peer-group\n" "peer-group name\n") +ALIAS (no_neighbor_interface_config, + no_neighbor_interface_config_remote_as_cmd, + "no neighbor WORD interface remote-as (" CMD_AS_RANGE "|internal|external)", + NO_STR + NEIGHBOR_STR + "Interface name\n" + "Configure BGP on interface\n" + AS_STR) + +ALIAS (no_neighbor_interface_config, + no_neighbor_interface_config_v6only_remote_as_cmd, + "no neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|internal|external)", + NO_STR + NEIGHBOR_STR + "Interface name\n" + "Configure BGP on interface\n" + "Enable BGP with v6 link-local only\n" + AS_STR) DEFUN (no_neighbor_peer_group, no_neighbor_peer_group_cmd, @@ -14124,12 +14195,16 @@ bgp_vty_init (void) install_element (BGP_NODE, &neighbor_interface_config_v6only_cmd); install_element (BGP_NODE, &neighbor_interface_config_peergroup_cmd); install_element (BGP_NODE, &neighbor_interface_config_v6only_peergroup_cmd); + install_element (BGP_NODE, &neighbor_interface_config_remote_as_cmd); + install_element (BGP_NODE, &neighbor_interface_v6only_config_remote_as_cmd); install_element (BGP_NODE, &no_neighbor_cmd); install_element (BGP_NODE, &no_neighbor_remote_as_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_v6only_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_peergroup_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_v6only_peergroup_cmd); + install_element (BGP_NODE, &no_neighbor_interface_config_remote_as_cmd); + install_element (BGP_NODE, &no_neighbor_interface_config_v6only_remote_as_cmd); /* "neighbor peer-group" commands. */ install_element (BGP_NODE, &neighbor_peer_group_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ca72d2403a..f8fe902bca 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2534,6 +2534,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, int first_member = 0; afi_t afi; safi_t safi; + int cap_enhe_preset = 0; /* Lookup the peer. */ if (!peer) @@ -2568,8 +2569,18 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, first_member = 1; } + if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + cap_enhe_preset = 1; + peer_group2peer_config_copy(group, peer); + /* + * Capability extended-nexthop is enabled for an interface neighbor by + * default. So, fix that up here. + */ + if (peer->ifp && cap_enhe_preset) + peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { @@ -6260,6 +6271,8 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, struct peer *g_peer = NULL; char buf[SU_ADDRSTRLEN]; char *addr; + int if_pg_printed = FALSE; + int if_ras_printed = FALSE; /* Skip dynamic neighbors. */ if (peer_dynamic_neighbor (peer)) @@ -6281,7 +6294,25 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, vty_out (vty, " neighbor %s interface", addr); if (peer_group_active (peer)) - vty_out (vty, " peer-group %s", peer->group->name); + { + vty_out (vty, " peer-group %s", peer->group->name); + if_pg_printed = TRUE; + } + else if (peer->as_type == AS_SPECIFIED) + { + vty_out (vty, " remote-as %u", peer->as); + if_ras_printed = TRUE; + } + else if (peer->as_type == AS_INTERNAL) + { + vty_out (vty, " remote-as internal"); + if_ras_printed = TRUE; + } + else if (peer->as_type == AS_EXTERNAL) + { + vty_out (vty, " remote-as external"); + if_ras_printed = TRUE; + } vty_out (vty, "%s", VTY_NEWLINE); } @@ -6292,7 +6323,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, { g_peer = peer->group->conf; - if (g_peer->as_type == AS_UNSPECIFIED) + if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) { if (peer->as_type == AS_SPECIFIED) { @@ -6311,7 +6342,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, /* For swpX peers we displayed the peer-group * via 'neighbor swpX interface peer-group WORD' */ - if (!peer->conf_if) + if (!if_pg_printed) vty_out (vty, " neighbor %s peer-group %s%s", addr, peer->group->name, VTY_NEWLINE); } @@ -6326,18 +6357,21 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, VTY_NEWLINE); } - if (peer->as_type == AS_SPECIFIED) + if (!if_ras_printed) { - vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, - VTY_NEWLINE); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE); + if (peer->as_type == AS_SPECIFIED) + { + vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, + VTY_NEWLINE); + } + else if (peer->as_type == AS_INTERNAL) + { + vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE); + } + else if (peer->as_type == AS_EXTERNAL) + { + vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE); + } } } @@ -6532,7 +6566,17 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } /* capability extended-nexthop */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + { + if (! peer_group_active (peer) || + ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + { + vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr, + VTY_NEWLINE); + } + } + + if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { if (! peer_group_active (peer) || ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 9650822d1e..22d44b3369 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -507,6 +507,56 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_add_to_del.append((ctx_keys, swpx_interface)) lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup)) + """ + In 3.0.1 we changed how we display neighbor interface command. Older + versions of quagga would display the following: + neighbor swp1 interface + neighbor swp1 remote-as external + neighbor swp1 capability extended-nexthop + + but today we display via a single line + neighbor swp1 interface remote-as external + + and capability extended-nexthop is no longer needed because we + automatically enable it when the neighbor is of type interface. + + This change confuses quagga-reload.py so check to see if we are deleting + neighbor swp1 interface remote-as (external|internal|ASNUM) + + and adding + neighbor swp1 interface + neighbor swp1 remote-as (external|internal|ASNUM) + neighbor swp1 capability extended-nexthop + + If so then chop the del line and the corresponding add lines + """ + re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line) + re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line) + + if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas: + swpx_interface = None + swpx_remoteas = None + + if re_swpx_int_remoteas: + swpx = re_swpx_int_remoteas.group(1) + remoteas = re_swpx_int_remoteas.group(2) + swpx_interface = "neighbor %s interface" % swpx + elif re_swpx_int_v6only_remoteas: + swpx = re_swpx_int_v6only_remoteas.group(1) + remoteas = re_swpx_int_v6only_remoteas.group(2) + swpx_interface = "neighbor %s interface v6only" % swpx + + swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas) + found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface) + found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas) + tmp_ctx_keys = tuple(list(ctx_keys)) + + if found_add_swpx_interface and found_add_swpx_remoteas: + deleted = True + lines_to_del_to_del.append((ctx_keys, line)) + lines_to_add_to_del.append((ctx_keys, swpx_interface)) + lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas)) + if not deleted: found_add_line = line_exist(lines_to_add, ctx_keys, line) From b3a39dc510a258282908674e55c5b27be61a642a Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Wed, 13 Jul 2016 15:31:27 -0700 Subject: [PATCH 045/226] Simplify BGP unnumbered configuration by eliminating the unessential. To make BGP configuration as simple as possible, assume the capability extended-nexthop to be default for interface neighbors. Also allow the ability to specify remote-as on the same line as neighbor interface to make BGP unnumbered configuration a single line. One corner case. This is the first feature for which the default for a member is different from the default for a peer-group. Since advertising the capability is only done for interface neighbors, the capability is not set for the peer-group, but is automatically set for interface neighbors that belong to that peer-group. So, if you want to disable the advertisement of this capability for an interface neighbor, you must do it per each interface neighbor. The patch is more complicated than it needs to be due to the handling of quagga reload and appropriate updates to the show running output. Ticket: CM-11830 Reviewed By: CCR-4958 Testing Done: Usual coterie, including manual (cherry picked from commit 347914a0a785993200cb04ae3cbf8ff9a9104d60) --- bgpd/bgp_vty.c | 93 ++++++++++++++++++++++++++++++++++++++---- bgpd/bgpd.c | 74 ++++++++++++++++++++++++++------- tools/quagga-reload.py | 50 +++++++++++++++++++++++ 3 files changed, 193 insertions(+), 24 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e62a225b0f..5a9d431d2e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2834,9 +2834,11 @@ DEFUN (neighbor_remote_as, static int peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, - safi_t safi, int v6only, const char *peer_group_name) + safi_t safi, int v6only, const char *peer_group_name, + const char *as_str) { - as_t as; + as_t as = 0; + int as_type = AS_UNSPECIFIED; struct bgp *bgp; struct peer *peer; struct peer_group *group; @@ -2852,14 +2854,34 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, return CMD_WARNING; } + if (as_str) + { + if (strncmp(as_str, "internal", strlen("internal")) == 0) + { + as_type = AS_INTERNAL; + } + else if (strncmp(as_str, "external", strlen("external")) == 0) + { + as_type = AS_EXTERNAL; + } + else + { + /* Get AS number. */ + VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX); + as_type = AS_SPECIFIED; + } + } + peer = peer_lookup_by_conf_if (bgp, conf_if); if (!peer) { if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, 0, 0, NULL); + peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, 0, 0, + NULL); else - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, afi, safi, NULL); + peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, afi, safi, + NULL); if (peer && v6only) SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); @@ -2870,7 +2892,10 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, * gets deleted later etc.) */ if (peer->ifp) - bgp_zebra_initiate_radv (bgp, peer); + { + bgp_zebra_initiate_radv (bgp, peer); + } + peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); } else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) || (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) @@ -2917,9 +2942,11 @@ DEFUN (neighbor_interface_config, "Enable BGP on interface\n") { if (argc == 2) - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + argv[1], NULL); else - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + NULL, NULL); } ALIAS (neighbor_interface_config, @@ -2940,9 +2967,11 @@ DEFUN (neighbor_interface_config_v6only, "Enable BGP with v6 link-local only\n") { if (argc == 2) - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + argv[1], NULL); else - return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL); + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + NULL, NULL); } ALIAS (neighbor_interface_config_v6only, @@ -2955,6 +2984,30 @@ ALIAS (neighbor_interface_config_v6only, "Member of the peer-group\n" "peer-group name\n") +DEFUN (neighbor_interface_config_remote_as, + neighbor_interface_config_remote_as_cmd, + "neighbor WORD interface remote-as (" CMD_AS_RANGE "|external|internal)", + NEIGHBOR_STR + "Interface name or neighbor tag\n" + "Enable BGP on interface\n" + AS_STR) +{ + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, + NULL, argv[1]); +} + +DEFUN (neighbor_interface_v6only_config_remote_as, + neighbor_interface_v6only_config_remote_as_cmd, + "neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|external|internal)", + NEIGHBOR_STR + "Interface name or neighbor tag\n" + "Enable BGP on interface\n" + AS_STR) +{ + return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, + NULL, argv[1]); +} + DEFUN (neighbor_peer_group, neighbor_peer_group_cmd, "neighbor WORD peer-group", @@ -3105,6 +3158,24 @@ ALIAS (no_neighbor_interface_config, "Member of the peer-group\n" "peer-group name\n") +ALIAS (no_neighbor_interface_config, + no_neighbor_interface_config_remote_as_cmd, + "no neighbor WORD interface remote-as (" CMD_AS_RANGE "|internal|external)", + NO_STR + NEIGHBOR_STR + "Interface name\n" + "Configure BGP on interface\n" + AS_STR) + +ALIAS (no_neighbor_interface_config, + no_neighbor_interface_config_v6only_remote_as_cmd, + "no neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|internal|external)", + NO_STR + NEIGHBOR_STR + "Interface name\n" + "Configure BGP on interface\n" + "Enable BGP with v6 link-local only\n" + AS_STR) DEFUN (no_neighbor_peer_group, no_neighbor_peer_group_cmd, @@ -14596,12 +14667,16 @@ bgp_vty_init (void) install_element (BGP_NODE, &neighbor_interface_config_v6only_cmd); install_element (BGP_NODE, &neighbor_interface_config_peergroup_cmd); install_element (BGP_NODE, &neighbor_interface_config_v6only_peergroup_cmd); + install_element (BGP_NODE, &neighbor_interface_config_remote_as_cmd); + install_element (BGP_NODE, &neighbor_interface_v6only_config_remote_as_cmd); install_element (BGP_NODE, &no_neighbor_cmd); install_element (BGP_NODE, &no_neighbor_remote_as_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_v6only_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_peergroup_cmd); install_element (BGP_NODE, &no_neighbor_interface_config_v6only_peergroup_cmd); + install_element (BGP_NODE, &no_neighbor_interface_config_remote_as_cmd); + install_element (BGP_NODE, &no_neighbor_interface_config_v6only_remote_as_cmd); /* "neighbor peer-group" commands. */ install_element (BGP_NODE, &neighbor_peer_group_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 05f1751e53..a06e95e244 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2546,6 +2546,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, int first_member = 0; afi_t afi; safi_t safi; + int cap_enhe_preset = 0; /* Lookup the peer. */ if (!peer) @@ -2580,8 +2581,18 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, first_member = 1; } + if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + cap_enhe_preset = 1; + peer_group2peer_config_copy(group, peer); + /* + * Capability extended-nexthop is enabled for an interface neighbor by + * default. So, fix that up here. + */ + if (peer->ifp && cap_enhe_preset) + peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { @@ -6269,6 +6280,8 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, struct peer *g_peer = NULL; char buf[SU_ADDRSTRLEN]; char *addr; + int if_pg_printed = FALSE; + int if_ras_printed = FALSE; /* Skip dynamic neighbors. */ if (peer_dynamic_neighbor (peer)) @@ -6290,7 +6303,25 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, vty_out (vty, " neighbor %s interface", addr); if (peer_group_active (peer)) - vty_out (vty, " peer-group %s", peer->group->name); + { + vty_out (vty, " peer-group %s", peer->group->name); + if_pg_printed = TRUE; + } + else if (peer->as_type == AS_SPECIFIED) + { + vty_out (vty, " remote-as %u", peer->as); + if_ras_printed = TRUE; + } + else if (peer->as_type == AS_INTERNAL) + { + vty_out (vty, " remote-as internal"); + if_ras_printed = TRUE; + } + else if (peer->as_type == AS_EXTERNAL) + { + vty_out (vty, " remote-as external"); + if_ras_printed = TRUE; + } vty_out (vty, "%s", VTY_NEWLINE); } @@ -6301,7 +6332,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, { g_peer = peer->group->conf; - if (g_peer->as_type == AS_UNSPECIFIED) + if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) { if (peer->as_type == AS_SPECIFIED) { @@ -6320,7 +6351,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, /* For swpX peers we displayed the peer-group * via 'neighbor swpX interface peer-group WORD' */ - if (!peer->conf_if) + if (!if_pg_printed) vty_out (vty, " neighbor %s peer-group %s%s", addr, peer->group->name, VTY_NEWLINE); } @@ -6335,18 +6366,21 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, VTY_NEWLINE); } - if (peer->as_type == AS_SPECIFIED) + if (!if_ras_printed) { - vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, - VTY_NEWLINE); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE); + if (peer->as_type == AS_SPECIFIED) + { + vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, + VTY_NEWLINE); + } + else if (peer->as_type == AS_INTERNAL) + { + vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE); + } + else if (peer->as_type == AS_EXTERNAL) + { + vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE); + } } } @@ -6541,7 +6575,17 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } /* capability extended-nexthop */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + { + if (! peer_group_active (peer) || + ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + { + vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr, + VTY_NEWLINE); + } + } + + if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { if (! peer_group_active (peer) || ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 9650822d1e..22d44b3369 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -507,6 +507,56 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_add_to_del.append((ctx_keys, swpx_interface)) lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup)) + """ + In 3.0.1 we changed how we display neighbor interface command. Older + versions of quagga would display the following: + neighbor swp1 interface + neighbor swp1 remote-as external + neighbor swp1 capability extended-nexthop + + but today we display via a single line + neighbor swp1 interface remote-as external + + and capability extended-nexthop is no longer needed because we + automatically enable it when the neighbor is of type interface. + + This change confuses quagga-reload.py so check to see if we are deleting + neighbor swp1 interface remote-as (external|internal|ASNUM) + + and adding + neighbor swp1 interface + neighbor swp1 remote-as (external|internal|ASNUM) + neighbor swp1 capability extended-nexthop + + If so then chop the del line and the corresponding add lines + """ + re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line) + re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line) + + if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas: + swpx_interface = None + swpx_remoteas = None + + if re_swpx_int_remoteas: + swpx = re_swpx_int_remoteas.group(1) + remoteas = re_swpx_int_remoteas.group(2) + swpx_interface = "neighbor %s interface" % swpx + elif re_swpx_int_v6only_remoteas: + swpx = re_swpx_int_v6only_remoteas.group(1) + remoteas = re_swpx_int_v6only_remoteas.group(2) + swpx_interface = "neighbor %s interface v6only" % swpx + + swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas) + found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface) + found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas) + tmp_ctx_keys = tuple(list(ctx_keys)) + + if found_add_swpx_interface and found_add_swpx_remoteas: + deleted = True + lines_to_del_to_del.append((ctx_keys, line)) + lines_to_add_to_del.append((ctx_keys, swpx_interface)) + lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas)) + if not deleted: found_add_line = line_exist(lines_to_add, ctx_keys, line) From 849144993d13bae68f8eccf45c677e4a78e153bd Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 18 Jul 2016 10:32:46 -0400 Subject: [PATCH 046/226] bgpd: Use the correct bgp instance for cli commands issuing clear Some bgp commands end with doing a bgp_clear_vty, which invalidly made the assumption that the clear should always be done for the default instance. This fix derives the correct instance from the vty-index if one is supplied, and uses the default instance if it is not. Ticket: CM-10113 Signed-off-by: Don Slice Reviewed-by: Donald Sharp --- bgpd/bgp_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5a9d431d2e..c429623e7e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -523,7 +523,7 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi, } else { - bgp = bgp_get_default (); + bgp = (vty->index) ? vty->index : bgp_get_default (); if (bgp == NULL) { vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); From f013eacdc81728b875d6e16e89895048392c13f8 Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Sun, 17 Jul 2016 23:38:51 -0700 Subject: [PATCH 047/226] Don't display integrated-vtysh-config as its the default in CL. Ticket: CM-11832 Reviewed By: Testing Done: Testing that its not displayed if enabled & only if disabled In the spirit of not displaying the defaults, we shouldn't display "service integrated-vtysh-config" as its the default. It also tends to clutter the output with stuff the user doesn't know or care about. This patch removes displaying that and only prints it when the option is disabled. --- vtysh/vtysh_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index fcad333b9f..eeb635419c 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -412,8 +412,8 @@ vtysh_config_write () sprintf (line, "hostname %s", host.name); vtysh_config_parse_line(line); } - if (vtysh_writeconfig_integrated) - vtysh_config_parse_line ("service integrated-vtysh-config"); + if (!vtysh_writeconfig_integrated) + vtysh_config_parse_line ("no service integrated-vtysh-config"); user_config_write (); } From 07fc159679d3d2511dd938246d41b50bf9a9c9ce Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Sun, 17 Jul 2016 23:12:12 -0700 Subject: [PATCH 048/226] Deprecate link-detect and don't display it in show running-config Ticket: CM-11808 Reviewed By: CCR-4972 Testing Done: Usual stuff link-detect is on by default, and has been so since the first release of Cumulus Linux. So, in the light of not displaying defaults, don't display link-detect if enabled, only if disabled. --- zebra/interface.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 87a426fdc4..c3ce83dd4a 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -2114,10 +2114,8 @@ if_config_write (struct vty *vty) if (ifp->bandwidth != 0) vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE); - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - vty_out(vty, " link-detect%s", VTY_NEWLINE); - else - vty_out(vty, " no link-detect%s", VTY_NEWLINE); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) + vty_out(vty, " no link-detect%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc)) { From 5be7afc8bb6dce6f6bcf77faad3a754e52812408 Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Sun, 17 Jul 2016 23:08:05 -0700 Subject: [PATCH 049/226] Don't print empty sections as they clutter the output of show-running Ticket: CM-11808 Reviewed By: CCR-4971 Testing Done: Usual stuff including doing show running with multiple daemons Interface and VRF are both sections of the config that could possibly be empty. This unnecessarily clutters the output of show running. This patch fixes that by not displaying empty sections of interface, and vrf. Routemaps have a genuine empty stanza and so we cannot add routemap to this list. Unfortunately this means a "show running-config ospfd" may have empty route-maps if the route-maps all correspond to BGP, for example. This is not a concern for the entire "show running-config". The trick in fixing this is on the vtysh side rather than on the client side. The reason for this is that its quite tricky given the number of options to ensure that a daemon never printed a section header unless there was something to print. On the vtysh side, however, its easy to check if a section is empty and not print it. --- vtysh/vtysh.c | 5 +++-- vtysh/vtysh_config.c | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index ecb6c5c6ac..abd5d04f44 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2097,7 +2097,8 @@ DEFUN (vtysh_write_terminal, vty_out (vty, "!%s", VTY_NEWLINE); for (i = 0; i < array_size(vtysh_client); i++) - vtysh_client_config (&vtysh_client[i], line); + if ((argc < 1 ) || (begins_with(vtysh_client[i].name, argv[0]))) + vtysh_client_config (&vtysh_client[i], line); /* Integrate vtysh specific configuration. */ vtysh_config_write (); @@ -2317,7 +2318,7 @@ ALIAS (vtysh_write_terminal, SHOW_STR "Current operating configuration\n") -ALIAS (vtysh_write_terminal_daemon, +ALIAS (vtysh_write_terminal, vtysh_show_running_config_daemon_cmd, "show running-config (zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pimd)", SHOW_STR diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index eeb635419c..e678fc1a8b 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -318,7 +318,14 @@ vtysh_config_dump (FILE *fp) if ((master = vector_slot (configvec, i)) != NULL) { for (ALL_LIST_ELEMENTS (master, node, nnode, config)) - { + { + /* Don't print empty sections for interface/vrf. Route maps on the + * other hand could have a legitimate empty section at the end. + */ + if ((config->index == INTERFACE_NODE || (config->index == VRF_NODE)) + && list_isempty (config->line)) + continue; + fprintf (fp, "%s\n", config->name); fflush (fp); From 58136de99d37b5f5d9905e43f2e385d29f751251 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 19 Jul 2016 19:17:38 -0700 Subject: [PATCH 050/226] ospfd: Ensure correct handling of router-id change Upon router-id change, one object that needs to be updated is the "nbr_self" structure that is created to contain information about the local router and is used during DR election, among other things. In the past, the code used to just change the router-id field of this structure. This is actually not sufficient - the neighbor has to be deleted and re-added into the tree. This was fixed upstream and the fix is now available in our tree, but those changes don't work well with prior Cumulus changes to defer updating the router-id in the OSPF instance until other cleanup has happened. Fixed code to update the "nbr_self" structure correctly while continuing to defer the router_id update in the OSPF structure. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: CM-11861 Reviewed By: CCR-4980 Testing Done: Manual, failed test --- ospfd/ospf_interface.c | 4 ++-- ospfd/ospf_neighbor.c | 8 ++++---- ospfd/ospf_neighbor.h | 4 ++-- ospfd/ospfd.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index a062004ac4..5602ebe897 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -297,7 +297,7 @@ ospf_if_cleanup (struct ospf_interface *oi) ospf_ls_upd_queue_empty (oi); /* Reset pseudo neighbor. */ - ospf_nbr_self_reset (oi); + ospf_nbr_self_reset (oi, oi->ospf->router_id); } void @@ -926,7 +926,7 @@ ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data) zlog_debug ("ospf_vl_new(): set associated area to the backbone"); /* Add pseudo neighbor. */ - ospf_nbr_self_reset (voi); + ospf_nbr_self_reset (voi, voi->ospf->router_id); ospf_area_add_if (voi->area, voi); diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 16753b85df..1954447b64 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -238,18 +238,18 @@ ospf_nbr_bidirectional (struct in_addr *router_id, /* reset nbr_self */ void -ospf_nbr_self_reset (struct ospf_interface *oi) +ospf_nbr_self_reset (struct ospf_interface *oi, struct in_addr router_id) { if (oi->nbr_self) ospf_nbr_delete (oi->nbr_self); oi->nbr_self = ospf_nbr_new (oi); - ospf_nbr_add_self (oi); + ospf_nbr_add_self (oi, router_id); } /* Add self to nbr list. */ void -ospf_nbr_add_self (struct ospf_interface *oi) +ospf_nbr_add_self (struct ospf_interface *oi, struct in_addr router_id) { struct prefix p; struct route_node *rn; @@ -260,7 +260,7 @@ ospf_nbr_add_self (struct ospf_interface *oi) /* Initial state */ oi->nbr_self->address = *oi->address; oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); - oi->nbr_self->router_id = oi->ospf->router_id; + oi->nbr_self->router_id = router_id; oi->nbr_self->src = oi->address->u.prefix4; oi->nbr_self->state = NSM_TwoWay; diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 81e212b573..0e209d2117 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -102,8 +102,8 @@ extern struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *); extern void ospf_nbr_free (struct ospf_neighbor *); extern void ospf_nbr_delete (struct ospf_neighbor *); extern int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int); -extern void ospf_nbr_self_reset (struct ospf_interface *); -extern void ospf_nbr_add_self (struct ospf_interface *); +extern void ospf_nbr_self_reset (struct ospf_interface *, struct in_addr); +extern void ospf_nbr_add_self (struct ospf_interface *, struct in_addr); extern int ospf_nbr_count (struct ospf_interface *, int); #ifdef HAVE_OPAQUE_LSA extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index ea66042f2e..2034ed1dbd 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -124,7 +124,7 @@ ospf_router_id_update (struct ospf *ospf) * oi->nbr_self->router_id = router_id for * !(virtual | ptop) links */ - ospf_nbr_self_reset (oi); + ospf_nbr_self_reset (oi, router_id); } /* If AS-external-LSA is queued, then flush those LSAs. */ @@ -888,7 +888,7 @@ add_ospf_interface (struct interface *ifp, struct ospf_area *area, oi->type = IF_DEF_PARAMS (ifp)->type; /* Add pseudo neighbor. */ - ospf_nbr_self_reset (oi); + ospf_nbr_self_reset (oi, oi->ospf->router_id); ospf_area_add_if (oi->area, oi); @@ -1160,7 +1160,7 @@ ospf_network_run_interface (struct prefix *p, struct ospf_area *area, oi->output_cost = ospf_if_get_output_cost (oi); /* Add pseudo neighbor. */ - ospf_nbr_add_self (oi); + ospf_nbr_add_self (oi, oi->ospf->router_id); /* Relate ospf interface to ospf instance. */ oi->ospf = area->ospf; From 46827ae98a459e157803df6acdaf5c0ebc51f140 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 20 Jul 2016 08:02:04 -0400 Subject: [PATCH 051/226] bgpd: Print the correct table in "show ip bgp x.x.x.x" Prior to this change, bgp always identified the routing table used as the default in the output of "show ip bgp x.x.x.x". This fix changes the behavior to use the correct table name. Ticket: CM-10239 Signed-off-by: Don Slice Reviewed-by: Donald Sharp --- bgpd/bgp_route.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fff595d190..fc6db0863d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7634,7 +7634,9 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, { vty_out (vty, ", best #%d", best); if (safi == SAFI_UNICAST) - vty_out (vty, ", table Default-IP-Routing-Table"); + vty_out (vty, ", table %s", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default-IP-Routing-Table" : bgp->name); } else vty_out (vty, ", no best path"); From 6ac9179ca77086c96a3c0a5de03420ec8b830db3 Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Wed, 20 Jul 2016 08:24:47 -0700 Subject: [PATCH 052/226] Make vtysh-integrated-config truly the default and fix quagga reload for this. Ticket: CM-11910 Reviewed By: sharpd, routing-dev slack Testing Done: Test with nothing in vtysh.conf, add no, remove it etc. Even though we force integrated config to be the default, we do this by adding a line to our default vtysh.conf which has integrated config enabled. When we stopped printing integrated-config as part of wr mem or show running-config, we broke quagga reload because it was explicitly looking for integrated config. Furthermore, merely fixing quagga reload wouldn't work because subsequent saves would result in config being saved to individual files since vtysh.conf no longer forced the file to be integrated. This patch fixes both issues. Makes integrated config the default in the code, rather than via a shipped default file, and fixes quagga reload to look for the "no integrated-vtysh-config" to deny attempting a reload. --- tools/quagga-reload.py | 6 +++--- vtysh/vtysh.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 22d44b3369..f90b3e95fc 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -708,15 +708,15 @@ if __name__ == '__main__': # Verify that 'service integrated-vtysh-config' is configured vtysh_filename = '/etc/quagga/vtysh.conf' - service_integrated_vtysh_config = False + service_integrated_vtysh_config = True if os.path.isfile(vtysh_filename): with open(vtysh_filename, 'r') as fh: for line in fh.readlines(): line = line.strip() - if line == 'service integrated-vtysh-config': - service_integrated_vtysh_config = True + if line == 'no service integrated-vtysh-config': + service_integrated_vtysh_config = False break if not service_integrated_vtysh_config: diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index abd5d04f44..ad43f41fd9 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -71,7 +71,7 @@ struct vtysh_client vtysh_client[] = }; /* Using integrated config from Quagga.conf. Default is no. */ -int vtysh_writeconfig_integrated = 0; +int vtysh_writeconfig_integrated = 1; extern char config_default[]; From 1ee08155dac77fb5a28f64e94df4dd6f7a7d3f3b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 19:50:51 -0400 Subject: [PATCH 053/226] lib: Modify 'banner motd file ' Modify the banner motd file X command to do these things differently: 1) Only allow the file to be in SYSCONFDIR 2) Only allow the user to use a file that exists. Signed-off-by: Donald Sharp Reviewed-by: Dinesh Dutt --- lib/command.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/command.c b/lib/command.c index 34864e9d3f..eea4fc1960 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3912,11 +3912,25 @@ DEFUN (no_config_log_timestamp_precision, int cmd_banner_motd_file (const char *file) { - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - host.motdfile = XSTRDUP (MTYPE_HOST, file); + int success = CMD_SUCCESS; + char p[PATH_MAX]; + char *rpath; + char *in; - return CMD_SUCCESS; + rpath = realpath (file, p); + if (!rpath) + return CMD_ERR_NO_FILE; + in = strstr (rpath, SYSCONFDIR); + if (in == rpath) + { + if (host.motdfile) + XFREE (MTYPE_HOST, host.motdfile); + host.motdfile = XSTRDUP (MTYPE_HOST, file); + } + else + success = CMD_WARNING; + + return success; } DEFUN (banner_motd_file, @@ -3927,7 +3941,15 @@ DEFUN (banner_motd_file, "Banner from a file\n" "Filename\n") { - return cmd_banner_motd_file (argv[0]); + int cmd = cmd_banner_motd_file (argv[0]); + + if (cmd == CMD_ERR_NO_FILE) + vty_out (vty, "%s does not exist", argv[0]); + else if (cmd == CMD_WARNING) + vty_out (vty, "%s must be in %s", + argv[0], SYSCONFDIR); + + return cmd; } DEFUN (banner_motd_default, From 4f2125df1ff3063af7de403e8165f38aef9c59ef Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 26 Jul 2016 12:42:28 -0400 Subject: [PATCH 054/226] debian: Disable pimd in cmaster-next Turn off the building of pimd in cmaster-next. Ticket: CM-12015 Signed-off-by: Donald Sharp Reviewed-by: Daniel Walton --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index 7a48448068..25461b89d8 100755 --- a/debian/rules +++ b/debian/rules @@ -53,6 +53,7 @@ override_dh_auto_configure: --enable-systemd=yes \ --enable-poll=yes \ --enable-cumulus=yes \ + --enable-pimd=no \ --enable-dependency-tracking; \ fi From 87e8267a836a9d5ebb33ec754c7478619a84cbd9 Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Tue, 26 Jul 2016 10:23:46 -0700 Subject: [PATCH 055/226] bgpd: Fix for vtysh -m does not mark "end" of router bgp There was an exit added at the end of the BGP commands after we pulled the code from upstream. This was causing the reload scripts to fail. Removed this exit. Ticket: CM-11464 CM-11924 Reviewed By: CCR-4995 Testing Done: Manual --- bgpd/bgpd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a06e95e244..49fc9e22a2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7268,8 +7268,6 @@ bgp_config_write (struct vty *vty) /* ENCAPv6 configuration. */ write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP); - vty_out (vty, " exit%s", VTY_NEWLINE); - write++; } return write; From 598a479fb34f837b76a29fb3560da2dcbcd3de12 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 26 Jul 2016 13:32:52 -0400 Subject: [PATCH 056/226] debian: Remove pimd build object from packaging We've disabled pimd, remove the build object from our packaging. Signed-off-by: Donald Sharp Reviewed-by: Vivek Venkataraman --- debian/quagga.install | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/quagga.install b/debian/quagga.install index 2651dd9e00..6a70be9925 100644 --- a/debian/quagga.install +++ b/debian/quagga.install @@ -1,6 +1,5 @@ etc/quagga/ usr/bin/vtysh -usr/bin/test_igmpv3_join usr/include/quagga/ usr/lib/ tools/quagga-reload.py usr/lib/quagga/ From 711093b5ebfd059f433396e4bca98216e02482fb Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 26 Jul 2016 10:45:51 -0700 Subject: [PATCH 057/226] bgpd: Fix attribute handling upon redistribution metric change When the metric for a redistributed route is changed through configuration, the path attribute for the route/routes need to be "re-created" as the hash entry would change. In the absence of this, the entry would have the correct values but when a hash lookup is done at a later time (e.g., when trying to free the entry), it would fail. This patch addresses the "re-creation" Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: CM-11168 Reviewed By: CCR-4990 Testing Done: Manual, bgp-smoke --- bgpd/bgp_zebra.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 4a39bc2b2e..888a819d06 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1891,16 +1891,30 @@ bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi, red->redist_metric_flag = 1; red->redist_metric = metric; - for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) { - if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && ri->type == type && - ri->instance == red->instance) { - ri->attr->med = red->redist_metric; - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); - bgp_process(bgp, rn, afi, SAFI_UNICAST); - } + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) + { + for (ri = rn->info; ri; ri = ri->next) + { + if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && + ri->type == type && + ri->instance == red->instance) + { + struct attr *old_attr; + struct attr new_attr; + struct attr_extra new_extra; + + new_attr.extra = &new_extra; + bgp_attr_dup (&new_attr, ri->attr); + new_attr.med = red->redist_metric; + old_attr = ri->attr; + ri->attr = bgp_attr_intern (&new_attr); + bgp_attr_unintern (&old_attr); + + bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } + } } - } return 1; } From c9a42b3d91e85d9aa400c65f0d217648c094eef0 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Tue, 26 Jul 2016 06:44:39 -0700 Subject: [PATCH 058/226] lib: Free memory correctly when braces used in parser When braces (optional parameters) are used in the quagga parser, there was a small leak on every iteration. Since this construct is primarily used in the configuation process rather than show commands, it was not readily apparent. With the addition of the "show ip bgp {json}" form of the commands, each time one was run, memory was leaked. Ticket: CM-11435 Signed-off-by: Don Slice Reviewed By: Donald Sharp Testing Done: Manual testing, bgp-min and bgp-smoke successful --- lib/command.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/command.c b/lib/command.c index eea4fc1960..b3819048e5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1427,6 +1427,7 @@ cmd_matcher_build_keyword_args(struct cmd_matcher *matcher, { word_token = vector_slot(keyword_vector, 0); arg = word_token->cmd; + XFREE (MTYPE_TMP, keyword_args); } else { From df08c28ed600e247f745b2b0aab9089f3195a403 Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Tue, 26 Jul 2016 18:20:37 -0700 Subject: [PATCH 059/226] bgpd: Fix for CM-11908 BGP: 'Address-family encap' cli issues Made fix to handle the "Ambigious command" for address-family vpvn6 and vpnv6 unicast. Rest of the bug analysis is below: 1. Issues with address-family encap/address-family encapv6/address-family vpnv6/address-family vpnv6 unicast need to be added to the ignore list in the test file tests.l3.quagga_cfg_cli_crawler_test. Sid to fix the "Ambiguous command" for vpnv6 as part of fix for this bug. 2. Neighbor disable-connected-check/ttl. Options should not be listed for interface. Anitha to file bugs for these. And also remove these commands from the test file tests.l3.quagga_cfg_cli_crawler_test. Ticket: CM-11908 Reviewed By: CCR-4999 Testing Done: Manual, Ran the tests.l3.quagga_cfg_cli_crawler_test --- vtysh/extract.pl.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index e8992a036a..a7b78bd7b9 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -58,6 +58,8 @@ $ignore{'"address-family ipv4 vrf NAME"'} = "ignore"; $ignore{'"address-family encap"'} = "ignore"; $ignore{'"address-family encapv4"'} = "ignore"; $ignore{'"address-family encapv6"'} = "ignore"; +$ignore{'"address-family vpnv6"'} = "ignore"; +$ignore{'"address-family vpnv6 unicast"'} = "ignore"; $ignore{'"exit-address-family"'} = "ignore"; $ignore{'"key chain WORD"'} = "ignore"; $ignore{'"key <0-2147483647>"'} = "ignore"; From d11f748b30d6867e13a77ed83666cb34881a2f53 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Jul 2016 19:39:44 +0200 Subject: [PATCH 060/226] *: fixup snmp support - HAVE_POLL is overloaded by net-snmp - missing includes - ospf6_snmp converted to vrf_iflist() Signed-off-by: David Lamparter --- lib/agentx.c | 1 + lib/thread.c | 12 ++++++++++++ ospf6d/ospf6_snmp.c | 8 +++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/agentx.c b/lib/agentx.c index bb95903adf..9dc5b47de3 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -27,6 +27,7 @@ #include "command.h" #include "smux.h" +#include "memory.h" int agentx_enabled = 0; diff --git a/lib/thread.c b/lib/thread.c index 8d75509b1d..a8ccb8b3d0 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -33,11 +33,23 @@ #include "sigevent.h" #if defined HAVE_SNMP && defined SNMP_AGENTX + +#ifdef HAVE_POLL +#define QUAGGA_HAVE_POLL +#endif + #include #include #include #include +#ifdef HAVE_POLL +#undef HAVE_POLL +#endif +#ifdef QUAGGA_HAVE_POLL +#define HAVE_POLL +#endif + extern int agentx_enabled; #endif diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 307d420ece..7423a3733a 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -29,6 +29,8 @@ #include "log.h" #include "vty.h" #include "linklist.h" +#include "vector.h" +#include "vrf.h" #include "smux.h" #include "ospf6_proto.h" @@ -749,7 +751,7 @@ ospfv3WwLsdbEntry (struct variable *v, oid *name, size_t *length, ifslist = list_new (); if (!ifslist) return NULL; ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (iflist, node, iif)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, iif)) listnode_add_sort (ifslist, iif); for (ALL_LIST_ELEMENTS_RO (ifslist, node, iif)) @@ -887,7 +889,7 @@ ospfv3IfEntry (struct variable *v, oid *name, size_t *length, ifslist = list_new (); if (!ifslist) return NULL; ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (iflist, i, iif)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif)) listnode_add_sort (ifslist, iif); for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif)) @@ -1047,7 +1049,7 @@ ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, ifslist = list_new (); if (!ifslist) return NULL; ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (iflist, i, iif)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif)) listnode_add_sort (ifslist, iif); for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif)) From fbfa8891688004bc6f554b759accee9ed917c5df Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Jul 2016 19:39:45 +0200 Subject: [PATCH 061/226] Revert "lib: Rewrite ipv4 address and prefix validator" This reverts commit d4dc41b6a23d5156b0d9068006a1eeb3ba32e301. The rewritten parser fails to recognise "1.2." as partial input for an IPv4 address, which causes "make check" to fail. Signed-off-by: David Lamparter --- lib/command.c | 152 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 40 deletions(-) diff --git a/lib/command.c b/lib/command.c index b3819048e5..4896c8a958 100644 --- a/lib/command.c +++ b/lib/command.c @@ -865,29 +865,59 @@ enum match_type exact_match }; -#define IPV4_ADDR_STR "0123456789." -#define IPV4_PREFIX_STR "0123456789./" - -/** - * Determines whether a string is a valid ipv4 token. - * - * @param[in] str the string to match - * @return exact_match if the string is an exact match, no_match/partly_match - * otherwise - */ static enum match_type cmd_ipv4_match (const char *str) { - struct sockaddr_in sin_dummy; + const char *sp; + int dots = 0, nums = 0; + char buf[4]; if (str == NULL) return partly_match; - if (strspn (str, IPV4_ADDR_STR) != strlen (str)) - return no_match; + for (;;) + { + memset (buf, 0, sizeof (buf)); + sp = str; + while (*str != '\0') + { + if (*str == '.') + { + if (dots >= 3) + return no_match; - if (inet_pton(AF_INET, str, &sin_dummy.sin_addr) != 1) - return no_match; + if (*(str + 1) == '.') + return no_match; + + if (*(str + 1) == '\0') + return partly_match; + + dots++; + break; + } + if (!isdigit ((int) *str)) + return no_match; + + str++; + } + + if (str - sp > 3) + return no_match; + + strncpy (buf, sp, str - sp); + if (atoi (buf) > 255) + return no_match; + + nums++; + + if (*str == '\0') + break; + + str++; + } + + if (nums < 4) + return partly_match; return exact_match; } @@ -895,37 +925,79 @@ cmd_ipv4_match (const char *str) static enum match_type cmd_ipv4_prefix_match (const char *str) { - struct sockaddr_in sin_dummy; - const char *delim = "/\0"; - char *dupe, *prefix, *mask, *context, *endptr; - int nmask = -1; + const char *sp; + int dots = 0; + char buf[4]; if (str == NULL) return partly_match; - if (strspn (str, IPV4_PREFIX_STR) != strlen (str)) + for (;;) + { + memset (buf, 0, sizeof (buf)); + sp = str; + while (*str != '\0' && *str != '/') + { + if (*str == '.') + { + if (dots == 3) + return no_match; + + if (*(str + 1) == '.' || *(str + 1) == '/') + return no_match; + + if (*(str + 1) == '\0') + return partly_match; + + dots++; + break; + } + + if (!isdigit ((int) *str)) + return no_match; + + str++; + } + + if (str - sp > 3) + return no_match; + + strncpy (buf, sp, str - sp); + if (atoi (buf) > 255) + return no_match; + + if (dots == 3) + { + if (*str == '/') + { + if (*(str + 1) == '\0') + return partly_match; + + str++; + break; + } + else if (*str == '\0') + return partly_match; + } + + if (*str == '\0') + return partly_match; + + str++; + } + + sp = str; + while (*str != '\0') + { + if (!isdigit ((int) *str)) + return no_match; + + str++; + } + + if (atoi (sp) > 32) return no_match; - /* tokenize to address + mask */ - dupe = XMALLOC(MTYPE_TMP, strlen(str)+1); - strncpy(dupe, str, strlen(str)+1); - prefix = strtok_r(dupe, delim, &context); - mask = strtok_r(NULL, delim, &context); - - if (!mask) - return partly_match; - - /* validate prefix */ - if (inet_pton(AF_INET, prefix, &sin_dummy.sin_addr) != 1) - return no_match; - - /* validate mask */ - nmask = strtol (mask, &endptr, 10); - if (*endptr != '\0' || nmask < 0 || nmask > 32) - return no_match; - - XFREE(MTYPE_TMP, dupe); - return exact_match; } From 355cf2a71abff73fc0ae9c53ac6200f330290c2b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Jul 2016 19:39:46 +0200 Subject: [PATCH 062/226] tests: update testcli reference output an extra comment line got added somewhere inbetween. Signed-off-by: David Lamparter --- tests/testcli.refout | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/testcli.refout b/tests/testcli.refout index 1515ea2c65..7da5494827 100644 --- a/tests/testcli.refout +++ b/tests/testcli.refout @@ -272,6 +272,7 @@ Current configuration: ! hostname test ! +! line vty ! end @@ -283,6 +284,7 @@ Current configuration: ! hostname foohost ! +! line vty ! end From e62d0e2535b46e3eb6887b2276278c5c468b4731 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Jul 2016 20:02:54 +0200 Subject: [PATCH 063/226] pimd: supply VIFF_USE_IFINDEX definition This fixes compilation if the system libc doesn't have VIFF_USE_IFINDEX. It'll still break runtime if the kernel is older than 2.6.32. Signed-off-by: David Lamparter --- pimd/pim_iface.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 1dfbd9990a..14c8c7262e 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -41,6 +41,19 @@ #include "pim_time.h" #include "pim_ssmpingd.h" +#ifndef VIFF_USE_IFINDEX +# ifdef linux +/* make it work compile-time - whether it works runtime depends on the user + * having 2.6.32 or newer */ +# define VIFF_USE_IFINDEX 0x8 +# else +# error no VIFF_USE_IFINDEX on this system, code needs porting +/* NB: without VIFF_USE_IFINDEX, the local IP address is used to identify + * interfaces, which means it's impossible to support multiple interfaces that + * have the same or no IP address (e.g. unnumbered) */ +# endif +#endif + struct interface *pim_regiface = NULL; static void pim_if_igmp_join_del_all(struct interface *ifp); From f31fa00421513629cea43a8b4274b23383480677 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Thu, 28 Jul 2016 14:35:48 -0700 Subject: [PATCH 064/226] bgpd: Pass correct bgp-name for clear command Found that original fix for CM-10113 had a significant flaw, that by deriving the bgp instance from the vty->index, if a clear ip bgp command was entered from a vty index other then bgp, a crash occurred. This fix passes the bgp->name to the clear functions so the correct instance can be derived. Tested manually in both the CM-10113 case as well as the problem discovered while testing CM-11480. Ticket: CM-10113 Signed-off-by: Don Slice Reviewed-by: --- bgpd/bgp_vty.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c429623e7e..bef9856a9d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -523,7 +523,7 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi, } else { - bgp = (vty->index) ? vty->index : bgp_get_default (); + bgp = bgp_get_default (); if (bgp == NULL) { vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); @@ -536,26 +536,22 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi, /* clear soft inbound */ static void -bgp_clear_star_soft_in (struct vty *vty) +bgp_clear_star_soft_in (struct vty *vty, const char *name) { - bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all, + bgp_clear_vty (vty,name, AFI_IP, SAFI_UNICAST, clear_all, BGP_CLEAR_SOFT_IN, NULL); -#ifdef HAVE_IPV6 - bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all, + bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all, BGP_CLEAR_SOFT_IN, NULL); -#endif /* HAVE_IPV6 */ } /* clear soft outbound */ static void -bgp_clear_star_soft_out (struct vty *vty) +bgp_clear_star_soft_out (struct vty *vty, const char *name) { - bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all, + bgp_clear_vty (vty, name, AFI_IP, SAFI_UNICAST, clear_all, BGP_CLEAR_SOFT_OUT, NULL); -#ifdef HAVE_IPV6 - bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all, + bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all, BGP_CLEAR_SOFT_OUT, NULL); -#endif /* HAVE_IPV6 */ } @@ -965,7 +961,7 @@ DEFUN (bgp_cluster_id, } bgp_cluster_id_set (bgp, &cluster); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); return CMD_SUCCESS; } @@ -1001,7 +997,7 @@ DEFUN (no_bgp_cluster_id, } bgp_cluster_id_unset (bgp); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); return CMD_SUCCESS; } @@ -1698,7 +1694,7 @@ DEFUN (bgp_client_to_client_reflection, bgp = vty->index; bgp_flag_unset (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); return CMD_SUCCESS; } @@ -1715,7 +1711,7 @@ DEFUN (no_bgp_client_to_client_reflection, bgp = vty->index; bgp_flag_set (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); return CMD_SUCCESS; } @@ -1936,7 +1932,7 @@ DEFUN (bgp_enforce_first_as, bgp = vty->index; bgp_flag_set (bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } @@ -1952,7 +1948,7 @@ DEFUN (no_bgp_enforce_first_as, bgp = vty->index; bgp_flag_unset (bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } @@ -2370,7 +2366,7 @@ DEFUN (bgp_default_local_preference, VTY_GET_INTEGER ("local preference", local_pref, argv[0]); bgp_default_local_preference_set (bgp, local_pref); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } @@ -2387,7 +2383,7 @@ DEFUN (no_bgp_default_local_preference, bgp = vty->index; bgp_default_local_preference_unset (bgp); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } @@ -2460,7 +2456,7 @@ DEFUN (bgp_rr_allow_outbound_policy, { bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); update_group_announce_rrclients(bgp); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); } return CMD_SUCCESS; @@ -2482,7 +2478,7 @@ DEFUN (no_bgp_rr_allow_outbound_policy, { bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); update_group_announce_rrclients(bgp); - bgp_clear_star_soft_out (vty); + bgp_clear_star_soft_out (vty, bgp->name); } return CMD_SUCCESS; @@ -2729,7 +2725,7 @@ DEFUN (bgp_disable_connected_route_check, bgp = vty->index; bgp_flag_set (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } @@ -2745,7 +2741,7 @@ DEFUN (no_bgp_disable_connected_route_check, bgp = vty->index; bgp_flag_unset (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); - bgp_clear_star_soft_in (vty); + bgp_clear_star_soft_in (vty, bgp->name); return CMD_SUCCESS; } From 4760600f788c71aec45ef13edd6a017faf73f9ca Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:33 +0200 Subject: [PATCH 065/226] bgpd: minor header/API clean up Adds "const" on: - peer_update_source_addr_set() - peer_description_set() Adds parameter names on: - bgp_timers_set() (really confusing, this one, with 2 unexplained args of same type) Adds new setter: - peer_afc_set(), calling peer_activate/peer_deactivate. (intended for API consumers, matches peer->afc) Signed-off-by: David Lamparter --- bgpd/bgpd.c | 13 +++++++++++-- bgpd/bgpd.h | 9 +++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 49fc9e22a2..9377568ec8 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1827,6 +1827,15 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) return ret; } +int +peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable) +{ + if (enable) + return peer_activate (peer, afi, safi); + else + return peer_deactivate (peer, afi, safi); +} + static void peer_nsf_stop (struct peer *peer) { @@ -4089,7 +4098,7 @@ peer_ebgp_multihop_unset (struct peer *peer) /* Neighbor description. */ int -peer_description_set (struct peer *peer, char *desc) +peer_description_set (struct peer *peer, const char *desc) { if (peer->desc) XFREE (MTYPE_PEER_DESC, peer->desc); @@ -4182,7 +4191,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname) } int -peer_update_source_addr_set (struct peer *peer, union sockunion *su) +peer_update_source_addr_set (struct peer *peer, const union sockunion *su) { struct peer_group *group; struct listnode *node, *nnode; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 2acdaed331..db857a8867 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1220,7 +1220,7 @@ extern int bgp_confederation_peers_check (struct bgp *, as_t); extern int bgp_confederation_peers_add (struct bgp *, as_t); extern int bgp_confederation_peers_remove (struct bgp *, as_t); -extern int bgp_timers_set (struct bgp *, u_int32_t, u_int32_t); +extern int bgp_timers_set (struct bgp *, u_int32_t keepalive, u_int32_t holdtime); extern int bgp_timers_unset (struct bgp *); extern int bgp_default_local_preference_set (struct bgp *, u_int32_t); @@ -1245,6 +1245,7 @@ extern int peer_group_listen_range_add(struct peer_group *, struct prefix *); extern int peer_activate (struct peer *, afi_t, safi_t); extern int peer_deactivate (struct peer *, afi_t, safi_t); +extern int peer_afc_set (struct peer *, afi_t, safi_t, int); extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *, struct peer_group *, as_t *); @@ -1261,11 +1262,11 @@ extern int peer_ebgp_multihop_set (struct peer *, int); extern int peer_ebgp_multihop_unset (struct peer *); extern int is_ebgp_multihop_configured (struct peer *peer); -extern int peer_description_set (struct peer *, char *); +extern int peer_description_set (struct peer *, const char *); extern int peer_description_unset (struct peer *); extern int peer_update_source_if_set (struct peer *, const char *); -extern int peer_update_source_addr_set (struct peer *, union sockunion *); +extern int peer_update_source_addr_set (struct peer *, const union sockunion *); extern int peer_update_source_unset (struct peer *); extern int peer_default_originate_set (struct peer *, afi_t, safi_t, const char *); @@ -1277,7 +1278,7 @@ extern int peer_port_unset (struct peer *); extern int peer_weight_set (struct peer *, u_int16_t); extern int peer_weight_unset (struct peer *); -extern int peer_timers_set (struct peer *, u_int32_t, u_int32_t); +extern int peer_timers_set (struct peer *, u_int32_t keepalive, u_int32_t holdtime); extern int peer_timers_unset (struct peer *); extern int peer_timers_connect_set (struct peer *, u_int32_t); From 0e6cb7434fbaca97d8991ac8a4ec291b4f74b1fa Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:34 +0200 Subject: [PATCH 066/226] bgpd: divorce router-id logic from CLI & zebra Logic for determining the router-id was spread out over bgp_zebra.c and bgp_vty.c. Move to bgpd/bgpd.c and have these two call more properly encapsulated functions. Significant work by Christian Franke . Signed-off-by: David Lamparter --- bgpd/bgp_vty.c | 15 ++++----------- bgpd/bgp_zebra.c | 29 +---------------------------- bgpd/bgpd.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- bgpd/bgpd.h | 3 ++- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bef9856a9d..0f27069a95 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -820,11 +820,7 @@ DEFUN (bgp_router_id, return CMD_WARNING; } - if (IPV4_ADDR_SAME (&bgp->router_id_static, &id)) - return CMD_SUCCESS; - - bgp->router_id_static = id; - bgp_router_id_set (bgp, &id); + bgp_router_id_static_set (bgp, id); return CMD_SUCCESS; } @@ -874,8 +870,8 @@ DEFUN (no_bgp_router_id, } } - bgp->router_id_static.s_addr = 0; - bgp_router_id_set (bgp, &bgp->router_id_zebra); + id.s_addr = 0; + bgp_router_id_static_set (bgp, id); return CMD_SUCCESS; } @@ -919,10 +915,7 @@ DEFUN (bgp_router_id_interface, if (p && (p->family == AF_INET)) { - if (IPV4_ADDR_SAME (&bgp->router_id_static, &p->u.prefix4)) - return CMD_SUCCESS; - bgp->router_id_static = p->u.prefix4; - bgp_router_id_set (bgp, &p->u.prefix4); + bgp_router_id_static_set(bgp, p->u.prefix4); return CMD_SUCCESS; } } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 888a819d06..68f6cede8b 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -109,8 +109,6 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct prefix router_id; - struct listnode *node, *nnode; - struct bgp *bgp; zebra_router_id_update_read(zclient->ibuf,&router_id); @@ -121,32 +119,7 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); } - if (vrf_id == VRF_DEFAULT) - { - /* Router-id change for default VRF has to also update all views. */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; - - bgp->router_id_zebra = router_id.u.prefix4; - - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id.u.prefix4); - } - } - else - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - { - bgp->router_id_zebra = router_id.u.prefix4; - - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id.u.prefix4); - } - } - + bgp_router_id_zebra_bump (vrf_id, &router_id); return 0; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9377568ec8..1a5270874c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -209,8 +209,8 @@ bgp_config_check (struct bgp *bgp, int config) } /* Set BGP router identifier. */ -int -bgp_router_id_set (struct bgp *bgp, struct in_addr *id) +static int +bgp_router_id_set (struct bgp *bgp, const struct in_addr *id) { struct peer *peer; struct listnode *node, *nnode; @@ -235,6 +235,46 @@ bgp_router_id_set (struct bgp *bgp, struct in_addr *id) return 0; } +void +bgp_router_id_zebra_bump (vrf_id_t vrf_id, const struct prefix *router_id) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + if (vrf_id == VRF_DEFAULT) + { + /* Router-id change for default VRF has to also update all views. */ + for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) + { + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; + + bgp->router_id_zebra = router_id->u.prefix4; + if (!bgp->router_id_static.s_addr) + bgp_router_id_set (bgp, &router_id->u.prefix4); + } + } + else + { + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (bgp) + { + bgp->router_id_zebra = router_id->u.prefix4; + + if (!bgp->router_id_static.s_addr) + bgp_router_id_set (bgp, &router_id->u.prefix4); + } + } +} + +int +bgp_router_id_static_set (struct bgp *bgp, struct in_addr id) +{ + bgp->router_id_static = id; + bgp_router_id_set (bgp, id.s_addr ? &id : &bgp->router_id_zebra); + return 0; +} + /* BGP's cluster-id control. */ int bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index db857a8867..1603ed2614 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1208,7 +1208,8 @@ extern int bgp_flag_check (struct bgp *, int); extern void bgp_lock (struct bgp *); extern void bgp_unlock (struct bgp *); -extern int bgp_router_id_set (struct bgp *, struct in_addr *); +extern void bgp_router_id_zebra_bump (vrf_id_t, const struct prefix*); +extern int bgp_router_id_static_set (struct bgp *, struct in_addr); extern int bgp_cluster_id_set (struct bgp *, struct in_addr *); extern int bgp_cluster_id_unset (struct bgp *); From cd37dad1b99cca18773cfe2268fed29fdd33cd71 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:35 +0200 Subject: [PATCH 067/226] bgpd: ditch unused bgp_node_*() functions Signed-off-by: David Lamparter --- bgpd/bgp_table.h | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index f4e5ec5b89..1114c37010 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -112,44 +112,6 @@ bgp_node_table (struct bgp_node *node) return bgp_node_to_rnode (node)->table->info; } -/* - * bgp_node_info - * - * Returns the 'info' pointer corresponding to a bgp node. - */ -static inline void * -bgp_node_info (const struct bgp_node *node) -{ - return node->info; -} - -/* - * bgp_node_set_info - */ -static inline void -bgp_node_set_info (struct bgp_node *node, void *info) -{ - node->info = info; -} - -/* - * bgp_node_prefix - */ -static inline struct prefix * -bgp_node_prefix (struct bgp_node *node) -{ - return &node->p; -} - -/* - * bgp_node_prefixlen - */ -static inline u_char -bgp_node_prefixlen (struct bgp_node *node) -{ - return bgp_node_prefix (node)->prefixlen; -} - /* * bgp_node_parent_nolock * From a05d8b7ae46410c6782729375090306fd56b4561 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:36 +0200 Subject: [PATCH 068/226] ospfd: monotonic clock for lsa_refresher_started ospf->lsa_refresher_started is only used in relative timing to itself; replace with monotonic clock which is appropriate for this. Signed-off-by: David Lamparter --- lib/thread.c | 8 ++++++++ lib/thread.h | 1 + ospfd/ospf_lsa.c | 6 +++--- ospfd/ospfd.c | 6 +++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index a8ccb8b3d0..717210b950 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -237,6 +237,14 @@ quagga_gettime (enum quagga_clkid clkid, struct timeval *tv) } } +time_t +quagga_monotime (void) +{ + struct timeval tv; + quagga_get_relative(&tv); + return tv.tv_sec; +} + /* time_t value in terms of stabilised absolute time. * replacement for POSIX time() */ diff --git a/lib/thread.h b/lib/thread.h index 8b42ffe58a..ac87595ee4 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -253,6 +253,7 @@ extern struct cmd_element clear_thread_cpu_cmd; * all systems, and fully monotonic on /some/ systems. */ extern int quagga_gettime (enum quagga_clkid, struct timeval *); +extern time_t quagga_monotime (void); extern time_t quagga_time (time_t *); /* Returns elapsed real (wall clock) time. */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index ec0eab5f0a..7e34e5dd9e 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -3731,7 +3731,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) */ delay = (random() % (max_delay - min_delay)) + min_delay; - current_index = ospf->lsa_refresh_queue.index + (quagga_time (NULL) + current_index = ospf->lsa_refresh_queue.index + (quagga_monotime () - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY; index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY) @@ -3795,7 +3795,7 @@ ospf_lsa_refresh_walker (struct thread *t) modulus. */ ospf->lsa_refresh_queue.index = ((unsigned long)(ospf->lsa_refresh_queue.index + - (quagga_time (NULL) - ospf->lsa_refresher_started) + (quagga_monotime () - ospf->lsa_refresher_started) / OSPF_LSA_REFRESHER_GRANULARITY)) % OSPF_LSA_REFRESHER_SLOTS; @@ -3836,7 +3836,7 @@ ospf_lsa_refresh_walker (struct thread *t) ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, ospf, ospf->lsa_refresh_interval); - ospf->lsa_refresher_started = quagga_time (NULL); + ospf->lsa_refresher_started = quagga_monotime (); for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa)) { diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 2034ed1dbd..2a3f9c1d08 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -272,7 +272,7 @@ ospf_new (u_short instance) new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, new, new->lsa_refresh_interval); - new->lsa_refresher_started = quagga_time (NULL); + new->lsa_refresher_started = quagga_monotime (); if ((new->fd = ospf_sock_init()) < 0) { @@ -1598,7 +1598,7 @@ ospf_timers_refresh_set (struct ospf *ospf, int interval) return 1; time_left = ospf->lsa_refresh_interval - - (quagga_time (NULL) - ospf->lsa_refresher_started); + (quagga_monotime () - ospf->lsa_refresher_started); if (time_left > interval) { @@ -1617,7 +1617,7 @@ ospf_timers_refresh_unset (struct ospf *ospf) int time_left; time_left = ospf->lsa_refresh_interval - - (quagga_time (NULL) - ospf->lsa_refresher_started); + (quagga_monotime () - ospf->lsa_refresher_started); if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) { From 60bad36fb798cecbd566129d88faeeccca7353c4 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:37 +0200 Subject: [PATCH 069/226] ospfd: ditch unused time fields The ctime/mtime fields in ospf_route and start_time field in ospf_master are written but never read, thus entirely useless. Remove them. Signed-off-by: David Lamparter --- ospfd/ospf_route.c | 2 -- ospfd/ospf_route.h | 6 ------ ospfd/ospfd.c | 1 - ospfd/ospfd.h | 3 --- 4 files changed, 12 deletions(-) diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 7efba7a8c0..175850c318 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -47,8 +47,6 @@ ospf_route_new () new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route)); - new->ctime = quagga_time (NULL); - new->mtime = new->ctime; new->paths = list_new (); new->paths->del = (void (*) (void *))ospf_path_free; diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 4de3a3da16..d0b121db38 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -90,12 +90,6 @@ struct route_external struct ospf_route { - /* Create time. */ - time_t ctime; - - /* Modified time. */ - time_t mtime; - /* Destination Type. */ u_char type; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 2a3f9c1d08..6d6bf12873 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -1939,5 +1939,4 @@ ospf_master_init () om = &ospf_master; om->ospf = list_new (); om->master = thread_master_create (); - om->start_time = quagga_time (NULL); } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 95809306d6..1a925c2c6a 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -98,9 +98,6 @@ struct ospf_master struct list *external[ZEBRA_ROUTE_MAX + 1]; #define EXTERNAL_INFO(E) (E->external_info) - /* OSPF start time. */ - time_t start_time; - /* Various OSPF global configuration. */ u_char options; #define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */ From 833a7ff9cc14b92caf36c48ea87e59f68037046c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:38 +0200 Subject: [PATCH 070/226] ospfd: use random() to pick initial DD seq# While the idea for this came the other way around - removing quagga_time() - using random() is actually a better idea here. It's seeded by time to begin with, but if ospfd restarts several times in a short timespan it won't run straight into the same sequence number. (Should also update the random seed to include microseconds so restarts within a second use a different seq#) Signed-off-by: David Lamparter --- ospfd/ospf_nsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 23d1e3fc6c..6fc7c266ac 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -783,7 +783,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state) if (state == NSM_ExStart) { if (nbr->dd_seqnum == 0) - nbr->dd_seqnum = quagga_time (NULL); + nbr->dd_seqnum = (uint32_t)random (); else nbr->dd_seqnum++; From 2176b7c3d248b16b63857582967eecfa4765dcc8 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:39 +0200 Subject: [PATCH 071/226] zebra: use quagga_monotime() for zserv and rnh quagga_time() will disappear with the next commit, this is the last remaining user of it. Signed-off-by: Christian Franke Signed-off-by: David Lamparter --- zebra/zebra_rnh.c | 2 +- zebra/zserv.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 8b76ea65c9..03ae466997 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -921,7 +921,7 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr } stream_putw_at (s, 0, stream_get_endp (s)); - client->nh_last_upd_time = quagga_time(NULL); + client->nh_last_upd_time = quagga_monotime(); client->last_write_cmd = cmd; return zebra_server_send_message(client); } diff --git a/zebra/zserv.c b/zebra/zserv.c index 886cd1b395..b36f8fe425 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -97,7 +97,7 @@ zserv_flush_data(struct thread *thread) break; } - client->last_write_time = quagga_time(NULL); + client->last_write_time = quagga_monotime(); return 0; } @@ -131,7 +131,7 @@ zebra_server_send_message(struct zserv *client) break; } - client->last_write_time = quagga_time(NULL); + client->last_write_time = quagga_monotime(); return 0; } @@ -864,7 +864,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, s = client->ibuf; - client->nh_reg_time = quagga_time(NULL); + client->nh_reg_time = quagga_monotime(); while (l < length) { @@ -952,7 +952,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length, rnh = zebra_lookup_rnh(&p, zvrf->vrf_id, type); if (rnh) { - client->nh_dereg_time = quagga_time(NULL); + client->nh_dereg_time = quagga_monotime(); zebra_remove_rnh_client(rnh, client, type); } } @@ -1889,7 +1889,7 @@ zebra_client_create (int sock) /* Set table number. */ client->rtm_table = zebrad.rtm_table_default; - client->connect_time = quagga_time(NULL); + client->connect_time = quagga_monotime(); /* Initialize flags */ for (afi = AFI_IP; afi < AFI_MAX; afi++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) @@ -2015,7 +2015,7 @@ zebra_client_read (struct thread *thread) zlog_debug ("zebra message received [%s] %d in VRF %u", zserv_command_string (command), length, vrf_id); - client->last_read_time = quagga_time(NULL); + client->last_read_time = quagga_monotime(); client->last_read_cmd = command; zvrf = zebra_vrf_lookup (vrf_id); @@ -2325,7 +2325,7 @@ zserv_time_buf(time_t *time1, char *buf, int buflen) return (buf); } - now = quagga_time(NULL); + now = quagga_monotime(); now -= *time1; tm = gmtime(&now); From 16f5949d44f7d9bec5b0402845754e9aca9b6f32 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:40 +0200 Subject: [PATCH 072/226] lib: remove a whole bunch of unused time stuff QUAGGA_CLK_REALTIME and QUAGGA_CLK_REALTIME_STABILISED aren't used anywhere in the code. Remove. The enum is kept to avoid having to change the calls everywhere. Same applies to the workaround code for systems that don't have a monotonic clock. None of the systems Quagga works on fall into that category; Linux, BSD and Solaris all do clock_gettime, for OSX we have mach_absolute_time() - that covers everything. Signed-off-by: David Lamparter --- lib/thread.c | 64 +--------------------------------------------------- lib/thread.h | 5 +--- 2 files changed, 2 insertions(+), 67 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 717210b950..0b50f9edeb 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -60,12 +60,8 @@ extern int agentx_enabled; /* Recent absolute time of day */ struct timeval recent_time; -static struct timeval last_recent_time; /* Relative time, since startup */ static struct timeval relative_time; -static struct timeval relative_time_base; -/* init flag */ -static unsigned short timers_inited; static struct hash *cpu_record = NULL; @@ -118,27 +114,6 @@ timeval_elapsed (struct timeval a, struct timeval b) + (a.tv_usec - b.tv_usec)); } -#if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__) -static void -quagga_gettimeofday_relative_adjust (void) -{ - struct timeval diff; - if (timeval_cmp (recent_time, last_recent_time) < 0) - { - relative_time.tv_sec++; - relative_time.tv_usec = 0; - } - else - { - diff = timeval_subtract (recent_time, last_recent_time); - relative_time.tv_sec += diff.tv_sec; - relative_time.tv_usec += diff.tv_usec; - relative_time = timeval_adjust (relative_time); - } - last_recent_time = recent_time; -} -#endif /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */ - /* gettimeofday wrapper, to keep recent_time updated */ static int quagga_gettimeofday (struct timeval *tv) @@ -149,12 +124,6 @@ quagga_gettimeofday (struct timeval *tv) if (!(ret = gettimeofday (&recent_time, NULL))) { - /* init... */ - if (!timers_inited) - { - relative_time_base = last_recent_time = recent_time; - timers_inited = 1; - } /* avoid copy if user passed recent_time pointer.. */ if (tv != &recent_time) *tv = recent_time; @@ -194,8 +163,7 @@ quagga_get_relative (struct timeval *tv) return 0; } #else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */ - if (!(ret = quagga_gettimeofday (&recent_time))) - quagga_gettimeofday_relative_adjust(); +#error no monotonic clock on this system #endif /* HAVE_CLOCK_MONOTONIC */ if (tv) @@ -204,18 +172,6 @@ quagga_get_relative (struct timeval *tv) return ret; } -/* Get absolute time stamp, but in terms of the internal timer - * Could be wrong, but at least won't go back. - */ -static void -quagga_real_stabilised (struct timeval *tv) -{ - *tv = relative_time_base; - tv->tv_sec += relative_time.tv_sec; - tv->tv_usec += relative_time.tv_usec; - *tv = timeval_adjust (*tv); -} - /* Exported Quagga timestamp function. * Modelled on POSIX clock_gettime. */ @@ -224,13 +180,8 @@ quagga_gettime (enum quagga_clkid clkid, struct timeval *tv) { switch (clkid) { - case QUAGGA_CLK_REALTIME: - return quagga_gettimeofday (tv); case QUAGGA_CLK_MONOTONIC: return quagga_get_relative (tv); - case QUAGGA_CLK_REALTIME_STABILISED: - quagga_real_stabilised (tv); - return 0; default: errno = EINVAL; return -1; @@ -245,19 +196,6 @@ quagga_monotime (void) return tv.tv_sec; } -/* time_t value in terms of stabilised absolute time. - * replacement for POSIX time() - */ -time_t -quagga_time (time_t *t) -{ - struct timeval tv; - quagga_real_stabilised (&tv); - if (t) - *t = tv.tv_sec; - return tv.tv_sec; -} - /* Public export of recent_relative_time by value */ struct timeval recent_relative_time (void) diff --git a/lib/thread.h b/lib/thread.h index ac87595ee4..3c0387eb11 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -130,9 +130,7 @@ struct cpu_thread_history /* Clocks supported by Quagga */ enum quagga_clkid { - QUAGGA_CLK_REALTIME = 0, /* ala gettimeofday() */ - QUAGGA_CLK_MONOTONIC, /* monotonic, against an indeterminate base */ - QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */ + QUAGGA_CLK_MONOTONIC = 1, /* monotonic, against an indeterminate base */ }; /* Struct timeval's tv_usec one second value. */ @@ -254,7 +252,6 @@ extern struct cmd_element clear_thread_cpu_cmd; */ extern int quagga_gettime (enum quagga_clkid, struct timeval *); extern time_t quagga_monotime (void); -extern time_t quagga_time (time_t *); /* Returns elapsed real (wall clock) time. */ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, From b21e9619c50276540bc447007a8b43ded267c7fe Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:41 +0200 Subject: [PATCH 073/226] lib: linklist: add listnode_add_before() This utility function, to join the zoo that the Quagga linked-list implementation has accumulated, does an insert-before while returning the newly allocated node. It is similar to: - listnode_add_after(), but - complementary direction - returns allocated node - list_add_node_prev(), but - supports before == NULL - returns allocated node In general, the entire linked-list implementation is in bad shape, and while it needs a cleanup / rewrite / replacement, this would both cause significant conflicts and block other cleanups... Signed-off-by: David Lamparter --- lib/linklist.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/linklist.h | 1 + 2 files changed, 39 insertions(+) diff --git a/lib/linklist.c b/lib/linklist.c index 4b16f07dd1..8b6a852826 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -159,6 +159,44 @@ listnode_add_after (struct list *list, struct listnode *pp, void *val) list->count++; } +struct listnode * +listnode_add_before (struct list *list, struct listnode *pp, void *val) +{ + struct listnode *nn; + + assert (val != NULL); + + nn = listnode_new (); + nn->data = val; + + if (pp == NULL) + { + if (list->tail) + list->tail->next = nn; + else + list->head = nn; + + nn->prev = list->tail; + nn->next = pp; + + list->tail = nn; + } + else + { + if (pp->prev) + pp->prev->next = nn; + else + list->head = nn; + + nn->prev = pp->prev; + nn->next = pp; + + pp->prev = nn; + } + list->count++; + return nn; +} + /* Move given listnode to tail of the list */ void listnode_move_to_tail (struct list *l, struct listnode *n) diff --git a/lib/linklist.h b/lib/linklist.h index 6209c8b9d6..96aaf43196 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -68,6 +68,7 @@ extern void list_free (struct list *); extern void listnode_add (struct list *, void *); extern void listnode_add_sort (struct list *, void *); extern void listnode_add_after (struct list *, struct listnode *, void *); +extern struct listnode *listnode_add_before (struct list *, struct listnode *, void *); extern void listnode_move_to_tail (struct list *, struct listnode *); extern void listnode_delete (struct list *, void *); extern struct listnode *listnode_lookup (struct list *, void *); From d03c4cbd9ac03926501fbb822b05b1c9a04b65cb Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:42 +0200 Subject: [PATCH 074/226] lib: add thread_add_timer_tv (struct timeval) Another zoo extension, this adds a timer scheduling function that takes a struct timeval argument (which is actually what the wrappers boil down to, yet it's not exposed...) Signed-off-by: David Lamparter --- lib/thread.c | 11 +++++++++++ lib/thread.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/lib/thread.c b/lib/thread.c index 0b50f9edeb..f3b0bdf8a5 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -941,6 +941,17 @@ funcname_thread_add_timer_msec (struct thread_master *m, arg, &trel, debugargpass); } +/* Add timer event thread with "millisecond" resolution */ +struct thread * +funcname_thread_add_timer_tv (struct thread_master *m, + int (*func) (struct thread *), + void *arg, struct timeval *tv, + debugargdef) +{ + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, + arg, tv, debugargpass); +} + /* Add a background thread, with an optional millisec delay */ struct thread * funcname_thread_add_background (struct thread_master *m, diff --git a/lib/thread.h b/lib/thread.h index 3c0387eb11..c692142839 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -197,6 +197,7 @@ enum quagga_clkid { #define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__) #define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__) #define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__) #define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__) #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) @@ -217,6 +218,10 @@ extern struct thread *funcname_thread_add_timer (struct thread_master *, extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, int (*)(struct thread *), void *, long, debugargdef); +extern struct thread *funcname_thread_add_timer_tv (struct thread_master *, + int (*)(struct thread *), + void *, struct timeval *, + debugargdef); extern struct thread *funcname_thread_add_event (struct thread_master *, int (*)(struct thread *), void *, int, debugargdef); From 56e2c5e8471704b3f28210a96f3e5ef7e8557b97 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:43 +0200 Subject: [PATCH 075/226] lib: AgentX: use threads instead of eventloop hack AgentX fd/timeout handling is rather hackishly monkeyed into thread.c. Replace with code that uses plain thread_* functions. NB: Net-SNMP's API rivals Quagga's in terms of age and absence of documentation. netsnmp_check_outstanding_agent_requests() in particular seems to be unused and is therefore untested. The most useful documentation on this is actually the blog post Vincent Bernat wrote when he originally integrated this into lldpd and Quagga: https://vincent.bernat.im/en/blog/2012-snmp-event-loop.html Signed-off-by: David Lamparter --- lib/agentx.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++- lib/thread.c | 82 +--------------------------------------- 2 files changed, 106 insertions(+), 81 deletions(-) diff --git a/lib/agentx.c b/lib/agentx.c index 9dc5b47de3..5996b34a0f 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -24,12 +24,110 @@ #if defined HAVE_SNMP && defined SNMP_AGENTX #include #include +#include +#include #include "command.h" #include "smux.h" #include "memory.h" +#include "linklist.h" -int agentx_enabled = 0; +static int agentx_enabled = 0; + +static struct thread_master *agentx_tm; +static struct thread *timeout_thr = NULL; +static struct list *events = NULL; + +static void agentx_events_update(void); + +static int +agentx_timeout(struct thread *t) +{ + timeout_thr = NULL; + + snmp_timeout (); + run_alarms (); + netsnmp_check_outstanding_agent_requests (); + agentx_events_update (); + return 0; +} + +static int +agentx_read(struct thread *t) +{ + fd_set fds; + struct listnode *ln = THREAD_ARG (t); + list_delete_node (events, ln); + + FD_ZERO (&fds); + FD_SET (THREAD_FD (t), &fds); + snmp_read (&fds); + + netsnmp_check_outstanding_agent_requests (); + agentx_events_update (); + return 0; +} + +static void +agentx_events_update(void) +{ + int maxfd = 0; + int block = 1; + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + fd_set fds; + struct listnode *ln; + struct thread *thr; + int fd, thr_fd; + + THREAD_OFF (timeout_thr); + + FD_ZERO (&fds); + snmp_select_info (&maxfd, &fds, &timeout, &block); + + if (!block) + timeout_thr = thread_add_timer_tv (agentx_tm, agentx_timeout, NULL, &timeout); + + ln = listhead (events); + thr = ln ? listgetdata (ln) : NULL; + thr_fd = thr ? THREAD_FD (thr) : -1; + + /* "two-pointer" / two-list simultaneous iteration + * ln/thr/thr_fd point to the next existing event listener to hit while + * fd counts to catch up */ + for (fd = 0; fd < maxfd; fd++) + { + /* caught up */ + if (thr_fd == fd) + { + struct listnode *nextln = listnextnode (ln); + if (!FD_ISSET (fd, &fds)) + { + thread_cancel (thr); + list_delete_node (events, ln); + } + ln = nextln; + thr = ln ? listgetdata (ln) : NULL; + thr_fd = thr ? THREAD_FD (thr) : -1; + } + /* need listener, but haven't hit one where it would be */ + else if (FD_ISSET (fd, &fds)) + { + struct listnode *newln; + thr = thread_add_read (agentx_tm, agentx_read, NULL, fd); + newln = listnode_add_before (events, ln, thr); + thr->arg = newln; + } + } + + /* leftover event listeners at this point have fd > maxfd, delete them */ + while (ln) + { + struct listnode *nextln = listnextnode (ln); + thread_cancel (listgetdata (ln)); + list_delete_node (events, ln); + ln = nextln; + } +} /* AgentX node. */ static struct cmd_node agentx_node = @@ -78,6 +176,8 @@ DEFUN (agentx_enable, if (!agentx_enabled) { init_snmp("quagga"); + events = list_new(); + agentx_events_update (); agentx_enabled = 1; return CMD_SUCCESS; } @@ -100,6 +200,8 @@ DEFUN (no_agentx, void smux_init (struct thread_master *tm) { + agentx_tm = tm; + netsnmp_enable_subagent (); snmp_disable_log (); snmp_enable_calllog (); @@ -208,6 +310,7 @@ smux_trap (struct variable *vp, size_t vp_len, send_v2trap (notification_vars); snmp_free_varbind (notification_vars); + agentx_events_update (); return 1; } diff --git a/lib/thread.c b/lib/thread.c index f3b0bdf8a5..a128786c3d 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -32,27 +32,6 @@ #include "command.h" #include "sigevent.h" -#if defined HAVE_SNMP && defined SNMP_AGENTX - -#ifdef HAVE_POLL -#define QUAGGA_HAVE_POLL -#endif - -#include -#include -#include -#include - -#ifdef HAVE_POLL -#undef HAVE_POLL -#endif -#ifdef QUAGGA_HAVE_POLL -#define HAVE_POLL -#endif - -extern int agentx_enabled; -#endif - #if defined(__APPLE__) #include #include @@ -1312,12 +1291,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) while (1) { int num = 0; -#if defined HAVE_SNMP && defined SNMP_AGENTX - struct timeval snmp_timer_wait; - int snmpblock = 0; - int fdsetsize; -#endif - + /* Signals pre-empt everything */ quagga_sigevent_process (); @@ -1353,35 +1327,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) timer_wait = timer_wait_bg; } - -#if defined HAVE_SNMP && defined SNMP_AGENTX - /* When SNMP is enabled, we may have to select() on additional - FD. snmp_select_info() will add them to `readfd'. The trick - with this function is its last argument. We need to set it to - 0 if timer_wait is not NULL and we need to use the provided - new timer only if it is still set to 0. */ - if (agentx_enabled) - { - fdsetsize = FD_SETSIZE; - snmpblock = 1; - if (timer_wait) - { - snmpblock = 0; - memcpy(&snmp_timer_wait, timer_wait, sizeof(struct timeval)); - } -#if defined(HAVE_POLL) - /* clear fdset since there are no other fds in fd_set, - then add injected fds from snmp_select_info into pollset */ - FD_ZERO(&readfd); -#endif - snmp_select_info(&fdsetsize, &readfd, &snmp_timer_wait, &snmpblock); -#if defined(HAVE_POLL) - add_snmp_pollfds(m, &readfd, fdsetsize); -#endif - if (snmpblock == 0) - timer_wait = &snmp_timer_wait; - } -#endif + num = fd_select (m, FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait); /* Signals should get quick treatment */ @@ -1393,30 +1339,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch) return NULL; } -#if defined HAVE_SNMP && defined SNMP_AGENTX -#if defined(HAVE_POLL) - /* re-enter pollfds in fd_set for handling in snmp_read */ - FD_ZERO(&readfd); - nfds_t i; - for (i = m->handler.pfdcount; i < m->handler.pfdcountsnmp; ++i) - { - if (m->handler.pfds[i].revents == POLLIN) - FD_SET(m->handler.pfds[i].fd, &readfd); - } -#endif - if (agentx_enabled) - { - if (num > 0) - snmp_read(&readfd); - else if (num == 0) - { - snmp_timeout(); - run_alarms(); - } - netsnmp_check_outstanding_agent_requests(); - } -#endif - /* Check foreground timers. Historically, they have had higher priority than I/O threads, so let's push them onto the ready list in front of the I/O threads. */ From 050ceb3b7c1943d042c79a3940dae9a234a01735 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:44 +0200 Subject: [PATCH 076/226] zebra: fix include for SNMP no idea where this disappeared. Signed-off-by: David Lamparter --- zebra/zebra_snmp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index 11fc0ef40d..3ba9fc26a8 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -39,6 +39,7 @@ #include "zebra/rib.h" #include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" #define IPFWMIB 1,3,6,1,2,1,4,24 From 1c6f50bf2dd960b7007eb254f068968fcdfd3149 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:45 +0200 Subject: [PATCH 077/226] *: snmp: add a load of "static" specifiers Make it easier to see which bits in *_snmp.c are actually referenced from non-SNMP parts of the code. Signed-off-by: David Lamparter --- bgpd/bgp_snmp.c | 8 ++++---- ospf6d/ospf6_snmp.c | 6 +++--- ospfd/ospf_snmp.c | 18 +++++++++--------- ripd/rip_snmp.c | 6 +++--- zebra/zebra_snmp.c | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 84a527b96a..fc5a0eb59c 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -116,8 +116,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA SNMP_LOCAL_VARIABLES /* BGP-MIB instances. */ -oid bgp_oid [] = { BGP4MIB }; -oid bgp_trap_oid [] = { BGP4MIB, 0 }; +static oid bgp_oid [] = { BGP4MIB }; +static oid bgp_trap_oid [] = { BGP4MIB, 0 }; /* IP address 0.0.0.0. */ static struct in_addr bgp_empty_addr = { .s_addr = 0 }; @@ -137,7 +137,7 @@ static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *, int, size_t *, WriteMethod **); /* static u_char *bgpTraps (); */ -struct variable bgp_variables[] = +static struct variable bgp_variables[] = { /* BGP version. */ {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, @@ -831,7 +831,7 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length, } /* BGP Traps. */ -struct trap_object bgpTrapList[] = +static struct trap_object bgpTrapList[] = { {3, {3, 1, BGPPEERLASTERROR}}, {3, {3, 1, BGPPEERSTATE}} diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 7423a3733a..cf1630bbc9 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -207,8 +207,8 @@ SNMP_LOCAL_VARIABLES /* OSPFv3-MIB instances. */ -oid ospfv3_oid [] = { OSPFv3MIB }; -oid ospfv3_trap_oid [] = { OSPFv3MIB, 0 }; +static oid ospfv3_oid [] = { OSPFv3MIB }; +static oid ospfv3_trap_oid [] = { OSPFv3MIB, 0 }; /* Hook functions. */ static u_char *ospfv3GeneralGroup (struct variable *, oid *, size_t *, @@ -222,7 +222,7 @@ static u_char *ospfv3NbrEntry (struct variable *, oid *, size_t *, static u_char *ospfv3IfEntry (struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); -struct variable ospfv3_variables[] = +static struct variable ospfv3_variables[] = { /* OSPF general variables */ {OSPFv3ROUTERID, UNSIGNED, RWRITE, ospfv3GeneralGroup, diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 1636153378..0eaf44b4d2 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -209,8 +209,8 @@ SNMP_LOCAL_VARIABLES /* OSPF-MIB instances. */ -oid ospf_oid [] = { OSPF2MIB }; -oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */ +static oid ospf_oid [] = { OSPF2MIB }; +static oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */ /* IP address 0.0.0.0. */ static struct in_addr ospf_empty_addr = { .s_addr = 0 }; @@ -243,7 +243,7 @@ static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int, static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); -struct variable ospf_variables[] = +static struct variable ospf_variables[] = { /* OSPF general variables */ {OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup, @@ -1408,7 +1408,7 @@ ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact, return NULL; } -struct list *ospf_snmp_iflist; +static struct list *ospf_snmp_iflist; struct ospf_snmp_if { @@ -1912,7 +1912,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, return NULL; } -struct route_table *ospf_snmp_vl_table; +static struct route_table *ospf_snmp_vl_table; void ospf_snmp_vl_add (struct ospf_vl_data *vl_data) @@ -2618,7 +2618,7 @@ ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length, #define NBRSTATECHANGE 2 #define VIRTNBRSTATECHANGE 3 -struct trap_object ospfNbrTrapList[] = +static struct trap_object ospfNbrTrapList[] = { {-2, {1, OSPFROUTERID}}, {3, {10, 1, OSPFNBRIPADDR}}, @@ -2627,7 +2627,7 @@ struct trap_object ospfNbrTrapList[] = }; -struct trap_object ospfVirtNbrTrapList[] = +static struct trap_object ospfVirtNbrTrapList[] = { {-2, {1, 1}}, {3, {11, 1, OSPFVIRTNBRAREA}}, @@ -2635,7 +2635,7 @@ struct trap_object ospfVirtNbrTrapList[] = {3, {11, 1, OSPFVIRTNBRSTATE}} }; -struct trap_object ospfIfTrapList[] = +static struct trap_object ospfIfTrapList[] = { {-2, {1, OSPFROUTERID}}, {3, {7, 1, OSPFIFIPADDRESS}}, @@ -2643,7 +2643,7 @@ struct trap_object ospfIfTrapList[] = {3, {7, 1, OSPFIFSTATE}} }; -struct trap_object ospfVirtIfTrapList[] = +static struct trap_object ospfVirtIfTrapList[] = { {-2, {1, OSPFROUTERID}}, {3, {9, 1, OSPFVIRTIFAREAID}}, diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 4b7d1b4c50..c28b9379cc 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -81,10 +81,10 @@ SNMP_LOCAL_VARIABLES /* RIP-MIB instances. */ -oid rip_oid [] = { RIPV2MIB }; +static oid rip_oid [] = { RIPV2MIB }; /* Interface cache table sorted by interface's address. */ -struct route_table *rip_ifaddr_table; +static struct route_table *rip_ifaddr_table; /* Hook functions. */ static u_char *rip2Globals (struct variable *, oid [], size_t *, @@ -96,7 +96,7 @@ static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *, static u_char *rip2PeerTable (struct variable *, oid [], size_t *, int, size_t *, WriteMethod **); -struct variable rip_variables[] = +static struct variable rip_variables[] = { /* RIP Global Counters. */ {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index 3ba9fc26a8..3186ebf693 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -85,7 +85,7 @@ #define IPADDRESS ASN_IPADDRESS #define OBJECTIDENTIFIER ASN_OBJECT_ID -oid ipfw_oid [] = { IPFWMIB }; +static oid ipfw_oid [] = { IPFWMIB }; /* Hook functions. */ static u_char * ipFwNumber (struct variable *, oid [], size_t *, @@ -97,7 +97,7 @@ static u_char * ipCidrNumber (struct variable *, oid [], size_t *, static u_char * ipCidrTable (struct variable *, oid [], size_t *, int, size_t *, WriteMethod **); -struct variable zebra_variables[] = +static struct variable zebra_variables[] = { {0, GAUGE32, RONLY, ipFwNumber, 1, {1}}, {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}}, From a8fd82028158f8e811e214fec0185cf6cdfdb9cb Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:46 +0200 Subject: [PATCH 078/226] lib: linklist: clean up insert-before/after dups - list_add_node_next was in fact unused - list_add_node_prev performs a subset of listnode_add_before and its only use in isisd replaced with that. Signed-off-by: David Lamparter --- isisd/isis_spf.c | 4 ++-- lib/linklist.c | 49 ++---------------------------------------------- lib/linklist.h | 4 +--- 3 files changed, 5 insertions(+), 52 deletions(-) diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 32026f9b17..fd5af4a2b8 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -545,13 +545,13 @@ isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, v = listgetdata (node); if (v->d_N > vertex->d_N) { - list_add_node_prev (spftree->tents, node, vertex); + listnode_add_before (spftree->tents, node, vertex); break; } else if (v->d_N == vertex->d_N && v->type > vertex->type) { /* Tie break, add according to type */ - list_add_node_prev (spftree->tents, node, vertex); + listnode_add_before (spftree->tents, node, vertex); break; } } diff --git a/lib/linklist.c b/lib/linklist.c index 8b6a852826..d27a2da848 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -122,7 +122,7 @@ listnode_add_sort (struct list *list, void *val) list->count++; } -void +struct listnode * listnode_add_after (struct list *list, struct listnode *pp, void *val) { struct listnode *nn; @@ -157,6 +157,7 @@ listnode_add_after (struct list *list, struct listnode *pp, void *val) pp->next = nn; } list->count++; + return nn; } struct listnode * @@ -304,52 +305,6 @@ list_delete_node (struct list *list, struct listnode *node) listnode_free (node); } -/* ospf_spf.c */ -void -list_add_node_prev (struct list *list, struct listnode *current, void *val) -{ - struct listnode *node; - - assert (val != NULL); - - node = listnode_new (); - node->next = current; - node->data = val; - - if (current->prev == NULL) - list->head = node; - else - current->prev->next = node; - - node->prev = current->prev; - current->prev = node; - - list->count++; -} - -/* ospf_spf.c */ -void -list_add_node_next (struct list *list, struct listnode *current, void *val) -{ - struct listnode *node; - - assert (val != NULL); - - node = listnode_new (); - node->prev = current; - node->data = val; - - if (current->next == NULL) - list->tail = node; - else - current->next->prev = node; - - node->next = current->next; - current->next = node; - - list->count++; -} - /* ospf_spf.c */ void list_add_list (struct list *l, struct list *m) diff --git a/lib/linklist.h b/lib/linklist.h index 96aaf43196..e99e50f4fa 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -67,7 +67,7 @@ extern void list_free (struct list *); extern void listnode_add (struct list *, void *); extern void listnode_add_sort (struct list *, void *); -extern void listnode_add_after (struct list *, struct listnode *, void *); +extern struct listnode *listnode_add_after (struct list *, struct listnode *, void *); extern struct listnode *listnode_add_before (struct list *, struct listnode *, void *); extern void listnode_move_to_tail (struct list *, struct listnode *); extern void listnode_delete (struct list *, void *); @@ -81,8 +81,6 @@ extern void list_delete_all_node (struct list *); extern void list_delete_node (struct list *, struct listnode *); /* For ospf_spf.c */ -extern void list_add_node_prev (struct list *, struct listnode *, void *); -extern void list_add_node_next (struct list *, struct listnode *, void *); extern void list_add_list (struct list *, struct list *); /* List iteration macro. From d6f4a61dde127c6154f7933b0a4003740b6a0768 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:47 +0200 Subject: [PATCH 079/226] lib: add 3-byte stream functions This will be used for BGP MPLS labels. Signed-off-by: David Lamparter --- lib/stream.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/stream.h | 4 +++ 2 files changed, 81 insertions(+) diff --git a/lib/stream.c b/lib/stream.c index 4c237563a5..fe77e2a2ad 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -373,6 +373,47 @@ stream_getw_from (struct stream *s, size_t from) return w; } +/* Get next 3-byte from the stream. */ +u_int32_t +stream_get3_from (struct stream *s, size_t from) +{ + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, from + 3)) + { + STREAM_BOUND_WARN (s, "get 3byte"); + return 0; + } + + l = s->data[from++] << 16; + l |= s->data[from++] << 8; + l |= s->data[from]; + + return l; +} + +u_int32_t +stream_get3 (struct stream *s) +{ + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE (s) < 3) + { + STREAM_BOUND_WARN (s, "get 3byte"); + return 0; + } + + l = s->data[s->getp++] << 16; + l |= s->data[s->getp++] << 8; + l |= s->data[s->getp++]; + + return l; +} + /* Get next long word from the stream. */ u_int32_t stream_getl_from (struct stream *s, size_t from) @@ -566,6 +607,25 @@ stream_putw (struct stream *s, u_int16_t w) return 2; } +/* Put long word to the stream. */ +int +stream_put3 (struct stream *s, u_int32_t l) +{ + STREAM_VERIFY_SANE (s); + + if (STREAM_WRITEABLE (s) < 3) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + + s->data[s->endp++] = (u_char)(l >> 16); + s->data[s->endp++] = (u_char)(l >> 8); + s->data[s->endp++] = (u_char)l; + + return 3; +} + /* Put long word to the stream. */ int stream_putl (struct stream *s, u_int32_t l) @@ -643,6 +703,23 @@ stream_putw_at (struct stream *s, size_t putp, u_int16_t w) return 2; } +int +stream_put3_at (struct stream *s, size_t putp, u_int32_t l) +{ + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID (s, putp + 3)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[putp] = (u_char)(l >> 16); + s->data[putp + 1] = (u_char)(l >> 8); + s->data[putp + 2] = (u_char)l; + + return 3; +} + int stream_putl_at (struct stream *s, size_t putp, u_int32_t l) { diff --git a/lib/stream.h b/lib/stream.h index 738034438c..4e9b21df5f 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -167,6 +167,8 @@ extern int stream_putc (struct stream *, u_char); extern int stream_putc_at (struct stream *, size_t, u_char); extern int stream_putw (struct stream *, u_int16_t); extern int stream_putw_at (struct stream *, size_t, u_int16_t); +extern int stream_put3 (struct stream *, u_int32_t); +extern int stream_put3_at (struct stream *, size_t, u_int32_t); extern int stream_putl (struct stream *, u_int32_t); extern int stream_putl_at (struct stream *, size_t, u_int32_t); extern int stream_putq (struct stream *, uint64_t); @@ -186,6 +188,8 @@ extern u_char stream_getc (struct stream *); extern u_char stream_getc_from (struct stream *, size_t); extern u_int16_t stream_getw (struct stream *); extern u_int16_t stream_getw_from (struct stream *, size_t); +extern u_int32_t stream_get3 (struct stream *); +extern u_int32_t stream_get3_from (struct stream *, size_t); extern u_int32_t stream_getl (struct stream *); extern u_int32_t stream_getl_from (struct stream *, size_t); extern uint64_t stream_getq (struct stream *); From 5ef104fc4131cacaf1843bb32e19d4b681fc5214 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:48 +0200 Subject: [PATCH 080/226] pimd: relegate pim_igmp_join.c into a header file pim_igmp_join.c only exists to make some portability hacks available to test_igmpv3_join. The function only has 1 call site in each pimd and the test tool, so it's nicely served as a simple static function in a header file. This removes a MTYPE related compiler/linker issue from referencing lib/if.h in a binary that doesn't link libzebra, as test_igmpv3_join is now fully independent of lib/. (Fix by Christian Franke: remove stray leftover ifindex_t) Signed-off-by: David Lamparter --- pimd/Makefile.am | 6 ++-- pimd/pim_igmp_join.c | 71 ----------------------------------------- pimd/pim_igmp_join.h | 46 +++++++++++++++++++++++--- pimd/test_igmpv3_join.c | 2 -- 4 files changed, 45 insertions(+), 80 deletions(-) delete mode 100644 pimd/pim_igmp_join.c diff --git a/pimd/Makefile.am b/pimd/Makefile.am index 115d73678d..d578c97363 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -43,7 +43,7 @@ AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libpim.a sbin_PROGRAMS = pimd -bin_PROGRAMS = test_igmpv3_join +noinst_PROGRAMS = test_igmpv3_join libpim_a_SOURCES = \ pimd.c pim_version.c pim_cmd.c pim_signals.c pim_iface.c \ @@ -52,7 +52,7 @@ libpim_a_SOURCES = \ pim_oil.c pim_zlookup.c pim_pim.c pim_tlv.c pim_neighbor.c \ pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \ pim_msg.c pim_upstream.c pim_rpf.c pim_macro.c \ - pim_igmp_join.c pim_ssmpingd.c pim_int.c pim_rp.c \ + pim_ssmpingd.c pim_int.c pim_rp.c \ pim_static.c pim_br.c pim_register.c pim_routemap.c noinst_HEADERS = \ @@ -69,7 +69,7 @@ pimd_SOURCES = \ pim_main.c $(libpim_a_SOURCES) test_igmpv3_join_SOURCES = \ - test_igmpv3_join.c pim_igmp_join.c + test_igmpv3_join.c pimd_LDADD = ../lib/libzebra.la @LIBCAP@ test_igmpv3_join_LDADD = ../lib/libzebra.la diff --git a/pimd/pim_igmp_join.c b/pimd/pim_igmp_join.c deleted file mode 100644 index 62e32c6014..0000000000 --- a/pimd/pim_igmp_join.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - PIM for Quagga - Copyright (C) 2008 Everton da Silva Marques - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING; if not, write to the - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - MA 02110-1301 USA - - $QuaggaId: $Format:%an, %ai, %h$ $ -*/ - -#include - -#include -#include -#include - -#include "pim_igmp_join.h" - -#ifndef SOL_IP -#define SOL_IP IPPROTO_IP -#endif - -#ifndef MCAST_JOIN_SOURCE_GROUP -#define MCAST_JOIN_SOURCE_GROUP 46 -struct group_source_req -{ - uint32_t gsr_interface; - struct sockaddr_storage gsr_group; - struct sockaddr_storage gsr_source; -}; -#endif - -int pim_igmp_join_source(int fd, int ifindex, - struct in_addr group_addr, - struct in_addr source_addr) -{ - struct group_source_req req; - struct sockaddr_in group; - struct sockaddr_in source; - - memset(&group, 0, sizeof(group)); - group.sin_family = AF_INET; - group.sin_addr = group_addr; - group.sin_port = htons(0); - memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); - - memset(&source, 0, sizeof(source)); - source.sin_family = AF_INET; - source.sin_addr = source_addr; - source.sin_port = htons(0); - memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); - - req.gsr_interface = ifindex; - - return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, - &req, sizeof(req)); - - return 0; -} diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 1127af1202..95519ff974 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -23,10 +23,48 @@ #ifndef PIM_IGMP_JOIN_H #define PIM_IGMP_JOIN_H -#include +/* required headers #include'd by caller */ -int pim_igmp_join_source(int fd, int ifindex, - struct in_addr group_addr, - struct in_addr source_addr); +#ifndef SOL_IP +#define SOL_IP IPPROTO_IP +#endif + +#ifndef MCAST_JOIN_SOURCE_GROUP +#define MCAST_JOIN_SOURCE_GROUP 46 +struct group_source_req +{ + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; +}; +#endif + +static int pim_igmp_join_source(int fd, int ifindex, + struct in_addr group_addr, + struct in_addr source_addr) +{ + struct group_source_req req; + struct sockaddr_in group; + struct sockaddr_in source; + + memset(&group, 0, sizeof(group)); + group.sin_family = AF_INET; + group.sin_addr = group_addr; + group.sin_port = htons(0); + memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); + + memset(&source, 0, sizeof(source)); + source.sin_family = AF_INET; + source.sin_addr = source_addr; + source.sin_port = htons(0); + memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); + + req.gsr_interface = ifindex; + + return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, + &req, sizeof(req)); + + return 0; +} #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index 6f1e34de88..fe64fbc005 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -30,10 +30,8 @@ #include #include -#include "thread.h" #include "pim_igmp_join.h" -struct thread_master *master; const char *prog_name = 0; static int iface_solve_index(const char *ifname) From c66f9c6186acb837a4fab441469a26b406f08e37 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:49 +0200 Subject: [PATCH 081/226] *: get rid of "MTYPE 0" A few places are using 0 in place of the MTYPE_* argument. The following rewrite of the alloc tracking won't deal with that, so let's use MTYPE_TMP instead. Acked-by: Vincent JARDIN Acked-by: Donald Sharp [DL: v2: fix XFREE(0, foo) calls too] Signed-off-by: David Lamparter --- lib/prefix.c | 2 +- ospfclient/ospf_apiclient.h | 2 +- ospfd/ospf_opaque.c | 6 +++--- ospfd/ospf_snmp.c | 4 ++-- ospfd/ospf_te.c | 2 +- vtysh/vtysh_main.c | 4 ++-- vtysh/vtysh_user.c | 2 +- zebra/zserv.c | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/prefix.c b/lib/prefix.c index 256cd3a49a..c311b94eef 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -572,7 +572,7 @@ str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) { int plen; - cp = XMALLOC (0, (pnt - str) + 1); + cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_pton (AF_INET6, cp, &p->prefix); diff --git a/ospfclient/ospf_apiclient.h b/ospfclient/ospf_apiclient.h index 0e74787ae0..809861995e 100644 --- a/ospfclient/ospf_apiclient.h +++ b/ospfclient/ospf_apiclient.h @@ -23,7 +23,7 @@ #ifndef _OSPF_APICLIENT_H #define _OSPF_APICLIENT_H -#define MTYPE_OSPF_APICLIENT 0 +#define MTYPE_OSPF_APICLIENT MTYPE_TMP /* Structure for the OSPF API client */ struct ospf_apiclient diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 4c05c77252..ff505b6bd3 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -22,9 +22,9 @@ */ /***** MTYPE definitions are not reflected to "memory.h" yet. *****/ -#define MTYPE_OSPF_OPAQUE_FUNCTAB 0 -#define MTYPE_OPAQUE_INFO_PER_TYPE 0 -#define MTYPE_OPAQUE_INFO_PER_ID 0 +#define MTYPE_OSPF_OPAQUE_FUNCTAB MTYPE_TMP +#define MTYPE_OPAQUE_INFO_PER_TYPE MTYPE_TMP +#define MTYPE_OPAQUE_INFO_PER_ID MTYPE_TMP #include #ifdef HAVE_OPAQUE_LSA diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 0eaf44b4d2..bedcb559bf 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -1420,13 +1420,13 @@ struct ospf_snmp_if static struct ospf_snmp_if * ospf_snmp_if_new (void) { - return XCALLOC (0, sizeof (struct ospf_snmp_if)); + return XCALLOC (MTYPE_TMP, sizeof (struct ospf_snmp_if)); } static void ospf_snmp_if_free (struct ospf_snmp_if *osif) { - XFREE (0, osif); + XFREE (MTYPE_TMP, osif); } void diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index db06623ddf..155a773b33 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -22,7 +22,7 @@ */ /***** MTYPE definition is not reflected to "memory.h" yet. *****/ -#define MTYPE_OSPF_MPLS_TE_LINKPARAMS 0 +#define MTYPE_OSPF_MPLS_TE_LINKPARAMS MTYPE_TMP #include diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index cd21c94efd..5bb3c61e52 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -317,7 +317,7 @@ main (int argc, char **argv, char **env) case 'c': { struct cmd_rec *cr; - cr = XMALLOC(0, sizeof(*cr)); + cr = XMALLOC(MTYPE_TMP, sizeof(*cr)); cr->line = optarg; cr->next = NULL; if (tail) @@ -501,7 +501,7 @@ main (int argc, char **argv, char **env) struct cmd_rec *cr; cr = cmd; cmd = cmd->next; - XFREE(0, cr); + XFREE(MTYPE_TMP, cr); } } diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index 0d72c378a3..988c768dce 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -116,7 +116,7 @@ struct list *userlist; static struct vtysh_user * user_new (void) { - return XCALLOC (0, sizeof (struct vtysh_user)); + return XCALLOC (MTYPE_TMP, sizeof (struct vtysh_user)); } static struct vtysh_user * diff --git a/zebra/zserv.c b/zebra/zserv.c index b36f8fe425..d625c02ff4 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1867,7 +1867,7 @@ zebra_client_close (struct zserv *client) /* Free client structure. */ listnode_delete (zebrad.client_list, client); - XFREE (0, client); + XFREE (MTYPE_TMP, client); } /* Make new client. */ @@ -1878,7 +1878,7 @@ zebra_client_create (int sock) int i; afi_t afi; - client = XCALLOC (0, sizeof (struct zserv)); + client = XCALLOC (MTYPE_TMP, sizeof (struct zserv)); /* Make client input/output buffer. */ client->sock = sock; From 65f9a9a8f588cf4bc3f685ab23dd07e2d0464875 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 29 Jul 2016 16:19:40 +0200 Subject: [PATCH 082/226] isisd: API: basic circuit config Create isis_vty.c and start moving off CLI functions into that. These then call newly-added "nice" API wrappers. Patch contains significant work authored by Christian Franke. [v2: removed stuff that crept in from the next patch] Signed-off-by: David Lamparter --- isisd/Makefile.am | 3 +- isisd/isis_circuit.c | 883 ++++--------------------------------------- isisd/isis_circuit.h | 12 + isisd/isis_redist.h | 1 + isisd/isis_vty.c | 678 +++++++++++++++++++++++++++++++++ isisd/isisd.h | 6 + 6 files changed, 773 insertions(+), 810 deletions(-) create mode 100644 isisd/isis_vty.c diff --git a/isisd/Makefile.am b/isisd/Makefile.am index 5f866638d9..6dd132d49a 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -16,7 +16,8 @@ libisis_a_SOURCES = \ isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ - isis_spf.c isis_redist.c isis_route.c isis_routemap.c + isis_spf.c isis_redist.c isis_route.c isis_routemap.c \ + isis_vty.c noinst_HEADERS = \ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 17ba40aa59..e17c0e77f7 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1250,364 +1250,88 @@ isis_interface_config_write (struct vty *vty) return write; } -DEFUN (ip_router_isis, - ip_router_isis_cmd, - "ip router isis WORD", - "Interface Internet Protocol config commands\n" - "IP router interface commands\n" - "IS-IS Routing for IP\n" - "Routing process tag\n") +struct isis_circuit * +isis_circuit_create (struct isis_area *area, struct interface *ifp) { struct isis_circuit *circuit; - struct interface *ifp; - struct isis_area *area; - int rv; - - ifp = (struct interface *) vty->index; - assert (ifp); - - /* Prevent more than one area per circuit */ - circuit = circuit_scan_by_ifp (ifp); - if (circuit) - { - if (circuit->ip_router == 1) - { - if (strcmp (circuit->area->area_tag, argv[0])) - { - vty_out (vty, "ISIS circuit is already defined on %s%s", - circuit->area->area_tag, VTY_NEWLINE); - return CMD_ERR_NOTHING_TODO; - } - return CMD_SUCCESS; - } - } - - if (isis_area_get (vty, argv[0]) != CMD_SUCCESS) - { - vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - area = vty->index; - - circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - { - vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); - rv = CMD_WARNING; - } - else - { - isis_circuit_if_bind (circuit, ifp); - - circuit->ip_router = 1; - area->ip_circuits++; - circuit_update_nlpids (circuit); - rv = CMD_SUCCESS; - } - - vty->node = INTERFACE_NODE; - vty->index = ifp; - - if (circuit->ipv6_router) - lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); - return rv; + circuit = isis_csm_state_change (ISIS_ENABLE, NULL, area); + assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); + isis_circuit_if_bind (circuit, ifp); + return circuit; } -DEFUN (no_ip_router_isis, - no_ip_router_isis_cmd, - "no ip router isis WORD", - NO_STR - "Interface Internet Protocol config commands\n" - "IP router interface commands\n" - "IS-IS Routing for IP\n" - "Routing process tag\n") +void +isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router) { - struct interface *ifp; - struct isis_area *area; - struct isis_circuit *circuit; + struct isis_area *area = circuit->area; + bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router; + bool was_enabled = circuit->ip_router || circuit->ipv6_router; - ifp = (struct interface *) vty->index; - if (!ifp) - { - vty_out (vty, "Invalid interface %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } + area->ip_circuits += ip_router - circuit->ip_router; + area->ipv6_circuits += ipv6_router - circuit->ipv6_router; + circuit->ip_router = ip_router; + circuit->ipv6_router = ipv6_router; - area = isis_area_lookup (argv[0]); - if (!area) - { - vty_out (vty, "Can't find ISIS instance %s%s", - argv[0], VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } + if (!change) + return; - circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s%s", - ifp->name, VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } + circuit_update_nlpids (circuit); - circuit->ip_router = 0; - area->ip_circuits--; - if (circuit->ipv6_router == 0) + if (!ip_router && !ipv6_router) isis_csm_state_change (ISIS_DISABLE, circuit, area); + else if (!was_enabled) + isis_csm_state_change (ISIS_ENABLE, circuit, area); else - lsp_regenerate_schedule(area, circuit->is_type, 0); - - return CMD_SUCCESS; -} - -#ifdef HAVE_IPV6 -DEFUN (ipv6_router_isis, - ipv6_router_isis_cmd, - "ipv6 router isis WORD", - "IPv6 interface subcommands\n" - "IPv6 Router interface commands\n" - "IS-IS Routing for IPv6\n" - "Routing process tag\n") -{ - struct isis_circuit *circuit; - struct interface *ifp; - struct isis_area *area; - int rv; - - ifp = (struct interface *) vty->index; - assert (ifp); - - /* Prevent more than one area per circuit */ - circuit = circuit_scan_by_ifp (ifp); - if (circuit) - { - if (circuit->ipv6_router == 1) - { - if (strcmp (circuit->area->area_tag, argv[0])) - { - vty_out (vty, "ISIS circuit is already defined for IPv6 on %s%s", - circuit->area->area_tag, VTY_NEWLINE); - return CMD_ERR_NOTHING_TODO; - } - return CMD_SUCCESS; - } - } - - if (isis_area_get (vty, argv[0]) != CMD_SUCCESS) - { - vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - area = vty->index; - - circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - { - vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); - rv = CMD_WARNING; - } - else - { - isis_circuit_if_bind (circuit, ifp); - - circuit->ipv6_router = 1; - area->ipv6_circuits++; - circuit_update_nlpids (circuit); - rv = CMD_SUCCESS; - } - - vty->node = INTERFACE_NODE; - vty->index = ifp; - - if (circuit->ip_router) lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); - return rv; } -DEFUN (no_ipv6_router_isis, - no_ipv6_router_isis_cmd, - "no ipv6 router isis WORD", - NO_STR - "IPv6 interface subcommands\n" - "IPv6 Router interface commands\n" - "IS-IS Routing for IPv6\n" - "Routing process tag\n") +int +isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) { - struct interface *ifp; - struct isis_area *area; - struct isis_circuit *circuit; + if (circuit->is_passive == passive) + return 0; - ifp = (struct interface *) vty->index; - if (!ifp) - { - vty_out (vty, "Invalid interface %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - area = isis_area_lookup (argv[0]); - if (!area) - { - vty_out (vty, "Can't find ISIS instance %s%s", - argv[0], VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s%s", - ifp->name, VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - circuit->ipv6_router = 0; - area->ipv6_circuits--; - if (circuit->ip_router == 0) - isis_csm_state_change (ISIS_DISABLE, circuit, area); - else - lsp_regenerate_schedule(area, circuit->is_type, 0); - - return CMD_SUCCESS; -} -#endif /* HAVE_IPV6 */ - -DEFUN (isis_passive, - isis_passive_cmd, - "isis passive", - "IS-IS commands\n" - "Configure the passive mode for interface\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - if (circuit->is_passive == 1) - return CMD_SUCCESS; + if (if_is_loopback (circuit->interface) && !passive) + return -1; if (circuit->state != C_STATE_UP) { - circuit->is_passive = 1; + circuit->is_passive = passive; } else { struct isis_area *area = circuit->area; isis_csm_state_change (ISIS_DISABLE, circuit, area); - circuit->is_passive = 1; + circuit->is_passive = passive; isis_csm_state_change (ISIS_ENABLE, circuit, area); } - return CMD_SUCCESS; + return 0; } -DEFUN (no_isis_passive, - no_isis_passive_cmd, - "no isis passive", - NO_STR - "IS-IS commands\n" - "Configure the passive mode for interface\n") +void +isis_circuit_is_type_set (struct isis_circuit *circuit, int circ_type) { - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *) vty->index; - if (!ifp) - { - vty_out (vty, "Invalid interface %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - /* FIXME: what is wrong with circuit = ifp->info ? */ - circuit = circuit_scan_by_ifp (ifp); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s%s", - ifp->name, VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - if (if_is_loopback(ifp)) - { - vty_out (vty, "Can't set no passive for loopback interface%s", - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - if (circuit->is_passive == 0) - return CMD_SUCCESS; - - if (circuit->state != C_STATE_UP) - { - circuit->is_passive = 0; - } - else - { - struct isis_area *area = circuit->area; - isis_csm_state_change (ISIS_DISABLE, circuit, area); - circuit->is_passive = 0; - isis_csm_state_change (ISIS_ENABLE, circuit, area); - } - - return CMD_SUCCESS; + if (circuit->circ_type != circ_type) + isis_event_circuit_type_change (circuit, circ_type); } -DEFUN (isis_circuit_type, - isis_circuit_type_cmd, - "isis circuit-type (level-1|level-1-2|level-2-only)", - "IS-IS commands\n" - "Configure circuit type for interface\n" - "Level-1 only adjacencies are formed\n" - "Level-1-2 adjacencies are formed\n" - "Level-2 only adjacencies are formed\n") +int +isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) { - int circuit_type; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + assert (level == IS_LEVEL_1 || level == IS_LEVEL_2); + if (metric > MAX_WIDE_LINK_METRIC) + return -1; + if (circuit->area && circuit->area->oldmetric + && metric > MAX_NARROW_LINK_METRIC) + return -1; - circuit_type = string2circuit_t (argv[0]); - if (!circuit_type) - { - vty_out (vty, "Unknown circuit-type %s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } + circuit->te_metric[level - 1] = metric; + circuit->metrics[level - 1].metric_default = metric; - if (circuit->state == C_STATE_UP && - circuit->area->is_type != IS_LEVEL_1_AND_2 && - circuit->area->is_type != circuit_type) - { - vty_out (vty, "Invalid circuit level for area %s.%s", - circuit->area->area_tag, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - isis_event_circuit_type_change (circuit, circuit_type); - - return CMD_SUCCESS; -} - -DEFUN (no_isis_circuit_type, - no_isis_circuit_type_cmd, - "no isis circuit-type (level-1|level-1-2|level-2-only)", - NO_STR - "IS-IS commands\n" - "Configure circuit type for interface\n" - "Level-1 only adjacencies are formed\n" - "Level-1-2 adjacencies are formed\n" - "Level-2 only adjacencies are formed\n") -{ - int circuit_type; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - /* - * Set the circuits level to its default value - */ - if (circuit->state == C_STATE_UP) - circuit_type = circuit->area->is_type; - else - circuit_type = IS_LEVEL_1_AND_2; - isis_event_circuit_type_change (circuit, circuit_type); - - return CMD_SUCCESS; + if (circuit->area) + lsp_regenerate_schedule (circuit->area, level, 0); + return 0; } DEFUN (isis_passwd_md5, @@ -1678,387 +1402,6 @@ DEFUN (no_isis_passwd, return CMD_SUCCESS; } -DEFUN (isis_priority, - isis_priority_cmd, - "isis priority <0-127>", - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n") -{ - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - prio = atoi (argv[0]); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>%s", - prio, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->priority[0] = prio; - circuit->priority[1] = prio; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_priority, - no_isis_priority_cmd, - "no isis priority", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->priority[0] = DEFAULT_PRIORITY; - circuit->priority[1] = DEFAULT_PRIORITY; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_priority, - no_isis_priority_arg_cmd, - "no isis priority <0-127>", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n") - -DEFUN (isis_priority_l1, - isis_priority_l1_cmd, - "isis priority <0-127> level-1", - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n" - "Specify priority for level-1 routing\n") -{ - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - prio = atoi (argv[0]); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>%s", - prio, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->priority[0] = prio; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_priority_l1, - no_isis_priority_l1_cmd, - "no isis priority level-1", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Specify priority for level-1 routing\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->priority[0] = DEFAULT_PRIORITY; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_priority_l1, - no_isis_priority_l1_arg_cmd, - "no isis priority <0-127> level-1", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n" - "Specify priority for level-1 routing\n") - -DEFUN (isis_priority_l2, - isis_priority_l2_cmd, - "isis priority <0-127> level-2", - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n" - "Specify priority for level-2 routing\n") -{ - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - prio = atoi (argv[0]); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>%s", - prio, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->priority[1] = prio; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_priority_l2, - no_isis_priority_l2_cmd, - "no isis priority level-2", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Specify priority for level-2 routing\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->priority[1] = DEFAULT_PRIORITY; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_priority_l2, - no_isis_priority_l2_arg_cmd, - "no isis priority <0-127> level-2", - NO_STR - "IS-IS commands\n" - "Set priority for Designated Router election\n" - "Priority value\n" - "Specify priority for level-2 routing\n") - -/* Metric command */ -DEFUN (isis_metric, - isis_metric_cmd, - "isis metric <0-16777215>", - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n") -{ - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - met = atoi (argv[0]); - - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->te_metric[0] = met; - circuit->te_metric[1] = met; - - circuit->metrics[0].metric_default = met; - circuit->metrics[1].metric_default = met; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); - - return CMD_SUCCESS; -} - -DEFUN (no_isis_metric, - no_isis_metric_cmd, - "no isis metric", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->te_metric[0] = DEFAULT_CIRCUIT_METRIC; - circuit->te_metric[1] = DEFAULT_CIRCUIT_METRIC; - circuit->metrics[0].metric_default = DEFAULT_CIRCUIT_METRIC; - circuit->metrics[1].metric_default = DEFAULT_CIRCUIT_METRIC; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); - - return CMD_SUCCESS; -} - -ALIAS (no_isis_metric, - no_isis_metric_arg_cmd, - "no isis metric <0-16777215>", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n") - -DEFUN (isis_metric_l1, - isis_metric_l1_cmd, - "isis metric <0-16777215> level-1", - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n" - "Specify metric for level-1 routing\n") -{ - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - met = atoi (argv[0]); - - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->te_metric[0] = met; - circuit->metrics[0].metric_default = met; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, IS_LEVEL_1, 0); - - return CMD_SUCCESS; -} - -DEFUN (no_isis_metric_l1, - no_isis_metric_l1_cmd, - "no isis metric level-1", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n" - "Specify metric for level-1 routing\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->te_metric[0] = DEFAULT_CIRCUIT_METRIC; - circuit->metrics[0].metric_default = DEFAULT_CIRCUIT_METRIC; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, IS_LEVEL_1, 0); - - return CMD_SUCCESS; -} - -ALIAS (no_isis_metric_l1, - no_isis_metric_l1_arg_cmd, - "no isis metric <0-16777215> level-1", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n" - "Specify metric for level-1 routing\n") - -DEFUN (isis_metric_l2, - isis_metric_l2_cmd, - "isis metric <0-16777215> level-2", - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n" - "Specify metric for level-2 routing\n") -{ - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - met = atoi (argv[0]); - - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled%s", - met, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->te_metric[1] = met; - circuit->metrics[1].metric_default = met; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, IS_LEVEL_2, 0); - - return CMD_SUCCESS; -} - -DEFUN (no_isis_metric_l2, - no_isis_metric_l2_cmd, - "no isis metric level-2", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n" - "Specify metric for level-2 routing\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->te_metric[1] = DEFAULT_CIRCUIT_METRIC; - circuit->metrics[1].metric_default = DEFAULT_CIRCUIT_METRIC; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, IS_LEVEL_2, 0); - - return CMD_SUCCESS; -} - -ALIAS (no_isis_metric_l2, - no_isis_metric_l2_arg_cmd, - "no isis metric <0-16777215> level-2", - NO_STR - "IS-IS commands\n" - "Set default metric for circuit\n" - "Default metric value\n" - "Specify metric for level-2 routing\n") -/* end of metrics */ - DEFUN (isis_hello_interval, isis_hello_interval_cmd, "isis hello-interval <1-600>", @@ -2726,86 +2069,43 @@ struct cmd_node interface_node = { 1, }; -DEFUN (isis_network, - isis_network_cmd, - "isis network point-to-point", - "IS-IS commands\n" - "Set network type\n" - "point-to-point network type\n") +int +isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + /* Changing the network type to/of loopback or unknown interfaces + * is not supported. */ + if (circ_type == CIRCUIT_T_UNKNOWN + || circ_type == CIRCUIT_T_LOOPBACK + || circuit->circ_type == CIRCUIT_T_UNKNOWN + || circuit->circ_type == CIRCUIT_T_LOOPBACK) + { + if (circuit->circ_type != circ_type) + return -1; + else + return 0; + } - /* RFC5309 section 4 */ - if (circuit->circ_type == CIRCUIT_T_P2P) - return CMD_SUCCESS; + if (circuit->circ_type == circ_type) + return 0; if (circuit->state != C_STATE_UP) { - circuit->circ_type = CIRCUIT_T_P2P; - circuit->circ_type_config = CIRCUIT_T_P2P; + circuit->circ_type = circ_type; + circuit->circ_type_config = circ_type; } else { struct isis_area *area = circuit->area; - if (!if_is_broadcast (circuit->interface)) - { - vty_out (vty, "isis network point-to-point " - "is valid only on broadcast interfaces%s", - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } + if (circ_type == CIRCUIT_T_BROADCAST + && !if_is_broadcast(circuit->interface)) + return -1; - isis_csm_state_change (ISIS_DISABLE, circuit, area); - circuit->circ_type = CIRCUIT_T_P2P; - circuit->circ_type_config = CIRCUIT_T_P2P; - isis_csm_state_change (ISIS_ENABLE, circuit, area); + isis_csm_state_change(ISIS_DISABLE, circuit, area); + circuit->circ_type = circ_type; + circuit->circ_type_config = circ_type; + isis_csm_state_change(ISIS_ENABLE, circuit, area); } - - return CMD_SUCCESS; -} - -DEFUN (no_isis_network, - no_isis_network_cmd, - "no isis network point-to-point", - NO_STR - "IS-IS commands\n" - "Set network type for circuit\n" - "point-to-point network type\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - /* RFC5309 section 4 */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - return CMD_SUCCESS; - - if (circuit->state != C_STATE_UP) - { - circuit->circ_type = CIRCUIT_T_BROADCAST; - circuit->circ_type_config = CIRCUIT_T_BROADCAST; - } - else - { - struct isis_area *area = circuit->area; - if (circuit->interface && - !if_is_broadcast (circuit->interface)) - { - vty_out (vty, "no isis network point-to-point " - "is valid only on broadcast interfaces%s", - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - isis_csm_state_change (ISIS_DISABLE, circuit, area); - circuit->circ_type = CIRCUIT_T_BROADCAST; - circuit->circ_type_config = CIRCUIT_T_BROADCAST; - isis_csm_state_change (ISIS_ENABLE, circuit, area); - } - - return CMD_SUCCESS; + return 0; } int @@ -2845,39 +2145,10 @@ isis_circuit_init () install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd); - install_element (INTERFACE_NODE, &ip_router_isis_cmd); - install_element (INTERFACE_NODE, &no_ip_router_isis_cmd); - - install_element (INTERFACE_NODE, &isis_passive_cmd); - install_element (INTERFACE_NODE, &no_isis_passive_cmd); - - install_element (INTERFACE_NODE, &isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &isis_passwd_clear_cmd); install_element (INTERFACE_NODE, &isis_passwd_md5_cmd); install_element (INTERFACE_NODE, &no_isis_passwd_cmd); - install_element (INTERFACE_NODE, &isis_priority_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd); - install_element (INTERFACE_NODE, &isis_priority_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l1_arg_cmd); - install_element (INTERFACE_NODE, &isis_priority_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l2_arg_cmd); - - install_element (INTERFACE_NODE, &isis_metric_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_arg_cmd); - install_element (INTERFACE_NODE, &isis_metric_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l1_arg_cmd); - install_element (INTERFACE_NODE, &isis_metric_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_cmd); install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd); install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd); @@ -2921,11 +2192,5 @@ isis_circuit_init () install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd); install_element (INTERFACE_NODE, &no_psnp_interval_l2_arg_cmd); - install_element (INTERFACE_NODE, &isis_network_cmd); - install_element (INTERFACE_NODE, &no_isis_network_cmd); - -#ifdef HAVE_IPV6 - install_element (INTERFACE_NODE, &ipv6_router_isis_cmd); - install_element (INTERFACE_NODE, &no_ipv6_router_isis_cmd); -#endif + isis_vty_init (); } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index d883879731..cd6420262f 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -24,6 +24,10 @@ #define ISIS_CIRCUIT_H #include "vty.h" +#include "if.h" + +#include "isis_constants.h" +#include "isis_common.h" #define CIRCUIT_MAX 255 @@ -167,4 +171,12 @@ void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, size_t isis_circuit_pdu_size(struct isis_circuit *circuit); void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream); +struct isis_circuit *isis_circuit_create (struct isis_area *area, struct interface *ifp); +void isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router); +int isis_circuit_passive_set (struct isis_circuit *circuit, bool passive); +void isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type); +int isis_circuit_circ_type_set (struct isis_circuit *circuit, int circ_type); + +int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric); + #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 2184620054..cc9c2e6345 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -44,6 +44,7 @@ struct isis_redist struct isis_area; struct prefix; +struct vty; struct route_table *get_ext_reach(struct isis_area *area, int family, int level); diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c new file mode 100644 index 0000000000..4b45df1df0 --- /dev/null +++ b/isisd/isis_vty.c @@ -0,0 +1,678 @@ +/* + * IS-IS Rout(e)ing protocol - isis_circuit.h + * + * Copyright (C) 2001,2002 Sampo Saaristo + * Tampere University of Technology + * Institute of Communications Engineering + * Copyright (C) 2016 David Lamparter, for NetDEF, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "isis_circuit.h" +#include "isis_csm.h" +#include "isis_misc.h" +#include "isisd.h" + +static struct isis_circuit * +isis_circuit_lookup (struct vty *vty) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *) vty->index; + if (!ifp) + { + vty_out (vty, "Invalid interface %s", VTY_NEWLINE); + return NULL; + } + + circuit = circuit_scan_by_ifp (ifp); + if (!circuit) + { + vty_out (vty, "ISIS is not enabled on circuit %s%s", + ifp->name, VTY_NEWLINE); + return NULL; + } + + return circuit; +} + +DEFUN (ip_router_isis, + ip_router_isis_cmd, + "(ip|ipv6) router isis WORD", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS Routing for IP\n" + "Routing process tag\n") +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_area *area; + const char *af = argv[0]; + const char *area_tag = argv[1]; + + ifp = (struct interface *) vty->index; + assert (ifp); + + /* Prevent more than one area per circuit */ + circuit = circuit_scan_by_ifp (ifp); + if (circuit) + { + if (circuit->ip_router == 1) + { + if (strcmp (circuit->area->area_tag, area_tag)) + { + vty_out (vty, "ISIS circuit is already defined on %s%s", + circuit->area->area_tag, VTY_NEWLINE); + return CMD_ERR_NOTHING_TODO; + } + return CMD_SUCCESS; + } + } + + area = isis_area_lookup (area_tag); + if (!area) + area = isis_area_create (area_tag); + + if (!circuit) + circuit = isis_circuit_create (area, ifp); + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = true; + else + ip = true; + + isis_circuit_af_set (circuit, ip, ipv6); + return CMD_SUCCESS; +} + +DEFUN (no_ip_router_isis, + no_ip_router_isis_cmd, + "no (ip|ipv6) router isis WORD", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS Routing for IP\n" + "Routing process tag\n") +{ + struct interface *ifp; + struct isis_area *area; + struct isis_circuit *circuit; + const char *af = argv[0]; + const char *area_tag = argv[1]; + + ifp = (struct interface *) vty->index; + if (!ifp) + { + vty_out (vty, "Invalid interface %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + area = isis_area_lookup (area_tag); + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s%s", + argv[0], VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); + if (!circuit) + { + vty_out (vty, "ISIS is not enabled on circuit %s%s", + ifp->name, VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = false; + else + ip = false; + + isis_circuit_af_set (circuit, ip, ipv6); + return CMD_SUCCESS; +} + +DEFUN (isis_passive, + isis_passive_cmd, + "isis passive", + "IS-IS commands\n" + "Configure the passive mode for interface\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + isis_circuit_passive_set (circuit, 1); + return CMD_SUCCESS; +} + +DEFUN (no_isis_passive, + no_isis_passive_cmd, + "no isis passive", + NO_STR + "IS-IS commands\n" + "Configure the passive mode for interface\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (if_is_loopback (circuit->interface)) + { + vty_out (vty, "Can't set no passive for loopback interface%s", + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + isis_circuit_passive_set (circuit, 0); + return CMD_SUCCESS; +} + +DEFUN (isis_circuit_type, + isis_circuit_type_cmd, + "isis circuit-type (level-1|level-1-2|level-2-only)", + "IS-IS commands\n" + "Configure circuit type for interface\n" + "Level-1 only adjacencies are formed\n" + "Level-1-2 adjacencies are formed\n" + "Level-2 only adjacencies are formed\n") +{ + int is_type; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + is_type = string2circuit_t (argv[0]); + if (!is_type) + { + vty_out (vty, "Unknown circuit-type %s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + if (circuit->state == C_STATE_UP && + circuit->area->is_type != IS_LEVEL_1_AND_2 && + circuit->area->is_type != is_type) + { + vty_out (vty, "Invalid circuit level for area %s.%s", + circuit->area->area_tag, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + isis_circuit_is_type_set (circuit, is_type); + + return CMD_SUCCESS; +} + +DEFUN (no_isis_circuit_type, + no_isis_circuit_type_cmd, + "no isis circuit-type (level-1|level-1-2|level-2-only)", + NO_STR + "IS-IS commands\n" + "Configure circuit type for interface\n" + "Level-1 only adjacencies are formed\n" + "Level-1-2 adjacencies are formed\n" + "Level-2 only adjacencies are formed\n") +{ + int is_type; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + /* + * Set the circuits level to its default value + */ + if (circuit->state == C_STATE_UP) + is_type = circuit->area->is_type; + else + is_type = IS_LEVEL_1_AND_2; + isis_circuit_is_type_set (circuit, is_type); + + return CMD_SUCCESS; +} + +DEFUN (isis_network, + isis_network_cmd, + "isis network point-to-point", + "IS-IS commands\n" + "Set network type\n" + "point-to-point network type\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) + { + vty_out (vty, "isis network point-to-point " + "is valid only on broadcast interfaces%s", + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + return CMD_SUCCESS; +} + +DEFUN (no_isis_network, + no_isis_network_cmd, + "no isis network point-to-point", + NO_STR + "IS-IS commands\n" + "Set network type for circuit\n" + "point-to-point network type\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) + { + vty_out (vty, "isis network point-to-point " + "is valid only on broadcast interfaces%s", + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + return CMD_SUCCESS; +} + +DEFUN (isis_priority, + isis_priority_cmd, + "isis priority <0-127>", + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n") +{ + int prio; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + prio = atoi (argv[0]); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) + { + vty_out (vty, "Invalid priority %d - should be <0-127>%s", + prio, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->priority[0] = prio; + circuit->priority[1] = prio; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_priority, + no_isis_priority_cmd, + "no isis priority", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->priority[0] = DEFAULT_PRIORITY; + circuit->priority[1] = DEFAULT_PRIORITY; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_priority, + no_isis_priority_arg_cmd, + "no isis priority <0-127>", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n") + +DEFUN (isis_priority_l1, + isis_priority_l1_cmd, + "isis priority <0-127> level-1", + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-1 routing\n") +{ + int prio; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + prio = atoi (argv[0]); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) + { + vty_out (vty, "Invalid priority %d - should be <0-127>%s", + prio, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->priority[0] = prio; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_priority_l1, + no_isis_priority_l1_cmd, + "no isis priority level-1", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Specify priority for level-1 routing\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->priority[0] = DEFAULT_PRIORITY; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_priority_l1, + no_isis_priority_l1_arg_cmd, + "no isis priority <0-127> level-1", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-1 routing\n") + +DEFUN (isis_priority_l2, + isis_priority_l2_cmd, + "isis priority <0-127> level-2", + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-2 routing\n") +{ + int prio; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + prio = atoi (argv[0]); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) + { + vty_out (vty, "Invalid priority %d - should be <0-127>%s", + prio, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->priority[1] = prio; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_priority_l2, + no_isis_priority_l2_cmd, + "no isis priority level-2", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Specify priority for level-2 routing\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->priority[1] = DEFAULT_PRIORITY; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_priority_l2, + no_isis_priority_l2_arg_cmd, + "no isis priority <0-127> level-2", + NO_STR + "IS-IS commands\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-2 routing\n") + +/* Metric command */ +DEFUN (isis_metric, + isis_metric_cmd, + "isis metric <0-16777215>", + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n") +{ + int met; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + met = atoi (argv[0]); + + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 && + met > MAX_NARROW_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 && + met > MAX_WIDE_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + isis_circuit_metric_set (circuit, IS_LEVEL_1, met); + isis_circuit_metric_set (circuit, IS_LEVEL_2, met); + return CMD_SUCCESS; +} + +DEFUN (no_isis_metric, + no_isis_metric_cmd, + "no isis metric", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); + isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; +} + +ALIAS (no_isis_metric, + no_isis_metric_arg_cmd, + "no isis metric <0-16777215>", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n") + +DEFUN (isis_metric_l1, + isis_metric_l1_cmd, + "isis metric <0-16777215> level-1", + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n" + "Specify metric for level-1 routing\n") +{ + int met; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + met = atoi (argv[0]); + + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 && + met > MAX_NARROW_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 && + met > MAX_WIDE_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + isis_circuit_metric_set (circuit, IS_LEVEL_1, met); + return CMD_SUCCESS; +} + +DEFUN (no_isis_metric_l1, + no_isis_metric_l1_cmd, + "no isis metric level-1", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n" + "Specify metric for level-1 routing\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; +} + +ALIAS (no_isis_metric_l1, + no_isis_metric_l1_arg_cmd, + "no isis metric <0-16777215> level-1", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n" + "Specify metric for level-1 routing\n") + +DEFUN (isis_metric_l2, + isis_metric_l2_cmd, + "isis metric <0-16777215> level-2", + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n" + "Specify metric for level-2 routing\n") +{ + int met; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + met = atoi (argv[0]); + + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 && + met > MAX_NARROW_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 && + met > MAX_WIDE_LINK_METRIC) + { + vty_out (vty, "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled%s", + met, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + isis_circuit_metric_set (circuit, IS_LEVEL_2, met); + return CMD_SUCCESS; +} + +DEFUN (no_isis_metric_l2, + no_isis_metric_l2_cmd, + "no isis metric level-2", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n" + "Specify metric for level-2 routing\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; +} + +ALIAS (no_isis_metric_l2, + no_isis_metric_l2_arg_cmd, + "no isis metric <0-16777215> level-2", + NO_STR + "IS-IS commands\n" + "Set default metric for circuit\n" + "Default metric value\n" + "Specify metric for level-2 routing\n") +/* end of metrics */ + +void +isis_vty_init (void) +{ + install_element (INTERFACE_NODE, &ip_router_isis_cmd); + install_element (INTERFACE_NODE, &no_ip_router_isis_cmd); + + install_element (INTERFACE_NODE, &isis_passive_cmd); + install_element (INTERFACE_NODE, &no_isis_passive_cmd); + + install_element (INTERFACE_NODE, &isis_circuit_type_cmd); + install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd); + + install_element (INTERFACE_NODE, &isis_network_cmd); + install_element (INTERFACE_NODE, &no_isis_network_cmd); + + install_element (INTERFACE_NODE, &isis_priority_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd); + install_element (INTERFACE_NODE, &isis_priority_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_l1_arg_cmd); + install_element (INTERFACE_NODE, &isis_priority_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_priority_l2_arg_cmd); + + install_element (INTERFACE_NODE, &isis_metric_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_arg_cmd); + install_element (INTERFACE_NODE, &isis_metric_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_l1_arg_cmd); + install_element (INTERFACE_NODE, &isis_metric_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd); +} diff --git a/isisd/isisd.h b/isisd/isisd.h index 6fe1eb8144..230e6b3f08 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -27,7 +27,11 @@ #define ISISD_VERSION "0.0.7" +#include "isisd/isis_constants.h" +#include "isisd/isis_common.h" #include "isisd/isis_redist.h" +#include "isis_flags.h" +#include "dict.h" /* uncomment if you are a developer in bug hunt */ /* #define EXTREME_DEBUG */ @@ -139,6 +143,8 @@ struct isis_area *isis_area_lookup (const char *); int isis_area_get (struct vty *vty, const char *area_tag); void print_debug(struct vty *, int, int); +void isis_vty_init (void); + /* Master of threads. */ extern struct thread_master *master; From a38a72db2c3660c6cdd990050ef80c2174ee81de Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:26 +0200 Subject: [PATCH 083/226] isisd: API: basic area config Move out basic area configuration (metric type, overload and attachment bits, dynamic hostname extension enable) into isis_vty.c. [v2: moved stuff back here that accidentally was in the previous patch] Signed-off-by: David Lamparter --- isisd/isis_vty.c | 178 ++++++++++++++++++++++++++++++++++++ isisd/isisd.c | 232 ++++++----------------------------------------- isisd/isisd.h | 6 ++ 3 files changed, 211 insertions(+), 205 deletions(-) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 4b45df1df0..06d59a814e 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -641,6 +641,172 @@ ALIAS (no_isis_metric_l2, "Specify metric for level-2 routing\n") /* end of metrics */ +static int +validate_metric_style_narrow (struct vty *vty, struct isis_area *area) +{ + struct isis_circuit *circuit; + struct listnode *node; + + if (! vty) + return CMD_ERR_AMBIGUOUS; + + if (! area) + { + vty_out (vty, "ISIS area is invalid%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) + { + if ((area->is_type & IS_LEVEL_1) && + (circuit->is_type & IS_LEVEL_1) && + (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) + { + vty_out (vty, "ISIS circuit %s metric is invalid%s", + circuit->interface->name, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if ((area->is_type & IS_LEVEL_2) && + (circuit->is_type & IS_LEVEL_2) && + (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) + { + vty_out (vty, "ISIS circuit %s metric is invalid%s", + circuit->interface->name, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + + return CMD_SUCCESS; +} + +DEFUN (metric_style, + metric_style_cmd, + "metric-style (narrow|transition|wide)", + "Use old-style (ISO 10589) or new-style packet formats\n" + "Use old style of TLVs with narrow metric\n" + "Send and accept both styles of TLVs during transition\n" + "Use new style of TLVs to carry wider metric\n") +{ + struct isis_area *area = vty->index; + int ret; + + assert(area); + + if (strncmp (argv[0], "w", 1) == 0) + { + isis_area_metricstyle_set(area, false, true); + return CMD_SUCCESS; + } + + ret = validate_metric_style_narrow (vty, area); + if (ret != CMD_SUCCESS) + return ret; + + if (strncmp (argv[0], "t", 1) == 0) + isis_area_metricstyle_set(area, true, true); + else if (strncmp (argv[0], "n", 1) == 0) + isis_area_metricstyle_set(area, true, false); + return CMD_SUCCESS; + + return CMD_SUCCESS; +} + +DEFUN (no_metric_style, + no_metric_style_cmd, + "no metric-style", + NO_STR + "Use old-style (ISO 10589) or new-style packet formats\n") +{ + struct isis_area *area = vty->index; + int ret; + + assert (area); + ret = validate_metric_style_narrow (vty, area); + if (ret != CMD_SUCCESS) + return ret; + + isis_area_metricstyle_set(area, true, false); + return CMD_SUCCESS; +} + +DEFUN (set_overload_bit, + set_overload_bit_cmd, + "set-overload-bit", + "Set overload bit to avoid any transit traffic\n" + "Set overload bit\n") +{ + struct isis_area *area = vty->index; + assert (area); + + isis_area_overload_bit_set(area, true); + return CMD_SUCCESS; +} + +DEFUN (no_set_overload_bit, + no_set_overload_bit_cmd, + "no set-overload-bit", + "Reset overload bit to accept transit traffic\n" + "Reset overload bit\n") +{ + struct isis_area *area = vty->index; + assert (area); + + isis_area_overload_bit_set(area, false); + return CMD_SUCCESS; +} + +DEFUN (set_attached_bit, + set_attached_bit_cmd, + "set-attached-bit", + "Set attached bit to identify as L1/L2 router for inter-area traffic\n" + "Set attached bit\n") +{ + struct isis_area *area = vty->index; + assert (area); + + isis_area_attached_bit_set(area, true); + return CMD_SUCCESS; +} + +DEFUN (no_set_attached_bit, + no_set_attached_bit_cmd, + "no set-attached-bit", + "Reset attached bit\n") +{ + struct isis_area *area = vty->index; + assert (area); + + isis_area_attached_bit_set(area, false); + return CMD_SUCCESS; +} + +DEFUN (dynamic_hostname, + dynamic_hostname_cmd, + "hostname dynamic", + "Dynamic hostname for IS-IS\n" + "Dynamic hostname\n") +{ + struct isis_area *area = vty->index; + assert(area); + + isis_area_dynhostname_set(area, true); + return CMD_SUCCESS; +} + +DEFUN (no_dynamic_hostname, + no_dynamic_hostname_cmd, + "no hostname dynamic", + NO_STR + "Dynamic hostname for IS-IS\n" + "Dynamic hostname\n") +{ + struct isis_area *area = vty->index; + assert(area); + + isis_area_dynhostname_set(area, false); + return CMD_SUCCESS; +} + void isis_vty_init (void) { @@ -675,4 +841,16 @@ isis_vty_init (void) install_element (INTERFACE_NODE, &isis_metric_l2_cmd); install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd); install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd); + + install_element (ISIS_NODE, &metric_style_cmd); + install_element (ISIS_NODE, &no_metric_style_cmd); + + install_element (ISIS_NODE, &set_overload_bit_cmd); + install_element (ISIS_NODE, &no_set_overload_bit_cmd); + + install_element (ISIS_NODE, &set_attached_bit_cmd); + install_element (ISIS_NODE, &no_set_attached_bit_cmd); + + install_element (ISIS_NODE, &dynamic_hostname_cmd); + install_element (ISIS_NODE, &no_dynamic_hostname_cmd); } diff --git a/isisd/isisd.c b/isisd/isisd.c index 228d2bcb31..7376bf84be 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -2174,213 +2174,47 @@ ALIAS (no_lsp_gen_interval_l2, "Set interval for level 2 only\n" "Minimum interval in seconds\n") -static int -validate_metric_style_narrow (struct vty *vty, struct isis_area *area) +void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, + bool new_metric) { - struct isis_circuit *circuit; - struct listnode *node; - - if (! vty) - return CMD_ERR_AMBIGUOUS; - - if (! area) + if (area->oldmetric != old_metric + || area->newmetric != new_metric) { - vty_out (vty, "ISIS area is invalid%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; + area->oldmetric = old_metric; + area->newmetric = new_metric; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); } +} - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) +void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit) +{ + char new_overload_bit = overload_bit ? LSPBIT_OL : 0; + + if (new_overload_bit != area->overload_bit) { - if ((area->is_type & IS_LEVEL_1) && - (circuit->is_type & IS_LEVEL_1) && - (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) - { - vty_out (vty, "ISIS circuit %s metric is invalid%s", - circuit->interface->name, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - if ((area->is_type & IS_LEVEL_2) && - (circuit->is_type & IS_LEVEL_2) && - (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) - { - vty_out (vty, "ISIS circuit %s metric is invalid%s", - circuit->interface->name, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } + area->overload_bit = new_overload_bit; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); } - - return CMD_SUCCESS; } -DEFUN (metric_style, - metric_style_cmd, - "metric-style (narrow|transition|wide)", - "Use old-style (ISO 10589) or new-style packet formats\n" - "Use old style of TLVs with narrow metric\n" - "Send and accept both styles of TLVs during transition\n" - "Use new style of TLVs to carry wider metric\n") +void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit) { - struct isis_area *area; - int ret; + char new_attached_bit = attached_bit ? LSPBIT_ATT : 0; - area = vty->index; - assert (area); - - if (strncmp (argv[0], "w", 1) == 0) + if (new_attached_bit != area->attached_bit) { - area->newmetric = 1; - area->oldmetric = 0; + area->attached_bit = new_attached_bit; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); } - else +} + +void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname) +{ + if (area->dynhostname != dynhostname) { - ret = validate_metric_style_narrow (vty, area); - if (ret != CMD_SUCCESS) - return ret; - - if (strncmp (argv[0], "t", 1) == 0) - { - area->newmetric = 1; - area->oldmetric = 1; - } - else if (strncmp (argv[0], "n", 1) == 0) - { - area->newmetric = 0; - area->oldmetric = 1; - } + area->dynhostname = dynhostname; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); } - - return CMD_SUCCESS; -} - -DEFUN (no_metric_style, - no_metric_style_cmd, - "no metric-style", - NO_STR - "Use old-style (ISO 10589) or new-style packet formats\n") -{ - struct isis_area *area; - int ret; - - area = vty->index; - assert (area); - - ret = validate_metric_style_narrow (vty, area); - if (ret != CMD_SUCCESS) - return ret; - - /* Default is narrow metric. */ - area->newmetric = 0; - area->oldmetric = 1; - - return CMD_SUCCESS; -} - -DEFUN (set_overload_bit, - set_overload_bit_cmd, - "set-overload-bit", - "Set overload bit to avoid any transit traffic\n" - "Set overload bit\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - area->overload_bit = LSPBIT_OL; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_set_overload_bit, - no_set_overload_bit_cmd, - "no set-overload-bit", - "Reset overload bit to accept transit traffic\n" - "Reset overload bit\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - area->overload_bit = 0; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -DEFUN (set_attached_bit, - set_attached_bit_cmd, - "set-attached-bit", - "Set attached bit to identify as L1/L2 router for inter-area traffic\n" - "Set attached bit\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - area->attached_bit = LSPBIT_ATT; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_set_attached_bit, - no_set_attached_bit_cmd, - "no set-attached-bit", - "Reset attached bit\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - area->attached_bit = 0; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -DEFUN (dynamic_hostname, - dynamic_hostname_cmd, - "hostname dynamic", - "Dynamic hostname for IS-IS\n" - "Dynamic hostname\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - if (!area->dynhostname) - { - area->dynhostname = 1; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } - - return CMD_SUCCESS; -} - -DEFUN (no_dynamic_hostname, - no_dynamic_hostname_cmd, - "no hostname dynamic", - NO_STR - "Dynamic hostname for IS-IS\n" - "Dynamic hostname\n") -{ - struct isis_area *area; - - area = vty->index; - assert (area); - - if (area->dynhostname) - { - area->dynhostname = 0; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } - - return CMD_SUCCESS; } DEFUN (spf_interval, @@ -3434,18 +3268,6 @@ isis_init () install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd); install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd); - install_element (ISIS_NODE, &set_overload_bit_cmd); - install_element (ISIS_NODE, &no_set_overload_bit_cmd); - - install_element (ISIS_NODE, &set_attached_bit_cmd); - install_element (ISIS_NODE, &no_set_attached_bit_cmd); - - install_element (ISIS_NODE, &dynamic_hostname_cmd); - install_element (ISIS_NODE, &no_dynamic_hostname_cmd); - - install_element (ISIS_NODE, &metric_style_cmd); - install_element (ISIS_NODE, &no_metric_style_cmd); - install_element (ISIS_NODE, &log_adj_changes_cmd); install_element (ISIS_NODE, &no_log_adj_changes_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 230e6b3f08..b3a61d1089 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -143,6 +143,12 @@ struct isis_area *isis_area_lookup (const char *); int isis_area_get (struct vty *vty, const char *area_tag); void print_debug(struct vty *, int, int); +void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit); +void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit); +void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname); +void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, + bool new_metric); + void isis_vty_init (void); /* Master of threads. */ From 50c7d14a2a250f469a434bdbd345a3262efe4b9c Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:27 +0200 Subject: [PATCH 084/226] isisd: API: circuit password This cleans up circuit password configuration a little bit. (Restructured several times by both Christian Franke and David Lamparter.) Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 81 +++++++++++++------------------------------- isisd/isis_circuit.h | 4 +++ isisd/isis_vty.c | 57 +++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 58 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index e17c0e77f7..cc7ada55f6 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1334,72 +1334,41 @@ isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) return 0; } -DEFUN (isis_passwd_md5, - isis_passwd_md5_cmd, - "isis password md5 WORD", - "IS-IS commands\n" - "Configure the authentication password for a circuit\n" - "Authentication type\n" - "Circuit password\n") +int +isis_circuit_passwd_unset (struct isis_circuit *circuit) { - int len; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - len = strlen (argv[0]); - if (len > 254) - { - vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - circuit->passwd.len = len; - circuit->passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5; - strncpy ((char *)circuit->passwd.passwd, argv[0], 255); - - return CMD_SUCCESS; + memset(&circuit->passwd, 0, sizeof(circuit->passwd)); + return 0; } -DEFUN (isis_passwd_clear, - isis_passwd_clear_cmd, - "isis password clear WORD", - "IS-IS commands\n" - "Configure the authentication password for a circuit\n" - "Authentication type\n" - "Circuit password\n") +static int +isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd) { int len; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - len = strlen (argv[0]); + if (!passwd) + return -1; + + len = strlen(passwd); if (len > 254) - { - vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - circuit->passwd.len = len; - circuit->passwd.type = ISIS_PASSWD_TYPE_CLEARTXT; - strncpy ((char *)circuit->passwd.passwd, argv[0], 255); + return -1; - return CMD_SUCCESS; + circuit->passwd.len = len; + strncpy((char *)circuit->passwd.passwd, passwd, 255); + circuit->passwd.type = passwd_type; + return 0; } -DEFUN (no_isis_passwd, - no_isis_passwd_cmd, - "no isis password", - NO_STR - "IS-IS commands\n" - "Configure the authentication password for a circuit\n") +int +isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd) { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd); +} - memset (&circuit->passwd, 0, sizeof (struct isis_passwd)); - - return CMD_SUCCESS; +int +isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd) +{ + return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd); } DEFUN (isis_hello_interval, @@ -2145,10 +2114,6 @@ isis_circuit_init () install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd); - install_element (INTERFACE_NODE, &isis_passwd_clear_cmd); - install_element (INTERFACE_NODE, &isis_passwd_md5_cmd); - install_element (INTERFACE_NODE, &no_isis_passwd_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_cmd); install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd); install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index cd6420262f..45bac09374 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -179,4 +179,8 @@ int isis_circuit_circ_type_set (struct isis_circuit *circuit, int circ_type); int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric); +int isis_circuit_passwd_unset (struct isis_circuit *circuit); +int isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd); +int isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd); + #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 06d59a814e..c6f2465348 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -293,6 +293,59 @@ DEFUN (no_isis_network, return CMD_SUCCESS; } +DEFUN (isis_passwd, + isis_passwd_cmd, + "isis password (md5|clear) WORD", + "IS-IS commands\n" + "Configure the authentication password for a circuit\n" + "HMAC-MD5 authentication\n" + "Cleartext password\n" + "Circuit password\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + int rv; + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (argv[0][0] == 'm') + rv = isis_circuit_passwd_hmac_md5_set(circuit, argv[1]); + else + rv = isis_circuit_passwd_cleartext_set(circuit, argv[1]); + if (rv) + { + vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + return CMD_SUCCESS; +} + +DEFUN (no_isis_passwd, + no_isis_passwd_cmd, + "no isis password", + NO_STR + "IS-IS commands\n" + "Configure the authentication password for a circuit\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + isis_circuit_passwd_unset(circuit); + + return CMD_SUCCESS; +} + +ALIAS (no_isis_passwd, + no_isis_passwd_arg_cmd, + "no isis password (md5|clear) WORD", + NO_STR + "IS-IS commands\n" + "Configure the authentication password for a circuit\n" + "HMAC-MD5 authentication\n" + "Cleartext password\n" + "Circuit password\n") + DEFUN (isis_priority, isis_priority_cmd, "isis priority <0-127>", @@ -822,6 +875,10 @@ isis_vty_init (void) install_element (INTERFACE_NODE, &isis_network_cmd); install_element (INTERFACE_NODE, &no_isis_network_cmd); + install_element (INTERFACE_NODE, &isis_passwd_cmd); + install_element (INTERFACE_NODE, &no_isis_passwd_cmd); + install_element (INTERFACE_NODE, &no_isis_passwd_arg_cmd); + install_element (INTERFACE_NODE, &isis_priority_cmd); install_element (INTERFACE_NODE, &no_isis_priority_cmd); install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd); From 01bb08b6dc9798bccb53a823de0b67d59239eee1 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:28 +0200 Subject: [PATCH 085/226] isisd: API: timers (IIH, CSNP, PSNP) No setters needed since change of fields doesn't require any specific action to make it apply. Just move the CLI defs to isis_vty.c. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 705 ------------------------------------------- isisd/isis_vty.c | 704 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 704 insertions(+), 705 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index cc7ada55f6..f53c08cfc5 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1370,668 +1370,6 @@ isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *pass { return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd); } - -DEFUN (isis_hello_interval, - isis_hello_interval_cmd, - "isis hello-interval <1-600>", - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 seconds, interval depends on multiplier\n") -{ - int interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atoi (argv[0]); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %d - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_interval[0] = (u_int16_t) interval; - circuit->hello_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_interval, - no_isis_hello_interval_cmd, - "no isis hello-interval", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; - circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_interval, - no_isis_hello_interval_arg_cmd, - "no isis hello-interval <1-600>", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 second, interval depends on multiplier\n") - -DEFUN (isis_hello_interval_l1, - isis_hello_interval_l1_cmd, - "isis hello-interval <1-600> level-1", - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 second, interval depends on multiplier\n" - "Specify hello-interval for level-1 IIHs\n") -{ - long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atoi (argv[0]); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_interval[0] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_interval_l1, - no_isis_hello_interval_l1_cmd, - "no isis hello-interval level-1", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n" - "Specify hello-interval for level-1 IIHs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_interval_l1, - no_isis_hello_interval_l1_arg_cmd, - "no isis hello-interval <1-600> level-1", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 second, interval depends on multiplier\n" - "Specify hello-interval for level-1 IIHs\n") - -DEFUN (isis_hello_interval_l2, - isis_hello_interval_l2_cmd, - "isis hello-interval <1-600> level-2", - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 second, interval depends on multiplier\n" - "Specify hello-interval for level-2 IIHs\n") -{ - long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atoi (argv[0]); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_interval_l2, - no_isis_hello_interval_l2_cmd, - "no isis hello-interval level-2", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n" - "Specify hello-interval for level-2 IIHs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_interval_l2, - no_isis_hello_interval_l2_arg_cmd, - "no isis hello-interval <1-600> level-2", - NO_STR - "IS-IS commands\n" - "Set Hello interval\n" - "Hello interval value\n" - "Holdtime 1 second, interval depends on multiplier\n" - "Specify hello-interval for level-2 IIHs\n") - -DEFUN (isis_hello_multiplier, - isis_hello_multiplier_cmd, - "isis hello-multiplier <2-100>", - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n") -{ - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - mult = atoi (argv[0]); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", - mult, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_multiplier[0] = (u_int16_t) mult; - circuit->hello_multiplier[1] = (u_int16_t) mult; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_multiplier, - no_isis_hello_multiplier_cmd, - "no isis hello-multiplier", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; - circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_multiplier, - no_isis_hello_multiplier_arg_cmd, - "no isis hello-multiplier <2-100>", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n") - -DEFUN (isis_hello_multiplier_l1, - isis_hello_multiplier_l1_cmd, - "isis hello-multiplier <2-100> level-1", - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n" - "Specify hello multiplier for level-1 IIHs\n") -{ - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - mult = atoi (argv[0]); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", - mult, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_multiplier[0] = (u_int16_t) mult; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_multiplier_l1, - no_isis_hello_multiplier_l1_cmd, - "no isis hello-multiplier level-1", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Specify hello multiplier for level-1 IIHs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_multiplier_l1, - no_isis_hello_multiplier_l1_arg_cmd, - "no isis hello-multiplier <2-100> level-1", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n" - "Specify hello multiplier for level-1 IIHs\n") - -DEFUN (isis_hello_multiplier_l2, - isis_hello_multiplier_l2_cmd, - "isis hello-multiplier <2-100> level-2", - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n" - "Specify hello multiplier for level-2 IIHs\n") -{ - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - mult = atoi (argv[0]); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", - mult, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->hello_multiplier[1] = (u_int16_t) mult; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_multiplier_l2, - no_isis_hello_multiplier_l2_cmd, - "no isis hello-multiplier level-2", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Specify hello multiplier for level-2 IIHs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; - - return CMD_SUCCESS; -} - -ALIAS (no_isis_hello_multiplier_l2, - no_isis_hello_multiplier_l2_arg_cmd, - "no isis hello-multiplier <2-100> level-2", - NO_STR - "IS-IS commands\n" - "Set multiplier for Hello holding time\n" - "Hello multiplier value\n" - "Specify hello multiplier for level-2 IIHs\n") - -DEFUN (isis_hello_padding, - isis_hello_padding_cmd, - "isis hello padding", - "IS-IS commands\n" - "Add padding to IS-IS hello packets\n" - "Pad hello packets\n" - "\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->pad_hellos = 1; - - return CMD_SUCCESS; -} - -DEFUN (no_isis_hello_padding, - no_isis_hello_padding_cmd, - "no isis hello padding", - NO_STR - "IS-IS commands\n" - "Add padding to IS-IS hello packets\n" - "Pad hello packets\n" - "\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->pad_hellos = 0; - - return CMD_SUCCESS; -} - -DEFUN (csnp_interval, - csnp_interval_cmd, - "isis csnp-interval <1-600>", - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->csnp_interval[0] = (u_int16_t) interval; - circuit->csnp_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_csnp_interval, - no_csnp_interval_cmd, - "no isis csnp-interval", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; - circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_csnp_interval, - no_csnp_interval_arg_cmd, - "no isis csnp-interval <1-600>", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n") - -DEFUN (csnp_interval_l1, - csnp_interval_l1_cmd, - "isis csnp-interval <1-600> level-1", - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n" - "Specify interval for level-1 CSNPs\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->csnp_interval[0] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_csnp_interval_l1, - no_csnp_interval_l1_cmd, - "no isis csnp-interval level-1", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "Specify interval for level-1 CSNPs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_csnp_interval_l1, - no_csnp_interval_l1_arg_cmd, - "no isis csnp-interval <1-600> level-1", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n" - "Specify interval for level-1 CSNPs\n") - -DEFUN (csnp_interval_l2, - csnp_interval_l2_cmd, - "isis csnp-interval <1-600> level-2", - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n" - "Specify interval for level-2 CSNPs\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->csnp_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_csnp_interval_l2, - no_csnp_interval_l2_cmd, - "no isis csnp-interval level-2", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "Specify interval for level-2 CSNPs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_csnp_interval_l2, - no_csnp_interval_l2_arg_cmd, - "no isis csnp-interval <1-600> level-2", - NO_STR - "IS-IS commands\n" - "Set CSNP interval in seconds\n" - "CSNP interval value\n" - "Specify interval for level-2 CSNPs\n") - -DEFUN (psnp_interval, - psnp_interval_cmd, - "isis psnp-interval <1-120>", - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->psnp_interval[0] = (u_int16_t) interval; - circuit->psnp_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_psnp_interval, - no_psnp_interval_cmd, - "no isis psnp-interval", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; - circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_psnp_interval, - no_psnp_interval_arg_cmd, - "no isis psnp-interval <1-120>", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n") - -DEFUN (psnp_interval_l1, - psnp_interval_l1_cmd, - "isis psnp-interval <1-120> level-1", - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n" - "Specify interval for level-1 PSNPs\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->psnp_interval[0] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_psnp_interval_l1, - no_psnp_interval_l1_cmd, - "no isis psnp-interval level-1", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "Specify interval for level-1 PSNPs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_psnp_interval_l1, - no_psnp_interval_l1_arg_cmd, - "no isis psnp-interval <1-120> level-1", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n" - "Specify interval for level-1 PSNPs\n") - -DEFUN (psnp_interval_l2, - psnp_interval_l2_cmd, - "isis psnp-interval <1-120> level-2", - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n" - "Specify interval for level-2 PSNPs\n") -{ - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - interval = atol (argv[0]); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", - interval, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - circuit->psnp_interval[1] = (u_int16_t) interval; - - return CMD_SUCCESS; -} - -DEFUN (no_psnp_interval_l2, - no_psnp_interval_l2_cmd, - "no isis psnp-interval level-2", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "Specify interval for level-2 PSNPs\n") -{ - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - - circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_psnp_interval_l2, - no_psnp_interval_l2_arg_cmd, - "no isis psnp-interval <1-120> level-2", - NO_STR - "IS-IS commands\n" - "Set PSNP interval in seconds\n" - "PSNP interval value\n" - "Specify interval for level-2 PSNPs\n") - struct cmd_node interface_node = { INTERFACE_NODE, "%s(config-if)# ", @@ -2114,48 +1452,5 @@ isis_circuit_init () install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_arg_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_arg_cmd); - - install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_arg_cmd); - install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_arg_cmd); - install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_arg_cmd); - - install_element (INTERFACE_NODE, &isis_hello_padding_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_padding_cmd); - - install_element (INTERFACE_NODE, &csnp_interval_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_arg_cmd); - install_element (INTERFACE_NODE, &csnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l1_arg_cmd); - install_element (INTERFACE_NODE, &csnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l2_arg_cmd); - - install_element (INTERFACE_NODE, &psnp_interval_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_arg_cmd); - install_element (INTERFACE_NODE, &psnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l1_arg_cmd); - install_element (INTERFACE_NODE, &psnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l2_arg_cmd); - isis_vty_init (); } diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index c6f2465348..3dd3682ced 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -694,6 +694,667 @@ ALIAS (no_isis_metric_l2, "Specify metric for level-2 routing\n") /* end of metrics */ +DEFUN (isis_hello_interval, + isis_hello_interval_cmd, + "isis hello-interval <1-600>", + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 seconds, interval depends on multiplier\n") +{ + int interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atoi (argv[0]); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) + { + vty_out (vty, "Invalid hello-interval %d - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_interval[0] = (u_int16_t) interval; + circuit->hello_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_interval, + no_isis_hello_interval_cmd, + "no isis hello-interval", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; + circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_interval, + no_isis_hello_interval_arg_cmd, + "no isis hello-interval <1-600>", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 second, interval depends on multiplier\n") + +DEFUN (isis_hello_interval_l1, + isis_hello_interval_l1_cmd, + "isis hello-interval <1-600> level-1", + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 second, interval depends on multiplier\n" + "Specify hello-interval for level-1 IIHs\n") +{ + long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atoi (argv[0]); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) + { + vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_interval[0] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_interval_l1, + no_isis_hello_interval_l1_cmd, + "no isis hello-interval level-1", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n" + "Specify hello-interval for level-1 IIHs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_interval_l1, + no_isis_hello_interval_l1_arg_cmd, + "no isis hello-interval <1-600> level-1", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 second, interval depends on multiplier\n" + "Specify hello-interval for level-1 IIHs\n") + +DEFUN (isis_hello_interval_l2, + isis_hello_interval_l2_cmd, + "isis hello-interval <1-600> level-2", + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 second, interval depends on multiplier\n" + "Specify hello-interval for level-2 IIHs\n") +{ + long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atoi (argv[0]); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) + { + vty_out (vty, "Invalid hello-interval %ld - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_interval_l2, + no_isis_hello_interval_l2_cmd, + "no isis hello-interval level-2", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n" + "Specify hello-interval for level-2 IIHs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_interval_l2, + no_isis_hello_interval_l2_arg_cmd, + "no isis hello-interval <1-600> level-2", + NO_STR + "IS-IS commands\n" + "Set Hello interval\n" + "Hello interval value\n" + "Holdtime 1 second, interval depends on multiplier\n" + "Specify hello-interval for level-2 IIHs\n") + +DEFUN (isis_hello_multiplier, + isis_hello_multiplier_cmd, + "isis hello-multiplier <2-100>", + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n") +{ + int mult; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + mult = atoi (argv[0]); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) + { + vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", + mult, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_multiplier[0] = (u_int16_t) mult; + circuit->hello_multiplier[1] = (u_int16_t) mult; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_multiplier, + no_isis_hello_multiplier_cmd, + "no isis hello-multiplier", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; + circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_multiplier, + no_isis_hello_multiplier_arg_cmd, + "no isis hello-multiplier <2-100>", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n") + +DEFUN (isis_hello_multiplier_l1, + isis_hello_multiplier_l1_cmd, + "isis hello-multiplier <2-100> level-1", + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n" + "Specify hello multiplier for level-1 IIHs\n") +{ + int mult; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + mult = atoi (argv[0]); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) + { + vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", + mult, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_multiplier[0] = (u_int16_t) mult; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_multiplier_l1, + no_isis_hello_multiplier_l1_cmd, + "no isis hello-multiplier level-1", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Specify hello multiplier for level-1 IIHs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_multiplier_l1, + no_isis_hello_multiplier_l1_arg_cmd, + "no isis hello-multiplier <2-100> level-1", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n" + "Specify hello multiplier for level-1 IIHs\n") + +DEFUN (isis_hello_multiplier_l2, + isis_hello_multiplier_l2_cmd, + "isis hello-multiplier <2-100> level-2", + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n" + "Specify hello multiplier for level-2 IIHs\n") +{ + int mult; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + mult = atoi (argv[0]); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) + { + vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>%s", + mult, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->hello_multiplier[1] = (u_int16_t) mult; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_multiplier_l2, + no_isis_hello_multiplier_l2_cmd, + "no isis hello-multiplier level-2", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Specify hello multiplier for level-2 IIHs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; + + return CMD_SUCCESS; +} + +ALIAS (no_isis_hello_multiplier_l2, + no_isis_hello_multiplier_l2_arg_cmd, + "no isis hello-multiplier <2-100> level-2", + NO_STR + "IS-IS commands\n" + "Set multiplier for Hello holding time\n" + "Hello multiplier value\n" + "Specify hello multiplier for level-2 IIHs\n") + +DEFUN (isis_hello_padding, + isis_hello_padding_cmd, + "isis hello padding", + "IS-IS commands\n" + "Add padding to IS-IS hello packets\n" + "Pad hello packets\n" + "\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->pad_hellos = 1; + + return CMD_SUCCESS; +} + +DEFUN (no_isis_hello_padding, + no_isis_hello_padding_cmd, + "no isis hello padding", + NO_STR + "IS-IS commands\n" + "Add padding to IS-IS hello packets\n" + "Pad hello packets\n" + "\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->pad_hellos = 0; + + return CMD_SUCCESS; +} + +DEFUN (csnp_interval, + csnp_interval_cmd, + "isis csnp-interval <1-600>", + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) + { + vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->csnp_interval[0] = (u_int16_t) interval; + circuit->csnp_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_csnp_interval, + no_csnp_interval_cmd, + "no isis csnp-interval", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; + circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_csnp_interval, + no_csnp_interval_arg_cmd, + "no isis csnp-interval <1-600>", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n") + +DEFUN (csnp_interval_l1, + csnp_interval_l1_cmd, + "isis csnp-interval <1-600> level-1", + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-1 CSNPs\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) + { + vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->csnp_interval[0] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_csnp_interval_l1, + no_csnp_interval_l1_cmd, + "no isis csnp-interval level-1", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "Specify interval for level-1 CSNPs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_csnp_interval_l1, + no_csnp_interval_l1_arg_cmd, + "no isis csnp-interval <1-600> level-1", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-1 CSNPs\n") + +DEFUN (csnp_interval_l2, + csnp_interval_l2_cmd, + "isis csnp-interval <1-600> level-2", + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-2 CSNPs\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) + { + vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->csnp_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_csnp_interval_l2, + no_csnp_interval_l2_cmd, + "no isis csnp-interval level-2", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "Specify interval for level-2 CSNPs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_csnp_interval_l2, + no_csnp_interval_l2_arg_cmd, + "no isis csnp-interval <1-600> level-2", + NO_STR + "IS-IS commands\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-2 CSNPs\n") + +DEFUN (psnp_interval, + psnp_interval_cmd, + "isis psnp-interval <1-120>", + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) + { + vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->psnp_interval[0] = (u_int16_t) interval; + circuit->psnp_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_psnp_interval, + no_psnp_interval_cmd, + "no isis psnp-interval", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; + circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_psnp_interval, + no_psnp_interval_arg_cmd, + "no isis psnp-interval <1-120>", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n") + +DEFUN (psnp_interval_l1, + psnp_interval_l1_cmd, + "isis psnp-interval <1-120> level-1", + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-1 PSNPs\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) + { + vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->psnp_interval[0] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_psnp_interval_l1, + no_psnp_interval_l1_cmd, + "no isis psnp-interval level-1", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "Specify interval for level-1 PSNPs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_psnp_interval_l1, + no_psnp_interval_l1_arg_cmd, + "no isis psnp-interval <1-120> level-1", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-1 PSNPs\n") + +DEFUN (psnp_interval_l2, + psnp_interval_l2_cmd, + "isis psnp-interval <1-120> level-2", + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-2 PSNPs\n") +{ + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + interval = atol (argv[0]); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) + { + vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>%s", + interval, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + circuit->psnp_interval[1] = (u_int16_t) interval; + + return CMD_SUCCESS; +} + +DEFUN (no_psnp_interval_l2, + no_psnp_interval_l2_cmd, + "no isis psnp-interval level-2", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "Specify interval for level-2 PSNPs\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + + circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_psnp_interval_l2, + no_psnp_interval_l2_arg_cmd, + "no isis psnp-interval <1-120> level-2", + NO_STR + "IS-IS commands\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-2 PSNPs\n") + static int validate_metric_style_narrow (struct vty *vty, struct isis_area *area) { @@ -899,6 +1560,49 @@ isis_vty_init (void) install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd); install_element (INTERFACE_NODE, &no_isis_metric_l2_arg_cmd); + install_element (INTERFACE_NODE, &isis_hello_interval_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd); + install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_arg_cmd); + install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_arg_cmd); + + install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_arg_cmd); + install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_arg_cmd); + install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_arg_cmd); + + install_element (INTERFACE_NODE, &isis_hello_padding_cmd); + install_element (INTERFACE_NODE, &no_isis_hello_padding_cmd); + + install_element (INTERFACE_NODE, &csnp_interval_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_arg_cmd); + install_element (INTERFACE_NODE, &csnp_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_l1_arg_cmd); + install_element (INTERFACE_NODE, &csnp_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_csnp_interval_l2_arg_cmd); + + install_element (INTERFACE_NODE, &psnp_interval_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_arg_cmd); + install_element (INTERFACE_NODE, &psnp_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_l1_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_l1_arg_cmd); + install_element (INTERFACE_NODE, &psnp_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd); + install_element (INTERFACE_NODE, &no_psnp_interval_l2_arg_cmd); + install_element (ISIS_NODE, &metric_style_cmd); install_element (ISIS_NODE, &no_metric_style_cmd); From 6754fc66505e38338d15f323d2f2dc1afafee8f3 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:29 +0200 Subject: [PATCH 086/226] isisd: API: LSP-MTU & area level Yet more CLI functions in isis_vty.c using more nice setters. Signed-off-by: David Lamparter --- isisd/isis_events.c | 113 ----------------------- isisd/isis_events.h | 5 - isisd/isis_vty.c | 126 +++++++++++++++++++++++++ isisd/isisd.c | 219 ++++++++++++++++++++------------------------ isisd/isisd.h | 2 + 5 files changed, 227 insertions(+), 238 deletions(-) diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 0dee9e6f52..8fb92fdd39 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -77,119 +77,6 @@ isis_event_circuit_state_change (struct isis_circuit *circuit, return; } -static void -area_resign_level (struct isis_area *area, int level) -{ - if (area->lspdb[level - 1]) - { - lsp_db_destroy (area->lspdb[level - 1]); - area->lspdb[level - 1] = NULL; - } - if (area->spftree[level - 1]) - { - isis_spftree_del (area->spftree[level - 1]); - area->spftree[level - 1] = NULL; - } -#ifdef HAVE_IPV6 - if (area->spftree6[level - 1]) - { - isis_spftree_del (area->spftree6[level - 1]); - area->spftree6[level - 1] = NULL; - } -#endif - if (area->route_table[level - 1]) - { - route_table_finish (area->route_table[level - 1]); - area->route_table[level - 1] = NULL; - } -#ifdef HAVE_IPV6 - if (area->route_table6[level - 1]) - { - route_table_finish (area->route_table6[level - 1]); - area->route_table6[level - 1] = NULL; - } -#endif /* HAVE_IPV6 */ - - sched_debug("ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.", - area->area_tag, level); - THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); - area->lsp_regenerate_pending[level - 1] = 0; -} - -void -isis_event_system_type_change (struct isis_area *area, int newtype) -{ - struct listnode *node; - struct isis_circuit *circuit; - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag, - circuit_t2string (area->is_type), circuit_t2string (newtype)); - - if (area->is_type == newtype) - return; /* No change */ - - switch (area->is_type) - { - case IS_LEVEL_1: - if (newtype == IS_LEVEL_2) - area_resign_level (area, IS_LEVEL_1); - - if (area->lspdb[1] == NULL) - area->lspdb[1] = lsp_db_init (); - if (area->route_table[1] == NULL) - area->route_table[1] = route_table_init (); -#ifdef HAVE_IPV6 - if (area->route_table6[1] == NULL) - area->route_table6[1] = route_table_init (); -#endif /* HAVE_IPV6 */ - break; - - case IS_LEVEL_1_AND_2: - if (newtype == IS_LEVEL_1) - area_resign_level (area, IS_LEVEL_2); - else - area_resign_level (area, IS_LEVEL_1); - break; - - case IS_LEVEL_2: - if (newtype == IS_LEVEL_1) - area_resign_level (area, IS_LEVEL_2); - - if (area->lspdb[0] == NULL) - area->lspdb[0] = lsp_db_init (); - if (area->route_table[0] == NULL) - area->route_table[0] = route_table_init (); -#ifdef HAVE_IPV6 - if (area->route_table6[0] == NULL) - area->route_table6[0] = route_table_init (); -#endif /* HAVE_IPV6 */ - break; - - default: - break; - } - - area->is_type = newtype; - - /* override circuit's is_type */ - if (area->is_type != IS_LEVEL_1_AND_2) - { - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - isis_event_circuit_type_change (circuit, newtype); - } - - spftree_area_init (area); - - if (newtype & IS_LEVEL_1) - lsp_generate (area, IS_LEVEL_1); - if (newtype & IS_LEVEL_2) - lsp_generate (area, IS_LEVEL_2); - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return; -} - static void circuit_commence_level (struct isis_circuit *circuit, int level) { diff --git a/isisd/isis_events.h b/isisd/isis_events.h index c252f3def9..e7cfa3509e 100644 --- a/isisd/isis_events.h +++ b/isisd/isis_events.h @@ -22,11 +22,6 @@ #ifndef _ZEBRA_ISIS_EVENTS_H #define _ZEBRA_ISIS_EVENTS_H -/* - * Events related to area - */ -void isis_event_system_type_change (struct isis_area *area, int newtype); - /* * Events related to circuit */ diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 3dd3682ced..ef910df9fc 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -1521,6 +1521,125 @@ DEFUN (no_dynamic_hostname, return CMD_SUCCESS; } +static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu) +{ + struct isis_area *area = vty->index; + struct listnode *node; + struct isis_circuit *circuit; + + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + { + if(circuit->state != C_STATE_INIT && circuit->state != C_STATE_UP) + continue; + if(lsp_mtu > isis_circuit_pdu_size(circuit)) + { + vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s", + circuit->interface->name, isis_circuit_pdu_size(circuit), + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + + isis_area_lsp_mtu_set(area, lsp_mtu); + return CMD_SUCCESS; +} + +DEFUN (area_lsp_mtu, + area_lsp_mtu_cmd, + "lsp-mtu <128-4352>", + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n") +{ + unsigned int lsp_mtu; + + VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352); + + return area_lsp_mtu_set(vty, lsp_mtu); +} + +DEFUN(no_area_lsp_mtu, + no_area_lsp_mtu_cmd, + "no lsp-mtu", + NO_STR + "Configure the maximum size of generated LSPs\n") +{ + return area_lsp_mtu_set(vty, DEFAULT_LSP_MTU); +} + +ALIAS(no_area_lsp_mtu, + no_area_lsp_mtu_arg_cmd, + "no lsp-mtu <128-4352>", + NO_STR + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n"); + +DEFUN (is_type, + is_type_cmd, + "is-type (level-1|level-1-2|level-2-only)", + "IS Level for this routing process (OSI only)\n" + "Act as a station router only\n" + "Act as both a station router and an area router\n" + "Act as an area router only\n") +{ + struct isis_area *area; + int type; + + area = vty->index; + + if (!area) + { + vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + type = string2circuit_t (argv[0]); + if (!type) + { + vty_out (vty, "Unknown IS level %s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + isis_area_is_type_set(area, type); + + return CMD_SUCCESS; +} + +DEFUN (no_is_type, + no_is_type_cmd, + "no is-type (level-1|level-1-2|level-2-only)", + NO_STR + "IS Level for this routing process (OSI only)\n" + "Act as a station router only\n" + "Act as both a station router and an area router\n" + "Act as an area router only\n") +{ + struct isis_area *area; + int type; + + area = vty->index; + assert (area); + + /* + * Put the is-type back to defaults: + * - level-1-2 on first area + * - level-1 for the rest + */ + if (listgetdata (listhead (isis->area_list)) == area) + type = IS_LEVEL_1_AND_2; + else + type = IS_LEVEL_1; + + isis_area_is_type_set(area, type); + + return CMD_SUCCESS; +} + void isis_vty_init (void) { @@ -1614,4 +1733,11 @@ isis_vty_init (void) install_element (ISIS_NODE, &dynamic_hostname_cmd); install_element (ISIS_NODE, &no_dynamic_hostname_cmd); + + install_element (ISIS_NODE, &area_lsp_mtu_cmd); + install_element (ISIS_NODE, &no_area_lsp_mtu_cmd); + install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd); + + install_element (ISIS_NODE, &is_type_cmd); + install_element (ISIS_NODE, &no_is_type_cmd); } diff --git a/isisd/isisd.c b/isisd/isisd.c index 7376bf84be..bcb16b8e63 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1612,78 +1612,12 @@ DEFUN (no_net, return area_clear_net_title (vty, argv[0]); } -static -int area_set_lsp_mtu(struct vty *vty, struct isis_area *area, unsigned int lsp_mtu) +void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu) { - struct isis_circuit *circuit; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) - { - if(circuit->state != C_STATE_INIT && circuit->state != C_STATE_UP) - continue; - if(lsp_mtu > isis_circuit_pdu_size(circuit)) - { - vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s", - circuit->interface->name, isis_circuit_pdu_size(circuit), - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - } - area->lsp_mtu = lsp_mtu; lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1); - - return CMD_SUCCESS; } -DEFUN (area_lsp_mtu, - area_lsp_mtu_cmd, - "lsp-mtu <128-4352>", - "Configure the maximum size of generated LSPs\n" - "Maximum size of generated LSPs\n") -{ - struct isis_area *area; - - area = vty->index; - if (!area) - { - vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - unsigned int lsp_mtu; - - VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352); - - return area_set_lsp_mtu(vty, area, lsp_mtu); -} - -DEFUN(no_area_lsp_mtu, - no_area_lsp_mtu_cmd, - "no lsp-mtu", - NO_STR - "Configure the maximum size of generated LSPs\n") -{ - struct isis_area *area; - - area = vty->index; - if (!area) - { - vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - return area_set_lsp_mtu(vty, area, DEFAULT_LSP_MTU); -} - -ALIAS(no_area_lsp_mtu, - no_area_lsp_mtu_arg_cmd, - "no lsp-mtu <128-4352>", - NO_STR - "Configure the maximum size of generated LSPs\n" - "Maximum size of generated LSPs\n"); - DEFUN (area_passwd_md5, area_passwd_md5_cmd, "area-password md5 WORD", @@ -1960,65 +1894,117 @@ DEFUN (no_domain_passwd, return CMD_SUCCESS; } -DEFUN (is_type, - is_type_cmd, - "is-type (level-1|level-1-2|level-2-only)", - "IS Level for this routing process (OSI only)\n" - "Act as a station router only\n" - "Act as both a station router and an area router\n" - "Act as an area router only\n") +static void +area_resign_level (struct isis_area *area, int level) { - struct isis_area *area; - int type; - - area = vty->index; - - if (!area) + if (area->lspdb[level - 1]) { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; + lsp_db_destroy (area->lspdb[level - 1]); + area->lspdb[level - 1] = NULL; } - - type = string2circuit_t (argv[0]); - if (!type) + if (area->spftree[level - 1]) { - vty_out (vty, "Unknown IS level %s", VTY_NEWLINE); - return CMD_SUCCESS; + isis_spftree_del (area->spftree[level - 1]); + area->spftree[level - 1] = NULL; } +#ifdef HAVE_IPV6 + if (area->spftree6[level - 1]) + { + isis_spftree_del (area->spftree6[level - 1]); + area->spftree6[level - 1] = NULL; + } +#endif + if (area->route_table[level - 1]) + { + route_table_finish (area->route_table[level - 1]); + area->route_table[level - 1] = NULL; + } +#ifdef HAVE_IPV6 + if (area->route_table6[level - 1]) + { + route_table_finish (area->route_table6[level - 1]); + area->route_table6[level - 1] = NULL; + } +#endif /* HAVE_IPV6 */ - isis_event_system_type_change (area, type); - - return CMD_SUCCESS; + sched_debug("ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.", + area->area_tag, level); + THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); + area->lsp_regenerate_pending[level - 1] = 0; } -DEFUN (no_is_type, - no_is_type_cmd, - "no is-type (level-1|level-1-2|level-2-only)", - NO_STR - "IS Level for this routing process (OSI only)\n" - "Act as a station router only\n" - "Act as both a station router and an area router\n" - "Act as an area router only\n") +void +isis_area_is_type_set(struct isis_area *area, int is_type) { - struct isis_area *area; - int type; + struct listnode *node; + struct isis_circuit *circuit; - area = vty->index; - assert (area); + if (isis->debugs & DEBUG_EVENTS) + zlog_debug ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag, + circuit_t2string (area->is_type), circuit_t2string (is_type)); - /* - * Put the is-type back to defaults: - * - level-1-2 on first area - * - level-1 for the rest - */ - if (listgetdata (listhead (isis->area_list)) == area) - type = IS_LEVEL_1_AND_2; - else - type = IS_LEVEL_1; + if (area->is_type == is_type) + return; /* No change */ - isis_event_system_type_change (area, type); + switch (area->is_type) + { + case IS_LEVEL_1: + if (is_type == IS_LEVEL_2) + area_resign_level (area, IS_LEVEL_1); - return CMD_SUCCESS; + if (area->lspdb[1] == NULL) + area->lspdb[1] = lsp_db_init (); + if (area->route_table[1] == NULL) + area->route_table[1] = route_table_init (); +#ifdef HAVE_IPV6 + if (area->route_table6[1] == NULL) + area->route_table6[1] = route_table_init (); +#endif /* HAVE_IPV6 */ + break; + + case IS_LEVEL_1_AND_2: + if (is_type == IS_LEVEL_1) + area_resign_level (area, IS_LEVEL_2); + else + area_resign_level (area, IS_LEVEL_1); + break; + + case IS_LEVEL_2: + if (is_type == IS_LEVEL_1) + area_resign_level (area, IS_LEVEL_2); + + if (area->lspdb[0] == NULL) + area->lspdb[0] = lsp_db_init (); + if (area->route_table[0] == NULL) + area->route_table[0] = route_table_init (); +#ifdef HAVE_IPV6 + if (area->route_table6[0] == NULL) + area->route_table6[0] = route_table_init (); +#endif /* HAVE_IPV6 */ + break; + + default: + break; + } + + area->is_type = is_type; + + /* override circuit's is_type */ + if (area->is_type != IS_LEVEL_1_AND_2) + { + for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) + isis_event_circuit_type_change (circuit, is_type); + } + + spftree_area_init (area); + + if (is_type & IS_LEVEL_1) + lsp_generate (area, IS_LEVEL_1); + if (is_type & IS_LEVEL_2) + lsp_generate (area, IS_LEVEL_2); + lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); + + return; } static int @@ -3209,13 +3195,6 @@ isis_init () install_element (ISIS_NODE, &net_cmd); install_element (ISIS_NODE, &no_net_cmd); - install_element (ISIS_NODE, &is_type_cmd); - install_element (ISIS_NODE, &no_is_type_cmd); - - install_element (ISIS_NODE, &area_lsp_mtu_cmd); - install_element (ISIS_NODE, &no_area_lsp_mtu_cmd); - install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd); - install_element (ISIS_NODE, &area_passwd_md5_cmd); install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd); install_element (ISIS_NODE, &area_passwd_clear_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index b3a61d1089..7a4575652d 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -148,6 +148,8 @@ void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit); void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname); void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, bool new_metric); +void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu); +void isis_area_is_type_set(struct isis_area *area, int is_type); void isis_vty_init (void); From 466ed4061dcce9a6d5895349fd2d8929258d9527 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:30 +0200 Subject: [PATCH 087/226] isisd: API: timers (LSP, SPF) See previous commits... Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 24 -- isisd/isis_vty.c | 565 +++++++++++++++++++++++++++++++++++++ isisd/isisd.c | 643 ++----------------------------------------- isisd/isisd.h | 4 + 4 files changed, 585 insertions(+), 651 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index f53c08cfc5..cac1065d44 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -196,30 +196,6 @@ circuit_scan_by_ifp (struct interface *ifp) return circuit_lookup_by_ifp (ifp, isis->init_circ_list); } -static struct isis_circuit * -isis_circuit_lookup (struct vty *vty) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *) vty->index; - if (!ifp) - { - vty_out (vty, "Invalid interface %s", VTY_NEWLINE); - return NULL; - } - - circuit = circuit_scan_by_ifp (ifp); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s%s", - ifp->name, VTY_NEWLINE); - return NULL; - } - - return circuit; -} - void isis_circuit_add_addr (struct isis_circuit *circuit, struct connected *connected) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index ef910df9fc..be41504302 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -1640,6 +1640,531 @@ DEFUN (no_is_type, return CMD_SUCCESS; } +static int +set_lsp_gen_interval (struct vty *vty, struct isis_area *area, + uint16_t interval, int level) +{ + int lvl; + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) + { + if (!(lvl & level)) + continue; + + if (interval >= area->lsp_refresh[lvl-1]) + { + vty_out (vty, "LSP gen interval %us must be less than " + "the LSP refresh interval %us%s", + interval, area->lsp_refresh[lvl-1], VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) + { + if (!(lvl & level)) + continue; + area->lsp_gen_interval[lvl-1] = interval; + } + + return CMD_SUCCESS; +} + +DEFUN (lsp_gen_interval, + lsp_gen_interval_cmd, + "lsp-gen-interval <1-120>", + "Minimum interval between regenerating same LSP\n" + "Minimum interval in seconds\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = atoi (argv[0]); + level = IS_LEVEL_1 | IS_LEVEL_2; + return set_lsp_gen_interval (vty, area, interval, level); +} + +DEFUN (no_lsp_gen_interval, + no_lsp_gen_interval_cmd, + "no lsp-gen-interval", + NO_STR + "Minimum interval between regenerating same LSP\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = DEFAULT_MIN_LSP_GEN_INTERVAL; + level = IS_LEVEL_1 | IS_LEVEL_2; + return set_lsp_gen_interval (vty, area, interval, level); +} + +ALIAS (no_lsp_gen_interval, + no_lsp_gen_interval_arg_cmd, + "no lsp-gen-interval <1-120>", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Minimum interval in seconds\n") + +DEFUN (lsp_gen_interval_l1, + lsp_gen_interval_l1_cmd, + "lsp-gen-interval level-1 <1-120>", + "Minimum interval between regenerating same LSP\n" + "Set interval for level 1 only\n" + "Minimum interval in seconds\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = atoi (argv[0]); + level = IS_LEVEL_1; + return set_lsp_gen_interval (vty, area, interval, level); +} + +DEFUN (no_lsp_gen_interval_l1, + no_lsp_gen_interval_l1_cmd, + "no lsp-gen-interval level-1", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Set interval for level 1 only\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = DEFAULT_MIN_LSP_GEN_INTERVAL; + level = IS_LEVEL_1; + return set_lsp_gen_interval (vty, area, interval, level); +} + +ALIAS (no_lsp_gen_interval_l1, + no_lsp_gen_interval_l1_arg_cmd, + "no lsp-gen-interval level-1 <1-120>", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Set interval for level 1 only\n" + "Minimum interval in seconds\n") + +DEFUN (lsp_gen_interval_l2, + lsp_gen_interval_l2_cmd, + "lsp-gen-interval level-2 <1-120>", + "Minimum interval between regenerating same LSP\n" + "Set interval for level 2 only\n" + "Minimum interval in seconds\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = atoi (argv[0]); + level = IS_LEVEL_2; + return set_lsp_gen_interval (vty, area, interval, level); +} + +DEFUN (no_lsp_gen_interval_l2, + no_lsp_gen_interval_l2_cmd, + "no lsp-gen-interval level-2", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Set interval for level 2 only\n") +{ + struct isis_area *area; + uint16_t interval; + int level; + + area = vty->index; + interval = DEFAULT_MIN_LSP_GEN_INTERVAL; + level = IS_LEVEL_2; + return set_lsp_gen_interval (vty, area, interval, level); +} + +ALIAS (no_lsp_gen_interval_l2, + no_lsp_gen_interval_l2_arg_cmd, + "no lsp-gen-interval level-2 <1-120>", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Set interval for level 2 only\n" + "Minimum interval in seconds\n") + +DEFUN (spf_interval, + spf_interval_cmd, + "spf-interval <1-120>", + "Minimum interval between SPF calculations\n" + "Minimum interval between consecutive SPFs in seconds\n") +{ + struct isis_area *area; + u_int16_t interval; + + area = vty->index; + interval = atoi (argv[0]); + area->min_spf_interval[0] = interval; + area->min_spf_interval[1] = interval; + + return CMD_SUCCESS; +} + +DEFUN (no_spf_interval, + no_spf_interval_cmd, + "no spf-interval", + NO_STR + "Minimum interval between SPF calculations\n") +{ + struct isis_area *area; + + area = vty->index; + + area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_spf_interval, + no_spf_interval_arg_cmd, + "no spf-interval <1-120>", + NO_STR + "Minimum interval between SPF calculations\n" + "Minimum interval between consecutive SPFs in seconds\n") + +DEFUN (spf_interval_l1, + spf_interval_l1_cmd, + "spf-interval level-1 <1-120>", + "Minimum interval between SPF calculations\n" + "Set interval for level 1 only\n" + "Minimum interval between consecutive SPFs in seconds\n") +{ + struct isis_area *area; + u_int16_t interval; + + area = vty->index; + interval = atoi (argv[0]); + area->min_spf_interval[0] = interval; + + return CMD_SUCCESS; +} + +DEFUN (no_spf_interval_l1, + no_spf_interval_l1_cmd, + "no spf-interval level-1", + NO_STR + "Minimum interval between SPF calculations\n" + "Set interval for level 1 only\n") +{ + struct isis_area *area; + + area = vty->index; + + area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_spf_interval, + no_spf_interval_l1_arg_cmd, + "no spf-interval level-1 <1-120>", + NO_STR + "Minimum interval between SPF calculations\n" + "Set interval for level 1 only\n" + "Minimum interval between consecutive SPFs in seconds\n") + +DEFUN (spf_interval_l2, + spf_interval_l2_cmd, + "spf-interval level-2 <1-120>", + "Minimum interval between SPF calculations\n" + "Set interval for level 2 only\n" + "Minimum interval between consecutive SPFs in seconds\n") +{ + struct isis_area *area; + u_int16_t interval; + + area = vty->index; + interval = atoi (argv[0]); + area->min_spf_interval[1] = interval; + + return CMD_SUCCESS; +} + +DEFUN (no_spf_interval_l2, + no_spf_interval_l2_cmd, + "no spf-interval level-2", + NO_STR + "Minimum interval between SPF calculations\n" + "Set interval for level 2 only\n") +{ + struct isis_area *area; + + area = vty->index; + + area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; + + return CMD_SUCCESS; +} + +ALIAS (no_spf_interval, + no_spf_interval_l2_arg_cmd, + "no spf-interval level-2 <1-120>", + NO_STR + "Minimum interval between SPF calculations\n" + "Set interval for level 2 only\n" + "Minimum interval between consecutive SPFs in seconds\n") + +static int +area_max_lsp_lifetime_set(struct vty *vty, int level, + uint16_t interval) +{ + struct isis_area *area = vty->index; + int lvl; + uint16_t refresh_interval = interval - 300; + int set_refresh_interval[ISIS_LEVELS] = {0, 0}; + + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) + { + if (!(lvl & level)) + continue; + + if (refresh_interval < area->lsp_refresh[lvl-1]) + { + vty_out (vty, "Level %d Max LSP lifetime %us must be 300s greater than " + "the configured LSP refresh interval %us%s", + lvl, interval, area->lsp_refresh[lvl-1], VTY_NEWLINE); + vty_out (vty, "Automatically reducing level %d LSP refresh interval " + "to %us%s", lvl, refresh_interval, VTY_NEWLINE); + set_refresh_interval[lvl-1] = 1; + + if (refresh_interval <= area->lsp_gen_interval[lvl-1]) + { + vty_out (vty, "LSP refresh interval %us must be greater than " + "the configured LSP gen interval %us%s", + refresh_interval, area->lsp_gen_interval[lvl-1], + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) + { + if (!(lvl & level)) + continue; + isis_area_max_lsp_lifetime_set(area, lvl, interval); + if (set_refresh_interval[lvl-1]) + isis_area_lsp_refresh_set(area, lvl, refresh_interval); + } + + return CMD_SUCCESS; +} + +DEFUN (max_lsp_lifetime, + max_lsp_lifetime_cmd, + "max-lsp-lifetime <350-65535>", + "Maximum LSP lifetime\n" + "LSP lifetime in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2, atoi(argv[0])); +} + +DEFUN (no_max_lsp_lifetime, + no_max_lsp_lifetime_cmd, + "no max-lsp-lifetime", + NO_STR + "LSP lifetime in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2, + DEFAULT_LSP_LIFETIME); +} + +ALIAS (no_max_lsp_lifetime, + no_max_lsp_lifetime_arg_cmd, + "no max-lsp-lifetime <350-65535>", + NO_STR + "Maximum LSP lifetime\n" + "LSP lifetime in seconds\n") + +DEFUN (max_lsp_lifetime_l1, + max_lsp_lifetime_l1_cmd, + "max-lsp-lifetime level-1 <350-65535>", + "Maximum LSP lifetime for Level 1 only\n" + "LSP lifetime for Level 1 only in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_1, atoi(argv[0])); +} + +DEFUN (no_max_lsp_lifetime_l1, + no_max_lsp_lifetime_l1_cmd, + "no max-lsp-lifetime level-1", + NO_STR + "LSP lifetime for Level 1 only in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_1, DEFAULT_LSP_LIFETIME); +} + +ALIAS (no_max_lsp_lifetime_l1, + no_max_lsp_lifetime_l1_arg_cmd, + "no max-lsp-lifetime level-1 <350-65535>", + NO_STR + "Maximum LSP lifetime for Level 1 only\n" + "LSP lifetime for Level 1 only in seconds\n") + +DEFUN (max_lsp_lifetime_l2, + max_lsp_lifetime_l2_cmd, + "max-lsp-lifetime level-2 <350-65535>", + "Maximum LSP lifetime for Level 2 only\n" + "LSP lifetime for Level 2 only in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_2, atoi(argv[0])); +} + +DEFUN (no_max_lsp_lifetime_l2, + no_max_lsp_lifetime_l2_cmd, + "no max-lsp-lifetime level-2", + NO_STR + "LSP lifetime for Level 2 only in seconds\n") +{ + return area_max_lsp_lifetime_set(vty, IS_LEVEL_2, DEFAULT_LSP_LIFETIME); +} + +ALIAS (no_max_lsp_lifetime_l2, + no_max_lsp_lifetime_l2_arg_cmd, + "no max-lsp-lifetime level-2 <350-65535>", + NO_STR + "Maximum LSP lifetime for Level 2 only\n" + "LSP lifetime for Level 2 only in seconds\n") + +static int +area_lsp_refresh_interval_set(struct vty *vty, int level, uint16_t interval) +{ + struct isis_area *area = vty->index; + int lvl; + + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) + { + if (!(lvl & level)) + continue; + if (interval <= area->lsp_gen_interval[lvl-1]) + { + vty_out (vty, "LSP refresh interval %us must be greater than " + "the configured LSP gen interval %us%s", + interval, area->lsp_gen_interval[lvl-1], + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (interval > (area->max_lsp_lifetime[lvl-1] - 300)) + { + vty_out (vty, "LSP refresh interval %us must be less than " + "the configured LSP lifetime %us less 300%s", + interval, area->max_lsp_lifetime[lvl-1], + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) + { + if (!(lvl & level)) + continue; + isis_area_lsp_refresh_set(area, lvl, interval); + } + + return CMD_SUCCESS; +} + +DEFUN (lsp_refresh_interval, + lsp_refresh_interval_cmd, + "lsp-refresh-interval <1-65235>", + "LSP refresh interval\n" + "LSP refresh interval in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_1_AND_2, atoi(argv[0])); +} + +DEFUN (no_lsp_refresh_interval, + no_lsp_refresh_interval_cmd, + "no lsp-refresh-interval", + NO_STR + "LSP refresh interval in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_1_AND_2, + DEFAULT_MAX_LSP_GEN_INTERVAL); +} + +ALIAS (no_lsp_refresh_interval, + no_lsp_refresh_interval_arg_cmd, + "no lsp-refresh-interval <1-65235>", + NO_STR + "LSP refresh interval\n" + "LSP refresh interval in seconds\n") + +DEFUN (lsp_refresh_interval_l1, + lsp_refresh_interval_l1_cmd, + "lsp-refresh-interval level-1 <1-65235>", + "LSP refresh interval for Level 1 only\n" + "LSP refresh interval for Level 1 only in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_1, atoi(argv[0])); +} + +DEFUN (no_lsp_refresh_interval_l1, + no_lsp_refresh_interval_l1_cmd, + "no lsp-refresh-interval level-1", + NO_STR + "LSP refresh interval for Level 1 only in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_1, + DEFAULT_MAX_LSP_GEN_INTERVAL); +} + +ALIAS (no_lsp_refresh_interval_l1, + no_lsp_refresh_interval_l1_arg_cmd, + "no lsp-refresh-interval level-1 <1-65235>", + NO_STR + "LSP refresh interval for Level 1 only\n" + "LSP refresh interval for Level 1 only in seconds\n") + +DEFUN (lsp_refresh_interval_l2, + lsp_refresh_interval_l2_cmd, + "lsp-refresh-interval level-2 <1-65235>", + "LSP refresh interval for Level 2 only\n" + "LSP refresh interval for Level 2 only in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_2, atoi(argv[0])); +} + +DEFUN (no_lsp_refresh_interval_l2, + no_lsp_refresh_interval_l2_cmd, + "no lsp-refresh-interval level-2", + NO_STR + "LSP refresh interval for Level 2 only in seconds\n") +{ + return area_lsp_refresh_interval_set(vty, IS_LEVEL_2, + DEFAULT_MAX_LSP_GEN_INTERVAL); +} + +ALIAS (no_lsp_refresh_interval_l2, + no_lsp_refresh_interval_l2_arg_cmd, + "no lsp-refresh-interval level-2 <1-65235>", + NO_STR + "LSP refresh interval for Level 2 only\n" + "LSP refresh interval for Level 2 only in seconds\n") + void isis_vty_init (void) { @@ -1740,4 +2265,44 @@ isis_vty_init (void) install_element (ISIS_NODE, &is_type_cmd); install_element (ISIS_NODE, &no_is_type_cmd); + + install_element (ISIS_NODE, &lsp_gen_interval_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_arg_cmd); + install_element (ISIS_NODE, &lsp_gen_interval_l1_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_l1_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_l1_arg_cmd); + install_element (ISIS_NODE, &lsp_gen_interval_l2_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_l2_cmd); + install_element (ISIS_NODE, &no_lsp_gen_interval_l2_arg_cmd); + + install_element (ISIS_NODE, &spf_interval_cmd); + install_element (ISIS_NODE, &no_spf_interval_cmd); + install_element (ISIS_NODE, &no_spf_interval_arg_cmd); + install_element (ISIS_NODE, &spf_interval_l1_cmd); + install_element (ISIS_NODE, &no_spf_interval_l1_cmd); + install_element (ISIS_NODE, &no_spf_interval_l1_arg_cmd); + install_element (ISIS_NODE, &spf_interval_l2_cmd); + install_element (ISIS_NODE, &no_spf_interval_l2_cmd); + install_element (ISIS_NODE, &no_spf_interval_l2_arg_cmd); + + install_element (ISIS_NODE, &max_lsp_lifetime_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_arg_cmd); + install_element (ISIS_NODE, &max_lsp_lifetime_l1_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_arg_cmd); + install_element (ISIS_NODE, &max_lsp_lifetime_l2_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_cmd); + install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_arg_cmd); + + install_element (ISIS_NODE, &lsp_refresh_interval_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_arg_cmd); + install_element (ISIS_NODE, &lsp_refresh_interval_l1_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_arg_cmd); + install_element (ISIS_NODE, &lsp_refresh_interval_l2_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd); + install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd); } diff --git a/isisd/isisd.c b/isisd/isisd.c index bcb16b8e63..4df38082ac 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -2007,159 +2007,6 @@ isis_area_is_type_set(struct isis_area *area, int is_type) return; } -static int -set_lsp_gen_interval (struct vty *vty, struct isis_area *area, - uint16_t interval, int level) -{ - int lvl; - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - - if (interval >= area->lsp_refresh[lvl-1]) - { - vty_out (vty, "LSP gen interval %us must be less than " - "the LSP refresh interval %us%s", - interval, area->lsp_refresh[lvl-1], VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - } - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - area->lsp_gen_interval[lvl-1] = interval; - } - - return CMD_SUCCESS; -} - -DEFUN (lsp_gen_interval, - lsp_gen_interval_cmd, - "lsp-gen-interval <1-120>", - "Minimum interval between regenerating same LSP\n" - "Minimum interval in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_gen_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_gen_interval, - no_lsp_gen_interval_cmd, - "no lsp-gen-interval", - NO_STR - "Minimum interval between regenerating same LSP\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MIN_LSP_GEN_INTERVAL; - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_gen_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_gen_interval, - no_lsp_gen_interval_arg_cmd, - "no lsp-gen-interval <1-120>", - NO_STR - "Minimum interval between regenerating same LSP\n" - "Minimum interval in seconds\n") - -DEFUN (lsp_gen_interval_l1, - lsp_gen_interval_l1_cmd, - "lsp-gen-interval level-1 <1-120>", - "Minimum interval between regenerating same LSP\n" - "Set interval for level 1 only\n" - "Minimum interval in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1; - return set_lsp_gen_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_gen_interval_l1, - no_lsp_gen_interval_l1_cmd, - "no lsp-gen-interval level-1", - NO_STR - "Minimum interval between regenerating same LSP\n" - "Set interval for level 1 only\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MIN_LSP_GEN_INTERVAL; - level = IS_LEVEL_1; - return set_lsp_gen_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_gen_interval_l1, - no_lsp_gen_interval_l1_arg_cmd, - "no lsp-gen-interval level-1 <1-120>", - NO_STR - "Minimum interval between regenerating same LSP\n" - "Set interval for level 1 only\n" - "Minimum interval in seconds\n") - -DEFUN (lsp_gen_interval_l2, - lsp_gen_interval_l2_cmd, - "lsp-gen-interval level-2 <1-120>", - "Minimum interval between regenerating same LSP\n" - "Set interval for level 2 only\n" - "Minimum interval in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_2; - return set_lsp_gen_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_gen_interval_l2, - no_lsp_gen_interval_l2_cmd, - "no lsp-gen-interval level-2", - NO_STR - "Minimum interval between regenerating same LSP\n" - "Set interval for level 2 only\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MIN_LSP_GEN_INTERVAL; - level = IS_LEVEL_2; - return set_lsp_gen_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_gen_interval_l2, - no_lsp_gen_interval_l2_arg_cmd, - "no lsp-gen-interval level-2 <1-120>", - NO_STR - "Minimum interval between regenerating same LSP\n" - "Set interval for level 2 only\n" - "Minimum interval in seconds\n") - void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, bool new_metric) { @@ -2203,450 +2050,32 @@ void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname) } } -DEFUN (spf_interval, - spf_interval_cmd, - "spf-interval <1-120>", - "Minimum interval between SPF calculations\n" - "Minimum interval between consecutive SPFs in seconds\n") +void +isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, + uint16_t max_lsp_lifetime) { - struct isis_area *area; - u_int16_t interval; + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); - area = vty->index; - interval = atoi (argv[0]); - area->min_spf_interval[0] = interval; - area->min_spf_interval[1] = interval; + if (area->max_lsp_lifetime[level-1] == max_lsp_lifetime) + return; - return CMD_SUCCESS; + area->max_lsp_lifetime[level-1] = max_lsp_lifetime; + lsp_regenerate_schedule(area, level, 1); } -DEFUN (no_spf_interval, - no_spf_interval_cmd, - "no spf-interval", - NO_STR - "Minimum interval between SPF calculations\n") +void +isis_area_lsp_refresh_set(struct isis_area *area, int level, + uint16_t lsp_refresh) { - struct isis_area *area; + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); - area = vty->index; + if (area->lsp_refresh[level-1] == lsp_refresh) + return; - area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; - area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; - - return CMD_SUCCESS; + area->lsp_refresh[level-1] = lsp_refresh; + lsp_regenerate_schedule(area, level, 1); } -ALIAS (no_spf_interval, - no_spf_interval_arg_cmd, - "no spf-interval <1-120>", - NO_STR - "Minimum interval between SPF calculations\n" - "Minimum interval between consecutive SPFs in seconds\n") - -DEFUN (spf_interval_l1, - spf_interval_l1_cmd, - "spf-interval level-1 <1-120>", - "Minimum interval between SPF calculations\n" - "Set interval for level 1 only\n" - "Minimum interval between consecutive SPFs in seconds\n") -{ - struct isis_area *area; - u_int16_t interval; - - area = vty->index; - interval = atoi (argv[0]); - area->min_spf_interval[0] = interval; - - return CMD_SUCCESS; -} - -DEFUN (no_spf_interval_l1, - no_spf_interval_l1_cmd, - "no spf-interval level-1", - NO_STR - "Minimum interval between SPF calculations\n" - "Set interval for level 1 only\n") -{ - struct isis_area *area; - - area = vty->index; - - area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_spf_interval, - no_spf_interval_l1_arg_cmd, - "no spf-interval level-1 <1-120>", - NO_STR - "Minimum interval between SPF calculations\n" - "Set interval for level 1 only\n" - "Minimum interval between consecutive SPFs in seconds\n") - -DEFUN (spf_interval_l2, - spf_interval_l2_cmd, - "spf-interval level-2 <1-120>", - "Minimum interval between SPF calculations\n" - "Set interval for level 2 only\n" - "Minimum interval between consecutive SPFs in seconds\n") -{ - struct isis_area *area; - u_int16_t interval; - - area = vty->index; - interval = atoi (argv[0]); - area->min_spf_interval[1] = interval; - - return CMD_SUCCESS; -} - -DEFUN (no_spf_interval_l2, - no_spf_interval_l2_cmd, - "no spf-interval level-2", - NO_STR - "Minimum interval between SPF calculations\n" - "Set interval for level 2 only\n") -{ - struct isis_area *area; - - area = vty->index; - - area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; - - return CMD_SUCCESS; -} - -ALIAS (no_spf_interval, - no_spf_interval_l2_arg_cmd, - "no spf-interval level-2 <1-120>", - NO_STR - "Minimum interval between SPF calculations\n" - "Set interval for level 2 only\n" - "Minimum interval between consecutive SPFs in seconds\n") - -static int -set_lsp_max_lifetime (struct vty *vty, struct isis_area *area, - uint16_t interval, int level) -{ - int lvl; - int set_refresh_interval[ISIS_LEVELS] = {0, 0}; - uint16_t refresh_interval; - - refresh_interval = interval - 300; - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - if (!(lvl & level)) - continue; - if (refresh_interval < area->lsp_refresh[lvl-1]) - { - vty_out (vty, "Level %d Max LSP lifetime %us must be 300s greater than " - "the configured LSP refresh interval %us%s", - lvl, interval, area->lsp_refresh[lvl-1], VTY_NEWLINE); - vty_out (vty, "Automatically reducing level %d LSP refresh interval " - "to %us%s", lvl, refresh_interval, VTY_NEWLINE); - set_refresh_interval[lvl-1] = 1; - - if (refresh_interval <= area->lsp_gen_interval[lvl-1]) - { - vty_out (vty, "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us%s", - refresh_interval, area->lsp_gen_interval[lvl-1], - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - } - } - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - if (!(lvl & level)) - continue; - area->max_lsp_lifetime[lvl-1] = interval; - /* Automatically reducing lsp_refresh_interval to interval - 300 */ - if (set_refresh_interval[lvl-1]) - area->lsp_refresh[lvl-1] = refresh_interval; - } - - lsp_regenerate_schedule (area, level, 1); - - return CMD_SUCCESS; -} - -DEFUN (max_lsp_lifetime, - max_lsp_lifetime_cmd, - "max-lsp-lifetime <350-65535>", - "Maximum LSP lifetime\n" - "LSP lifetime in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -DEFUN (no_max_lsp_lifetime, - no_max_lsp_lifetime_cmd, - "no max-lsp-lifetime", - NO_STR - "LSP lifetime in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_LSP_LIFETIME; - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -ALIAS (no_max_lsp_lifetime, - no_max_lsp_lifetime_arg_cmd, - "no max-lsp-lifetime <350-65535>", - NO_STR - "Maximum LSP lifetime\n" - "LSP lifetime in seconds\n") - -DEFUN (max_lsp_lifetime_l1, - max_lsp_lifetime_l1_cmd, - "max-lsp-lifetime level-1 <350-65535>", - "Maximum LSP lifetime for Level 1 only\n" - "LSP lifetime for Level 1 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -DEFUN (no_max_lsp_lifetime_l1, - no_max_lsp_lifetime_l1_cmd, - "no max-lsp-lifetime level-1", - NO_STR - "LSP lifetime for Level 1 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_LSP_LIFETIME; - level = IS_LEVEL_1; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -ALIAS (no_max_lsp_lifetime_l1, - no_max_lsp_lifetime_l1_arg_cmd, - "no max-lsp-lifetime level-1 <350-65535>", - NO_STR - "Maximum LSP lifetime for Level 1 only\n" - "LSP lifetime for Level 1 only in seconds\n") - -DEFUN (max_lsp_lifetime_l2, - max_lsp_lifetime_l2_cmd, - "max-lsp-lifetime level-2 <350-65535>", - "Maximum LSP lifetime for Level 2 only\n" - "LSP lifetime for Level 2 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_2; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -DEFUN (no_max_lsp_lifetime_l2, - no_max_lsp_lifetime_l2_cmd, - "no max-lsp-lifetime level-2", - NO_STR - "LSP lifetime for Level 2 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_LSP_LIFETIME; - level = IS_LEVEL_2; - return set_lsp_max_lifetime (vty, area, interval, level); -} - -ALIAS (no_max_lsp_lifetime_l2, - no_max_lsp_lifetime_l2_arg_cmd, - "no max-lsp-lifetime level-2 <350-65535>", - NO_STR - "Maximum LSP lifetime for Level 2 only\n" - "LSP lifetime for Level 2 only in seconds\n") - -static int -set_lsp_refresh_interval (struct vty *vty, struct isis_area *area, - uint16_t interval, int level) -{ - int lvl; - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - if (interval <= area->lsp_gen_interval[lvl-1]) - { - vty_out (vty, "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us%s", - interval, area->lsp_gen_interval[lvl-1], - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - if (interval > (area->max_lsp_lifetime[lvl-1] - 300)) - { - vty_out (vty, "LSP refresh interval %us must be less than " - "the configured LSP lifetime %us less 300%s", - interval, area->max_lsp_lifetime[lvl-1], - VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - } - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - area->lsp_refresh[lvl-1] = interval; - } - lsp_regenerate_schedule (area, level, 1); - - return CMD_SUCCESS; -} - -DEFUN (lsp_refresh_interval, - lsp_refresh_interval_cmd, - "lsp-refresh-interval <1-65235>", - "LSP refresh interval\n" - "LSP refresh interval in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_refresh_interval, - no_lsp_refresh_interval_cmd, - "no lsp-refresh-interval", - NO_STR - "LSP refresh interval in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MAX_LSP_GEN_INTERVAL; - level = IS_LEVEL_1 | IS_LEVEL_2; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_refresh_interval, - no_lsp_refresh_interval_arg_cmd, - "no lsp-refresh-interval <1-65235>", - NO_STR - "LSP refresh interval\n" - "LSP refresh interval in seconds\n") - -DEFUN (lsp_refresh_interval_l1, - lsp_refresh_interval_l1_cmd, - "lsp-refresh-interval level-1 <1-65235>", - "LSP refresh interval for Level 1 only\n" - "LSP refresh interval for Level 1 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_1; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_refresh_interval_l1, - no_lsp_refresh_interval_l1_cmd, - "no lsp-refresh-interval level-1", - NO_STR - "LSP refresh interval for Level 1 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MAX_LSP_GEN_INTERVAL; - level = IS_LEVEL_1; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_refresh_interval_l1, - no_lsp_refresh_interval_l1_arg_cmd, - "no lsp-refresh-interval level-1 <1-65235>", - NO_STR - "LSP refresh interval for Level 1 only\n" - "LSP refresh interval for Level 1 only in seconds\n") - -DEFUN (lsp_refresh_interval_l2, - lsp_refresh_interval_l2_cmd, - "lsp-refresh-interval level-2 <1-65235>", - "LSP refresh interval for Level 2 only\n" - "LSP refresh interval for Level 2 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = atoi (argv[0]); - level = IS_LEVEL_2; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -DEFUN (no_lsp_refresh_interval_l2, - no_lsp_refresh_interval_l2_cmd, - "no lsp-refresh-interval level-2", - NO_STR - "LSP refresh interval for Level 2 only in seconds\n") -{ - struct isis_area *area; - uint16_t interval; - int level; - - area = vty->index; - interval = DEFAULT_MAX_LSP_GEN_INTERVAL; - level = IS_LEVEL_2; - return set_lsp_refresh_interval (vty, area, interval, level); -} - -ALIAS (no_lsp_refresh_interval_l2, - no_lsp_refresh_interval_l2_arg_cmd, - "no lsp-refresh-interval level-2 <1-65235>", - NO_STR - "LSP refresh interval for Level 2 only\n" - "LSP refresh interval for Level 2 only in seconds\n") - DEFUN (log_adj_changes, log_adj_changes_cmd, "log-adjacency-changes", @@ -3207,46 +2636,6 @@ isis_init () install_element (ISIS_NODE, &domain_passwd_clear_snpauth_cmd); install_element (ISIS_NODE, &no_domain_passwd_cmd); - install_element (ISIS_NODE, &lsp_gen_interval_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_arg_cmd); - install_element (ISIS_NODE, &lsp_gen_interval_l1_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_l1_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_l1_arg_cmd); - install_element (ISIS_NODE, &lsp_gen_interval_l2_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_l2_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_l2_arg_cmd); - - install_element (ISIS_NODE, &spf_interval_cmd); - install_element (ISIS_NODE, &no_spf_interval_cmd); - install_element (ISIS_NODE, &no_spf_interval_arg_cmd); - install_element (ISIS_NODE, &spf_interval_l1_cmd); - install_element (ISIS_NODE, &no_spf_interval_l1_cmd); - install_element (ISIS_NODE, &no_spf_interval_l1_arg_cmd); - install_element (ISIS_NODE, &spf_interval_l2_cmd); - install_element (ISIS_NODE, &no_spf_interval_l2_cmd); - install_element (ISIS_NODE, &no_spf_interval_l2_arg_cmd); - - install_element (ISIS_NODE, &max_lsp_lifetime_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_arg_cmd); - install_element (ISIS_NODE, &max_lsp_lifetime_l1_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_l1_arg_cmd); - install_element (ISIS_NODE, &max_lsp_lifetime_l2_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_l2_arg_cmd); - - install_element (ISIS_NODE, &lsp_refresh_interval_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_arg_cmd); - install_element (ISIS_NODE, &lsp_refresh_interval_l1_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_l1_arg_cmd); - install_element (ISIS_NODE, &lsp_refresh_interval_l2_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd); - install_element (ISIS_NODE, &log_adj_changes_cmd); install_element (ISIS_NODE, &no_log_adj_changes_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 7a4575652d..5f996970f5 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -150,6 +150,10 @@ void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, bool new_metric); void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu); void isis_area_is_type_set(struct isis_area *area, int is_type); +void isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, + uint16_t max_lsp_lifetime); +void isis_area_lsp_refresh_set(struct isis_area *area, int level, + uint16_t lsp_refresh); void isis_vty_init (void); From 9093b23046a085b3c5ecc70fe361dccac79bf69b Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 28 Jul 2016 17:23:31 +0200 Subject: [PATCH 088/226] isisd: API: area (L1), domain (L2) passwords Last isisd CLI cleanup for now. This also folds L1 & L2 configs into common functions, reducing CLI function bloat by a bit. (This patch contains changes authored by both Christian Franke and David Lamparter.) Signed-off-by: David Lamparter --- isisd/isis_vty.c | 117 ++++++++++++++++++ isisd/isisd.c | 304 ++++++----------------------------------------- isisd/isisd.h | 7 +- 3 files changed, 160 insertions(+), 268 deletions(-) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index be41504302..3f218561cc 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -2165,6 +2165,117 @@ ALIAS (no_lsp_refresh_interval_l2, "LSP refresh interval for Level 2 only\n" "LSP refresh interval for Level 2 only in seconds\n") +static int +area_passwd_set(struct vty *vty, int level, + int (*type_set)(struct isis_area *area, int level, + const char *passwd, u_char snp_auth), + const char *passwd, u_char snp_auth) +{ + struct isis_area *area = vty->index; + + if (!area) + { + vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + if (passwd && strlen(passwd) > 254) + { + vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + type_set(area, level, passwd, snp_auth); + return CMD_SUCCESS; +} + +DEFUN (area_passwd_md5, + area_passwd_md5_cmd, + "(area-password|domain-password) md5 WORD", + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n" + "Authentication type\n" + "Level-wide password\n") +{ + u_char snp_auth = 0; + int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1; + + if (argc > 2) + { + snp_auth = SNP_AUTH_SEND; + if (strncmp(argv[2], "v", 1) == 0) + snp_auth |= SNP_AUTH_RECV; + } + + return area_passwd_set(vty, level, isis_area_passwd_hmac_md5_set, + argv[1], snp_auth); +} + +ALIAS (area_passwd_md5, + area_passwd_md5_snpauth_cmd, + "(area-password|domain-password) md5 WORD authenticate snp (send-only|validate)", + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n" + "Authentication type\n" + "Level-wide password\n" + "Authentication\n" + "SNP PDUs\n" + "Send but do not check PDUs on receiving\n" + "Send and check PDUs on receiving\n") + +DEFUN (area_passwd_clear, + area_passwd_clear_cmd, + "(area-password|domain-password) clear WORD", + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n" + "Authentication type\n" + "Area password\n") +{ + u_char snp_auth = 0; + int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1; + + if (argc > 2) + { + snp_auth = SNP_AUTH_SEND; + if (strncmp(argv[2], "v", 1) == 0) + snp_auth |= SNP_AUTH_RECV; + } + + return area_passwd_set(vty, level, isis_area_passwd_cleartext_set, + argv[1], snp_auth); +} + +ALIAS (area_passwd_clear, + area_passwd_clear_snpauth_cmd, + "(area-password|domain-password) clear WORD authenticate snp (send-only|validate)", + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n" + "Authentication type\n" + "Area password\n" + "Authentication\n" + "SNP PDUs\n" + "Send but do not check PDUs on receiving\n" + "Send and check PDUs on receiving\n") + +DEFUN (no_area_passwd, + no_area_passwd_cmd, + "no (area-password|domain-password)", + NO_STR + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n") +{ + int level = (argv[0][0] == 'd') ? IS_LEVEL_2 : IS_LEVEL_1; + struct isis_area *area = vty->index; + + if (!area) + { + vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + return isis_area_passwd_unset (area, level); +} + void isis_vty_init (void) { @@ -2305,4 +2416,10 @@ isis_vty_init (void) install_element (ISIS_NODE, &lsp_refresh_interval_l2_cmd); install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_cmd); install_element (ISIS_NODE, &no_lsp_refresh_interval_l2_arg_cmd); + + install_element (ISIS_NODE, &area_passwd_md5_cmd); + install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd); + install_element (ISIS_NODE, &area_passwd_clear_cmd); + install_element (ISIS_NODE, &area_passwd_clear_snpauth_cmd); + install_element (ISIS_NODE, &no_area_passwd_cmd); } diff --git a/isisd/isisd.c b/isisd/isisd.c index 4df38082ac..62c5e26538 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1618,280 +1618,62 @@ void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu) lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1); } -DEFUN (area_passwd_md5, - area_passwd_md5_cmd, - "area-password md5 WORD", - "Configure the authentication password for an area\n" - "Authentication type\n" - "Area password\n") +static int +isis_area_passwd_set(struct isis_area *area, int level, u_char passwd_type, + const char *passwd, u_char snp_auth) { - struct isis_area *area; + struct isis_passwd *dest; + struct isis_passwd modified; int len; - area = vty->index; + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); + dest = (level == IS_LEVEL_1) ? &area->area_passwd : &area->domain_passwd; + memset(&modified, 0, sizeof(modified)); - if (!area) + if (passwd_type != ISIS_PASSWD_TYPE_UNUSED) { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; + if (!passwd) + return -1; + + len = strlen(passwd); + if (len > 254) + return -1; + + modified.len = len; + strncpy((char*)modified.passwd, passwd, 255); + modified.type = passwd_type; + modified.snp_auth = snp_auth; } - len = strlen (argv[0]); - if (len > 254) + if (memcmp(&modified, dest, sizeof(modified))) { - vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; + memcpy(dest, &modified, sizeof(modified)); + lsp_regenerate_schedule(area, IS_LEVEL_1|IS_LEVEL_2, 1); } - area->area_passwd.len = (u_char) len; - area->area_passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5; - strncpy ((char *)area->area_passwd.passwd, argv[0], 255); - - if (argc > 1) - { - SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND); - if (strncmp(argv[1], "v", 1) == 0) - SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - else - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - } - else - { - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND); - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - } - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; + return 0; } -ALIAS (area_passwd_md5, - area_passwd_md5_snpauth_cmd, - "area-password md5 WORD authenticate snp (send-only|validate)", - "Configure the authentication password for an area\n" - "Authentication type\n" - "Area password\n" - "Authentication\n" - "SNP PDUs\n" - "Send but do not check PDUs on receiving\n" - "Send and check PDUs on receiving\n") - -DEFUN (area_passwd_clear, - area_passwd_clear_cmd, - "area-password clear WORD", - "Configure the authentication password for an area\n" - "Authentication type\n" - "Area password\n") +int +isis_area_passwd_unset (struct isis_area *area, int level) { - struct isis_area *area; - int len; - - area = vty->index; - - if (!area) - { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - len = strlen (argv[0]); - if (len > 254) - { - vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - area->area_passwd.len = (u_char) len; - area->area_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT; - strncpy ((char *)area->area_passwd.passwd, argv[0], 255); - - if (argc > 1) - { - SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND); - if (strncmp(argv[1], "v", 1) == 0) - SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - else - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - } - else - { - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND); - UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV); - } - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; + return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_UNUSED, NULL, 0); } -ALIAS (area_passwd_clear, - area_passwd_clear_snpauth_cmd, - "area-password clear WORD authenticate snp (send-only|validate)", - "Configure the authentication password for an area\n" - "Authentication type\n" - "Area password\n" - "Authentication\n" - "SNP PDUs\n" - "Send but do not check PDUs on receiving\n" - "Send and check PDUs on receiving\n") - -DEFUN (no_area_passwd, - no_area_passwd_cmd, - "no area-password", - NO_STR - "Configure the authentication password for an area\n") +int +isis_area_passwd_cleartext_set (struct isis_area *area, int level, + const char *passwd, u_char snp_auth) { - struct isis_area *area; - - area = vty->index; - - if (!area) - { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - memset (&area->area_passwd, 0, sizeof (struct isis_passwd)); - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; + return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_CLEARTXT, + passwd, snp_auth); } -DEFUN (domain_passwd_md5, - domain_passwd_md5_cmd, - "domain-password md5 WORD", - "Set the authentication password for a routing domain\n" - "Authentication type\n" - "Routing domain password\n") +int +isis_area_passwd_hmac_md5_set (struct isis_area *area, int level, + const char *passwd, u_char snp_auth) { - struct isis_area *area; - int len; - - area = vty->index; - - if (!area) - { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - len = strlen (argv[0]); - if (len > 254) - { - vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - area->domain_passwd.len = (u_char) len; - area->domain_passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5; - strncpy ((char *)area->domain_passwd.passwd, argv[0], 255); - - if (argc > 1) - { - SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND); - if (strncmp(argv[1], "v", 1) == 0) - SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - else - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - } - else - { - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND); - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - } - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -ALIAS (domain_passwd_md5, - domain_passwd_md5_snpauth_cmd, - "domain-password md5 WORD authenticate snp (send-only|validate)", - "Set the authentication password for a routing domain\n" - "Authentication type\n" - "Routing domain password\n" - "Authentication\n" - "SNP PDUs\n" - "Send but do not check PDUs on receiving\n" - "Send and check PDUs on receiving\n") - -DEFUN (domain_passwd_clear, - domain_passwd_clear_cmd, - "domain-password clear WORD", - "Set the authentication password for a routing domain\n" - "Authentication type\n" - "Routing domain password\n") -{ - struct isis_area *area; - int len; - - area = vty->index; - - if (!area) - { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - len = strlen (argv[0]); - if (len > 254) - { - vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; - } - - area->domain_passwd.len = (u_char) len; - area->domain_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT; - strncpy ((char *)area->domain_passwd.passwd, argv[0], 255); - - if (argc > 1) - { - SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND); - if (strncmp(argv[1], "v", 1) == 0) - SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - else - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - } - else - { - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND); - UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV); - } - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; -} - -ALIAS (domain_passwd_clear, - domain_passwd_clear_snpauth_cmd, - "domain-password clear WORD authenticate snp (send-only|validate)", - "Set the authentication password for a routing domain\n" - "Authentication type\n" - "Routing domain password\n" - "Authentication\n" - "SNP PDUs\n" - "Send but do not check PDUs on receiving\n" - "Send and check PDUs on receiving\n") - -DEFUN (no_domain_passwd, - no_domain_passwd_cmd, - "no domain-password", - NO_STR - "Set the authentication password for a routing domain\n") -{ - struct isis_area *area; - - area = vty->index; - - if (!area) - { - vty_out (vty, "Can't find IS-IS instance%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; - } - - memset (&area->domain_passwd, 0, sizeof (struct isis_passwd)); - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return CMD_SUCCESS; + return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_HMAC_MD5, + passwd, snp_auth); } static void @@ -2624,18 +2406,6 @@ isis_init () install_element (ISIS_NODE, &net_cmd); install_element (ISIS_NODE, &no_net_cmd); - install_element (ISIS_NODE, &area_passwd_md5_cmd); - install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd); - install_element (ISIS_NODE, &area_passwd_clear_cmd); - install_element (ISIS_NODE, &area_passwd_clear_snpauth_cmd); - install_element (ISIS_NODE, &no_area_passwd_cmd); - - install_element (ISIS_NODE, &domain_passwd_md5_cmd); - install_element (ISIS_NODE, &domain_passwd_md5_snpauth_cmd); - install_element (ISIS_NODE, &domain_passwd_clear_cmd); - install_element (ISIS_NODE, &domain_passwd_clear_snpauth_cmd); - install_element (ISIS_NODE, &no_domain_passwd_cmd); - install_element (ISIS_NODE, &log_adj_changes_cmd); install_element (ISIS_NODE, &no_log_adj_changes_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 5f996970f5..69a0100d50 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -154,7 +154,12 @@ void isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, uint16_t max_lsp_lifetime); void isis_area_lsp_refresh_set(struct isis_area *area, int level, uint16_t lsp_refresh); - +/* IS_LEVEL_1 sets area_passwd, IS_LEVEL_2 domain_passwd */ +int isis_area_passwd_unset (struct isis_area *area, int level); +int isis_area_passwd_cleartext_set (struct isis_area *area, int level, + const char *passwd, u_char snp_auth); +int isis_area_passwd_hmac_md5_set (struct isis_area *area, int level, + const char *passwd, u_char snp_auth); void isis_vty_init (void); /* Master of threads. */ From 47a928fb85cbd2656c6f48824173301f9252e478 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 28 Jul 2016 17:23:32 +0200 Subject: [PATCH 089/226] isisd: drop unused per-type metric values Expense, Error and Delay metrics never quite made it into the real world. Either way isisd does nothing useful with them, so let's drop them from the code. If someone wants to implement them, this patch can still be reverted. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 11 ++++------- isisd/isis_circuit.h | 2 +- isisd/isis_lsp.c | 21 +++++++++++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index cac1065d44..d8ca694d59 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -92,10 +92,7 @@ isis_circuit_new () circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL; circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL; circuit->priority[i] = DEFAULT_PRIORITY; - circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRIC; - circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED; - circuit->metrics[i].metric_error = METRICS_UNSUPPORTED; - circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED; + circuit->metric[i] = DEFAULT_CIRCUIT_METRIC; circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC; } @@ -899,7 +896,7 @@ isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, vty_out (vty, " Metric: %d", circuit->te_metric[0]); else vty_out (vty, " Metric: %d", - circuit->metrics[0].metric_default); + circuit->metric[0]); if (!circuit->is_passive) { vty_out (vty, ", Active neighbors: %u%s", @@ -932,7 +929,7 @@ isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, vty_out (vty, " Metric: %d", circuit->te_metric[1]); else vty_out (vty, " Metric: %d", - circuit->metrics[1].metric_default); + circuit->metric[1]); if (!circuit->is_passive) { vty_out (vty, ", Active neighbors: %u%s", @@ -1303,7 +1300,7 @@ isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) return -1; circuit->te_metric[level - 1] = metric; - circuit->metrics[level - 1].metric_default = metric; + circuit->metric[level - 1] = metric; if (circuit->area) lsp_regenerate_schedule (circuit->area, level, 0); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 45bac09374..9d6e426d41 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -117,7 +117,7 @@ struct isis_circuit u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ - struct metric metrics[2]; /* l1XxxMetric */ + u_int8_t metric[2]; u_int32_t te_metric[2]; int ip_router; /* Route IP ? */ int is_passive; /* Is Passive ? */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 7309248611..81f1958e63 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -1481,7 +1481,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) { ipreach = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability)); - ipreach->metrics = circuit->metrics[level - 1]; + ipreach->metrics.metric_default = circuit->metric[level - 1]; + ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; + ipreach->metrics.metric_error = METRICS_UNSUPPORTED; + ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; masklen2ip (ipv4->prefixlen, &ipreach->mask); ipreach->prefix.s_addr = ((ipreach->mask.s_addr) & (ipv4->prefix.s_addr)); @@ -1506,7 +1509,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) ((ipv4->prefixlen + 7)/8) - 1); if (area->oldmetric) - te_ipreach->te_metric = htonl (circuit->metrics[level - 1].metric_default); + te_ipreach->te_metric = htonl (circuit->metric[level - 1]); else te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]); @@ -1541,7 +1544,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) if (area->oldmetric) ip6reach->metric = - htonl (circuit->metrics[level - 1].metric_default); + htonl (circuit->metric[level - 1]); else ip6reach->metric = htonl (circuit->te_metric[level - 1]); @@ -1580,7 +1583,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) else memcpy (is_neigh->neigh_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); - is_neigh->metrics = circuit->metrics[level - 1]; + is_neigh->metrics.metric_default = circuit->metric[level - 1]; + is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED; + is_neigh->metrics.metric_error = METRICS_UNSUPPORTED; + is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED; if (!memcmp (is_neigh->neigh_id, zero_id, ISIS_SYS_ID_LEN + 1)) { @@ -1612,7 +1618,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) memcpy (te_is_neigh->neigh_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); if (area->oldmetric) - metric = circuit->metrics[level - 1].metric_default; + metric = circuit->metric[level - 1]; else metric = circuit->te_metric[level - 1]; SET_TE_METRIC(te_is_neigh, metric); @@ -1651,7 +1657,10 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) } is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh)); memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); - is_neigh->metrics = circuit->metrics[level - 1]; + is_neigh->metrics.metric_default = circuit->metric[level - 1]; + is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED; + is_neigh->metrics.metric_error = METRICS_UNSUPPORTED; + is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED; listnode_add (tlv_data.is_neighs, is_neigh); lsp_debug("ISIS (%s): Adding old-style is reach for %s", area->area_tag, sysid_print(is_neigh->neigh_id)); From daa2bc7068397dc74db06dac6b3730fa5ee1ef7b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Jul 2016 14:02:52 -0400 Subject: [PATCH 090/226] lib: 'show commandtree' is not a CLI command The 'show commandtree' command was added to the CONFIG_NODE. We have a basic assumption that CONFIG_NODE commands actually change state. 'show commandtree' doesn't meet this requirement. Signed-off-by: Donald Sharp --- lib/command.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/command.c b/lib/command.c index 4896c8a958..2e80eea9e3 100644 --- a/lib/command.c +++ b/lib/command.c @@ -4159,7 +4159,6 @@ cmd_init (int terminal) install_element (RESTRICTED_NODE, &config_enable_cmd); install_element (RESTRICTED_NODE, &config_terminal_length_cmd); install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd); - install_element (RESTRICTED_NODE, &show_commandtree_cmd); install_element (RESTRICTED_NODE, &echo_cmd); } @@ -4237,7 +4236,6 @@ cmd_init (int terminal) vrf_install_commands (); } - install_element (CONFIG_NODE, &show_commandtree_cmd); srandom(time(NULL)); } From 9994130f1d052b851bfffdd44d85e0a1c461a5cb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Jul 2016 14:28:22 -0400 Subject: [PATCH 091/226] vtysh: Do not run extract.pl over protocols that are not configured Dynamically figure out the list of .c files that we need to scan based upon whether or not the daemon is --enabled via configure. Ticket: CM-12081 Signed-off-by: Donald Sharp Reviewed-by: Quentin Young --- vtysh/Makefile.am | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am index 2180a78629..d4a74487ec 100644 --- a/vtysh/Makefile.am +++ b/vtysh/Makefile.am @@ -20,10 +20,37 @@ dist_examples_DATA = vtysh.conf.sample EXTRA_DIST = extract.pl -vtysh_cmd_FILES = $(top_srcdir)/bgpd/*.c $(top_srcdir)/isisd/*.c \ - $(top_srcdir)/ospfd/*.c $(top_srcdir)/ospf6d/*.c \ - $(top_srcdir)/ripd/*.c $(top_srcdir)/ripngd/*.c \ - $(top_srcdir)/pimd/pim_cmd.c \ +vtysh_scan = + +if PIMD +vtysh_scan += $(top_srcdir)/pimd/pim_cmd.c +endif + +if BGPD +vtysh_scan += $(top_srcdir)/bgpd/*.c +endif + +if ISISD +vtysh_scan += $(top_srcdir)/isisd/*.c +endif + +if OSPFD +vtysh_scan += $(top_srcdir)/ospfd/*.c +endif + +if OSPF6D +vtysh_scan += $(top_srcdir)/ospf6d/*.c +endif + +if RIPD +vtysh_scan += $(top_srcdir)/ripd/*.c +endif + +if RIPNGD +vtysh_scan += $(top_srcdir)/ripngd/*.c +endif + +vtysh_cmd_FILES = $(vtysh_scan) \ $(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \ $(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \ $(top_srcdir)/lib/distribute.c $(top_srcdir)/lib/if_rmap.c \ From 7ef817d9519e84e8a655076a8f5ae612b4a285ea Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 1 Aug 2016 12:15:28 +0000 Subject: [PATCH 092/226] BGP displays "keepalive" instead of "keepalives" for debugs Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12101 --- bgpd/bgp_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index a3d420f691..5b6ee0e070 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -1663,7 +1663,7 @@ bgp_config_write_debug (struct vty *vty) if (CONF_BGP_DEBUG (keepalive, KEEPALIVE)) { - write += bgp_debug_list_conf_print (vty, "debug bgp keepalive", + write += bgp_debug_list_conf_print (vty, "debug bgp keepalives", bgp_debug_keepalive_peers); } From 10b8ab26918c88ee351dec187e517921d6f0de24 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 4 Jun 2016 19:55:22 -0400 Subject: [PATCH 093/226] configure: Auto pick-up the correct json env Fix the code to allow Quagga to automatically compile with the correct json library. Signed-off-by: Donald Sharp Conflicts: configure.ac --- configure.ac | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 5c9b2e552a..792cacd0c3 100755 --- a/configure.ac +++ b/configure.ac @@ -326,13 +326,10 @@ AC_ARG_ENABLE(rr-semantics, AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c") if test $ac_cv_lib_json_c_json_object_get = no; then - AC_MSG_ERROR([lib json is needed to compile]) -fi - -AC_CHECK_HEADERS(json-c/json.h) -AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c") -if test $ac_cv_lib_json_c_json_object_get = no; then - AC_MSG_ERROR([lib json is needed to compile]) + AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson") + if test $ac_cv_lib_json_json_object_get = no; then + AC_MSG_ERROR([lib json is needed to compile]) + fi fi if test x"${enable_gcc_rdynamic}" != x"no" ; then From ca492402abc015500172f405e5cbd968da78cca1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 1 Aug 2016 13:38:05 -0400 Subject: [PATCH 094/226] bgpd: Add the no form of some dump bgp commands Ticket: CM-9432 Signed-off-by: Donald Sharp Reviewed-by: --- bgpd/bgp_dump.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index ea292f5931..59bb2f8a13 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -771,15 +771,41 @@ DEFUN (dump_bgp_all, DEFUN (no_dump_bgp_all, no_dump_bgp_all_cmd, - "no dump bgp (all|updates|routes-mrt) [PATH] [INTERVAL]", + "no dump bgp (all|all-et|updates|updates-et|routes-mrt) [PATH] [INTERVAL]", NO_STR "Stop dump packet\n" "Stop BGP packet dump\n" - "Stop dump process all/all-et\n" - "Stop dump process updates/updates-et\n" + "Stop dump process all\n" + "Stop dump process all-et\n" + "Stop dump process updates\n" + "Stop dump process updates-et\n" "Stop dump process route-mrt\n") { - return bgp_dump_unset (vty, &bgp_dump_all); + int bgp_dump_type = 0; + const struct bgp_dump_type_map *map = NULL; + struct bgp_dump *bgp_dump_struct = NULL; + + for (map = bgp_dump_type_map; map->str; map++) + if (strcmp(argv[0], map->str) == 0) + bgp_dump_type = map->type; + + switch (bgp_dump_type) + { + case BGP_DUMP_ALL: + case BGP_DUMP_ALL_ET: + bgp_dump_struct = &bgp_dump_all; + break; + case BGP_DUMP_UPDATES: + case BGP_DUMP_UPDATES_ET: + bgp_dump_struct = &bgp_dump_updates; + break; + case BGP_DUMP_ROUTES: + default: + bgp_dump_struct = &bgp_dump_routes; + break; + } + + return bgp_dump_unset (vty, bgp_dump_struct); } /* BGP node structure. */ From 161995ea541d809118af16a4eb20d03572d32379 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 3 Aug 2016 06:49:09 -0700 Subject: [PATCH 095/226] bgpd: Add command to prefer global ipv6 address There are cases where customers desire the ability to override the default behavior of installing ipv6 prefixes with a link-local next-hop if both a link-local and global ipv6 next-op is present in the bgp table. This fix provides this ability and will allow the global to be used as the next-hop. This also retains the ability to manually set the ipv6 next-hop global value as before, and if so, this manual entry will be used for the next-hop. Ticket: CM-11480 Signed-off-by: Don Slice Reviewed By: CCR-4983 Testing Done: Manual testing results attached to the ticket. bgp-min and bgp-smoke will be completed before committing. --- bgpd/bgp_attr.h | 3 ++ bgpd/bgp_route.c | 30 +++++++++------- bgpd/bgp_routemap.c | 84 ++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_zebra.c | 16 ++++++--- 4 files changed, 114 insertions(+), 19 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 1117f6269d..a279674af2 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -99,6 +99,9 @@ struct attr_extra /* MP Nexthop length */ u_char mp_nexthop_len; + /* MP Nexthop preference */ + u_char mp_nexthop_prefer_global; + /* route tag */ u_short tag; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fc6db0863d..f47e2f6074 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5873,7 +5873,7 @@ route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); } } -#ifdef HAVE_IPV6 + /* IPv6 Next Hop */ else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { @@ -5901,8 +5901,9 @@ route_vty_out (struct vty *vty, struct prefix *p, json_object_string_add(json_nexthop_ll, "afi", "ipv6"); json_object_string_add(json_nexthop_ll, "scope", "link-local"); - if (IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global, - &attr->extra->mp_nexthop_local) != 0) + if ((IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global, + &attr->extra->mp_nexthop_local) != 0) && + !attr->extra->mp_nexthop_prefer_global) json_object_boolean_true_add(json_nexthop_ll, "used"); else json_object_boolean_true_add(json_nexthop_global, "used"); @@ -5912,7 +5913,10 @@ route_vty_out (struct vty *vty, struct prefix *p, } else { - if ((attr->extra->mp_nexthop_len == 32) || (binfo->peer->conf_if)) + /* Display LL if LL/Global both in table unless prefer-global is set */ + if (((attr->extra->mp_nexthop_len == 32) && + !attr->extra->mp_nexthop_prefer_global) || + (binfo->peer->conf_if)) { if (binfo->peer->conf_if) { @@ -5954,7 +5958,6 @@ route_vty_out (struct vty *vty, struct prefix *p, } } } -#endif /* HAVE_IPV6 */ /* MED/Metric */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) @@ -6635,7 +6638,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (json_paths) json_object_string_add(json_nexthop_global, "afi", "ipv4"); } -#ifdef HAVE_IPV6 else { assert (attr->extra); @@ -6654,8 +6656,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, buf, INET6_ADDRSTRLEN)); } } -#endif /* HAVE_IPV6 */ - /* Display the IGP cost or 'inaccessible' */ if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) @@ -6761,7 +6761,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (!json_paths) vty_out (vty, "%s", VTY_NEWLINE); -#ifdef HAVE_IPV6 /* display the link-local nexthop */ if (attr->extra && attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { @@ -6775,13 +6774,19 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, json_object_string_add(json_nexthop_ll, "scope", "link-local"); json_object_boolean_true_add(json_nexthop_ll, "accessible"); - json_object_boolean_true_add(json_nexthop_ll, "used"); + + if (!attr->extra->mp_nexthop_prefer_global) + json_object_boolean_true_add(json_nexthop_ll, "used"); + else + json_object_boolean_true_add(json_nexthop_global, "used"); } else { - vty_out (vty, " (%s) (used)%s", - inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, + vty_out (vty, " (%s) %s%s", + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, buf, INET6_ADDRSTRLEN), + attr->extra->mp_nexthop_prefer_global ? + "(prefer-global)" : "(used)", VTY_NEWLINE); } } @@ -6791,7 +6796,6 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (json_paths) json_object_boolean_true_add(json_nexthop_global, "used"); } -#endif /* HAVE_IPV6 */ /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */ if (json_paths) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 3018d074fc..2a4d416633 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -103,6 +103,7 @@ o Cisco route-map o Local extensions set ipv6 next-hop global: Done + set ipv6 next-hop prefer-global: Done set ipv6 next-hop local : Done set as-path exclude : Done @@ -2192,6 +2193,61 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = route_set_ipv6_nexthop_global_free }; +/* Set next-hop preference value. */ +static route_map_result_t +route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct bgp_info *bgp_info; + struct peer *peer; + + if (type == RMAP_BGP) + { + /* Fetch routemap's rule information. */ + bgp_info = object; + peer = bgp_info->peer; + + if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) || + CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family (peer->su_remote) == AF_INET6) + { + /* Set next hop preference to global */ + bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); + } + } + return RMAP_OKAY; +} + +static void * +route_set_ipv6_nexthop_prefer_global_compile (const char *arg) +{ + int *rins = NULL; + + rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int)); + *rins = 1; + + return rins; +} + +/* Free route map's compiled `ip next-hop' value. */ +static void +route_set_ipv6_nexthop_prefer_global_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for ip nexthop set preferred. */ +struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = +{ + "ipv6 next-hop prefer-global", + route_set_ipv6_nexthop_prefer_global, + route_set_ipv6_nexthop_prefer_global_compile, + route_set_ipv6_nexthop_prefer_global_free +}; + /* `set ipv6 nexthop local IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ @@ -4366,11 +4422,34 @@ DEFUN (no_set_ipv6_nexthop_peer, SET_STR IPV6_STR "IPv6 next-hop address\n" - ) + "Use peer address (for BGP only)\n") { return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL); } +DEFUN (set_ipv6_nexthop_prefer_global, + set_ipv6_nexthop_prefer_global_cmd, + "set ipv6 next-hop prefer-global", + SET_STR + IPV6_STR + "IPv6 next-hop address\n" + "Prefer global over link-local if both exist\n") +{ + return bgp_route_set_add (vty, vty->index, "ipv6 next-hop prefer-global", NULL);; +} + +DEFUN (no_set_ipv6_nexthop_prefer_global, + no_set_ipv6_nexthop_prefer_global_cmd, + "no set ipv6 next-hop prefer-global", + NO_STR + SET_STR + IPV6_STR + "IPv6 next-hop address\n" + "Prefer global over link-local if both exist\n") +{ + return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop prefer-global", NULL); +} + DEFUN (set_ipv6_nexthop_global, set_ipv6_nexthop_global_cmd, "set ipv6 next-hop global X:X::X:X", @@ -4704,6 +4783,7 @@ bgp_route_map_init (void) route_map_install_match (&route_match_ipv6_next_hop_cmd); route_map_install_match (&route_match_ipv6_address_prefix_list_cmd); route_map_install_set (&route_set_ipv6_nexthop_global_cmd); + route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd); route_map_install_set (&route_set_ipv6_nexthop_local_cmd); route_map_install_set (&route_set_ipv6_nexthop_peer_cmd); @@ -4716,6 +4796,8 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd); install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd); install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd); + install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd); + install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd); install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd); install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 68f6cede8b..3df63d5ba7 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1136,12 +1136,18 @@ bgp_info_to_ipv6_nexthop (struct bgp_info *info) /* If both global and link-local address present. */ if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { - /* Workaround for Cisco's nexthop bug. */ - if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) - && info->peer->su_remote->sa.sa_family == AF_INET6) - nexthop = &info->peer->su_remote->sin6.sin6_addr; + /* Check if route-map is set to prefer global over link-local */ + if (info->attr->extra->mp_nexthop_prefer_global) + nexthop = &info->attr->extra->mp_nexthop_global; else - nexthop = &info->attr->extra->mp_nexthop_local; + { + /* Workaround for Cisco's nexthop bug. */ + if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) + && info->peer->su_remote->sa.sa_family == AF_INET6) + nexthop = &info->peer->su_remote->sin6.sin6_addr; + else + nexthop = &info->attr->extra->mp_nexthop_local; + } } return nexthop; From c152e0c131786a2ddc1bfdc5d5bcbe503adc4617 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 10:26:31 -0400 Subject: [PATCH 096/226] lib: Arm build breakage with MAX_INT macro issues The VTY_GET_INTEGER_RANGE macro is failing on arm with a warning->error issue where we are passing in a unsigned MAXINT to this macro and it is complaining that the comparison of (TMPL) > MAXINT is always going to be false because of data structure size. I've changed the tmp variable to a unsigned long long which alleviates this issue. Ticket: CM-12187 Signed-off-by: Donald Sharp Reviewed-by: Don Slice --- lib/vty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vty.h b/lib/vty.h index 81251e07bb..599882a382 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -220,7 +220,7 @@ do { \ #define VTY_GET_INTEGER_RANGE(NAME,V,STR,MIN,MAX) \ do { \ - unsigned long tmpl; \ + unsigned long long tmpl; \ VTY_GET_INTEGER_RANGE_HEART(NAME,tmpl,STR,MIN,MAX); \ (V) = tmpl; \ } while (0) From 473b996bfccf30c55e545af8eb5a52995b86e155 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 04:54:45 -0400 Subject: [PATCH 097/226] quagga: Set version strings appropriately Set the version strings to be correct for the upcoming 3.1 release of Quagga. Signed-off-by: Donald Sharp --- configure.ac | 2 +- debian/changelog | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 5c9b2e552a..8fcafbb0f0 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(Quagga, 0.99.24+cl3u2, [https://bugzilla.quagga.net]) +AC_INIT(Quagga, 0.99.24+cl3u3, [https://bugzilla.quagga.net]) CONFIG_ARGS="$*" AC_SUBST(CONFIG_ARGS) AC_CONFIG_SRCDIR(lib/zebra.h) diff --git a/debian/changelog b/debian/changelog index b83daec10a..1907c93d6f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +quagga (0.99.24+cl3u3) Release; urgency=medium + + * New Enabled: Merge up-to 0.99.24 code from upstream + * New Enabled: Additional CLI simplification + * New Enabled: Various Bug Fixes + quagga (0.99.23.1-1+cl3u2) Release; urgency=medium * New Enabled: VRF - See Documentation for how to use From 9b34069d02d591a1b05d3a1b93b88796bc10099e Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 3 Aug 2016 19:30:06 +0000 Subject: [PATCH 098/226] lib: Add newline terminators to pim docstring Signed-off-by: Quentin Young --- pimd/pim_cmd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 13cc305274..54ed11da81 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2462,9 +2462,9 @@ DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D", IP_STR - "pim multicast routing" - "Rendevous Point" - "ip address of RP") + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n") { int result; @@ -2487,9 +2487,9 @@ DEFUN (no_ip_pim_rp, "no ip pim rp {A.B.C.D}", NO_STR IP_STR - "pim multicast routing" - "Rendevous Point" - "ip address of RP") + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n") { qpim_rp.rpf_addr.s_addr = INADDR_NONE; From a79fb1aa761653d9a70b27e54dac8ce39cb037a5 Mon Sep 17 00:00:00 2001 From: John Berezovik Date: Thu, 4 Aug 2016 09:08:37 -0700 Subject: [PATCH 099/226] Fix changelog to add maintainer info, build fails without it --- debian/changelog | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 1907c93d6f..3114db3fd1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,12 @@ -quagga (0.99.24+cl3u3) Release; urgency=medium +quagga (0.99.24+cl3u3) RELEASED; urgency=medium * New Enabled: Merge up-to 0.99.24 code from upstream * New Enabled: Additional CLI simplification * New Enabled: Various Bug Fixes -quagga (0.99.23.1-1+cl3u2) Release; urgency=medium + -- dev-support Thu, 04 Aug 2016 08:43:36 -0700 + +quagga (0.99.23.1-1+cl3u2) RELEASED; urgency=medium * New Enabled: VRF - See Documentation for how to use * New Enabled: Improved interface statistics From 7fe9687b0831071febc4b08cdbb819d1c9334c49 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Fri, 5 Aug 2016 21:47:42 +0000 Subject: [PATCH 100/226] 'debug ospf' print a garbage character Signed-off-by: Daniel Walton Reviewed-by: sidkhot@cumulusnetworks.com Ticket: CM-12271 --- ospfd/ospf_dump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 861f9d3516..65d6e09b6d 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -2133,6 +2133,7 @@ config_write_debug (struct vty *vty) struct ospf *ospf; char str[16]; + memset (str, 0, 16); if ((ospf = ospf_lookup()) == NULL) return CMD_SUCCESS; From eb117f29e1c18cd4ddf32d7b01fa10a7bc3d0fab Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Fri, 5 Aug 2016 16:49:39 -0700 Subject: [PATCH 101/226] bgpd: Fix for CM-11982 bgp failed to redistribute connected in vrf table Made fix to update the redistribute vrf bitmap when vrf goes down and comes up. Ticket: CM-11982 Reviewed By: CCR-5032 Testing Done: bgp-min passed, manual --- bgpd/bgp_main.c | 11 +++++++++++ bgpd/bgp_zebra.c | 18 ++++++++++++++++++ bgpd/bgpd.h | 1 + 3 files changed, 30 insertions(+) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 1f2f7f86ce..a5f066bff0 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -317,6 +317,7 @@ bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) { struct vrf *vrf; struct bgp *bgp; + vrf_id_t old_vrf_id; vrf = vrf_lookup (vrf_id); if (!vrf) // unexpected @@ -328,8 +329,13 @@ bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) bgp = bgp_lookup_by_name(name); if (bgp) { + old_vrf_id = bgp->vrf_id; /* We have instance configured, link to VRF and make it "up". */ bgp_vrf_link (bgp, vrf); + + /* Update any redistribute vrf bitmaps if the vrf_id changed */ + if (old_vrf_id != bgp->vrf_id) + bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); bgp_instance_up (bgp); } @@ -341,6 +347,7 @@ bgp_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) { struct vrf *vrf; struct bgp *bgp; + vrf_id_t old_vrf_id; if (vrf_id == VRF_DEFAULT) return 0; @@ -355,8 +362,12 @@ bgp_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) bgp = bgp_lookup_by_name(name); if (bgp) { + old_vrf_id = bgp->vrf_id; /* We have instance configured, unlink from VRF and make it "down". */ bgp_vrf_unlink (bgp, vrf); + /* Update any redistribute vrf bitmaps if the vrf_id changed */ + if (old_vrf_id != bgp->vrf_id) + bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); bgp_instance_down (bgp); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 3df63d5ba7..b4bac840e3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1965,6 +1965,24 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type, u_short instance) return CMD_SUCCESS; } +/* Update redistribute vrf bitmap during triggers like + restart networking or delete/add VRFs */ +void +bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id) +{ + int i; + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id)) + { + vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id); + vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id); + } + return; +} + void bgp_zclient_reset (void) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1603ed2614..991afdf7cc 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1504,4 +1504,5 @@ bgp_vrf_unlink (struct bgp *bgp, struct vrf *vrf) bgp->vrf_id = VRF_UNKNOWN; } +extern void bgp_update_redist_vrf_bitmaps (struct bgp*, vrf_id_t); #endif /* _QUAGGA_BGPD_H */ From 23b1f400488df822664e62c41fa24dde9c17913d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:24 -0300 Subject: [PATCH 102/226] zebra: fix build on OpenBSD >= 5.9 RTF_XRESOLVE was removed from the OpenBSD tree recently. Signed-off-by: Renato Westphal --- zebra/kernel_socket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index b47ee787e8..f9df983abf 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -240,7 +240,9 @@ static const struct message rtm_flag_str[] = #ifdef RTF_CLONING {RTF_CLONING, "CLONING"}, #endif /* RTF_CLONING */ +#ifdef RTF_XRESOLVE {RTF_XRESOLVE, "XRESOLVE"}, +#endif /* RTF_XRESOLVE */ #ifdef RTF_LLINFO {RTF_LLINFO, "LLINFO"}, #endif /* RTF_LLINFO */ From 288b91e0bdf99bd835ce82905415011f77ce5a62 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:25 -0300 Subject: [PATCH 103/226] ospf6d: fix sendmsg on OpenBSD When sending ancillary data on OpenBSD, we need to tell the compiler that the ancillary data buffer should be aligned on the stack to the minimum alignment of the first ancillary data object that will be sent. Additionally, HAVE_SIN6_SCOPE_ID is not defined anywhere, check for HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID instead. Signed-off-by: Renato Westphal --- ospf6d/ospf6_network.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 7b1cf91932..5e254661f1 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -198,14 +198,18 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, int retval; struct msghdr smsghdr; struct cmsghdr *scmsgp; - u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; + union + { + struct cmsghdr hdr; + u_char buf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; + } cmsgbuf; struct in6_pktinfo *pktinfo; struct sockaddr_in6 dst_sin6; assert (dst); assert (*ifindex); - scmsgp = (struct cmsghdr *)cmsgbuf; + scmsgp = (struct cmsghdr *)&cmsgbuf; pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); memset (&dst_sin6, 0, sizeof (struct sockaddr_in6)); @@ -222,7 +226,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, dst_sin6.sin6_len = sizeof (struct sockaddr_in6); #endif /*SIN6_LEN*/ memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr)); -#ifdef HAVE_SIN6_SCOPE_ID +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID dst_sin6.sin6_scope_id = *ifindex; #endif @@ -238,8 +242,8 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, smsghdr.msg_iovlen = iov_count (message); smsghdr.msg_name = (caddr_t) &dst_sin6; smsghdr.msg_namelen = sizeof (struct sockaddr_in6); - smsghdr.msg_control = (caddr_t) cmsgbuf; - smsghdr.msg_controllen = scmsgp->cmsg_len; + smsghdr.msg_control = (caddr_t) &cmsgbuf.buf; + smsghdr.msg_controllen = sizeof(cmsgbuf.buf); retval = sendmsg (ospf6_sock, &smsghdr, 0); if (retval != iov_totallen (message)) From 4a3867d0d331ab64311f517bfb39bddfc933c9ee Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:26 -0300 Subject: [PATCH 104/226] lib: fix setting of IPv4 multicast sockopts on OpenBSD OpenBSD doesn't support the "ifindex hack" derived from RFC 1724 which allows an ifindex to be encoded in the imr_interface field (in_addr) of the ip_mreq structure. OpenBSD also doesn't support the RFC3678 Protocol-Independent socket API extensions, which allows an interface to be specified by its ifindex. With that said, in OpenBSD we still need to specify an interface by its IP address. This patch adds an exception in the multicast sockopt functions to handle this case. Signed-off-by: Renato Westphal --- lib/sockopt.c | 19 +++++++++++++------ lib/sockopt.h | 3 ++- ospfd/ospf_network.c | 10 +++++----- ripd/rip_interface.c | 10 ++++++++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/sockopt.c b/lib/sockopt.c index 257271bc0b..d8204936f9 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -219,6 +219,7 @@ setsockopt_ipv6_tclass(int sock, int tclass) int setsockopt_ipv4_multicast(int sock, int optname, + struct in_addr if_addr, unsigned int mcast_addr, unsigned int ifindex) { @@ -279,18 +280,20 @@ setsockopt_ipv4_multicast(int sock, #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ /* standard BSD API */ - struct in_addr m; struct ip_mreq mreq; int ret; assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); - m.s_addr = htonl(ifindex); memset (&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr.s_addr = mcast_addr; - mreq.imr_interface = m; - +#if !defined __OpenBSD__ + mreq.imr_interface.s_addr = htonl (ifindex); +#else + mreq.imr_interface.s_addr = if_addr.s_addr; +#endif + ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) { @@ -318,7 +321,7 @@ setsockopt_ipv4_multicast(int sock, * Set IP_MULTICAST_IF socket option in an OS-dependent manner. */ int -setsockopt_ipv4_multicast_if(int sock, +setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, unsigned int ifindex) { @@ -336,7 +339,11 @@ setsockopt_ipv4_multicast_if(int sock, #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) struct in_addr m; - m.s_addr = htonl(ifindex); +#if !defined __OpenBSD__ + m.s_addr = htonl (ifindex); +#else + m.s_addr = if_addr.s_addr; +#endif return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); #else diff --git a/lib/sockopt.h b/lib/sockopt.h index cb14efc7ba..a597314c3d 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -83,9 +83,10 @@ extern int setsockopt_ipv6_tclass (int, int); (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \ ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) -extern int setsockopt_ipv4_multicast_if(int sock, +extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, unsigned int ifindex); extern int setsockopt_ipv4_multicast(int sock, int optname, + struct in_addr if_addr, unsigned int mcast_addr, unsigned int ifindex); extern int setsockopt_ipv4_tos(int sock, int tos); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 2f167a50a5..9f516d7390 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -53,7 +53,7 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - htonl (OSPF_ALLSPFROUTERS), + p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -74,7 +74,7 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - htonl (OSPF_ALLSPFROUTERS), + p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -95,7 +95,7 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - htonl (OSPF_ALLDROUTERS), + p->u.prefix4, htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -116,7 +116,7 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int int ret; ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - htonl (OSPF_ALLDROUTERS), + p->u.prefix4, htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -151,7 +151,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex) zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", top->fd, safe_strerror (errno)); - ret = setsockopt_ipv4_multicast_if (top->fd, ifindex); + ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex); if (ret < 0) zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " "ifindex %u): %s", diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 6748e197da..4499966ad0 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -80,6 +80,7 @@ ipv4_multicast_join (int sock, ret = setsockopt_ipv4_multicast (sock, IP_ADD_MEMBERSHIP, + ifa, group.s_addr, ifindex); @@ -101,6 +102,7 @@ ipv4_multicast_leave (int sock, ret = setsockopt_ipv4_multicast (sock, IP_DROP_MEMBERSHIP, + ifa, group.s_addr, ifindex); @@ -136,9 +138,13 @@ rip_interface_new (void) void rip_interface_multicast_set (int sock, struct connected *connected) { + struct in_addr addr; + assert (connected != NULL); - - if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0) + + addr = CONNECTED_ID(connected)->u.prefix4; + + if (setsockopt_ipv4_multicast_if (sock, addr, connected->ifp->ifindex) < 0) { zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to " "ifindex %d for interface %s", From 76d7ac06244706cea102f96ae1554d21a36aa21a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:27 -0300 Subject: [PATCH 105/226] lib: update strlcpy to OpenBSD v1.13 Signed-off-by: Renato Westphal --- lib/str.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/str.c b/lib/str.c index d8f039a094..16f759c074 100644 --- a/lib/str.c +++ b/lib/str.c @@ -54,26 +54,34 @@ snprintf(char *str, size_t size, const char *format, ...) #endif #ifndef HAVE_STRLCPY -/** - * Like strncpy but does not 0 fill the buffer and always null - * terminates. - * - * @param bufsize is the size of the destination buffer. - * - * @return index of the terminating byte. - **/ +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ size_t -strlcpy(char *d, const char *s, size_t bufsize) +strlcpy(char *dst, const char *src, size_t dsize) { - size_t len = strlen(s); - size_t ret = len; - if (bufsize > 0) { - if (len >= bufsize) - len = bufsize-1; - memcpy(d, s, len); - d[len] = 0; + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } } - return ret; + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ } #endif From 60060acc54fd5cb22f00e8f903d04081211a430d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:28 -0300 Subject: [PATCH 106/226] bgpd: use utsname.domainname only when available Signed-off-by: Renato Westphal --- bgpd/bgp_open.c | 7 ++++++- configure.ac | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 947f5c09d4..8765488881 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1473,7 +1473,7 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc(s, len); stream_put(s, names.nodename, len); -#ifdef _GNU_SOURCE +#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME if ((names.domainname[0] != '\0') && (strcmp(names.domainname, "(none)") != 0)) { @@ -1497,8 +1497,13 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc_at(s, capp, len); if (bgp_debug_neighbor_events(peer)) +#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME zlog_debug("%s Sending hostname cap with hn = %s, dn = %s", peer->host, names.nodename, names.domainname); +#else + zlog_debug("%s Sending hostname cap with hn = %s", peer->host, + names.nodename); +#endif } /* Sending base graceful-restart capability irrespective of the config */ diff --git a/configure.ac b/configure.ac index 9cdf1903d3..6f07f10cd0 100755 --- a/configure.ac +++ b/configure.ac @@ -1098,6 +1098,11 @@ AC_SUBST(IPFORWARD) AC_CHECK_FUNCS(getaddrinfo, [have_getaddrinfo=yes], [have_getaddrinfo=no]) +dnl ---------------------------------------------------------------------------- +dnl figure out if domainname is available in the utsname struct (GNU extension). +dnl ---------------------------------------------------------------------------- +AC_CHECK_MEMBERS([struct utsname.domainname], [], [], [#include ]) + dnl ---------- dnl IPv6 check dnl ---------- From 2bb913f5e77157fa8424d7ff0b46b8743112f955 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:29 -0300 Subject: [PATCH 107/226] bgpd: fix wrong use of IN6_IS_ADDR_LINKLOCAL The IN6_IS_ADDR_LINKLOCAL macro expects to receive a pointer to an in6_addr structure. Signed-off-by: Renato Westphal --- bgpd/bgp_zebra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index b4bac840e3..874d80bd8e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -877,7 +877,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) if (cp->family == AF_INET6) if (prefix_match (cp, (struct prefix *)&p)) { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6.s6_addr32[0])) + if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { if (ifindex == ifp->ifindex) return ifp; From b3f2bf7cbe92b1ee6942f68038f17a3329c61f06 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:30 -0300 Subject: [PATCH 108/226] pimd: add a workaround for *BSD VIFF_USE_IFINDEX is not available on BSDs and other UNIX systems. In order to build pimd on these platforms, use 'vifc_lcl_addr' instead of 'vifc_lcl_ifindex' to specify the interfaces we want to enable forwarding of multicast traffic. In the case of unnumbered interfaces, print an error and return. Signed-off-by: Renato Westphal --- configure.ac | 45 ++++++++++++++++++++++++++++++++++++++++----- pimd/pim_iface.c | 24 ++++++++---------------- pimd/pim_mroute.c | 9 +++++++++ 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 6f07f10cd0..50918227e9 100755 --- a/configure.ac +++ b/configure.ac @@ -996,11 +996,46 @@ dnl figure out how to specify an interface in multicast sockets API dnl --------------------------------------------------------------- AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], QUAGGA_INCLUDES) -AC_CHECK_HEADERS([linux/mroute.h], [], [], -[ -#if HAVE_NETINET_IN_H -#include -#endif]) +AC_CHECK_HEADERS([linux/mroute.h], [], [],[ + #ifdef HAVE_SYS_SOCKET_H + # include + #endif + #ifdef HAVE_NETINET_IN_H + # include + #endif + #define _LINUX_IN_H /* For Linux <= 2.6.25 */ + #include +]) + +m4_define([QUAGGA_INCLUDES], +QUAGGA_INCLUDES +[#if HAVE_LINUX_MROUTE_H +# include +#endif +])dnl + +AC_CHECK_HEADERS([netinet/ip_mroute.h], [], [],[ + #ifdef HAVE_SYS_SOCKET_H + # include + #endif + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #ifdef HAVE_NETINET_IN_H + # include + #endif + #ifdef HAVE_NET_ROUTE_H + # include + #endif +]) + +m4_define([QUAGGA_INCLUDES], +QUAGGA_INCLUDES +[#if HAVE_NETINET_IP_MROUTE_H +# include +#endif +])dnl + AC_MSG_CHECKING([for BSD struct ip_mreq hack]) AC_TRY_COMPILE([#ifdef HAVE_SYS_PARAM_H #include diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 14c8c7262e..3c60275027 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -41,19 +41,6 @@ #include "pim_time.h" #include "pim_ssmpingd.h" -#ifndef VIFF_USE_IFINDEX -# ifdef linux -/* make it work compile-time - whether it works runtime depends on the user - * having 2.6.32 or newer */ -# define VIFF_USE_IFINDEX 0x8 -# else -# error no VIFF_USE_IFINDEX on this system, code needs porting -/* NB: without VIFF_USE_IFINDEX, the local IP address is used to identify - * interfaces, which means it's impossible to support multiple interfaces that - * have the same or no IP address (e.g. unnumbered) */ -# endif -#endif - struct interface *pim_regiface = NULL; static void pim_if_igmp_join_del_all(struct interface *ifp); @@ -645,7 +632,7 @@ int pim_if_add_vif(struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; struct in_addr ifaddr; - unsigned char flags; + unsigned char flags = 0; zassert(pim_ifp); @@ -681,8 +668,13 @@ int pim_if_add_vif(struct interface *ifp) return -3; } - flags = (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) ? - VIFF_REGISTER : VIFF_USE_IFINDEX; + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + flags = VIFF_REGISTER; +#ifdef VIFF_USE_IFINDEX + else + flags = VIFF_USE_IFINDEX; +#endif + if (pim_mroute_add_vif(ifp, ifaddr, flags)) { /* pim_mroute_add_vif reported error */ return -5; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index ab3742438d..56f49d62f5 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -501,7 +501,16 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned ch memset(&vc, 0, sizeof(vc)); vc.vifc_vifi = pim_ifp->mroute_vif_index; +#ifdef VIFF_USE_IFINDEX vc.vifc_lcl_ifindex = ifp->ifindex; +#else + if (ifaddr.s_addr == INADDR_ANY) { + zlog_warn("%s: unnumbered interfaces are not supported on this platform", + __PRETTY_FUNCTION__); + return -1; + } + memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); +#endif vc.vifc_flags = flags; vc.vifc_threshold = PIM_MROUTE_MIN_TTL; vc.vifc_rate_limit = 0; From 1bb6e9b7fafc20249570727b84fa4101643d9091 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:31 -0300 Subject: [PATCH 109/226] zebra: replace __u32 with standard uint32_t Signed-off-by: Renato Westphal --- zebra/kernel_null.c | 2 +- zebra/rt_netlink.c | 2 +- zebra/rt_netlink.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 5efc1e2a55..184f223971 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -60,7 +60,7 @@ int kernel_address_delete_ipv4 (struct interface *a, struct connected *b) return 0; } -int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) +int netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) { return 0; } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 481ff781e3..9185fbb4ca 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1974,7 +1974,7 @@ _netlink_route_debug( } int -netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) +netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) { struct { struct nlmsghdr n; diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 1d9280a295..5ef5cc37a9 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -42,7 +42,7 @@ extern const char * nl_rtproto_to_str (u_char rtproto); int -netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); +netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen); extern int interface_lookup_netlink (struct zebra_ns *zns); extern int netlink_route_read (struct zebra_ns *zns); From 6b8a5694d3f138f0d32026d56d24a129a21c5da8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:32 -0300 Subject: [PATCH 110/226] zebra: create an abstraction layer for netlink_neigh_update() We shouldn't have platform-agnostic code (e.g. zebra/interface.c) calling platform-specific functions (e.g. netlink_neigh_update). This commit introduces the kernel_neigh_update() function, which then has to be implemented by all supported platforms. Currently only Linux implements this function, which is only used by the RTADV code. Signed-off-by: Renato Westphal --- zebra/interface.c | 4 ++-- zebra/kernel_null.c | 2 +- zebra/rt.h | 1 + zebra/rt_netlink.c | 8 +++++++- zebra/rt_netlink.h | 3 --- zebra/rt_socket.c | 7 +++++++ 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index c3ce83dd4a..ca10387a84 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -39,6 +39,7 @@ #include "zebra_vrf.h" #include "zebra/interface.h" #include "zebra/rib.h" +#include "zebra/rt.h" #include "zebra/zserv.h" #include "zebra/redistribute.h" #include "zebra/debug.h" @@ -744,8 +745,7 @@ if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, inet_pton (AF_INET, buf, &ipv4_ll); ipv6_ll_address_to_mac(address, (u_char *)mac); - netlink_neigh_update (add ? RTM_NEWNEIGH : RTM_DELNEIGH, - ifp->ifindex, ipv4_ll.s_addr, mac, 6); + kernel_neigh_update (add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); } static void diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 184f223971..b90c6f57f9 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -60,7 +60,7 @@ int kernel_address_delete_ipv4 (struct interface *a, struct connected *b) return 0; } -int netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update (int a, int b, uint32_t c, char *d, int e) { return 0; } diff --git a/zebra/rt.h b/zebra/rt.h index 331df45c47..4515d56a38 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -33,6 +33,7 @@ extern int kernel_delete_ipv4 (struct prefix *, struct rib *); extern int kernel_add_route (struct prefix_ipv4 *, struct in_addr *, int, int); extern int kernel_address_add_ipv4 (struct interface *, struct connected *); extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); +extern int kernel_neigh_update (int, int, uint32_t, char *, int); #ifdef HAVE_IPV6 extern int kernel_add_ipv6 (struct prefix *, struct rib *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 9185fbb4ca..b2a54a83ac 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1973,7 +1973,7 @@ _netlink_route_debug( } } -int +static int netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) { struct { @@ -2392,6 +2392,12 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); } +int +kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +{ + return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr, + lla, llalen); +} extern struct thread_master *master; diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 5ef5cc37a9..80d035e839 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -41,9 +41,6 @@ nl_msg_type_to_str (uint16_t msg_type); extern const char * nl_rtproto_to_str (u_char rtproto); -int -netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen); - extern int interface_lookup_netlink (struct zebra_ns *zns); extern int netlink_route_read (struct zebra_ns *zns); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index abeb87a427..ffb0d088a7 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -428,3 +428,10 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) return route; } #endif /* HAVE_IPV6 */ + +int +kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +{ + /* TODO */ + return 0; +} From 8f500a1cf156c6033f2e0b1ef40db09f9d6f34a2 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 4 Aug 2016 10:07:33 -0300 Subject: [PATCH 111/226] *: fix trivial build errors on *BSD Signed-off-by: Renato Westphal --- bgpd/bgpd.c | 4 ++-- cumulus/start-stop-daemon.c | 7 ++++++- pimd/test_igmpv3_join.c | 2 ++ zebra/if_ioctl.c | 2 +- zebra/kernel_socket.c | 20 ++++++++++---------- zebra/zebra_ptm.c | 5 ++++- zebra/zebra_rib.c | 12 ++++++++---- 7 files changed, 33 insertions(+), 19 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1a5270874c..b3721a03ea 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1315,7 +1315,7 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) else if (s_addr % 4 == 2) peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su->sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return 1; } @@ -1328,7 +1328,7 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) else peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su->sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return 1; } diff --git a/cumulus/start-stop-daemon.c b/cumulus/start-stop-daemon.c index ea63fbc217..4d447d9051 100644 --- a/cumulus/start-stop-daemon.c +++ b/cumulus/start-stop-daemon.c @@ -56,8 +56,9 @@ #include #include #include -#include +#ifdef linux #include +#endif static int testmode = 0; static int quietmode = 0; @@ -241,6 +242,7 @@ next_dirname(const char *s) return cur; } +#ifdef linux static void add_namespace(const char *path) { @@ -270,6 +272,7 @@ add_namespace(const char *path) namespace->nstype = nstype; LIST_INSERT_HEAD(&namespace_head, namespace, list); } +#endif #ifdef HAVE_LXC static void @@ -567,7 +570,9 @@ parse_options(int argc, char * const *argv) changeroot = optarg; break; case 'd': /* --namespace /.../||/name */ +#ifdef linux add_namespace(optarg); +#endif break; case 'N': /* --nice */ nicelevel = atoi(optarg); diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index fe64fbc005..7fcf38bcec 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -20,6 +20,8 @@ $QuaggaId: $Format:%an, %ai, %h$ $ */ +#include + #include #include #include diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 88fea3427f..0a9807b8b9 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -427,7 +427,7 @@ interface_info_ioctl () struct listnode *node, *nnode; struct interface *ifp; - for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) + for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) { if_get_index (ifp); #ifdef SIOCGIFHWADDR diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index f9df983abf..23224dc241 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -927,7 +927,7 @@ rtm_read (struct rt_msghdr *rtm) case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); return; break; } @@ -940,18 +940,18 @@ rtm_read (struct rt_msghdr *rtm) case ZEBRA_RIB_FOUND_EXACT: zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); break; case ZEBRA_RIB_FOUND_CONNECTED: case ZEBRA_RIB_FOUND_NOGATE: zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); break; case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf); - rib_lookup_and_dump (&p); + rib_lookup_and_dump (&p, VRF_DEFAULT); return; break; } @@ -968,7 +968,7 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, 0, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD @@ -976,8 +976,8 @@ rtm_read (struct rt_msghdr *rtm) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0 zebra_flags, - &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, + &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, 0, SAFI_UNICAST); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) @@ -1010,16 +1010,16 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, 0, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ } diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 931fc73e43..133b0fc2e9 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -31,6 +31,7 @@ #include "command.h" #include "stream.h" #include "ptm_lib.h" +#include "network.h" #include "buffer.h" #include "zebra/zebra_ptm_redistribute.h" #include "bfd.h" @@ -383,9 +384,11 @@ zebra_ptm_socket_init (void) ptm_cb.ptm_sock = -1; - sock = socket (PF_UNIX, (SOCK_STREAM | SOCK_NONBLOCK), 0); + sock = socket (PF_UNIX, SOCK_STREAM, 0); if (sock < 0) return -1; + if (set_nonblocking(sock) < 0) + return -1; /* Make server socket. */ memset (&addr, 0, sizeof (struct sockaddr_un)); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8a2728a890..3aa9356fe6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -119,13 +119,17 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int prior int is_zebra_valid_kernel_table(u_int32_t table_id) { - if ((table_id > ZEBRA_KERNEL_TABLE_MAX) || - (table_id == RT_TABLE_UNSPEC) || + if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) + return 0; + +#ifdef linux + if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL) || (table_id == RT_TABLE_COMPAT)) return 0; - else - return 1; +#endif + + return 1; } int From e018c7cc9a7d218ce3a28b5619761c22eb060882 Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Fri, 12 Aug 2016 17:09:27 -0700 Subject: [PATCH 112/226] bgpd: Reverting fix for CM-5040: BGP and OSPF should accept "router-id use-loopback" ospfd: Reverting fix for CM-5040: BGP and OSPF should accept "router-id use-loopback" This reverts commit cdb805bc9e45e355f4f034be8c89f0b7ca7894fd. Conflicts: bgpd/bgp_vty.c --- bgpd/bgp_vty.c | 83 +++++-------------------------------------- ospfd/ospf_vty.c | 92 ------------------------------------------------ 2 files changed, 8 insertions(+), 167 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 0f27069a95..9df92fea03 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -32,8 +32,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "hash.h" #include "queue.h" -#include "if.h" -#include "vrf.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_advertise.h" @@ -835,10 +833,6 @@ DEFUN (no_bgp_router_id, int ret; struct in_addr id; struct bgp *bgp; - struct interface *ifp; - struct listnode *node; - struct connected *ifc; - struct prefix *p; bgp = vty->index; @@ -846,28 +840,16 @@ DEFUN (no_bgp_router_id, { ret = inet_aton (argv[0], &id); if (! ret) - { - ifp = if_lookup_by_name_vrf(argv[0], bgp->vrf_id); - if (!ifp) { - vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE); - return CMD_WARNING; - } - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - p = ifc->address; - if (p && (p->family == AF_INET)) - { - id = p->u.prefix4; - break; - } - } - } + { + vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE); + return CMD_WARNING; + } if (! IPV4_ADDR_SAME (&bgp->router_id_static, &id)) - { - vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE); - return CMD_WARNING; - } + { + vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE); + return CMD_WARNING; + } } id.s_addr = 0; @@ -884,53 +866,6 @@ ALIAS (no_bgp_router_id, "Override configured router identifier\n" "Manually configured router identifier\n") -DEFUN (bgp_router_id_interface, - bgp_router_id_interface_cmd, - "bgp router-id IFNAME", - BGP_STR - "Override configured router identifier\n" - "Interface name\n") -{ - struct bgp *bgp; - struct interface *ifp; - struct connected *ifc; - struct listnode *node; - struct prefix *p; - struct vrf *vrf; - - bgp = vty->index; - p = NULL; - - ifp = if_lookup_by_name_vrf(argv[0], bgp->vrf_id); - if (!ifp) - { - vrf = vrf_lookup(bgp->vrf_id); - vty_out (vty, "%% Couldnt find interface %s in VRF %s%s", argv[0], vrf? vrf->name:"", VTY_NEWLINE); - return CMD_WARNING; - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - p = ifc->address; - - if (p && (p->family == AF_INET)) - { - bgp_router_id_static_set(bgp, p->u.prefix4); - return CMD_SUCCESS; - } - } - vty_out (vty, "%% Couldnt assign the router-id%s", VTY_NEWLINE); - return CMD_WARNING; -} - -ALIAS (no_bgp_router_id, - no_bgp_router_id_interface_cmd, - "no bgp router-id IFNAME", - NO_STR - BGP_STR - "Override configured router identifier\n" - "Interface name\n") - /* BGP Cluster ID. */ DEFUN (bgp_cluster_id, @@ -14477,8 +14412,6 @@ bgp_vty_init (void) install_element (BGP_NODE, &bgp_router_id_cmd); install_element (BGP_NODE, &no_bgp_router_id_cmd); install_element (BGP_NODE, &no_bgp_router_id_val_cmd); - install_element (BGP_NODE, &bgp_router_id_interface_cmd); - install_element (BGP_NODE, &no_bgp_router_id_interface_cmd); /* "bgp cluster-id" commands. */ install_element (BGP_NODE, &bgp_cluster_id_cmd); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index beda0caa11..16fab68c99 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -271,43 +271,10 @@ DEFUN (no_ospf_router_id, struct ospf *ospf = vty->index; struct listnode *node; struct ospf_area *area; - struct in_addr id; - struct interface *ifp; - struct connected *ifc; - struct prefix *p; - int ret; if (!ospf) return CMD_SUCCESS; - if (argc == 1) - { - ret = inet_aton (argv[0], &id); - if (! ret) - { - ifp = if_lookup_by_name(argv[0]); - if (!ifp) { - vty_out (vty, "%% Malformed OSPF router identifier%s", VTY_NEWLINE); - return CMD_WARNING; - } - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - p = ifc->address; - if (p && (p->family == AF_INET)) - { - id = p->u.prefix4; - break; - } - } - } - - if (! IPV4_ADDR_SAME (&ospf->router_id_static, &id)) - { - vty_out (vty, "%% OSPF router-id doesn't match%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - ospf->router_id_static.s_addr = 0; for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) @@ -331,63 +298,6 @@ ALIAS (no_ospf_router_id, "router-id for the OSPF process\n" "OSPF router-id in IP address format\n") -DEFUN (ospf_router_id_interface, - ospf_router_id_interface_cmd, - "ospf router-id IFNAME", - "OSPF specific commands\n" - "router-id for the OSPF process\n" - "Interface name\n") -{ - struct ospf *ospf = vty->index; - struct listnode *node; - struct ospf_area *area; - struct interface *ifp; - struct connected *ifc; - struct prefix *p; - - if (!ospf) - return CMD_SUCCESS; - - p = NULL; - ifp = if_lookup_by_name(argv[0]); - if (!ifp) - { - vty_out (vty, "%% Couldnt find interface %s%s", argv[0], VTY_NEWLINE); - return CMD_WARNING; - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - p = ifc->address; - - if (p && (p->family == AF_INET)) - { - if (IPV4_ADDR_SAME (&ospf->router_id_static, &p->u.prefix4)) - return CMD_SUCCESS; - ospf->router_id_static = p->u.prefix4; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area->full_nbrs) - { - vty_out (vty, "For this router-id change to take effect," - " save config and restart ospfd%s", VTY_NEWLINE); - return CMD_SUCCESS; - } - ospf_router_id_update (ospf); - return CMD_SUCCESS; - } - } - vty_out (vty, "%% Couldnt assign the router-id%s", VTY_NEWLINE); - return CMD_WARNING; -} - -ALIAS (no_ospf_router_id, - no_ospf_router_id_interface_cmd, - "no ospf router-id IFNAME", - NO_STR - "OSPF specific commands\n" - "router-id for the OSPF process\n" - "Interface name\n") - static void ospf_passive_interface_default (struct ospf *ospf, u_char newval) { @@ -10421,10 +10331,8 @@ ospf_vty_init (void) /* "ospf router-id" commands. */ install_element (OSPF_NODE, &ospf_router_id_cmd); install_element (OSPF_NODE, &ospf_router_id_old_cmd); - install_element (OSPF_NODE, &ospf_router_id_interface_cmd); install_element (OSPF_NODE, &no_ospf_router_id_cmd); install_element (OSPF_NODE, &no_ospf_router_id_val_cmd); - install_element (OSPF_NODE, &no_ospf_router_id_interface_cmd); /* "passive-interface" commands. */ install_element (OSPF_NODE, &ospf_passive_interface_addr_cmd); From f04605f4e5518ca161ee4088895988c4ae050b57 Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Sat, 13 Aug 2016 00:41:21 -0700 Subject: [PATCH 113/226] Remove individual daemon conf files and replace with Quagga.conf Ticket: CM-11777 Reviewed By: CCR-5096 Testing Done: The recommended, and in many ways the only supported, model for the configuration file of quagga is to use a single Quagga.conf configuration file. However, we weren't shipping with this model, which led to some confusion amongst users. This patch fixes this by removing all individual daemon configuration files and replacing it with the single Quagga.conf file. --- cumulus/etc/quagga/Quagga.conf | 3 +++ cumulus/etc/quagga/bgpd.conf | 3 --- cumulus/etc/quagga/ospf6d.conf | 3 --- cumulus/etc/quagga/ospfd.conf | 3 --- cumulus/etc/quagga/pimd.conf | 5 ----- cumulus/etc/quagga/zebra.conf | 2 -- 6 files changed, 3 insertions(+), 16 deletions(-) create mode 100644 cumulus/etc/quagga/Quagga.conf delete mode 100644 cumulus/etc/quagga/bgpd.conf delete mode 100644 cumulus/etc/quagga/ospf6d.conf delete mode 100644 cumulus/etc/quagga/ospfd.conf delete mode 100644 cumulus/etc/quagga/pimd.conf delete mode 100644 cumulus/etc/quagga/zebra.conf diff --git a/cumulus/etc/quagga/Quagga.conf b/cumulus/etc/quagga/Quagga.conf new file mode 100644 index 0000000000..a0b3ee0cfb --- /dev/null +++ b/cumulus/etc/quagga/Quagga.conf @@ -0,0 +1,3 @@ +log file /var/log/quagga/quagga.log +log timestamp precision 6 + diff --git a/cumulus/etc/quagga/bgpd.conf b/cumulus/etc/quagga/bgpd.conf deleted file mode 100644 index 7c9c5ae286..0000000000 --- a/cumulus/etc/quagga/bgpd.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname bgpd -log timestamp precision 6 -log file /var/log/quagga/bgpd.log diff --git a/cumulus/etc/quagga/ospf6d.conf b/cumulus/etc/quagga/ospf6d.conf deleted file mode 100644 index 408ca1af1e..0000000000 --- a/cumulus/etc/quagga/ospf6d.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname ospfd -log timestamp precision 6 -log file /var/log/quagga/ospf6d.log diff --git a/cumulus/etc/quagga/ospfd.conf b/cumulus/etc/quagga/ospfd.conf deleted file mode 100644 index 8f2e53e030..0000000000 --- a/cumulus/etc/quagga/ospfd.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname ospfd -log timestamp precision 6 -log file /var/log/quagga/ospfd.log diff --git a/cumulus/etc/quagga/pimd.conf b/cumulus/etc/quagga/pimd.conf deleted file mode 100644 index 8aa1e7f5f0..0000000000 --- a/cumulus/etc/quagga/pimd.conf +++ /dev/null @@ -1,5 +0,0 @@ -hostname pimd -password cn321 -enable password cn321 -log timestamp precision 6 -log file /var/log/quagga/pimd.log diff --git a/cumulus/etc/quagga/zebra.conf b/cumulus/etc/quagga/zebra.conf deleted file mode 100644 index 67e4799413..0000000000 --- a/cumulus/etc/quagga/zebra.conf +++ /dev/null @@ -1,2 +0,0 @@ -hostname zebra -log file /var/log/quagga/zebra.log From 911ad1e2f9044191a1d05d384212078d6011ac35 Mon Sep 17 00:00:00 2001 From: vivek Date: Sat, 13 Aug 2016 13:25:56 -0700 Subject: [PATCH 114/226] zebra: Fix interface lookup for RA statistics Ensure we lookup interface across VRFs, not just in the default VRF. Signed-off-by: Vivek Venkatraman Reviewed-by: Dinesh Dutt Ticket: CM-12357 Reviewed By: CCR-5097 Testing Done: Manual, bgp-min --- zebra/rtadv.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 750502aa23..f3f1cee14b 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -69,22 +69,25 @@ static void rtadv_event (struct zebra_ns *, enum rtadv_event, int); static int if_join_all_router (int, struct interface *); static int if_leave_all_router (int, struct interface *); -static int rtadv_increment_received(unsigned int *ifindex) { +static int +rtadv_increment_received(struct zebra_ns *zns, unsigned int *ifindex) +{ int ret = -1; struct interface *iface; struct zebra_if *zif; - iface = if_lookup_by_index_vrf(*ifindex, VRF_DEFAULT); - if (iface && iface->info) { - zif = iface->info; - zif->ra_rcvd++; - ret = 0; - } + iface = if_lookup_by_index_per_ns (zns, *ifindex); + if (iface && iface->info) + { + zif = iface->info; + zif->ra_rcvd++; + ret = 0; + } return ret; } static int -rtadv_recv_packet (int sock, u_char *buf, int buflen, +rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen, struct sockaddr_in6 *from, unsigned int *ifindex, int *hoplimit) { @@ -134,10 +137,7 @@ rtadv_recv_packet (int sock, u_char *buf, int buflen, } } - if(rtadv_increment_received(ifindex) < 0) - zlog_err("%s: could not increment RA received counter on ifindex %d", - __func__, *ifindex); - + rtadv_increment_received(zns, ifindex); return ret; } @@ -619,7 +619,7 @@ rtadv_read (struct thread *thread) /* Register myself. */ rtadv_event (zns, RTADV_READ, sock); - len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); + len = rtadv_recv_packet (zns, sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); if (len < 0) { From e33efc8aa85ad17698bd8d42f1d32d80eb5ca4b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 15 Aug 2016 12:04:30 -0400 Subject: [PATCH 115/226] zebra: Fix usage of accidental NULL pointer NS_DEFAULT is #defined to 0, We are passing it in to a function that is taking 'struct zebra_ns *' which is translating into a NULL pointer. Which in some situations will cause a crash. Signed-off-by: Donald Sharp Reviewed-by: Don Slice Daniel Walton Nikolay Aleksandrov (cherry picked from commit 1e9fa2763953adc603c3acc4ed2a46c9e72cbb29) --- zebra/rt_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b2a54a83ac..bd1c923506 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1998,7 +1998,7 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &zns->netlink_cmd, NS_DEFAULT); + return netlink_talk (&req.n, &zns->netlink_cmd, zns); } /* Routing table change via netlink interface. */ From 352534ac21dd985fa3b5c71a0276849cb7a71633 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 15 Aug 2016 12:04:30 -0400 Subject: [PATCH 116/226] zebra: Fix usage of accidental NULL pointer NS_DEFAULT is #defined to 0, We are passing it in to a function that is taking 'struct zebra_ns *' which is translating into a NULL pointer. Which in some situations will cause a crash. Signed-off-by: Donald Sharp Reviewed-by: Don Slice Daniel Walton Nikolay Aleksandrov (cherry picked from commit 1e9fa2763953adc603c3acc4ed2a46c9e72cbb29) (cherry picked from commit e33efc8aa85ad17698bd8d42f1d32d80eb5ca4b6) --- zebra/rt_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 481ff781e3..0549900650 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1998,7 +1998,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &zns->netlink_cmd, NS_DEFAULT); + return netlink_talk (&req.n, &zns->netlink_cmd, zns); } /* Routing table change via netlink interface. */ From 6d9e66dce7975e181c33bc9e93ff578bbf0cfb5c Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 15 Aug 2016 19:25:02 +0000 Subject: [PATCH 117/226] "No such peer-groupr" should be "No such peer-group" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12191 --- bgpd/bgp_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 9df92fea03..f16cf53cbe 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -13599,7 +13599,7 @@ bgp_show_peer_group (struct vty *vty, struct bgp *bgp, } if (type == show_peer_group && ! find) - vty_out (vty, "%% No such peer-groupr%s", VTY_NEWLINE); + vty_out (vty, "%% No such peer-group%s", VTY_NEWLINE); return CMD_SUCCESS; } From 9bb3897b9cf7d2f6f1971295ad8b5c0ea326776d Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Mon, 15 Aug 2016 17:59:47 -0700 Subject: [PATCH 118/226] Revert "Remove individual daemon conf files and replace with Quagga.conf" This reverts commit f04605f4e5518ca161ee4088895988c4ae050b57. --- cumulus/etc/quagga/Quagga.conf | 3 --- cumulus/etc/quagga/bgpd.conf | 3 +++ cumulus/etc/quagga/ospf6d.conf | 3 +++ cumulus/etc/quagga/ospfd.conf | 3 +++ cumulus/etc/quagga/pimd.conf | 5 +++++ cumulus/etc/quagga/zebra.conf | 2 ++ 6 files changed, 16 insertions(+), 3 deletions(-) delete mode 100644 cumulus/etc/quagga/Quagga.conf create mode 100644 cumulus/etc/quagga/bgpd.conf create mode 100644 cumulus/etc/quagga/ospf6d.conf create mode 100644 cumulus/etc/quagga/ospfd.conf create mode 100644 cumulus/etc/quagga/pimd.conf create mode 100644 cumulus/etc/quagga/zebra.conf diff --git a/cumulus/etc/quagga/Quagga.conf b/cumulus/etc/quagga/Quagga.conf deleted file mode 100644 index a0b3ee0cfb..0000000000 --- a/cumulus/etc/quagga/Quagga.conf +++ /dev/null @@ -1,3 +0,0 @@ -log file /var/log/quagga/quagga.log -log timestamp precision 6 - diff --git a/cumulus/etc/quagga/bgpd.conf b/cumulus/etc/quagga/bgpd.conf new file mode 100644 index 0000000000..7c9c5ae286 --- /dev/null +++ b/cumulus/etc/quagga/bgpd.conf @@ -0,0 +1,3 @@ +hostname bgpd +log timestamp precision 6 +log file /var/log/quagga/bgpd.log diff --git a/cumulus/etc/quagga/ospf6d.conf b/cumulus/etc/quagga/ospf6d.conf new file mode 100644 index 0000000000..408ca1af1e --- /dev/null +++ b/cumulus/etc/quagga/ospf6d.conf @@ -0,0 +1,3 @@ +hostname ospfd +log timestamp precision 6 +log file /var/log/quagga/ospf6d.log diff --git a/cumulus/etc/quagga/ospfd.conf b/cumulus/etc/quagga/ospfd.conf new file mode 100644 index 0000000000..8f2e53e030 --- /dev/null +++ b/cumulus/etc/quagga/ospfd.conf @@ -0,0 +1,3 @@ +hostname ospfd +log timestamp precision 6 +log file /var/log/quagga/ospfd.log diff --git a/cumulus/etc/quagga/pimd.conf b/cumulus/etc/quagga/pimd.conf new file mode 100644 index 0000000000..8aa1e7f5f0 --- /dev/null +++ b/cumulus/etc/quagga/pimd.conf @@ -0,0 +1,5 @@ +hostname pimd +password cn321 +enable password cn321 +log timestamp precision 6 +log file /var/log/quagga/pimd.log diff --git a/cumulus/etc/quagga/zebra.conf b/cumulus/etc/quagga/zebra.conf new file mode 100644 index 0000000000..67e4799413 --- /dev/null +++ b/cumulus/etc/quagga/zebra.conf @@ -0,0 +1,2 @@ +hostname zebra +log file /var/log/quagga/zebra.log From d8efb772eb7adb2513a779a8bf247861c56f8eef Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 10 Nov 2015 18:04:42 +0100 Subject: [PATCH 119/226] lib: don't have log functions change errno Signed-off-by: Christian Franke Acked-by: Donald Sharp (cherry picked from commit abfd40d68202882696260617729518a6d2c99302) --- lib/log.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/log.c b/lib/log.c index 453a611dcd..ea50ae18cc 100644 --- a/lib/log.c +++ b/lib/log.c @@ -179,6 +179,7 @@ static void vzlog (struct zlog *zl, int priority, const char *format, va_list args) { char proto_str[32]; + int original_errno = errno; struct timestamp_control tsctl; tsctl.already_rendered = 0; @@ -197,6 +198,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) fflush (stderr); /* In this case we return at here. */ + errno = original_errno; return; } tsctl.precision = zl->timestamp_precision; @@ -249,6 +251,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), proto_str, format, &tsctl, args); + + errno = original_errno; } static char * From 9af6011992d8012ca146343be49a8e3df4da3885 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 16:59:08 +0200 Subject: [PATCH 120/226] isisd: fix isis_circuit_create() Between the awkwardly managed CSM and the tacked-on IPv6 support, the simplified logic to setup a circuit wasn't quite right. Note that the API essentially allows creating a circuit without enabling either IPv4 or IPv6. This wasn't possible before and probably breaks isisd in 'interesting' ways. The CLI won't do this, so it's only an issue when adding on other configuration mechanisms. Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 6 ++++-- isisd/isis_vty.c | 16 ++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d8ca694d59..b9ebf52505 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1226,8 +1226,10 @@ isis_interface_config_write (struct vty *vty) struct isis_circuit * isis_circuit_create (struct isis_area *area, struct interface *ifp) { - struct isis_circuit *circuit; - circuit = isis_csm_state_change (ISIS_ENABLE, NULL, area); + struct isis_circuit *circuit = circuit_scan_by_ifp (ifp); + if (circuit && circuit->area) + return NULL; + circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); isis_circuit_if_bind (circuit, ifp); return circuit; diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 3f218561cc..3ce06b83da 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -72,17 +72,13 @@ DEFUN (ip_router_isis, /* Prevent more than one area per circuit */ circuit = circuit_scan_by_ifp (ifp); - if (circuit) + if (circuit && circuit->area) { - if (circuit->ip_router == 1) + if (strcmp (circuit->area->area_tag, area_tag)) { - if (strcmp (circuit->area->area_tag, area_tag)) - { - vty_out (vty, "ISIS circuit is already defined on %s%s", - circuit->area->area_tag, VTY_NEWLINE); - return CMD_ERR_NOTHING_TODO; - } - return CMD_SUCCESS; + vty_out (vty, "ISIS circuit is already defined on %s%s", + circuit->area->area_tag, VTY_NEWLINE); + return CMD_ERR_NOTHING_TODO; } } @@ -90,7 +86,7 @@ DEFUN (ip_router_isis, if (!area) area = isis_area_create (area_tag); - if (!circuit) + if (!circuit || !circuit->area) circuit = isis_circuit_create (area, ifp); bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; From 19dd696bda25a595f4e324a9729f27c4d8405e48 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 17:02:50 +0200 Subject: [PATCH 121/226] isisd: fix isis_circuit_af_set() on fresh circuit A newly-created circuit will be in enabled state but have neither IPv4 nor IPv6 configured. The logic in isis_circuit_af_set assumed that "enabled" is equivalent to "ip || ipv6". This is the only place where this distinction is currently relevant, as the CLI won't allow enabling an interface without enabling either IPv4 or IPv6; and it will also disable a circuit when both are deconfigured. Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index b9ebf52505..ad1eca89e3 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1240,7 +1240,7 @@ isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_rou { struct isis_area *area = circuit->area; bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router; - bool was_enabled = circuit->ip_router || circuit->ipv6_router; + bool was_enabled = !!circuit->area; area->ip_circuits += ip_router - circuit->ip_router; area->ipv6_circuits += ipv6_router - circuit->ipv6_router; From b7b5d562226119f5abe02c626f9233d3a4ae9b9d Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 11 Aug 2016 16:08:05 +0200 Subject: [PATCH 122/226] isisd: fix network-type configuration Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 1 - isisd/isis_vty.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index ad1eca89e3..ac41b55b87 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1358,7 +1358,6 @@ isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) * is not supported. */ if (circ_type == CIRCUIT_T_UNKNOWN || circ_type == CIRCUIT_T_LOOPBACK - || circuit->circ_type == CIRCUIT_T_UNKNOWN || circuit->circ_type == CIRCUIT_T_LOOPBACK) { if (circuit->circ_type != circ_type) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 3ce06b83da..f9b96a42d8 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -255,7 +255,7 @@ DEFUN (isis_network, if (!circuit) return CMD_ERR_NO_MATCH; - if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { vty_out (vty, "isis network point-to-point " "is valid only on broadcast interfaces%s", @@ -278,7 +278,7 @@ DEFUN (no_isis_network, if (!circuit) return CMD_ERR_NO_MATCH; - if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { vty_out (vty, "isis network point-to-point " "is valid only on broadcast interfaces%s", From f6ad4ba172ae387f06e68b3599745c74a2c75b49 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 13 Aug 2016 01:20:20 +0200 Subject: [PATCH 123/226] isisd: fix is_type_set Code's "is_type" is "circuit-type" in CLI, "circuit_type" is "network" (type) in CLI, and the function to change is_type is isis_event_circuit_type_change()... *headdesk* Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index ac41b55b87..300c2cd85e 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1285,10 +1285,10 @@ isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) } void -isis_circuit_is_type_set (struct isis_circuit *circuit, int circ_type) +isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type) { - if (circuit->circ_type != circ_type) - isis_event_circuit_type_change (circuit, circ_type); + if (circuit->is_type != is_type) + isis_event_circuit_type_change (circuit, is_type); } int From ab1f20e60797c6dc31eb537b0018ab375c9ce3cd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 13 Aug 2016 01:32:52 +0200 Subject: [PATCH 124/226] isisd: fold up isis_circuit_is_type_set() see previous commit. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 7 ------- isisd/isis_events.c | 2 +- isisd/isisd.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 300c2cd85e..efed420161 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1284,13 +1284,6 @@ isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) return 0; } -void -isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type) -{ - if (circuit->is_type != is_type) - isis_event_circuit_type_change (circuit, is_type); -} - int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) { diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 8fb92fdd39..460b1d25ba 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -145,7 +145,7 @@ circuit_resign_level (struct isis_circuit *circuit, int level) } void -isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype) +isis_circuit_is_type_set (struct isis_circuit *circuit, int newtype) { if (circuit->state != C_STATE_UP) { diff --git a/isisd/isisd.c b/isisd/isisd.c index 62c5e26538..0d0b805a20 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1775,7 +1775,7 @@ isis_area_is_type_set(struct isis_area *area, int is_type) if (area->is_type != IS_LEVEL_1_AND_2) { for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - isis_event_circuit_type_change (circuit, is_type); + isis_circuit_is_type_set (circuit, is_type); } spftree_area_init (area); From eb735f6774b12172b41b41b12459f91722143e9e Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 15 Aug 2016 13:36:59 +0200 Subject: [PATCH 125/226] isisd: warn if there is an MTU issue on circuits Instead of later tripping over an assert, add a proper warning for interfaces whose MTU is too low. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 3 ++- isisd/isis_vty.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index efed420161..728cbdc67d 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1230,7 +1230,8 @@ isis_circuit_create (struct isis_area *area, struct interface *ifp) if (circuit && circuit->area) return NULL; circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + return circuit; isis_circuit_if_bind (circuit, ifp); return circuit; } diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index f9b96a42d8..4148eb55b9 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -86,9 +86,16 @@ DEFUN (ip_router_isis, if (!area) area = isis_area_create (area_tag); - if (!circuit || !circuit->area) + if (!circuit || !circuit->area) { circuit = isis_circuit_create (area, ifp); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + { + vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; if (af[2] != '\0') ipv6 = true; From 120c658793d960796030793b74385a9fe9888ebb Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 17:28:58 +0200 Subject: [PATCH 126/226] bgpd: only try to identify VRF on Linux Only Linux has SO_BINDTODEVICE, but that's not a problem since the whole VRF use case in that instance is currently Linux-specific. Other OS's VRF implementations will need different code. Reported-by: Martin Winter Signed-off-by: David Lamparter --- bgpd/bgp_network.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 61972aabf1..bafc666a19 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -228,6 +228,17 @@ bgp_set_socket_ttl (struct peer *peer, int bgp_sock) static int bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) { +#ifndef SO_BINDTODEVICE + /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here + * anyway since the assumption is that the interface name returned by + * getsockopt() is useful in identifying the VRF, particularly with Linux's + * VRF l3master device. The whole mechanism is specific to Linux, so... + * when other platforms add VRF support, this will need handling here as + * well. (or, some restructuring) */ + *bgp_inst = bgp_get_default (); + return !*bgp_inst; + +#else char name[VRF_NAMSIZ + 1]; socklen_t name_len = VRF_NAMSIZ; struct bgp *bgp; @@ -275,6 +286,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) /* We didn't match to either an instance or an interface. */ return -1; +#endif } /* Accept bgp connection. */ From 6bcd6029f1143b62f005c3508df3b3021787f898 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 17:51:41 +0200 Subject: [PATCH 127/226] pimd: don't break with missing SO_BINDTODEVICE This effectively a partial revert of commit 61ea395... "pimd: Bind pim sockets to interface they are associated with" Note this isn't really a proper fix, it just clears the build breakage on BSD without improving the usage of multiple sockets. Reported-by: Martin Winter Signed-off-by: David Lamparter --- pimd/pim_sock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index a2e166f796..e04cd41575 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -79,6 +79,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) return PIM_SOCK_ERR_SOCKET; } +#ifdef SO_BINDTODEVICE if (protocol == IPPROTO_PIM) { int ret; @@ -104,7 +105,10 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) return PIM_SOCK_ERR_BIND; } } - +#else + /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to + * only use 1 socket for all interfaces? */ +#endif /* Needed to obtain destination address from recvmsg() */ { From 039f3a3495b9b19e486d296de57a8ba46f9a8c87 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 7 Jan 2016 10:03:01 -0500 Subject: [PATCH 128/226] lib, bgpd, tests: Refactor FILTER_X in zebra.h lib/zebra.h has FILTER_X #define's. These do not belong there. Put them in lib/filter.h where they belong. Signed-off-by: Donald Sharp (cherry picked from commit 0490729cc033a3483fc6b0ed45085ee249cac779) --- bgpd/bgp_advertise.c | 1 + bgpd/bgp_aspath.c | 1 + bgpd/bgp_attr.c | 1 + bgpd/bgp_bfd.c | 2 ++ bgpd/bgp_btoa.c | 1 + bgpd/bgp_clist.c | 1 + bgpd/bgp_damp.c | 1 + bgpd/bgp_debug.c | 1 + bgpd/bgp_dump.c | 2 +- bgpd/bgp_ecommunity.c | 1 + bgpd/bgp_filter.c | 9 ++------- bgpd/bgp_fsm.c | 1 + bgpd/bgp_mpath.c | 1 + bgpd/bgp_mplsvpn.c | 1 + bgpd/bgp_network.c | 1 + bgpd/bgp_nexthop.c | 1 + bgpd/bgp_nht.c | 1 + bgpd/bgp_open.c | 1 + bgpd/bgp_packet.c | 1 + bgpd/bgp_regex.c | 1 + bgpd/bgp_snmp.c | 1 + bgpd/bgp_table.c | 1 + bgpd/bgp_updgrp_adv.c | 1 + bgpd/bgp_vty.c | 1 + bgpd/bgp_zebra.c | 1 + lib/filter.h | 5 +++++ lib/zebra.h | 5 ----- tests/aspath_test.c | 1 + tests/bgp_capability_test.c | 1 + tests/bgp_mp_attr_test.c | 1 + tests/bgp_mpath_test.c | 1 + tests/ecommunity_test.c | 1 + vtysh/vtysh.c | 1 + 33 files changed, 38 insertions(+), 13 deletions(-) diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index de27513a42..da5ab94e97 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "hash.h" #include "thread.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 4161d149fa..eca4441010 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "jhash.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index eefdd9e8ec..dc157ba7d0 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "jhash.h" #include "queue.h" #include "table.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index b8b0053695..b0c812cca9 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -34,6 +34,8 @@ #include "vty.h" #include "bfd.h" #include "lib/json.h" +#include "filter.h" + #include "bgpd/bgpd.h" #include "bgp_fsm.h" #include "bgpd/bgp_bfd.h" diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index a6c16d8c2d..904ae66e10 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "privs.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_dump.h" diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 4beae4391e..12c936b190 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 2e2dc42ad1..f4a83d720b 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "thread.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_damp.h" diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 5b6ee0e070..7427afed7b 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 59bb2f8a13..e219d5248e 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -29,9 +29,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "linklist.h" #include "queue.h" #include "memory.h" +#include "filter.h" #include "bgpd/bgp_table.h" - #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index dc0137fd19..e55ce3528c 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "command.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 693c639f75..33877e7258 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "buffer.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -66,18 +67,12 @@ struct as_filter char *reg_str; }; -enum as_list_type -{ - ACCESS_TYPE_STRING, - ACCESS_TYPE_NUMBER -}; - /* AS path filter list. */ struct as_list { char *name; - enum as_list_type type; + enum access_type type; struct as_list *next; struct as_list *prev; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9da21fdffd..ae77ac421a 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "workqueue.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 8397177f8f..9d742204f6 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -29,6 +29,7 @@ #include "sockunion.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 00f8221bcb..4650495faf 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "stream.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index bafc666a19..0caada488b 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -33,6 +33,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "network.h" #include "queue.h" #include "hash.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_open.h" diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 80495065b0..d96224c093 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "jhash.h" #include "nexthop.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9d8d8f3b52..42885165c7 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -31,6 +31,7 @@ #include "memory.h" #include "nexthop.h" #include "vrf.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 8765488881..915757e622 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "lib/json.h" #include "bgpd/bgpd.h" diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 0236f6777a..937623a30b 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "linklist.h" #include "plist.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c index 15c23c9ff9..ea87633dc0 100644 --- a/bgpd/bgp_regex.c +++ b/bgpd/bgp_regex.c @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd.h" #include "bgp_aspath.h" diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index fc5a0eb59c..5e6218e8a3 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "thread.h" #include "smux.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 1df24859f5..114c6ef013 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "vty.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 4b684be1bb..96bcd011ca 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -36,6 +36,7 @@ #include "thread.h" #include "queue.h" #include "routemap.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 9df92fea03..4b1174b16d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "hash.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_advertise.h" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 874d80bd8e..ce5d1b498e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "memory.h" #include "lib/json.h" #include "lib/bfd.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" diff --git a/lib/filter.h b/lib/filter.h index 37535cb13b..e6ccd33b3a 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -25,6 +25,11 @@ #include "if.h" +/* Filter direction. */ +#define FILTER_IN 0 +#define FILTER_OUT 1 +#define FILTER_MAX 2 + /* Filter type is made by `permit', `deny' and `dynamic'. */ enum filter_type { diff --git a/lib/zebra.h b/lib/zebra.h index 59c154ba46..b3a814c0d2 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -522,11 +522,6 @@ typedef enum { #define SAFI_ENCAP 7 /* per IANA */ #define SAFI_MAX 8 -/* Filter direction. */ -#define FILTER_IN 0 -#define FILTER_OUT 1 -#define FILTER_MAX 2 - /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_CONNECT_DISTANCE_DEFAULT 0 diff --git a/tests/aspath_test.c b/tests/aspath_test.c index fde12c41c4..9d595807fe 100644 --- a/tests/aspath_test.c +++ b/tests/aspath_test.c @@ -25,6 +25,7 @@ #include "stream.h" #include "privs.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" diff --git a/tests/bgp_capability_test.c b/tests/bgp_capability_test.c index ecabc2f19f..73f46b59a0 100644 --- a/tests/bgp_capability_test.c +++ b/tests/bgp_capability_test.c @@ -26,6 +26,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_open.h" diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c index ba619916d4..928d69752a 100644 --- a/tests/bgp_mp_attr_test.c +++ b/tests/bgp_mp_attr_test.c @@ -26,6 +26,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" diff --git a/tests/bgp_mpath_test.c b/tests/bgp_mpath_test.c index bafbef75fb..66a718cbe2 100644 --- a/tests/bgp_mpath_test.c +++ b/tests/bgp_mpath_test.c @@ -30,6 +30,7 @@ #include "memory.h" #include "zclient.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/tests/ecommunity_test.c b/tests/ecommunity_test.c index 1d4f6a1860..9166af6142 100644 --- a/tests/ecommunity_test.c +++ b/tests/ecommunity_test.c @@ -25,6 +25,7 @@ #include "privs.h" #include "memory.h" #include "queue.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index ad43f41fd9..80ee0acc3e 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -37,6 +37,7 @@ #include "linklist.h" #include "command.h" #include "memory.h" +#include "filter.h" #include "vtysh/vtysh.h" #include "log.h" #include "bgpd/bgp_vty.h" From cd66cd4ce103aef4dd357dbab1d150cd16f8edd4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Dec 2015 14:22:10 -0500 Subject: [PATCH 129/226] ospfd: Remove HAVE_OPAQUE_LSA HAVE_OPAQUE_LSA is used by default and you have to actively turn it off except that OPAQUE_LSA is an industry standard and used pretty much everywhere. There is no need to have special #defines for this anymore. Signed-off-by: Donald Sharp (cherry picked from commit 36fef5708d074a3ef41f34d324c309c45bae119b) --- configure.ac | 15 +++------------ ospfd/ospf_api.c | 3 --- ospfd/ospf_apiserver.c | 3 --- ospfd/ospf_dump.c | 2 -- ospfd/ospf_flood.c | 28 ---------------------------- ospfd/ospf_interface.c | 8 -------- ospfd/ospf_interface.h | 4 ---- ospfd/ospf_ism.c | 2 -- ospfd/ospf_lsa.c | 30 ------------------------------ ospfd/ospf_lsa.h | 6 ------ ospfd/ospf_main.c | 2 -- ospfd/ospf_neighbor.c | 2 -- ospfd/ospf_neighbor.h | 2 -- ospfd/ospf_nsm.c | 10 ---------- ospfd/ospf_opaque.c | 2 -- ospfd/ospf_packet.c | 24 ------------------------ ospfd/ospf_te.c | 3 --- ospfd/ospf_vty.c | 39 --------------------------------------- ospfd/ospfd.c | 16 ---------------- ospfd/ospfd.h | 10 ---------- 20 files changed, 3 insertions(+), 208 deletions(-) diff --git a/configure.ac b/configure.ac index 50918227e9..3e10222369 100755 --- a/configure.ac +++ b/configure.ac @@ -265,8 +265,6 @@ AC_ARG_WITH(libpam, AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh])) AC_ARG_ENABLE(tcp-zebra, AS_HELP_STRING([--enable-tcp-zebra], [enable TCP/IP socket connection between zebra and protocol daemon])) -AC_ARG_ENABLE(opaque-lsa, - AS_HELP_STRING([--disable-opaque-lsa],[do not build OSPF Opaque-LSA with OSPFAPI support (RFC2370)])) AC_ARG_ENABLE(ospfapi, AS_HELP_STRING([--disable-ospfapi], [do not build OSPFAPI to access the OSPF LSA Database])) AC_ARG_ENABLE(ospfclient, @@ -383,12 +381,7 @@ if test "${enable_tcp_zebra}" = "yes"; then AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication) fi -if test "${enable_opaque_lsa}" != "no"; then - AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA) -fi - if test "${enable_ospf_te}" != "no"; then - AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA) AC_DEFINE(HAVE_OSPF_TE,,OSPF TE) fi @@ -1245,16 +1238,14 @@ fi AM_CONDITIONAL(WATCHQUAGGA, test "x$WATCHQUAGGA" = "xwatchquagga") OSPFCLIENT="" -if test "${enable_opaque_lsa}" != "no"; then - if test "${enable_ospfapi}" != "no";then +if test "${enable_ospfapi}" != "no";then AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI) - if test "${enable_ospfclient}" != "no";then + if test "${enable_ospfclient}" != "no";then OSPFCLIENT="ospfclient" - fi fi - fi + AM_CONDITIONAL(OSPFCLIENT, test "x$OSPFCLIENT" = "xospfclient") case "${enable_ripngd}" in diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index 45525f4a2c..9f90f671ce 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -23,9 +23,6 @@ #include #ifdef SUPPORT_OSPF_API -#ifndef HAVE_OPAQUE_LSA -#error "Core Opaque-LSA module must be configured." -#endif /* HAVE_OPAQUE_LSA */ #include "linklist.h" #include "prefix.h" diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 92f68f75f8..aac8ef4b8b 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -23,9 +23,6 @@ #include #ifdef SUPPORT_OSPF_API -#ifndef HAVE_OPAQUE_LSA -#error "Core Opaque-LSA module must be configured." -#endif /* HAVE_OPAQUE_LSA */ #include "linklist.h" #include "prefix.h" diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 65d6e09b6d..ed279f38ff 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -619,13 +619,11 @@ ospf_packet_ls_upd_dump (struct stream *s, u_int16_t length) case OSPF_AS_NSSA_LSA: ospf_as_external_lsa_dump (s, length); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_dump (s, length); break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index e9f443111a..7f83ddeaae 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -156,9 +156,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf, ospf_router_lsa_update_area (area); return; case OSPF_NETWORK_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: -#endif /* HAVE_OPAQUE_LSA */ /* We must find the interface the LSA could belong to. If the interface is no more a broadcast type or we are no more the DR, we flush the LSA otherwise -- create the new instance and @@ -178,13 +176,11 @@ ospf_process_self_originated_lsa (struct ospf *ospf, return; } -#ifdef HAVE_OPAQUE_LSA if (new->data->type == OSPF_OPAQUE_LINK_LSA) { ospf_opaque_lsa_refresh (new); return; } -#endif /* HAVE_OPAQUE_LSA */ if (oi->network_lsa_self) oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum; @@ -211,14 +207,12 @@ ospf_process_self_originated_lsa (struct ospf *ospf, else ospf_lsa_flush_as (ospf, new); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AREA_LSA: ospf_opaque_lsa_refresh (new); break; case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */ break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -299,25 +293,17 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, interface. */ lsa_ack_flag = ospf_flood_through (ospf, nbr, new); -#ifdef HAVE_OPAQUE_LSA /* Remove the current database copy from all neighbors' Link state retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does ^^^^^^^^^^^^^^^^^^^^^^^ not have area ID. All other (even NSSA's) do have area ID. */ -#else /* HAVE_OPAQUE_LSA */ - /* Remove the current database copy from all neighbors' Link state - retransmission lists. Only AS_EXTERNAL does not have area ID. - All other (even NSSA's) do have area ID. */ -#endif /* HAVE_OPAQUE_LSA */ if (current) { switch (current->data->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_ls_retransmit_delete_nbr_as (ospf, current); break; default: @@ -439,7 +425,6 @@ ospf_flood_through_interface (struct ospf_interface *oi, } } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type)) { if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O)) @@ -449,7 +434,6 @@ ospf_flood_through_interface (struct ospf_interface *oi, continue; } } -#endif /* HAVE_OPAQUE_LSA */ /* If the new LSA was received from this neighbor, examine the next neighbor. */ @@ -584,7 +568,6 @@ ospf_flood_through_area (struct ospf_area *area, oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; -#ifdef HAVE_OPAQUE_LSA if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi)) { /* @@ -596,7 +579,6 @@ ospf_flood_through_area (struct ospf_area *area, (void *)lsa->oi, (void *)oi); continue; } -#endif /* HAVE_OPAQUE_LSA */ if (ospf_flood_through_interface (oi, inbr, lsa)) lsa_ack_flag = 1; @@ -706,16 +688,12 @@ ospf_flood_through (struct ospf *ospf, case OSPF_NETWORK_LSA: case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); break; case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); break; /* Type-7 Only received within NSSA, then flooded */ @@ -745,9 +723,7 @@ ospf_flood_through (struct ospf *ospf, switch (lsa->data->type) { case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); break; /* Type-7 Only received within NSSA, then flooded */ @@ -1024,16 +1000,12 @@ ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa) case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_lsa_flush_area (lsa, lsa->area); break; case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ ospf_lsa_flush_as (ospf, lsa); break; default: diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 5602ebe897..2c8124b93d 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -243,9 +243,7 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) oi->crypt_seqnum = time (NULL); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type9_lsa_init (oi); -#endif /* HAVE_OPAQUE_LSA */ oi->ospf = ospf; @@ -307,9 +305,7 @@ ospf_if_free (struct ospf_interface *oi) assert (oi->state == ISM_Down); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type9_lsa_term (oi); -#endif /* HAVE_OPAQUE_LSA */ /* Free Pseudo Neighbour */ ospf_nbr_delete (oi->nbr_self); @@ -696,9 +692,7 @@ ospf_if_new_hook (struct interface *ifp) SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET; -#ifdef HAVE_OPAQUE_LSA rc = ospf_opaque_new_if (ifp); -#endif /* HAVE_OPAQUE_LSA */ return rc; } @@ -707,9 +701,7 @@ ospf_if_delete_hook (struct interface *ifp) { int rc = 0; struct route_node *rn; -#ifdef HAVE_OPAQUE_LSA rc = ospf_opaque_del_if (ifp); -#endif /* HAVE_OPAQUE_LSA */ route_table_finish (IF_OIFS (ifp)); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 68dbf186d2..7a74288bff 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -188,9 +188,7 @@ struct ospf_interface /* self-originated LSAs. */ struct ospf_lsa *network_lsa_self; /* network-LSA. */ -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-9 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ struct route_table *ls_upd_queue; @@ -211,9 +209,7 @@ struct ospf_interface struct thread *t_ls_ack; /* timer */ struct thread *t_ls_ack_direct; /* event */ struct thread *t_ls_upd_event; /* event */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-9 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ int on_write_q; diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 9649df8dc0..ae6d0cdbc5 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -593,9 +593,7 @@ ism_change_state (struct ospf_interface *oi, int state) oi->network_lsa_self = NULL; } -#ifdef HAVE_OPAQUE_LSA ospf_opaque_ism_change (oi, old_state); -#endif /* HAVE_OPAQUE_LSA */ /* Check area border status. */ ospf_check_abr_status (oi->ospf); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 7e34e5dd9e..68a3946b3a 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2642,11 +2642,9 @@ ospf_discard_from_db (struct ospf *ospf, ospf_ase_unregister_external_lsa (old, ospf); ospf_ls_retransmit_delete_nbr_as (ospf, old); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: ospf_ls_retransmit_delete_nbr_as (ospf, old); break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: ospf_ls_retransmit_delete_nbr_area (old->area, old); ospf_ase_unregister_external_lsa (old, ospf); @@ -2680,9 +2678,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, lsdb = ospf->lsdb; break; case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsdb = ospf->lsdb; break; default: @@ -2794,7 +2790,6 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, case OSPF_AS_EXTERNAL_LSA: new = ospf_external_lsa_install (ospf, lsa, rt_recalc); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: if (IS_LSA_SELF (lsa)) lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */ @@ -2807,7 +2802,6 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, case OSPF_OPAQUE_AS_LSA: new = ospf_opaque_lsa_install (lsa, rt_recalc); break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: new = ospf_external_lsa_install (ospf, lsa, rt_recalc); default: /* type-6,8,9....nothing special */ @@ -2825,9 +2819,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, switch (lsa->data->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_NSSA_LSA: zlog_debug ("LSA[%s]: Install %s", dump_lsa_key (new), @@ -3061,7 +3053,6 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) switch (lsa->data->type) { -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -3074,7 +3065,6 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) * topology, and thus, routing recalculation is not needed here. */ break; -#endif /* HAVE_OPAQUE_LSA */ case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_NSSA_LSA: ospf_ase_incremental_update (ospf, lsa); @@ -3115,12 +3105,10 @@ ospf_lsa_maxage_walker (struct thread *thread) ospf_lsa_maxage_walker_remover (ospf, lsa); LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ LSDB_LOOP (NSSA_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); } @@ -3130,10 +3118,8 @@ ospf_lsa_maxage_walker (struct thread *thread) { LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker, @@ -3186,15 +3172,11 @@ ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router); case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router); default: break; @@ -3230,13 +3212,11 @@ ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type, return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: /* Currently not used. */ break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -3249,14 +3229,12 @@ ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah) { struct ospf_lsa *match; -#ifdef HAVE_OPAQUE_LSA /* * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) * is redefined to have two subfields; opaque-type and opaque-id. * However, it is harmless to treat the two sub fields together, as if * they two were forming a unique LSA-ID. */ -#endif /* HAVE_OPAQUE_LSA */ match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router); @@ -3407,14 +3385,12 @@ ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa) switch (lsa->data->type) { -#ifdef HAVE_OPAQUE_LSA /* Opaque wants to be notified of flushes */ case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_refresh (lsa); break; -#endif /* HAVE_OPAQUE_LSA */ default: ospf_refresher_unregister_lsa (ospf, lsa); ospf_lsa_flush (ospf, lsa); @@ -3474,22 +3450,18 @@ ospf_flush_self_originated_lsas_now (struct ospf *ospf) ospf_lsa_flush_schedule (ospf, lsa); LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } if (need_to_flush_ase) { LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_lsa_flush_schedule (ospf, lsa); -#endif /* HAVE_OPAQUE_LSA */ } /* @@ -3698,13 +3670,11 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) else ospf_lsa_flush_as (ospf, lsa); break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: new = ospf_opaque_lsa_refresh (lsa); break; -#endif /* HAVE_OPAQUE_LSA */ default: break; } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index f2c08b1b93..b3d72109d6 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -27,11 +27,7 @@ /* OSPF LSA Range definition. */ #define OSPF_MIN_LSA 1 /* begin range here */ -#if defined (HAVE_OPAQUE_LSA) #define OSPF_MAX_LSA 12 -#else -#define OSPF_MAX_LSA 8 -#endif /* OSPF LSA Type definition. */ #define OSPF_UNKNOWN_LSA 0 @@ -211,9 +207,7 @@ struct as_external_lsa } e[1]; }; -#ifdef HAVE_OPAQUE_LSA #include "ospfd/ospf_opaque.h" -#endif /* HAVE_OPAQUE_LSA */ /* Macros. */ #define GET_METRIC(x) get_metric(x) diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 495ee2fd02..4d7b9d0350 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -323,9 +323,7 @@ main (int argc, char **argv) #ifdef HAVE_SNMP ospf_snmp_init (); #endif /* HAVE_SNMP */ -#ifdef HAVE_OPAQUE_LSA ospf_opaque_init (); -#endif /* HAVE_OPAQUE_LSA */ /* Need to initialize the default ospf structure, so the interface mode commands can be duly processed if they are received before 'router ospf', diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 1954447b64..a573936c18 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -310,7 +310,6 @@ ospf_nbr_count (struct ospf_interface *oi, int state) return count; } -#ifdef HAVE_OPAQUE_LSA int ospf_nbr_count_opaque_capable (struct ospf_interface *oi) { @@ -327,7 +326,6 @@ ospf_nbr_count_opaque_capable (struct ospf_interface *oi) return count; } -#endif /* HAVE_OPAQUE_LSA */ /* lookup nbr by address - use this only if you know you must * otherwise use the ospf_nbr_lookup() wrapper, which deals diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 0e209d2117..d62de44b5e 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -105,9 +105,7 @@ extern int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int); extern void ospf_nbr_self_reset (struct ospf_interface *, struct in_addr); extern void ospf_nbr_add_self (struct ospf_interface *, struct in_addr); extern int ospf_nbr_count (struct ospf_interface *, int); -#ifdef HAVE_OPAQUE_LSA extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); -#endif /* HAVE_OPAQUE_LSA */ extern struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, struct ospf_header *, struct ip *, struct prefix *); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 6fc7c266ac..c6b55b0746 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -222,7 +222,6 @@ ospf_db_summary_isempty (struct ospf_neighbor *nbr) static int ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { -#ifdef HAVE_OPAQUE_LSA switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: @@ -240,7 +239,6 @@ ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) default: break; } -#endif /* HAVE_OPAQUE_LSA */ /* Stay away from any Local Translated Type-7 LSAs */ if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) @@ -299,7 +297,6 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) ospf_db_summary_add (nbr, lsa); -#ifdef HAVE_OPAQUE_LSA /* Process only if the neighbor is opaque capable. */ if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { @@ -308,7 +305,6 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_db_summary_add (nbr, lsa); } -#endif /* HAVE_OPAQUE_LSA */ if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP)) { @@ -321,13 +317,11 @@ nsm_negotiation_done (struct ospf_neighbor *nbr) LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa) ospf_db_summary_add (nbr, lsa); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O) && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK && area->external_routing == OSPF_AREA_DEFAULT)) LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa) ospf_db_summary_add (nbr, lsa); -#endif /* HAVE_OPAQUE_LSA */ return 0; } @@ -383,10 +377,8 @@ nsm_clear_adj (struct ospf_neighbor *nbr) if (!ospf_ls_retransmit_isempty (nbr)) ospf_ls_retransmit_clear (nbr); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) UNSET_FLAG (nbr->options, OSPF_OPTION_O); -#endif /* HAVE_OPAQUE_LSA */ } static int @@ -768,9 +760,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state) } } -#ifdef HAVE_OPAQUE_LSA ospf_opaque_nsm_change (nbr, old_state); -#endif /* HAVE_OPAQUE_LSA */ /* State changes from > ExStart to <= ExStart should clear any Exchange * or Full/LSA Update related lists and state. diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index ff505b6bd3..a263b3c80e 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -27,7 +27,6 @@ #define MTYPE_OPAQUE_INFO_PER_ID MTYPE_TMP #include -#ifdef HAVE_OPAQUE_LSA #include "linklist.h" #include "prefix.h" @@ -2185,4 +2184,3 @@ oi_to_top (struct ospf_interface *oi) return top; } -#endif /* HAVE_OPAQUE_LSA */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 3f80bf214b..2df1596ee3 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -925,7 +925,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE) && CHECK_FLAG (hello->options, OSPF_OPTION_O)) { @@ -941,7 +940,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */ #endif /* STRICT_OBIT_USAGE_CHECK */ } -#endif /* HAVE_OPAQUE_LSA */ /* new for NSSA is to ensure that NP is on and E is off */ @@ -1093,7 +1091,6 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, return; } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsah->type) && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { @@ -1101,14 +1098,11 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); return; } -#endif /* HAVE_OPAQUE_LSA */ switch (lsah->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ /* Check for stub area. Reject if AS-External from stub but allow if from NSSA. */ if (oi->area->external_routing == OSPF_AREA_STUB) @@ -1282,7 +1276,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (dd->options, OSPF_OPTION_O) && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { @@ -1292,7 +1285,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, */ UNSET_FLAG (dd->options, OSPF_OPTION_O); } -#endif /* HAVE_OPAQUE_LSA */ /* Add event to thread. */ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); @@ -1357,7 +1349,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, /* This is where the real Options are saved */ nbr->options = dd->options; -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) @@ -1375,7 +1366,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, /* This situation is undesirable, but not a real error. */ } } -#endif /* HAVE_OPAQUE_LSA */ OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone); @@ -1653,7 +1643,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE) lsah->ls_age = htons (OSPF_LSA_MAXAGE); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { #ifdef STRICT_OBIT_USAGE_CHECK @@ -1685,7 +1674,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id)); continue; } -#endif /* HAVE_OPAQUE_LSA */ /* Create OSPF LSA instance. */ lsa = ospf_lsa_new (); @@ -1695,16 +1683,12 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, switch (lsah->type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ lsa->area = NULL; break; -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: lsa->oi = oi; /* Remember incoming interface for flooding control. */ /* Fallthrough */ -#endif /* HAVE_OPAQUE_LSA */ default: lsa->area = oi->area; break; @@ -1892,7 +1876,6 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, DISCARD_LSA (lsa, 3); } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type) && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id)) { @@ -1940,7 +1923,6 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, continue; } } -#endif /* HAVE_OPAQUE_LSA */ /* It might be happen that received LSA is self-originated network LSA, but * router ID is changed. So, we should check if LSA is a network-LSA whose @@ -2517,7 +2499,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -2525,7 +2506,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char * data) padded to 32-bit alignment." This is considered equivalent * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt * file for the detailed analysis of this passage. */ -#endif ret = lsalen % 4 ? MSG_NG : MSG_OK; break; default: @@ -3157,10 +3137,8 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, /* Set Options. */ options = OPTIONS (oi); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) SET_FLAG (options, OSPF_OPTION_O); -#endif /* HAVE_OPAQUE_LSA */ stream_putc (s, options); /* DD flags */ @@ -3185,7 +3163,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, for (rn = route_top (table); rn; rn = route_next (rn)) if ((lsa = rn->info) != NULL) { -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type) && (! CHECK_FLAG (options, OSPF_OPTION_O))) { @@ -3194,7 +3171,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, ospf_lsdb_delete (lsdb, lsa); continue; } -#endif /* HAVE_OPAQUE_LSA */ if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) { diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 155a773b33..b4de7bafd3 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -27,9 +27,6 @@ #include #ifdef HAVE_OSPF_TE -#ifndef HAVE_OPAQUE_LSA -#error "Wrong configure option" -#endif /* HAVE_OPAQUE_LSA */ #include "linklist.h" #include "prefix.h" diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 16fab68c99..3022a316c6 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3265,7 +3265,6 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_ar ospf_lsdb_checksum (area->lsdb, OSPF_AS_NSSA_LSA), VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { json_object_int_add(json_area, "lsaOpaqueLinkNumber", ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_LINK_LSA)); @@ -3282,7 +3281,6 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_ar ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_AREA_LSA), ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_AREA_LSA), VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ if (use_json) json_object_object_add(json_areas, inet_ntoa (area->area_id), json_area); @@ -3366,7 +3364,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) "enabled" : "disabled", VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) @@ -3380,7 +3377,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE) ? "enabled" : "disabled", VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ /* Show stub-router configuration */ if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED @@ -3534,7 +3530,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) ospf_lsdb_checksum (ospf->lsdb, OSPF_AS_EXTERNAL_LSA), VTY_NEWLINE); } -#ifdef HAVE_OPAQUE_LSA if (use_json) { json_object_int_add(json, "lsaAsopaqueCounter", @@ -3548,7 +3543,6 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) ospf_lsdb_count (ospf->lsdb, OSPF_OPAQUE_AS_LSA), ospf_lsdb_checksum (ospf->lsdb, OSPF_OPAQUE_AS_LSA), VTY_NEWLINE); } -#endif /* HAVE_OPAQUE_LSA */ /* Show number of areas attached. */ if (use_json) @@ -5095,11 +5089,9 @@ show_lsa_summary (struct vty *vty, struct ospf_lsa *lsa, int self) break; case OSPF_NETWORK_LSA: case OSPF_ASBR_SUMMARY_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ default: break; } @@ -5119,12 +5111,10 @@ static const char *show_database_desc[] = "AS External Link States", "Group Membership LSA", "NSSA-external Link States", -#ifdef HAVE_OPAQUE_LSA "Type-8 LSA", "Link-Local Opaque-LSA", "Area-Local Opaque-LSA", "AS-external Opaque-LSA", -#endif /* HAVE_OPAQUE_LSA */ }; static const char *show_database_header[] = @@ -5137,12 +5127,10 @@ static const char *show_database_header[] = "Link ID ADV Router Age Seq# CkSum Route", " --- header for Group Member ----", "Link ID ADV Router Age Seq# CkSum Route", -#ifdef HAVE_OPAQUE_LSA " --- type-8 ---", "Opaque-Type/Id ADV Router Age Seq# CkSum", "Opaque-Type/Id ADV Router Age Seq# CkSum", "Opaque-Type/Id ADV Router Age Seq# CkSum", -#endif /* HAVE_OPAQUE_LSA */ }; static void @@ -5414,7 +5402,6 @@ show_func_dummy (struct vty *vty, struct ospf_lsa *lsa) return 0; } -#ifdef HAVE_OPAQUE_LSA static int show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) { @@ -5427,7 +5414,6 @@ show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) } return 0; } -#endif /* HAVE_OPAQUE_LSA */ int (*show_function[])(struct vty *, struct ospf_lsa *) = { @@ -5439,12 +5425,10 @@ int (*show_function[])(struct vty *, struct ospf_lsa *) = show_as_external_lsa_detail, show_func_dummy, show_as_nssa_lsa_detail, /* almost same as external */ -#ifdef HAVE_OPAQUE_LSA NULL, /* type-8 */ show_opaque_lsa_detail, show_opaque_lsa_detail, show_opaque_lsa_detail, -#endif /* HAVE_OPAQUE_LSA */ }; static void @@ -5503,9 +5487,7 @@ show_lsa_detail (struct vty *vty, struct ospf *ospf, int type, switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ vty_out (vty, " %s %s%s", show_database_desc[type], VTY_NEWLINE, VTY_NEWLINE); @@ -5552,9 +5534,7 @@ show_lsa_detail_adv_router (struct vty *vty, struct ospf *ospf, int type, switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ vty_out (vty, " %s %s%s", show_database_desc[type], VTY_NEWLINE, VTY_NEWLINE); @@ -5590,9 +5570,7 @@ show_ip_ospf_database_summary (struct vty *vty, struct ospf *ospf, int self) switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ continue; default: break; @@ -5619,9 +5597,7 @@ show_ip_ospf_database_summary (struct vty *vty, struct ospf *ospf, int self) switch (type) { case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ break; default: continue; @@ -5673,17 +5649,10 @@ show_ip_ospf_database_maxage (struct vty *vty, struct ospf *ospf) #define OSPF_LSA_TYPE_NSSA_DESC "NSSA external link state\n" #define OSPF_LSA_TYPE_NSSA_CMD_STR "|nssa-external" -#ifdef HAVE_OPAQUE_LSA #define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "Link local Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "Link area Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_AS_DESC "Link AS Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_CMD_STR "|opaque-link|opaque-area|opaque-as" -#else /* HAVE_OPAQUE_LSA */ -#define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_AS_DESC "" -#define OSPF_LSA_TYPE_OPAQUE_CMD_STR "" -#endif /* HAVE_OPAQUE_LSA */ #define OSPF_LSA_TYPES_CMD_STR \ "asbr-summary|external|network|router|summary" \ @@ -5745,14 +5714,12 @@ show_ip_ospf_database_common (struct vty *vty, struct ospf *ospf, show_ip_ospf_database_maxage (vty, ospf); return CMD_SUCCESS; } -#ifdef HAVE_OPAQUE_LSA else if (strncmp (argv[arg_base + 0], "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; else if (strncmp (argv[arg_base + 0], "opaque-ar", 9) == 0) type = OSPF_OPAQUE_AREA_LSA; else if (strncmp (argv[arg_base + 0], "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; -#endif /* HAVE_OPAQUE_LSA */ else return CMD_WARNING; @@ -5947,14 +5914,12 @@ show_ip_ospf_database_type_adv_router_common (struct vty *vty, struct ospf *ospf type = OSPF_ASBR_SUMMARY_LSA; else if (strncmp (argv[arg_base + 0], "e", 1) == 0) type = OSPF_AS_EXTERNAL_LSA; -#ifdef HAVE_OPAQUE_LSA else if (strncmp (argv[arg_base + 0], "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; else if (strncmp (argv[arg_base + 0], "opaque-ar", 9) == 0) type = OSPF_OPAQUE_AREA_LSA; else if (strncmp (argv[arg_base + 0], "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; -#endif /* HAVE_OPAQUE_LSA */ else return CMD_WARNING; @@ -9489,9 +9454,7 @@ config_write_interface (struct vty *vty) } } while (rn); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_config_write_if (vty, ifp); -#endif /* HAVE_OPAQUE_LSA */ } return write; @@ -9987,9 +9950,7 @@ ospf_config_write (struct vty *vty) /* Distance configuration. */ config_write_ospf_distance (vty, ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_config_write_router (vty, ospf); -#endif /* HAVE_OPAQUE_LSA */ } return write; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 6d6bf12873..9d0e4b9e87 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -351,9 +351,7 @@ ospf_get () if (ospf->router_id_static.s_addr == 0) ospf_router_id_update (ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_init (ospf); -#endif /* HAVE_OPAQUE_LSA */ } return ospf; @@ -373,9 +371,7 @@ ospf_get_instance (u_short instance) if (ospf->router_id_static.s_addr == 0) ospf_router_id_update (ospf); -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_init (ospf); -#endif /* HAVE_OPAQUE_LSA */ } return ospf; @@ -513,9 +509,7 @@ ospf_finish_final (struct ospf *ospf) int i; u_short instance = 0; -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type11_lsa_term (ospf); -#endif /* HAVE_OPAQUE_LSA */ /* be nice if this worked, but it doesn't */ /*ospf_flush_self_originated_lsas_now (ospf);*/ @@ -611,17 +605,13 @@ ospf_finish_final (struct ospf *ospf) OSPF_TIMER_OFF (ospf->t_lsa_refresher); OSPF_TIMER_OFF (ospf->t_read); OSPF_TIMER_OFF (ospf->t_write); -#ifdef HAVE_OPAQUE_LSA OSPF_TIMER_OFF (ospf->t_opaque_lsa_self); -#endif close (ospf->fd); stream_free(ospf->ibuf); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) ospf_discard_from_db (ospf, ospf->lsdb, lsa); -#endif /* HAVE_OPAQUE_LSA */ LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) ospf_discard_from_db (ospf, ospf->lsdb, lsa); @@ -733,9 +723,7 @@ ospf_area_new (struct ospf *ospf, struct in_addr area_id) /* Self-originated LSAs initialize. */ new->router_lsa_self = NULL; -#ifdef HAVE_OPAQUE_LSA ospf_opaque_type10_lsa_init (new); -#endif /* HAVE_OPAQUE_LSA */ new->oiflist = list_new (); new->ranges = route_table_init (); @@ -764,12 +752,10 @@ ospf_area_free (struct ospf_area *area) LSDB_LOOP (NSSA_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); -#ifdef HAVE_OPAQUE_LSA LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_discard_from_db (area->ospf, area->lsdb, lsa); -#endif /* HAVE_OPAQUE_LSA */ ospf_lsdb_delete_all (area->lsdb); ospf_lsdb_free (area->lsdb); @@ -787,9 +773,7 @@ ospf_area_free (struct ospf_area *area) /* Cancel timer. */ OSPF_TIMER_OFF (area->t_stub_router); -#ifdef HAVE_OPAQUE_LSA OSPF_TIMER_OFF (area->t_opaque_lsa_self); -#endif /* HAVE_OPAQUE_LSA */ if (OSPF_IS_AREA_BACKBONE (area)) area->ospf->backbone = NULL; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 1a925c2c6a..5f0a7bf113 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -162,11 +162,9 @@ struct ospf #define OSPF_LOG_ADJACENCY_CHANGES (1 << 3) #define OSPF_LOG_ADJACENCY_DETAIL (1 << 4) -#ifdef HAVE_OPAQUE_LSA /* Opaque-LSA administrative flags. */ u_char opaque; #define OPAQUE_OPERATION_READY_BIT (1 << 0) -#endif /* HAVE_OPAQUE_LSA */ /* RFC3137 stub router. Configured time to stay stub / max-metric */ unsigned int stub_router_startup_time; /* seconds */ @@ -209,9 +207,7 @@ struct ospf int external_origin; /* AS-external-LSA origin flag. */ int ase_calc; /* ASE calculation flag. */ -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ /* Routing tables. */ struct route_table *old_table; /* Old routing table. */ @@ -240,9 +236,7 @@ struct ospf struct thread *t_spf_calc; /* SPF calculation timer. */ struct thread *t_ase_calc; /* ASE calculation timer. */ struct thread *t_external_lsa; /* AS-external-LSA origin timer. */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ -#endif /* HAVE_OPAQUE_LSA */ unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */ struct thread *t_maxage; /* MaxAge LSA remover timer. */ @@ -365,9 +359,7 @@ struct ospf_area /* Self-originated LSAs. */ struct ospf_lsa *router_lsa_self; -#ifdef HAVE_OPAQUE_LSA struct list *opaque_lsa_self; /* Type-10 Opaque-LSAs */ -#endif /* HAVE_OPAQUE_LSA */ /* Area announce list. */ struct @@ -409,9 +401,7 @@ struct ospf_area /* Threads. */ struct thread *t_stub_router; /* Stub-router timer */ -#ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-10 Opaque-LSAs origin. */ -#endif /* HAVE_OPAQUE_LSA */ /* Statistics field. */ u_int32_t spf_calculation; /* SPF Calculation Count. */ From 628426cd9d2332d37635d75ab5af3454816f330b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Dec 2015 14:22:11 -0500 Subject: [PATCH 130/226] ospfd: Remove HAVE_OSPF_TE Remove from ospf the HAVE_OSPF_TE define and just always have ospf traffic engineering. Signed-off-by: Donald Sharp Tested-by: NetDEF CI System (cherry picked from commit 693da6096a28eef5eadeea699771265987b3ec0c) --- configure.ac | 6 ------ ospfd/ospf_opaque.c | 6 ------ ospfd/ospf_te.c | 4 ---- 3 files changed, 16 deletions(-) diff --git a/configure.ac b/configure.ac index 3e10222369..f6d7bd33cf 100755 --- a/configure.ac +++ b/configure.ac @@ -270,8 +270,6 @@ AC_ARG_ENABLE(ospfapi, AC_ARG_ENABLE(ospfclient, AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI, (this is the default if --disable-ospfapi is set)])) -AC_ARG_ENABLE(ospf-te, - AS_HELP_STRING([--disable-ospf-te],[disable Traffic Engineering Extension to OSPF])) AC_ARG_ENABLE(multipath, AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit])) AC_ARG_ENABLE(user, @@ -381,10 +379,6 @@ if test "${enable_tcp_zebra}" = "yes"; then AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication) fi -if test "${enable_ospf_te}" != "no"; then - AC_DEFINE(HAVE_OSPF_TE,,OSPF TE) -fi - if test "${enable_linux24_tcp_md5}" = "yes"; then AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch) fi diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index a263b3c80e..ee2608b05b 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -61,9 +61,7 @@ * Followings are initialize/terminate functions for Opaque-LSAs handling. *------------------------------------------------------------------------*/ -#ifdef HAVE_OSPF_TE #include "ospfd/ospf_te.h" -#endif /* HAVE_OSPF_TE */ #ifdef SUPPORT_OSPF_API int ospf_apiserver_init (void); @@ -86,10 +84,8 @@ ospf_opaque_init (void) ospf_opaque_register_vty (); ospf_opaque_funclist_init (); -#ifdef HAVE_OSPF_TE if (ospf_mpls_te_init () != 0) exit (1); -#endif /* HAVE_OSPF_TE */ #ifdef SUPPORT_OSPF_API if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0)) @@ -102,9 +98,7 @@ ospf_opaque_init (void) void ospf_opaque_term (void) { -#ifdef HAVE_OSPF_TE ospf_mpls_te_term (); -#endif /* HAVE_OSPF_TE */ #ifdef SUPPORT_OSPF_API ospf_apiserver_term (); diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index b4de7bafd3..6dba2d3bee 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -26,8 +26,6 @@ #include -#ifdef HAVE_OSPF_TE - #include "linklist.h" #include "prefix.h" #include "vrf.h" @@ -1925,5 +1923,3 @@ ospf_mpls_te_register_vty (void) return; } - -#endif /* HAVE_OSPF_TE */ From 8ca1689f1967c09d418ab68ec054f3c449a9ad45 Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Tue, 16 Aug 2016 16:27:34 -0700 Subject: [PATCH 131/226] bgpd: Fix for CM-11777 Need Quagga.conf created at quagga install Ticket: CM-11777 Reviewed By: CCR-5110 Testing Done: Manual --- cumulus/etc/quagga/Quagga.conf | 2 ++ cumulus/etc/quagga/bgpd.conf | 3 --- cumulus/etc/quagga/ospf6d.conf | 3 --- cumulus/etc/quagga/ospfd.conf | 3 --- cumulus/etc/quagga/pimd.conf | 5 ----- cumulus/etc/quagga/zebra.conf | 2 -- vtysh/vtysh_main.c | 5 ++++- 7 files changed, 6 insertions(+), 17 deletions(-) create mode 100644 cumulus/etc/quagga/Quagga.conf delete mode 100644 cumulus/etc/quagga/bgpd.conf delete mode 100644 cumulus/etc/quagga/ospf6d.conf delete mode 100644 cumulus/etc/quagga/ospfd.conf delete mode 100644 cumulus/etc/quagga/pimd.conf delete mode 100644 cumulus/etc/quagga/zebra.conf diff --git a/cumulus/etc/quagga/Quagga.conf b/cumulus/etc/quagga/Quagga.conf new file mode 100644 index 0000000000..e52f3f8aab --- /dev/null +++ b/cumulus/etc/quagga/Quagga.conf @@ -0,0 +1,2 @@ +log file /var/log/quagga/quagga.log +log timestamp precision 6 diff --git a/cumulus/etc/quagga/bgpd.conf b/cumulus/etc/quagga/bgpd.conf deleted file mode 100644 index 7c9c5ae286..0000000000 --- a/cumulus/etc/quagga/bgpd.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname bgpd -log timestamp precision 6 -log file /var/log/quagga/bgpd.log diff --git a/cumulus/etc/quagga/ospf6d.conf b/cumulus/etc/quagga/ospf6d.conf deleted file mode 100644 index 408ca1af1e..0000000000 --- a/cumulus/etc/quagga/ospf6d.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname ospfd -log timestamp precision 6 -log file /var/log/quagga/ospf6d.log diff --git a/cumulus/etc/quagga/ospfd.conf b/cumulus/etc/quagga/ospfd.conf deleted file mode 100644 index 8f2e53e030..0000000000 --- a/cumulus/etc/quagga/ospfd.conf +++ /dev/null @@ -1,3 +0,0 @@ -hostname ospfd -log timestamp precision 6 -log file /var/log/quagga/ospfd.log diff --git a/cumulus/etc/quagga/pimd.conf b/cumulus/etc/quagga/pimd.conf deleted file mode 100644 index 8aa1e7f5f0..0000000000 --- a/cumulus/etc/quagga/pimd.conf +++ /dev/null @@ -1,5 +0,0 @@ -hostname pimd -password cn321 -enable password cn321 -log timestamp precision 6 -log file /var/log/quagga/pimd.log diff --git a/cumulus/etc/quagga/zebra.conf b/cumulus/etc/quagga/zebra.conf deleted file mode 100644 index 67e4799413..0000000000 --- a/cumulus/etc/quagga/zebra.conf +++ /dev/null @@ -1,2 +0,0 @@ -hostname zebra -log file /var/log/quagga/zebra.log diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 5bb3c61e52..3c46194d31 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -415,7 +415,10 @@ main (int argc, char **argv, char **env) if (vtysh_connect_all (daemon_name) <= 0) { fprintf(stderr, "Exiting: failed to connect to any daemons.\n"); - exit(1); + if (no_error) + exit(0); + else + exit(1); } if (inputfile) From a94d98ae98ec45e34de287daf4c9d16be3ea62b9 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 17 Aug 2016 00:22:12 +0000 Subject: [PATCH 132/226] BGP: neighbor activate lines for ipv4 unicast are not in the sub context Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12080 --- bgpd/bgpd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1a5270874c..a6265ad8ba 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6727,7 +6727,9 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, { if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) { - vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE); + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s activate%s", + addr, VTY_NEWLINE); } } else From c05795b16b4bcb9de4663f3fc9664a623277d47a Mon Sep 17 00:00:00 2001 From: Sid Khot Date: Wed, 17 Aug 2016 19:36:54 -0700 Subject: [PATCH 133/226] Fix for CM-12450 Ensure quagga logs at startup are sent to syslog (until log configuration is processed) Ticket: CM-12450 Reviewed By: CCR-5112 Testing Done: Manual --- bgpd/bgp_main.c | 4 +++- isisd/isis_main.c | 4 +++- lib/command.c | 4 ++++ ospf6d/ospf6_main.c | 4 +++- ospfd/ospf_main.c | 4 +++- pimd/pim_main.c | 4 +++- ripd/rip_main.c | 4 +++- ripngd/ripng_main.c | 4 +++- watchquagga/watchquagga.c | 2 -- zebra/main.c | 4 +++- 10 files changed, 28 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index a5f066bff0..0d24c9c294 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -419,7 +419,9 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_BGP, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&bgpd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* BGP master init. */ bgp_master_init (); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index f088bc1dec..234e516db5 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -245,7 +245,9 @@ main (int argc, char **argv, char **envp) zlog_default = openzlog (progname, ZLOG_ISIS, 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); zprivs_init (&isisd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME , zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* for reload */ _argc = argc; diff --git a/lib/command.c b/lib/command.c index 2e80eea9e3..10ab066bfb 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3752,6 +3752,10 @@ set_log_file(struct vty *vty, const char *fname, int loglevel) host.logfile = XSTRDUP (MTYPE_HOST, fname); +#if defined(HAVE_CUMULUS) + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) + zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED; +#endif return CMD_SUCCESS; } diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index c989a5a10a..a368b05304 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -321,7 +321,9 @@ main (int argc, char *argv[], char *envp[]) LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&ospf6d_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* initialize zebra libraries */ signal_init (master, array_size(ospf6_signals), ospf6_signals); diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 495ee2fd02..48f39d0099 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -288,7 +288,9 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_OSPF, instance, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&ospfd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* OSPF master init. */ ospf_master_init (); diff --git a/pimd/pim_main.c b/pimd/pim_main.c index b28b3d6242..b65b925fad 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -138,7 +138,9 @@ int main(int argc, char** argv, char** envp) { zlog_default = openzlog(progname, ZLOG_PIM, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&pimd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* this while just reads the options */ while (1) { diff --git a/ripd/rip_main.c b/ripd/rip_main.c index f920e809e2..aa1c4ff4df 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -205,7 +205,9 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_RIP, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&ripd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* Command line option parse. */ while (1) diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index a1c71c8562..f401a43156 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -204,7 +204,9 @@ main (int argc, char **argv) zlog_default = openzlog(progname, ZLOG_RIPNG, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&ripngd_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif while (1) { diff --git a/watchquagga/watchquagga.c b/watchquagga/watchquagga.c index 2a237efb6a..e882653e38 100644 --- a/watchquagga/watchquagga.c +++ b/watchquagga/watchquagga.c @@ -1337,8 +1337,6 @@ main(int argc, char **argv) zlog_default = openzlog(progname, ZLOG_NONE, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); - zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); if (daemon_mode) { diff --git a/zebra/main.c b/zebra/main.c index ab907f83e8..8a9857a04d 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -245,7 +245,9 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_ZEBRA, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zprivs_init (&zserv_privs); - zlog_set_file (NULL, LOG_DEFAULT_FILENAME, zlog_default->default_lvl); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif while (1) { From b892f1ddfe42a620d84b6c245d1997e4b560eea8 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Mon, 18 Jan 2016 10:12:10 +0000 Subject: [PATCH 134/226] *: use an ifindex_t type, defined in lib/if.h, for ifindex values (cherry picked from commit 9099f9b2a66e86f8a90d7fe18f61bd2bb1bc6744) --- bgpd/bgp_attr.h | 2 +- bgpd/bgp_btoa.c | 2 +- bgpd/bgp_network.c | 2 +- bgpd/bgp_zebra.c | 8 ++++---- bgpd/bgp_zebra.h | 4 ++-- bgpd/bgpd.h | 2 +- isisd/isis_route.c | 10 +++++----- isisd/isis_route.h | 4 ++-- isisd/isis_zebra.c | 8 ++++---- lib/if.c | 26 +++++++++++++------------- lib/if.h | 24 +++++++++++++----------- lib/nexthop.h | 2 +- lib/sockopt.c | 16 ++++++++-------- lib/sockopt.h | 8 ++++---- lib/sockunion.c | 2 +- lib/sockunion.h | 3 ++- lib/zclient.c | 2 +- lib/zclient.h | 4 ++-- ospf6d/ospf6_asbr.c | 5 +++-- ospf6d/ospf6_asbr.h | 6 +++--- ospf6d/ospf6_interface.c | 2 +- ospf6d/ospf6_interface.h | 2 +- ospf6d/ospf6_message.c | 4 ++-- ospf6d/ospf6_message.h | 2 +- ospf6d/ospf6_neighbor.h | 2 +- ospf6d/ospf6_network.c | 6 +++--- ospf6d/ospf6_network.h | 6 +++--- ospf6d/ospf6_route.c | 2 +- ospf6d/ospf6_route.h | 4 ++-- ospf6d/ospf6_snmp.c | 12 ++++++------ ospf6d/ospf6_spf.c | 2 +- ospf6d/ospf6_zebra.c | 4 ++-- ospfd/ospf_asbr.c | 2 +- ospfd/ospf_asbr.h | 4 ++-- ospfd/ospf_lsa.c | 2 +- ospfd/ospf_lsa.h | 2 +- ospfd/ospf_network.c | 12 +++++------- ospfd/ospf_network.h | 10 +++++----- ospfd/ospf_packet.c | 2 +- ospfd/ospf_route.h | 2 +- ospfd/ospf_snmp.c | 30 +++++++++++++++--------------- pimd/pim_iface.c | 7 ++++--- pimd/pim_iface.h | 6 +++--- pimd/pim_igmp.c | 8 ++++---- pimd/pim_igmp_join.h | 2 +- pimd/pim_pim.c | 4 ++-- pimd/pim_sock.c | 6 +++--- pimd/pim_sock.h | 6 +++--- pimd/pim_ssmpingd.c | 2 +- pimd/pim_static.c | 8 ++++---- pimd/pim_static.h | 2 +- pimd/pim_zebra.c | 8 ++++---- pimd/pim_zlookup.h | 2 +- pimd/test_igmpv3_join.c | 5 +++-- ripd/rip_interface.c | 4 ++-- ripd/ripd.c | 8 ++++---- ripd/ripd.h | 8 ++++---- ripngd/ripng_zebra.c | 2 +- ripngd/ripngd.c | 8 ++++---- ripngd/ripngd.h | 6 +++--- zebra/kernel_socket.c | 2 +- zebra/rib.h | 27 +++++++++++++-------------- zebra/rt_netlink.c | 2 +- zebra/rt_socket.c | 4 ++-- zebra/rtadv.c | 8 ++++---- zebra/test_main.c | 2 +- zebra/zebra_rib.c | 30 +++++++++++++++--------------- zebra/zebra_routemap.c | 2 +- zebra/zserv.c | 2 +- 69 files changed, 219 insertions(+), 216 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index a279674af2..b8cdfea137 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -131,7 +131,7 @@ struct attr struct in_addr nexthop; u_int32_t med; u_int32_t local_pref; - u_int32_t nh_ifindex; + ifindex_t nh_ifindex; /* Path origin attribute */ u_char origin; diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index 904ae66e10..cd52c94b1f 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -144,7 +144,7 @@ main (int argc, char **argv) size_t len; int source_as; int dest_as; - int ifindex; + ifindex_t ifindex; int family; struct in_addr sip; struct in_addr dip; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 0caada488b..ed1c5600ee 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -579,7 +579,7 @@ bgp_update_source (struct peer *peer) int bgp_connect (struct peer *peer) { - unsigned int ifindex = 0; + ifindex_t ifindex = 0; if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) { diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index ce5d1b498e..81bede0e92 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -856,7 +856,7 @@ if_lookup_by_ipv4_exact (struct in_addr *addr, vrf_id_t vrf_id) #ifdef HAVE_IPV6 struct interface * -if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) +if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *ifnode; struct listnode *cnode; @@ -892,7 +892,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) } struct interface * -if_lookup_by_ipv6_exact (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id) +if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *ifnode; struct listnode *cnode; @@ -1381,7 +1381,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (p->family == AF_INET6 || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { - unsigned int ifindex; + ifindex_t ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; int valid_nh_count = 0; @@ -1527,7 +1527,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = valid_nh_count; - api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf); + api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; api.tag = 0; diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 1f845bd918..af921af82f 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -58,8 +58,8 @@ extern int bgp_redistribute_unreg (struct bgp *, afi_t, int, u_short); extern struct interface *if_lookup_by_ipv4 (struct in_addr *, vrf_id_t); extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t); #ifdef HAVE_IPV6 -extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, unsigned int, vrf_id_t); -extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, unsigned int, vrf_id_t); +extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t); +extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t); #endif /* HAVE_IPV6 */ #endif /* _QUAGGA_BGP_ZEBRA_H */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 991afdf7cc..d9a68599c5 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -583,7 +583,7 @@ struct peer time_t readtime; /* Last read time */ time_t resettime; /* Last reset time */ - unsigned int ifindex; /* ifindex of the BGP connection. */ + ifindex_t ifindex; /* ifindex of the BGP connection. */ char *conf_if; /* neighbor interface config name. */ struct interface *ifp; /* corresponding interface */ char *ifname; /* bind interface name. */ diff --git a/isisd/isis_route.c b/isisd/isis_route.c index e72e0cac7a..67d45c8f10 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -50,7 +50,7 @@ #include "isis_zebra.h" static struct isis_nexthop * -isis_nexthop_create (struct in_addr *ip, unsigned int ifindex) +isis_nexthop_create (struct in_addr *ip, ifindex_t ifindex) { struct listnode *node; struct isis_nexthop *nexthop; @@ -91,7 +91,7 @@ isis_nexthop_delete (struct isis_nexthop *nexthop) static int nexthoplookup (struct list *nexthops, struct in_addr *ip, - unsigned int ifindex) + ifindex_t ifindex) { struct listnode *node; struct isis_nexthop *nh; @@ -130,7 +130,7 @@ nexthops_print (struct list *nhs) #ifdef HAVE_IPV6 static struct isis_nexthop6 * -isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) +isis_nexthop6_new (struct in6_addr *ip6, ifindex_t ifindex) { struct isis_nexthop6 *nexthop6; @@ -144,7 +144,7 @@ isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) } static struct isis_nexthop6 * -isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex) +isis_nexthop6_create (struct in6_addr *ip6, ifindex_t ifindex) { struct listnode *node; struct isis_nexthop6 *nexthop6; @@ -181,7 +181,7 @@ isis_nexthop6_delete (struct isis_nexthop6 *nexthop6) static int nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6, - unsigned int ifindex) + ifindex_t ifindex) { struct listnode *node; struct isis_nexthop6 *nh6; diff --git a/isisd/isis_route.h b/isisd/isis_route.h index 5adea2293b..0d2379cbe8 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -28,7 +28,7 @@ #ifdef HAVE_IPV6 struct isis_nexthop6 { - unsigned int ifindex; + ifindex_t ifindex; struct in6_addr ip6; struct in6_addr router_address6; unsigned int lock; @@ -37,7 +37,7 @@ struct isis_nexthop6 struct isis_nexthop { - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ip; struct in_addr router_address; unsigned int lock; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 125a2f63d3..81f9d86930 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -333,7 +333,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix, { struct zapi_ipv6 api; struct in6_addr **nexthop_list; - unsigned int *ifindex_list; + ifindex_t *ifindex_list; struct isis_nexthop6 *nexthop6; int i, size; struct listnode *node; @@ -370,7 +370,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix, /* allocate memory for ifindex_list */ size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size); + ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); if (!ifindex_list) { zlog_err ("isis_zebra_add_route_ipv6: out of memory!"); @@ -420,7 +420,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix, { struct zapi_ipv6 api; struct in6_addr **nexthop_list; - unsigned int *ifindex_list; + ifindex_t *ifindex_list; struct isis_nexthop6 *nexthop6; int i, size; struct listnode *node; @@ -451,7 +451,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix, /* allocate memory for ifindex_list */ size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size); + ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); if (!ifindex_list) { zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); diff --git a/lib/if.c b/lib/if.c index 8f1461326f..2c63c985dc 100644 --- a/lib/if.c +++ b/lib/if.c @@ -226,41 +226,41 @@ if_add_hook (int type, int (*func)(struct interface *ifp)) /* Interface existance check by index. */ struct interface * -if_lookup_by_index_vrf (unsigned int index, vrf_id_t vrf_id) +if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { - if (ifp->ifindex == index) + if (ifp->ifindex == ifindex) return ifp; } return NULL; } struct interface * -if_lookup_by_index (unsigned int index) +if_lookup_by_index (ifindex_t ifindex) { - return if_lookup_by_index_vrf (index, VRF_DEFAULT); + return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); } const char * -ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id) +ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_index_vrf (index, vrf_id)) != NULL) ? + return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ? ifp->name : "unknown"; } const char * -ifindex2ifname (unsigned int index) +ifindex2ifname (ifindex_t ifindex) { - return ifindex2ifname_vrf (index, VRF_DEFAULT); + return ifindex2ifname_vrf (ifindex, VRF_DEFAULT); } -unsigned int +ifindex_t ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) { struct interface *ifp; @@ -269,7 +269,7 @@ ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -unsigned int +ifindex_t ifname2ifindex (const char *name) { return ifname2ifindex_vrf (name, VRF_DEFAULT); @@ -1167,7 +1167,7 @@ connected_add_by_prefix (struct interface *ifp, struct prefix *p, } #ifndef HAVE_IF_NAMETOINDEX -unsigned int +ifindex_t if_nametoindex (const char *name) { struct interface *ifp; @@ -1179,7 +1179,7 @@ if_nametoindex (const char *name) #ifndef HAVE_IF_INDEXTONAME char * -if_indextoname (unsigned int ifindex, char *name) +if_indextoname (ifindex_t ifindex, char *name) { struct interface *ifp; @@ -1244,7 +1244,7 @@ ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) /* Lookup interface by interface's IP address or interface index. */ static struct interface * -ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) +ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) { struct prefix_ipv4 p; struct route_node *rn; diff --git a/lib/if.h b/lib/if.h index 4ec85bc841..35d91f0cfa 100644 --- a/lib/if.h +++ b/lib/if.h @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _ZEBRA_IF_H #define _ZEBRA_IF_H +#include "zebra.h" #include "linklist.h" /* @@ -36,6 +37,8 @@ Boston, MA 02111-1307, USA. */ #define INTERFACE_NAMSIZ 20 #define INTERFACE_HWADDR_MAX 20 +typedef signed int ifindex_t; + #ifdef HAVE_PROC_NET_DEV struct if_stats { @@ -82,9 +85,9 @@ struct interface /* Interface index (should be IFINDEX_INTERNAL for non-kernel or deleted interfaces). */ - unsigned int ifindex; + ifindex_t ifindex; #define IFINDEX_INTERNAL 0 -#define IFINDEX_DELETED UINT_MAX +#define IFINDEX_DELETED INT_MAX /* Zebra internal interface status */ u_char status; @@ -264,7 +267,7 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); extern struct interface *if_create (const char *name, int namelen); -extern struct interface *if_lookup_by_index (unsigned int); +extern struct interface *if_lookup_by_index (ifindex_t); extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct interface *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); @@ -273,8 +276,7 @@ extern void if_update_vrf (struct interface *, const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id); -extern struct interface *if_lookup_by_index_vrf (unsigned int, - vrf_id_t vrf_id); +extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id); extern struct interface *if_lookup_address_vrf (void *matchaddr, int family, @@ -332,14 +334,14 @@ extern const char *if_flag_dump(unsigned long); /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ -extern const char *ifindex2ifname (unsigned int); -extern const char *ifindex2ifname_vrf (unsigned int, vrf_id_t vrf_id); +extern const char *ifindex2ifname (ifindex_t); +extern const char *ifindex2ifname_vrf (ifindex_t, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must make a system call. */ -extern unsigned int ifname2ifindex(const char *ifname); -extern unsigned int ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); +extern ifindex_t ifname2ifindex(const char *ifname); +extern ifindex_t ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new (void); @@ -359,10 +361,10 @@ extern void nbr_connected_free (struct nbr_connected *); struct nbr_connected *nbr_connected_check (struct interface *, struct prefix *); #ifndef HAVE_IF_NAMETOINDEX -extern unsigned int if_nametoindex (const char *); +extern ifindex_t if_nametoindex (const char *); #endif #ifndef HAVE_IF_INDEXTONAME -extern char *if_indextoname (unsigned int, char *); +extern char *if_indextoname (ifindex_t, char *); #endif /* Exported variables. */ diff --git a/lib/nexthop.h b/lib/nexthop.h index eb9b27ea9e..4445c4ad27 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -48,7 +48,7 @@ struct nexthop struct nexthop *prev; /* Interface index. */ - unsigned int ifindex; + ifindex_t ifindex; enum nexthop_types_t type; diff --git a/lib/sockopt.c b/lib/sockopt.c index d8204936f9..31b2edbacf 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -221,7 +221,7 @@ setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, unsigned int mcast_addr, - unsigned int ifindex) + ifindex_t ifindex) { #ifdef HAVE_RFC3678 struct group_req gr; @@ -322,7 +322,7 @@ setsockopt_ipv4_multicast(int sock, */ int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, - unsigned int ifindex) + ifindex_t ifindex) { #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX @@ -352,7 +352,7 @@ setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, } static int -setsockopt_ipv4_ifindex (int sock, int val) +setsockopt_ipv4_ifindex (int sock, ifindex_t val) { int ret; @@ -388,7 +388,7 @@ setsockopt_ipv4_tos(int sock, int tos) int -setsockopt_ifindex (int af, int sock, int val) +setsockopt_ifindex (int af, int sock, ifindex_t val) { int ret = -1; @@ -415,11 +415,11 @@ setsockopt_ifindex (int af, int sock, int val) * Returns the interface index (small integer >= 1) if it can be * determined, or else 0. */ -static int +static ifindex_t getsockopt_ipv4_ifindex (struct msghdr *msgh) { /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ - int ifindex = -1; + ifindex_t ifindex = -1; #if defined(IP_PKTINFO) /* Linux pktinfo based ifindex retrieval */ @@ -439,7 +439,7 @@ getsockopt_ipv4_ifindex (struct msghdr *msgh) struct sockaddr_dl *sdl; #else /* SUNOS_5 uses an integer with the index. */ - int *ifindex_p; + ifindex_t *ifindex_p; #endif /* SUNOS_5 */ #ifndef SUNOS_5 @@ -480,7 +480,7 @@ getsockopt_ipv4_ifindex (struct msghdr *msgh) } /* return ifindex, 0 if none found */ -int +ifindex_t getsockopt_ifindex (int af, struct msghdr *msgh) { switch (af) diff --git a/lib/sockopt.h b/lib/sockopt.h index a597314c3d..d67b510b66 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -84,16 +84,16 @@ extern int setsockopt_ipv6_tclass (int, int); ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, - unsigned int ifindex); + ifindex_t ifindex); extern int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, unsigned int mcast_addr, - unsigned int ifindex); + ifindex_t ifindex); extern int setsockopt_ipv4_tos(int sock, int tos); /* Ask for, and get, ifindex, by whatever method is supported. */ -extern int setsockopt_ifindex (int, int, int); -extern int getsockopt_ifindex (int, struct msghdr *); +extern int setsockopt_ifindex (int, int, ifindex_t); +extern ifindex_t getsockopt_ifindex (int, struct msghdr *); /* swab the fields in iph between the host order and system order expected * for IP_HDRINCL. diff --git a/lib/sockunion.c b/lib/sockunion.c index b5a2eb954a..9184e500fc 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -291,7 +291,7 @@ sockunion_sizeof (const union sockunion *su) 1 : connect is in progress */ enum connect_result sockunion_connect (int fd, const union sockunion *peersu, unsigned short port, - unsigned int ifindex) + ifindex_t ifindex) { int ret; int val; diff --git a/lib/sockunion.h b/lib/sockunion.h index a33051ae57..105b11a24c 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -24,6 +24,7 @@ #define _ZEBRA_SOCKUNION_H #include "privs.h" +#include "if.h" union sockunion { @@ -95,7 +96,7 @@ extern int sockunion_socket (const union sockunion *su); extern const char *inet_sutop (const union sockunion *su, char *str); extern enum connect_result sockunion_connect (int fd, const union sockunion *su, unsigned short port, - unsigned int); + ifindex_t); extern union sockunion *sockunion_getsockname (int); extern union sockunion *sockunion_getpeername (int); extern union sockunion *sockunion_dup (const union sockunion *); diff --git a/lib/zclient.c b/lib/zclient.c index ef9516c912..a28db083cb 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1133,7 +1133,7 @@ memconstant(const void *s, int c, size_t n) struct connected * zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) { - unsigned int ifindex; + ifindex_t ifindex; struct interface *ifp; struct connected *ifc; struct prefix p, d; diff --git a/lib/zclient.h b/lib/zclient.h index f30190c1b4..8926bbbe63 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -146,7 +146,7 @@ struct zapi_ipv4 struct in_addr **nexthop; u_char ifindex_num; - unsigned int *ifindex; + ifindex_t *ifindex; u_char distance; @@ -229,7 +229,7 @@ struct zapi_ipv6 struct in6_addr **nexthop; u_char ifindex_num; - unsigned int *ifindex; + ifindex_t *ifindex; u_char distance; diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 1207419e58..208d3b8c4c 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -426,7 +426,7 @@ ospf6_asbr_send_externals_to_area (struct ospf6_area *oa) } void -ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, +ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix, u_int nexthop_num, struct in6_addr *nexthop) { int ret; @@ -575,7 +575,8 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, } void -ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix) +ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, + struct prefix *prefix) { struct ospf6_route *match; struct ospf6_external_info *info = NULL; diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index 90befdc0dd..645e8fd9cf 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -49,7 +49,7 @@ struct ospf6_external_info struct in6_addr forwarding; /* u_int32_t tag; */ - unsigned int ifindex; + ifindex_t ifindex; }; /* AS-External-LSA */ @@ -79,11 +79,11 @@ extern void ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry); extern void ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry); extern int ospf6_asbr_is_asbr (struct ospf6 *o); -extern void ospf6_asbr_redistribute_add (int type, int ifindex, +extern void ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix, u_int nexthop_num, struct in6_addr *nexthop); -extern void ospf6_asbr_redistribute_remove (int type, int ifindex, +extern void ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, struct prefix *prefix); extern int ospf6_redistribute_config_write (struct vty *vty); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 720a3e0e69..f24ec46da7 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -61,7 +61,7 @@ const char *ospf6_interface_state_str[] = }; struct ospf6_interface * -ospf6_interface_lookup_by_ifindex (int ifindex) +ospf6_interface_lookup_by_ifindex (ifindex_t ifindex) { struct ospf6_interface *oi; struct interface *ifp; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 5e6b455682..3e09bfb930 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -152,7 +152,7 @@ extern const char *ospf6_interface_state_str[]; /* Function Prototypes */ -extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex (int); +extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex (ifindex_t); extern struct ospf6_interface *ospf6_interface_create (struct interface *); extern void ospf6_interface_delete (struct ospf6_interface *); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index fe57f2f423..b0e94288b4 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -290,7 +290,7 @@ ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); /* Neighbor ifindex check */ - if (on->ifindex != ntohl (hello->interface_id)) + if (on->ifindex != (ifindex_t)ntohl (hello->interface_id)) { on->ifindex = ntohl (hello->interface_id); neighbor_ifindex_change++; @@ -1525,7 +1525,7 @@ ospf6_receive (struct thread *thread) unsigned int len; char srcname[64], dstname[64]; struct in6_addr src, dst; - unsigned int ifindex; + ifindex_t ifindex; struct iovec iovector[2]; struct ospf6_interface *oi; struct ospf6_header *oh; diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index b085a9673b..4a9e0c7a66 100644 --- a/ospf6d/ospf6_message.h +++ b/ospf6d/ospf6_message.h @@ -64,7 +64,7 @@ struct ospf6_header #define OSPF6_HELLO_MIN_SIZE 20U struct ospf6_hello { - u_int32_t interface_id; + ifindex_t interface_id; u_char priority; u_char options[3]; u_int16_t hello_interval; diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index fad7fd578a..f9e197e99b 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -53,7 +53,7 @@ struct ospf6_neighbor u_int32_t router_id; /* Neighbor Interface ID */ - u_int32_t ifindex; + ifindex_t ifindex; /* Router Priority of this neighbor */ u_char priority; diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 5e254661f1..2227d03477 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -113,7 +113,7 @@ ospf6_serv_sock (void) /* ospf6 set socket option */ int -ospf6_sso (u_int ifindex, struct in6_addr *group, int option) +ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option) { struct ipv6_mreq mreq6; int ret; @@ -193,7 +193,7 @@ iov_totallen (struct iovec *iov) int ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, - unsigned int *ifindex, struct iovec *message) + ifindex_t *ifindex, struct iovec *message) { int retval; struct msghdr smsghdr; @@ -255,7 +255,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, int ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst, - unsigned int *ifindex, struct iovec *message) + ifindex_t *ifindex, struct iovec *message) { int retval; struct msghdr rmsghdr; diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h index 2aeafe5041..4fa2839519 100644 --- a/ospf6d/ospf6_network.h +++ b/ospf6d/ospf6_network.h @@ -29,12 +29,12 @@ extern struct in6_addr allspfrouters6; extern struct in6_addr alldrouters6; extern int ospf6_serv_sock (void); -extern int ospf6_sso (u_int ifindex, struct in6_addr *group, int option); +extern int ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option); extern int ospf6_sendmsg (struct in6_addr *, struct in6_addr *, - unsigned int *, struct iovec *); + ifindex_t *, struct iovec *); extern int ospf6_recvmsg (struct in6_addr *, struct in6_addr *, - unsigned int *, struct iovec *); + ifindex_t *, struct iovec *); #endif /* OSPF6_NETWORK_H */ diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 0a98c8f082..5172eee48d 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -331,7 +331,7 @@ ospf6_add_nexthop (struct list *nh_list, int ifindex, void ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - unsigned int *ifindexes, + ifindex_t *ifindexes, struct in6_addr **nexthop_addr, int entries) { diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e783b72d8e..610b0970b0 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -41,7 +41,7 @@ extern unsigned char conf_debug_ospf6_route; struct ospf6_nexthop { /* Interface index */ - unsigned int ifindex; + ifindex_t ifindex; /* IP address, if any */ struct in6_addr address; @@ -278,7 +278,7 @@ extern int ospf6_num_nexthops (struct list *nh_list); extern int ospf6_route_cmp_nexthops (struct ospf6_route *a, struct ospf6_route *b); extern void ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - unsigned int *ifindices, + ifindex_t *ifindices, struct in6_addr **addr, int entries); extern int ospf6_route_get_first_nh_index (struct ospf6_route *route); diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index cf1630bbc9..382cf62f72 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -625,7 +625,7 @@ ospfv3WwLsdbEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct ospf6_lsa *lsa = NULL; - u_int32_t ifindex, area_id, id, instid, adv_router; + ifindex_t ifindex, area_id, id, instid, adv_router; u_int16_t type; int len; oid *offset; @@ -837,7 +837,8 @@ static u_char * ospfv3IfEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex, instid; + ifindex_t ifindex = 0; + unsigned int instid = 0; struct ospf6_interface *oi = NULL; struct ospf6_lsa *lsa = NULL; struct interface *iif; @@ -851,8 +852,6 @@ ospfv3IfEntry (struct variable *v, oid *name, size_t *length, == MATCH_FAILED) return NULL; - ifindex = instid = 0; - /* Check OSPFv3 instance. */ if (ospf6 == NULL) return NULL; @@ -990,7 +989,8 @@ static u_char * ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex, instid, rtrid; + ifindex_t ifindex = 0; + unsigned int instid, rtrid; struct ospf6_interface *oi = NULL; struct ospf6_neighbor *on = NULL; struct interface *iif; @@ -1003,7 +1003,7 @@ ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, == MATCH_FAILED) return NULL; - ifindex = instid = rtrid = 0; + instid = rtrid = 0; /* Check OSPFv3 instance. */ if (ospf6 == NULL) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index ab1213ebb6..957988b53d 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -266,7 +266,7 @@ ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, caddr_t lsdesc) { int i; - unsigned int ifindex; + ifindex_t ifindex; struct ospf6_interface *oi; u_int16_t type; u_int32_t adv_router; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 0395b082da..77ea01e53d 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -377,7 +377,7 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request) char buf[PREFIX2STR_BUFFER]; int nhcount; struct in6_addr **nexthops; - unsigned int *ifindexes; + ifindex_t *ifindexes; int ret = 0; struct prefix_ipv6 *dest; @@ -443,7 +443,7 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request) /* allocate memory for ifindex_list */ ifindexes = XCALLOC (MTYPE_OSPF6_OTHER, - nhcount * sizeof (unsigned int)); + nhcount * sizeof (ifindex_t)); if (ifindexes == NULL) { zlog_warn ("Can't send route to zebra: malloc failed"); diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index ddb26dd543..21f99af128 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -136,7 +136,7 @@ ospf_route_map_set_compare (struct route_map_set_values *values1, /* Add an External info for AS-external-LSA. */ struct external_info * ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, - unsigned int ifindex, struct in_addr nexthop, + ifindex_t ifindex, struct in_addr nexthop, u_short tag) { struct external_info *new; diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index ade671013a..25a53aad4f 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -41,7 +41,7 @@ struct external_info struct prefix_ipv4 p; /* Interface index. */ - unsigned int ifindex; + ifindex_t ifindex; /* Nexthop address. */ struct in_addr nexthop; @@ -63,7 +63,7 @@ extern int ospf_route_map_set_compare (struct route_map_set_values *, struct route_map_set_values *); extern struct external_info *ospf_external_info_add (u_char, u_short, struct prefix_ipv4, - unsigned int, + ifindex_t, struct in_addr, u_short); extern void ospf_external_info_delete (u_char, u_short, struct prefix_ipv4); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 68a3946b3a..b96ed452c1 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2251,7 +2251,7 @@ ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p) void ospf_external_lsa_flush (struct ospf *ospf, u_char type, struct prefix_ipv4 *p, - unsigned int ifindex /*, struct in_addr nexthop */) + ifindex_t ifindex /*, struct in_addr nexthop */) { struct ospf_lsa *lsa; diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index b3d72109d6..28ecc9d4d6 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -277,7 +277,7 @@ extern struct ospf_lsa *ospf_lsa_install (struct ospf *, extern void ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p); extern void ospf_external_lsa_flush (struct ospf *, u_char, struct prefix_ipv4 *, - unsigned int /* , struct in_addr nexthop */); + ifindex_t /* , struct in_addr nexthop */); extern struct in_addr ospf_get_ip_from_ifp (struct ospf_interface *); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 9f516d7390..6caa38d68b 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -48,7 +48,7 @@ extern struct zebra_privs_t ospfd_privs; /* Join to the OSPF ALL SPF ROUTERS multicast group. */ int ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; @@ -69,7 +69,7 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, int ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; @@ -89,8 +89,7 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, /* Join to the OSPF ALL Designated ROUTERS multicast group. */ int -ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int - ifindex) +ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) { int ret; @@ -110,8 +109,7 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int } int -ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int - ifindex) +ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) { int ret; @@ -130,7 +128,7 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int } int -ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex) +ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) { u_char val; int ret, len; diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index e0a5c69d5c..8257adb4af 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -25,14 +25,14 @@ /* Prototypes. */ extern int ospf_if_add_allspfrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_add_alldrouters (struct ospf *, struct prefix *, - unsigned int); + ifindex_t); extern int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, - unsigned int); -extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, unsigned int); + ifindex_t); +extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, ifindex_t); extern int ospf_sock_init (void); extern void ospf_adjust_sndbuflen (struct ospf *, unsigned int); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 2df1596ee3..e6014a14c6 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2143,7 +2143,7 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) int ret; struct ip *iph; u_int16_t ip_len; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; struct iovec iov; /* Header and data both require alignment. */ char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index d0b121db38..6b6d9f1fab 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -39,7 +39,7 @@ struct ospf_path { struct in_addr nexthop; struct in_addr adv_router; - unsigned int ifindex; + ifindex_t ifindex; unsigned char unnumbered; }; diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index bedcb559bf..676756d6d9 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -1413,7 +1413,7 @@ static struct list *ospf_snmp_iflist; struct ospf_snmp_if { struct in_addr addr; - unsigned int ifindex; + ifindex_t ifindex; struct interface *ifp; }; @@ -1455,7 +1455,7 @@ ospf_snmp_if_update (struct interface *ifp) struct prefix *p; struct ospf_snmp_if *osif; struct in_addr *addr; - unsigned int ifindex; + ifindex_t ifindex; ospf_snmp_if_delete (ifp); @@ -1530,7 +1530,7 @@ ospf_snmp_is_if_have_addr (struct interface *ifp) } static struct ospf_interface * -ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex) +ospf_snmp_if_lookup (struct in_addr *ifaddr, ifindex_t *ifindex) { struct listnode *node; struct ospf_snmp_if *osif; @@ -1554,8 +1554,8 @@ ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex) } static struct ospf_interface * -ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex, - int ifaddr_next, int ifindex_next) +ospf_snmp_if_lookup_next (struct in_addr *ifaddr, ifindex_t *ifindex, + int ifaddr_next, ifindex_t ifindex_next) { struct ospf_snmp_if *osif; struct listnode *nn; @@ -1638,11 +1638,11 @@ ospf_snmp_iftype (struct interface *ifp) static struct ospf_interface * ospfIfLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, unsigned int *ifindex, int exact) + struct in_addr *ifaddr, ifindex_t *ifindex, int exact) { unsigned int len; int ifaddr_next = 0; - int ifindex_next = 0; + ifindex_t ifindex_next = 0; struct ospf_interface *oi; oid *offset; @@ -1694,7 +1694,7 @@ static u_char * ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ifaddr; struct ospf_interface *oi; struct ospf *ospf; @@ -1802,11 +1802,11 @@ ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact, static struct ospf_interface * ospfIfMetricLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, unsigned int *ifindex, int exact) + struct in_addr *ifaddr, ifindex_t *ifindex, int exact) { unsigned int len; int ifaddr_next = 0; - int ifindex_next = 0; + ifindex_t ifindex_next = 0; struct ospf_interface *oi; oid *offset; int metric; @@ -1866,7 +1866,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { /* Currently we support metric 1 only. */ - unsigned int ifindex; + ifindex_t ifindex; struct in_addr ifaddr; struct ospf_interface *oi; struct ospf *ospf; @@ -2133,7 +2133,7 @@ ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact, static struct ospf_neighbor * ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, - unsigned int *ifindex) + ifindex_t *ifindex) { struct listnode *node, *nnode; struct ospf_interface *oi; @@ -2161,7 +2161,7 @@ ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, } static struct ospf_neighbor * -ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, +ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, ifindex_t *ifindex, int first) { struct listnode *nn; @@ -2208,7 +2208,7 @@ ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, static struct ospf_neighbor * ospfNbrLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *nbr_addr, unsigned int *ifindex, int exact) + struct in_addr *nbr_addr, ifindex_t *ifindex, int exact) { unsigned int len; int first; @@ -2303,7 +2303,7 @@ ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct in_addr nbr_addr; - unsigned int ifindex; + ifindex_t ifindex; struct ospf_neighbor *nbr; struct ospf_interface *oi; diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 3c60275027..a8a1d08805 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -772,7 +772,7 @@ void pim_if_del_vif_all() } } -struct interface *pim_if_find_by_vif_index(int vif_index) +struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) { struct listnode *ifnode; struct interface *ifp; @@ -784,6 +784,7 @@ struct interface *pim_if_find_by_vif_index(int vif_index) if (ifp->info) { struct pim_interface *pim_ifp; pim_ifp = ifp->info; + if (vif_index == pim_ifp->mroute_vif_index) return ifp; } @@ -795,7 +796,7 @@ struct interface *pim_if_find_by_vif_index(int vif_index) /* pim_if_add_vif() uses ifindex as vif_index */ -int pim_if_find_vifindex_by_ifindex(int ifindex) +int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) { struct pim_interface *pim_ifp; struct interface *ifp; @@ -954,7 +955,7 @@ static struct igmp_join *igmp_join_find(struct list *join_list, } static int igmp_join_sock(const char *ifname, - int ifindex, + ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 15489f81fa..790afabea1 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -63,7 +63,7 @@ enum pim_interface_type { struct pim_interface { enum pim_interface_type itype; uint32_t options; /* bit vector */ - int mroute_vif_index; + ifindex_t mroute_vif_index; struct in_addr primary_address; /* remember addr to detect change */ int igmp_default_robustness_variable; /* IGMPv3 QRV */ @@ -133,8 +133,8 @@ int pim_if_del_vif(struct interface *ifp); void pim_if_add_vif_all(void); void pim_if_del_vif_all(void); -struct interface *pim_if_find_by_vif_index(int vif_index); -int pim_if_find_vifindex_by_ifindex(int ifindex); +struct interface *pim_if_find_by_vif_index(ifindex_t vif_index); +int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex); int pim_if_lan_delay_enabled(struct interface *ifp); uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 440d648723..3b63b10e0d 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -46,7 +46,7 @@ static void group_timer_off(struct igmp_group *group); -static int igmp_sock_open(struct in_addr ifaddr, int ifindex, uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim_options) { int fd; int join = 0; @@ -971,7 +971,7 @@ static int pim_igmp_read(struct thread *t) socklen_t tolen = sizeof(to); uint8_t buf[PIM_IGMP_BUFSIZE_READ]; int len; - int ifindex = -1; + ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); @@ -1009,7 +1009,7 @@ static int pim_igmp_read(struct thread *t) #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ - if (ifindex != (int) igmp->interface->ifindex) { + if (ifindex != igmp->interface->ifindex) { char from_str[100]; char to_str[100]; struct interface *ifp; @@ -1021,7 +1021,7 @@ static int pim_igmp_read(struct thread *t) ifp = if_lookup_by_index(ifindex); if (ifp) { - zassert(ifindex == (int) ifp->ifindex); + zassert(ifindex == ifp->ifindex); } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 95519ff974..1700276de8 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -39,7 +39,7 @@ struct group_source_req }; #endif -static int pim_igmp_join_source(int fd, int ifindex, +static int pim_igmp_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index eedbc116d8..0dfd39cd16 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -278,7 +278,7 @@ static int pim_sock_read(struct thread *t) socklen_t tolen = sizeof(to); uint8_t buf[PIM_PIM_BUFSIZE_READ]; int len; - int ifindex = -1; + ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); @@ -386,7 +386,7 @@ static void pim_sock_read_on(struct interface *ifp) pim_ifp->pim_sock_fd); } -static int pim_sock_open(struct in_addr ifaddr, int ifindex) +static int pim_sock_open(struct in_addr ifaddr, ifindex_t ifindex) { int fd; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index e04cd41575..a024e3ae01 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -213,7 +213,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) } int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, int ifindex) + struct in_addr ifaddr, ifindex_t ifindex) { int ret; @@ -261,7 +261,7 @@ int pim_socket_join(int fd, struct in_addr group, return ret; } -int pim_socket_join_source(int fd, int ifindex, +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr, const char *ifname) @@ -285,7 +285,7 @@ int pim_socket_join_source(int fd, int ifindex, int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, - int *ifindex) + ifindex_t *ifindex) { struct msghdr msgh; struct cmsghdr *cmsg; diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 9a9b64a4a3..f0a1600818 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -41,15 +41,15 @@ int pim_socket_raw(int protocol); int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop); int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, int ifindex); -int pim_socket_join_source(int fd, int ifindex, + struct in_addr ifaddr, ifindex_t ifindex); +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr, const char *ifname); int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, - int *ifindex); + ifindex_t *ifindex); int pim_socket_mcastloop_get(int fd); diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index d564bf57bc..fe88eba271 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -250,7 +250,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) struct sockaddr_in to; socklen_t fromlen = sizeof(from); socklen_t tolen = sizeof(to); - int ifindex = -1; + ifindex_t ifindex = -1; uint8_t buf[1000]; int len; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 1931f1ee6c..c1154dc088 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -85,8 +85,8 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr struct static_route *original_s_route = 0; struct pim_interface *pim_iif = iif ? iif->info : 0; struct pim_interface *pim_oif = oif ? oif->info : 0; - unsigned int iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - unsigned int oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; if (!iif_index || !oif_index) { zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", @@ -229,8 +229,8 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr struct static_route *s_route = 0; struct pim_interface *pim_iif = iif ? iif->info : 0; struct pim_interface *pim_oif = oif ? oif->info : 0; - unsigned int iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - unsigned int oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; if (!iif_index || !oif_index) { zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", diff --git a/pimd/pim_static.h b/pimd/pim_static.h index ff89fb150e..07d31d59b7 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -33,7 +33,7 @@ struct static_route { struct in_addr source; struct channel_oil c_oil; - unsigned int iif; + ifindex_t iif; unsigned char oif_ttls[MAXVIFS]; }; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index efab00e227..d357e5cc83 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -533,7 +533,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, { struct stream *s; struct zapi_ipv4 api; - unsigned long ifindex; + ifindex_t ifindex; struct in_addr nexthop; struct prefix_ipv4 p; int min_len = 4; @@ -620,7 +620,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: add %s %s/%d " - "nexthop %s ifindex %ld metric%s %u distance%s %u", + "nexthop %s ifindex %d metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), @@ -638,7 +638,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: delete %s %s/%d " - "nexthop %s ifindex %ld metric%s %u distance%s %u", + "nexthop %s ifindex %d metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), @@ -763,7 +763,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; int num_ifindex; int vif_index; - int first_ifindex; + ifindex_t first_ifindex; num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 1f184942ca..f2be6d4fa0 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -31,7 +31,7 @@ struct pim_zlookup_nexthop { struct in_addr nexthop_addr; - int ifindex; + ifindex_t ifindex; uint32_t route_metric; uint8_t protocol_distance; }; diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index 7fcf38bcec..5c4574024b 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -32,6 +32,7 @@ #include #include +#include "if.h" #include "pim_igmp_join.h" const char *prog_name = 0; @@ -39,7 +40,7 @@ const char *prog_name = 0; static int iface_solve_index(const char *ifname) { struct if_nameindex *ini; - int ifindex = -1; + ifindex_t ifindex = -1; int i; if (!ifname) @@ -79,7 +80,7 @@ int main(int argc, const char *argv[]) const char *ifname; const char *group; const char *source; - int ifindex; + ifindex_t ifindex; int result; int fd; diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 4499966ad0..09b35d00b9 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -74,7 +74,7 @@ static int ipv4_multicast_join (int sock, struct in_addr group, struct in_addr ifa, - unsigned int ifindex) + ifindex_t ifindex) { int ret; @@ -96,7 +96,7 @@ static int ipv4_multicast_leave (int sock, struct in_addr group, struct in_addr ifa, - unsigned int ifindex) + ifindex_t ifindex) { int ret; diff --git a/ripd/ripd.c b/ripd/ripd.c index 42f1015453..3a8cd80e7a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1579,7 +1579,7 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, /* Add redistributed route to RIP table. */ void rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, - unsigned int ifindex, struct in_addr *nexthop, + ifindex_t ifindex, struct in_addr *nexthop, unsigned int metric, unsigned char distance) { int ret; @@ -1653,7 +1653,7 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, /* Delete redistributed route from RIP table. */ void rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, - unsigned int ifindex) + ifindex_t ifindex) { int ret; struct route_node *rp; @@ -1795,7 +1795,7 @@ setsockopt_pktinfo (int sock) /* Read RIP packet by recvmsg function. */ int rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from, - int *ifindex) + ifindex_t *ifindex) { int ret; struct msghdr msg; @@ -1836,7 +1836,7 @@ rip_read_new (struct thread *t) int sock; char buf[RIP_PACKET_MAXSIZ]; struct sockaddr_in from; - unsigned int ifindex; + ifindex_t ifindex; /* Fetch socket then register myself. */ sock = THREAD_FD (t); diff --git a/ripd/ripd.h b/ripd/ripd.h index fe9e521d88..d01d0b6bbe 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -198,7 +198,7 @@ struct rip_info struct in_addr from; /* Which interface does this route come from. */ - unsigned int ifindex; + ifindex_t ifindex; /* Metric of this route. */ u_int32_t metric; @@ -224,7 +224,7 @@ struct rip_info u_char metric_set; u_int32_t metric_out; u_short tag_out; - unsigned int ifindex_out; + ifindex_t ifindex_out; struct route_node *rp; @@ -400,9 +400,9 @@ extern int rip_request_send (struct sockaddr_in *, struct interface *, u_char, extern int rip_neighbor_lookup (struct sockaddr_in *); extern int rip_redistribute_check (int); -extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, unsigned int, +extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, ifindex_t, struct in_addr *, unsigned int, unsigned char); -extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int); +extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, ifindex_t); extern void rip_redistribute_withdraw (int); extern void rip_zebra_ipv4_add (struct route_node *); extern void rip_zebra_ipv4_delete (struct route_node *); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index ecfe2d5154..d8667cb68c 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -42,7 +42,7 @@ static void ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) { static struct in6_addr **nexthops = NULL; - static unsigned int *ifindexes = NULL; + static ifindex_t *ifindexes = NULL; static unsigned int nexthops_len = 0; struct list *list = (struct list *)rp->info; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index b786c6f938..2858bb6462 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -229,7 +229,7 @@ ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, /* Receive UDP RIPng packet from socket. */ static int ripng_recv_packet (int sock, u_char *buf, int bufsize, - struct sockaddr_in6 *from, unsigned int *ifindex, + struct sockaddr_in6 *from, ifindex_t *ifindex, int *hoplimit) { int ret; @@ -973,7 +973,7 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, /* Add redistributed route to RIPng table. */ void ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, - unsigned int ifindex, struct in6_addr *nexthop) + ifindex_t ifindex, struct in6_addr *nexthop) { struct route_node *rp; struct ripng_info *rinfo = NULL, newinfo; @@ -1043,7 +1043,7 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, /* Delete redistributed route to RIPng table. */ void ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, - unsigned int ifindex) + ifindex_t ifindex) { struct route_node *rp; struct ripng_info *rinfo; @@ -1361,7 +1361,7 @@ ripng_read (struct thread *thread) int sock; struct sockaddr_in6 from; struct ripng_packet *packet; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; struct interface *ifp; int hoplimit = -1; diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 1496de08bf..b87b927f48 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -176,7 +176,7 @@ struct ripng_info struct in6_addr from; /* Which interface does this route come from. */ - unsigned int ifindex; + ifindex_t ifindex; /* Metric of this route. */ u_char metric; @@ -381,9 +381,9 @@ extern void ripng_info_free (struct ripng_info *rinfo); extern void ripng_event (enum ripng_event, int); extern int ripng_request (struct interface *ifp); extern void ripng_redistribute_add (int, int, struct prefix_ipv6 *, - unsigned int, struct in6_addr *); + ifindex_t, struct in6_addr *); extern void ripng_redistribute_delete (int, int, struct prefix_ipv6 *, - unsigned int); + ifindex_t); extern void ripng_redistribute_withdraw (int type); extern void ripng_distribute_update_interface (struct interface *); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 23224dc241..638062d5d6 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -988,7 +988,7 @@ rtm_read (struct rt_msghdr *rtm) if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) return; struct prefix_ipv6 p; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; p.family = AF_INET6; p.prefix = dest.sin6.sin6_addr; diff --git a/zebra/rib.h b/zebra/rib.h index 5e0bce4461..291ee0b714 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -203,7 +203,7 @@ struct static_route * STATIC_IFINDEX uses ifindex */ union g_addr addr; - unsigned int ifindex; + ifindex_t ifindex; char ifname[INTERFACE_NAMSIZ + 1]; @@ -215,7 +215,6 @@ struct static_route */ }; - /* The following for loop allows to iterate over the nexthop * structure of routes. * @@ -321,14 +320,14 @@ typedef enum RIB_UPDATE_OTHER } rib_update_event_t; -extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, unsigned int); +extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, ifindex_t); extern struct nexthop *rib_nexthop_blackhole_add (struct rib *); extern struct nexthop *rib_nexthop_ipv4_add (struct rib *, struct in_addr *, struct in_addr *); extern struct nexthop *rib_nexthop_ipv4_ifindex_add (struct rib *, struct in_addr *, struct in_addr *, - unsigned int); + ifindex_t); extern void rib_nexthop_add (struct rib *rib, struct nexthop *nexthop); extern void rib_copy_nexthops (struct rib *rib, struct nexthop *nh); @@ -364,7 +363,7 @@ extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *); extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, - unsigned int ifindex); + ifindex_t ifindex); extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id); @@ -375,13 +374,13 @@ extern int zebra_check_addr (struct prefix *p); * also implicitly withdraw equal prefix of same type. */ extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, + ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t, u_char, safi_t); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, + struct in_addr *gate, ifindex_t ifindex, vrf_id_t, u_int32_t, safi_t safi); extern struct rib *rib_match_ipv4 (struct in_addr, safi_t safi, vrf_id_t, @@ -406,22 +405,22 @@ extern void static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); extern int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, +static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, const char *ifname, u_char flags, u_short tag, u_char distance, struct zebra_vrf *zvrf); extern int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, +static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, u_short tag, u_char distance, struct zebra_vrf *zvrf); extern int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi); extern int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, safi_t safi); extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); @@ -432,16 +431,16 @@ extern struct route_table *rib_table_ipv6; extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, const char *ifname, u_char flags, + ifindex_t ifindex, const char *ifname, u_char flags, u_short tag, u_char distance, struct zebra_vrf *zvrf); extern int rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, - unsigned long); + ifindex_t); extern int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, u_short tag, u_char distance, + ifindex_t ifindex, u_short tag, u_char distance, struct zebra_vrf *zvrf); extern int rib_gc_dest (struct route_node *rn); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index bd1c923506..d93a530317 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -74,7 +74,7 @@ extern u_int32_t nl_rcvbufsize; /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ static void -set_ifindex(struct interface *ifp, unsigned int ifi_index) +set_ifindex(struct interface *ifp, ifindex_t ifi_index) { struct interface *oifp; struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index ffb0d088a7..24671829f0 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -76,7 +76,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family) struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; char prefix_buf[PREFIX_STRLEN]; @@ -287,7 +287,7 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib, struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; diff --git a/zebra/rtadv.c b/zebra/rtadv.c index f3f1cee14b..8333d2e08c 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -70,7 +70,7 @@ static int if_join_all_router (int, struct interface *); static int if_leave_all_router (int, struct interface *); static int -rtadv_increment_received(struct zebra_ns *zns, unsigned int *ifindex) +rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) { int ret = -1; struct interface *iface; @@ -88,7 +88,7 @@ rtadv_increment_received(struct zebra_ns *zns, unsigned int *ifindex) static int rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen, - struct sockaddr_in6 *from, unsigned int *ifindex, + struct sockaddr_in6 *from, ifindex_t *ifindex, int *hoplimit) { int ret; @@ -534,7 +534,7 @@ rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, static void -rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit, +rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit, struct sockaddr_in6 *from, struct zebra_ns *zns) { struct icmp6_hdr *icmph; @@ -609,7 +609,7 @@ rtadv_read (struct thread *thread) int len; u_char buf[RTADV_MSG_SIZE]; struct sockaddr_in6 from; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int hoplimit = -1; struct zebra_ns *zns = THREAD_ARG (thread); diff --git a/zebra/test_main.c b/zebra/test_main.c index 902c675aef..95c56bb046 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -112,7 +112,7 @@ usage (char *progname, int status) exit (status); } -static unsigned int test_ifindex = 0; +static ifindex_t test_ifindex = 0; /* testrib commands */ DEFUN (test_interface_state, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 3aa9356fe6..16f43f7312 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -21,12 +21,12 @@ #include +#include "if.h" #include "prefix.h" #include "table.h" #include "memory.h" #include "str.h" #include "command.h" -#include "if.h" #include "log.h" #include "sockunion.h" #include "linklist.h" @@ -210,7 +210,7 @@ rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop) struct nexthop * -rib_nexthop_ifindex_add (struct rib *rib, unsigned int ifindex) +rib_nexthop_ifindex_add (struct rib *rib, ifindex_t ifindex) { struct nexthop *nexthop; @@ -241,7 +241,7 @@ rib_nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src struct nexthop * rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, - struct in_addr *src, unsigned int ifindex) + struct in_addr *src, ifindex_t ifindex) { struct nexthop *nexthop; struct interface *ifp; @@ -281,7 +281,7 @@ rib_nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6) struct nexthop * rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, - unsigned int ifindex) + ifindex_t ifindex) { struct nexthop *nexthop; @@ -1199,8 +1199,8 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) { struct nexthop *nexthop; union g_addr prev_src; - unsigned int prev_active, prev_index, new_active, old_num_nh; - + unsigned int prev_active, new_active, old_num_nh; + ifindex_t prev_index; old_num_nh = rib->nexthop_active_num; rib->nexthop_active_num = 0; @@ -2413,7 +2413,7 @@ rib_delnode (struct route_node *rn, struct rib *rib) int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, + ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; @@ -2770,7 +2770,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* XXX factor with rib_delete_ipv6 */ int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + struct in_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, safi_t safi) { struct route_table *table; @@ -3182,7 +3182,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ } int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, +static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, const char *ifname, u_char flags, u_short tag, u_char distance, struct zebra_vrf *zvrf) { @@ -3278,7 +3278,7 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned i } int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex, +static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, u_short tag, u_char distance, struct zebra_vrf *zvrf) { u_char type = 0; @@ -3341,7 +3341,7 @@ static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigne int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; @@ -3450,7 +3450,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, int rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, - unsigned long ifindex) + ifindex_t ifindex) { struct route_table *table; struct route_node *rn; @@ -3565,7 +3565,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, safi_t safi) { struct route_table *table; @@ -3702,7 +3702,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Add static route into static route configuration. */ int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, const char *ifname, u_char flags, + ifindex_t ifindex, const char *ifname, u_char flags, u_short tag, u_char distance, struct zebra_vrf *zvrf) { struct route_node *rn; @@ -3798,7 +3798,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* Delete static route from static route configuration. */ int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - unsigned int ifindex, u_short tag, u_char distance, + ifindex_t ifindex, u_short tag, u_char distance, struct zebra_vrf *zvrf) { struct route_node *rn; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index db3e5eaba1..1417824d07 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -252,7 +252,7 @@ route_match_interface (void *rule, struct prefix *prefix, { struct nh_rmap_obj *nh_data; char *ifname = rule; - unsigned int ifindex; + ifindex_t ifindex; if (type == RMAP_ZEBRA) { diff --git a/zebra/zserv.c b/zebra/zserv.c index d625c02ff4..a1fe9bc188 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1188,7 +1188,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) u_char nexthop_num; u_char nexthop_type; struct stream *s; - unsigned int ifindex; + ifindex_t ifindex; safi_t safi; int ret; From 2c494df3fa14e55ab1c909619b55b73853804f55 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 16 Aug 2016 17:08:54 +0200 Subject: [PATCH 135/226] Revert "per-interface ospf enable and area set command." This reverts commit e723861da171fd811f499665e5432dce4e364ee6. The code is from Joakim Tjernlund; this is just to fix the history (and attribution) of it. The last commit will restore the exact same tree state. THIS COMMIT WILL PROBABLY NOT COMPILE. Signed-off-by: David Lamparter --- doc/ospfd.texi | 5 -- ospfd/ospf_interface.h | 2 - ospfd/ospf_vty.c | 27 ------ ospfd/ospfd.c | 184 +++++------------------------------------ ospfd/ospfd.h | 5 -- 5 files changed, 20 insertions(+), 203 deletions(-) diff --git a/doc/ospfd.texi b/doc/ospfd.texi index 45d1ad7cd2..56ab5a3ed5 100644 --- a/doc/ospfd.texi +++ b/doc/ospfd.texi @@ -510,11 +510,6 @@ incremented by this value when transmitting. The default value is 1 seconds. @end deffn -@deffn {Interface Command} {ip ospf area (A.B.C.D|<0-4294967295>)} {} -@deffnx {Interface Command} {no ip ospf area} {} -Enable ospf on an interface and set associated area. -@end deffn - @node Redistribute routes to OSPF @section Redistribute routes to OSPF diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 7a74288bff..988493a210 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -47,8 +47,6 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ - /* Enable OSPF on this interface with area if_area */ - DECLARE_IF_PARAM (struct in_addr, if_area); DECLARE_IF_PARAM (u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3022a316c6..ea76856afe 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -543,13 +543,6 @@ DEFUN (ospf_network_area, return CMD_WARNING; } - if (ospf->if_ospf_cli_count > 0) - { - vty_out (vty, "Please remove all ip ospf area x.x.x.x commands first.%s", - VTY_NEWLINE); - return CMD_WARNING; - } - /* Get network prefix and Area ID. */ VTY_GET_IPV4_PREFIX ("network prefix", p, argv[0]); VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); @@ -9410,18 +9403,6 @@ config_write_interface (struct vty *vty) vty_out (vty, "%s", VTY_NEWLINE); } - /* Area print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) - { - if (ospf->instance) - vty_out (vty, " ip ospf %d area %s%s", ospf->instance, - inet_ntoa (params->if_area), VTY_NEWLINE); - else - vty_out (vty, " ip ospf area %s%s", - inet_ntoa (params->if_area), VTY_NEWLINE); - - } - /* bfd print. */ ospf_bfd_write_config(vty, params); @@ -10152,14 +10133,6 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_sec_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_sec_cmd); - /* "ip ospf area" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_area_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_area_val_cmd); - install_element (INTERFACE_NODE, &ip_ospf_instance_area_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_instance_area_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_instance_area_val_cmd); - /* These commands are compatibitliy for previous version. */ install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 9d0e4b9e87..fb84903285 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -501,7 +501,6 @@ ospf_finish_final (struct ospf *ospf) struct route_node *rn; struct ospf_nbr_nbma *nbr_nbma; struct ospf_lsa *lsa; - struct interface *ifp; struct ospf_interface *oi; struct ospf_area *area; struct ospf_vl_data *vl_data; @@ -537,16 +536,6 @@ ospf_finish_final (struct ospf *ospf) list_delete (ospf->vlinks); - /* Remove any ospf interface config params */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - UNSET_IF_PARAM (params, if_area); - } - /* Reset interface. */ for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) ospf_if_free (oi); @@ -849,69 +838,6 @@ ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) listnode_delete (area->oiflist, oi); } -static struct ospf_interface * -add_ospf_interface (struct interface *ifp, struct ospf_area *area, - struct connected *co) -{ - struct ospf_interface *oi; - - oi = ospf_if_new (area->ospf, ifp, co->address); - oi->connected = co; - - oi->area = area; - - oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); - oi->output_cost = ospf_if_get_output_cost (oi); - - /* Relate ospf interface to ospf instance. */ - oi->ospf = area->ospf; - - /* update network type as interface flag */ - /* If network type is specified previously, - skip network type setting. */ - oi->type = IF_DEF_PARAMS (ifp)->type; - - /* Add pseudo neighbor. */ - ospf_nbr_self_reset (oi, oi->ospf->router_id); - - ospf_area_add_if (oi->area, oi); - - return (oi); -} - -static void update_redistributed(struct ospf *ospf, int add_to_ospf) -{ - struct route_node *rn; - struct external_info *ei; - struct ospf_external *ext; - - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT, 0)) - if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0)) && - EXTERNAL_INFO (ext)) - { - for (rn = route_top (EXTERNAL_INFO (ext)); - rn; rn = route_next (rn)) - { - if ((ei = rn->info) != NULL) - { - if (add_to_ospf) - { - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - } - else - { - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); - } - } - } - } -} - /* Config network statement related functions. */ static struct ospf_network * @@ -941,6 +867,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, struct ospf_network *network; struct ospf_area *area; struct route_node *rn; + struct external_info *ei; int ret = OSPF_AREA_ID_FORMAT_ADDRESS; rn = route_node_get (ospf->networks, (struct prefix *)p); @@ -958,7 +885,15 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ - update_redistributed(ospf, 1); /* interfaces possibly added */ + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) + if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) + for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); + rn; rn = route_next (rn)) + if ((ei = rn->info) != NULL) + if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (!ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_flush (ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); ospf_area_check_free (ospf, area_id); @@ -971,6 +906,7 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, { struct route_node *rn; struct ospf_network *network; + struct external_info *ei; struct listnode *node, *nnode; struct ospf_interface *oi; @@ -1017,86 +953,14 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, } /* Update connected redistribute. */ - update_redistributed(ospf, 0); /* interfaces possibly removed */ - ospf_area_check_free (ospf, area_id); - - return 1; -} - -int -ospf_interface_set (struct interface *ifp, struct in_addr area_id) -{ - struct ospf_area *area; - struct listnode *cnode; - struct connected *co; - struct ospf *ospf; - struct ospf_if_params *params; - struct ospf_interface *oi; - int ret = OSPF_AREA_ID_FORMAT_ADDRESS; - - if ((ospf = ospf_lookup ()) == NULL) - return 1; /* Ospf not ready yet */ - - params = IF_DEF_PARAMS (ifp); - - SET_IF_PARAM (params, if_area); - params->if_area = area_id; - - area = ospf_area_get (ospf, area_id, ret); - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) - { - if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) - continue; - - if (co->address->family == AF_INET) - { - oi = ospf_if_table_lookup(ifp, co->address); - if (!oi) - oi = add_ospf_interface(ifp, area, co); - - /* if router_id is not configured, dont bring up - * interfaces. - * ospf_router_id_update() will call ospf_if_update - * whenever r-id is configured instead. - */ - if ((area->ospf->router_id.s_addr != 0) && if_is_operative (ifp)) - ospf_if_up (oi); - } - } - - /* Update connected redistribute. */ - update_redistributed(ospf, 1); /* interface possibly added */ - return 1; -} - -int -ospf_interface_unset (struct interface *ifp) -{ - struct ospf *ospf; - struct ospf_if_params *params; - struct listnode *node, *nnode; - struct ospf_interface *oi; - struct in_addr area_id; - - ospf = ospf_lookup (); - if (!ospf) - return 1; /* Ospf not ready yet */ - - params = IF_DEF_PARAMS (ifp); - UNSET_IF_PARAM (params, if_area); - area_id = params->if_area; - - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - { - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - if (oi->ifp == ifp) ospf_if_free (oi); - } - - /* Update connected redistribute. */ - update_redistributed(ospf, 0); /* interfaces possibly removed */ - ospf_area_check_free (ospf, area_id); + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) + if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) + for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); + rn; rn = route_next (rn)) + if ((ei = rn->info) != NULL) + if (!ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_originate (ospf, ei); return 1; } @@ -1216,8 +1080,7 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) struct route_node *rn; struct ospf_network *network; struct ospf_area *area; - struct ospf_if_params *params; - + if (!ospf) ospf = ospf_lookup (); @@ -1233,13 +1096,6 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) area = ospf_area_get (ospf, network->area_id, network->format); ospf_network_run_interface (&rn->p, area, ifp); } - - /* create oif for any new co */ - params = IF_DEF_PARAMS (ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - { - ospf_interface_set (ifp, params->if_area); - } } void diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 5f0a7bf113..3d3c73156c 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -296,9 +296,6 @@ struct ospf /* Statistics for LSA used for new instantiation. */ u_int32_t rx_lsa_count; - /* Counter of "ip ospf area x.x.x.x" */ - u_int32_t if_ospf_cli_count; - struct route_table *distance_table; }; @@ -581,6 +578,4 @@ extern void ospf_snmp_init (void); extern void ospf_master_init (void); -extern int ospf_interface_set (struct interface *ifp, struct in_addr area_id); -extern int ospf_interface_unset (struct interface *ifp); #endif /* _ZEBRA_OSPFD_H */ From 953cde65c5a35c8762f5858ace216b768814d01c Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 7 Aug 2009 13:48:15 +0200 Subject: [PATCH 136/226] ospfd: Impl. per interface 'ip ospf area' command Use with interface command: interface ppp0 ip ospf area 0.0.0.0 This will enable OSPF on ppp0 with area 0.0.0.0 Remove with "no ip ospf area" * ospf_vty.c: add "ip ospf area (A.B.C.D|<0-4294967295>)" interface command * ospfd.c: (ospf_interface_{un,}set) new helper function to enable/disable OSPF on a specific interface. (ospf_if_update) 2 possible paths now to deal with interface updates. Acked-by: Donald Sharp [DL: this restores the tree to deccaf9...] --- doc/ospfd.texi | 5 ++ ospfd/ospf_interface.h | 2 + ospfd/ospf_vty.c | 27 ++++++ ospfd/ospfd.c | 184 ++++++++++++++++++++++++++++++++++++----- ospfd/ospfd.h | 5 ++ 5 files changed, 203 insertions(+), 20 deletions(-) diff --git a/doc/ospfd.texi b/doc/ospfd.texi index 56ab5a3ed5..45d1ad7cd2 100644 --- a/doc/ospfd.texi +++ b/doc/ospfd.texi @@ -510,6 +510,11 @@ incremented by this value when transmitting. The default value is 1 seconds. @end deffn +@deffn {Interface Command} {ip ospf area (A.B.C.D|<0-4294967295>)} {} +@deffnx {Interface Command} {no ip ospf area} {} +Enable ospf on an interface and set associated area. +@end deffn + @node Redistribute routes to OSPF @section Redistribute routes to OSPF diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 988493a210..7a74288bff 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -47,6 +47,8 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ + /* Enable OSPF on this interface with area if_area */ + DECLARE_IF_PARAM (struct in_addr, if_area); DECLARE_IF_PARAM (u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index ea76856afe..3022a316c6 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -543,6 +543,13 @@ DEFUN (ospf_network_area, return CMD_WARNING; } + if (ospf->if_ospf_cli_count > 0) + { + vty_out (vty, "Please remove all ip ospf area x.x.x.x commands first.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + /* Get network prefix and Area ID. */ VTY_GET_IPV4_PREFIX ("network prefix", p, argv[0]); VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); @@ -9403,6 +9410,18 @@ config_write_interface (struct vty *vty) vty_out (vty, "%s", VTY_NEWLINE); } + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) + { + if (ospf->instance) + vty_out (vty, " ip ospf %d area %s%s", ospf->instance, + inet_ntoa (params->if_area), VTY_NEWLINE); + else + vty_out (vty, " ip ospf area %s%s", + inet_ntoa (params->if_area), VTY_NEWLINE); + + } + /* bfd print. */ ospf_bfd_write_config(vty, params); @@ -10133,6 +10152,14 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_sec_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_sec_cmd); + /* "ip ospf area" commands. */ + install_element (INTERFACE_NODE, &ip_ospf_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_area_val_cmd); + install_element (INTERFACE_NODE, &ip_ospf_instance_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_instance_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_instance_area_val_cmd); + /* These commands are compatibitliy for previous version. */ install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index fb84903285..9d0e4b9e87 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -501,6 +501,7 @@ ospf_finish_final (struct ospf *ospf) struct route_node *rn; struct ospf_nbr_nbma *nbr_nbma; struct ospf_lsa *lsa; + struct interface *ifp; struct ospf_interface *oi; struct ospf_area *area; struct ospf_vl_data *vl_data; @@ -536,6 +537,16 @@ ospf_finish_final (struct ospf *ospf) list_delete (ospf->vlinks); + /* Remove any ospf interface config params */ + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + { + struct ospf_if_params *params; + + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + UNSET_IF_PARAM (params, if_area); + } + /* Reset interface. */ for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) ospf_if_free (oi); @@ -838,6 +849,69 @@ ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) listnode_delete (area->oiflist, oi); } +static struct ospf_interface * +add_ospf_interface (struct interface *ifp, struct ospf_area *area, + struct connected *co) +{ + struct ospf_interface *oi; + + oi = ospf_if_new (area->ospf, ifp, co->address); + oi->connected = co; + + oi->area = area; + + oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); + oi->output_cost = ospf_if_get_output_cost (oi); + + /* Relate ospf interface to ospf instance. */ + oi->ospf = area->ospf; + + /* update network type as interface flag */ + /* If network type is specified previously, + skip network type setting. */ + oi->type = IF_DEF_PARAMS (ifp)->type; + + /* Add pseudo neighbor. */ + ospf_nbr_self_reset (oi, oi->ospf->router_id); + + ospf_area_add_if (oi->area, oi); + + return (oi); +} + +static void update_redistributed(struct ospf *ospf, int add_to_ospf) +{ + struct route_node *rn; + struct external_info *ei; + struct ospf_external *ext; + + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT, 0)) + if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0)) && + EXTERNAL_INFO (ext)) + { + for (rn = route_top (EXTERNAL_INFO (ext)); + rn; rn = route_next (rn)) + { + if ((ei = rn->info) != NULL) + { + if (add_to_ospf) + { + if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (!ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_flush (ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + } + else + { + if (!ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_originate (ospf, ei); + } + } + } + } +} + /* Config network statement related functions. */ static struct ospf_network * @@ -867,7 +941,6 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, struct ospf_network *network; struct ospf_area *area; struct route_node *rn; - struct external_info *ei; int ret = OSPF_AREA_ID_FORMAT_ADDRESS; rn = route_node_get (ospf->networks, (struct prefix *)p); @@ -885,15 +958,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); + update_redistributed(ospf, 1); /* interfaces possibly added */ ospf_area_check_free (ospf, area_id); @@ -906,7 +971,6 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, { struct route_node *rn; struct ospf_network *network; - struct external_info *ei; struct listnode *node, *nnode; struct ospf_interface *oi; @@ -953,14 +1017,86 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, } /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); + update_redistributed(ospf, 0); /* interfaces possibly removed */ + ospf_area_check_free (ospf, area_id); + + return 1; +} + +int +ospf_interface_set (struct interface *ifp, struct in_addr area_id) +{ + struct ospf_area *area; + struct listnode *cnode; + struct connected *co; + struct ospf *ospf; + struct ospf_if_params *params; + struct ospf_interface *oi; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + params = IF_DEF_PARAMS (ifp); + + SET_IF_PARAM (params, if_area); + params->if_area = area_id; + + area = ospf_area_get (ospf, area_id, ret); + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) + { + if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) + continue; + + if (co->address->family == AF_INET) + { + oi = ospf_if_table_lookup(ifp, co->address); + if (!oi) + oi = add_ospf_interface(ifp, area, co); + + /* if router_id is not configured, dont bring up + * interfaces. + * ospf_router_id_update() will call ospf_if_update + * whenever r-id is configured instead. + */ + if ((area->ospf->router_id.s_addr != 0) && if_is_operative (ifp)) + ospf_if_up (oi); + } + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 1); /* interface possibly added */ + return 1; +} + +int +ospf_interface_unset (struct interface *ifp) +{ + struct ospf *ospf; + struct ospf_if_params *params; + struct listnode *node, *nnode; + struct ospf_interface *oi; + struct in_addr area_id; + + ospf = ospf_lookup (); + if (!ospf) + return 1; /* Ospf not ready yet */ + + params = IF_DEF_PARAMS (ifp); + UNSET_IF_PARAM (params, if_area); + area_id = params->if_area; + + for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) + { + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + if (oi->ifp == ifp) ospf_if_free (oi); + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 0); /* interfaces possibly removed */ + ospf_area_check_free (ospf, area_id); return 1; } @@ -1080,7 +1216,8 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) struct route_node *rn; struct ospf_network *network; struct ospf_area *area; - + struct ospf_if_params *params; + if (!ospf) ospf = ospf_lookup (); @@ -1096,6 +1233,13 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) area = ospf_area_get (ospf, network->area_id, network->format); ospf_network_run_interface (&rn->p, area, ifp); } + + /* create oif for any new co */ + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + { + ospf_interface_set (ifp, params->if_area); + } } void diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 3d3c73156c..5f0a7bf113 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -296,6 +296,9 @@ struct ospf /* Statistics for LSA used for new instantiation. */ u_int32_t rx_lsa_count; + /* Counter of "ip ospf area x.x.x.x" */ + u_int32_t if_ospf_cli_count; + struct route_table *distance_table; }; @@ -578,4 +581,6 @@ extern void ospf_snmp_init (void); extern void ospf_master_init (void); +extern int ospf_interface_set (struct interface *ifp, struct in_addr area_id); +extern int ospf_interface_unset (struct interface *ifp); #endif /* _ZEBRA_OSPFD_H */ From 169d94f7aa2d882ed75280a223a6dbf3db0f8126 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Jan 2016 13:41:45 -0500 Subject: [PATCH 137/226] zebra: additional redistribute related logging Signed-off-by: Lou Berger Signed-off-by: David Lamparter (cherry picked from commit 40278bd4c51939ccf8ec06ef1f33aedf8f05e86c) --- zebra/redistribute.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 1867362778..305fb4bc82 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -144,17 +144,22 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) - if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) - && newrib->type == type - && newrib->instance == instance - && newrib->distance != DISTANCE_INFINITY - && zebra_check_addr (&rn->p)) - { - client->redist_v4_add_cnt++; - zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); - } - -#ifdef HAVE_IPV6 + { + zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, zebra_check_addr=%d", + __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), + newrib->type, newrib->distance, zebra_check_addr (&rn->p)); + + if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) + && newrib->type == type + && newrib->instance == instance + && newrib->distance != DISTANCE_INFINITY + && zebra_check_addr (&rn->p)) + { + client->redist_v4_add_cnt++; + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); + } + } + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) @@ -168,7 +173,6 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v client->redist_v6_add_cnt++; zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, &rn->p, newrib); } -#endif /* HAVE_IPV6 */ } /* Either advertise a route for redistribution to registered clients or */ From c85d435bd742c3059f15eb9c219355b3bdbd5fac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 10:15:01 -0400 Subject: [PATCH 138/226] zebra: Fix up cherry-pick mistake I forgot to include the if (IS_ZEBRA_DEBUG_EVENT) test --- zebra/redistribute.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 305fb4bc82..4238d8329e 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -145,9 +145,10 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) { - zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, zebra_check_addr=%d", - __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), - newrib->type, newrib->distance, zebra_check_addr (&rn->p)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, zebra_check_addr=%d", + __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), + newrib->type, newrib->distance, zebra_check_addr (&rn->p)); if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->type == type From a5b89524bccfeac78388402fab524fa1290cc871 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 18 Aug 2016 17:47:01 +0000 Subject: [PATCH 139/226] vtysh --markfile needs to ignore the "end" lines Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12515 --- vtysh/vtysh.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index ad43f41fd9..3d3b8e6dce 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -504,6 +504,28 @@ vtysh_execute (const char *line) return vtysh_execute_func (line, 1); } +static char * +trim (char *s) +{ + size_t size; + char *end; + + size = strlen(s); + + if (!size) + return s; + + end = s + size - 1; + while (end >= s && isspace(*end)) + end--; + *(end + 1) = '\0'; + + while (*s && isspace(*s)) + s++; + + return s; +} + int vtysh_mark_file (const char *filename) { @@ -515,6 +537,8 @@ vtysh_mark_file (const char *filename) struct cmd_element *cmd; int saved_ret, prev_node; int lineno = 0; + char *vty_buf_copy = NULL; + char *vty_buf_trimmed = NULL; if (strncmp("-", filename, 1) == 0) confp = stdin; @@ -535,13 +559,16 @@ vtysh_mark_file (const char *filename) vtysh_execute_no_pager ("enable"); vtysh_execute_no_pager ("configure terminal"); + vty_buf_copy = XCALLOC (MTYPE_VTY, VTY_BUFSIZ); while (fgets (vty->buf, VTY_BUFSIZ, confp)) { lineno++; tried = 0; + strcpy(vty_buf_copy, vty->buf); + vty_buf_trimmed = trim(vty_buf_copy); - if (vty->buf[0] == '!' || vty->buf[1] == '#') + if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') { fprintf(stdout, "%s", vty->buf); continue; @@ -556,6 +583,12 @@ vtysh_mark_file (const char *filename) continue; } + /* Ignore the "end" lines, we will generate these where appropriate */ + if (strlen(vty_buf_trimmed) == 3 && strncmp("end", vty_buf_trimmed, 3) == 0) + { + continue; + } + prev_node = vty->node; saved_ret = ret = cmd_execute_command_strict (vline, vty, &cmd); @@ -606,21 +639,25 @@ vtysh_mark_file (const char *filename) fprintf (stderr,"line %d: Warning...: %s\n", lineno, vty->buf); fclose(confp); vty_close(vty); + XFREE(MTYPE_VTY, vty_buf_copy); return CMD_WARNING; case CMD_ERR_AMBIGUOUS: fprintf (stderr,"line %d: %% Ambiguous command: %s\n", lineno, vty->buf); fclose(confp); vty_close(vty); + XFREE(MTYPE_VTY, vty_buf_copy); return CMD_ERR_AMBIGUOUS; case CMD_ERR_NO_MATCH: fprintf (stderr,"line %d: %% Unknown command: %s\n", lineno, vty->buf); fclose(confp); vty_close(vty); + XFREE(MTYPE_VTY, vty_buf_copy); return CMD_ERR_NO_MATCH; case CMD_ERR_INCOMPLETE: fprintf (stderr,"line %d: %% Command incomplete: %s\n", lineno, vty->buf); fclose(confp); vty_close(vty); + XFREE(MTYPE_VTY, vty_buf_copy); return CMD_ERR_INCOMPLETE; case CMD_SUCCESS: fprintf(stdout, "%s", vty->buf); @@ -652,6 +689,7 @@ vtysh_mark_file (const char *filename) /* This is the end */ fprintf(stdout, "end\n"); vty_close(vty); + XFREE(MTYPE_VTY, vty_buf_copy); if (confp != stdin) fclose(confp); From 926ea62e0bfb598bfa2fb950e28861b2588f41ea Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 18 Aug 2016 18:03:46 +0000 Subject: [PATCH 140/226] quagga-reload.py should not restart quagga if bgp ASN changes Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Reviewed-by: Dinesh Dutt Ticket: CM-12521 --- tools/quagga-reload.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index f90b3e95fc..781086d9da 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -448,7 +448,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): for (ctx_keys, line) in lines_to_del: deleted = False - if ctx_keys[0].startswith('router bgp') and line.startswith('neighbor '): + if ctx_keys[0].startswith('router bgp') and line and line.startswith('neighbor '): """ BGP changed how it displays swpX peers that are part of peer-group. Older versions of quagga would display these on separate lines: @@ -608,7 +608,7 @@ def compare_context_objects(newconf, running): # Compare the two Config objects to find the lines that we need to add/del lines_to_add = [] lines_to_del = [] - restart_bgpd = False + delete_bgpd = False # Find contexts that are in newconf but not in running # Find contexts that are in running but not in newconf @@ -616,17 +616,21 @@ def compare_context_objects(newconf, running): if running_ctx_keys not in newconf.contexts: - # Check if bgp's local ASN has changed. If yes, just restart it # We check that the len is 1 here so that we only look at ('router bgp 10') # and not ('router bgp 10', 'address-family ipv4 unicast'). The - # latter could cause a false restart_bgpd positive if ipv4 unicast is in + # latter could cause a false delete_bgpd positive if ipv4 unicast is in # running but not in newconf. if "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) == 1: - restart_bgpd = True + delete_bgpd = True + lines_to_del.append((running_ctx_keys, None)) + + # If this is an address-family under 'router bgp' and we are already deleting the + # entire 'router bgp' context then ignore this sub-context + elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd: continue # Non-global context - if running_ctx_keys and not any("address-family" in key for key in running_ctx_keys): + elif running_ctx_keys and not any("address-family" in key for key in running_ctx_keys): lines_to_del.append((running_ctx_keys, None)) # Global context @@ -652,11 +656,6 @@ def compare_context_objects(newconf, running): for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems(): if newconf_ctx_keys not in running.contexts: - - # If its "router bgp" and we're restarting bgp, skip doing - # anything specific for bgp - if "router bgp" in newconf_ctx_keys[0] and restart_bgpd: - continue lines_to_add.append((newconf_ctx_keys, None)) for line in newconf_ctx.lines: @@ -664,7 +663,7 @@ def compare_context_objects(newconf, running): (lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del) - return (lines_to_add, lines_to_del, restart_bgpd) + return (lines_to_add, lines_to_del) if __name__ == '__main__': # Command line options @@ -684,6 +683,11 @@ if __name__ == '__main__': if args.test or args.stdout: logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)5s: %(message)s') + + # Color the errors and warnings in red + logging.addLevelName(logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR)) + logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING)) + elif args.reload: if not os.path.isdir('/var/log/quagga/'): os.makedirs('/var/log/quagga/') @@ -742,7 +746,7 @@ if __name__ == '__main__': else: running.load_from_show_running() - (lines_to_add, lines_to_del, restart_bgp) = compare_context_objects(newconf, running) + (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) lines_to_configure = [] if lines_to_del: @@ -771,9 +775,6 @@ if __name__ == '__main__': lines_to_configure.append(cmd) print cmd - if restart_bgp: - print "BGP local AS changed, bgpd would restart" - elif args.reload: logger.debug('New Quagga Config\n%s', newconf.get_lines()) @@ -805,7 +806,7 @@ if __name__ == '__main__': running.load_from_show_running() logger.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines()) - (lines_to_add, lines_to_del, restart_bgp) = compare_context_objects(newconf, running) + (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) if lines_to_del: for (ctx_keys, line) in lines_to_del: @@ -881,6 +882,5 @@ if __name__ == '__main__': subprocess.call(['/usr/bin/vtysh', '-f', filename]) os.unlink(filename) - if restart_bgp: - subprocess.call(['sudo', 'systemctl', 'reset-failed', 'quagga']) - subprocess.call(['sudo', 'systemctl', '--no-block', 'restart', 'quagga']) + # Make these changes persistent + subprocess.call(['/usr/bin/vtysh', '-c', 'write']) From e5d1e72daaf5775e4bf67d812553d4fd8775791a Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 18 Aug 2016 15:02:49 -0700 Subject: [PATCH 141/226] bgpd: Upon interface up (update) only kick-off non-Established peers Any interface flags/parameter change (e.g., MTU, PROMISC flag change) is notified by zebra to clients as an "up" event. BGP literally treats this as the interface coming up and kicks all neighbors on that interface (i.e., directly connected peers). When doing so for IPv4 peers on the interface (numbered or unnumbered /30-/31) or IPv6 numbered peers, peers that may already be Established are also flapped; when doing so for IPv6 unnumbered peers (classic 'neighbor swpX interface' scenario with no configured IP address on interface), only peers not in Established state are processed. This patch fixes the code to ensure that in all cases, only non-Established peers are kicked. Signed-off-by: Vivek Venkatraman Reviewed-by: Don Slice Reviewed-by: Chris Cormier Ticket: CM-12526 Reviewed By: CCR-5119 Testing Done: Manual, bgp-min --- bgpd/bgp_nexthop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 80495065b0..a58b73e9f3 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -236,6 +236,7 @@ bgp_connected_add (struct bgp *bgp, struct connected *ifc) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) && + peer->status != Established && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) { if (peer_active(peer)) From 139c1f36d45f7ab34ea3d1f343b63ac3487b3415 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 16:59:08 +0200 Subject: [PATCH 142/226] isisd: fix isis_circuit_create() Between the awkwardly managed CSM and the tacked-on IPv6 support, the simplified logic to setup a circuit wasn't quite right. Note that the API essentially allows creating a circuit without enabling either IPv4 or IPv6. This wasn't possible before and probably breaks isisd in 'interesting' ways. The CLI won't do this, so it's only an issue when adding on other configuration mechanisms. Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 6 ++++-- isisd/isis_vty.c | 16 ++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d8ca694d59..b9ebf52505 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1226,8 +1226,10 @@ isis_interface_config_write (struct vty *vty) struct isis_circuit * isis_circuit_create (struct isis_area *area, struct interface *ifp) { - struct isis_circuit *circuit; - circuit = isis_csm_state_change (ISIS_ENABLE, NULL, area); + struct isis_circuit *circuit = circuit_scan_by_ifp (ifp); + if (circuit && circuit->area) + return NULL; + circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); isis_circuit_if_bind (circuit, ifp); return circuit; diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 3f218561cc..3ce06b83da 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -72,17 +72,13 @@ DEFUN (ip_router_isis, /* Prevent more than one area per circuit */ circuit = circuit_scan_by_ifp (ifp); - if (circuit) + if (circuit && circuit->area) { - if (circuit->ip_router == 1) + if (strcmp (circuit->area->area_tag, area_tag)) { - if (strcmp (circuit->area->area_tag, area_tag)) - { - vty_out (vty, "ISIS circuit is already defined on %s%s", - circuit->area->area_tag, VTY_NEWLINE); - return CMD_ERR_NOTHING_TODO; - } - return CMD_SUCCESS; + vty_out (vty, "ISIS circuit is already defined on %s%s", + circuit->area->area_tag, VTY_NEWLINE); + return CMD_ERR_NOTHING_TODO; } } @@ -90,7 +86,7 @@ DEFUN (ip_router_isis, if (!area) area = isis_area_create (area_tag); - if (!circuit) + if (!circuit || !circuit->area) circuit = isis_circuit_create (area, ifp); bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; From aa11f85082d8d0272bfd7e06742739afb4783e07 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 Aug 2016 17:02:50 +0200 Subject: [PATCH 143/226] isisd: fix isis_circuit_af_set() on fresh circuit A newly-created circuit will be in enabled state but have neither IPv4 nor IPv6 configured. The logic in isis_circuit_af_set assumed that "enabled" is equivalent to "ip || ipv6". This is the only place where this distinction is currently relevant, as the CLI won't allow enabling an interface without enabling either IPv4 or IPv6; and it will also disable a circuit when both are deconfigured. Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index b9ebf52505..ad1eca89e3 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1240,7 +1240,7 @@ isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_rou { struct isis_area *area = circuit->area; bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router; - bool was_enabled = circuit->ip_router || circuit->ipv6_router; + bool was_enabled = !!circuit->area; area->ip_circuits += ip_router - circuit->ip_router; area->ipv6_circuits += ipv6_router - circuit->ipv6_router; From 6f32c890cb549b6ba58d5aae5eb6fbb50abfe063 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 11 Aug 2016 16:08:05 +0200 Subject: [PATCH 144/226] isisd: fix network-type configuration Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 1 - isisd/isis_vty.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index ad1eca89e3..ac41b55b87 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1358,7 +1358,6 @@ isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) * is not supported. */ if (circ_type == CIRCUIT_T_UNKNOWN || circ_type == CIRCUIT_T_LOOPBACK - || circuit->circ_type == CIRCUIT_T_UNKNOWN || circuit->circ_type == CIRCUIT_T_LOOPBACK) { if (circuit->circ_type != circ_type) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 3ce06b83da..f9b96a42d8 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -255,7 +255,7 @@ DEFUN (isis_network, if (!circuit) return CMD_ERR_NO_MATCH; - if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { vty_out (vty, "isis network point-to-point " "is valid only on broadcast interfaces%s", @@ -278,7 +278,7 @@ DEFUN (no_isis_network, if (!circuit) return CMD_ERR_NO_MATCH; - if (!isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { vty_out (vty, "isis network point-to-point " "is valid only on broadcast interfaces%s", From 791ffe38a5e87236fef7943b28d4db7caca768b4 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 13 Aug 2016 01:20:20 +0200 Subject: [PATCH 145/226] isisd: fix is_type_set Code's "is_type" is "circuit-type" in CLI, "circuit_type" is "network" (type) in CLI, and the function to change is_type is isis_event_circuit_type_change()... *headdesk* Reported-by: Martin Winter Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index ac41b55b87..300c2cd85e 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1285,10 +1285,10 @@ isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) } void -isis_circuit_is_type_set (struct isis_circuit *circuit, int circ_type) +isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type) { - if (circuit->circ_type != circ_type) - isis_event_circuit_type_change (circuit, circ_type); + if (circuit->is_type != is_type) + isis_event_circuit_type_change (circuit, is_type); } int From f1d489ea29240037c6579d2ee5134dce11b7d511 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 13 Aug 2016 01:32:52 +0200 Subject: [PATCH 146/226] isisd: fold up isis_circuit_is_type_set() see previous commit. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 7 ------- isisd/isis_events.c | 2 +- isisd/isisd.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 300c2cd85e..efed420161 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1284,13 +1284,6 @@ isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) return 0; } -void -isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type) -{ - if (circuit->is_type != is_type) - isis_event_circuit_type_change (circuit, is_type); -} - int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) { diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 8fb92fdd39..460b1d25ba 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -145,7 +145,7 @@ circuit_resign_level (struct isis_circuit *circuit, int level) } void -isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype) +isis_circuit_is_type_set (struct isis_circuit *circuit, int newtype) { if (circuit->state != C_STATE_UP) { diff --git a/isisd/isisd.c b/isisd/isisd.c index 62c5e26538..0d0b805a20 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1775,7 +1775,7 @@ isis_area_is_type_set(struct isis_area *area, int is_type) if (area->is_type != IS_LEVEL_1_AND_2) { for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - isis_event_circuit_type_change (circuit, is_type); + isis_circuit_is_type_set (circuit, is_type); } spftree_area_init (area); From 83cd1f1aab571b479000a50d0d322a8c44ab409f Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 15 Aug 2016 13:36:59 +0200 Subject: [PATCH 147/226] isisd: warn if there is an MTU issue on circuits Instead of later tripping over an assert, add a proper warning for interfaces whose MTU is too low. Signed-off-by: David Lamparter --- isisd/isis_circuit.c | 3 ++- isisd/isis_vty.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index efed420161..728cbdc67d 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1230,7 +1230,8 @@ isis_circuit_create (struct isis_area *area, struct interface *ifp) if (circuit && circuit->area) return NULL; circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + return circuit; isis_circuit_if_bind (circuit, ifp); return circuit; } diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index f9b96a42d8..4148eb55b9 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -86,9 +86,16 @@ DEFUN (ip_router_isis, if (!area) area = isis_area_create (area_tag); - if (!circuit || !circuit->area) + if (!circuit || !circuit->area) { circuit = isis_circuit_create (area, ifp); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + { + vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; if (af[2] != '\0') ipv6 = true; From 2f97fa65ff6331e6dec751901ac2e4e450e2d66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 2 Nov 2015 16:50:05 +0200 Subject: [PATCH 148/226] zebra: make ZEBRA_FLAG_CHANGED internal status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This flag is used internally in zebra only. And it makes no sense to expose it over the zclient API, as having it set from client could corrupt the internal state. Signed-off-by: Timo Teräs Acked-by: Donald Sharp (cherry picked from commit 7eb6136b2732d4782360f9f376336c6d4f667ff0) --- lib/zebra.h | 1 - zebra/rib.h | 1 + zebra/zebra_rib.c | 46 +++++++++++++++++++++++----------------------- zebra/zebra_rnh.c | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/zebra.h b/lib/zebra.h index b3a814c0d2..e117e26bf6 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -489,7 +489,6 @@ extern const char *zserv_command_string (unsigned int command); #define ZEBRA_FLAG_BLACKHOLE 0x04 #define ZEBRA_FLAG_IBGP 0x08 #define ZEBRA_FLAG_SELECTED 0x10 -#define ZEBRA_FLAG_CHANGED 0x20 #define ZEBRA_FLAG_STATIC 0x40 #define ZEBRA_FLAG_REJECT 0x80 #define ZEBRA_FLAG_SCOPE_LINK 0x100 diff --git a/zebra/rib.h b/zebra/rib.h index 291ee0b714..a2109d8c17 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -81,6 +81,7 @@ struct rib #define RIB_ENTRY_REMOVED 0x1 /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define RIB_ENTRY_NEXTHOPS_CHANGED 0x2 +#define RIB_ENTRY_CHANGED 0x4 /* Nexthop information. */ u_char nexthop_num; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 16f43f7312..c1bceee9e6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1188,7 +1188,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, /* Iterate over all nexthops of the given RIB entry and refresh their * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any * nexthop is found to toggle the ACTIVE flag, the whole rib structure - * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is + * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is * transparently passed to nexthop_active_check(). * * Return value is the new number of active nexthops. @@ -1204,7 +1204,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) old_num_nh = rib->nexthop_active_num; rib->nexthop_active_num = 0; - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { @@ -1224,15 +1224,15 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && !(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6)))) { - SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG (rib->flags, RIB_ENTRY_CHANGED); SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } } if (old_num_nh != rib->nexthop_active_num) - SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG (rib->flags, RIB_ENTRY_CHANGED); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_CHANGED)) + if (CHECK_FLAG (rib->flags, RIB_ENTRY_CHANGED)) { SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } @@ -1429,7 +1429,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active or not. */ if (!nexthop_active_update (rn, select, 1)) { - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); return; } @@ -1455,7 +1455,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update for redistribution. */ if (installed) redistribute_update (&rn->p, select, NULL); - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); } static void @@ -1482,7 +1482,7 @@ rib_process_del_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update nexthop for route, reset changed flag. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); } static void @@ -1503,7 +1503,7 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, * something has changed. */ if (select != fib || - CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) + CHECK_FLAG (select->flags, RIB_ENTRY_CHANGED)) { zfpm_trigger_update (rn, "updating existing route"); @@ -1623,11 +1623,11 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); } /* Clear changed flag. */ - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); } /* Core function for processing routing information base. */ @@ -1707,7 +1707,7 @@ rib_process (struct route_node *rn) * the nexthop_active_update() code. Thus, we might miss changes to * recursive NHs. */ - if (!CHECK_FLAG(rib->flags, ZEBRA_FLAG_CHANGED) && + if (!CHECK_FLAG(rib->flags, RIB_ENTRY_CHANGED) && ! nexthop_active_update (rn, rib, 0)) { if (rib->type == ZEBRA_ROUTE_TABLE) @@ -1735,7 +1735,7 @@ rib_process (struct route_node *rn) /* Infinite distance. */ if (rib->distance == DISTANCE_INFINITY) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); continue; } @@ -1761,30 +1761,30 @@ rib_process (struct route_node *rn) if (select->type != ZEBRA_ROUTE_CONNECT || rib->metric <= select->metric) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); select = rib; } else - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); continue; } else if (select->type == ZEBRA_ROUTE_CONNECT) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); continue; } /* higher distance loses */ if (rib->distance > select->distance) { - UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); continue; } /* lower wins */ if (rib->distance < select->distance) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); select = rib; continue; } @@ -1792,7 +1792,7 @@ rib_process (struct route_node *rn) /* metric tie-breaks equal distance */ if (rib->metric <= select->metric) { - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); select = rib; } } /* RNODE_FOREACH_RIB_SAFE */ @@ -1823,7 +1823,7 @@ rib_process (struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB) rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p", (void *)select, (void *)fib); - if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) + if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED)) { if (info->safi == SAFI_UNICAST) zfpm_trigger_update (rn, "updating existing route"); @@ -1865,7 +1865,7 @@ rib_process (struct route_node *rn) rib_uninstall_kernel (rn, select); UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); } - UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); } else if (! RIB_SYSTEM_ROUTE (select)) { @@ -1918,7 +1918,7 @@ rib_process (struct route_node *rn) /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); } /* Regardless of some RIB entry being SELECTED or not before, now we can @@ -1988,7 +1988,7 @@ rib_process (struct route_node *rn) redistribute_delete(&rn->p, fib); } } - UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); + UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); } #endif diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 03ae466997..b3cc6f44c0 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -593,7 +593,7 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, vrfid, bufn, bufs); } - SET_FLAG(srib->flags, ZEBRA_FLAG_CHANGED); + SET_FLAG(srib->flags, RIB_ENTRY_CHANGED); SET_FLAG(srib->status, RIB_ENTRY_NEXTHOPS_CHANGED); rib_queue_add(static_rn); } From 2b50b6031ceb1c960337dd263c91095c4fd27696 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 21 Aug 2016 12:59:48 -0400 Subject: [PATCH 149/226] zebra: Fix cherry-pick of ZEBRA_FLAG_CHANGED When cherrypicking I did not notice the move of the flag from flags -> status. Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 40 ++++++++++++++++++++-------------------- zebra/zebra_rnh.c | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index c1bceee9e6..0dc8086906 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1224,15 +1224,15 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && !(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6)))) { - SET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + SET_FLAG (rib->status, RIB_ENTRY_CHANGED); SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } } if (old_num_nh != rib->nexthop_active_num) - SET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + SET_FLAG (rib->status, RIB_ENTRY_CHANGED); - if (CHECK_FLAG (rib->flags, RIB_ENTRY_CHANGED)) + if (CHECK_FLAG (rib->status, RIB_ENTRY_CHANGED)) { SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); } @@ -1429,7 +1429,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active or not. */ if (!nexthop_active_update (rn, select, 1)) { - UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); return; } @@ -1455,7 +1455,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update for redistribution. */ if (installed) redistribute_update (&rn->p, select, NULL); - UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } static void @@ -1482,7 +1482,7 @@ rib_process_del_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Update nexthop for route, reset changed flag. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } static void @@ -1503,7 +1503,7 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, * something has changed. */ if (select != fib || - CHECK_FLAG (select->flags, RIB_ENTRY_CHANGED)) + CHECK_FLAG (select->status, RIB_ENTRY_CHANGED)) { zfpm_trigger_update (rn, "updating existing route"); @@ -1623,11 +1623,11 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } /* Clear changed flag. */ - UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } /* Core function for processing routing information base. */ @@ -1707,7 +1707,7 @@ rib_process (struct route_node *rn) * the nexthop_active_update() code. Thus, we might miss changes to * recursive NHs. */ - if (!CHECK_FLAG(rib->flags, RIB_ENTRY_CHANGED) && + if (!CHECK_FLAG(rib->status, RIB_ENTRY_CHANGED) && ! nexthop_active_update (rn, rib, 0)) { if (rib->type == ZEBRA_ROUTE_TABLE) @@ -1735,7 +1735,7 @@ rib_process (struct route_node *rn) /* Infinite distance. */ if (rib->distance == DISTANCE_INFINITY) { - UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } @@ -1761,30 +1761,30 @@ rib_process (struct route_node *rn) if (select->type != ZEBRA_ROUTE_CONNECT || rib->metric <= select->metric) { - UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; } else - UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } else if (select->type == ZEBRA_ROUTE_CONNECT) { - UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } /* higher distance loses */ if (rib->distance > select->distance) { - UNSET_FLAG (rib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); continue; } /* lower wins */ if (rib->distance < select->distance) { - UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; continue; } @@ -1792,7 +1792,7 @@ rib_process (struct route_node *rn) /* metric tie-breaks equal distance */ if (rib->metric <= select->metric) { - UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); select = rib; } } /* RNODE_FOREACH_RIB_SAFE */ @@ -1865,7 +1865,7 @@ rib_process (struct route_node *rn) rib_uninstall_kernel (rn, select); UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); } - UNSET_FLAG (select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); } else if (! RIB_SYSTEM_ROUTE (select)) { @@ -1918,7 +1918,7 @@ rib_process (struct route_node *rn) /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); } /* Regardless of some RIB entry being SELECTED or not before, now we can @@ -1988,7 +1988,7 @@ rib_process (struct route_node *rn) redistribute_delete(&rn->p, fib); } } - UNSET_FLAG(select->flags, RIB_ENTRY_CHANGED); + UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } #endif diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index b3cc6f44c0..55c428067b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -593,7 +593,7 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, vrfid, bufn, bufs); } - SET_FLAG(srib->flags, RIB_ENTRY_CHANGED); + SET_FLAG(srib->status, RIB_ENTRY_CHANGED); SET_FLAG(srib->status, RIB_ENTRY_NEXTHOPS_CHANGED); rib_queue_add(static_rn); } From c50ca33acf29bb269e8f26be19a8ccd06ab41d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 2 Nov 2015 16:50:07 +0200 Subject: [PATCH 150/226] zebra: implement per-route mtu handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commits allow overriding MTU using netlink attributes on per-route basis. This is useful for routing protocols that can advertice prefix specific MTUs between routers (e.g. NHRP). Signed-off-by: Timo Teräs (cherry picked from commit b11f3b54c842117e22e2f5cf1561ea34eee8dfcc) --- lib/zclient.c | 8 ++++++ lib/zclient.h | 5 ++++ zebra/connected.c | 6 ++--- zebra/kernel_socket.c | 6 +++-- zebra/redistribute.c | 3 ++- zebra/rib.h | 9 +++++-- zebra/rt_netlink.c | 57 ++++++++++++++++++++++++++++++++++++++----- zebra/zebra_rib.c | 14 ++++++++--- zebra/zebra_vty.c | 2 ++ zebra/zserv.c | 17 +++++++++++++ 10 files changed, 110 insertions(+), 17 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index a28db083cb..0259af5971 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -709,6 +709,8 @@ zclient_connect (struct thread *t) * * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 2 byte value * + * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value + * * XXX: No attention paid to alignment. */ int @@ -769,6 +771,8 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -834,6 +838,8 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -898,6 +904,8 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, stream_putl (s, api->metric); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) stream_putw (s, api->tag); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) + stream_putl (s, api->mtu); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); diff --git a/lib/zclient.h b/lib/zclient.h index 8926bbbe63..c42d8c9aa3 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -116,6 +116,7 @@ struct zclient #define ZAPI_MESSAGE_DISTANCE 0x04 #define ZAPI_MESSAGE_METRIC 0x08 #define ZAPI_MESSAGE_TAG 0x10 +#define ZAPI_MESSAGE_MTU 0x20 /* Zserv protocol message header */ struct zserv_header @@ -154,6 +155,8 @@ struct zapi_ipv4 u_short tag; + u_int32_t mtu; + vrf_id_t vrf_id; }; @@ -237,6 +240,8 @@ struct zapi_ipv6 u_short tag; + u_int32_t mtu; + vrf_id_t vrf_id; }; diff --git a/zebra/connected.c b/zebra/connected.c index 42b5a8ab9c..3077272221 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -201,10 +201,10 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) return; rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", @@ -379,7 +379,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) #endif rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 638062d5d6..c5763dd46f 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -974,7 +974,8 @@ rtm_read (struct rt_msghdr *rtm) || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, + 0, 0, 0, 0, SAFI_UNICAST); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, 0, SAFI_UNICAST); @@ -1016,7 +1017,8 @@ rtm_read (struct rt_msghdr *rtm) || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, + 0, 0, 0, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, SAFI_UNICAST); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4238d8329e..892bc2af2b 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -578,7 +578,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, gate, &nhop->src.ipv4, nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, - rib->metric, + rib->metric, rib->mtu, zebra_import_table_distance[AFI_IP][rib->table], SAFI_UNICAST); } @@ -589,6 +589,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char newrib->distance = zebra_import_table_distance[AFI_IP][rib->table]; newrib->flags = rib->flags; newrib->metric = rib->metric; + newrib->mtu = rib->mtu; newrib->table = zebrad.rtm_table_default; newrib->nexthop_num = 0; newrib->uptime = time(NULL); diff --git a/zebra/rib.h b/zebra/rib.h index a2109d8c17..095b9c6f8f 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -64,6 +64,10 @@ struct rib /* Metric */ u_int32_t metric; + /* MTU */ + u_int32_t mtu; + u_int32_t nexthop_mtu; + /* Distance. */ u_char distance; @@ -376,7 +380,7 @@ extern int zebra_check_addr (struct prefix *p); extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t, u_char, safi_t); + u_int32_t, u_int32_t, u_char, safi_t); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); @@ -417,7 +421,8 @@ static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex extern int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi); + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance, safi_t safi); extern int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d93a530317..49dcd1e6de 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -866,6 +866,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, int index; int table; int metric; + u_int32_t mtu = 0; void *dest; void *gate; @@ -937,6 +938,18 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (tb[RTA_PRIORITY]) metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + if (tb[RTA_METRICS]) + { + struct rtattr *mxrta[RTAX_MAX+1]; + + memset (mxrta, 0, sizeof mxrta); + netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + } + if (rtm->rtm_family == AF_INET) { struct prefix_ipv4 p; @@ -946,7 +959,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - vrf_id, table, metric, 0, SAFI_UNICAST); + vrf_id, table, metric, mtu, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -962,6 +975,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, rib->distance = 0; rib->flags = flags; rib->metric = metric; + rib->mtu = mtu; rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; @@ -1014,7 +1028,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, p.prefixlen = rtm->rtm_dst_len; rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + table, metric, mtu, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -1051,6 +1065,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int index; int table; int metric; + u_int32_t mtu = 0; void *dest; void *gate; @@ -1142,8 +1157,23 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (tb[RTA_PREFSRC]) src = RTA_DATA (tb[RTA_PREFSRC]); - if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + if (h->nlmsg_type == RTM_NEWROUTE) + { + if (tb[RTA_PRIORITY]) + metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + + if (tb[RTA_METRICS]) + { + struct rtattr *mxrta[RTAX_MAX+1]; + + memset (mxrta, 0, sizeof mxrta); + netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + } + } if (rtm->rtm_family == AF_INET) { @@ -1164,7 +1194,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, { if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + table, metric, mtu, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -1180,6 +1210,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, rib->distance = 0; rib->flags = 0; rib->metric = metric; + rib->mtu = mtu; rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; @@ -1248,7 +1279,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (h->nlmsg_type == RTM_NEWROUTE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, - table, metric, 0, SAFI_UNICAST); + table, metric, mtu, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, vrf_id, table, SAFI_UNICAST); @@ -2079,6 +2110,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, addattr32(&req.n, sizeof req, RTA_TABLE, rib->table); } + if (rib->mtu || rib->nexthop_mtu) + { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *) buf; + u_int32_t mtu = rib->mtu; + if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu)) + mtu = rib->nexthop_mtu; + rta->rta_type = RTA_METRICS; + rta->rta_len = RTA_LENGTH(0); + rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); + addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta), + RTA_PAYLOAD (rta)); + } + if (discard) { if (cmd == RTM_NEWROUTE) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0dc8086906..195d3633e1 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -352,6 +352,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, zebra_deregister_rnh_static_nexthops(rib->vrf_id, nexthop->resolved, top); nexthops_free(nexthop->resolved); nexthop->resolved = NULL; + rib->nexthop_mtu = 0; } /* Skip nexthops that have been filtered out due to route-map */ @@ -545,6 +546,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, } resolved = 1; } + if (resolved && set) + rib->nexthop_mtu = match->mtu; return resolved; } else @@ -2414,7 +2417,7 @@ int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t metric, u_char distance, safi_t safi) + u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi) { struct rib *rib; struct rib *same = NULL; @@ -2481,6 +2484,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, rib->distance = distance; rib->flags = flags; rib->metric = metric; + rib->mtu = mtu; rib->table = table_id; rib->vrf_id = vrf_id; rib->nexthop_num = 0; @@ -2554,9 +2558,10 @@ void _rib_dump (const char * func, ); zlog_debug ( - "%s: metric == %u, distance == %u, flags == %u, status == %u", + "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", func, rib->metric, + rib->mtu, rib->distance, rib->flags, rib->status @@ -2992,6 +2997,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro rib->instance = 0; rib->distance = si->distance; rib->metric = 0; + rib->mtu = 0; rib->vrf_id = si->vrf_id; rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; rib->nexthop_num = 0; @@ -3342,7 +3348,8 @@ static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance, safi_t safi) { struct rib *rib; struct rib *same = NULL; @@ -3401,6 +3408,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, rib->distance = distance; rib->flags = flags; rib->metric = metric; + rib->mtu = mtu; rib->table = table_id; rib->vrf_id = vrf_id; rib->nexthop_num = 0; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index e9090cbed2..ff2f7c7bc4 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1929,6 +1929,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); if (rib->tag) vty_out (vty, ", tag %d", rib->tag); + if (rib->mtu) + vty_out (vty, ", mtu %u", rib->mtu); if (rib->vrf_id != VRF_DEFAULT) { zvrf = vrf_info_lookup(rib->vrf_id); diff --git a/zebra/zserv.c b/zebra/zserv.c index a1fe9bc188..84881e14a4 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -695,6 +695,8 @@ zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p, SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); stream_putw(s, rib->tag); } + SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU); + stream_putl (s, rib->mtu); } /* write real message flags value */ @@ -1264,6 +1266,11 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* Table */ rib->table = zvrf->table_id; @@ -1518,6 +1525,11 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* Table */ rib->table = zvrf->table_id; @@ -1636,6 +1648,11 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) else rib->tag = 0; + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + else + rib->mtu = 0; + /* VRF ID */ rib->vrf_id = zvrf->vrf_id; rib->table = zvrf->table_id; From 53519ae74ad7e87d02758acd407d1b1d1e5575cb Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 22 Aug 2016 12:37:13 +0000 Subject: [PATCH 151/226] quagga route-map on-match and continue statements accept 65536 Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12581 --- lib/routemap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/routemap.c b/lib/routemap.c index d8d1872d65..9267056df6 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1591,7 +1591,7 @@ DEFUN (rmap_onmatch_goto, } if (argc == 1 && argv[0]) - VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 65536); + VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 65535); else d = index->pref + 1; @@ -1669,7 +1669,7 @@ DEFUN (rmap_show_name, ALIAS (rmap_onmatch_goto, rmap_continue_index_cmd, - "continue <1-65536>", + "continue <1-65535>", "Exit policy on matches\n" "Goto Clause number\n") From f43e655ed8d2fae1bf76aa32485cadf4de23be42 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 24 Aug 2016 12:11:00 -0300 Subject: [PATCH 152/226] bgpd: fix build on Solaris * Solaris doesn't have u_int64_t, so use uint64_t instead. C99-style fixed-width integers should always be preferred to improve portability; * 's_addr' is a macro on Solaris, so we can't use it as a variable name. Rename the 's_addr' variable to 'addr' in the bgp_peer_conf_if_to_su_update_v4() function. Signed-off-by: Renato Westphal --- bgpd/bgp_table.h | 8 ++++---- bgpd/bgp_updgrp.c | 4 ++-- bgpd/bgp_updgrp.h | 20 ++++++++++---------- bgpd/bgp_updgrp_adv.c | 6 +++--- bgpd/bgp_vty.c | 24 ++++++++++++------------ bgpd/bgpd.c | 20 ++++++++++---------- bgpd/bgpd.h | 6 +++--- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 1114c37010..2f839c4af7 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -35,7 +35,7 @@ struct bgp_table struct peer *owner; struct route_table *route_table; - u_int64_t version; + uint64_t version; }; struct bgp_node @@ -56,7 +56,7 @@ struct bgp_node struct bgp_node *prn; - u_int64_t version; + uint64_t version; u_char flags; #define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_USER_CLEAR (1 << 1) @@ -311,13 +311,13 @@ bgp_table_iter_started (bgp_table_iter_t * iter) /* This would benefit from a real atomic operation... * until then. */ -static inline u_int64_t +static inline uint64_t bgp_table_next_version (struct bgp_table *table) { return ++table->version; } -static inline u_int64_t +static inline uint64_t bgp_table_version (struct bgp_table *table) { return table->version; diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index cd7710b501..29e6243a1a 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -668,7 +668,7 @@ updgrp_show_packet_queue_walkcb (struct update_group *updgrp, void *arg) */ void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { struct updwalk_context ctx; @@ -1587,7 +1587,7 @@ update_bgp_group_free (struct bgp *bgp) void update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t subgrp_id) + uint64_t subgrp_id) { struct updwalk_context ctx; memset (&ctx, 0, sizeof (ctx)); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index aab2458b30..6ab384369c 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -133,7 +133,7 @@ struct update_group safi_t safi; int afid; - u_int64_t id; + uint64_t id; time_t uptime; u_int32_t join_events; @@ -231,8 +231,8 @@ struct update_subgroup */ struct { - u_int64_t update_group_id; - u_int64_t subgroup_id; + uint64_t update_group_id; + uint64_t subgroup_id; } split_from; u_int32_t join_events; @@ -248,7 +248,7 @@ struct update_subgroup u_int32_t split_events; u_int32_t merge_checks_triggered; - u_int64_t id; + uint64_t id; struct zlog *log; u_int16_t sflags; @@ -297,8 +297,8 @@ struct updwalk_context struct vty *vty; struct bgp_node *rn; struct bgp_info *ri; - u_int64_t updgrp_id; - u_int64_t subgrp_id; + uint64_t updgrp_id; + uint64_t subgrp_id; bgp_policy_type_e policy_type; const char *policy_name; int policy_event_start_flag; @@ -367,7 +367,7 @@ extern void update_bgp_group_init (struct bgp *); extern void udpate_bgp_group_free (struct bgp *); extern void -update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, u_int64_t subgrp_id); +update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id); extern void update_group_show_stats (struct bgp *bgp, struct vty *vty); extern void update_group_adjust_peer (struct peer_af *paf); extern int update_group_adjust_soloness (struct peer *peer, int set); @@ -439,13 +439,13 @@ extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct *adj); extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - u_int64_t id); + uint64_t id); extern void subgroup_announce_route (struct update_subgroup *subgrp); extern void subgroup_announce_all (struct update_subgroup *subgrp); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 96bcd011ca..c485e61e5c 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -277,7 +277,7 @@ updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg) static void updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id, u_int8_t flags) + struct vty *vty, uint64_t id, u_int8_t flags) { struct updwalk_context ctx; memset (&ctx, 0, sizeof (ctx)); @@ -850,14 +850,14 @@ group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi, void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE); } void update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, u_int64_t id) + struct vty *vty, uint64_t id) { updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED); } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bb074dc027..66f3290729 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -13013,7 +13013,7 @@ DEFUN (show_ip_bgp_attr_info, static int bgp_show_update_groups(struct vty *vty, const char *name, int afi, int safi, - u_int64_t subgrp_id) + uint64_t subgrp_id) { struct bgp *bgp; @@ -13140,7 +13140,7 @@ DEFUN (show_ip_bgp_updgrps_s, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); return (bgp_show_update_groups(vty, NULL, AFI_IP, SAFI_UNICAST, subgrp_id)); @@ -13156,7 +13156,7 @@ DEFUN (show_ip_bgp_instance_updgrps_s, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); return (bgp_show_update_groups(vty, argv[1], AFI_IP, SAFI_UNICAST, subgrp_id)); @@ -13170,7 +13170,7 @@ DEFUN (show_bgp_ipv6_updgrps_s, "Detailed info about v6 dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); return(bgp_show_update_groups(vty, NULL, AFI_IP6, SAFI_UNICAST, subgrp_id)); @@ -13184,7 +13184,7 @@ DEFUN (show_bgp_instance_ipv6_updgrps_s, "Detailed info about v6 dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); return(bgp_show_update_groups(vty, argv[1], AFI_IP6, SAFI_UNICAST, subgrp_id)); @@ -13204,7 +13204,7 @@ DEFUN (show_bgp_updgrps_s, { afi_t afi; safi_t safi; - u_int64_t subgrp_id; + uint64_t subgrp_id; afi = (strcmp(argv[0], "ipv4") == 0) ? AFI_IP : AFI_IP6; safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; @@ -13251,7 +13251,7 @@ DEFUN (show_bgp_instance_updgrps_stats, static void show_bgp_updgrps_adj_info_aux (struct vty *vty, const char *name, afi_t afi, safi_t safi, - const char *what, u_int64_t subgrp_id) + const char *what, uint64_t subgrp_id) { struct bgp *bgp; @@ -13370,7 +13370,7 @@ DEFUN (show_ip_bgp_updgrps_adj_s, "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); @@ -13392,7 +13392,7 @@ DEFUN (show_ip_bgp_instance_updgrps_adj_s, "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); @@ -13418,7 +13418,7 @@ DEFUN (show_bgp_updgrps_afi_adj_s, { afi_t afi; safi_t safi; - u_int64_t subgrp_id; + uint64_t subgrp_id; afi = (strcmp(argv[0], "ipv4") == 0) ? AFI_IP : AFI_IP6; safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; @@ -13439,7 +13439,7 @@ DEFUN (show_bgp_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[0]); @@ -13459,7 +13459,7 @@ DEFUN (show_bgp_instance_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - u_int64_t subgrp_id; + uint64_t subgrp_id; VTY_GET_ULL("subgroup-id", subgrp_id, argv[2]); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 71ccf7c90d..b18572c07a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1295,7 +1295,7 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) { struct connected *ifc; struct prefix p; - u_int32_t s_addr; + u_int32_t addr; struct listnode *node; /* If our IPv4 address on the interface is /30 or /31, we can derive the @@ -1309,11 +1309,11 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) if (p.prefixlen == 30) { peer->su.sa.sa_family = AF_INET; - s_addr = ntohl(p.u.prefix4.s_addr); - if (s_addr % 4 == 1) - peer->su.sin.sin_addr.s_addr = htonl(s_addr+1); - else if (s_addr % 4 == 2) - peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 4 == 1) + peer->su.sin.sin_addr.s_addr = htonl(addr+1); + else if (addr % 4 == 2) + peer->su.sin.sin_addr.s_addr = htonl(addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ @@ -1322,11 +1322,11 @@ bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) else if (p.prefixlen == 31) { peer->su.sa.sa_family = AF_INET; - s_addr = ntohl(p.u.prefix4.s_addr); - if (s_addr % 2 == 0) - peer->su.sin.sin_addr.s_addr = htonl(s_addr+1); + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 2 == 0) + peer->su.sin.sin_addr.s_addr = htonl(addr+1); else - peer->su.sin.sin_addr.s_addr = htonl(s_addr-1); + peer->su.sin.sin_addr.s_addr = htonl(addr-1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN peer->su.sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index d9a68599c5..e8827ca91f 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -112,8 +112,8 @@ struct bgp_master #define BGP_OPT_CONFIG_CISCO (1 << 2) #define BGP_OPT_NO_LISTEN (1 << 3) - u_int64_t updgrp_idspace; - u_int64_t subgrp_idspace; + uint64_t updgrp_idspace; + uint64_t subgrp_idspace; /* timer to dampen route map changes */ struct thread *t_rmap_update; /* Handle route map updates */ @@ -518,7 +518,7 @@ struct peer /* BGP peer group. */ struct peer_group *group; - u_int64_t version[AFI_MAX][SAFI_MAX]; + uint64_t version[AFI_MAX][SAFI_MAX]; /* BGP peer_af structures, per configured AF on this peer */ struct peer_af *peer_af_array[BGP_AF_MAX]; From 2f35bbfe7453f5c7f6f81a3bea83be38232f75c5 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Jan 2016 13:42:03 -0500 Subject: [PATCH 153/226] bgp: Reorg cleanup to align process and bgp instance init/destroy bgp_address_destroy became per-bgp instance. Moved the call to the bgp_address_destroy function to the bgp delete. Signed-off-by: Lou Berger (cherry picked from commit 637035710a2f8e1e5944ee714135b7f88ac15ac4) --- bgpd/bgp_main.c | 5 ++--- bgpd/bgpd.c | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 0d24c9c294..20fa138ce8 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -227,7 +227,6 @@ bgp_exit (int status) { struct bgp *bgp; struct listnode *node, *nnode; - extern struct zclient *zclient; /* it only makes sense for this to be called on a clean exit */ assert (status == 0); @@ -277,8 +276,8 @@ bgp_exit (int status) bgp_vrf_terminate (); cmd_terminate (); vty_terminate (); - if (zclient) - zclient_free (zclient); + + bgp_zebra_destroy(); if (bgp_nexthop_buf) stream_free (bgp_nexthop_buf); if (bgp_ifindices_buf) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index b18572c07a..f63f3f8f94 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3178,6 +3178,8 @@ bgp_delete (struct bgp *bgp) /* Free interfaces in this instance. */ bgp_if_finish (bgp); + bgp_address_destroy (bgp); + thread_master_free_unused(bm->master); bgp_unlock(bgp); /* initial reference */ From 4e851f1fa711946a7c8cea17ef41df76336881a9 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Jan 2016 13:42:05 -0500 Subject: [PATCH 154/226] bgpd: cleanup vty bgp_node_afi/safi utils Signed-off-by: Lou Berger (cherry picked from commit 135ca1502cc54d9ad00b60b3410a0932bfeceb29) --- bgpd/bgp_vty.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 66f3290729..276fe16e78 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -63,12 +63,20 @@ listen_range_exists (struct bgp *bgp, struct prefix *range, int exact); afi_t bgp_node_afi (struct vty *vty) { - if (vty->node == BGP_IPV6_NODE || - vty->node == BGP_IPV6M_NODE || - vty->node == BGP_VPNV6_NODE || - vty->node == BGP_ENCAPV6_NODE) - return AFI_IP6; - return AFI_IP; + afi_t afi; + switch (vty->node) + { + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_VPNV6_NODE: + case BGP_ENCAPV6_NODE: + afi = AFI_IP6; + break; + default: + afi = AFI_IP; + break; + } + return afi; } /* Utility function to get subsequent address family from current @@ -76,13 +84,26 @@ bgp_node_afi (struct vty *vty) safi_t bgp_node_safi (struct vty *vty) { - if (vty->node == BGP_VPNV4_NODE || vty->node == BGP_VPNV6_NODE) - return SAFI_MPLS_VPN; - if (vty->node == BGP_ENCAP_NODE || vty->node == BGP_ENCAPV6_NODE) - return SAFI_ENCAP; - if (vty->node == BGP_IPV4M_NODE || vty->node == BGP_IPV6M_NODE) - return SAFI_MULTICAST; - return SAFI_UNICAST; + safi_t safi; + switch (vty->node) + { + case BGP_ENCAP_NODE: + case BGP_ENCAPV6_NODE: + safi = SAFI_ENCAP; + break; + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + safi = SAFI_MPLS_VPN; + break; + case BGP_IPV4M_NODE: + case BGP_IPV6M_NODE: + safi = SAFI_MULTICAST; + break; + default: + safi = SAFI_UNICAST; + break; + } + return safi; } int From ea8b7c71a7d5fd7f49cd4ffe60b065dd2058b45d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 26 Aug 2016 20:46:24 -0300 Subject: [PATCH 155/226] build/solaris: fix one error and a few warnings Signed-off-by: Renato Westphal --- bgpd/bgp_mplsvpn.c | 4 ++-- bgpd/bgp_network.c | 2 ++ lib/bfd.c | 4 ++-- pimd/pim_cmd.c | 8 ++++---- zebra/rtread_getmsg.c | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 4650495faf..c22dbb05a9 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -482,7 +482,7 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u { u_int16_t type; struct rd_as rd_as; - struct rd_ip rd_ip = { 0, { 0 }, 0}; + struct rd_ip rd_ip = {0}; u_char *pnt; pnt = rn->p.u.val; @@ -672,7 +672,7 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty { u_int16_t type; struct rd_as rd_as; - struct rd_ip rd_ip = { 0, { 0 }, 0}; + struct rd_ip rd_ip = {0}; u_char *pnt; pnt = rn->p.u.val; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index ed1c5600ee..58761a11d0 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -63,7 +63,9 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password) { int ret = -1; int en = ENOSYS; +#if HAVE_DECL_TCP_MD5SIG union sockunion su2; +#endif /* HAVE_TCP_MD5SIG */ assert (socket >= 0); diff --git a/lib/bfd.c b/lib/bfd.c index 2116fa5c1f..67a84c95f9 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -504,8 +504,8 @@ bfd_client_sendmsg (struct zclient *zclient, int command) if (ret < 0) { if (bfd_debug) - zlog_debug ("bfd_client_sendmsg %d: zclient_send_message() failed", - getpid()); + zlog_debug ("bfd_client_sendmsg %ld: zclient_send_message() failed", + (long) getpid()); return; } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 54ed11da81..6cfed0f2c6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2087,10 +2087,10 @@ static void show_multicast_interfaces(struct vty *vty) inet_ntoa(ifaddr), ifp->ifindex, pim_ifp->mroute_vif_index, - vreq.icount, - vreq.ocount, - vreq.ibytes, - vreq.obytes, + (unsigned long) vreq.icount, + (unsigned long) vreq.ocount, + (unsigned long) vreq.ibytes, + (unsigned long) vreq.obytes, VTY_NEWLINE); } } diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 6d2edde640..9defa49bfd 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -91,7 +91,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) gateway.s_addr = routeEntry->ipRouteNextHop; rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); + &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST); } void From 18a4ded2a72cc5613f54845dd29c1ee7d05bbf04 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 29 Aug 2016 19:59:53 +0000 Subject: [PATCH 156/226] json support for "show ip route" for "show ipv6 route" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12633 --- zebra/zebra_vty.c | 360 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 297 insertions(+), 63 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ff2f7c7bc4..3c2626670b 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -35,13 +35,18 @@ #include "zebra/zebra_rnh.h" #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" +#include "lib/json.h" extern int allow_delete; -static int do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi); +static int do_show_ip_route(struct vty *vty, const char *vrf_name, + safi_t safi, u_char use_json); static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast); +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND 60*60*24*7 + /* General function for static route. */ static int zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, @@ -278,7 +283,7 @@ DEFUN (show_ip_rpf, IP_STR "Display RPF information for multicast source\n") { - return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST); + return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST, 0); } DEFUN (show_ip_rpf_addr, @@ -1946,8 +1951,6 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) vty_out (vty, ", reject"); vty_out (vty, "%s", VTY_NEWLINE); -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 if (rib->type == ZEBRA_ROUTE_RIP || rib->type == ZEBRA_ROUTE_OSPF || rib->type == ZEBRA_ROUTE_ISIS @@ -2050,12 +2053,151 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) } static void -vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) +vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, + json_object *json) { struct nexthop *nexthop, *tnexthop; int recursing; int len = 0; char buf[BUFSIZ]; + json_object *json_nexthops = NULL; + json_object *json_nexthop = NULL; + json_object *json_route = NULL; + + if (json) + { + json_route = json_object_new_object(); + json_nexthops = json_object_new_array(); + + json_object_string_add(json_route, "prefix", prefix2str (&rn->p, buf, sizeof buf)); + json_object_string_add(json_route, "protocol", zebra_route_string(rib->type)); + + if (rib->instance) + json_object_int_add(json_route, "instance", rib->instance); + + if (rib->vrf_id) + json_object_int_add(json_route, "vrfId", rib->vrf_id); + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) + json_object_boolean_true_add(json_route, "selected"); + + if (rib->type != ZEBRA_ROUTE_CONNECT && rib->type != ZEBRA_ROUTE_KERNEL) + { + json_object_int_add(json_route, "distance", rib->distance); + json_object_int_add(json_route, "metric", rib->metric); + } + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) + json_object_boolean_true_add(json_route, "blackhole"); + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) + json_object_boolean_true_add(json_route, "reject"); + + if (rib->type == ZEBRA_ROUTE_RIP + || rib->type == ZEBRA_ROUTE_OSPF + || rib->type == ZEBRA_ROUTE_ISIS + || rib->type == ZEBRA_ROUTE_TABLE + || rib->type == ZEBRA_ROUTE_BGP) + { + time_t uptime; + struct tm *tm; + + uptime = time (NULL); + uptime -= rib->uptime; + tm = gmtime (&uptime); + + if (uptime < ONE_DAY_SECOND) + sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, tm->tm_min); + else + sprintf(buf, "%02dw%dd%02dh", tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); + + json_object_string_add(json_route, "uptime", buf); + } + + for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) + { + json_nexthop = json_object_new_object(); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + json_object_boolean_true_add(json_nexthop, "fib"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(json_nexthop, "ip", inet_ntoa (nexthop->gate.ipv4)); + json_object_string_add(json_nexthop, "afi", "ipv4"); + + if (nexthop->ifindex) + { + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add(json_nexthop, "ip", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + json_object_string_add(json_nexthop, "afi", "ipv6"); + + if (nexthop->ifindex) + { + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + } + break; + + case NEXTHOP_TYPE_IFINDEX: + json_object_boolean_true_add(json_nexthop, "directlyConnected"); + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + json_object_boolean_true_add(json_nexthop, "blackhole"); + break; + default: + break; + } + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + json_object_boolean_true_add(json_nexthop, "active"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) + json_object_boolean_true_add(json_nexthop, "onLink"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + json_object_boolean_true_add(json_nexthop, "recursive"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) + { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) + json_object_string_add(json_nexthop, "source", buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) + json_object_string_add(json_nexthop, "source", buf); + } + break; + default: + break; + } + + json_object_array_add(json_nexthops, json_nexthop); + } + + json_object_object_add(json_route, "nexthops", json_nexthops); + json_object_array_add(json, json_route); + return; + } /* Nexthop information. */ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) @@ -2162,9 +2304,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) uptime -= rib->uptime; tm = gmtime (&uptime); -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 - if (uptime < ONE_DAY_SECOND) vty_out (vty, ", %02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -2182,62 +2321,112 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) DEFUN (show_ip_route, show_ip_route_cmd, - "show ip route", + "show ip route {json}", SHOW_STR IP_STR "IP routing table\n") { - return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST); + return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST, use_json(argc, argv)); } static int -do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi) +do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi, + u_char use_json) { struct route_table *table; struct route_node *rn; struct rib *rib; int first = 1; struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; if (!(zvrf = zebra_vrf_list_lookup_by_name (vrf_name))) { - vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE); + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE); return CMD_SUCCESS; } if (zvrf->vrf_id == VRF_UNKNOWN) { - vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE); + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE); return CMD_SUCCESS; } table = zebra_vrf_table (AFI_IP, safi, zvrf->vrf_id); if (! table) - return CMD_SUCCESS; + { + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + if (use_json) + { + json = json_object_new_object(); + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (!json_prefix) + json_prefix = json_object_new_array(); + vty_show_ip_route (vty, rn, rib, json_prefix); + } + + if (json_prefix) + { + prefix2str (&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } + else + { + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); + } + } + } - /* Show all IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } return CMD_SUCCESS; } DEFUN (show_ip_route_vrf, show_ip_route_vrf_cmd, - "show ip route " VRF_CMD_STR, + "show ip route " VRF_CMD_STR " {json}", SHOW_STR IP_STR "IP routing table\n" VRF_CMD_HELP_STR) { - return do_show_ip_route (vty, argv[0], SAFI_UNICAST); + u_char uj = use_json(argc, argv); + + if (argc == 1 && uj) + return do_show_ip_route (vty, NULL, SAFI_UNICAST, uj); + else + return do_show_ip_route (vty, argv[0], SAFI_UNICAST, uj); } DEFUN (show_ip_nht, @@ -2432,7 +2621,7 @@ DEFUN (show_ip_route_tag, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2492,7 +2681,7 @@ DEFUN (show_ip_route_prefix_longer, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2544,7 +2733,7 @@ DEFUN (show_ip_route_supernets, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } return CMD_SUCCESS; @@ -2602,7 +2791,7 @@ DEFUN (show_ip_route_protocol, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2647,7 +2836,7 @@ DEFUN (show_ip_route_ospf_instance, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -3016,7 +3205,7 @@ DEFUN (show_ip_route_vrf_all, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3070,7 +3259,7 @@ DEFUN (show_ip_route_vrf_all_tag, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3126,7 +3315,7 @@ DEFUN (show_ip_route_vrf_all_prefix_longer, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3179,7 +3368,7 @@ DEFUN (show_ip_route_vrf_all_supernets, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } vrf_header = 1; @@ -3235,7 +3424,7 @@ DEFUN (show_ip_route_vrf_all_protocol, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -4546,7 +4735,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref_tag_vrf, DEFUN (show_ipv6_route, show_ipv6_route_cmd, - "show ipv6 route", + "show ipv6 route {json}", SHOW_STR IP_STR "IPv6 routing table\n") @@ -4557,18 +4746,28 @@ DEFUN (show_ipv6_route, int first = 1; vrf_id_t vrf_id = VRF_DEFAULT; struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; + u_char uj = use_json(argc, argv); - if (argc > 0) + if (argc > 0 && argv[0] && strcmp(argv[0], "json") != 0) { if (!(zvrf = zebra_vrf_list_lookup_by_name (argv[0]))) { - vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE); + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE); return CMD_SUCCESS; } if (zvrf->vrf_id == VRF_UNKNOWN) { - vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE); + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE); return CMD_SUCCESS; } else @@ -4577,25 +4776,60 @@ DEFUN (show_ipv6_route, table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) - return CMD_SUCCESS; + { + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + if (uj) + { + json = json_object_new_object(); + + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (!json_prefix) + json_prefix = json_object_new_array(); + vty_show_ip_route (vty, rn, rib, json_prefix); + } + + if (json_prefix) + { + prefix2str (&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } + else + { + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); + } + } + } - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } return CMD_SUCCESS; } ALIAS (show_ipv6_route, show_ipv6_route_vrf_cmd, - "show ipv6 route " VRF_CMD_STR, + "show ipv6 route " VRF_CMD_STR " {json}", SHOW_STR IP_STR "IPv6 routing table\n" @@ -4641,7 +4875,7 @@ DEFUN (show_ipv6_route_tag, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4701,7 +4935,7 @@ DEFUN (show_ipv6_route_prefix_longer, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4759,7 +4993,7 @@ DEFUN (show_ipv6_route_protocol, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4985,7 +5219,7 @@ DEFUN (show_ipv6_mroute, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -5035,7 +5269,7 @@ DEFUN (show_ipv6_route_vrf_all, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5089,7 +5323,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5146,7 +5380,7 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5201,7 +5435,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5345,7 +5579,7 @@ DEFUN (show_ipv6_mroute_vrf_all, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } return CMD_SUCCESS; From 3aef92192569c33906c6a2623d0753c16c0e7a64 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 30 Aug 2016 08:59:08 -0400 Subject: [PATCH 157/226] bgpd: Add fix for multiple set commands with prefer-global In further testing, found that if there were multiple set commands in the route-map with one being prefer-global, the removal of the prefer-global was not recognized and reacted to correctly. This small addition includes that support Ticket: CM-11480 Signed-off-by: Don Slice Reviewed By: Donald Sharp Testing Done: Manual testing, bgp-min and bgp-smoke completed --- bgpd/bgp_attr.h | 2 ++ bgpd/bgp_routemap.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index a279674af2..9a8e2a75e2 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -148,6 +148,7 @@ struct attr #define BATTR_RMAP_NEXTHOP_UNCHANGED (1 << 3) #define BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED (1 << 4) #define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5) +#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6) /* Router Reflector related structure. */ struct cluster_list @@ -277,6 +278,7 @@ bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags) CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) || + CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) || CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); } diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2a4d416633..e4fd730cf0 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2215,8 +2215,14 @@ route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix, /* Set next hop preference to global */ bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE; SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); } + else + { + bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); + } } return RMAP_OKAY; } From 337299a936d9db8951825dcbf3acc4bd3b89ac32 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 31 Aug 2016 12:31:47 +0000 Subject: [PATCH 158/226] Quagga won't advertise 0.0.0.0/0 with network statement Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12561 --- zebra/zebra_rnh.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 55c428067b..7b4840164e 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -353,18 +353,17 @@ zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type, if (!rn) return NULL; - /* Do not resolve over default route unless allowed && - * match route to be exact if so specified + /* When resolving nexthops, do not resolve via the default route unless + * 'ip nht resolve-via-default' is configured. */ if ((type == RNH_NEXTHOP_TYPE) && (is_default_prefix (&rn->p) && !nh_resolve_via_default(rn->p.family))) rib = NULL; - else if ((type == RNH_IMPORT_CHECK_TYPE) && - ((is_default_prefix(&rn->p)) || - ((CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) && - !prefix_same(&nrn->p, &rn->p)))) - rib = NULL; + else if ((type == RNH_IMPORT_CHECK_TYPE) && + CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) && + !prefix_same(&nrn->p, &rn->p)) + rib = NULL; else { /* Identify appropriate route entry. */ From a782e613dd44a4447e4a9ef08cfe014e09da2b2f Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 31 Aug 2016 12:58:46 +0000 Subject: [PATCH 159/226] quagga-reload.py should be importable Signed-off-by: Daniel Walton Reviewed-by: Don Slice Ticket: CM-12686 --- tools/quagga-reload.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 781086d9da..900ed55c43 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -23,6 +23,9 @@ from ipaddr import IPv6Address from pprint import pformat +log = logging.getLogger(__name__) + + class Context(object): """ @@ -80,12 +83,12 @@ class Config(object): The internal representation has been marked appropriately by passing it through vtysh with the -m parameter """ - logger.info('Loading Config object from file %s', filename) + log.info('Loading Config object from file %s', filename) try: file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename]) except subprocess.CalledProcessError as e: - logger.error('vtysh marking of config file %s failed with error %s:', filename, str(e)) + log.error('vtysh marking of config file %s failed with error %s:', filename, str(e)) print "vtysh marking of file %s failed with error: %s" % (filename, str(e)) sys.exit(1) @@ -105,14 +108,14 @@ class Config(object): The internal representation has been marked appropriately by passing it through vtysh with the -m parameter """ - logger.info('Loading Config object from vtysh show running') + log.info('Loading Config object from vtysh show running') try: config_text = subprocess.check_output( "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -", shell=True) except subprocess.CalledProcessError as e: - logger.error('vtysh marking of running config failed with error %s:', str(e)) + log.error('vtysh marking of running config failed with error %s:', str(e)) print "vtysh marking of running config failed with error %s:" % (str(e)) sys.exit(1) @@ -259,13 +262,13 @@ end ctx_keys = [line, ] current_context_lines = [] - logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) self.save_contexts(ctx_keys, current_context_lines) new_ctx = True elif line == "end": self.save_contexts(ctx_keys, current_context_lines) - logger.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) # Start a new context new_ctx = True @@ -281,7 +284,7 @@ end # Start a new context ctx_keys = copy.deepcopy(main_ctx_key) current_context_lines = [] - logger.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys) + log.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys) elif new_ctx is True: if not main_ctx_key: @@ -292,7 +295,7 @@ end current_context_lines = [] new_ctx = False - logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) elif "address-family " in line: main_ctx_key = [] @@ -301,7 +304,7 @@ end self.save_contexts(ctx_keys, current_context_lines) current_context_lines = [] main_ctx_key = copy.deepcopy(ctx_keys) - logger.debug('LINE %-50s: entering sub-context, append to ctx_keys', line) + log.debug('LINE %-50s: entering sub-context, append to ctx_keys', line) if line == "address-family ipv6": ctx_keys.append("address-family ipv6 unicast") @@ -313,7 +316,7 @@ end else: # Continuing in an existing context, add non-commented lines to it current_context_lines.append(line) - logger.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys) + log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys) # Save the context of the last one self.save_contexts(ctx_keys, current_context_lines) @@ -699,7 +702,7 @@ if __name__ == '__main__': # argparse should prevent this from happening but just to be safe... else: raise Exception('Must specify --reload or --test') - logger = logging.getLogger(__name__) + log = logging.getLogger(__name__) # Verify the new config file is valid if not os.path.isfile(args.filename): @@ -728,9 +731,9 @@ if __name__ == '__main__': sys.exit(1) if args.debug: - logger.setLevel(logging.DEBUG) + log.setLevel(logging.DEBUG) - logger.info('Called via "%s"', str(args)) + log.info('Called via "%s"', str(args)) # Create a Config object from the config generated by newconf newconf = Config() @@ -777,7 +780,7 @@ if __name__ == '__main__': elif args.reload: - logger.debug('New Quagga Config\n%s', newconf.get_lines()) + log.debug('New Quagga Config\n%s', newconf.get_lines()) # This looks a little odd but we have to do this twice...here is why # If the user had this running bgp config: @@ -804,7 +807,7 @@ if __name__ == '__main__': for x in range(2): running = Config() running.load_from_show_running() - logger.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines()) + log.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines()) (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) @@ -844,17 +847,17 @@ if __name__ == '__main__': # 'no ip ospf authentication message-digest 1.1.1.1' in # our example above # - Split that last entry by whitespace and drop the last word - logger.warning('Failed to execute %s', ' '.join(cmd)) + log.warning('Failed to execute %s', ' '.join(cmd)) last_arg = cmd[-1].split(' ') if len(last_arg) <= 2: - logger.error('"%s" we failed to remove this command', original_cmd) + log.error('"%s" we failed to remove this command', original_cmd) break new_last_arg = last_arg[0:-1] cmd[-1] = ' '.join(new_last_arg) else: - logger.info('Executed "%s"', ' '.join(cmd)) + log.info('Executed "%s"', ' '.join(cmd)) break if lines_to_add: @@ -874,7 +877,7 @@ if __name__ == '__main__': string.digits) for _ in range(6)) filename = "/var/run/quagga/reload-%s.txt" % random_string - logger.info("%s content\n%s" % (filename, pformat(lines_to_configure))) + log.info("%s content\n%s" % (filename, pformat(lines_to_configure))) with open(filename, 'w') as fh: for line in lines_to_configure: From 6a98e6a916c18bb130430d1dcbd9f23a17ac97bd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 31 Aug 2016 13:31:16 +0200 Subject: [PATCH 160/226] zebra: stack overrun in IPv6 RA receive code (CVE ##TBA##) The IPv6 RA code also receives ICMPv6 RS and RA messages. Unfortunately, by bad coding practice, the buffer size specified on receiving such messages mixed up 2 constants that in fact have different values. The code itself has: #define RTADV_MSG_SIZE 4096 While BUFSIZ is system-dependent, in my case (x86_64 glibc): /usr/include/_G_config.h:#define _G_BUFSIZ 8192 /usr/include/libio.h:#define _IO_BUFSIZ _G_BUFSIZ /usr/include/stdio.h:# define BUFSIZ _IO_BUFSIZ As the latter is passed to the kernel on recvmsg(), it's possible to overwrite 4kB of stack -- with ICMPv6 packets that can be globally sent to any of the system's addresses (using fragmentation to get to 8k). (The socket has filters installed limiting this to RS and RA packets, but does not have a filter for source address or TTL.) Issue discovered by trying to test other stuff, which randomly caused the stack to be smaller than 8kB in that code location, which then causes the kernel to report EFAULT (Bad address). Ticket: CM-12687 Signed-off-by: David Lamparter Reviewed-by: Donald Sharp --- zebra/rtadv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rtadv.c b/zebra/rtadv.c index f3f1cee14b..93f0155fdb 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -619,7 +619,7 @@ rtadv_read (struct thread *thread) /* Register myself. */ rtadv_event (zns, RTADV_READ, sock); - len = rtadv_recv_packet (zns, sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); + len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit); if (len < 0) { From 28f6dde859dad5785aa40067a9ce611684e28fb4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 1 Sep 2016 07:20:02 -0400 Subject: [PATCH 161/226] zebra: Create zebra_static.[ch] to isolate code Isolate the zebra static_XXX functions from zebra_rib.c This is the first in a series of changes to clean up the zebra code a bit more. Signed-off-by: Donald Sharp --- zebra/Makefile.am | 6 +- zebra/rib.h | 75 +----- zebra/zebra_rib.c | 593 +---------------------------------------- zebra/zebra_static.c | 617 +++++++++++++++++++++++++++++++++++++++++++ zebra/zebra_static.h | 95 +++++++ zebra/zebra_vrf.c | 1 + zebra/zebra_vty.c | 3 +- 7 files changed, 729 insertions(+), 661 deletions(-) create mode 100644 zebra/zebra_static.c create mode 100644 zebra/zebra_static.h diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 4492f9e6d4..0218af81b7 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -31,19 +31,19 @@ zebra_SOURCES = \ redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \ irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \ $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ - zebra_ns.c zebra_vrf.c + zebra_ns.c zebra_vrf.c zebra_static.c testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \ kernel_null.c redistribute_null.c ioctl_null.c misc_null.c zebra_rnh_null.c \ - zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c + zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c zebra_static.c noinst_HEADERS = \ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \ interface.h ipforward.h irdp.h router-id.h kernel_socket.h \ rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ - zebra_ns.h zebra_vrf.h ioctl_solaris.h + zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) diff --git a/zebra/rib.h b/zebra/rib.h index 095b9c6f8f..32f370f9ef 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -175,51 +175,6 @@ typedef struct rib_dest_t_ #define RNODE_FOREACH_RIB_SAFE(rn, rib, next) \ RIB_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), rib, next) -/* Static route information. */ -struct static_route -{ - /* For linked list. */ - struct static_route *prev; - struct static_route *next; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Administrative distance. */ - u_char distance; - - /* Tag */ - u_short tag; - - /* Flag for this static route's type. */ - u_char type; -#define STATIC_IFINDEX 1 -#define STATIC_IPV4_GATEWAY 2 -#define STATIC_IPV4_BLACKHOLE 3 -#define STATIC_IPV6_GATEWAY 4 -#define STATIC_IPV6_GATEWAY_IFINDEX 5 - - /* - * Nexthop value. - * - * Under IPv4 addr and ifindex are - * used independentyly. - * STATIC_IPV4_GATEWAY uses addr - * STATIC_IFINDEX uses ifindex - */ - union g_addr addr; - ifindex_t ifindex; - - char ifname[INTERFACE_NAMSIZ + 1]; - - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ -}; - /* The following for loop allows to iterate over the nexthop * structure of routes. * @@ -365,6 +320,7 @@ extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, #define ZEBRA_RIB_FOUND_CONNECTED 2 #define ZEBRA_RIB_NOTFOUND 3 +extern void rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop); extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *); extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, @@ -374,6 +330,11 @@ extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id); extern int zebra_check_addr (struct prefix *p); +extern void rib_addnode (struct route_node *rn, struct rib *rib, int process); +extern void rib_delnode (struct route_node *rn, struct rib *rib); +extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int update); +extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib); + /* NOTE: * All rib_add_ipv[46]* functions will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ @@ -404,20 +365,6 @@ extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); extern void rib_queue_add (struct route_node *rn); -extern void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); -extern void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); - -extern int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf); - -extern int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf); - extern int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, @@ -435,20 +382,10 @@ extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t); extern struct route_table *rib_table_ipv6; -extern int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf); - extern int rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, ifindex_t); -extern int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf); - extern int rib_gc_dest (struct route_node *rn); extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 195d3633e1..0db1b0a689 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -195,7 +195,7 @@ rib_copy_nexthops (struct rib *rib, struct nexthop *nh) } /* Delete specified nexthop from the list. */ -static void +void rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop) { if (nexthop->next) @@ -1248,7 +1248,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) /* Update flag indicates whether this is a "replace" or not. Currently, this * is only used for IPv4. */ -static int +int rib_install_kernel (struct route_node *rn, struct rib *rib, int update) { int ret = 0; @@ -1303,7 +1303,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, int update) } /* Uninstall the route from kernel. */ -static int +int rib_uninstall_kernel (struct route_node *rn, struct rib *rib) { int ret = 0; @@ -1555,7 +1555,6 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); } - } /* Update for redistribution. */ @@ -2324,7 +2323,7 @@ rib_link (struct route_node *rn, struct rib *rib, int process) rib_queue_add (rn); } -static void +void rib_addnode (struct route_node *rn, struct rib *rib, int process) { /* RIB node has been un-removed before route-node is processed. @@ -2379,7 +2378,7 @@ rib_unlink (struct route_node *rn, struct rib *rib) } -static void +void rib_delnode (struct route_node *rn, struct rib *rib) { afi_t afi; @@ -2910,440 +2909,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, return 0; } -/* Install static route into rib. */ -void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) -{ - struct rib *rib; - struct route_node *rn; - struct route_table *table; - struct prefix nh_p; - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route */ - rn = route_node_get (table, p); - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) - break; - } - - if (rib) - { - /* if tag value changed , update old value in RIB */ - if (rib->tag != si->tag) - rib->tag = si->tag; - - /* Same distance static route is there. Update it with new - nexthop. */ - route_unlock_node (rn); - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - rib_nexthop_ifindex_add (rib, si->ifindex); - break; - case STATIC_IPV4_BLACKHOLE: - rib_nexthop_blackhole_add (rib); - break; - case STATIC_IPV6_GATEWAY: - rib_nexthop_ipv6_add (rib, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); - break; - } - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - /* Schedule route for processing or invoke NHT, as appropriate. */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - else - rib_queue_add (rn); - } - else - { - /* This is new static route. */ - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - - rib->type = ZEBRA_ROUTE_STATIC; - rib->instance = 0; - rib->distance = si->distance; - rib->metric = 0; - rib->mtu = 0; - rib->vrf_id = si->vrf_id; - rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; - rib->nexthop_num = 0; - rib->tag = si->tag; - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - rib_nexthop_ifindex_add (rib, si->ifindex); - break; - case STATIC_IPV4_BLACKHOLE: - rib_nexthop_blackhole_add (rib); - break; - case STATIC_IPV6_GATEWAY: - rib_nexthop_ipv6_add (rib, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); - break; - } - - /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - /* Link this rib to the tree. Schedule for processing or invoke NHT, - * as appropriate. - */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - { - rib_addnode (rn, rib, 0); - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - } - else - rib_addnode (rn, rib, 1); - } -} - -static int -static_nexthop_same (struct nexthop *nexthop, struct static_route *si) -{ - if (nexthop->type == NEXTHOP_TYPE_IPV4 - && si->type == STATIC_IPV4_GATEWAY - && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - && si->type == STATIC_IFINDEX - && nexthop->ifindex == si->ifindex) - return 1; - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE - && si->type == STATIC_IPV4_BLACKHOLE) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IPV6 - && si->type == STATIC_IPV6_GATEWAY - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) - return 1; - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX - && si->type == STATIC_IPV6_GATEWAY_IFINDEX - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) - && nexthop->ifindex == si->ifindex) - return 1; - return 0; -} - -/* Uninstall static route from RIB. */ -void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) -{ - struct route_node *rn; - struct rib *rib; - struct nexthop *nexthop; - struct route_table *table; - struct prefix nh_p; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route with type and distance. */ - rn = route_node_lookup (table, p); - if (! rn) - return; - - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && - rib->tag == si->tag) - break; - } - - if (! rib) - { - route_unlock_node (rn); - return; - } - - /* Lookup nexthop. */ - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (static_nexthop_same (nexthop, si)) - break; - - /* Can't find nexthop. */ - if (! nexthop) - { - route_unlock_node (rn); - return; - } - - /* Check nexthop. */ - if (rib->nexthop_num == 1) - rib_delnode (rn, rib); - else - { - /* Mark this nexthop as inactive and reinstall the route. Then, delete - * the nexthop. There is no need to re-evaluate the route for this - * scenario. - */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); - } - } - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - /* If there are other active nexthops, do an update. */ - if (rib->nexthop_active_num > 1) - { - rib_install_kernel (rn, rib, 1); - redistribute_update (&rn->p, rib, NULL); - } - else - { - redistribute_delete (&rn->p, rib); - rib_uninstall_kernel (rn, rib); - } - } - - if (afi == AFI_IP) - { - /* Delete the nexthop and dereg from NHT */ - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nexthop->gate.ipv4; - } - else - { - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nexthop->gate.ipv6; - } - rib_nexthop_delete (rib, nexthop); - zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); - nexthop_free (nexthop); - } - /* Unlock node. */ - route_unlock_node (rn); -} - -int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf) -{ - u_char type = 0; - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP][safi]; - - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_get (stable, p); - - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag)) - { - route_unlock_node (rn); - return 0; - } - else - update = si; - } - } - - /* Distance or tag changed. */ - if (update) - static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf->vrf_id; - si->ifindex = ifindex; - if (si->ifindex) - strcpy(si->ifname, ifname); - - if (gate) - si->addr.ipv4 = *gate; - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) - { - if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) - break; - if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) - continue; - } - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (AFI_IP, safi, p, si); - - return 1; -} - -int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf) -{ - u_char type = 0; - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, safi, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); - if (! rn) - return 0; - - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (AFI_IP, safi, p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - route_unlock_node (rn); - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - route_unlock_node (rn); - - return 1; -} int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, @@ -3707,155 +3273,6 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, return 0; } -/* Add static route into static route configuration. */ -int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; - - if (! stable) - return -1; - - if (!gate && - (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - if (!ifindex && - (type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX)) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_get (stable, p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag)) - { - route_unlock_node (rn); - return 0; - } - else - update = si; - } - } - - /* Distance or tag changed. */ - if (update) - static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf->vrf_id; - si->ifindex = ifindex; - if (si->ifindex) - strcpy (si->ifname, ifname); - - switch (type) - { - case STATIC_IPV6_GATEWAY: - si->addr.ipv6 = *gate; - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - si->addr.ipv6 = *gate; - break; - } - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (AFI_IP6, SAFI_UNICAST, p, si); - - return 1; -} - -/* Delete static route from static route configuration. */ -int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); - if (! rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (distance == si->distance - && type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - return 1; -} - /* Schedule routes of a particular table (address-family) based on event. */ static void rib_update_table (struct route_table *table, rib_update_event_t event) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c new file mode 100644 index 0000000000..9d16f12679 --- /dev/null +++ b/zebra/zebra_static.c @@ -0,0 +1,617 @@ +/* + * Static Routing Information code + * Copyright (C) 2016 Cumulus Networks + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include + +#include +#include + +#include "zebra/debug.h" +#include "zebra/rib.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/zebra_static.h" +#include "zebra/zebra_rnh.h" +#include "zebra/redistribute.h" + +/* Install static route into rib. */ +void +static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +{ + struct rib *rib; + struct route_node *rn; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table (afi, safi, si->vrf_id); + if (! table) + return; + + /* Lookup existing route */ + rn = route_node_get (table, p); + RNODE_FOREACH_RIB (rn, rib) + { + if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) + continue; + + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) + break; + } + + if (rib) + { + /* if tag value changed , update old value in RIB */ + if (rib->tag != si->tag) + rib->tag = si->tag; + + /* Same distance static route is there. Update it with new + nexthop. */ + route_unlock_node (rn); + switch (si->type) + { + case STATIC_IPV4_GATEWAY: + rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + rib_nexthop_ifindex_add (rib, si->ifindex); + break; + case STATIC_IPV4_BLACKHOLE: + rib_nexthop_blackhole_add (rib); + break; + case STATIC_IPV6_GATEWAY: + rib_nexthop_ipv6_add (rib, &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); + break; + } + + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + /* Schedule route for processing or invoke NHT, as appropriate. */ + if (si->type == STATIC_IPV4_GATEWAY || + si->type == STATIC_IPV6_GATEWAY) + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); + else + rib_queue_add (rn); + } + else + { + /* This is new static route. */ + rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); + + rib->type = ZEBRA_ROUTE_STATIC; + rib->instance = 0; + rib->distance = si->distance; + rib->metric = 0; + rib->mtu = 0; + rib->vrf_id = si->vrf_id; + rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; + rib->nexthop_num = 0; + rib->tag = si->tag; + + switch (si->type) + { + case STATIC_IPV4_GATEWAY: + rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + rib_nexthop_ifindex_add (rib, si->ifindex); + break; + case STATIC_IPV4_BLACKHOLE: + rib_nexthop_blackhole_add (rib); + break; + case STATIC_IPV6_GATEWAY: + rib_nexthop_ipv6_add (rib, &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex); + break; + } + + /* Save the flags of this static routes (reject, blackhole) */ + rib->flags = si->flags; + + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + /* Link this rib to the tree. Schedule for processing or invoke NHT, + * as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY || + si->type == STATIC_IPV6_GATEWAY) + { + rib_addnode (rn, rib, 0); + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); + } + else + rib_addnode (rn, rib, 1); + } +} +static int +static_nexthop_same (struct nexthop *nexthop, struct static_route *si) +{ + if (nexthop->type == NEXTHOP_TYPE_IPV4 + && si->type == STATIC_IPV4_GATEWAY + && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + && si->type == STATIC_IFINDEX + && nexthop->ifindex == si->ifindex) + return 1; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_IPV4_BLACKHOLE) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IPV6 + && si->type == STATIC_IPV6_GATEWAY + && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) + return 1; + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && si->type == STATIC_IPV6_GATEWAY_IFINDEX + && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) + && nexthop->ifindex == si->ifindex) + return 1; + return 0; +} + +/* Uninstall static route from RIB. */ +void +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +{ + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table (afi, safi, si->vrf_id); + if (! table) + return; + + /* Lookup existing route with type and distance. */ + rn = route_node_lookup (table, p); + if (! rn) + return; + + RNODE_FOREACH_RIB (rn, rib) + { + if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) + continue; + + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && + rib->tag == si->tag) + break; + } + + if (! rib) + { + route_unlock_node (rn); + return; + } + + /* Lookup nexthop. */ + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (static_nexthop_same (nexthop, si)) + break; + + /* Can't find nexthop. */ + if (! nexthop) + { + route_unlock_node (rn); + return; + } + + /* Check nexthop. */ + if (rib->nexthop_num == 1) + rib_delnode (rn, rib); + else + { + /* Mark this nexthop as inactive and reinstall the route. Then, delete + * the nexthop. There is no need to re-evaluate the route for this + * scenario. + */ + if (IS_ZEBRA_DEBUG_RIB) + { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) + { + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, rib, rib->type); + } + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + { + /* If there are other active nexthops, do an update. */ + if (rib->nexthop_active_num > 1) + { + rib_install_kernel (rn, rib, 1); + redistribute_update (&rn->p, rib, NULL); + } + else + { + redistribute_delete (&rn->p, rib); + rib_uninstall_kernel (rn, rib); + } + } + + if (afi == AFI_IP) + { + /* Delete the nexthop and dereg from NHT */ + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nexthop->gate.ipv4; + } + else + { + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nexthop->gate.ipv6; + } + rib_nexthop_delete (rib, nexthop); + zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); + nexthop_free (nexthop); + } + /* Unlock node. */ + route_unlock_node (rn); +} + +int +static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf) +{ + u_char type = 0; + struct route_node *rn; + struct static_route *si; + struct static_route *pp; + struct static_route *cp; + struct static_route *update = NULL; + struct route_table *stable = zvrf->stable[AFI_IP][safi]; + + if (! stable) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_get (stable, p); + + /* Make flags. */ + if (gate) + type = STATIC_IPV4_GATEWAY; + else if (ifindex) + type = STATIC_IFINDEX; + else + type = STATIC_IPV4_BLACKHOLE; + + /* Do nothing if there is a same static route. */ + for (si = rn->info; si; si = si->next) + { + if (type == si->type + && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) + && (! ifindex || ifindex == si->ifindex)) + { + if ((distance == si->distance) && (tag == si->tag)) + { + route_unlock_node (rn); + return 0; + } + else + update = si; + } + } + + /* Distance or tag changed. */ + if (update) + static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf); + + /* Make new static route structure. */ + si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); + + si->type = type; + si->distance = distance; + si->flags = flags; + si->tag = tag; + si->vrf_id = zvrf->vrf_id; + si->ifindex = ifindex; + if (si->ifindex) + strcpy(si->ifname, ifname); + + if (gate) + si->addr.ipv4 = *gate; + + /* Add new static route information to the tree with sort by + distance value and gateway address. */ + for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) + { + if (si->distance < cp->distance) + break; + if (si->distance > cp->distance) + continue; + if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) + { + if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) + break; + if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) + continue; + } + } + + /* Make linked list. */ + if (pp) + pp->next = si; + else + rn->info = si; + if (cp) + cp->prev = si; + si->prev = pp; + si->next = cp; + + /* Install into rib. */ + static_install_route (AFI_IP, safi, p, si); + + return 1; +} + +int +static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, struct zebra_vrf *zvrf) +{ + u_char type = 0; + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + + /* Lookup table. */ + stable = zebra_vrf_static_table (AFI_IP, safi, zvrf); + if (! stable) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_lookup (stable, p); + if (! rn) + return 0; + + /* Make flags. */ + if (gate) + type = STATIC_IPV4_GATEWAY; + else if (ifindex) + type = STATIC_IFINDEX; + else + type = STATIC_IPV4_BLACKHOLE; + + /* Find same static route is the tree */ + for (si = rn->info; si; si = si->next) + if (type == si->type + && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) + && (! ifindex || ifindex == si->ifindex) + && (! tag || (tag == si->tag))) + break; + + /* Can't find static route. */ + if (! si) + { + route_unlock_node (rn); + return 0; + } + + /* Install into rib. */ + static_uninstall_route (AFI_IP, safi, p, si); + + /* Unlink static route from linked list. */ + if (si->prev) + si->prev->next = si->next; + else + rn->info = si->next; + if (si->next) + si->next->prev = si->prev; + route_unlock_node (rn); + + /* Free static route configuration. */ + XFREE (MTYPE_STATIC_ROUTE, si); + + route_unlock_node (rn); + + return 1; +} + +/* Add static route into static route configuration. */ +int +static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, + u_short tag, u_char distance, struct zebra_vrf *zvrf) +{ + struct route_node *rn; + struct static_route *si; + struct static_route *pp; + struct static_route *cp; + struct static_route *update = NULL; + struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; + + if (! stable) + return -1; + + if (!gate && + (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + if (!ifindex && + (type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX)) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_get (stable, p); + + /* Do nothing if there is a same static route. */ + for (si = rn->info; si; si = si->next) + { + if (type == si->type + && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) + && (! ifindex || ifindex == si->ifindex)) + { + if ((distance == si->distance) && (tag == si->tag)) + { + route_unlock_node (rn); + return 0; + } + else + update = si; + } + } + + /* Distance or tag changed. */ + if (update) + static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf); + + /* Make new static route structure. */ + si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); + + si->type = type; + si->distance = distance; + si->flags = flags; + si->tag = tag; + si->vrf_id = zvrf->vrf_id; + si->ifindex = ifindex; + if (si->ifindex) + strcpy (si->ifname, ifname); + + switch (type) + { + case STATIC_IPV6_GATEWAY: + si->addr.ipv6 = *gate; + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + si->addr.ipv6 = *gate; + break; + } + + /* Add new static route information to the tree with sort by + distance value and gateway address. */ + for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) + { + if (si->distance < cp->distance) + break; + if (si->distance > cp->distance) + continue; + } + + /* Make linked list. */ + if (pp) + pp->next = si; + else + rn->info = si; + if (cp) + cp->prev = si; + si->prev = pp; + si->next = cp; + + /* Install into rib. */ + static_install_route (AFI_IP6, SAFI_UNICAST, p, si); + + return 1; +} + +/* Delete static route from static route configuration. */ +int +static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, + ifindex_t ifindex, u_short tag, u_char distance, + struct zebra_vrf *zvrf) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + + /* Lookup table. */ + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf); + if (! stable) + return -1; + + /* Lookup static route prefix. */ + rn = route_node_lookup (stable, p); + if (! rn) + return 0; + + /* Find same static route is the tree */ + for (si = rn->info; si; si = si->next) + if (distance == si->distance + && type == si->type + && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) + && (! ifindex || ifindex == si->ifindex) + && (! tag || (tag == si->tag))) + break; + + /* Can't find static route. */ + if (! si) + { + route_unlock_node (rn); + return 0; + } + + /* Install into rib. */ + static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si); + + /* Unlink static route from linked list. */ + if (si->prev) + si->prev->next = si->next; + else + rn->info = si->next; + if (si->next) + si->next->prev = si->prev; + + /* Free static route configuration. */ + XFREE (MTYPE_STATIC_ROUTE, si); + + return 1; +} diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h new file mode 100644 index 0000000000..a3096725f7 --- /dev/null +++ b/zebra/zebra_static.h @@ -0,0 +1,95 @@ +/* + * Static Routing Information header + * Copyright (C) 2016 Cumulus Networks + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef __ZEBRA_STATIC_H__ +#define __ZEBRA_STATIC_H__ + +/* Static route information. */ +struct static_route +{ + /* For linked list. */ + struct static_route *prev; + struct static_route *next; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Administrative distance. */ + u_char distance; + + /* Tag */ + u_short tag; + + /* Flag for this static route's type. */ + u_char type; +#define STATIC_IFINDEX 1 +#define STATIC_IPV4_GATEWAY 2 +#define STATIC_IPV4_BLACKHOLE 3 +#define STATIC_IPV6_GATEWAY 4 +#define STATIC_IPV6_GATEWAY_IFINDEX 5 + + /* + * Nexthop value. + * + * Under IPv4 addr and ifindex are + * used independentyly. + * STATIC_IPV4_GATEWAY uses addr + * STATIC_IFINDEX uses ifindex + */ + union g_addr addr; + ifindex_t ifindex; + + char ifname[INTERFACE_NAMSIZ + 1]; + + /* bit flags */ + u_char flags; +/* + see ZEBRA_FLAG_REJECT + ZEBRA_FLAG_BLACKHOLE + */ +}; + +extern void +static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); +extern void +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); + +extern int +static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf); + +extern int +static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, struct zebra_vrf *zvrf); + +extern int +static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, + u_short tag, u_char distance, struct zebra_vrf *zvrf); + +extern int +static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, + ifindex_t ifindex, u_short tag, u_char distance, + struct zebra_vrf *zvrf); + +#endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 46dc29d102..d9bd919bfe 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -29,6 +29,7 @@ #include "zebra/rib.h" #include "zebra/zebra_vrf.h" #include "zebra/router-id.h" +#include "zebra/zebra_static.h" extern struct zebra_t zebrad; struct list *zvrf_list; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 3c2626670b..716e74c0b0 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -29,13 +29,14 @@ #include "rib.h" #include "nexthop.h" #include "vrf.h" +#include "lib/json.h" #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_rnh.h" #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" -#include "lib/json.h" +#include "zebra/zebra_static.h" extern int allow_delete; From c7cfcb75e926f19f833d3c7881127bc743e4c661 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 00:07:49 -0400 Subject: [PATCH 162/226] zebra: Refactor v4 and v6 static_delete Refactor v4 and v6 static delete into 1 function. Signed-off-by: Donald Sharp --- zebra/zebra_static.c | 80 +++++++------------------------------------- zebra/zebra_static.h | 11 +++--- zebra/zebra_vty.c | 13 ++++--- 3 files changed, 25 insertions(+), 79 deletions(-) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 9d16f12679..74a37c45c1 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -355,7 +355,8 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t /* Distance or tag changed. */ if (update) - static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf); + static_delete_route (AFI_IP, safi, type, p, (union g_addr *)gate, + ifindex, update->tag, update->distance, zvrf); /* Make new static route structure. */ si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); @@ -406,16 +407,16 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t } int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf) +static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, struct zebra_vrf *zvrf) { - u_char type = 0; struct route_node *rn; struct static_route *si; struct route_table *stable; /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, safi, zvrf); + stable = zebra_vrf_static_table (afi, safi, zvrf); if (! stable) return -1; @@ -424,18 +425,12 @@ static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex if (! rn) return 0; - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - /* Find same static route is the tree */ for (si = rn->info; si; si = si->next) if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) + && (! gate || ( + (afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || + (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) && (! ifindex || ifindex == si->ifindex) && (! tag || (tag == si->tag))) break; @@ -513,7 +508,9 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* Distance or tag changed. */ if (update) - static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf); + static_delete_route (AFI_IP6, SAFI_UNICAST, type, p, + (union g_addr *)gate, ifindex, + update->tag, update->distance, zvrf); /* Make new static route structure. */ si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); @@ -562,56 +559,3 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, return 1; } - -/* Delete static route from static route configuration. */ -int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); - if (! rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (distance == si->distance - && type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - return 1; -} diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index a3096725f7..b2f5ea0bb1 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -79,17 +79,14 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t u_char distance, struct zebra_vrf *zvrf); extern int -static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - u_short tag, u_char distance, struct zebra_vrf *zvrf); +static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_short tag, u_char distance, + struct zebra_vrf *zvrf); extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, ifindex_t ifindex, const char *ifname, u_char flags, u_short tag, u_char distance, struct zebra_vrf *zvrf); -extern int -static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, u_short tag, u_char distance, - struct zebra_vrf *zvrf); - #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 716e74c0b0..f8774f0026 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -66,6 +66,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, struct zebra_vrf *zvrf = NULL; unsigned int ifindex = 0; const char *ifname = NULL; + u_char type = STATIC_IPV4_BLACKHOLE; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -119,7 +120,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (add_cmd) static_add_ipv4 (safi, &p, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, NULL, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -142,10 +143,11 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (gate_str == NULL) { + type = STATIC_IFINDEX; if (add_cmd) static_add_ipv4 (safi, &p, NULL, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, NULL, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -164,12 +166,15 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, else ifindex = ifp->ifindex; ifname = gate_str; + type = STATIC_IFINDEX; } + else + type = STATIC_IPV4_GATEWAY; if (add_cmd) static_add_ipv4 (safi, &p, ifindex ? NULL : &gate, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv4 (safi, &p, ifindex ? NULL : &gate, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP, safi, type, &p, ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } @@ -3735,7 +3740,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, if (add_cmd) static_add_ipv6 (&p, type, gate, ifindex, ifname, flag, tag, distance, zvrf); else - static_delete_ipv6 (&p, type, gate, ifindex, tag, distance, zvrf); + static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, ifindex, tag, distance, zvrf); return CMD_SUCCESS; } From 3a3d00f1bd3b82a9b1f2bca5485c578773c403b7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 00:26:07 -0400 Subject: [PATCH 163/226] zebra: Refactor v4 and v6 static_add into 1 function Refactor the static_add_ipv[4|6] functions into 1 function call. They are basically doing the exact same thing no need for separate code paths. Signed-off-by: Donald Sharp --- zebra/zebra_static.c | 151 ++++++++++--------------------------------- zebra/zebra_static.h | 11 ++-- zebra/zebra_vty.c | 9 ++- 3 files changed, 43 insertions(+), 128 deletions(-) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 74a37c45c1..7d47510635 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -310,37 +310,42 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ } int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf) +static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf) { - u_char type = 0; struct route_node *rn; struct static_route *si; struct static_route *pp; struct static_route *cp; struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP][safi]; + struct route_table *stable = zvrf->stable[afi][safi]; if (! stable) return -1; + if (!gate && + (type == STATIC_IPV4_GATEWAY || + type == STATIC_IPV6_GATEWAY || + type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + if (!ifindex && + (type == STATIC_IFINDEX || + type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + /* Lookup static route prefix. */ rn = route_node_get (stable, p); - /* Make flags. */ - if (gate) - type = STATIC_IPV4_GATEWAY; - else if (ifindex) - type = STATIC_IFINDEX; - else - type = STATIC_IPV4_BLACKHOLE; - /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) { if (type == si->type - && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4)) + && (! gate || + ((afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || + (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) && (! ifindex || ifindex == si->ifindex)) { if ((distance == si->distance) && (tag == si->tag)) @@ -355,7 +360,7 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t /* Distance or tag changed. */ if (update) - static_delete_route (AFI_IP, safi, type, p, (union g_addr *)gate, + static_delete_route (afi, safi, type, p, gate, ifindex, update->tag, update->distance, zvrf); /* Make new static route structure. */ @@ -370,8 +375,20 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t if (si->ifindex) strcpy(si->ifname, ifname); - if (gate) - si->addr.ipv4 = *gate; + switch (type) + { + case STATIC_IPV4_GATEWAY: + si->addr.ipv4 = gate->ipv4; + break; + case STATIC_IPV6_GATEWAY: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IFINDEX: + break; + } /* Add new static route information to the tree with sort by distance value and gateway address. */ @@ -401,7 +418,7 @@ static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t si->next = cp; /* Install into rib. */ - static_install_route (AFI_IP, safi, p, si); + static_install_route (afi, safi, p, si); return 1; } @@ -461,101 +478,3 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, return 1; } - -/* Add static route into static route configuration. */ -int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf) -{ - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; - - if (! stable) - return -1; - - if (!gate && - (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - if (!ifindex && - (type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX)) - return -1; - - /* Lookup static route prefix. */ - rn = route_node_get (stable, p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6)) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag)) - { - route_unlock_node (rn); - return 0; - } - else - update = si; - } - } - - /* Distance or tag changed. */ - if (update) - static_delete_route (AFI_IP6, SAFI_UNICAST, type, p, - (union g_addr *)gate, ifindex, - update->tag, update->distance, zvrf); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf->vrf_id; - si->ifindex = ifindex; - if (si->ifindex) - strcpy (si->ifname, ifname); - - switch (type) - { - case STATIC_IPV6_GATEWAY: - si->addr.ipv6 = *gate; - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - si->addr.ipv6 = *gate; - break; - } - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (AFI_IP6, SAFI_UNICAST, p, si); - - return 1; -} diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index b2f5ea0bb1..0f00609b55 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -74,9 +74,10 @@ extern void static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); extern int -static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, u_short tag, - u_char distance, struct zebra_vrf *zvrf); +static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + const char *ifname, u_char flags, u_short tag, + u_char distance, struct zebra_vrf *zvrf); extern int static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, @@ -84,9 +85,5 @@ static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, u_short tag, u_char distance, struct zebra_vrf *zvrf); -extern int -static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - ifindex_t ifindex, const char *ifname, u_char flags, - u_short tag, u_char distance, struct zebra_vrf *zvrf); #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index f8774f0026..72d0ced658 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -118,7 +118,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (safi, &p, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf); else static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); return CMD_SUCCESS; @@ -143,9 +143,8 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (gate_str == NULL) { - type = STATIC_IFINDEX; if (add_cmd) - static_add_ipv4 (safi, &p, NULL, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, flag, tag, distance, zvrf); else static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, zvrf); @@ -172,7 +171,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, type = STATIC_IPV4_GATEWAY; if (add_cmd) - static_add_ipv4 (safi, &p, ifindex ? NULL : &gate, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP, safi, type, &p, ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, flag, tag, distance, zvrf); else static_delete_route (AFI_IP, safi, type, &p, ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, distance, zvrf); @@ -3738,7 +3737,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_ipv6 (&p, type, gate, ifindex, ifname, flag, tag, distance, zvrf); + static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, ifindex, ifname, flag, tag, distance, zvrf); else static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, ifindex, tag, distance, zvrf); From 14364a318097a49062f545a255e4e6a306e7b2fe Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 00:48:37 -0400 Subject: [PATCH 164/226] zebra: Refactor rib_match_ipv[4|6] the rib_match_ipv4 and rib_match_ipv6 functions were the same. Refactor to 1 function. Signed-off-by: Donald Sharp --- zebra/rib.h | 6 +-- zebra/zebra_rib.c | 98 ++++++++++------------------------------------- zebra/zserv.c | 6 ++- 3 files changed, 26 insertions(+), 84 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 32f370f9ef..7fd29dcd5a 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -349,8 +349,8 @@ extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix struct in_addr *gate, ifindex_t ifindex, vrf_id_t, u_int32_t, safi_t safi); -extern struct rib *rib_match_ipv4 (struct in_addr, safi_t safi, vrf_id_t, - struct route_node **rn_out); +extern struct rib *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, + struct route_node **rn_out); extern struct rib *rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out); @@ -378,8 +378,6 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); -extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t); - extern struct route_table *rib_table_ipv6; extern int diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0db1b0a689..3a160825d5 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -747,10 +747,10 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, } struct rib * -rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id, - struct route_node **rn_out) +rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id, + union g_addr *addr, struct route_node **rn_out) { - struct prefix_ipv4 p; + struct prefix p; struct route_table *table; struct route_node *rn; struct rib *match; @@ -758,14 +758,18 @@ rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id, int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, safi, vrf_id); + table = zebra_vrf_table (afi, safi, vrf_id); if (! table) return 0; - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + memset (&p, 0, sizeof (struct prefix)); + p.family = afi; + p.u.prefix = *(u_char *)addr; p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; + if (afi == AFI_IP) + p.prefixlen = IPV4_MAX_PREFIXLEN; + else + p.prefixlen = IPV6_MAX_PREFIXLEN; rn = route_node_match (table, (struct prefix *) &p); @@ -820,23 +824,23 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out) { struct rib *rib = NULL, *mrib = NULL, *urib = NULL; struct route_node *m_rn = NULL, *u_rn = NULL; - int skip_bgp = 0; /* bool */ + union g_addr gaddr = { .ipv4 = addr }; switch (ipv4_multicast_mode) { case MCAST_MRIB_ONLY: - return rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, rn_out); + return rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, rn_out); case MCAST_URIB_ONLY: - return rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, rn_out); + return rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, rn_out); case MCAST_NO_CONFIG: case MCAST_MIX_MRIB_FIRST: - rib = mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); + rib = mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); if (!mrib) - rib = urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + rib = urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); break; case MCAST_MIX_DISTANCE: - mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); - urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); + urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); if (mrib && urib) rib = urib->distance < mrib->distance ? urib : mrib; else if (mrib) @@ -845,8 +849,8 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out) rib = urib; break; case MCAST_MIX_PFXLEN: - mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn); - urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn); + mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn); + urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn); if (mrib && urib) rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib; else if (mrib) @@ -1009,68 +1013,6 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, return ZEBRA_RIB_NOTFOUND; } -struct rib * -rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id) -{ - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct rib *match; - struct nexthop *newhop, *tnewhop; - int recursing; - - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return 0; - - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - IPV6_ADDR_COPY (&p.prefix, addr); - - rn = route_node_match (table, (struct prefix *) &p); - - while (rn) - { - route_unlock_node (rn); - - /* Pick up selected route. */ - RNODE_FOREACH_RIB (rn, match) - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } - - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); - } - else - { - if (match->type == ZEBRA_ROUTE_CONNECT) - /* Directly point connected route. */ - return match; - else - { - for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - return match; - return NULL; - } - } - } - return NULL; -} - #define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) diff --git a/zebra/zserv.c b/zebra/zserv.c index 84881e14a4..73e84faca2 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -722,9 +722,10 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, unsigned long nump; u_char num; struct nexthop *nexthop; + union g_addr gaddr = { .ipv6 = *addr }; /* Lookup nexthop. */ - rib = rib_match_ipv6 (addr, vrf_id); + rib = rib_match (AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, NULL); /* Get output stream. */ s = client->obuf; @@ -788,9 +789,10 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, unsigned long nump; u_char num; struct nexthop *nexthop; + union g_addr gaddr = { .ipv4 = addr }; /* Lookup nexthop. */ - rib = rib_match_ipv4 (addr, SAFI_UNICAST, vrf_id, NULL); + rib = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, NULL); /* Get output stream. */ s = client->obuf; From 616368ed1ea8165beb2b1ba137b474ee794046d5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 01:39:08 -0400 Subject: [PATCH 165/226] zebra: Refactor rib_delete_ipv[4|6] These two functions are essentially the same. Refactor. Signed-off-by: Donald Sharp --- zebra/connected.c | 24 +++---- zebra/kernel_socket.c | 35 ++++----- zebra/redistribute.c | 13 ++-- zebra/rib.h | 12 ++-- zebra/rt_netlink.c | 26 ++++--- zebra/zebra_rib.c | 162 ++++-------------------------------------- zebra/zserv.c | 29 ++++---- 7 files changed, 81 insertions(+), 220 deletions(-) diff --git a/zebra/connected.c b/zebra/connected.c index 3077272221..e3cb12bcd0 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -303,7 +303,7 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv4 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; @@ -311,19 +311,19 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv4 (&p); + apply_mask (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ - if (prefix_ipv4_any (&p)) + if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, - SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, - SAFI_MULTICAST); + rib_delete (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", @@ -456,20 +456,20 @@ connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, void connected_down_ipv6 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv6 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); - apply_mask_ipv6 (&p); + apply_mask (&p); - if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; - rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, - ifp->vrf_id, 0, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index c5763dd46f..ccc54ce81f 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -884,10 +884,10 @@ rtm_read (struct rt_msghdr *rtm) if (dest.sa.sa_family == AF_INET) { - struct prefix_ipv4 p; + struct prefix p; p.family = AF_INET; - p.prefix = dest.sin.sin_addr; + p.u.prefix4 = dest.sin.sin_addr; if (flags & RTF_HOST) p.prefixlen = IPV4_MAX_PREFIXLEN; else @@ -967,20 +967,20 @@ rtm_read (struct rt_msghdr *rtm) * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, 0, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, 0, 0); + union g_addr ggate = { .ipv4 = gate.sin.sin_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, + (struct prefix_ipv4 *)&p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST); else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, 0, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &&ggate, 0, 0); } -#ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { /* One day we might have a debug section here like one in the @@ -988,11 +988,11 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) return; - struct prefix_ipv6 p; + struct prefix p; ifindex_t ifindex = 0; p.family = AF_INET6; - p.prefix = dest.sin6.sin6_addr; + p.u.prefix6 = dest.sin6.sin6_addr; if (flags & RTF_HOST) p.prefixlen = IPV6_MAX_PREFIXLEN; else @@ -1010,20 +1010,21 @@ rtm_read (struct rt_msghdr *rtm) * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, VRF_DEFAULT, 0, SAFI_UNICAST); - + rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, 0, 0); + + union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, + (struct prefix_ipv6 *)&p, &gate.sin6.sin6_addr, + ifindex, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &ggate, ifindex, 0); } -#endif /* HAVE_IPV6 */ } /* Interface function for the kernel routing table updates. Support diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 892bc2af2b..2eb4f257f5 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -614,16 +614,17 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char int zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) { - struct prefix_ipv4 p4; + struct prefix p; if (rn->p.family == AF_INET) { - p4.family = AF_INET; - p4.prefixlen = rn->p.prefixlen; - p4.prefix = rn->p.u.prefix4; + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; - rib_delete_ipv4(ZEBRA_ROUTE_TABLE, rib->table, rib->flags, &p4, NULL, - 0, rib->vrf_id, zebrad.rtm_table_default, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, + rib->table, rib->flags, &p, NULL, + 0, zebrad.rtm_table_default); } /* DD: Add IPv6 code */ diff --git a/zebra/rib.h b/zebra/rib.h index 7fd29dcd5a..8b70de7a03 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -345,9 +345,10 @@ extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ip extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); -extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, ifindex_t ifindex, - vrf_id_t, u_int32_t, safi_t safi); +extern int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, ifindex_t ifindex, + u_int32_t table_id); extern struct rib *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, struct route_node **rn_out); @@ -371,11 +372,6 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, u_int32_t table_id, u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi); -extern int -rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi); - extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); extern struct route_table *rib_table_ipv6; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 49dcd1e6de..dc3aa2f6bb 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1059,7 +1059,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char zebra_flags = 0; - + struct prefix p; + char anyaddr[16] = { 0 }; int index; @@ -1177,9 +1178,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_family == AF_INET) { - struct prefix_ipv4 p; p.family = AF_INET; - memcpy (&p.prefix, dest, 4); + memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) @@ -1193,7 +1193,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv4 *)&p, gate, src, index, vrf_id, table, metric, mtu, 0, SAFI_UNICAST); else { @@ -1252,21 +1252,20 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST); + rib_add_ipv4_multipath ((struct prefix_ipv4 *)&p, rib, SAFI_UNICAST); } } else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - vrf_id, table, SAFI_UNICAST); + rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, + &p, gate, index, table); } -#ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) { - struct prefix_ipv6 p; + struct prefix p; p.family = AF_INET6; - memcpy (&p.prefix, dest, 16); + memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) @@ -1278,13 +1277,12 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv6 *)&p, gate, index, vrf_id, table, metric, mtu, 0, SAFI_UNICAST); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - vrf_id, table, SAFI_UNICAST); + rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, gate, index, table); } -#endif /* HAVE_IPV6 */ return 0; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 3a160825d5..0dbbd47a45 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2713,11 +2713,10 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) return ret; } -/* XXX factor with rib_delete_ipv6 */ int -rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi) +rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, + int flags, struct prefix *p, union g_addr *gate, ifindex_t ifindex, + u_int32_t table_id) { struct route_table *table; struct route_node *rn; @@ -2730,15 +2729,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, char buf2[INET6_ADDRSTRLEN]; /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); + table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) return 0; /* Apply mask. */ - apply_mask_ipv4 (p); + apply_mask (p); /* Lookup route node. */ - rn = route_node_lookup (table, (struct prefix *) p); + rn = route_node_lookup (table, p); if (! rn) { if (IS_ZEBRA_DEBUG_RIB) @@ -2784,7 +2783,8 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, break; } for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate)) + if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || + IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) { same = rib; break; @@ -2802,10 +2802,10 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, { if (IS_ZEBRA_DEBUG_RIB) { - zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted " + zlog_debug ("%u:%s: rn %p, rib %p (type %d) was deleted " "from kernel, adding", - vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, rn, fib, fib->type); + vrf_id, prefix2str(p, buf1, INET6_ADDRSTRLEN), + rn, fib, fib->type); } if (allow_delete) { @@ -2830,7 +2830,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, zlog_debug ("%u:%s: via %s ifindex %d type %d " "doesn't exist in rib", vrf_id, prefix2str (p, buf1, sizeof(buf1)), - inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), + inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), ifindex, type); else @@ -3077,144 +3077,6 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, return ret; } -/* XXX factor with rib_delete_ipv6 */ - -int -rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, safi_t safi) -{ - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct rib *fib = NULL; - struct rib *same = NULL; - struct nexthop *nexthop, *tnexthop; - int recursing; - char buf1[PREFIX_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - /* Apply mask. */ - apply_mask_ipv6 (p); - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); - if (! table) - return 0; - - /* Lookup route node. */ - rn = route_node_lookup (table, (struct prefix *) p); - if (! rn) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s: doesn't exist in rib", - vrf_id, prefix2str (p, buf1, sizeof(buf1))); - return ZEBRA_ERR_RTNOEXIST; - } - - /* Lookup same type route. */ - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) - fib = rib; - - if (rib->type != type) - continue; - if (rib->instance != instance) - continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->ifindex != ifindex) - continue; - if (rib->refcnt) - { - rib->refcnt--; - route_unlock_node (rn); - route_unlock_node (rn); - return 0; - } - same = rib; - break; - } - /* Make sure that the route found has the same gateway. */ - else - { - if (gate == NULL) - { - same = rib; - break; - } - for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) - { - same = rib; - break; - } - if (same) - break; - } - } - - /* If same type of route can't be found and this message is from - kernel. */ - if (! same) - { - if (fib && type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted " - "from kernel, adding", - vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, rn, fib, fib->type); - if (allow_delete) - { - /* Unset flags. */ - for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); - } - else - { - /* This means someone else, other than Zebra, has deleted a Zebra - * route from the kernel. We will add it back */ - rib_install_kernel(rn, fib, 0); - } - } - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (gate) - zlog_debug ("%s: vrf %u via %s ifindex %d type %d " - "doesn't exist in rib", - prefix2str (p, buf1, sizeof(buf1)), vrf_id, - inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), - ifindex, - type); - else - zlog_debug ("%s: vrf %u ifindex %d type %d doesn't exist in rib", - prefix2str (p, buf1, sizeof(buf1)), vrf_id, - ifindex, - type); - } - route_unlock_node (rn); - return ZEBRA_ERR_RTNOEXIST; - } - } - - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; -} - /* Schedule routes of a particular table (address-family) based on event. */ static void rib_update_table (struct route_table *table, rib_update_event_t event) diff --git a/zebra/zserv.c b/zebra/zserv.c index 73e84faca2..09992870a7 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1293,9 +1293,10 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) int i; struct stream *s; struct zapi_ipv4 api; - struct in_addr nexthop, *nexthop_p; + struct in_addr nexthop; + union g_addr *nexthop_p; unsigned long ifindex; - struct prefix_ipv4 p; + struct prefix p; u_char nexthop_num; u_char nexthop_type; u_int32_t table_id; @@ -1316,7 +1317,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) @@ -1334,11 +1335,11 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) break; case ZEBRA_NEXTHOP_IPV4: nexthop.s_addr = stream_get_ipv4 (s); - nexthop_p = &nexthop; + nexthop_p = (union g_addr *)&nexthop; break; case ZEBRA_NEXTHOP_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); - nexthop_p = &nexthop; + nexthop_p = (union g_addr *)&nexthop; ifindex = stream_getl (s); break; case ZEBRA_NEXTHOP_IPV6: @@ -1368,8 +1369,8 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) table_id = zvrf->table_id; - rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, - zvrf->vrf_id, table_id, api.safi); + rib_delete (AFI_IP, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, nexthop_p, ifindex, table_id); client->v4_route_del_cnt++; return 0; } @@ -1677,8 +1678,9 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) struct stream *s; struct zapi_ipv6 api; struct in6_addr nexthop; + union g_addr *pnexthop; unsigned long ifindex; - struct prefix_ipv6 p; + struct prefix p; s = client->ibuf; ifindex = 0; @@ -1695,7 +1697,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) @@ -1711,6 +1713,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { case ZEBRA_NEXTHOP_IPV6: stream_get (&nexthop, s, 16); + pnexthop = (union g_addr *)&nexthop; break; case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); @@ -1738,11 +1741,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) api.tag = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, - zvrf->vrf_id, client->rtm_table, api.safi); + rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, NULL, ifindex, client->rtm_table); else - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, - zvrf->vrf_id, client->rtm_table, api.safi); + rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + api.flags, &p, pnexthop, ifindex, client->rtm_table); client->v6_route_del_cnt++; return 0; From 3b1098beed5c294746a9203b5de3c9da82c25d76 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 02:20:47 -0400 Subject: [PATCH 166/226] zebra: Refactor rib_add_ipv[4|6] to a common function rib_add_ipv[4|6] both were essentially the same function combine and refactor everywhere. Signed-off-by: Donald Sharp --- zebra/connected.c | 33 ++++---- zebra/kernel_socket.c | 14 ++-- zebra/redistribute.c | 25 +++--- zebra/rib.h | 9 ++- zebra/rt_netlink.c | 31 ++++---- zebra/rtread_getmsg.c | 32 ++++---- zebra/zebra_rib.c | 175 +++++++++--------------------------------- 7 files changed, 111 insertions(+), 208 deletions(-) diff --git a/zebra/connected.c b/zebra/connected.c index e3cb12bcd0..2aa91ecd66 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -185,26 +185,28 @@ connected_update(struct interface *ifp, struct connected *ifc) void connected_up_ipv4 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv4 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv4 (&p); + apply_mask (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ - if (prefix_ipv4_any (&p)) + if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) return; - rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); - rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST); + rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", @@ -358,28 +360,28 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } -#ifdef HAVE_IPV6 void connected_up_ipv6 (struct interface *ifp, struct connected *ifc) { - struct prefix_ipv6 p; + struct prefix p; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ - apply_mask_ipv6 (&p); + apply_mask (&p); #ifndef LINUX /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ - if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; #endif - rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, - RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, NULL, ifp->ifindex, + RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", @@ -502,7 +504,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } -#endif /* HAVE_IPV6 */ int connected_is_unnumbered (struct interface *ifp) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index ccc54ce81f..a500fabbfb 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -974,12 +974,11 @@ rtm_read (struct rt_msghdr *rtm) if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - (struct prefix_ipv4 *)&p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, - 0, 0, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, + &p, &ggate, NULL, 0, 0, 0, 0, 0); else rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, &&ggate, 0, 0); + 0, zebra_flags, &p, &ggate, 0, 0); } if (dest.sa.sa_family == AF_INET6) { @@ -1017,10 +1016,9 @@ rtm_read (struct rt_msghdr *rtm) if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - (struct prefix_ipv6 *)&p, &gate.sin6.sin6_addr, - ifindex, VRF_DEFAULT, - 0, 0, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, &ggate, NULL, ifindex, + 0, 0, 0, 0); else rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, &ggate, ifindex, 0); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 2eb4f257f5..776c3519be 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -550,9 +550,9 @@ int zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char *rmap_name) { struct rib *newrib; - struct prefix_ipv4 p4; + struct prefix p; struct nexthop *nhop; - struct in_addr *gate; + union g_addr *gate; route_map_result_t ret = RMAP_MATCH; if (rmap_name) @@ -563,9 +563,9 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char { if (rn->p.family == AF_INET) { - p4.family = AF_INET; - p4.prefixlen = rn->p.prefixlen; - p4.prefix = rn->p.u.prefix4; + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; if (rib->nexthop_num == 1) { @@ -573,14 +573,13 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char if (nhop->type == NEXTHOP_TYPE_IFINDEX) gate = NULL; else - gate = &nhop->gate.ipv4; + gate = (union g_addr *)&nhop->gate.ipv4; - rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, - gate, &nhop->src.ipv4, - nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, - rib->metric, rib->mtu, - zebra_import_table_distance[AFI_IP][rib->table], - SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, + rib->table, 0, &p, gate, (union g_addr *)&nhop->src.ipv4, + nhop->ifindex, zebrad.rtm_table_default, + rib->metric, rib->mtu, + zebra_import_table_distance[AFI_IP][rib->table]); } else if (rib->nexthop_num > 1) { @@ -599,7 +598,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char for (nhop = rib->nexthop; nhop; nhop = nhop->next) rib_copy_nexthops(newrib, nhop); - rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST); + rib_add_ipv4_multipath((struct prefix_ipv4 *)&p, newrib, SAFI_UNICAST); } } } diff --git a/zebra/rib.h b/zebra/rib.h index 8b70de7a03..e51e1277bf 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -338,10 +338,11 @@ extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib); /* NOTE: * All rib_add_ipv[46]* functions will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ -extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, struct in_addr *src, - ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t, u_int32_t, u_char, safi_t); +extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, union g_addr *src, + ifindex_t ifindex, u_int32_t table_id, + u_int32_t, u_int32_t, u_char); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index dc3aa2f6bb..be291c0c9b 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -860,6 +860,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; + struct prefix p; char anyaddr[16] = { 0 }; @@ -952,14 +953,14 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_family == AF_INET) { - struct prefix_ipv4 p; p.family = AF_INET; - memcpy (&p.prefix, dest, 4); + memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - vrf_id, table, metric, mtu, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, gate, src, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -1016,21 +1017,19 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST); + rib_add_ipv4_multipath ((struct prefix_ipv4 *)&p, rib, SAFI_UNICAST); } } -#ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) { - struct prefix_ipv6 p; p.family = AF_INET6; - memcpy (&p.prefix, dest, 16); + memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, - table, metric, mtu, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, gate, src, index, + table, metric, mtu, 0); } -#endif /* HAVE_IPV6 */ return 0; } @@ -1193,8 +1192,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv4 *)&p, gate, src, index, vrf_id, - table, metric, mtu, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, 0, &p, gate, src, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -1277,8 +1277,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv6 *)&p, gate, index, vrf_id, - table, metric, mtu, 0, SAFI_UNICAST); + rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, 0, &p, gate, src, index, + table, metric, mtu, 0); else rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, table); diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 9defa49bfd..0facc1a19f 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -70,28 +70,30 @@ static void handle_route_entry (mib2_ipRouteEntry_t *routeEntry) { - struct prefix_ipv4 prefix; - struct in_addr tmpaddr, gateway; - u_char zebra_flags = 0; + struct prefix prefix; + struct in_addr tmpaddr, gateway; + union g_addr *ggateway; + u_char zebra_flags = 0; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) - return; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) + return; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) + zebra_flags |= ZEBRA_FLAG_SELFROUTE; - prefix.family = AF_INET; + prefix.family = AF_INET; - tmpaddr.s_addr = routeEntry->ipRouteDest; - prefix.prefix = tmpaddr; + tmpaddr.s_addr = routeEntry->ipRouteDest; + prefix.u.prefix4 = tmpaddr; - tmpaddr.s_addr = routeEntry->ipRouteMask; - prefix.prefixlen = ip_masklen (tmpaddr); + tmpaddr.s_addr = routeEntry->ipRouteMask; + prefix.prefixlen = ip_masklen (tmpaddr); - gateway.s_addr = routeEntry->ipRouteNextHop; + gateway.s_addr = routeEntry->ipRouteNextHop; + ggateway = (union g_addr *)&gateway; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST); + rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, + zebra_flags, &prefix, ggateway, NULL, 0, 0, 0, 0, 0); } void diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0dbbd47a45..17d59236f8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2354,124 +2354,6 @@ rib_delnode (struct route_node *rn, struct rib *rib) } } -int -rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, struct in_addr *src, - ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id, - u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi) -{ - struct rib *rib; - struct rib *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *nexthop; - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); - if (! table) - return 0; - - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 (p); - - /* Set default distance by route type. */ - if (distance == 0) - { - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; - - /* iBGP distance is 200. */ - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; - } - - /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); - - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - - if (rib->type != type) - continue; - if (rib->instance != instance) - continue; - - if (rib->type != ZEBRA_ROUTE_CONNECT) - { - same = rib; - break; - } - /* Duplicate connected route comes in. */ - else if ((nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex && - !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - { - rib->refcnt++; - return 0 ; - } - } - - /* Allocate new rib structure. */ - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - rib->type = type; - rib->instance = instance; - rib->distance = distance; - rib->flags = flags; - rib->metric = metric; - rib->mtu = mtu; - rib->table = table_id; - rib->vrf_id = vrf_id; - rib->nexthop_num = 0; - rib->uptime = time (NULL); - - /* Nexthop settings. */ - if (gate) - { - if (ifindex) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, ifindex); - else - rib_nexthop_ipv4_add (rib, gate, src); - } - else - rib_nexthop_ifindex_add (rib, ifindex); - - /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " - "existing %p", - vrf_id, buf, p->prefixlen, (void *)rn, (void *)rib, rib->type, (void *)same); - } - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); - } - rib_addnode (rn, rib, 1); - - /* Free implicit route.*/ - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; -} - /* This function dumps the contents of a given RIB entry into * standard debug log. Calling function name and IP prefix in * question are passed as 1st and 2nd arguments. @@ -2854,10 +2736,11 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int -rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - u_char distance, safi_t safi) +rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + union g_addr *gate, union g_addr *src, ifindex_t ifindex, + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance) { struct rib *rib; struct rib *same = NULL; @@ -2866,22 +2749,28 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct nexthop *nexthop; /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); + table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) return 0; /* Make sure mask is applied. */ - apply_mask_ipv6 (p); + apply_mask (p); /* Set default distance by route type. */ - if (!distance) - distance = route_info[type].distance; - - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; + if (distance == 0) + { + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; + + /* iBGP distance is 200. */ + if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) + distance = 200; + } /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); + rn = route_node_get (table, p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -2899,12 +2788,14 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, same = rib; break; } + /* Duplicate connected route comes in. */ else if ((nexthop = rib->nexthop) && nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex) + nexthop->ifindex == ifindex && + !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) { rib->refcnt++; - return 0; + return 0 ; } } @@ -2925,10 +2816,20 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Nexthop settings. */ if (gate) { - if (ifindex) - rib_nexthop_ipv6_ifindex_add (rib, gate, ifindex); + if (afi == AFI_IP6) + { + if (ifindex) + rib_nexthop_ipv6_ifindex_add (rib, &gate->ipv6, ifindex); + else + rib_nexthop_ipv6_add (rib, &gate->ipv6); + } else - rib_nexthop_ipv6_add (rib, gate); + { + if (ifindex) + rib_nexthop_ipv4_ifindex_add (rib, &gate->ipv4, &src->ipv4, ifindex); + else + rib_nexthop_ipv4_add (rib, &gate->ipv4, &src->ipv4); + } } else rib_nexthop_ifindex_add (rib, ifindex); @@ -2944,7 +2845,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, char buf[INET6_ADDRSTRLEN]; if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", vrf_id, buf, p->prefixlen, (void *)rn, @@ -2952,7 +2853,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, } if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); + rib_dump (p, rib); } rib_addnode (rn, rib, 1); From b4c034b0330e378b51a0e516d717b5fbfcfc083f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 04:01:20 -0400 Subject: [PATCH 167/226] zebra: refactor rib_add_ipv[4|6]_multipath The rib_add_ipv[4|6]_multipath functions are functionally equivalent. Refactor to 1 function. Signed-off-by: Donald Sharp --- zebra/connected.c | 2 +- zebra/redistribute.c | 2 +- zebra/rib.h | 15 +---- zebra/rt_netlink.c | 4 +- zebra/zebra_rib.c | 135 +++++-------------------------------------- zebra/zserv.c | 22 +++---- 6 files changed, 32 insertions(+), 148 deletions(-) diff --git a/zebra/connected.c b/zebra/connected.c index 2aa91ecd66..6e82e6ec78 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -374,7 +374,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) apply_mask (&p); #ifndef LINUX - /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ + /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; #endif diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 776c3519be..2864e0b8a5 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -598,7 +598,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char for (nhop = rib->nexthop; nhop; nhop = nhop->next) rib_copy_nexthops(newrib, nhop); - rib_add_ipv4_multipath((struct prefix_ipv4 *)&p, newrib, SAFI_UNICAST); + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, newrib); } } } diff --git a/zebra/rib.h b/zebra/rib.h index e51e1277bf..0faa088d87 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -336,7 +336,7 @@ extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int updat extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib); /* NOTE: - * All rib_add_ipv[46]* functions will not just add prefix into RIB, but + * All rib_add function will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, @@ -344,7 +344,8 @@ extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, ifindex_t ifindex, u_int32_t table_id, u_int32_t, u_int32_t, u_char); -extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); +extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *, + struct rib *); extern int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, @@ -367,20 +368,10 @@ extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); extern void rib_queue_add (struct route_node *rn); -extern int -rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id, - u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - u_char distance, safi_t safi); - extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); extern struct route_table *rib_table_ipv6; -extern int -rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, - ifindex_t); - extern int rib_gc_dest (struct route_node *rn); extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index be291c0c9b..826c59a729 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1017,7 +1017,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath ((struct prefix_ipv4 *)&p, rib, SAFI_UNICAST); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); } } if (rtm->rtm_family == AF_INET6) @@ -1252,7 +1252,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_ipv4_multipath ((struct prefix_ipv4 *)&p, rib, SAFI_UNICAST); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); } } else diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 17d59236f8..23ec8dab9a 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2517,21 +2517,31 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) } int -rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) +rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, + struct rib *rib) { struct route_table *table; struct route_node *rn; struct rib *same; struct nexthop *nexthop; int ret = 0; - + int family; + + if (!rib) + return 0; + + if (p->family == AF_INET) + family = AFI_IP; + else + family = AFI_IP6; + /* Lookup table. */ - table = zebra_vrf_table_with_table_id (AFI_IP, safi, rib->vrf_id, rib->table); + table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table); if (! table) return 0; /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 (p); + apply_mask (p); /* Set default distance by route type. */ if (rib->distance == 0) @@ -2545,7 +2555,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) } /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); + rn = route_node_get (table, p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -2571,7 +2581,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) char buf[INET6_ADDRSTRLEN]; if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); + inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", rib->vrf_id, buf, p->prefixlen, (void *)rn, @@ -2865,119 +2875,6 @@ rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, return 0; } -int -rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, - ifindex_t ifindex) -{ - struct route_table *table; - struct route_node *rn; - struct rib *same = NULL; - struct nexthop *nexthop; - int ret = 0; - int family; - - if (!rib) - return 0; - - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table); - if (! table) - return 0; - - if (p->family == AF_INET) - { - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask_ipv4 ((struct prefix_ipv4 *)p); - } - else - { - /* Make sure mask is applied. */ - apply_mask_ipv6 ((struct prefix_ipv6 *)p); - } - - /* Set default distance by route type. */ - if (rib->distance == 0) - { - rib->distance = route_info[rib->type].distance; - - /* iBGP distance is 200. */ - if (rib->type == ZEBRA_ROUTE_BGP - && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) - rib->distance = 200; - } - - /* Lookup route node.*/ - rn = route_node_get (table, (struct prefix *) p); - - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RIB (rn, same) { - if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED)) { - continue; - } - if (same->type != rib->type) { - continue; - } - - if (same->instance != rib->instance) { - continue; - } - - if (same->table != rib->table) { - continue; - } - if (same->type != ZEBRA_ROUTE_CONNECT) { - break; - } - else if ((nexthop = same->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex) { - same->refcnt++; - return 0; - } - } - - /* If this route is kernel route, set FIB flag to the route. */ - if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) { - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " - "existing %p", - rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same); - } - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); - } - rib_addnode (rn, rib, 1); - ret = 1; - - /* Free implicit route.*/ - if (same) - { - rib_delnode (rn, same); - ret = -1; - } - - route_unlock_node (rn); - return ret; -} - /* Schedule routes of a particular table (address-family) based on event. */ static void rib_update_table (struct route_table *table, rib_update_event_t event) diff --git a/zebra/zserv.c b/zebra/zserv.c index 09992870a7..e72683afd1 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1186,7 +1186,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { int i; struct rib *rib; - struct prefix_ipv4 p; + struct prefix p; u_char message; struct in_addr nexthop; u_char nexthop_num; @@ -1214,7 +1214,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ rib->vrf_id = zvrf->vrf_id; @@ -1276,7 +1276,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) /* Table */ rib->table = zvrf->table_id; - ret = rib_add_ipv4_multipath (&p, rib, safi); + ret = rib_add_multipath (AFI_IP, safi, &p, rib); /* Stats */ if (ret > 0) @@ -1427,8 +1427,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct u_char message; u_char nexthop_num; u_char nexthop_type; - unsigned long ifindex; - struct prefix_ipv4 p; + struct prefix p; safi_t safi; static struct in6_addr nexthops[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM]; @@ -1437,7 +1436,6 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct /* Get input stream. */ s = client->ibuf; - ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Allocate new rib. */ @@ -1455,7 +1453,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ rib->vrf_id = zvrf->vrf_id; @@ -1536,7 +1534,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct /* Table */ rib->table = zvrf->table_id; - ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); + ret = rib_add_multipath (AFI_IP6, safi, &p, rib); /* Stats */ if (ret > 0) client->v4_route_add_cnt++; @@ -1556,8 +1554,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) u_char message; u_char nexthop_num; u_char nexthop_type; - unsigned long ifindex; - struct prefix_ipv6 p; + struct prefix p; safi_t safi; static struct in6_addr nexthops[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM]; @@ -1566,7 +1563,6 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) /* Get input stream. */ s = client->ibuf; - ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Allocate new rib. */ @@ -1584,7 +1580,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); /* We need to give nh-addr, nh-ifindex with the same next-hop object * to the rib to ensure that IPv6 multipathing works; need to coalesce @@ -1660,7 +1656,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) rib->vrf_id = zvrf->vrf_id; rib->table = zvrf->table_id; - ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); + ret = rib_add_multipath (AFI_IP, safi, &p, rib); /* Stats */ if (ret > 0) client->v6_route_add_cnt++; From 2a74df346a83d95d75370800710af9cec3026da7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 04:05:36 -0400 Subject: [PATCH 168/226] zebra: Remove unused function reference. The rib_lookup_ipv6 is not implemented. Remove it. Signed-off-by: Donald Sharp --- zebra/rib.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 0faa088d87..500d96cbe4 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -368,8 +368,6 @@ extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); extern void rib_queue_add (struct route_node *rn); -extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); - extern struct route_table *rib_table_ipv6; extern int rib_gc_dest (struct route_node *rn); From 954a34c67ba5988557b6aa121e32c1d48e7f76a6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 05:02:22 -0400 Subject: [PATCH 169/226] zebra: refactor zsend_ipv[4|6]_nexthop_lookup These two functions are functionally equivalent refactor. Signed-off-by: Donald Sharp --- zebra/zserv.c | 106 +++++++++++++------------------------------------- 1 file changed, 27 insertions(+), 79 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index e72683afd1..c09cb17507 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -712,31 +712,39 @@ zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p, return zebra_server_send_message(client); } -#ifdef HAVE_IPV6 static int -zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, - vrf_id_t vrf_id) +zsend_nexthop_lookup (struct zserv *client, afi_t afi, safi_t safi, + vrf_id_t vrf_id, union g_addr *addr) { struct stream *s; struct rib *rib; unsigned long nump; u_char num; struct nexthop *nexthop; - union g_addr gaddr = { .ipv6 = *addr }; /* Lookup nexthop. */ - rib = rib_match (AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, NULL); + rib = rib_match (afi, safi, vrf_id, addr, NULL); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, vrf_id); - stream_put (s, addr, 16); + if (afi == AFI_IP) + { + zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id); + stream_put_in_addr (s, &addr->ipv4); + } + else + { + zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, vrf_id); + stream_put (s, &addr->ipv6, 16); + } if (rib) { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Matching rib entry found.", __func__); stream_putl (s, rib->metric); num = 0; nump = stream_get_endp(s); @@ -744,75 +752,6 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, /* Only non-recursive routes are elegible to resolve nexthop we * are looking up. Therefore, we will just iterate over the top * chain of nexthops. */ - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - stream_putc (s, nexthop->type); - switch (nexthop->type) - { - case ZEBRA_NEXTHOP_IPV6: - stream_put (s, &nexthop->gate.ipv6, 16); - break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - case ZEBRA_NEXTHOP_IFINDEX: - stream_putl (s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - num++; - } - stream_putc_at (s, nump, num); - } - else - { - stream_putl (s, 0); - stream_putc (s, 0); - } - - stream_putw_at (s, 0, stream_get_endp (s)); - - return zebra_server_send_message(client); -} -#endif /* HAVE_IPV6 */ - -static int -zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, - vrf_id_t vrf_id) -{ - struct stream *s; - struct rib *rib; - unsigned long nump; - u_char num; - struct nexthop *nexthop; - union g_addr gaddr = { .ipv4 = addr }; - - /* Lookup nexthop. */ - rib = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, NULL); - - /* Get output stream. */ - s = client->obuf; - stream_reset (s); - - /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id); - stream_put_in_addr (s, &addr); - - if (rib) - { - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug("%s: Matching rib entry found.", __func__); - stream_putl (s, rib->metric); - num = 0; - nump = stream_get_endp(s); - stream_putc (s, 0); - /* Only non-recursive routes are elegible to resolve the nexthop we - * are looking up. Therefore, we will just iterate over the top - * chain of nexthops. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { @@ -826,6 +765,13 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; + case ZEBRA_NEXTHOP_IPV6: + stream_put (s, &nexthop->gate.ipv6, 16); + break; + case ZEBRA_NEXTHOP_IPV6_IFINDEX: + stream_put (s, &nexthop->gate.ipv6, 16); + stream_putl (s, nexthop->ifindex); + break; case ZEBRA_NEXTHOP_IFINDEX: stream_putl (s, nexthop->ifindex); break; @@ -846,7 +792,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, } stream_putw_at (s, 0, stream_get_endp (s)); - + return zebra_server_send_message(client); } @@ -1387,7 +1333,8 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length, if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) zlog_debug("%s: looking up %s", __func__, inet_ntop (AF_INET, &addr, buf, BUFSIZ)); - return zsend_ipv4_nexthop_lookup (client, addr, zvrf->vrf_id); + return zsend_nexthop_lookup (client, AFI_IP, SAFI_UNICAST, + zvrf->vrf_id, (union g_addr *)&addr); } /* MRIB Nexthop lookup for IPv4. */ @@ -1759,7 +1706,8 @@ zread_ipv6_nexthop_lookup (struct zserv *client, u_short length, zlog_debug("%s: looking up %s", __func__, inet_ntop (AF_INET6, &addr, buf, BUFSIZ)); - return zsend_ipv6_nexthop_lookup (client, &addr, zvrf->vrf_id); + return zsend_nexthop_lookup (client, AFI_IP6, SAFI_UNICAST, + zvrf->vrf_id, (union g_addr *)&addr); } /* Register zebra server router-id information. Send current router-id */ From b2e03f7a77ccbc19b014de588e8694f571545cd1 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 30 Aug 2016 08:59:08 -0400 Subject: [PATCH 170/226] bgpd: Add fix for multiple set commands with prefer-global In further testing, found that if there were multiple set commands in the route-map with one being prefer-global, the removal of the prefer-global was not recognized and reacted to correctly. This small addition includes that support Ticket: CM-11480 Signed-off-by: Don Slice Reviewed By: Donald Sharp Testing Done: Manual testing, bgp-min and bgp-smoke completed (cherry picked from commit 3aef92192569c33906c6a2623d0753c16c0e7a64) --- bgpd/bgp_attr.h | 2 ++ bgpd/bgp_routemap.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index b8cdfea137..0bf8c897de 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -148,6 +148,7 @@ struct attr #define BATTR_RMAP_NEXTHOP_UNCHANGED (1 << 3) #define BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED (1 << 4) #define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5) +#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6) /* Router Reflector related structure. */ struct cluster_list @@ -277,6 +278,7 @@ bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags) CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) || + CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) || CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); } diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2a4d416633..e4fd730cf0 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2215,8 +2215,14 @@ route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix, /* Set next hop preference to global */ bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE; SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); } + else + { + bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); + } } return RMAP_OKAY; } From d9ce8324300b19ee154944413e8227a20a81ba04 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 31 Aug 2016 13:31:16 +0200 Subject: [PATCH 171/226] zebra: stack overrun in IPv6 RA receive code (CVE ##TBA##) The IPv6 RA code also receives ICMPv6 RS and RA messages. Unfortunately, by bad coding practice, the buffer size specified on receiving such messages mixed up 2 constants that in fact have different values. The code itself has: #define RTADV_MSG_SIZE 4096 While BUFSIZ is system-dependent, in my case (x86_64 glibc): /usr/include/_G_config.h:#define _G_BUFSIZ 8192 /usr/include/libio.h:#define _IO_BUFSIZ _G_BUFSIZ /usr/include/stdio.h:# define BUFSIZ _IO_BUFSIZ As the latter is passed to the kernel on recvmsg(), it's possible to overwrite 4kB of stack -- with ICMPv6 packets that can be globally sent to any of the system's addresses (using fragmentation to get to 8k). (The socket has filters installed limiting this to RS and RA packets, but does not have a filter for source address or TTL.) Issue discovered by trying to test other stuff, which randomly caused the stack to be smaller than 8kB in that code location, which then causes the kernel to report EFAULT (Bad address). Ticket: CM-12687 Signed-off-by: David Lamparter Reviewed-by: Donald Sharp (cherry picked from commit 6a98e6a916c18bb130430d1dcbd9f23a17ac97bd) --- zebra/rtadv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 8333d2e08c..54614a232e 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -619,7 +619,7 @@ rtadv_read (struct thread *thread) /* Register myself. */ rtadv_event (zns, RTADV_READ, sock); - len = rtadv_recv_packet (zns, sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); + len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit); if (len < 0) { From 5abe0c9519f971a6ecfb7447217593d27f2cb5d7 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 31 Aug 2016 12:58:46 +0000 Subject: [PATCH 172/226] quagga-reload.py should be importable Signed-off-by: Daniel Walton Reviewed-by: Don Slice Ticket: CM-12686 (cherry picked from commit a782e613dd44a4447e4a9ef08cfe014e09da2b2f) --- tools/quagga-reload.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py index 781086d9da..900ed55c43 100755 --- a/tools/quagga-reload.py +++ b/tools/quagga-reload.py @@ -23,6 +23,9 @@ from ipaddr import IPv6Address from pprint import pformat +log = logging.getLogger(__name__) + + class Context(object): """ @@ -80,12 +83,12 @@ class Config(object): The internal representation has been marked appropriately by passing it through vtysh with the -m parameter """ - logger.info('Loading Config object from file %s', filename) + log.info('Loading Config object from file %s', filename) try: file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename]) except subprocess.CalledProcessError as e: - logger.error('vtysh marking of config file %s failed with error %s:', filename, str(e)) + log.error('vtysh marking of config file %s failed with error %s:', filename, str(e)) print "vtysh marking of file %s failed with error: %s" % (filename, str(e)) sys.exit(1) @@ -105,14 +108,14 @@ class Config(object): The internal representation has been marked appropriately by passing it through vtysh with the -m parameter """ - logger.info('Loading Config object from vtysh show running') + log.info('Loading Config object from vtysh show running') try: config_text = subprocess.check_output( "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -", shell=True) except subprocess.CalledProcessError as e: - logger.error('vtysh marking of running config failed with error %s:', str(e)) + log.error('vtysh marking of running config failed with error %s:', str(e)) print "vtysh marking of running config failed with error %s:" % (str(e)) sys.exit(1) @@ -259,13 +262,13 @@ end ctx_keys = [line, ] current_context_lines = [] - logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) self.save_contexts(ctx_keys, current_context_lines) new_ctx = True elif line == "end": self.save_contexts(ctx_keys, current_context_lines) - logger.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) # Start a new context new_ctx = True @@ -281,7 +284,7 @@ end # Start a new context ctx_keys = copy.deepcopy(main_ctx_key) current_context_lines = [] - logger.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys) + log.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys) elif new_ctx is True: if not main_ctx_key: @@ -292,7 +295,7 @@ end current_context_lines = [] new_ctx = False - logger.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) + log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) elif "address-family " in line: main_ctx_key = [] @@ -301,7 +304,7 @@ end self.save_contexts(ctx_keys, current_context_lines) current_context_lines = [] main_ctx_key = copy.deepcopy(ctx_keys) - logger.debug('LINE %-50s: entering sub-context, append to ctx_keys', line) + log.debug('LINE %-50s: entering sub-context, append to ctx_keys', line) if line == "address-family ipv6": ctx_keys.append("address-family ipv6 unicast") @@ -313,7 +316,7 @@ end else: # Continuing in an existing context, add non-commented lines to it current_context_lines.append(line) - logger.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys) + log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys) # Save the context of the last one self.save_contexts(ctx_keys, current_context_lines) @@ -699,7 +702,7 @@ if __name__ == '__main__': # argparse should prevent this from happening but just to be safe... else: raise Exception('Must specify --reload or --test') - logger = logging.getLogger(__name__) + log = logging.getLogger(__name__) # Verify the new config file is valid if not os.path.isfile(args.filename): @@ -728,9 +731,9 @@ if __name__ == '__main__': sys.exit(1) if args.debug: - logger.setLevel(logging.DEBUG) + log.setLevel(logging.DEBUG) - logger.info('Called via "%s"', str(args)) + log.info('Called via "%s"', str(args)) # Create a Config object from the config generated by newconf newconf = Config() @@ -777,7 +780,7 @@ if __name__ == '__main__': elif args.reload: - logger.debug('New Quagga Config\n%s', newconf.get_lines()) + log.debug('New Quagga Config\n%s', newconf.get_lines()) # This looks a little odd but we have to do this twice...here is why # If the user had this running bgp config: @@ -804,7 +807,7 @@ if __name__ == '__main__': for x in range(2): running = Config() running.load_from_show_running() - logger.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines()) + log.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines()) (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) @@ -844,17 +847,17 @@ if __name__ == '__main__': # 'no ip ospf authentication message-digest 1.1.1.1' in # our example above # - Split that last entry by whitespace and drop the last word - logger.warning('Failed to execute %s', ' '.join(cmd)) + log.warning('Failed to execute %s', ' '.join(cmd)) last_arg = cmd[-1].split(' ') if len(last_arg) <= 2: - logger.error('"%s" we failed to remove this command', original_cmd) + log.error('"%s" we failed to remove this command', original_cmd) break new_last_arg = last_arg[0:-1] cmd[-1] = ' '.join(new_last_arg) else: - logger.info('Executed "%s"', ' '.join(cmd)) + log.info('Executed "%s"', ' '.join(cmd)) break if lines_to_add: @@ -874,7 +877,7 @@ if __name__ == '__main__': string.digits) for _ in range(6)) filename = "/var/run/quagga/reload-%s.txt" % random_string - logger.info("%s content\n%s" % (filename, pformat(lines_to_configure))) + log.info("%s content\n%s" % (filename, pformat(lines_to_configure))) with open(filename, 'w') as fh: for line in lines_to_configure: From 5b2c166731c351fd04507b5d495a2ae012cc7ca1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 09:38:28 -0400 Subject: [PATCH 173/226] lib: Remove unused ZEBRA_NEXTHOP_IPV4_ONLINK type Remove the unused ZEBRA_NEXTHOP_IPV4_ONLINK type from the system. Signed-off-by: Donald Sharp --- lib/zebra.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/zebra.h b/lib/zebra.h index e117e26bf6..4b48454835 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -500,7 +500,6 @@ extern const char *zserv_command_string (unsigned int command); #define ZEBRA_NEXTHOP_IPV6 4 #define ZEBRA_NEXTHOP_IPV6_IFINDEX 5 #define ZEBRA_NEXTHOP_BLACKHOLE 6 -#define ZEBRA_NEXTHOP_IPV4_ONLINK 7 #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */ From 5b30316ea51a86de29450b59ea288afa858953b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 10:32:14 -0400 Subject: [PATCH 174/226] bgpd, lib, ospfd, pimd, zebra: Use nexthop_types_t Use the 'enum nexthop_types_t' instead of the zebra.h #defines. And remove code from zebra.h that does not belong there. Signed-off-by: Donald Sharp Reviewed-by: Daniel Walton --- bgpd/bgp_nht.c | 12 +++++----- isisd/isis_zebra.c | 4 ++-- lib/zclient.c | 19 ++++++++-------- lib/zebra.h | 8 ------- ospfd/ospf_zebra.c | 19 ++++++++-------- pimd/pim_zlookup.c | 8 +++---- zebra/zebra_rnh.c | 10 ++++----- zebra/zserv.c | 56 +++++++++++++++++++++++----------------------- 8 files changed, 64 insertions(+), 72 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 42885165c7..11b59fb3e1 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -397,25 +397,23 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id) nexthop->type = stream_getc (s); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: nexthop->ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); nexthop->ifindex = stream_getl (s); break; -#ifdef HAVE_IPV6 - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop->gate.ipv6, s, 16); break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: stream_get (&nexthop->gate.ipv6, s, 16); nexthop->ifindex = stream_getl (s); break; -#endif default: /* do nothing */ break; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 81f9d86930..0e5a7ff3b7 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -278,12 +278,12 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix, /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc (stream, ZEBRA_NEXTHOP_IPV4); + stream_putc (stream, NEXTHOP_TYPE_IPV4); stream_put_in_addr (stream, &nexthop->ip); } else { - stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (stream, NEXTHOP_TYPE_IFINDEX); stream_putl (stream, nexthop->ifindex); } } diff --git a/lib/zclient.c b/lib/zclient.c index 0259af5971..dd13587d74 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -32,6 +32,7 @@ #include "zclient.h" #include "memory.h" #include "table.h" +#include "nexthop.h" /* Zebra client events. */ enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; @@ -746,7 +747,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -755,12 +756,12 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, api->nexthop[i]); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } @@ -813,7 +814,7 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -822,12 +823,12 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV6); + stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } @@ -879,7 +880,7 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } @@ -888,12 +889,12 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, for (i = 0; i < api->nexthop_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IPV6); + stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); } for (i = 0; i < api->ifindex_num; i++) { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, api->ifindex[i]); } } diff --git a/lib/zebra.h b/lib/zebra.h index 4b48454835..546f0dd3d7 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -493,14 +493,6 @@ extern const char *zserv_command_string (unsigned int command); #define ZEBRA_FLAG_REJECT 0x80 #define ZEBRA_FLAG_SCOPE_LINK 0x100 -/* Zebra nexthop flags. */ -#define ZEBRA_NEXTHOP_IFINDEX 1 -#define ZEBRA_NEXTHOP_IPV4 2 -#define ZEBRA_NEXTHOP_IPV4_IFINDEX 3 -#define ZEBRA_NEXTHOP_IPV6 4 -#define ZEBRA_NEXTHOP_IPV6_IFINDEX 5 -#define ZEBRA_NEXTHOP_BLACKHOLE 6 - #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */ #endif diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index f945a4acb7..a31ef5f707 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -35,6 +35,7 @@ #include "plist.h" #include "log.h" #include "lib/bfd.h" +#include "nexthop.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -393,18 +394,18 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else @@ -414,18 +415,18 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else @@ -514,18 +515,18 @@ ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or) if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc (s, ZEBRA_NEXTHOP_IPV4); + stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, &path->nexthop); } else { - stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); + stream_putc (s, NEXTHOP_TYPE_IFINDEX); stream_putl (s, path->ifindex); } diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 1f8cdfa07e..86d7edbd01 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -229,8 +229,8 @@ static int zclient_read_nexthop(struct zclient *zlookup, --length; switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: if (num_ifindex >= tab_size) { char addr_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); @@ -239,7 +239,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, (num_ifindex + 1), tab_size, addr_str); return num_ifindex; } - if (nexthop_type == ZEBRA_NEXTHOP_IPV4_IFINDEX) { + if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { if (length < 4) { zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d", __func__, zlookup->sock, length); @@ -256,7 +256,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_tab[num_ifindex].route_metric = metric; ++num_ifindex; break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: if (num_ifindex >= tab_size) { char addr_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 7b4840164e..ef2357b99c 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -886,21 +886,21 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; #ifdef HAVE_IPV6 - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_put (s, &nexthop->gate.ipv6, 16); break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: stream_put (s, &nexthop->gate.ipv6, 16); stream_putl (s, nexthop->ifindex); break; diff --git a/zebra/zserv.c b/zebra/zserv.c index c09cb17507..480c734711 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -758,21 +758,21 @@ zsend_nexthop_lookup (struct zserv *client, afi_t afi, safi_t safi, stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_put (s, &nexthop->gate.ipv6, 16); break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: stream_put (s, &nexthop->gate.ipv6, 16); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -946,14 +946,14 @@ zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struc stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -1011,14 +1011,14 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p, stream_putc (s, nexthop->type); switch (nexthop->type) { - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: stream_putl (s, nexthop->ifindex); break; default: @@ -1177,23 +1177,23 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); rib_nexthop_ifindex_add (rib, ifindex); break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop.s_addr = stream_get_ipv4 (s); rib_nexthop_ipv4_add (rib, &nexthop, NULL); break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); ifindex = stream_getl (s); rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex); break; - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_forward_getp (s, IPV6_MAX_BYTELEN); break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1276,19 +1276,19 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV4: + case NEXTHOP_TYPE_IPV4: nexthop.s_addr = stream_get_ipv4 (s); nexthop_p = (union g_addr *)&nexthop; break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); nexthop_p = (union g_addr *)&nexthop; ifindex = stream_getl (s); break; - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_forward_getp (s, IPV6_MAX_BYTELEN); break; } @@ -1423,18 +1423,18 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); if (nh_count < MULTIPATH_NUM) { nexthops[nh_count++] = nexthop; } break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: if (if_count < MULTIPATH_NUM) { ifindices[if_count++] = stream_getl (s); } break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1547,18 +1547,18 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); if (nh_count < MULTIPATH_NUM) { nexthops[nh_count++] = nexthop; } break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: if (if_count < MULTIPATH_NUM) { ifindices[if_count++] = stream_getl (s); } break; - case ZEBRA_NEXTHOP_BLACKHOLE: + case NEXTHOP_TYPE_BLACKHOLE: rib_nexthop_blackhole_add (rib); break; } @@ -1654,11 +1654,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { - case ZEBRA_NEXTHOP_IPV6: + case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); pnexthop = (union g_addr *)&nexthop; break; - case ZEBRA_NEXTHOP_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: ifindex = stream_getl (s); break; } From 4c2f8e95a1ae558be380da0a2f42fea5a02785d3 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 2 Sep 2016 06:42:07 +0300 Subject: [PATCH 175/226] configure: fix static linking with readline When static linking is used, the order of the libraries is important, and the libraries using a symbol from another library should be listed *before* the library providing that symbol (see http://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking) for details. When vtysh is linked statically, the command line contains "-lcurses -lreadline", which causes a build failure due to unresolved symbols. This is because readline is using symbols from the curses library: the order should be the opposite. This patch fixes that problem by putting the -lreadline at the beginning of the LIBREADLINE variable calcualted by the configure script. Signed-off-by: Thomas Petazzoni Signed-off-by: Baruch Siach Signed-off-by: Thomas Petazzoni Signed-off-by: Baruch Siach --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f6d7bd33cf..35a40356dd 100755 --- a/configure.ac +++ b/configure.ac @@ -700,7 +700,7 @@ dnl [TODO] on Linux, and in [TODO] on Solaris. )] )] ) - AC_CHECK_LIB(readline, main, LIBREADLINE="$LIBREADLINE -lreadline",, + AC_CHECK_LIB(readline, main, LIBREADLINE="-lreadline $LIBREADLINE",, "$LIBREADLINE") if test $ac_cv_lib_readline_main = no; then AC_MSG_ERROR([vtysh needs libreadline but was not found and usable on your system.]) From bfe15094c260719095c92ecc617ad29fdda160eb Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 2 Sep 2016 06:42:08 +0300 Subject: [PATCH 176/226] lib/memory: fix indirect static link with zlib quagga SNMP support depends on netsnmp, that optionally depends on OpenSSL, which in turn requires zlib. zlib exports the 'zcalloc' symbol, which collides with a function of the same name in memory.c. This is not a problem when linking dynamically, since quagga does not use zlib directly. But static linking fails with the error: CCLD ospfd .../output/host/usr/mips64el-buildroot-linux-uclibc/sysroot/usr/lib/libz.a(zutil.o): In function `zcalloc': zutil.c:(.text+0x48): multiple definition of `zcalloc' .../output/build/quagga-1.0.20160315/lib/.libs/libzebra.a(memory.o):memory.c:(.text+0x1a0): first defined here Rename 'zcalloc' to 'zzcalloc' to avoid symbol collision. Signed-off-by: Baruch Siach Signed-off-by: Baruch Siach --- lib/memory.c | 14 ++++++++------ lib/memory.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/memory.c b/lib/memory.c index 290b999bb8..8d1a03743e 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -80,9 +80,11 @@ zmalloc (int type, size_t size) /* * Allocate memory as in zmalloc, and also clear the memory. + * Add an extra 'z' prefix to function name to avoid collision when linking + * statically with zlib that exports the 'zcalloc' symbol. */ void * -zcalloc (int type, size_t size) +zzcalloc (int type, size_t size) { void *memory; @@ -97,9 +99,9 @@ zcalloc (int type, size_t size) } /* - * Given a pointer returned by zmalloc or zcalloc, free it and + * Given a pointer returned by zmalloc or zzcalloc, free it and * return a pointer to a new size, basically acting like realloc(). - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * Requires: ptr was returned by zmalloc, zzcalloc, or zrealloc with the * same type. * Effects: Returns a pointer to the new memory, or aborts. */ @@ -109,7 +111,7 @@ zrealloc (int type, void *ptr, size_t size) void *memory; if (ptr == NULL) /* is really alloc */ - return zcalloc(type, size); + return zzcalloc(type, size); memory = realloc (ptr, size); if (memory == NULL) @@ -122,7 +124,7 @@ zrealloc (int type, void *ptr, size_t size) /* * Free memory allocated by z*alloc or zstrdup. - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * Requires: ptr was returned by zmalloc, zzcalloc, or zrealloc with the * same type. * Effects: The memory is freed and may no longer be referenced. */ @@ -196,7 +198,7 @@ mtype_zcalloc (const char *file, int line, int type, size_t size) mstat[type].c_calloc++; mstat[type].t_calloc++; - memory = zcalloc (type, size); + memory = zzcalloc (type, size); mtype_log ("xcalloc", memory, file, line, type); return memory; diff --git a/lib/memory.h b/lib/memory.h index 23962235db..501352993d 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -56,7 +56,7 @@ extern struct mlist mlists[]; mtype_zstrdup (__FILE__, __LINE__, (mtype), (str)) #else #define XMALLOC(mtype, size) zmalloc ((mtype), (size)) -#define XCALLOC(mtype, size) zcalloc ((mtype), (size)) +#define XCALLOC(mtype, size) zzcalloc ((mtype), (size)) #define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size)) #define XFREE(mtype, ptr) do { \ zfree ((mtype), (ptr)); \ @@ -67,7 +67,7 @@ extern struct mlist mlists[]; /* Prototypes of memory function. */ extern void *zmalloc (int type, size_t size); -extern void *zcalloc (int type, size_t size); +extern void *zzcalloc (int type, size_t size); extern void *zrealloc (int type, void *ptr, size_t size); extern void zfree (int type, void *ptr); extern char *zstrdup (int type, const char *str); From 6d128e1d7889924ec6ef5eb897d0ba94fed313db Mon Sep 17 00:00:00 2001 From: Jafar Al-Gharaibeh Date: Mon, 1 Aug 2016 18:14:38 -0500 Subject: [PATCH 177/226] vtysh: Fix, guard against NULL pointer dereference getpwuid() may fail returning a null value leaving subsequent code vulnerable to a null pointer dereference. Signed-off-by: Jafar Al-Gharaibeh Signed-off-by: Jafar Al-Gharaibeh Tested-by: NetDEF CI System --- vtysh/vtysh_user.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index 988c768dce..1886ba3a67 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -195,7 +195,11 @@ vtysh_auth (void) struct vtysh_user *user; struct passwd *passwd; - passwd = getpwuid (geteuid ()); + if ((passwd = getpwuid (geteuid ())) == NULL) + { + fprintf (stderr, "could not lookup user ID %d\n", (int) geteuid()); + exit (1); + } user = user_lookup (passwd->pw_name); if (user && user->nopassword) From 0b02a1b49b3dbde83b58a641b146fef70a4497fb Mon Sep 17 00:00:00 2001 From: Jafar Al-Gharaibeh Date: Thu, 28 Jul 2016 14:41:20 -0500 Subject: [PATCH 178/226] config: Give the option of disabling run as user/group Leave "user/group" unset when explicitly configuring with "--disable-user" / "--enable-user=no" and "--disable-group" / "--enable-group=no" This allows quagga to skip unsupported system calls such as setuid() on certain platfroms. Signed-off-by: Jafar Al-Gharaibeh Signed-off-by: Jafar Al-Gharaibeh Tested-by: NetDEF CI System --- configure.ac | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 35a40356dd..edd77b2b8a 100755 --- a/configure.ac +++ b/configure.ac @@ -406,16 +406,22 @@ AC_SUBST(ISIS_TOPOLOGY_INCLUDES) AC_SUBST(ISIS_TOPOLOGY_DIR) AC_SUBST(ISIS_TOPOLOGY_LIB) -if test "${enable_user}" = "yes" || test x"${enable_user}" = x""; then - enable_user="quagga" -elif test "${enable_user}" = "no"; then - enable_user="root" +if test x"${enable_user}" = x"no"; then + enable_user="" +else + if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then + enable_user="quagga" + fi + AC_DEFINE_UNQUOTED(QUAGGA_USER, "${enable_user}", Quagga User) fi -if test "${enable_group}" = "yes" || test x"${enable_group}" = x""; then - enable_group="quagga" -elif test "${enable_group}" = "no"; then - enable_group="root" +if test x"${enable_group}" = x"no"; then + enable_group="" +else + if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then + enable_group="quagga" + fi + AC_DEFINE_UNQUOTED(QUAGGA_GROUP, "${enable_group}", Quagga Group) fi if test x"${enable_vty_group}" = x"yes" ; then @@ -428,8 +434,6 @@ fi AC_SUBST([enable_user]) AC_SUBST([enable_group]) AC_SUBST([enable_vty_group]) -AC_DEFINE_UNQUOTED(QUAGGA_USER, "${enable_user}", Quagga User) -AC_DEFINE_UNQUOTED(QUAGGA_GROUP, "${enable_group}", Quagga Group) enable_configfile_mask=${enable_configfile_mask:-0600} AC_DEFINE_UNQUOTED(CONFIGFILE_MASK, ${enable_configfile_mask}, Mask for config files) From 8ccc7e802b67092e2cf0938992a3ea304e3151b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 15 Jan 2016 17:36:33 +0200 Subject: [PATCH 179/226] lib, zebra: unify link layer type and hardware address handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes the BSD specific usage of struct sockaddr_dl hardware address. This unifies to use explict hw_addr member for the address, and zebra specific enumeration for the link layer type. Additionally the zapi is updated to never send platform specific structures over the wire, but the ll_type along with hw_addr_len and hw_addr are now sent for all platforms. Based on initial work by Paul Jakma. Signed-off-by: Timo Teräs Signed-off-by: Donald Sharp # Please enter the commit message for your changes. Lines starting # with '#' will be kept; you may remove them yourself if you want to. # An empty message aborts the commit. # # Author: Timo Teräs # # rebase in progress; onto 9c2f85d # You are currently editing a commit while rebasing branch 'renato' on '9c2f85d'. # # Changes to be committed: # modified: isisd/isis_circuit.c # modified: lib/if.c # modified: lib/if.h # modified: lib/zclient.c # modified: zebra/interface.c # modified: zebra/interface.h # modified: zebra/kernel_socket.c # modified: zebra/rt_netlink.c # modified: zebra/rtadv.c # modified: zebra/zserv.c # # Untracked files: # "\033\033OA\033OB\033" # 0001-bgpd-fix-build-on-Solaris.patch # ldpd/ # redhat/ldpd.init # redhat/ldpd.service # tags # --- isisd/isis_circuit.c | 10 ------ lib/if.c | 60 ++++++++++++++++++++++++++++++++++ lib/if.h | 75 ++++++++++++++++++++++++++++++++++++------- lib/zclient.c | 5 +-- zebra/interface.c | 18 +---------- zebra/interface.h | 10 ++++++ zebra/kernel_socket.c | 43 ++++++++++++++++++++++--- zebra/rt_netlink.c | 65 ++++++++++++++++++++++++++++++++++++- zebra/rtadv.c | 22 ------------- zebra/zserv.c | 5 +-- 10 files changed, 238 insertions(+), 75 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 728cbdc67d..7138b42318 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -619,15 +619,6 @@ isis_circuit_up (struct isis_circuit *circuit) /* * Get the Hardware Address */ -#ifdef HAVE_STRUCT_SOCKADDR_DL -#ifndef SUNOS_5 - if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN) - zlog_warn ("unsupported link layer"); - else - memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl), - ETH_ALEN); -#endif -#else if (circuit->interface->hw_addr_len != ETH_ALEN) { zlog_warn ("unsupported link layer"); @@ -641,7 +632,6 @@ isis_circuit_up (struct isis_circuit *circuit) circuit->interface->ifindex, ISO_MTU (circuit), snpa_print (circuit->u.bc.snpa)); #endif /* EXTREME_DEBUG */ -#endif /* HAVE_STRUCT_SOCKADDR_DL */ circuit->u.bc.adjdb[0] = list_new (); circuit->u.bc.adjdb[1] = list_new (); diff --git a/lib/if.c b/lib/if.c index 2c63c985dc..11d339ffb7 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1304,3 +1304,63 @@ if_terminate (struct list **intf_list) list_delete (*intf_list); *intf_list = NULL; } + +const char * +if_link_type_str (enum zebra_link_type llt) +{ + switch (llt) + { +#define llts(T,S) case (T): return (S) + llts(ZEBRA_LLT_UNKNOWN, "Unknown"); + llts(ZEBRA_LLT_ETHER, "Ethernet"); + llts(ZEBRA_LLT_EETHER, "Experimental Ethernet"); + llts(ZEBRA_LLT_AX25, "AX.25 Level 2"); + llts(ZEBRA_LLT_PRONET, "PROnet token ring"); + llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB"); + llts(ZEBRA_LLT_ARCNET, "ARCnet"); + llts(ZEBRA_LLT_APPLETLK, "AppleTalk"); + llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI"); + llts(ZEBRA_LLT_ATM, "ATM"); + llts(ZEBRA_LLT_METRICOM, "Metricom STRIP"); + llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4"); + llts(ZEBRA_LLT_EUI64, "EUI-64"); + llts(ZEBRA_LLT_INFINIBAND, "InfiniBand"); + llts(ZEBRA_LLT_SLIP, "SLIP"); + llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); + llts(ZEBRA_LLT_SLIP6, "SLIPv6"); + llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); + llts(ZEBRA_LLT_X25, "CCITT X.25"); + llts(ZEBRA_LLT_PPP, "PPP"); + llts(ZEBRA_LLT_CHDLC, "Cisco HDLC"); + llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC"); + llts(ZEBRA_LLT_LAPB, "LAPB"); + llts(ZEBRA_LLT_IPIP, "IPIP Tunnel"); + llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel"); + llts(ZEBRA_LLT_FRAD, "FRAD"); + llts(ZEBRA_LLT_SKIP, "SKIP vif"); + llts(ZEBRA_LLT_LOOPBACK, "Loopback"); + llts(ZEBRA_LLT_LOCALTLK, "Localtalk"); + llts(ZEBRA_LLT_FDDI, "FDDI"); + llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); + llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); + llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); + llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_IRDA, "IrDA"); + llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); + llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); + llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop"); + llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric"); + llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring"); + llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11"); + llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); + llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); + llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); + default: + zlog_warn ("Unknown value %d", llt); + return "Unknown type!"; +#undef llts + } + return NULL; +} diff --git a/lib/if.h b/lib/if.h index 35d91f0cfa..63e50f48bb 100644 --- a/lib/if.h +++ b/lib/if.h @@ -24,6 +24,66 @@ Boston, MA 02111-1307, USA. */ #include "zebra.h" #include "linklist.h" +/* Interface link-layer type, if known. Derived from: + * + * net/if_arp.h on various platforms - Linux especially. + * http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml + * + * Some of the more obviously defunct technologies left out. + */ +enum zebra_link_type { + ZEBRA_LLT_UNKNOWN = 0, + ZEBRA_LLT_ETHER, + ZEBRA_LLT_EETHER, + ZEBRA_LLT_AX25, + ZEBRA_LLT_PRONET, + ZEBRA_LLT_IEEE802, + ZEBRA_LLT_ARCNET, + ZEBRA_LLT_APPLETLK, + ZEBRA_LLT_DLCI, + ZEBRA_LLT_ATM, + ZEBRA_LLT_METRICOM, + ZEBRA_LLT_IEEE1394, + ZEBRA_LLT_EUI64, + ZEBRA_LLT_INFINIBAND, + ZEBRA_LLT_SLIP, + ZEBRA_LLT_CSLIP, + ZEBRA_LLT_SLIP6, + ZEBRA_LLT_CSLIP6, + ZEBRA_LLT_RSRVD, + ZEBRA_LLT_ADAPT, + ZEBRA_LLT_ROSE, + ZEBRA_LLT_X25, + ZEBRA_LLT_PPP, + ZEBRA_LLT_CHDLC, + ZEBRA_LLT_LAPB, + ZEBRA_LLT_RAWHDLC, + ZEBRA_LLT_IPIP, + ZEBRA_LLT_IPIP6, + ZEBRA_LLT_FRAD, + ZEBRA_LLT_SKIP, + ZEBRA_LLT_LOOPBACK, + ZEBRA_LLT_LOCALTLK, + ZEBRA_LLT_FDDI, + ZEBRA_LLT_SIT, + ZEBRA_LLT_IPDDP, + ZEBRA_LLT_IPGRE, + ZEBRA_LLT_IP6GRE, + ZEBRA_LLT_PIMREG, + ZEBRA_LLT_HIPPI, + ZEBRA_LLT_ECONET, + ZEBRA_LLT_IRDA, + ZEBRA_LLT_FCPP, + ZEBRA_LLT_FCAL, + ZEBRA_LLT_FCPL, + ZEBRA_LLT_FCFABRIC, + ZEBRA_LLT_IEEE802_TR, + ZEBRA_LLT_IEEE80211, + ZEBRA_LLT_IEEE80211_RADIOTAP, + ZEBRA_LLT_IEEE802154, + ZEBRA_LLT_IEEE802154_PHY, +}; + /* Interface name length. @@ -106,20 +166,10 @@ struct interface unsigned int mtu; /* IPv4 MTU */ unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ - /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - union { - /* note that sdl_storage is never accessed, it only exists to make space. - * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits - * best with C aliasing rules. */ - struct sockaddr_dl sdl; - struct sockaddr_storage sdl_storage; - }; -#else - unsigned short hw_type; + /* Link-layer information and hardware address */ + enum zebra_link_type ll_type; u_char hw_addr[INTERFACE_HWADDR_MAX]; int hw_addr_len; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* interface bandwidth, kbits */ unsigned int bandwidth; @@ -330,6 +380,7 @@ extern void if_init (struct list **); extern void if_terminate (struct list **); extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); +extern const char *if_link_type_str (enum zebra_link_type); /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must diff --git a/lib/zclient.c b/lib/zclient.c index dd13587d74..a49403d314 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1118,13 +1118,10 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp) ifp->mtu = stream_getl (s); ifp->mtu6 = stream_getl (s); ifp->bandwidth = stream_getl (s); -#ifdef HAVE_STRUCT_SOCKADDR_DL - stream_get (&ifp->sdl, s, sizeof (ifp->sdl_storage)); -#else + ifp->ll_type = stream_getl (s); ifp->hw_addr_len = stream_getl (s); if (ifp->hw_addr_len) stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); -#endif /* HAVE_STRUCT_SOCKADDR_DL */ } static int diff --git a/zebra/interface.c b/zebra/interface.c index ca10387a84..36270ac425 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -991,9 +991,6 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) static void if_dump_vty (struct vty *vty, struct interface *ifp) { -#ifdef HAVE_STRUCT_SOCKADDR_DL - struct sockaddr_dl *sdl; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ struct connected *connected; struct nbr_connected *nbr_connected; struct listnode *node; @@ -1055,19 +1052,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) if_flag_dump (ifp->flags), VTY_NEWLINE); /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - sdl = &ifp->sdl; - if (sdl != NULL && sdl->sdl_alen != 0) - { - int i; - u_char *ptr; - - vty_out (vty, " HWaddr: "); - for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++) - vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr); - vty_out (vty, "%s", VTY_NEWLINE); - } -#else + vty_out (vty, " Type: %s%s", if_link_type_str (ifp->ll_type), VTY_NEWLINE); if (ifp->hw_addr_len != 0) { int i; @@ -1077,7 +1062,6 @@ if_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]); vty_out (vty, "%s", VTY_NEWLINE); } -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Bandwidth in Mbps */ if (ifp->bandwidth != 0) diff --git a/zebra/interface.h b/zebra/interface.h index 2857198373..6039e2d379 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -211,6 +211,16 @@ struct zebra_if struct irdp_interface irdp; #endif +#ifdef HAVE_STRUCT_SOCKADDR_DL + union { + /* note that sdl_storage is never accessed, it only exists to make space. + * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits + * best with C aliasing rules. */ + struct sockaddr_dl sdl; + struct sockaddr_storage sdl_storage; + }; +#endif + #ifdef SUNOS_5 /* the real IFF_UP state of the primary interface. * need this to differentiate between all interfaces being diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index a500fabbfb..733e627265 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -20,6 +20,7 @@ */ #include +#include #include "if.h" #include "prefix.h" @@ -379,6 +380,29 @@ bsd_linkdetect_translate (struct if_msghdr *ifm) } #endif /* HAVE_BSD_IFI_LINK_STATE */ +static enum zebra_link_type +sdl_to_zebra_link_type (unsigned int sdlt) +{ + switch (sdlt) + { + case IFT_ETHER: return ZEBRA_LLT_ETHER; + case IFT_X25: return ZEBRA_LLT_X25; + case IFT_FDDI: return ZEBRA_LLT_FDDI; + case IFT_PPP: return ZEBRA_LLT_PPP; + case IFT_LOOP: return ZEBRA_LLT_LOOPBACK; + case IFT_SLIP: return ZEBRA_LLT_SLIP; + case IFT_ARCNET: return ZEBRA_LLT_ARCNET; + case IFT_ATM: return ZEBRA_LLT_ATM; + case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK; + case IFT_HIPPI: return ZEBRA_LLT_HIPPI; +#ifdef IFT_IEEE1394 + case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394; +#endif + + default: return ZEBRA_LLT_UNKNOWN; + } +} + /* * Handle struct if_msghdr obtained from reading routing socket or * sysctl (from interface_list). There may or may not be sockaddrs @@ -535,14 +559,23 @@ ifm_read (struct if_msghdr *ifm) * is fine here. * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid */ + ifp->ll_type = ZEBRA_LLT_UNKNOWN; + ifp->hw_addr_len = 0; if (ifnlen) - { + { #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN - memcpy (&ifp->sdl, sdl, sdl->sdl_len); + memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len); #else - memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); + memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl)); #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */ - } + + ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type); + if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) + { + memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen); + ifp->hw_addr_len = sdl->sdl_alen; + } + } if_add_update (ifp); } @@ -1100,7 +1133,7 @@ rtm_write (int message, __func__, dest_buf, mask_buf, index); return -1; } - gate = (union sockunion *) & ifp->sdl; + gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl; } if (mask) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 826c59a729..fb9aef4aaf 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -20,6 +20,7 @@ */ #include +#include /* Hack for GNU libc version 2. */ #ifndef MSG_TRUNC @@ -523,6 +524,68 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) } } +static enum zebra_link_type +netlink_to_zebra_link_type (unsigned int hwt) +{ + switch (hwt) + { + case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; + case ARPHRD_X25: return ZEBRA_LLT_X25; + case ARPHRD_PPP: return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; +#ifdef ARPHRD_IP6GRE + case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; +#endif +#ifdef ARPHRD_IEEE802154_PHY + case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; +#endif + + default: return ZEBRA_LLT_UNKNOWN; + } +} + #define parse_rtattr_nested(tb, max, rta) \ netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) @@ -698,7 +761,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Hardware type and address. */ - ifp->hw_type = ifi->ifi_type; + ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); netlink_interface_update_hw_addr (tb, ifp); if_add_update (ifp); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 54614a232e..8384b327ff 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -152,9 +152,6 @@ rtadv_send_packet (int sock, struct interface *ifp) struct cmsghdr *cmsgptr; struct in6_pktinfo *pkt; struct sockaddr_in6 addr; -#ifdef HAVE_STRUCT_SOCKADDR_DL - struct sockaddr_dl *sdl; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ static void *adata = NULL; unsigned char buf[RTADV_MSG_SIZE]; struct nd_router_advert *rtadv; @@ -315,24 +312,6 @@ rtadv_send_packet (int sock, struct interface *ifp) } /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - sdl = &ifp->sdl; - if (sdl != NULL && sdl->sdl_alen != 0) - { - buf[len++] = ND_OPT_SOURCE_LINKADDR; - - /* Option length should be rounded up to next octet if - the link address does not end on an octet boundary. */ - buf[len++] = (sdl->sdl_alen + 9) >> 3; - - memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen); - len += sdl->sdl_alen; - - /* Pad option to end on an octet boundary. */ - memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7); - len += -(sdl->sdl_alen + 2) & 0x7; - } -#else if (ifp->hw_addr_len != 0) { buf[len++] = ND_OPT_SOURCE_LINKADDR; @@ -348,7 +327,6 @@ rtadv_send_packet (int sock, struct interface *ifp) memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); len += -(ifp->hw_addr_len + 2) & 0x7; } -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* MTU */ if (zif->rtadv.AdvLinkMTU) diff --git a/zebra/zserv.c b/zebra/zserv.c index 480c734711..989bca0788 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -160,13 +160,10 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); -#ifdef HAVE_STRUCT_SOCKADDR_DL - stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage)); -#else + stream_putl (s, ifp->ll_type); stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); From 16f1b9ee2901404ebb5cd9d5e623bb28ffbf236a Mon Sep 17 00:00:00 2001 From: Olivier Dugeon Date: Tue, 19 Apr 2016 16:21:46 +0200 Subject: [PATCH 180/226] Update Traffic Engineering Support for OSPFD NOTE: I am squashing several commits together because they do not independently compile and we need this ability to do any type of sane testing on the patches. Since this series builds together I am doing this. -DBS This new structure is the basis to get new link parameters for Traffic Engineering from Zebra/interface layer to OSPFD and ISISD for the support of Traffic Engineering * lib/if.[c,h]: link parameters struture and get/set functions * lib/command.[c,h]: creation of a new link-node * lib/zclient.[c,h]: modification to the ZBUS message to convey the link parameters structure * lib/zebra.h: New ZBUS message Signed-off-by: Olivier Dugeon Add support for IEEE 754 format * lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to safely convert between big-endian IEEE-754 single and double binary format, as used in IETF RFCs, and C99. Implementation depends on host using __STDC_IEC_559__, which should be everything we care about. Should correctly error out otherwise. * lib/network.[c,h]: Add ntohf and htonf converter * lib/memtypes.c: Add new memeory type for Traffic Engineering support Signed-off-by: Olivier Dugeon Add link parameters support to Zebra * zebra/interface.c: - Add new link-params CLI commands - Add new functions to set/get link parameters for interface * zebra/redistribute.[c,h]: Add new function to propagate link parameters to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering. * zebra/redistribute_null.c: Add new function zebra_interface_parameters_update() * zebra/zserv.[c,h]: Add new functions to send link parameters Signed-off-by: Olivier Dugeon Add support of new link-params CLI to vtysh In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue to use the ordered version for adding line i.e. config_add_line_uniq() to print Interface CLI commands as it completely break the new LINK_PARAMS_NODE. Signed-off-by: Olivier Dugeon Update Traffic Engineering support for OSPFD These patches update original code to RFC3630 (OSPF-TE) and add support of RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support of RFC6827 (ASON - GMPLS). * ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering * ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392 * ospfd/ospf_packet.c: Update checking of OSPF_OPTION * ospfd/ospf_vty.[c,h]: Update ospf_str2area_id * ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get Link Parameters information from the interface to populate Traffic Engineering metrics * ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN) * ospfd/ospf_te.[c,h]: Major modifications to update the code to new link parameters structure and new RFCs Signed-off-by: Olivier Dugeon tmp --- lib/command.c | 8 + lib/command.h | 5 + lib/if.c | 44 + lib/if.h | 64 ++ lib/memtypes.c | 4 + lib/network.c | 18 + lib/network.h | 3 + lib/stream.c | 44 + lib/stream.h | 6 + lib/zclient.c | 186 +++- lib/zclient.h | 4 + lib/zebra.h | 3 +- ospfd/ospf_dump.c | 39 +- ospfd/ospf_dump.h | 4 + ospfd/ospf_opaque.c | 40 +- ospfd/ospf_opaque.h | 8 +- ospfd/ospf_packet.c | 4 +- ospfd/ospf_te.c | 1926 +++++++++++++++++++++++++------------ ospfd/ospf_te.h | 319 +++++- ospfd/ospf_vty.c | 2 +- ospfd/ospf_vty.h | 1 + ospfd/ospf_zebra.c | 21 + ospfd/ospfd.c | 2 +- ospfd/ospfd.h | 3 +- vtysh/extract.pl.in | 1 + vtysh/vtysh.c | 25 + zebra/interface.c | 817 +++++++++++++++- zebra/redistribute.c | 33 +- zebra/redistribute.h | 1 + zebra/redistribute_null.c | 4 + zebra/zserv.c | 39 + zebra/zserv.h | 2 + 32 files changed, 2981 insertions(+), 699 deletions(-) diff --git a/lib/command.c b/lib/command.c index 10ab066bfb..0e921bd636 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2537,8 +2537,12 @@ node_parent ( enum node_type node ) case KEYCHAIN_KEY_NODE: ret = KEYCHAIN_NODE; break; + case LINK_PARAMS_NODE: + ret = INTERFACE_NODE; + break; default: ret = CONFIG_NODE; + break; } return ret; @@ -2926,6 +2930,9 @@ DEFUN (config_exit, case KEYCHAIN_KEY_NODE: vty->node = KEYCHAIN_NODE; break; + case LINK_PARAMS_NODE: + vty->node = INTERFACE_NODE; + break; default: break; } @@ -2975,6 +2982,7 @@ DEFUN (config_end, case MASC_NODE: case PIM_NODE: case VTY_NODE: + case LINK_PARAMS_NODE: vty_config_unlock (vty); vty->node = ENABLE_NODE; break; diff --git a/lib/command.h b/lib/command.h index c1ef0e55bd..8f20a92807 100644 --- a/lib/command.h +++ b/lib/command.h @@ -108,6 +108,7 @@ enum node_type FORWARDING_NODE, /* IP forwarding node. */ PROTOCOL_NODE, /* protocol filtering node */ VTY_NODE, /* Vty node. */ + LINK_PARAMS_NODE, /* Link-parameters node */ }; /* Node which has some commands and prompt string and configuration @@ -516,6 +517,10 @@ struct cmd_token #define AREA_TAG_STR "[area tag]\n" #define COMMUNITY_AANN_STR "Community number where AA and NN are <0-65535>\n" #define COMMUNITY_VAL_STR "Community number in AA:NN format (where AA and NN are <0-65535>) or local-AS|no-advertise|no-export|internet or additive\n" +#define MPLS_TE_STR "MPLS-TE specific commands\n" +#define LINK_PARAMS_STR "Configure interface link parameters\n" +#define OSPF_RI_STR "OSPF Router Information specific commands\n" +#define PCE_STR "PCE Router Information specific commands\n" #define CONF_BACKUP_EXT ".sav" diff --git a/lib/if.c b/lib/if.c index 11d339ffb7..e44882a43e 100644 --- a/lib/if.c +++ b/lib/if.c @@ -205,6 +205,8 @@ if_delete (struct interface *ifp) list_free (ifp->connected); list_free (ifp->nbr_connected); + if_link_params_free (ifp); + XFREE (MTYPE_IF, ifp); } @@ -1364,3 +1366,45 @@ if_link_type_str (enum zebra_link_type llt) } return NULL; } + +struct if_link_params * +if_link_params_get (struct interface *ifp) +{ + int i; + + if (ifp->link_params != NULL) + return ifp->link_params; + + struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, + sizeof (struct if_link_params)); + if (iflp == NULL) return NULL; + + /* Set TE metric == standard metric */ + iflp->te_metric = ifp->metric; + + /* Compute default bandwidth based on interface */ + int bw = (float)((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) + * TE_KILO_BIT / TE_BYTE); + + /* Set Max, Reservable and Unreserved Bandwidth */ + iflp->max_bw = bw; + iflp->max_rsv_bw = bw; + for (i = 0; i < MAX_CLASS_TYPE; i++) + iflp->unrsv_bw[i] = bw; + + /* Update Link parameters status */ + iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; + + /* Finally attach newly created Link Parameters */ + ifp->link_params = iflp; + + return iflp; +} + +void +if_link_params_free (struct interface *ifp) +{ + if (ifp->link_params == NULL) return; + XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params); + ifp->link_params = NULL; +} diff --git a/lib/if.h b/lib/if.h index 63e50f48bb..17f8565595 100644 --- a/lib/if.h +++ b/lib/if.h @@ -131,6 +131,63 @@ struct if_stats }; #endif /* HAVE_PROC_NET_DEV */ +/* Here are "non-official" architectural constants. */ +#define TE_EXT_MASK 0x0FFFFFFF +#define TE_EXT_ANORMAL 0x80000000 +#define LOSS_PRECISION 0.000003 +#define TE_KILO_BIT 1000 +#define TE_BYTE 8 +#define DEFAULT_BANDWIDTH 10000 +#define MAX_CLASS_TYPE 8 +#define MAX_PKT_LOSS 50.331642 + +/* Link Parameters Status: 0: unset, 1: set, */ +#define LP_UNSET 0x0000 +#define LP_TE 0x0001 +#define LP_MAX_BW 0x0002 +#define LP_MAX_RSV_BW 0x0004 +#define LP_UNRSV_BW 0x0008 +#define LP_ADM_GRP 0x0010 +#define LP_RMT_AS 0x0020 +#define LP_DELAY 0x0040 +#define LP_MM_DELAY 0x0080 +#define LP_DELAY_VAR 0x0100 +#define LP_PKT_LOSS 0x0200 +#define LP_RES_BW 0x0400 +#define LP_AVA_BW 0x0800 +#define LP_USE_BW 0x1000 + +#define IS_PARAM_UNSET(lp, st) !(lp->lp_status & st) +#define IS_PARAM_SET(lp, st) (lp->lp_status & st) +#define IS_LINK_PARAMS_SET(lp) (lp->lp_status != LP_UNSET) + +#define SET_PARAM(lp, st) (lp->lp_status) |= (st) +#define UNSET_PARAM(lp, st) (lp->lp_status) &= ~(st) +#define RESET_LINK_PARAM(lp) (lp->lp_status = LP_UNSET) + +/* Link Parameters for Traffic Engineering */ +struct if_link_params { + u_int32_t lp_status; /* Status of Link Parameters: */ + u_int32_t te_metric; /* Traffic Engineering metric */ + float max_bw; /* Maximum Bandwidth */ + float max_rsv_bw; /* Maximum Reservable Bandwidth */ + float unrsv_bw[MAX_CLASS_TYPE]; /* Unreserved Bandwidth per Class Type (8) */ + u_int32_t admin_grp; /* Administrative group */ + u_int32_t rmt_as; /* Remote AS number */ + struct in_addr rmt_ip; /* Remote IP address */ + u_int32_t av_delay; /* Link Average Delay */ + u_int32_t min_delay; /* Link Min Delay */ + u_int32_t max_delay; /* Link Max Delay */ + u_int32_t delay_var; /* Link Delay Variation */ + float pkt_loss; /* Link Packet Loss */ + float res_bw; /* Residual Bandwidth */ + float ava_bw; /* Available Bandwidth */ + float use_bw; /* Utilized Bandwidth */ +}; + +#define INTERFACE_LINK_PARAMS_SIZE sizeof(struct if_link_params) +#define HAS_LINK_PARAMS(ifp) ((ifp)->link_params != NULL) + /* Interface structure */ struct interface { @@ -174,6 +231,9 @@ struct interface /* interface bandwidth, kbits */ unsigned int bandwidth; + /* Link parameters for Traffic Engineering */ + struct if_link_params *link_params; + /* description of the interface. */ char *desc; @@ -418,6 +478,10 @@ extern ifindex_t if_nametoindex (const char *); extern char *if_indextoname (ifindex_t, char *); #endif +/* link parameters */ +struct if_link_params *if_link_params_get (struct interface *); +void if_link_params_free (struct interface *); + /* Exported variables. */ extern struct cmd_element interface_desc_cmd; extern struct cmd_element no_interface_desc_cmd; diff --git a/lib/memtypes.c b/lib/memtypes.c index d0faecb640..56d4faead5 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -77,6 +77,7 @@ struct memory_list memory_list_lib[] = { MTYPE_VRF, "VRF" }, { MTYPE_VRF_NAME, "VRF name" }, { MTYPE_VRF_BITMAP, "VRF bit-map" }, + { MTYPE_IF_LINK_PARAMS, "Informational Link Parameters" }, { -1, NULL }, }; @@ -228,6 +229,8 @@ struct memory_list memory_list_ospf[] = { MTYPE_OSPF_IF_INFO, "OSPF if info" }, { MTYPE_OSPF_IF_PARAMS, "OSPF if params" }, { MTYPE_OSPF_MESSAGE, "OSPF message" }, + { MTYPE_OSPF_MPLS_TE, "OSPF MPLS parameters" }, + { MTYPE_OSPF_PCE_PARAMS, "OSPF PCE parameters" }, { -1, NULL }, }; @@ -269,6 +272,7 @@ struct memory_list memory_list_isis[] = { MTYPE_ISIS_NEXTHOP6, "ISIS nexthop6" }, { MTYPE_ISIS_DICT, "ISIS dictionary" }, { MTYPE_ISIS_DICT_NODE, "ISIS dictionary node" }, + { MTYPE_ISIS_MPLS_TE, "ISIS MPLS_TE parameters" }, { -1, NULL }, }; diff --git a/lib/network.c b/lib/network.c index 3373983b3c..5379ecb5a6 100644 --- a/lib/network.c +++ b/lib/network.c @@ -93,3 +93,21 @@ set_nonblocking(int fd) } return 0; } + +float +htonf (float host) +{ + u_int32_t lu1, lu2; + float convert; + + memcpy (&lu1, &host, sizeof (u_int32_t)); + lu2 = htonl (lu1); + memcpy (&convert, &lu2, sizeof (u_int32_t)); + return convert; +} + +float +ntohf (float net) +{ + return htonf (net); +} diff --git a/lib/network.h b/lib/network.h index 4d9c2284bf..0fcb575d1c 100644 --- a/lib/network.h +++ b/lib/network.h @@ -37,4 +37,7 @@ extern int set_nonblocking(int fd); #define ERRNO_IO_RETRY(EN) \ (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR)) +extern float htonf (float); +extern float ntohf (float); + #endif /* _ZEBRA_NETWORK_H */ diff --git a/lib/stream.c b/lib/stream.c index fe77e2a2ad..809e749fb9 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -543,6 +543,28 @@ stream_get_ipv4 (struct stream *s) return l; } +float +stream_getf (struct stream *s) +{ + union { + float r; + uint32_t d; + } u; + u.d = stream_getl (s); + return u.r; +} + +double +stream_getd (struct stream *s) +{ + union { + double r; + uint64_t d; + } u; + u.d = stream_getq (s); + return u.r; +} + /* Copy to source to stream. * * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap @@ -670,6 +692,28 @@ stream_putq (struct stream *s, uint64_t q) return 8; } +int +stream_putf (struct stream *s, float f) +{ + union { + float i; + uint32_t o; + } u; + u.i = f; + return stream_putl (s, u.o); +} + +int +stream_putd (struct stream *s, double d) +{ + union { + double i; + uint64_t o; + } u; + u.i = d; + return stream_putq (s, u.o); +} + int stream_putc_at (struct stream *s, size_t putp, u_char c) { diff --git a/lib/stream.h b/lib/stream.h index 4e9b21df5f..1e2bc89b32 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -196,6 +196,12 @@ extern uint64_t stream_getq (struct stream *); extern uint64_t stream_getq_from (struct stream *, size_t); extern u_int32_t stream_get_ipv4 (struct stream *); +/* IEEE-754 floats */ +extern float stream_getf (struct stream *); +extern double stream_getd (struct stream *); +extern int stream_putf (struct stream *, float); +extern int stream_putd (struct stream *, double); + #undef stream_read #undef stream_write diff --git a/lib/zclient.c b/lib/zclient.c index a49403d314..753954fd84 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -960,8 +960,6 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * ZEBRA_INTERFACE_DELETE from zebra to the client is: * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+ - * | type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifname | * | | @@ -969,20 +967,32 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * | | * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ifindex | + * | ifindex | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | if_flags | + * | status | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | if_flags | * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | metric | + * | metric | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ifmtu | + * | ifmtu | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ifmtu6 | + * | ifmtu6 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | bandwidth | + * | bandwidth | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | sockaddr_dl | + * | Link Layer Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Harware Address Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Hardware Address if HW lenght different from 0 | + * | ... max INTERFACE_HWADDR_MAX | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Link_params? | Whether a link-params follows: 1 or 0. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Link_params 0 or 1 INTERFACE_LINK_PARAMS_SIZE sized | + * | .... (struct if_link_params). | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ @@ -1071,7 +1081,138 @@ zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id) return ifp; } -/* +static void +link_params_set_value(struct stream *s, struct if_link_params *iflp) +{ + + if (iflp == NULL) + return; + + iflp->lp_status = stream_getl (s); + iflp->te_metric = stream_getl (s); + iflp->max_bw = stream_getf (s); + iflp->max_rsv_bw = stream_getf (s); + uint32_t bwclassnum = stream_getl (s); + { + unsigned int i; + for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++) + iflp->unrsv_bw[i] = stream_getf (s); + if (i < bwclassnum) + zlog_err ("%s: received %d > %d (MAX_CLASS_TYPE) bw entries" + " - outdated library?", + __func__, bwclassnum, MAX_CLASS_TYPE); + } + iflp->admin_grp = stream_getl (s); + iflp->rmt_as = stream_getl (s); + iflp->rmt_ip.s_addr = stream_get_ipv4 (s); + + iflp->av_delay = stream_getl (s); + iflp->min_delay = stream_getl (s); + iflp->max_delay = stream_getl (s); + iflp->delay_var = stream_getl (s); + + iflp->pkt_loss = stream_getf (s); + iflp->res_bw = stream_getf (s); + iflp->ava_bw = stream_getf (s); + iflp->use_bw = stream_getf (s); +} + +struct interface * +zebra_interface_link_params_read (struct stream *s) +{ + struct if_link_params *iflp; + uint32_t ifindex = stream_getl (s); + + struct interface *ifp = if_lookup_by_index (ifindex); + + if (ifp == NULL || s == NULL) + { + zlog_err ("%s: unknown ifindex %u, shouldn't happen", + __func__, ifindex); + return NULL; + } + + if ((iflp = if_link_params_get (ifp)) == NULL) + return NULL; + + link_params_set_value(s, iflp); + + return ifp; +} + +void +zebra_interface_if_set_value (struct stream *s, struct interface *ifp) +{ + u_char link_params_status = 0; + + /* Read interface's index. */ + ifp->ifindex = stream_getl (s); + ifp->status = stream_getc (s); + + /* Read interface's value. */ + ifp->flags = stream_getq (s); + ifp->ptm_enable = stream_getc (s); + ifp->ptm_status = stream_getc (s); + ifp->metric = stream_getl (s); + ifp->mtu = stream_getl (s); + ifp->mtu6 = stream_getl (s); + ifp->bandwidth = stream_getl (s); + ifp->ll_type = stream_getl (s); + ifp->hw_addr_len = stream_getl (s); + if (ifp->hw_addr_len) + stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); + + /* Read Traffic Engineering status */ + link_params_status = stream_getc (s); + /* Then, Traffic Engineering parameters if any */ + if (link_params_status) + { + struct if_link_params *iflp = if_link_params_get (ifp); + link_params_set_value(s, iflp); + } +} + +size_t +zebra_interface_link_params_write (struct stream *s, struct interface *ifp) +{ + size_t w; + struct if_link_params *iflp; + int i; + + if (s == NULL || ifp == NULL || ifp->link_params == NULL) + return 0; + + iflp = ifp->link_params; + w = 0; + + w += stream_putl (s, iflp->lp_status); + + w += stream_putl (s, iflp->te_metric); + w += stream_putf (s, iflp->max_bw); + w += stream_putf (s, iflp->max_rsv_bw); + + w += stream_putl (s, MAX_CLASS_TYPE); + for (i = 0; i < MAX_CLASS_TYPE; i++) + w += stream_putf (s, iflp->unrsv_bw[i]); + + w += stream_putl (s, iflp->admin_grp); + w += stream_putl (s, iflp->rmt_as); + w += stream_put_in_addr (s, &iflp->rmt_ip); + + w += stream_putl (s, iflp->av_delay); + w += stream_putl (s, iflp->min_delay); + w += stream_putl (s, iflp->max_delay); + w += stream_putl (s, iflp->delay_var); + + w += stream_putf (s, iflp->pkt_loss); + w += stream_putf (s, iflp->res_bw); + w += stream_putf (s, iflp->ava_bw); + w += stream_putf (s, iflp->use_bw); + + return w; +} + +/* * format of message for address additon is: * 0 * 0 1 2 3 4 5 6 7 @@ -1100,30 +1241,8 @@ zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id) * : : * | | * +-+-+-+-+-+-+-+-+ - * */ -void -zebra_interface_if_set_value (struct stream *s, struct interface *ifp) -{ - /* Read interface's index. */ - ifp->ifindex = stream_getl (s); - ifp->status = stream_getc (s); - - /* Read interface's value. */ - ifp->flags = stream_getq (s); - ifp->ptm_enable = stream_getc (s); - ifp->ptm_status = stream_getc (s); - ifp->metric = stream_getl (s); - ifp->mtu = stream_getl (s); - ifp->mtu6 = stream_getl (s); - ifp->bandwidth = stream_getl (s); - ifp->ll_type = stream_getl (s); - ifp->hw_addr_len = stream_getl (s); - if (ifp->hw_addr_len) - stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); -} - static int memconstant(const void *s, int c, size_t n) { @@ -1509,6 +1628,9 @@ zclient_read (struct thread *thread) case ZEBRA_REDISTRIBUTE_IPV6_DEL: if (zclient->redistribute_route_ipv6_del) (*zclient->redistribute_route_ipv6_del) (command, zclient, length, vrf_id); + case ZEBRA_INTERFACE_LINK_PARAMS: + if (zclient->interface_link_params) + (*zclient->interface_link_params) (command, zclient, length); break; default: break; diff --git a/lib/zclient.h b/lib/zclient.h index c42d8c9aa3..b95d18ec1a 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -93,6 +93,7 @@ struct zclient int (*interface_down) (int, struct zclient *, uint16_t, vrf_id_t); int (*interface_address_add) (int, struct zclient *, uint16_t, vrf_id_t); int (*interface_address_delete) (int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_link_params) (int, struct zclient *, uint16_t); int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t, vrf_id_t); int (*interface_nbr_address_add) (int, struct zclient *, uint16_t, vrf_id_t); int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t, vrf_id_t); @@ -214,6 +215,9 @@ extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid); extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, struct zapi_ipv4 *); +extern struct interface *zebra_interface_link_params_read (struct stream *); +extern size_t zebra_interface_link_params_write (struct stream *, + struct interface *); #ifdef HAVE_IPV6 /* IPv6 prefix add and delete function prototype. */ diff --git a/lib/zebra.h b/lib/zebra.h index 546f0dd3d7..94158013ec 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -445,7 +445,8 @@ struct in_pktinfo #define ZEBRA_INTERFACE_ENABLE_RADV 47 #define ZEBRA_INTERFACE_DISABLE_RADV 48 #define ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB 49 -#define ZEBRA_MESSAGE_MAX 50 +#define ZEBRA_INTERFACE_LINK_PARAMS 50 +#define ZEBRA_MESSAGE_MAX 51 /* Marker value used in new Zserv, in the byte location corresponding * the command value in the old zserv header. To allow old and new diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index ed279f38ff..a53c726853 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -133,6 +133,7 @@ unsigned long conf_debug_ospf_nsm = 0; unsigned long conf_debug_ospf_lsa = 0; unsigned long conf_debug_ospf_zebra = 0; unsigned long conf_debug_ospf_nssa = 0; +unsigned long conf_debug_ospf_te = 0; /* Enable debug option variables -- valid only session. */ unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0}; @@ -142,7 +143,7 @@ unsigned long term_debug_ospf_nsm = 0; unsigned long term_debug_ospf_lsa = 0; unsigned long term_debug_ospf_zebra = 0; unsigned long term_debug_ospf_nssa = 0; - +unsigned long term_debug_ospf_te = 0; const char * @@ -328,13 +329,14 @@ ospf_options_dump (u_char options) { static char buf[OSPF_OPTION_STR_MAXLEN]; - snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|*", + snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|%s", (options & OSPF_OPTION_O) ? "O" : "-", (options & OSPF_OPTION_DC) ? "DC" : "-", (options & OSPF_OPTION_EA) ? "EA" : "-", (options & OSPF_OPTION_NP) ? "N/P" : "-", (options & OSPF_OPTION_MC) ? "MC" : "-", - (options & OSPF_OPTION_E) ? "E" : "-"); + (options & OSPF_OPTION_E) ? "E" : "-", + (options & OSPF_OPTION_MT) ? "M/T" : "-"); return buf; } @@ -1920,6 +1922,33 @@ DEFUN (no_debug_ospf_instance_nssa, return CMD_SUCCESS; } +DEFUN (debug_ospf_te, + debug_ospf_te_cmd, + "debug ospf te", + DEBUG_STR + OSPF_STR + "OSPF-TE information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON (te, TE); + TERM_DEBUG_ON (te, TE); + return CMD_SUCCESS; +} + +DEFUN (no_debug_ospf_te, + no_debug_ospf_te_cmd, + "no debug ospf te", + NO_STR + DEBUG_STR + OSPF_STR + "OSPF-TE information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF (te, TE); + TERM_DEBUG_OFF (te, TE); + return CMD_SUCCESS; +} + DEFUN (no_debug_ospf, no_debug_ospf_cmd, "no debug ospf", @@ -2270,6 +2299,7 @@ debug_init () install_element (ENABLE_NODE, &debug_ospf_zebra_cmd); install_element (ENABLE_NODE, &debug_ospf_event_cmd); install_element (ENABLE_NODE, &debug_ospf_nssa_cmd); + install_element (ENABLE_NODE, &debug_ospf_te_cmd); install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_detail_cmd); install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_cmd); install_element (ENABLE_NODE, &no_debug_ospf_packet_all_cmd); @@ -2283,6 +2313,7 @@ debug_init () install_element (ENABLE_NODE, &no_debug_ospf_zebra_cmd); install_element (ENABLE_NODE, &no_debug_ospf_event_cmd); install_element (ENABLE_NODE, &no_debug_ospf_nssa_cmd); + install_element (ENABLE_NODE, &no_debug_ospf_te_cmd); install_element (ENABLE_NODE, &show_debugging_ospf_instance_cmd); install_element (ENABLE_NODE, &debug_ospf_instance_packet_send_recv_detail_cmd); @@ -2326,6 +2357,7 @@ debug_init () install_element (CONFIG_NODE, &debug_ospf_zebra_cmd); install_element (CONFIG_NODE, &debug_ospf_event_cmd); install_element (CONFIG_NODE, &debug_ospf_nssa_cmd); + install_element (CONFIG_NODE, &debug_ospf_te_cmd); install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_detail_cmd); install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_cmd); install_element (CONFIG_NODE, &no_debug_ospf_packet_all_cmd); @@ -2339,6 +2371,7 @@ debug_init () install_element (CONFIG_NODE, &no_debug_ospf_zebra_cmd); install_element (CONFIG_NODE, &no_debug_ospf_event_cmd); install_element (CONFIG_NODE, &no_debug_ospf_nssa_cmd); + install_element (CONFIG_NODE, &no_debug_ospf_te_cmd); install_element (CONFIG_NODE, &debug_ospf_instance_packet_send_recv_detail_cmd); install_element (CONFIG_NODE, &debug_ospf_instance_packet_send_recv_cmd); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index a2d5e8ba19..f843df03ae 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -57,6 +57,7 @@ #define OSPF_DEBUG_EVENT 0x01 #define OSPF_DEBUG_NSSA 0x02 +#define OSPF_DEBUG_TE 0x04 /* Macro for setting debug option. */ #define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b) @@ -98,6 +99,8 @@ #define IS_DEBUG_OSPF_NSSA IS_DEBUG_OSPF(nssa,NSSA) +#define IS_DEBUG_OSPF_TE IS_DEBUG_OSPF(te,TE) + #define IS_CONF_DEBUG_OSPF_PACKET(a, b) \ (conf_debug_ospf_packet[a] & OSPF_DEBUG_ ## b) #define IS_CONF_DEBUG_OSPF(a, b) \ @@ -119,6 +122,7 @@ extern unsigned long term_debug_ospf_nsm; extern unsigned long term_debug_ospf_lsa; extern unsigned long term_debug_ospf_zebra; extern unsigned long term_debug_ospf_nssa; +extern unsigned long term_debug_ospf_te; /* Message Strings. */ extern char *ospf_lsa_type_str[]; diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index ee2608b05b..8c6ec892c4 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -213,6 +213,9 @@ ospf_opaque_type_name (u_char opaque_type) case OPAQUE_TYPE_GRACE_LSA: name = "Grace-LSA"; break; + case OPAQUE_TYPE_INTER_AS_LSA: + name = "Inter-AS TE-v2 LSA"; + break; default: if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type)) name = "Unassigned"; @@ -1979,6 +1982,7 @@ ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0) struct opaque_info_per_type *oipt; struct opaque_info_per_id *oipi; struct ospf_lsa *lsa; + struct ospf *top; int delay; if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL @@ -2010,7 +2014,10 @@ ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0) ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); break; case OSPF_OPAQUE_AS_LSA: - ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa); + top = ospf_lookup (); + if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) + top = lsa0->area->ospf; + ospf_ls_retransmit_delete_nbr_as (top, lsa); break; default: zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type); @@ -2055,6 +2062,9 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0) struct opaque_info_per_type *oipt; struct opaque_info_per_id *oipi; struct ospf_lsa *lsa; + struct ospf *top; + + top = ospf_lookup (); if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL) @@ -2078,7 +2088,9 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0) ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); break; case OSPF_OPAQUE_AS_LSA: - ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa); + if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) + top = lsa0->area->ospf; + ospf_ls_retransmit_delete_nbr_as (top, lsa); break; default: zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type); @@ -2102,7 +2114,7 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0) zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); /* This lsa will be flushed and removed eventually. */ - ospf_lsa_flush (lsa0->area->ospf, lsa); + ospf_lsa_flush (top, lsa); out: return; @@ -2144,28 +2156,6 @@ ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, * Followings are util functions; probably be used by Opaque-LSAs only... *------------------------------------------------------------------------*/ -void -htonf (float *src, float *dst) -{ - u_int32_t lu1, lu2; - - memcpy (&lu1, src, sizeof (u_int32_t)); - lu2 = htonl (lu1); - memcpy (dst, &lu2, sizeof (u_int32_t)); - return; -} - -void -ntohf (float *src, float *dst) -{ - u_int32_t lu1, lu2; - - memcpy (&lu1, src, sizeof (u_int32_t)); - lu2 = ntohl (lu1); - memcpy (dst, &lu2, sizeof (u_int32_t)); - return; -} - struct ospf * oi_to_top (struct ospf_interface *oi) { diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index b9490a0ff2..2ac9b41efc 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -60,6 +60,10 @@ #define OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA 1 #define OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC 2 #define OPAQUE_TYPE_GRACE_LSA 3 +#define OPAQUE_TYPE_L1VPN_LSA 5 +#define OPAQUE_TYPE_ROUTER_INFORMATION_LSA 4 +#define OPAQUE_TYPE_INTER_AS_LSA 6 +#define OPAQUE_TYPE_MAX 6 /* Followings types are proposed in internet-draft documents. */ #define OPAQUE_TYPE_8021_QOSPF 129 @@ -70,7 +74,7 @@ #define OPAQUE_TYPE_WILDCARD 0 #define OPAQUE_TYPE_RANGE_UNASSIGNED(type) \ - ( 4 <= (type) && (type) <= 127) + ( OPAQUE_TYPE_MAX <= (type) && (type) <= 127) #define OPAQUE_TYPE_RANGE_RESERVED(type) \ (127 < (type) && (type) <= 255) @@ -137,8 +141,6 @@ extern void ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa); extern void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa); -extern void htonf (float *src, float *dst); -extern void ntohf (float *src, float *dst); extern struct ospf *oi_to_top (struct ospf_interface *oi); #endif /* _ZEBRA_OSPF_OPAQUE_H */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index e6014a14c6..399a558a0d 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -913,7 +913,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, /* Compare options. */ #define REJECT_IF_TBIT_ON 1 /* XXX */ #ifdef REJECT_IF_TBIT_ON - if (CHECK_FLAG (hello->options, OSPF_OPTION_T)) + if (CHECK_FLAG (hello->options, OSPF_OPTION_MT)) { /* * This router does not support non-zero TOS. @@ -1265,7 +1265,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } #ifdef REJECT_IF_TBIT_ON - if (CHECK_FLAG (dd->options, OSPF_OPTION_T)) + if (CHECK_FLAG (dd->options, OSPF_OPTION_MT)) { /* * In Hello protocol, optional capability must have checked diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 6dba2d3bee..b55105ac8f 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1,8 +1,11 @@ /* - * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt + * This is an implementation of RFC3630 * Copyright (C) 2001 KDD R&D Laboratories, Inc. * http://www.kddlabs.co.jp/ * + * Copyright (C) 2012 Orange Labs + * http://www.orange.com + * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it @@ -21,10 +24,11 @@ * 02111-1307, USA. */ -/***** MTYPE definition is not reflected to "memory.h" yet. *****/ -#define MTYPE_OSPF_MPLS_TE_LINKPARAMS MTYPE_TMP +/* Add support of RFC7471 */ +/* Add support of RFC5392, RFC6827 */ #include +#include #include "linklist.h" #include "prefix.h" @@ -39,6 +43,7 @@ #include "thread.h" #include "hash.h" #include "sockunion.h" /* for inet_aton() */ +#include "network.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -56,81 +61,35 @@ #include "ospfd/ospf_ase.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_te.h" - -/* Following structure are internal use only. */ -struct ospf_mpls_te -{ - enum { disabled, enabled } status; - - /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */ - struct list *iflist; - - /* Store Router-TLV in network byte order. */ - struct te_tlv_router_addr router_addr; -}; - -struct mpls_te_link -{ - /* - * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field - * is subdivided into 8-bit "unused" field and 16-bit "instance" field. - * In this implementation, each Link-TLV has its own instance. - */ - u_int32_t instance; - - /* Reference pointer to a Zebra-interface. */ - struct interface *ifp; - - /* Area info in which this MPLS-TE link belongs to. */ - struct ospf_area *area; - - /* Flags to manage this link parameters. */ - u_int32_t flags; -#define LPFLG_LOOKUP_DONE 0x1 -#define LPFLG_LSA_ENGAGED 0x2 -#define LPFLG_LSA_FORCED_REFRESH 0x4 - - /* Store Link-TLV in network byte order. */ - struct te_tlv_link link_header; - struct te_link_subtlv_link_type link_type; - struct te_link_subtlv_link_id link_id; - struct te_link_subtlv_lclif_ipaddr *lclif_ipaddr; - struct te_link_subtlv_rmtif_ipaddr *rmtif_ipaddr; - struct te_link_subtlv_te_metric te_metric; - struct te_link_subtlv_max_bw max_bw; - struct te_link_subtlv_max_rsv_bw max_rsv_bw; - struct te_link_subtlv_unrsv_bw unrsv_bw; - struct te_link_subtlv_rsc_clsclr rsc_clsclr; -}; +#include "ospfd/ospf_vty.h" /* * Global variable to manage Opaque-LSA/MPLS-TE on this node. * Note that all parameter values are stored in network byte order. */ -static struct ospf_mpls_te OspfMplsTE; +struct ospf_mpls_te OspfMplsTE; -enum oifstate { +const char *mode2text[] = { "Disable", "AS", "Area", "Emulate" }; + +enum oifstate +{ OI_ANY, OI_DOWN, OI_UP }; -enum sched_opcode { - REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA -}; - /*------------------------------------------------------------------------* * Followings are initialize/terminate functions for MPLS-TE handling. *------------------------------------------------------------------------*/ static int ospf_mpls_te_new_if (struct interface *ifp); static int ospf_mpls_te_del_if (struct interface *ifp); -static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status); +static void ospf_mpls_te_ism_change (struct ospf_interface *oi, + int old_status); static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status); static void ospf_mpls_te_config_write_router (struct vty *vty); -static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp); static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa); -static int ospf_mpls_te_lsa_originate (void *arg); +static int ospf_mpls_te_lsa_originate_area (void *arg); +static int ospf_mpls_te_lsa_originate_as (void *arg); static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa); -static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode); static void del_mpls_te_link (void *val); static void ospf_mpls_te_register_vty (void); @@ -148,21 +107,22 @@ ospf_mpls_te_init (void) ospf_mpls_te_ism_change, ospf_mpls_te_nsm_change, ospf_mpls_te_config_write_router, - ospf_mpls_te_config_write_if, + NULL,/*ospf_mpls_te_config_write_if */ NULL,/* ospf_mpls_te_config_write_debug */ ospf_mpls_te_show_info, - ospf_mpls_te_lsa_originate, + ospf_mpls_te_lsa_originate_area, ospf_mpls_te_lsa_refresh, NULL,/* ospf_mpls_te_new_lsa_hook */ NULL /* ospf_mpls_te_del_lsa_hook */); if (rc != 0) { - zlog_warn ("ospf_mpls_te_init: Failed to register functions"); + zlog_warn ("ospf_mpls_te_init: Failed to register Traffic Engineering functions"); goto out; } memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te)); OspfMplsTE.status = disabled; + OspfMplsTE.inter_as = Disable; OspfMplsTE.iflist = list_new (); OspfMplsTE.iflist->del = del_mpls_te_link; @@ -172,16 +132,75 @@ out: return rc; } +/* Additional register for RFC5392 support */ +static int +ospf_mpls_te_register (enum inter_as_mode mode) +{ + int rc; + u_int8_t scope; + + if (OspfMplsTE.inter_as != Disable) + return 0; + + if (mode == AS) + scope = OSPF_OPAQUE_AS_LSA; + else + scope = OSPF_OPAQUE_AREA_LSA; + + rc = ospf_register_opaque_functab (scope, + OPAQUE_TYPE_INTER_AS_LSA, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ospf_mpls_te_show_info, + ospf_mpls_te_lsa_originate_as, + ospf_mpls_te_lsa_refresh, NULL, NULL); + + if (rc != 0) + { + zlog_warn ("ospf_router_info_init: Failed to register Inter-AS functions"); + return rc; + } + + return 0; +} + +static int +ospf_mpls_te_unregister () +{ + u_int8_t scope; + + if (OspfMplsTE.inter_as == Disable) + return 0; + + if (OspfMplsTE.inter_as == AS) + scope = OSPF_OPAQUE_AS_LSA; + else + scope = OSPF_OPAQUE_AREA_LSA; + + ospf_delete_opaque_functab (scope, OPAQUE_TYPE_INTER_AS_LSA); + + return 0; + +} + void ospf_mpls_te_term (void) { list_delete (OspfMplsTE.iflist); - OspfMplsTE.iflist = NULL; - OspfMplsTE.status = disabled; ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); + OspfMplsTE.status = disabled; + + ospf_mpls_te_unregister (); + OspfMplsTE.inter_as = Disable; + return; } @@ -192,11 +211,11 @@ ospf_mpls_te_term (void) static void del_mpls_te_link (void *val) { - XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val); + XFREE (MTYPE_OSPF_MPLS_TE, val); return; } -static u_int32_t +u_int32_t get_mpls_te_instance_value (void) { static u_int32_t seqno = 0; @@ -274,9 +293,9 @@ lookup_linkparams_by_instance (struct ospf_lsa *lsa) } static void -ospf_mpls_te_foreach_area ( - void (*func)(struct mpls_te_link *lp, enum sched_opcode), - enum sched_opcode sched_opcode) +ospf_mpls_te_foreach_area (void (*func) + (struct mpls_te_link * lp, opcode_t sched_opcode), + opcode_t sched_opcode) { struct listnode *node, *nnode; struct listnode *node2; @@ -285,10 +304,12 @@ ospf_mpls_te_foreach_area ( for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) { + /* Skip Inter-AS TEv2 Links */ + if (IS_INTER_AS (lp->type)) + continue; if ((area = lp->area) == NULL) continue; - if (lp->flags & LPFLG_LOOKUP_DONE) - continue; + if CHECK_FLAG (lp->flags, LPFLG_LOOKUP_DONE) continue; if (func != NULL) (* func)(lp, sched_opcode); @@ -297,12 +318,12 @@ ospf_mpls_te_foreach_area ( if ((lp = listgetdata (node2)) != NULL) if (lp->area != NULL) if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id)) - lp->flags |= LPFLG_LOOKUP_DONE; + SET_FLAG (lp->flags, LPFLG_LOOKUP_DONE); } for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) if (lp->area != NULL) - lp->flags &= ~LPFLG_LOOKUP_DONE; + UNSET_FLAG (lp->flags, LPFLG_LOOKUP_DONE); return; } @@ -311,7 +332,7 @@ static void set_mpls_te_router_addr (struct in_addr ipv4) { OspfMplsTE.router_addr.header.type = htons (TE_TLV_ROUTER_ADDR); - OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4)); + OspfMplsTE.router_addr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); OspfMplsTE.router_addr.value = ipv4; return; } @@ -319,7 +340,6 @@ set_mpls_te_router_addr (struct in_addr ipv4) static void set_linkparams_link_header (struct mpls_te_link *lp) { - struct te_tlv_header *tlvh; u_int16_t length = 0; /* TE_LINK_SUBTLV_LINK_TYPE */ @@ -331,14 +351,12 @@ set_linkparams_link_header (struct mpls_te_link *lp) length += TLV_SIZE (&lp->link_id.header); /* TE_LINK_SUBTLV_LCLIF_IPADDR */ - if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL - && ntohs (tlvh->type) != 0) - length += TLV_SIZE (tlvh); + if (lp->lclif_ipaddr.header.type != 0) + length += TLV_SIZE (&lp->lclif_ipaddr.header); /* TE_LINK_SUBTLV_RMTIF_IPADDR */ - if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL - && ntohs (tlvh->type) != 0) - length += TLV_SIZE (tlvh); + if (lp->rmtif_ipaddr.header.type != 0) + length += TLV_SIZE (&lp->rmtif_ipaddr.header); /* TE_LINK_SUBTLV_TE_METRIC */ if (ntohs (lp->te_metric.header.type) != 0) @@ -360,6 +378,50 @@ set_linkparams_link_header (struct mpls_te_link *lp) if (ntohs (lp->rsc_clsclr.header.type) != 0) length += TLV_SIZE (&lp->rsc_clsclr.header); + /* TE_LINK_SUBTLV_LLRI */ + if (ntohs (lp->llri.header.type) != 0) + length += TLV_SIZE (&lp->llri.header); + + /* TE_LINK_SUBTLV_RIP */ + if (ntohs (lp->rip.header.type) != 0) + length += TLV_SIZE (&lp->rip.header); + + /* TE_LINK_SUBTLV_RAS */ + if (ntohs (lp->ras.header.type) != 0) + length += TLV_SIZE (&lp->ras.header); + + /* TE_LINK_SUBTLV_LRRID */ + if (ntohs (lp->lrrid.header.type) != 0) + length += TLV_SIZE (&lp->lrrid.header); + + /* TE_LINK_SUBTLV_AV_DELAY */ + if (ntohs (lp->av_delay.header.type) != 0) + length += TLV_SIZE (&lp->av_delay.header); + + /* TE_LINK_SUBTLV_MM_DELAY */ + if (ntohs (lp->mm_delay.header.type) != 0) + length += TLV_SIZE (&lp->mm_delay.header); + + /* TE_LINK_SUBTLV_DELAY_VAR */ + if (ntohs (lp->delay_var.header.type) != 0) + length += TLV_SIZE (&lp->delay_var.header); + + /* TE_LINK_SUBTLV_PKT_LOSS */ + if (ntohs (lp->pkt_loss.header.type) != 0) + length += TLV_SIZE (&lp->pkt_loss.header); + + /* TE_LINK_SUBTLV_RES_BW */ + if (ntohs (lp->res_bw.header.type) != 0) + length += TLV_SIZE (&lp->res_bw.header); + + /* TE_LINK_SUBTLV_AVA_BW */ + if (ntohs (lp->ava_bw.header.type) != 0) + length += TLV_SIZE (&lp->ava_bw.header); + + /* TE_LINK_SUBTLV_USE_BW */ + if (ntohs (lp->use_bw.header.type) != 0) + length += TLV_SIZE (&lp->use_bw.header); + lp->link_header.header.type = htons (TE_TLV_LINK); lp->link_header.header.length = htons (length); @@ -370,7 +432,7 @@ static void set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp) { lp->link_type.header.type = htons (TE_LINK_SUBTLV_LINK_TYPE); - lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value)); + lp->link_type.header.length = htons (TE_LINK_SUBTLV_TYPE_SIZE); switch (oi->type) { @@ -396,7 +458,7 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) int done = 0; lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID); - lp->link_id.header.length = htons (sizeof (lp->link_id.value)); + lp->link_id.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); /* * The Link ID is identical to the contents of the Link ID field @@ -406,8 +468,7 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) { case OSPF_IFTYPE_POINTOPOINT: /* Take the router ID of the neighbor. */ - if ((nbr = ospf_nbr_lookup_ptop (oi)) - && nbr->state == NSM_Full) + if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full) { lp->link_id.value = nbr->router_id; done = 1; @@ -442,40 +503,60 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) return; } +static void +set_linkparams_lclif_ipaddr (struct mpls_te_link *lp, struct in_addr lclif) +{ + + lp->lclif_ipaddr.header.type = htons (TE_LINK_SUBTLV_LCLIF_IPADDR); + lp->lclif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->lclif_ipaddr.value[0] = lclif; + return; +} + +static void +set_linkparams_rmtif_ipaddr (struct mpls_te_link *lp, struct in_addr rmtif) +{ + + lp->rmtif_ipaddr.header.type = htons (TE_LINK_SUBTLV_RMTIF_IPADDR); + lp->rmtif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->rmtif_ipaddr.value[0] = rmtif; + return; +} + static void set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric) { lp->te_metric.header.type = htons (TE_LINK_SUBTLV_TE_METRIC); - lp->te_metric.header.length = htons (sizeof (lp->te_metric.value)); + lp->te_metric.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); lp->te_metric.value = htonl (te_metric); return; } static void -set_linkparams_max_bw (struct mpls_te_link *lp, float *fp) +set_linkparams_max_bw (struct mpls_te_link *lp, float fp) { lp->max_bw.header.type = htons (TE_LINK_SUBTLV_MAX_BW); - lp->max_bw.header.length = htons (sizeof (lp->max_bw.value)); - htonf (fp, &lp->max_bw.value); + lp->max_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->max_bw.value = htonf (fp); return; } static void -set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp) +set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float fp) { lp->max_rsv_bw.header.type = htons (TE_LINK_SUBTLV_MAX_RSV_BW); - lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value)); - htonf (fp, &lp->max_rsv_bw.value); + lp->max_rsv_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->max_rsv_bw.value = htonf (fp); return; } static void -set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp) +set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float fp) { /* Note that TLV-length field is the size of array. */ lp->unrsv_bw.header.type = htons (TE_LINK_SUBTLV_UNRSV_BW); - lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value)); - htonf (fp, &lp->unrsv_bw.value [priority]); + lp->unrsv_bw.header.length = htons (TE_LINK_SUBTLV_UNRSV_SIZE); + lp->unrsv_bw.value [priority] = htonf (fp); return; } @@ -483,21 +564,283 @@ static void set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor) { lp->rsc_clsclr.header.type = htons (TE_LINK_SUBTLV_RSC_CLSCLR); - lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value)); + lp->rsc_clsclr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); lp->rsc_clsclr.value = htonl (classcolor); return; } +static void +set_linkparams_inter_as (struct mpls_te_link *lp, struct in_addr addr, + u_int32_t as) +{ + + /* Set the Remote ASBR IP address and then the associated AS number */ + lp->rip.header.type = htons (TE_LINK_SUBTLV_RIP); + lp->rip.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->rip.value = addr; + + lp->ras.header.type = htons (TE_LINK_SUBTLV_RAS); + lp->ras.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->ras.value = htonl (as); +} + +static void +unset_linkparams_inter_as (struct mpls_te_link *lp) +{ + + /* Reset the Remote ASBR IP address and then the associated AS number */ + lp->rip.header.type = htons (0); + lp->rip.header.length = htons (0); + lp->rip.value.s_addr = htonl (0); + + lp->ras.header.type = htons (0); + lp->ras.header.length = htons (0); + lp->ras.value = htonl (0); +} + +void +set_linkparams_llri (struct mpls_te_link *lp, u_int32_t local, + u_int32_t remote) +{ + + lp->llri.header.type = htons (TE_LINK_SUBTLV_LLRI); + lp->llri.header.length = htons (TE_LINK_SUBTLV_LLRI_SIZE); + lp->llri.local = htonl (local); + lp->llri.remote = htonl (remote); +} + +void +set_linkparams_lrrid (struct mpls_te_link *lp, struct in_addr local, + struct in_addr remote) +{ + + lp->lrrid.header.type = htons (TE_LINK_SUBTLV_LRRID); + lp->lrrid.header.length = htons (TE_LINK_SUBTLV_LRRID_SIZE); + lp->lrrid.local.s_addr = local.s_addr; + lp->lrrid.remote.s_addr = remote.s_addr; +} + +static void +set_linkparams_av_delay (struct mpls_te_link *lp, u_int32_t delay, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->av_delay.header.type = htons (TE_LINK_SUBTLV_AV_DELAY); + lp->av_delay.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + tmp = delay & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->av_delay.value = htonl (tmp); + return; +} + +static void +set_linkparams_mm_delay (struct mpls_te_link *lp, u_int32_t low, u_int32_t high, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->mm_delay.header.type = htons (TE_LINK_SUBTLV_MM_DELAY); + lp->mm_delay.header.length = htons (TE_LINK_SUBTLV_MM_DELAY_SIZE); + tmp = low & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->mm_delay.low = htonl (tmp); + lp->mm_delay.high = htonl (high); + return; +} + +static void +set_linkparams_delay_var (struct mpls_te_link *lp, u_int32_t jitter) +{ + /* Note that TLV-length field is the size of array. */ + lp->delay_var.header.type = htons (TE_LINK_SUBTLV_DELAY_VAR); + lp->delay_var.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->delay_var.value = htonl (jitter & TE_EXT_MASK); + return; +} + +static void +set_linkparams_pkt_loss (struct mpls_te_link *lp, u_int32_t loss, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->pkt_loss.header.type = htons (TE_LINK_SUBTLV_PKT_LOSS); + lp->pkt_loss.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + tmp = loss & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->pkt_loss.value = htonl (tmp); + return; +} + +static void +set_linkparams_res_bw (struct mpls_te_link *lp, float fp) +{ + /* Note that TLV-length field is the size of array. */ + lp->res_bw.header.type = htons (TE_LINK_SUBTLV_RES_BW); + lp->res_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->res_bw.value = htonf (fp); + return; +} + +static void +set_linkparams_ava_bw (struct mpls_te_link *lp, float fp) +{ + /* Note that TLV-length field is the size of array. */ + lp->ava_bw.header.type = htons (TE_LINK_SUBTLV_AVA_BW); + lp->ava_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->ava_bw.value = htonf (fp); + return; +} + +static void +set_linkparams_use_bw (struct mpls_te_link *lp, float fp) +{ + /* Note that TLV-length field is the size of array. */ + lp->use_bw.header.type = htons (TE_LINK_SUBTLV_USE_BW); + lp->use_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + lp->use_bw.value = htonf (fp); + return; +} + +/* Update TE parameters from Interface */ +static void +update_linkparams(struct mpls_te_link *lp) +{ + int i; + struct interface *ifp; + + /* Get the Interface structure */ + if ((ifp = lp->ifp) == NULL) + { + zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters"); + return; + } + if (!HAS_LINK_PARAMS(ifp)) + { + zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface"); + return; + } + + /* RFC3630 metrics */ + if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) + set_linkparams_rsc_clsclr (lp, ifp->link_params->admin_grp); + else + TLV_TYPE(lp->rsc_clsclr) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) + set_linkparams_max_bw (lp, ifp->link_params->max_bw); + else + TLV_TYPE(lp->max_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) + set_linkparams_max_rsv_bw (lp, ifp->link_params->max_rsv_bw); + else + TLV_TYPE(lp->max_rsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) + for (i = 0; i < MAX_CLASS_TYPE; i++) + set_linkparams_unrsv_bw (lp, i, ifp->link_params->unrsv_bw[i]); + else + TLV_TYPE(lp->unrsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_TE)) + set_linkparams_te_metric(lp, ifp->link_params->te_metric); + else + TLV_TYPE(lp->te_metric) = 0; + + /* TE metric Extensions */ + if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) + set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0); + else + TLV_TYPE(lp->av_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) + set_linkparams_mm_delay(lp, ifp->link_params->min_delay, ifp->link_params->max_delay, 0); + else + TLV_TYPE(lp->mm_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) + set_linkparams_delay_var(lp, ifp->link_params->delay_var); + else + TLV_TYPE(lp->delay_var) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) + set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0); + else + TLV_TYPE(lp->pkt_loss) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) + set_linkparams_res_bw(lp, ifp->link_params->res_bw); + else + TLV_TYPE(lp->res_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) + set_linkparams_ava_bw(lp, ifp->link_params->ava_bw); + else + TLV_TYPE(lp->ava_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) + set_linkparams_use_bw(lp, ifp->link_params->use_bw); + else + TLV_TYPE(lp->use_bw) = 0; + + /* RFC5392 */ + if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) + { + /* Flush LSA if it engaged and was previously a STD_TE one */ + if (IS_STD_TE(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) + { + if (IS_DEBUG_OSPF_TE) + zlog_debug("OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]", + ifp->name, lp->flags, lp->type); + + ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); + /* Then, switch it to INTER-AS */ + if (OspfMplsTE.inter_as == AS) + lp->flags = INTER_AS | FLOOD_AS; + else + { + lp->flags = INTER_AS | FLOOD_AREA; + lp->area = ospf_area_lookup_by_area_id (ospf_lookup(), OspfMplsTE.interas_areaid); + } + } + set_linkparams_inter_as(lp, ifp->link_params->rmt_ip, ifp->link_params->rmt_as); + } + else + { + if (IS_DEBUG_OSPF_TE) + zlog_debug("OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]", + ifp->name, lp->flags, lp->type); + + /* reset inter-as TE params */ + /* Flush LSA if it engaged and was previously an INTER_AS one */ + if (IS_INTER_AS(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) + { + ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); + /* Then, switch it to Standard TE */ + lp->flags = STD_TE | FLOOD_AREA; + } + unset_linkparams_inter_as (lp); + } +} + static void initialize_linkparams (struct mpls_te_link *lp) { struct interface *ifp = lp->ifp; struct ospf_interface *oi; - float fval; - int i; + + if (IS_DEBUG_OSPF_TE) + zlog_debug("MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s", + ifp->name); if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL) - return; + { + zlog_warn("MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s", + ifp->name); + return; + } /* * Try to set initial values those can be derived from @@ -505,18 +848,19 @@ initialize_linkparams (struct mpls_te_link *lp) */ set_linkparams_link_type (oi, lp); - /* - * Linux and *BSD kernel holds bandwidth parameter as an "int" type. - * We may have to reconsider, if "ifp->bandwidth" type changes to float. - */ - fval = (float)((ifp->bandwidth ? ifp->bandwidth - : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8); + /* Set local IP addr */ + set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4); - set_linkparams_max_bw (lp, &fval); - set_linkparams_max_rsv_bw (lp, &fval); + /* Set Remote IP addr if Point to Point Interface */ + if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) + { + struct prefix *pref = CONNECTED_PREFIX(oi->connected); + if (pref != NULL) + set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4); + } - for (i = 0; i < 8; i++) - set_linkparams_unrsv_bw (lp, i, &fval); + /* Keep Area information in combination with link parameters. */ + lp->area = oi->area; return; } @@ -527,13 +871,22 @@ is_mandated_params_set (struct mpls_te_link *lp) int rc = 0; if (ntohs (OspfMplsTE.router_addr.header.type) == 0) + { + zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Router Address"); goto out; + } if (ntohs (lp->link_type.header.type) == 0) + { + zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link Type"); goto out; + } - if (ntohs (lp->link_id.header.type) == 0) + if (!IS_INTER_AS (lp->type) && (ntohs (lp->link_id.header.type) == 0)) + { + zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link ID"); goto out; + } rc = 1; out: @@ -550,6 +903,10 @@ ospf_mpls_te_new_if (struct interface *ifp) struct mpls_te_link *new; int rc = -1; + if (IS_DEBUG_OSPF_TE) + zlog_debug ("MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list", + ifp->link_params ? "Active" : "Inactive", ifp->name); + if (lookup_linkparams_by_ifp (ifp) != NULL) { zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp); @@ -557,23 +914,33 @@ ospf_mpls_te_new_if (struct interface *ifp) goto out; } - new = XCALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS, - sizeof (struct mpls_te_link)); + new = XCALLOC (MTYPE_OSPF_MPLS_TE, sizeof (struct mpls_te_link)); if (new == NULL) { zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno)); goto out; } - new->area = NULL; - new->flags = 0; new->instance = get_mpls_te_instance_value (); new->ifp = ifp; + /* By default TE-Link is RFC3630 compatible flooding in Area and not active */ + /* This default behavior will be adapted with call to ospf_mpls_te_update_if() */ + new->type = STD_TE | FLOOD_AREA; + new->flags = LPFLG_LSA_INACTIVE; - initialize_linkparams (new); + /* Initialize Link Parameters from Interface */ + initialize_linkparams(new); + /* Set TE Parameters from Interface */ + update_linkparams(new); + + /* Add Link Parameters structure to the list */ listnode_add (OspfMplsTE.iflist, new); + if (IS_DEBUG_OSPF_TE) + zlog_debug("OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]", + ifp->name, new->flags, new->type); + /* Schedule Opaque-LSA refresh. *//* XXX */ rc = 0; @@ -598,7 +965,7 @@ ospf_mpls_te_del_if (struct interface *ifp) if (listcount (iflist) == 0) iflist->head = iflist->tail = NULL; - XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp); + XFREE (MTYPE_OSPF_MPLS_TE, lp); } /* Schedule Opaque-LSA refresh. *//* XXX */ @@ -608,6 +975,56 @@ ospf_mpls_te_del_if (struct interface *ifp) return rc; } +/* Main initialization / update function of the MPLS TE Link context */ + +/* Call when interface TE Link parameters are modified */ +void +ospf_mpls_te_update_if (struct interface *ifp) +{ + struct mpls_te_link *lp; + + if (IS_DEBUG_OSPF_TE) + zlog_debug ("OSPF MPLS-TE: Update LSA parameters for interface %s [%s]", + ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF"); + + /* Get Link context from interface */ + if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) + { + zlog_warn ("OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s", ifp->name); + return; + } + + /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */ + if (HAS_LINK_PARAMS(ifp)) + { + SET_FLAG (lp->flags, LPFLG_LSA_ACTIVE); + + /* Update TE parameters */ + update_linkparams(lp); + + /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is enabled */ + if (OspfMplsTE.status == enabled) + if (lp->area != NULL) + { + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); + else + ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); + } + } + else + { + /* If MPLS TE is disable on this interface, flush LSA if it is already engaged */ + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); + else + /* Reset Activity flag */ + lp->flags = LPFLG_LSA_INACTIVE; + } + + return; +} + static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state) { @@ -620,10 +1037,10 @@ ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state) zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi)); goto out; } + if (oi->area == NULL || oi->area->ospf == NULL) { - zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", -IF_NAME (oi)); + zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi)); goto out; } #ifdef notyet @@ -632,13 +1049,17 @@ IF_NAME (oi)); || (lp->area != NULL && oi->area == NULL)) { /* How should we consider this case? */ - zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A"); + zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", + IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A"); ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); } #endif - /* Keep Area information in conbination with linkparams. */ + /* Keep Area information in combination with linkparams. */ lp->area = oi->area; + /* Keep interface MPLS-TE status */ + lp->flags = HAS_LINK_PARAMS(oi->ifp); + switch (oi->state) { case ISM_PointToPoint: @@ -648,37 +1069,53 @@ IF_NAME (oi)); old_type = lp->link_type; old_id = lp->link_id; + /* Set Link type, Link ID, Local and Remote IP addr */ set_linkparams_link_type (oi, lp); set_linkparams_link_id (oi, lp); + set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4); + if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) + { + struct prefix *pref = CONNECTED_PREFIX(oi->connected); + if (pref != NULL) + set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4); + } + + /* Update TE parameters */ + update_linkparams(lp); + + /* Try to Schedule LSA */ if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type) || old_type.link_type.value != lp->link_type.link_type.value) || (ntohs (old_id.header.type) != ntohs (lp->link_id.header.type) - || ntohl (old_id.value.s_addr) != ntohl (lp->link_id.value.s_addr))) + || ntohl (old_id.value.s_addr) != + ntohl (lp->link_id.value.s_addr))) { - if (lp->flags & LPFLG_LSA_ENGAGED) + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); + ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); + } break; default: lp->link_type.header.type = htons (0); lp->link_id.header.type = htons (0); - if (lp->flags & LPFLG_LSA_ENGAGED) + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); break; } out: return; + } static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state) { - /* So far, nothing to do here. */ + /* Nothing to do here */ return; } @@ -706,106 +1143,10 @@ build_router_tlv (struct stream *s) } static void -build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->link_type.header; - if (ntohs (tlvh->type) != 0) +build_link_subtlv (struct stream *s, struct te_tlv_header *tlvh) { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} -static void -build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->link_id.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr; - if (tlvh != NULL && ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr; - if (tlvh != NULL && ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->te_metric.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->max_bw.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->max_rsv_bw.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->unrsv_bw.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp) -{ - struct te_tlv_header *tlvh = &lp->rsc_clsclr.header; - if (ntohs (tlvh->type) != 0) + if ((tlvh != NULL) && (ntohs (tlvh->type) != 0)) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); @@ -819,15 +1160,27 @@ build_link_tlv (struct stream *s, struct mpls_te_link *lp) set_linkparams_link_header (lp); build_tlv_header (s, &lp->link_header.header); - build_link_subtlv_link_type (s, lp); - build_link_subtlv_link_id (s, lp); - build_link_subtlv_lclif_ipaddr (s, lp); - build_link_subtlv_rmtif_ipaddr (s, lp); - build_link_subtlv_te_metric (s, lp); - build_link_subtlv_max_bw (s, lp); - build_link_subtlv_max_rsv_bw (s, lp); - build_link_subtlv_unrsv_bw (s, lp); - build_link_subtlv_rsc_clsclr (s, lp); + build_link_subtlv (s, &lp->link_type.header); + build_link_subtlv (s, &lp->link_id.header); + build_link_subtlv (s, &lp->lclif_ipaddr.header); + build_link_subtlv (s, &lp->rmtif_ipaddr.header); + build_link_subtlv (s, &lp->te_metric.header); + build_link_subtlv (s, &lp->max_bw.header); + build_link_subtlv (s, &lp->max_rsv_bw.header); + build_link_subtlv (s, &lp->unrsv_bw.header); + build_link_subtlv (s, &lp->rsc_clsclr.header); + build_link_subtlv (s, &lp->lrrid.header); + build_link_subtlv (s, &lp->llri.header); + build_link_subtlv (s, &lp->rip.header); + build_link_subtlv (s, &lp->ras.header); + build_link_subtlv (s, &lp->av_delay.header); + build_link_subtlv (s, &lp->mm_delay.header); + build_link_subtlv (s, &lp->delay_var.header); + build_link_subtlv (s, &lp->pkt_loss.header); + build_link_subtlv (s, &lp->res_bw.header); + build_link_subtlv (s, &lp->ava_bw.header); + build_link_subtlv (s, &lp->res_bw.header); + return; } @@ -856,7 +1209,7 @@ ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp) struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new = NULL; - u_char options, lsa_type; + u_char options, lsa_type = 0; struct in_addr lsa_id; u_int32_t tmp; u_int16_t length; @@ -869,19 +1222,42 @@ ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp) } lsah = (struct lsa_header *) STREAM_DATA (s); - options = LSA_OPTIONS_GET (area); - options |= LSA_OPTIONS_NSSA_GET (area); - options |= OSPF_OPTION_O; /* Don't forget this :-) */ + options = OSPF_OPTION_O; /* Don't forget this :-) */ - lsa_type = OSPF_OPAQUE_AREA_LSA; - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); - lsa_id.s_addr = htonl (tmp); + /* Set opaque-LSA header fields depending of the type of RFC */ + if (IS_INTER_AS (lp->type)) + { + if IS_FLOOD_AS (lp->type) + { + options |= OSPF_OPTION_E; /* Enable AS external as we flood Inter-AS with Opaque Type 11 */ + lsa_type = OSPF_OPAQUE_AS_LSA; + } + else + { + options |= LSA_OPTIONS_GET (area); /* Get area default option */ + options |= LSA_OPTIONS_NSSA_GET (area); + lsa_type = OSPF_OPAQUE_AREA_LSA; + } + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); + lsa_id.s_addr = htonl (tmp); + + struct ospf *top = ospf_lookup (); + + lsa_header_set (s, options, lsa_type, lsa_id, top->router_id); + } + else + { + options |= LSA_OPTIONS_GET (area); /* Get area default option */ + options |= LSA_OPTIONS_NSSA_GET (area); + lsa_type = OSPF_OPAQUE_AREA_LSA; + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); + lsa_id.s_addr = htonl (tmp); + lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id); + } if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id)); - - /* Set opaque-LSA header fields. */ - lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id); + zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", + lsa_type, inet_ntoa (lsa_id)); /* Set opaque-LSA body fields. */ ospf_mpls_te_lsa_body_set (s, lp); @@ -936,9 +1312,8 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp) goto out; } - /* Now this linkparameter entry has associated LSA. */ - lp->flags |= LPFLG_LSA_ENGAGED; - + /* Now this link-parameter entry has associated LSA. */ + SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); /* Update new LSA origination count. */ area->ospf->lsa_originate_count++; @@ -949,7 +1324,8 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp) { char area_id[INET_ADDRSTRLEN]; strcpy (area_id, inet_ntoa (area->area_id)); - zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name); + zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", + new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name); ospf_lsa_header_dump (new->data); } @@ -959,7 +1335,7 @@ out: } static int -ospf_mpls_te_lsa_originate (void *arg) +ospf_mpls_te_lsa_originate_area (void *arg) { struct ospf_area *area = (struct ospf_area *) arg; struct listnode *node, *nnode; @@ -968,34 +1344,44 @@ ospf_mpls_te_lsa_originate (void *arg) if (OspfMplsTE.status == disabled) { - zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now."); + zlog_info ("ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now."); rc = 0; /* This is not an error case. */ goto out; } for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) { + /* Process only enabled LSA with area scope flooding */ + if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || IS_FLOOD_AS (lp->type)) + continue; + if (lp->area == NULL) continue; + if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id)) continue; - if (lp->flags & LPFLG_LSA_ENGAGED) + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) { - if (lp->flags & LPFLG_LSA_FORCED_REFRESH) + if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH) { - lp->flags &= ~LPFLG_LSA_FORCED_REFRESH; + UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); + zlog_warn ("OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate"); ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); } continue; } if (! is_mandated_params_set (lp)) { - zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?"); + zlog_warn ("ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.", + lp->ifp ? lp->ifp->name : "?"); continue; } /* Ok, let's try to originate an LSA for this area and Link. */ + if (IS_DEBUG_OSPF_TE) + zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s", + lp->instance, inet_ntoa (area->area_id), lp->ifp ? lp->ifp->name : "?"); if (ospf_mpls_te_lsa_originate1 (area, lp) != 0) goto out; } @@ -1005,11 +1391,112 @@ out: return rc; } +static int +ospf_mpls_te_lsa_originate2 (struct ospf *top, struct mpls_te_link *lp) +{ + struct ospf_lsa *new; + int rc = -1; + + /* Create new Opaque-LSA/Inter-AS instance. */ + if ((new = ospf_mpls_te_lsa_new (NULL, lp)) == NULL) + { + zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?"); + goto out; + } + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) + { + zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?"); + ospf_lsa_unlock (&new); + goto out; + } + + /* Now this Router Info parameter entry has associated LSA. */ + SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AS. */ + ospf_flood_through_as (top, NULL /*nbr */ , new); + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + + rc = 0; +out:return rc; +} + +static int +ospf_mpls_te_lsa_originate_as (void *arg) +{ + struct ospf *top; + struct ospf_area *area; + struct listnode *node, *nnode; + struct mpls_te_link *lp; + int rc = -1; + + if ((OspfMplsTE.status == disabled) || (OspfMplsTE.inter_as == Disable)) + { + zlog_info + ("ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) + { + /* Process only enabled INTER_AS Links or Pseudo-Links */ + if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || !IS_INTER_AS (lp->type)) + continue; + + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) + { + if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH) + { + UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); + ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); + } + continue; + } + if (!is_mandated_params_set (lp)) + { + zlog_warn ("ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.", + lp->ifp ? lp->ifp->name : "?"); + continue; + } + + /* Ok, let's try to originate an LSA for this AS and Link. */ + if (IS_DEBUG_OSPF_TE) + zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s", + lp->instance, IS_FLOOD_AS (lp->type) ? "AS" : "Area", lp->ifp ? lp->ifp->name : "Unknown"); + + if (IS_FLOOD_AS (lp->type)) + { + top = (struct ospf *) arg; + rc = ospf_mpls_te_lsa_originate2 (top, lp); + } + else + { + area = (struct ospf_area *) arg; + rc = ospf_mpls_te_lsa_originate1 (area, lp); + } + } + + rc = 0; +out:return rc; +} + static struct ospf_lsa * ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa) { struct mpls_te_link *lp; struct ospf_area *area = lsa->area; + struct ospf *top; struct ospf_lsa *new = NULL; if (OspfMplsTE.status == disabled) @@ -1029,11 +1516,18 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa) lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ } + /* Check if lp was not disable in the interval */ + if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE)) + { + zlog_warn ("ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!"); + lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + /* If the lsa's age reached to MaxAge, start flushing procedure. */ if (IS_LSA_MAXAGE (lsa)) { if (lp) - lp->flags &= ~LPFLG_LSA_ENGAGED; + UNSET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); ospf_opaque_lsa_flush_schedule (lsa); goto out; } @@ -1048,15 +1542,24 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa) /* Install this LSA into LSDB. */ /* Given "lsa" will be freed in the next function. */ - if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) + /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use ospf_lookup() to get ospf instance */ + if (area) + top = area->ospf; + else + top = ospf_lookup (); + + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); ospf_lsa_unlock (&new); goto out; } - /* Flood updated LSA through area. */ - ospf_flood_through_area (area, NULL/*nbr*/, new); + /* Flood updated LSA through AS or Area depending of the RFC of the link */ + if (IS_FLOOD_AS (lp->type)) + ospf_flood_through_as (top, NULL, new); + else + ospf_flood_through_area (area, NULL/*nbr*/, new); /* Debug logging. */ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) @@ -1070,34 +1573,80 @@ out: return new; } -static void -ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, - enum sched_opcode opcode) +void +ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode) { struct ospf_lsa lsa; struct lsa_header lsah; + struct ospf *top; u_int32_t tmp; memset (&lsa, 0, sizeof (lsa)); memset (&lsah, 0, sizeof (lsah)); + top = ospf_lookup (); + + /* Check if the pseudo link is ready to flood */ + if (!(CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE)) + || !(IS_FLOOD_AREA (lp->type) || IS_FLOOD_AS (lp->type))) { + return; + } lsa.area = lp->area; lsa.data = &lsah; - lsah.type = OSPF_OPAQUE_AREA_LSA; - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); - lsah.id.s_addr = htonl (tmp); + if (IS_FLOOD_AS (lp->type)) + { + lsah.type = OSPF_OPAQUE_AS_LSA; + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); + lsah.id.s_addr = htonl (tmp); + } + else + { + lsah.type = OSPF_OPAQUE_AREA_LSA; + if (IS_INTER_AS (lp->type)) + { + /* Set the area context if not know */ + if (lp->area == NULL) + lp->area = ospf_area_lookup_by_area_id (top, OspfMplsTE.interas_areaid); + /* Unable to set the area context. Abort! */ + if (lp->area == NULL) + { + zlog_warn ("MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !"); + return; + } + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); + } + else + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); + lsah.id.s_addr = htonl (tmp); + } switch (opcode) { - case REORIGINATE_PER_AREA: - ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, - OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); + case REORIGINATE_THIS_LSA: + if (IS_FLOOD_AS (lp->type)) + { + ospf_opaque_lsa_reoriginate_schedule ((void *) top, OSPF_OPAQUE_AS_LSA, + OPAQUE_TYPE_INTER_AS_LSA); + break; + } + + if (IS_FLOOD_AREA (lp->type)) + { + if (IS_INTER_AS (lp->type)) + ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_INTER_AS_LSA); + else + ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); + break; + } break; case REFRESH_THIS_LSA: ospf_opaque_lsa_refresh_schedule (&lsa); break; case FLUSH_THIS_LSA: - lp->flags &= ~LPFLG_LSA_ENGAGED; + /* Reset Activity flag */ + lp->flags = LPFLG_LSA_INACTIVE; ospf_opaque_lsa_flush_schedule (&lsa); break; default: @@ -1108,6 +1657,7 @@ ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, return; } + /*------------------------------------------------------------------------* * Followings are vty session control functions. *------------------------------------------------------------------------*/ @@ -1118,7 +1668,8 @@ show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh) struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh; if (vty != NULL) - vty_out (vty, " Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE); + vty_out (vty, " Router-Address: %s%s", inet_ntoa (top->value), + VTY_NEWLINE); else zlog_debug (" Router-Address: %s", inet_ntoa (top->value)); @@ -1131,7 +1682,8 @@ show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh) struct te_tlv_link *top = (struct te_tlv_link *) tlvh; if (vty != NULL) - vty_out (vty, " Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE); + vty_out (vty, " Link: %u octets of data%s", ntohs (top->header.length), + VTY_NEWLINE); else zlog_debug (" Link: %u octets of data", ntohs (top->header.length)); @@ -1158,7 +1710,8 @@ show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh) } if (vty != NULL) - vty_out (vty, " Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE); + vty_out (vty, " Link-Type: %s (%u)%s", cp, top->link_type.value, + VTY_NEWLINE); else zlog_debug (" Link-Type: %s (%u)", cp, top->link_type.value); @@ -1180,7 +1733,8 @@ show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh) } static u_int16_t -show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh) +show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, + struct te_tlv_header *tlvh) { struct te_link_subtlv_lclif_ipaddr *top; int i, n; @@ -1196,7 +1750,8 @@ show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh) for (i = 0; i < n; i++) { if (vty != NULL) - vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE); + vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), + VTY_NEWLINE); else zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i])); } @@ -1204,7 +1759,8 @@ show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh) } static u_int16_t -show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh) +show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, + struct te_tlv_header *tlvh) { struct te_link_subtlv_rmtif_ipaddr *top; int i, n; @@ -1219,7 +1775,8 @@ show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh) for (i = 0; i < n; i++) { if (vty != NULL) - vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE); + vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), + VTY_NEWLINE); else zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i])); } @@ -1233,9 +1790,11 @@ show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh) top = (struct te_link_subtlv_te_metric *) tlvh; if (vty != NULL) - vty_out (vty, " Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE); + vty_out (vty, " Traffic Engineering Metric: %u%s", + (u_int32_t) ntohl (top->value), VTY_NEWLINE); else - zlog_debug (" Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value)); + zlog_debug (" Traffic Engineering Metric: %u", + (u_int32_t) ntohl (top->value)); return TLV_SIZE (tlvh); } @@ -1247,7 +1806,7 @@ show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh) float fval; top = (struct te_link_subtlv_max_bw *) tlvh; - ntohf (&top->value, &fval); + fval = ntohf (top->value); if (vty != NULL) vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); @@ -1264,10 +1823,11 @@ show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh) float fval; top = (struct te_link_subtlv_max_rsv_bw *) tlvh; - ntohf (&top->value, &fval); + fval = ntohf (top->value); if (vty != NULL) - vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, + VTY_NEWLINE); else zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval); @@ -1278,17 +1838,25 @@ static u_int16_t show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh) { struct te_link_subtlv_unrsv_bw *top; - float fval; + float fval1, fval2; int i; top = (struct te_link_subtlv_unrsv_bw *) tlvh; - for (i = 0; i < 8; i++) + if (vty != NULL) + vty_out (vty, " Unreserved Bandwidth per Class Type in Byte/s:%s", VTY_NEWLINE); + else + zlog_debug (" Unreserved Bandwidth per Class Type in Byte/s:"); + for (i = 0; i < MAX_CLASS_TYPE; i+=2) { - ntohf (&top->value[i], &fval); + fval1 = ntohf (top->value[i]); + fval2 = ntohf (top->value[i+1]); + if (vty != NULL) - vty_out (vty, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE); + vty_out(vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s", + i, fval1, i+1, fval2, VTY_NEWLINE); else - zlog_debug (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval); + zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", + i, fval1, i+1, fval2); } return TLV_SIZE (tlvh); @@ -1301,9 +1869,230 @@ show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh) top = (struct te_link_subtlv_rsc_clsclr *) tlvh; if (vty != NULL) - vty_out (vty, " Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE); + vty_out (vty, " Resource class/color: 0x%x%s", + (u_int32_t) ntohl (top->value), VTY_NEWLINE); else - zlog_debug (" Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value)); + zlog_debug (" Resource Class/Color: 0x%x", + (u_int32_t) ntohl (top->value)); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_lrrid (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_lrrid *top; + + top = (struct te_link_subtlv_lrrid *) tlvh; + + if (vty != NULL) + { + vty_out (vty, " Local TE Router ID: %s%s", inet_ntoa (top->local), + VTY_NEWLINE); + vty_out (vty, " Remote TE Router ID: %s%s", inet_ntoa (top->remote), + VTY_NEWLINE); + } + else + { + zlog_debug (" Local TE Router ID: %s", inet_ntoa (top->local)); + zlog_debug (" Remote TE Router ID: %s", inet_ntoa (top->remote)); + } + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_llri (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_llri *top; + + top = (struct te_link_subtlv_llri *) tlvh; + + if (vty != NULL) + { + vty_out (vty, " Link Local ID: %d%s", (u_int32_t) ntohl (top->local), + VTY_NEWLINE); + vty_out (vty, " Link Remote ID: %d%s", (u_int32_t) ntohl (top->remote), + VTY_NEWLINE); + } + else + { + zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (top->local)); + zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (top->remote)); + } + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_rip (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_rip *top; + + top = (struct te_link_subtlv_rip *) tlvh; + + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s%s", + inet_ntoa (top->value), VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote ASBR IP address: %s", + inet_ntoa (top->value)); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_ras (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_ras *top; + + top = (struct te_link_subtlv_ras *) tlvh; + + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote AS number: %u%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (top->value)); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_av_delay (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_av_delay *top; + u_int32_t delay; + u_int32_t anomalous; + + top = (struct te_link_subtlv_av_delay *) tlvh; + delay = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; + anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Average Link Delay: %d (micro-sec)%s", + anomalous ? "Anomalous" : "Normal", delay, VTY_NEWLINE); + else + zlog_debug (" %s Average Link Delay: %d (micro-sec)", + anomalous ? "Anomalous" : "Normal", delay); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_mm_delay (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_mm_delay *top; + u_int32_t low, high; + u_int32_t anomalous; + + top = (struct te_link_subtlv_mm_delay *) tlvh; + low = (u_int32_t) ntohl (top->low) & TE_EXT_MASK; + anomalous = (u_int32_t) ntohl (top->low) & TE_EXT_ANORMAL; + high = (u_int32_t) ntohl (top->high); + + if (vty != NULL) + vty_out (vty, " %s Min/Max Link Delay: %d/%d (micro-sec)%s", + anomalous ? "Anomalous" : "Normal", low, high, VTY_NEWLINE); + else + zlog_debug (" %s Min/Max Link Delay: %d/%d (micro-sec)", + anomalous ? "Anomalous" : "Normal", low, high); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_delay_var (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_delay_var *top; + u_int32_t jitter; + + top = (struct te_link_subtlv_delay_var *) tlvh; + jitter = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; + + if (vty != NULL) + vty_out (vty, " Delay Variation: %d (micro-sec)%s", jitter, VTY_NEWLINE); + else + zlog_debug (" Delay Variation: %d (micro-sec)", jitter); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_pkt_loss (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_pkt_loss *top; + u_int32_t loss; + u_int32_t anomalous; + float fval; + + top = (struct te_link_subtlv_pkt_loss *) tlvh; + loss = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; + fval = (float) (loss * LOSS_PRECISION); + anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Link Loss: %g (%%)%s", anomalous ? "Anomalous" : "Normal", + fval, VTY_NEWLINE); + else + zlog_debug (" %s Link Loss: %g (%%)", anomalous ? "Anomalous" : "Normal", + fval); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_res_bw (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_res_bw *top; + float fval; + + top = (struct te_link_subtlv_res_bw *) tlvh; + fval = ntohf (top->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Residual Bandwidth: %g (Bytes/sec)%s", + fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Residual Bandwidth: %g (Bytes/sec)", + fval); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_ava_bw (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_ava_bw *top; + float fval; + + top = (struct te_link_subtlv_ava_bw *) tlvh; + fval = ntohf (top->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)%s", + fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)", + fval); + + return TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_link_subtlv_use_bw (struct vty *vty, struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_use_bw *top; + float fval; + + top = (struct te_link_subtlv_use_bw *) tlvh; + fval = ntohf (top->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Utilized Bandwidth: %g (Bytes/sec)%s", + fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Utilized Bandwidth: %g (Bytes/sec)", + fval); return TLV_SIZE (tlvh); } @@ -1312,9 +2101,11 @@ static u_int16_t show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh) { if (vty != NULL) - vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE); + vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s", + ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE); else - zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length)); + zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", + ntohs (tlvh->type), ntohs (tlvh->length)); return TLV_SIZE (tlvh); } @@ -1358,6 +2149,39 @@ ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0, case TE_LINK_SUBTLV_RSC_CLSCLR: sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh); break; + case TE_LINK_SUBTLV_LRRID: + sum += show_vty_link_subtlv_lrrid (vty, tlvh); + break; + case TE_LINK_SUBTLV_LLRI: + sum += show_vty_link_subtlv_llri (vty, tlvh); + break; + case TE_LINK_SUBTLV_RIP: + sum += show_vty_link_subtlv_rip (vty, tlvh); + break; + case TE_LINK_SUBTLV_RAS: + sum += show_vty_link_subtlv_ras (vty, tlvh); + break; + case TE_LINK_SUBTLV_AV_DELAY: + sum += show_vty_link_subtlv_av_delay (vty, tlvh); + break; + case TE_LINK_SUBTLV_MM_DELAY: + sum += show_vty_link_subtlv_mm_delay (vty, tlvh); + break; + case TE_LINK_SUBTLV_DELAY_VAR: + sum += show_vty_link_subtlv_delay_var (vty, tlvh); + break; + case TE_LINK_SUBTLV_PKT_LOSS: + sum += show_vty_link_subtlv_pkt_loss (vty, tlvh); + break; + case TE_LINK_SUBTLV_RES_BW: + sum += show_vty_link_subtlv_res_bw (vty, tlvh); + break; + case TE_LINK_SUBTLV_AVA_BW: + sum += show_vty_link_subtlv_ava_bw (vty, tlvh); + break; + case TE_LINK_SUBTLV_USE_BW: + sum += show_vty_link_subtlv_use_bw (vty, tlvh); + break; default: sum += show_vty_unknown_tlv (vty, tlvh); break; @@ -1411,49 +2235,20 @@ ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa) static void ospf_mpls_te_config_write_router (struct vty *vty) { + if (OspfMplsTE.status == enabled) { - vty_out (vty, " mpls-te%s", VTY_NEWLINE); + vty_out (vty, " mpls-te on%s", VTY_NEWLINE); vty_out (vty, " mpls-te router-address %s%s", inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE); } - return; -} -static void -ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp) -{ - struct mpls_te_link *lp; + if (OspfMplsTE.inter_as == AS) + vty_out (vty, " mpls-te inter-as as%s", VTY_NEWLINE); + if (OspfMplsTE.inter_as == Area) + vty_out (vty, " mpls-te inter-as area %s %s", + inet_ntoa (OspfMplsTE.interas_areaid), VTY_NEWLINE); - if ((OspfMplsTE.status == enabled) - && (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0) - && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)) - { - float fval; - int i; - - vty_out (vty, " mpls-te link metric %u%s", - (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE); - - ntohf (&lp->max_bw.value, &fval); - if (fval >= MPLS_TE_MINIMUM_BANDWIDTH) - vty_out (vty, " mpls-te link max-bw %g%s", fval, VTY_NEWLINE); - - ntohf (&lp->max_rsv_bw.value, &fval); - if (fval >= MPLS_TE_MINIMUM_BANDWIDTH) - vty_out (vty, " mpls-te link max-rsv-bw %g%s", fval, VTY_NEWLINE); - - for (i = 0; i < 8; i++) - { - ntohf (&lp->unrsv_bw.value[i], &fval); - if (fval >= MPLS_TE_MINIMUM_BANDWIDTH) - vty_out (vty, " mpls-te link unrsv-bw %d %g%s", - i, fval, VTY_NEWLINE); - } - - vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s", - (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE); - } return; } @@ -1461,13 +2256,13 @@ ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp) * Followings are vty command functions. *------------------------------------------------------------------------*/ -DEFUN (mpls_te, - mpls_te_cmd, - "mpls-te", - "Configure MPLS-TE parameters\n" +DEFUN (ospf_mpls_te_on, + ospf_mpls_te_on_cmd, + "mpls-te on", + MPLS_TE_STR "Enable the MPLS-TE functionality\n") { - struct listnode *node, *nnode; + struct listnode *node; struct mpls_te_link *lp; struct ospf *ospf = vty->index; @@ -1482,31 +2277,28 @@ DEFUN (mpls_te, OspfMplsTE.status = enabled; - /* - * Following code is intended to handle two cases; - * - * 1) MPLS-TE was disabled at startup time, but now become enabled. - * 2) MPLS-TE was once enabled then disabled, and now enabled again. - */ - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - initialize_linkparams (lp); + /* Reoriginate RFC3630 & RFC6827 Links */ + ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA); - ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA); + /* Reoriginate LSA if INTER-AS is always on */ + if (OspfMplsTE.inter_as != Disable) + { + for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) + { + if (IS_INTER_AS (lp->type)) + { + ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); + } + } + } return CMD_SUCCESS; } -ALIAS (mpls_te, - mpls_te_on_cmd, - "mpls-te on", - "Configure MPLS-TE parameters\n" - "Enable the MPLS-TE functionality\n") - -DEFUN (no_mpls_te, - no_mpls_te_cmd, +DEFUN (no_ospf_mpls_te, + no_ospf_mpls_te_cmd, "no mpls-te", NO_STR - "Configure MPLS-TE parameters\n" "Disable the MPLS-TE functionality\n") { struct listnode *node, *nnode; @@ -1525,24 +2317,23 @@ DEFUN (no_mpls_te, OspfMplsTE.status = disabled; for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - if (lp->area != NULL) - if (lp->flags & LPFLG_LSA_ENGAGED) + if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); return CMD_SUCCESS; } -ALIAS (no_mpls_te, - no_mpls_te_val_cmd, +ALIAS (no_ospf_mpls_te, + no_ospf_mpls_te_val_cmd, "no mpls-te on", NO_STR - "Configure MPLS-TE parameters\n" + MPLS_TE_STR "Disable the MPLS-TE functionality\n") -DEFUN (mpls_te_router_addr, - mpls_te_router_addr_cmd, +DEFUN (ospf_mpls_te_router_addr, + ospf_mpls_te_router_addr_cmd, "mpls-te router-address A.B.C.D", - "MPLS-TE specific commands\n" + MPLS_TE_STR "Stable IP address of the advertising router\n" "MPLS-TE router address in IPv4 address format\n") { @@ -1573,10 +2364,10 @@ DEFUN (mpls_te_router_addr, for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) { - if (lp->area == NULL) + if ((lp->area == NULL) || IS_FLOOD_AS (lp->type)) continue; - if ((lp->flags & LPFLG_LSA_ENGAGED) == 0) + if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) { need_to_reoriginate = 1; break; @@ -1585,247 +2376,152 @@ DEFUN (mpls_te_router_addr, for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) { - if (lp->area == NULL) + if ((lp->area == NULL) || IS_FLOOD_AS (lp->type)) continue; if (need_to_reoriginate) - lp->flags |= LPFLG_LSA_FORCED_REFRESH; + SET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); else ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); } if (need_to_reoriginate) - ospf_mpls_te_foreach_area ( - ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA); + ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA); } out: return CMD_SUCCESS; } -DEFUN (mpls_te_link_metric, - mpls_te_link_metric_cmd, - "mpls-te link metric <0-4294967295>", - "MPLS-TE specific commands\n" - "Configure MPLS-TE link parameters\n" - "Link metric for MPLS-TE purpose\n" - "Metric\n") +static int +set_inter_as_mode (struct vty *vty, const char *mode_name, + const char *area_id) { - struct interface *ifp = (struct interface *) vty->index; + enum inter_as_mode mode; + struct listnode *node; struct mpls_te_link *lp; - u_int32_t value; + int format; - if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL) + if (OspfMplsTE.status == enabled) { - vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE); - return CMD_WARNING; - } - value = strtoul (argv[0], NULL, 10); + /* Read and Check inter_as mode */ + if (strcmp (mode_name, "as") == 0) + mode = AS; + else if (strcmp (mode_name, "area") == 0) + { + mode = Area; + VTY_GET_OSPF_AREA_ID (OspfMplsTE.interas_areaid, format, area_id); + } + else + { + vty_out (vty, "Unknown mode. Please choose between as or area%s", + VTY_NEWLINE); + return CMD_WARNING; + } - if (ntohs (lp->te_metric.header.type) == 0 - || ntohl (lp->te_metric.value) != value) - { - set_linkparams_te_metric (lp, value); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("MPLS-TE: Inter-AS enable with %s flooding support", + mode2text[mode]); - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if (lp->flags & LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); - } + /* Register new callbacks regarding the flooding scope (AS or Area) */ + if (ospf_mpls_te_register (mode) < 0) + { + vty_out (vty, "Internal error: Unable to register Inter-AS functions%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Enable mode and re-originate LSA if needed */ + if ((OspfMplsTE.inter_as == Disable) && (mode != OspfMplsTE.inter_as)) + { + OspfMplsTE.inter_as = mode; + /* Re-originate all InterAS-TEv2 LSA */ + for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) + { + if (IS_INTER_AS (lp->type)) + { + if (mode == AS) + lp->type |= FLOOD_AS; + else + lp->type |= FLOOD_AREA; + ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); + } + } + } + else + { + vty_out (vty, "Please change Inter-AS support to disable first before going to mode %s%s", + mode2text[mode], VTY_NEWLINE); + return CMD_WARNING; + } } return CMD_SUCCESS; } -DEFUN (mpls_te_link_maxbw, - mpls_te_link_maxbw_cmd, - "mpls-te link max-bw BANDWIDTH", - "MPLS-TE specific commands\n" - "Configure MPLS-TE link parameters\n" - "Maximum bandwidth that can be used\n" - "Bytes/second (IEEE floating point format)\n") + +DEFUN (ospf_mpls_te_inter_as_as, + ospf_mpls_te_inter_as_cmd, + "mpls-te inter-as as", + MPLS_TE_STR + "Configure MPLS-TE Inter-AS support\n" + "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n") { - struct interface *ifp = (struct interface *) vty->index; + return set_inter_as_mode (vty, "as", ""); +} + +DEFUN (ospf_mpls_te_inter_as_area, + ospf_mpls_te_inter_as_area_cmd, + "mpls-te inter-as area (A.B.C.D|<0-4294967295>)", + MPLS_TE_STR + "Configure MPLS-TE Inter-AS support\n" + "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n" + "OSPF area ID in IP format\n" + "OSPF area ID as decimal value\n") +{ + return set_inter_as_mode (vty, "area", argv[0]); +} + +DEFUN (no_ospf_mpls_te_inter_as, + no_ospf_mpls_te_inter_as_cmd, + "no mpls-te inter-as", + NO_STR + MPLS_TE_STR + "Disable MPLS-TE Inter-AS support\n") +{ + + struct listnode *node, *nnode; struct mpls_te_link *lp; - float f1, f2; - if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL) + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("MPLS-TE: Inter-AS support OFF"); + + if ((OspfMplsTE.status == enabled) && (OspfMplsTE.inter_as != Disable)) { - vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE); - return CMD_WARNING; + OspfMplsTE.inter_as = Disable; + /* Flush all Inter-AS LSA */ + for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) + if (IS_INTER_AS (lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) + ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); } - ntohf (&lp->max_bw.value, &f1); - if (sscanf (argv[0], "%g", &f2) != 1) - { - vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE); - return CMD_WARNING; - } + /* Deregister the Callbacks for Inter-AS suport */ + ospf_mpls_te_unregister (); - if (ntohs (lp->max_bw.header.type) == 0 - || f1 != f2) - { - set_linkparams_max_bw (lp, &f2); - - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if (lp->flags & LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); - } - } return CMD_SUCCESS; } -DEFUN (mpls_te_link_max_rsv_bw, - mpls_te_link_max_rsv_bw_cmd, - "mpls-te link max-rsv-bw BANDWIDTH", - "MPLS-TE specific commands\n" - "Configure MPLS-TE link parameters\n" - "Maximum bandwidth that may be reserved\n" - "Bytes/second (IEEE floating point format)\n") -{ - struct interface *ifp = (struct interface *) vty->index; - struct mpls_te_link *lp; - float f1, f2; - - if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL) - { - vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE); - return CMD_WARNING; - } - - ntohf (&lp->max_rsv_bw.value, &f1); - if (sscanf (argv[0], "%g", &f2) != 1) - { - vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE); - return CMD_WARNING; - } - - if (ntohs (lp->max_rsv_bw.header.type) == 0 - || f1 != f2) - { - set_linkparams_max_rsv_bw (lp, &f2); - - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if (lp->flags & LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); - } - } - return CMD_SUCCESS; -} - -DEFUN (mpls_te_link_unrsv_bw, - mpls_te_link_unrsv_bw_cmd, - "mpls-te link unrsv-bw <0-7> BANDWIDTH", - "MPLS-TE specific commands\n" - "Configure MPLS-TE link parameters\n" - "Unreserved bandwidth at each priority level\n" - "Priority\n" - "Bytes/second (IEEE floating point format)\n") -{ - struct interface *ifp = (struct interface *) vty->index; - struct mpls_te_link *lp; - int priority; - float f1, f2; - - if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL) - { - vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE); - return CMD_WARNING; - } - - /* We don't have to consider about range check here. */ - if (sscanf (argv[0], "%d", &priority) != 1) - { - vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE); - return CMD_WARNING; - } - - ntohf (&lp->unrsv_bw.value [priority], &f1); - if (sscanf (argv[1], "%g", &f2) != 1) - { - vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE); - return CMD_WARNING; - } - - if (ntohs (lp->unrsv_bw.header.type) == 0 - || f1 != f2) - { - set_linkparams_unrsv_bw (lp, priority, &f2); - - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if (lp->flags & LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); - } - } - return CMD_SUCCESS; -} - -DEFUN (mpls_te_link_rsc_clsclr, - mpls_te_link_rsc_clsclr_cmd, - "mpls-te link rsc-clsclr BITPATTERN", - "MPLS-TE specific commands\n" - "Configure MPLS-TE link parameters\n" - "Administrative group membership\n" - "32-bit Hexadecimal value (ex. 0xa1)\n") -{ - struct interface *ifp = (struct interface *) vty->index; - struct mpls_te_link *lp; - unsigned long value; - - if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL) - { - vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (sscanf (argv[0], "0x%lx", &value) != 1) - { - vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE); - return CMD_WARNING; - } - - if (ntohs (lp->rsc_clsclr.header.type) == 0 - || ntohl (lp->rsc_clsclr.value) != value) - { - set_linkparams_rsc_clsclr (lp, value); - - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if (lp->flags & LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); - } - } - return CMD_SUCCESS; -} - -DEFUN (show_mpls_te_router, - show_mpls_te_router_cmd, - "show mpls-te router", +DEFUN (show_ip_ospf_mpls_te_router, + show_ip_ospf_mpls_te_router_cmd, + "show ip ospf mpls-te router", SHOW_STR + IP_STR + OSPF_STR "MPLS-TE information\n" - "Router information\n") + "MPLS-TE Router parameters\n") { if (OspfMplsTE.status == enabled) { - vty_out (vty, "--- MPLS-TE router parameters ---%s", - VTY_NEWLINE); + vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE); if (ntohs (OspfMplsTE.router_addr.header.type) != 0) show_vty_router_addr (vty, &OspfMplsTE.router_addr.header); @@ -1839,29 +2535,73 @@ static void show_mpls_te_link_sub (struct vty *vty, struct interface *ifp) { struct mpls_te_link *lp; - struct te_tlv_header *tlvh; if ((OspfMplsTE.status == enabled) - && (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0) - && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)) + && HAS_LINK_PARAMS(ifp) + && !if_is_loopback (ifp) + && if_is_up (ifp) + && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)) { + /* Continue only if interface is not passive or support Inter-AS TEv2 */ + if (!(ospf_oi_count (ifp) > 0)) + { + if (IS_INTER_AS (lp->type)) + { + vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --%s", + ifp->name, VTY_NEWLINE); + } + else + { + /* MPLS-TE is not activate on this interface */ + /* or this interface is passive and Inter-AS TEv2 is not activate */ + vty_out (vty, " %s: MPLS-TE is disabled on this interface%s", + ifp->name, VTY_NEWLINE); + return; + } + } + else + { vty_out (vty, "-- MPLS-TE link parameters for %s --%s", ifp->name, VTY_NEWLINE); + } - show_vty_link_subtlv_link_type (vty, &lp->link_type.header); - show_vty_link_subtlv_link_id (vty, &lp->link_id.header); - - if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL) - show_vty_link_subtlv_lclif_ipaddr (vty, tlvh); - if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL) - show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh); - - show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header); - - show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header); - show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header); - show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header); - show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header); + if (TLV_TYPE(lp->link_type) != 0) + show_vty_link_subtlv_link_type (vty, &lp->link_type.header); + if (TLV_TYPE(lp->link_id) != 0) + show_vty_link_subtlv_link_id (vty, &lp->link_id.header); + if (TLV_TYPE(lp->lclif_ipaddr) != 0) + show_vty_link_subtlv_lclif_ipaddr (vty, &lp->lclif_ipaddr.header); + if (TLV_TYPE(lp->rmtif_ipaddr) != 0) + show_vty_link_subtlv_rmtif_ipaddr (vty, &lp->rmtif_ipaddr.header); + if (TLV_TYPE(lp->rip) != 0) + show_vty_link_subtlv_rip (vty, &lp->rip.header); + if (TLV_TYPE(lp->ras) != 0) + show_vty_link_subtlv_ras (vty, &lp->ras.header); + if (TLV_TYPE(lp->te_metric) != 0) + show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header); + if (TLV_TYPE(lp->max_bw) != 0) + show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header); + if (TLV_TYPE(lp->max_rsv_bw) != 0) + show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header); + if (TLV_TYPE(lp->unrsv_bw) != 0) + show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header); + if (TLV_TYPE(lp->rsc_clsclr) != 0) + show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header); + if (TLV_TYPE(lp->av_delay) != 0) + show_vty_link_subtlv_av_delay (vty, &lp->av_delay.header); + if (TLV_TYPE(lp->mm_delay) != 0) + show_vty_link_subtlv_mm_delay (vty, &lp->mm_delay.header); + if (TLV_TYPE(lp->delay_var) != 0) + show_vty_link_subtlv_delay_var (vty, &lp->delay_var.header); + if (TLV_TYPE(lp->pkt_loss) != 0) + show_vty_link_subtlv_pkt_loss (vty, &lp->pkt_loss.header); + if (TLV_TYPE(lp->res_bw) != 0) + show_vty_link_subtlv_res_bw (vty, &lp->res_bw.header); + if (TLV_TYPE(lp->ava_bw) != 0) + show_vty_link_subtlv_ava_bw (vty, &lp->ava_bw.header); + if (TLV_TYPE(lp->use_bw) != 0) + show_vty_link_subtlv_use_bw (vty, &lp->use_bw.header); + vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE); } else { @@ -1872,10 +2612,12 @@ show_mpls_te_link_sub (struct vty *vty, struct interface *ifp) return; } -DEFUN (show_mpls_te_link, - show_mpls_te_link_cmd, - "show mpls-te interface [INTERFACE]", +DEFUN (show_ip_ospf_mpls_te_link, + show_ip_ospf_mpls_te_link_cmd, + "show ip ospf mpls-te interface [INTERFACE]", SHOW_STR + IP_STR + OSPF_STR "MPLS-TE information\n" "Interface information\n" "Interface name\n") @@ -1904,22 +2646,18 @@ DEFUN (show_mpls_te_link, static void ospf_mpls_te_register_vty (void) { - install_element (VIEW_NODE, &show_mpls_te_router_cmd); - install_element (VIEW_NODE, &show_mpls_te_link_cmd); - install_element (ENABLE_NODE, &show_mpls_te_router_cmd); - install_element (ENABLE_NODE, &show_mpls_te_link_cmd); + install_element (VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd); + install_element (VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_mpls_te_router_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_mpls_te_link_cmd); - install_element (OSPF_NODE, &mpls_te_cmd); - install_element (OSPF_NODE, &no_mpls_te_cmd); - install_element (OSPF_NODE, &no_mpls_te_val_cmd); - install_element (OSPF_NODE, &mpls_te_on_cmd); - install_element (OSPF_NODE, &mpls_te_router_addr_cmd); - - install_element (INTERFACE_NODE, &mpls_te_link_metric_cmd); - install_element (INTERFACE_NODE, &mpls_te_link_maxbw_cmd); - install_element (INTERFACE_NODE, &mpls_te_link_max_rsv_bw_cmd); - install_element (INTERFACE_NODE, &mpls_te_link_unrsv_bw_cmd); - install_element (INTERFACE_NODE, &mpls_te_link_rsc_clsclr_cmd); + install_element (OSPF_NODE, &ospf_mpls_te_on_cmd); + install_element (OSPF_NODE, &no_ospf_mpls_te_cmd); + install_element (OSPF_NODE, &no_ospf_mpls_te_val_cmd); + install_element (OSPF_NODE, &ospf_mpls_te_router_addr_cmd); + install_element (OSPF_NODE, &ospf_mpls_te_inter_as_cmd); + install_element (OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd); + install_element (OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd); return; } diff --git a/ospfd/ospf_te.h b/ospfd/ospf_te.h index 863d8ba8f2..8bb77c40c5 100644 --- a/ospfd/ospf_te.h +++ b/ospfd/ospf_te.h @@ -1,8 +1,11 @@ /* - * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt + * This is an implementation of RFC3630, RFC5392 & RFC6827 * Copyright (C) 2001 KDD R&D Laboratories, Inc. * http://www.kddlabs.co.jp/ * + * Copyright (C) 2012 Orange Labs + * http://www.orange.com + * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it @@ -21,6 +24,10 @@ * 02111-1307, USA. */ +/* Add support of RFC7471 */ +/* Add support of RFC5392 */ +/* Add support of RFC6827 (partial) */ + #ifndef _ZEBRA_OSPF_MPLS_TE_H #define _ZEBRA_OSPF_MPLS_TE_H @@ -42,6 +49,7 @@ */ #define MAX_LEGAL_TE_INSTANCE_NUM (0xffff) +#define LEGAL_TE_INSTANCE_RANGE(i) (0 <= (i) && (i) <= 0xffff) /* * 24 16 8 0 @@ -62,6 +70,31 @@ * +--------+--------+--------+--------+ --- */ +/* Following define the type of TE link regarding the various RFC */ +#define STD_TE 0x01 +#define GMPLS 0x02 +#define INTER_AS 0x04 +#define PSEUDO_TE 0x08 +#define FLOOD_AREA 0x10 +#define FLOOD_AS 0x20 +#define EMULATED 0x80 + +#define IS_STD_TE(x) (x & STD_TE) +#define IS_PSEUDO_TE(x) (x & PSEUDO_TE) +#define IS_INTER_AS(x) (x & INTER_AS) +#define IS_EMULATED(x) (x & EMULATED) +#define IS_FLOOD_AREA(x) (x & FLOOD_AREA) +#define IS_FLOOD_AS(x) (x & FLOOD_AS) +#define IS_INTER_AS_EMU(x) (x & INTER_AS & EMULATED) +#define IS_INTER_AS_AS(x) (x & INTER_AS & FLOOD_AS) + +/* Flags to manage TE Link LSA */ +#define LPFLG_LSA_INACTIVE 0x0 +#define LPFLG_LSA_ACTIVE 0x1 +#define LPFLG_LSA_ENGAGED 0x2 +#define LPFLG_LOOKUP_DONE 0x4 +#define LPFLG_LSA_FORCED_REFRESH 0x8 + /* * Following section defines TLV (tag, length, value) structures, * used for Traffic Engineering. @@ -87,10 +120,18 @@ struct te_tlv_header #define TLV_HDR_NEXT(tlvh) \ (struct te_tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh)) +#define TLV_HDR_SUBTLV(tlvh) \ + (struct te_tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE) + +#define TLV_TYPE(tlvh) tlvh.header.type +#define TLV_LEN(tlvh) tlvh.header.length +#define TLV_HDR(tlvh) tlvh.header + + /* * Following section defines TLV body parts. */ -/* Router Address TLV *//* Mandatory */ +/* Router Address TLV */ /* Mandatory */ #define TE_TLV_ROUTER_ADDR 1 struct te_tlv_router_addr { @@ -106,12 +147,16 @@ struct te_tlv_link /* A set of link-sub-TLVs will follow. */ }; -/* Link Type Sub-TLV *//* Mandatory */ -#define TE_LINK_SUBTLV_LINK_TYPE 1 +#define TE_LINK_SUBTLV_DEF_SIZE 4 + +/* Link Type Sub-TLV */ /* Mandatory */ +#define TE_LINK_SUBTLV_LINK_TYPE 1 +#define TE_LINK_SUBTLV_TYPE_SIZE 1 struct te_link_subtlv_link_type { struct te_tlv_header header; /* Value length is 1 octet. */ - struct { + struct + { #define LINK_TYPE_SUBTLV_VALUE_PTP 1 #define LINK_TYPE_SUBTLV_VALUE_MA 2 u_char value; @@ -119,75 +164,303 @@ struct te_link_subtlv_link_type } link_type; }; -/* Link Sub-TLV: Link ID *//* Mandatory */ -#define TE_LINK_SUBTLV_LINK_ID 2 +/* Link Sub-TLV: Link ID */ /* Mandatory */ +#define TE_LINK_SUBTLV_LINK_ID 2 struct te_link_subtlv_link_id { struct te_tlv_header header; /* Value length is 4 octets. */ struct in_addr value; /* Same as router-lsa's link-id. */ }; -/* Link Sub-TLV: Local Interface IP Address *//* Optional */ -#define TE_LINK_SUBTLV_LCLIF_IPADDR 3 +/* Link Sub-TLV: Local Interface IP Address */ /* Optional */ +#define TE_LINK_SUBTLV_LCLIF_IPADDR 3 struct te_link_subtlv_lclif_ipaddr { struct te_tlv_header header; /* Value length is 4 x N octets. */ struct in_addr value[1]; /* Local IP address(es). */ }; -/* Link Sub-TLV: Remote Interface IP Address *//* Optional */ -#define TE_LINK_SUBTLV_RMTIF_IPADDR 4 +/* Link Sub-TLV: Remote Interface IP Address */ /* Optional */ +#define TE_LINK_SUBTLV_RMTIF_IPADDR 4 struct te_link_subtlv_rmtif_ipaddr { struct te_tlv_header header; /* Value length is 4 x N octets. */ struct in_addr value[1]; /* Neighbor's IP address(es). */ }; -/* Link Sub-TLV: Traffic Engineering Metric *//* Optional */ -#define TE_LINK_SUBTLV_TE_METRIC 5 +/* Link Sub-TLV: Traffic Engineering Metric */ /* Optional */ +#define TE_LINK_SUBTLV_TE_METRIC 5 struct te_link_subtlv_te_metric { struct te_tlv_header header; /* Value length is 4 octets. */ u_int32_t value; /* Link metric for TE purpose. */ }; -/* Link Sub-TLV: Maximum Bandwidth *//* Optional */ -#define TE_LINK_SUBTLV_MAX_BW 6 +/* Link Sub-TLV: Maximum Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_MAX_BW 6 struct te_link_subtlv_max_bw { struct te_tlv_header header; /* Value length is 4 octets. */ float value; /* bytes/sec */ }; -/* Link Sub-TLV: Maximum Reservable Bandwidth *//* Optional */ -#define TE_LINK_SUBTLV_MAX_RSV_BW 7 +/* Link Sub-TLV: Maximum Reservable Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_MAX_RSV_BW 7 struct te_link_subtlv_max_rsv_bw { struct te_tlv_header header; /* Value length is 4 octets. */ float value; /* bytes/sec */ }; -/* Link Sub-TLV: Unreserved Bandwidth *//* Optional */ -#define TE_LINK_SUBTLV_UNRSV_BW 8 +/* Link Sub-TLV: Unreserved Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_UNRSV_BW 8 +#define TE_LINK_SUBTLV_UNRSV_SIZE 32 struct te_link_subtlv_unrsv_bw { struct te_tlv_header header; /* Value length is 32 octets. */ - float value[8]; /* One for each priority level. */ + float value[MAX_CLASS_TYPE]; /* One for each priority level. */ }; -/* Link Sub-TLV: Resource Class/Color *//* Optional */ -#define TE_LINK_SUBTLV_RSC_CLSCLR 9 +/* Link Sub-TLV: Resource Class/Color */ /* Optional */ +#define TE_LINK_SUBTLV_RSC_CLSCLR 9 struct te_link_subtlv_rsc_clsclr { struct te_tlv_header header; /* Value length is 4 octets. */ u_int32_t value; /* Admin. group membership. */ }; -/* Here are "non-official" architechtual constants. */ +/* For RFC6827 */ +/* Local and Remote TE Router ID */ +#define TE_LINK_SUBTLV_LRRID 10 +#define TE_LINK_SUBTLV_LRRID_SIZE 8 +struct te_link_subtlv_lrrid +{ + struct te_tlv_header header; /* Value length is 8 octets. */ + struct in_addr local; /* Local TE Router Identifier */ + struct in_addr remote; /* Remote TE Router Identifier */ +}; + +/* RFC4203: Link Local/Remote Identifiers */ +#define TE_LINK_SUBTLV_LLRI 11 +#define TE_LINK_SUBTLV_LLRI_SIZE 8 +struct te_link_subtlv_llri +{ + struct te_tlv_header header; /* Value length is 8 octets. */ + u_int32_t local; /* Link Local Identifier */ + u_int32_t remote; /* Link Remote Identifier */ +}; + +/* Inter-RA Export Upward sub-TLV (12) and Inter-RA Export Downward sub-TLV (13) (RFC6827bis) are not yet supported */ +/* SUBTLV 14-16 (RFC4203) are not yet supported */ +/* Bandwidth Constraints sub-TLV (17) (RFC4124) is not yet supported */ +/* SUBLV 18-20 are for OSPFv6 TE (RFC5329). see ospf6d */ + +/* For RFC 5392 */ +/* Remote AS Number sub-TLV */ +#define TE_LINK_SUBTLV_RAS 21 +struct te_link_subtlv_ras +{ + struct te_tlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Remote AS number */ +}; + +/* IPv4 Remote ASBR ID Sub-TLV */ +#define TE_LINK_SUBTLV_RIP 22 +struct te_link_subtlv_rip +{ + struct te_tlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Remote ASBR IP address */ +}; + +/* SUBTLV 24 is IPv6 Remote ASBR ID (RFC5392). see ospf6d */ + +/* SUBTLV 23 (RFC5330) and 25 (RFC6001) are not yet supported */ + +/* SUBTLV 26 (RFC7308) is not yet supported */ + +/* RFC7471 */ +/* Link Sub-TLV: Average Link Delay */ /* Optional */ +#define TE_LINK_SUBTLV_AV_DELAY 27 +struct te_link_subtlv_av_delay +{ + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit as Upper most bit */ +}; + +/* Link Sub-TLV: Low/High Link Delay */ +#define TE_LINK_SUBTLV_MM_DELAY 28 +#define TE_LINK_SUBTLV_MM_DELAY_SIZE 8 +struct te_link_subtlv_mm_delay +{ + struct te_tlv_header header; /* Value length is 8 bytes. */ + u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit (A) as Upper most bit */ + u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */ +}; + +/* Link Sub-TLV: Link Delay Variation i.e. Jitter */ +#define TE_LINK_SUBTLV_DELAY_VAR 29 +struct te_link_subtlv_delay_var +{ + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... 16777215 */ +}; + +/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */ +#define TE_LINK_SUBTLV_PKT_LOSS 30 +struct te_link_subtlv_pkt_loss +{ + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* in percentage of total traffic only 24 bits (2^24 - 2) + with Anomalous Bit as Upper most bit */ +}; + +/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_RES_BW 31 +struct te_link_subtlv_res_bw +{ + struct te_tlv_header header; /* Value length is 4 bytes. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +}; + +/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_AVA_BW 32 +struct te_link_subtlv_ava_bw +{ + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +}; + +/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */ +#define TE_LINK_SUBTLV_USE_BW 33 +struct te_link_subtlv_use_bw +{ + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +}; + +#define TE_LINK_SUBTLV_MAX 34 /* Last SUBTLV + 1 */ + +/* Here are "non-official" architectural constants. */ #define MPLS_TE_MINIMUM_BANDWIDTH 1.0 /* Reasonable? *//* XXX */ +/* Following declaration concerns the MPLS-TE and LINk-TE management */ +typedef enum _opcode_t +{ REORIGINATE_THIS_LSA, REFRESH_THIS_LSA, FLUSH_THIS_LSA } opcode_t; + +typedef enum _status_t +{ disabled, enabled } status_t; + +/* Mode for Inter-AS Opaque-LSA */ +enum inter_as_mode { Disable, AS, Area }; + +struct te_link_subtlv +{ + struct te_tlv_header header; + union + { + u_int32_t link_type; + struct in_addr link_id; + struct in_addr lclif; + struct in_addr rmtif; + u_int32_t te_metric; + float max_bw; + float max_rsv_bw; + float unrsv[8]; + u_int32_t rsc_clsclr; + u_int32_t llri[2]; + u_int32_t ras; + struct in_addr rip; + struct in_addr lrrid[2]; + u_int32_t av_delay; + u_int32_t mm_delay; + u_int32_t delay_var; + u_int32_t pkt_loss; + float res_bw; + float ava_bw; + float use_bw; + } value; +}; + +/* Following structure are internal use only. */ +struct ospf_mpls_te +{ + /* Status of MPLS-TE: enable or disbale */ + status_t status; + + /* RFC5392 */ + enum inter_as_mode inter_as; + struct in_addr interas_areaid; + + /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */ + struct list *iflist; + + /* Store Router-TLV in network byte order. */ + struct te_tlv_router_addr router_addr; +}; + +struct mpls_te_link +{ + /* + * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field + * is subdivided into 8-bit "unused" field and 16-bit "instance" field. + * In this implementation, each Link-TLV has its own instance. + */ + u_int32_t instance; + + /* Reference pointer to a Zebra-interface. */ + struct interface *ifp; + + /* Area info in which this MPLS-TE link belongs to. */ + struct ospf_area *area; + + /* Flags to manage this link parameters. */ + u_int32_t flags; + + /* Type of MPLS-TE link: RFC3630, RFC5392, RFC5392 emulated, RFC6827 */ + u_int8_t type; + + /* Store Link-TLV in network byte order. */ + /* RFC3630 & RFC6827 / RFC 6827 */ + struct te_tlv_link link_header; + struct te_link_subtlv_link_type link_type; + struct te_link_subtlv_link_id link_id; + struct te_link_subtlv_lclif_ipaddr lclif_ipaddr; + struct te_link_subtlv_rmtif_ipaddr rmtif_ipaddr; + struct te_link_subtlv_te_metric te_metric; + struct te_link_subtlv_max_bw max_bw; + struct te_link_subtlv_max_rsv_bw max_rsv_bw; + struct te_link_subtlv_unrsv_bw unrsv_bw; + struct te_link_subtlv_rsc_clsclr rsc_clsclr; + /* RFC4203 */ + struct te_link_subtlv_llri llri; + /* RFC5392 */ + struct te_link_subtlv_ras ras; + struct te_link_subtlv_rip rip; + /* RFC6827 */ + struct te_link_subtlv_lrrid lrrid; + /* RFC7471 */ + struct te_link_subtlv_av_delay av_delay; + struct te_link_subtlv_mm_delay mm_delay; + struct te_link_subtlv_delay_var delay_var; + struct te_link_subtlv_pkt_loss pkt_loss; + struct te_link_subtlv_res_bw res_bw; + struct te_link_subtlv_ava_bw ava_bw; + struct te_link_subtlv_use_bw use_bw; + + struct in_addr adv_router; + struct in_addr id; +}; + /* Prototypes. */ extern int ospf_mpls_te_init (void); extern void ospf_mpls_te_term (void); +extern struct ospf_mpls_te *get_ospf_mpls_te (void); +extern void ospf_mpls_te_update_if (struct interface *); +extern void ospf_mpls_te_lsa_schedule (struct mpls_te_link *, opcode_t); +extern u_int32_t get_mpls_te_instance_value (void); +extern void set_linkparams_llri (struct mpls_te_link *, u_int32_t, u_int32_t); +extern void set_linkparams_lrrid (struct mpls_te_link *, struct in_addr, struct in_addr); #endif /* _ZEBRA_OSPF_MPLS_TE_H */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3022a316c6..264249b4c0 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -64,7 +64,7 @@ static const char *ospf_network_type_str[] = }; /* Utility functions. */ -static int +int ospf_str2area_id (const char *str, struct in_addr *area_id, int *format) { char *endptr = NULL; diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h index 28bb419af8..429ac318f7 100644 --- a/ospfd/ospf_vty.h +++ b/ospfd/ospf_vty.h @@ -54,5 +54,6 @@ extern void ospf_vty_init (void); extern void ospf_vty_show_init (void); extern void ospf_vty_clear_init (void); +extern int ospf_str2area_id (const char *, struct in_addr *, int *); #endif /* _QUAGGA_OSPF_VTY_H */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index a31ef5f707..c0b94a3360 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -53,6 +53,7 @@ #ifdef HAVE_SNMP #include "ospfd/ospf_snmp.h" #endif /* HAVE_SNMP */ +#include "ospfd/ospf_te.h" /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -331,6 +332,24 @@ ospf_interface_address_delete (int command, struct zclient *zclient, return 0; } +static int +ospf_interface_link_params (int command, struct zclient *zclient, + zebra_size_t length) +{ + struct interface *ifp; + + ifp = zebra_interface_link_params_read (zclient->ibuf); + + if (ifp == NULL) + return 0; + + /* Update TE TLV */ + ospf_mpls_te_update_if (ifp); + + return 0; +} + + void ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) { @@ -1580,6 +1599,8 @@ ospf_zebra_init (struct thread_master *master, u_short instance) zclient->interface_down = ospf_interface_state_down; zclient->interface_address_add = ospf_interface_address_add; zclient->interface_address_delete = ospf_interface_address_delete; + zclient->interface_link_params = ospf_interface_link_params; + zclient->ipv4_route_add = ospf_zebra_read_ipv4; zclient->ipv4_route_delete = ospf_zebra_read_ipv4; zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 9d0e4b9e87..7156c1edac 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -305,7 +305,7 @@ ospf_lookup () if (listcount (om->ospf) == 0) return NULL; - return listgetdata (listhead (om->ospf)); + return listgetdata ((struct listnode *)listhead (om->ospf)); } struct ospf * diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 5f0a7bf113..af238c53ae 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -59,13 +59,14 @@ #define OSPF_AUTH_CMD_NOTSEEN -2 /* OSPF options. */ -#define OSPF_OPTION_T 0x01 /* TOS. */ +#define OSPF_OPTION_MT 0x01 /* M/T */ #define OSPF_OPTION_E 0x02 #define OSPF_OPTION_MC 0x04 #define OSPF_OPTION_NP 0x08 #define OSPF_OPTION_EA 0x10 #define OSPF_OPTION_DC 0x20 #define OSPF_OPTION_O 0x40 +#define OSPF_OPTION_DN 0x80 /* OSPF Database Description flags. */ #define OSPF_DD_FLAG_MS 0x01 diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index a7b78bd7b9..4ead722213 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -36,6 +36,7 @@ EOF $ignore{'"interface IFNAME"'} = "ignore"; $ignore{'"interface IFNAME " "vrf <0-65535>"'} = "ignore"; $ignore{'"interface IFNAME " "vrf NAME"'} = "ignore"; +$ignore{'"link-params"'} = "ignore"; $ignore{'"vrf NAME"'} = "ignore"; $ignore{'"ip vrf NAME"'} = "ignore"; $ignore{'"router rip"'} = "ignore"; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 7241455cd1..5cf27facb8 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1032,6 +1032,12 @@ static struct cmd_node keychain_key_node = "%s(config-keychain-key)# " }; +struct cmd_node link_params_node = +{ + LINK_PARAMS_NODE, + "%s(config-link-params)# ", +}; + /* Defined in lib/vty.c */ extern struct cmd_node vty_node; @@ -1414,6 +1420,9 @@ vtysh_exit (struct vty *vty) case KEYCHAIN_KEY_NODE: vty->node = KEYCHAIN_NODE; break; + case LINK_PARAMS_NODE: + vty->node = INTERFACE_NODE; + break; default: break; } @@ -1746,6 +1755,17 @@ DEFUN (vtysh_show_work_queues_daemon, return ret; } +DEFUNSH (VTYSH_ZEBRA, + vtysh_link_params, + vtysh_link_params_cmd, + "link-params", + LINK_PARAMS_STR + ) +{ + vty->node = LINK_PARAMS_NODE; + return CMD_SUCCESS; +} + /* Memory */ DEFUN (vtysh_show_memory, vtysh_show_memory_cmd, @@ -2843,6 +2863,7 @@ vtysh_init_vty (void) install_node (&bgp_node, NULL); install_node (&rip_node, NULL); install_node (&interface_node, NULL); + install_node (&link_params_node, NULL); install_node (&vrf_node, NULL); install_node (&rmap_node, NULL); install_node (&zebra_node, NULL); @@ -2872,6 +2893,7 @@ vtysh_init_vty (void) vtysh_install_default (BGP_NODE); vtysh_install_default (RIP_NODE); vtysh_install_default (INTERFACE_NODE); + vtysh_install_default (LINK_PARAMS_NODE); vtysh_install_default (VRF_NODE); vtysh_install_default (RMAP_NODE); vtysh_install_default (ZEBRA_NODE); @@ -2965,6 +2987,8 @@ vtysh_init_vty (void) install_element (INTERFACE_NODE, &no_interface_desc_cmd); install_element (INTERFACE_NODE, &vtysh_end_all_cmd); install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd); + install_element (LINK_PARAMS_NODE, &vtysh_end_all_cmd); + install_element (LINK_PARAMS_NODE, &vtysh_exit_interface_cmd); install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd); install_element (VRF_NODE, &vtysh_end_all_cmd); @@ -3015,6 +3039,7 @@ vtysh_init_vty (void) install_element (CONFIG_NODE, &vtysh_no_interface_cmd); install_element (CONFIG_NODE, &vtysh_interface_vrf_cmd); install_element (CONFIG_NODE, &vtysh_no_interface_vrf_cmd); + install_element (INTERFACE_NODE, &vtysh_link_params_cmd); install_element (ENABLE_NODE, &vtysh_show_running_config_cmd); install_element (ENABLE_NODE, &vtysh_show_running_config_daemon_cmd); install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd); diff --git a/zebra/interface.c b/zebra/interface.c index 36270ac425..2b1e6f4ac6 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -281,7 +281,7 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc) /* If deleted address is primary, mark subsequent one as such and distribute. */ if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) { - ifc = listgetdata (listhead (addr_list)); + ifc = listgetdata ((struct listnode *)listhead (addr_list)); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); /* XXX: Linux kernel removes all the secondary addresses when the primary @@ -1074,7 +1074,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) { if (! rn->info) continue; - + for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected)) connected_dump_vty (vty, connected); } @@ -1086,6 +1086,53 @@ if_dump_vty (struct vty *vty, struct interface *ifp) connected_dump_vty (vty, connected); } + if (HAS_LINK_PARAMS(ifp)) + { + int i; + struct if_link_params *iflp = ifp->link_params; + vty_out(vty, " Traffic Engineering Link Parameters:%s", VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_TE)) + vty_out(vty, " TE metric %u%s",iflp->te_metric, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_MAX_BW)) + vty_out(vty, " Maximum Bandwidth %g (Byte/s)%s", iflp->max_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + vty_out(vty, " Maximum Reservable Bandwidth %g (Byte/s)%s", iflp->max_rsv_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + vty_out(vty, " Unreserved Bandwidth per Class Type in Byte/s:%s", VTY_NEWLINE); + for (i = 0; i < MAX_CLASS_TYPE; i+=2) + vty_out(vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s", + i, iflp->unrsv_bw[i], i+1, iflp->unrsv_bw[i+1], VTY_NEWLINE); + } + + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " Administrative Group:%u%s", iflp->admin_grp, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_DELAY)) + { + vty_out(vty, " Link Delay Average: %u (micro-sec.)", iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) + { + vty_out(vty, " Min: %u (micro-sec.)", iflp->min_delay); + vty_out(vty, " Max: %u (micro-sec.)", iflp->max_delay); + } + vty_out(vty, "%s", VTY_NEWLINE); + } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, " Link Delay Variation %u (micro-sec.)%s", iflp->delay_var, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " Link Packet Loss %g (in %%)%s", iflp->pkt_loss, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " Available Bandwidth %g (Byte/s)%s", iflp->ava_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " Residual Bandwidth %g (Byte/s)%s", iflp->res_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " Utilized Bandwidth %g (Byte/s)%s", iflp->use_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " Neighbor ASBR IP: %s AS: %u %s", inet_ntoa(iflp->rmt_ip), iflp->rmt_as, VTY_NEWLINE); + } + + #ifdef RTADV + nd_dump_vty (vty, ifp); + #endif /* RTADV */ #if defined (HAVE_RTADV) nd_dump_vty (vty, ifp); #endif /* HAVE_RTADV */ @@ -1185,13 +1232,13 @@ DEFUN_NOSH (zebra_interface, "Interface's name\n") { int ret; - struct interface * ifp; + struct interface *ifp; /* Call lib interface() */ if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS) return ret; - ifp = vty->index; + ifp = vty->index; if (ifp->ifindex == IFINDEX_INTERNAL) /* Is this really necessary? Shouldn't status be initialized to 0 @@ -1690,6 +1737,692 @@ ALIAS (no_bandwidth_if, "Set bandwidth informational parameter\n" "Bandwidth in megabits\n") +struct cmd_node link_params_node = +{ + LINK_PARAMS_NODE, + "%s(config-link-params)# ", + 1, +}; + +static void +link_param_cmd_set_uint32 (struct interface *ifp, uint32_t *field, + uint32_t type, uint32_t value) +{ + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) + { + *field = value; + SET_PARAM(ifp->link_params, type); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + } +} +static void +link_param_cmd_set_float (struct interface *ifp, float *field, + uint32_t type, float value) +{ + + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) + { + *field = value; + SET_PARAM(ifp->link_params, type); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + } +} + +static void +link_param_cmd_unset (struct interface *ifp, uint32_t type) +{ + + /* Unset field */ + UNSET_PARAM(ifp->link_params, type); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); +} + +DEFUN (link_params, + link_params_cmd, + "link-params", + LINK_PARAMS_STR) +{ + vty->node = LINK_PARAMS_NODE; + + return CMD_SUCCESS; +} + +/* Specific Traffic Engineering parameters commands */ +DEFUN (link_params_enable, + link_params_enable_cmd, + "enable", + "Activate link parameters on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* This command could be issue at startup, when activate MPLS TE */ + /* on a new interface or after a ON / OFF / ON toggle */ + /* In all case, TE parameters are reset to their default factory */ + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("Link-params: enable TE link parameters on interface %s", ifp->name); + + if (!if_link_params_get (ifp)) + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("Link-params: failed to init TE link parameters %s", ifp->name); + + return CMD_WARNING; + } + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_enable, + no_link_params_enable_cmd, + "no enable", + NO_STR + "Disable link parameters on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + zlog_debug ("MPLS-TE: disable TE link parameters on interface %s", ifp->name); + + if_link_params_free (ifp); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + + return CMD_SUCCESS; +} + +/* STANDARD TE metrics */ +DEFUN (link_params_metric, + link_params_metric_cmd, + "metric <0-4294967295>", + "Link metric for MPLS-TE purpose\n" + "Metric value in decimal\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + u_int32_t metric; + + VTY_GET_ULONG("metric", metric, argv[0]); + + /* Update TE metric if needed */ + link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE, metric); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_metric, + no_link_params_metric_cmd, + "no metric", + NO_STR + "Disbale Link Metric on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset TE Metric */ + link_param_cmd_unset(ifp, LP_TE); + + return CMD_SUCCESS; +} + +DEFUN (link_params_maxbw, + link_params_maxbw_cmd, + "max-bw BANDWIDTH", + "Maximum bandwidth that can be used\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + + float bw; + + if (sscanf (argv[0], "%g", &bw) != 1) + { + vty_out (vty, "link_params_maxbw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that Maximum bandwidth is not lower than other bandwidth parameters */ + if ((bw <= iflp->max_rsv_bw) + || (bw <= iflp->unrsv_bw[0]) + || (bw <= iflp->unrsv_bw[1]) + || (bw <= iflp->unrsv_bw[2]) + || (bw <= iflp->unrsv_bw[3]) + || (bw <= iflp->unrsv_bw[4]) + || (bw <= iflp->unrsv_bw[5]) + || (bw <= iflp->unrsv_bw[6]) + || (bw <= iflp->unrsv_bw[7]) + || (bw <= iflp->ava_bw) + || (bw <= iflp->res_bw) + || (bw <= iflp->use_bw)) + { + vty_out (vty, + "Maximum Bandwidth could not be lower than others bandwidth%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Maximum Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->max_bw, LP_MAX_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (link_params_max_rsv_bw, + link_params_max_rsv_bw_cmd, + "max-rsv-bw BANDWIDTH", + "Maximum bandwidth that may be reserved\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + float bw; + + if (sscanf (argv[0], "%g", &bw) != 1) + { + vty_out (vty, "link_params_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter */ + if (bw > iflp->max_bw) + { + vty_out (vty, + "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)%s", + iflp->max_bw, VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Maximum Reservable Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (link_params_unrsv_bw, + link_params_unrsv_bw_cmd, + "unrsv-bw <0-7> BANDWIDTH", + "Unreserved bandwidth at each priority level\n" + "Priority\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + int priority; + float bw; + + /* We don't have to consider about range check here. */ + if (sscanf (argv[0], "%d", &priority) != 1) + { + vty_out (vty, "link_params_unrsv_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (sscanf (argv[1], "%g", &bw) != 1) + { + vty_out (vty, "link_params_unrsv_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter */ + if (bw > iflp->max_bw) + { + vty_out (vty, + "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)%s", + iflp->max_bw, VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Unreserved Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (link_params_admin_grp, + link_params_admin_grp_cmd, + "admin-grp BITPATTERN", + "Administrative group membership\n" + "32-bit Hexadecimal value (e.g. 0xa1)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + unsigned long value; + + if (sscanf (argv[0], "0x%lx", &value) != 1) + { + vty_out (vty, "link_params_admin_grp: fscanf: %s%s", + safe_strerror (errno), VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Administrative Group if needed */ + link_param_cmd_set_uint32 (ifp, &iflp->admin_grp, LP_ADM_GRP, value); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_admin_grp, + no_link_params_admin_grp_cmd, + "no admin-grp", + NO_STR + "Disbale Administrative group membership on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Admin Group */ + link_param_cmd_unset(ifp, LP_ADM_GRP); + + return CMD_SUCCESS; +} + +/* RFC5392 & RFC5316: INTER-AS */ +DEFUN (link_params_inter_as, + link_params_inter_as_cmd, + "neighbor A.B.C.D as <1-4294967295>", + "Configure remote ASBR information (Neighbor IP address and AS number)\n" + "Remote IP address in dot decimal A.B.C.D\n" + "Remote AS number\n" + "AS number in the range <1-4294967295>\n") +{ + + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + struct in_addr addr; + u_int32_t as; + + if (!inet_aton (argv[0], &addr)) + { + vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + VTY_GET_ULONG("AS number", as, argv[1]); + + /* Update Remote IP and Remote AS fields if needed */ + if (IS_PARAM_UNSET(iflp, LP_RMT_AS) + || iflp->rmt_as != as + || iflp->rmt_ip.s_addr != addr.s_addr) + { + + iflp->rmt_as = as; + iflp->rmt_ip.s_addr = addr.s_addr; + SET_PARAM(iflp, LP_RMT_AS); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + } + return CMD_SUCCESS; +} + +DEFUN (no_link_params_inter_as, + no_link_params_inter_as_cmd, + "no neighbor", + NO_STR + "Remove Neighbor IP address and AS number for Inter-AS TE\n") +{ + + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + + /* Reset Remote IP and AS neighbor */ + iflp->rmt_as = 0; + iflp->rmt_ip.s_addr = 0; + UNSET_PARAM(iflp, LP_RMT_AS); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + + return CMD_SUCCESS; +} + +/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & draft-ietf-isis-metric-extensions-07.txt */ +DEFUN (link_params_delay, + link_params_delay_cmd, + "delay <0-16777215>", + "Unidirectional Average Link Delay\n" + "Average delay in micro-second as decimal (0...16777215)\n") +{ + + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + u_int32_t delay = 0, low = 0, high = 0; + u_int8_t update = 0; + + /* Get and Check new delay values */ + VTY_GET_ULONG("delay", delay, argv[0]); + switch (argc) + { + case 1: + /* Check new delay value against old Min and Max delays if set */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY) + && (delay <= iflp->min_delay || delay >= iflp->max_delay)) + { + vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay%s", + iflp->min_delay, iflp->max_delay, VTY_NEWLINE); + return CMD_WARNING; + } + /* Update delay if value is not set or change */ + if (IS_PARAM_UNSET(iflp, LP_DELAY)|| iflp->av_delay != delay) + { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + update = 1; + } + /* Unset Min and Max delays if already set */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) + { + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + break; + case 2: + vty_out (vty, "You should specify both Minimum and Maximum delay with Average delay%s", + VTY_NEWLINE); + return CMD_WARNING; + break; + case 3: + VTY_GET_ULONG("minimum delay", low, argv[1]); + VTY_GET_ULONG("maximum delay", high, argv[2]); + /* Check new delays value coherency */ + if (delay <= low || delay >= high) + { + vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay%s", + low, high, VTY_NEWLINE); + return CMD_WARNING; + } + /* Update Delays if needed */ + if (IS_PARAM_UNSET(iflp, LP_DELAY) + || IS_PARAM_UNSET(iflp, LP_MM_DELAY) + || iflp->av_delay != delay + || iflp->min_delay != low + || iflp->max_delay != high) + { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + iflp->min_delay = low; + iflp->max_delay = high; + SET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + break; + default: + return CMD_WARNING; + break; + } + + /* force protocols to update LINK STATE due to parameters change */ + if (update == 1 && if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + + return CMD_SUCCESS; +} + +ALIAS (link_params_delay, + link_params_delay_mm_cmd, + "delay <0-16777215> min <0-16777215> max <0-16777215>", + "Unidirectional Average Link Delay (optionally Minimum and Maximum delays)\n" + "Average delay in micro-second as decimal (0...16777215)\n" + "Minimum delay\n" + "Minimum delay in micro-second as decimal (0...16777215)\n" + "Maximum delay\n" + "Maximum delay in micro-second as decimal (0...16777215)\n") + +DEFUN (no_link_params_delay, + no_link_params_delay_cmd, + "no delay", + NO_STR + "Disbale Unidirectional Average, Min & Max Link Delay on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + + /* Unset Delays */ + iflp->av_delay = 0; + UNSET_PARAM(iflp, LP_DELAY); + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); + + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative (ifp)) + zebra_interface_parameters_update (ifp); + + return CMD_SUCCESS; +} + +DEFUN (link_params_delay_var, + link_params_delay_var_cmd, + "delay-variation <0-16777215>", + "Unidirectional Link Delay Variation\n" + "delay variation in micro-second as decimal (0...16777215)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + u_int32_t value; + + VTY_GET_ULONG("delay variation", value, argv[0]); + + /* Update Delay Variation if needed */ + link_param_cmd_set_uint32 (ifp, &iflp->delay_var, LP_DELAY_VAR, value); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_delay_var, + no_link_params_delay_var_cmd, + "no delay-variation", + NO_STR + "Disbale Unidirectional Delay Variation on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Delay Variation */ + link_param_cmd_unset(ifp, LP_DELAY_VAR); + + return CMD_SUCCESS; +} + +DEFUN (link_params_pkt_loss, + link_params_pkt_loss_cmd, + "packet-loss PERCENTAGE", + "Unidirectional Link Packet Loss\n" + "percentage of total traffic by 0.000003% step and less than 50.331642%\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + float fval; + + if (sscanf (argv[0], "%g", &fval) != 1) + { + vty_out (vty, "link_params_pkt_loss: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (fval > MAX_PKT_LOSS) + fval = MAX_PKT_LOSS; + + /* Update Packet Loss if needed */ + link_param_cmd_set_float (ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_pkt_loss, + no_link_params_pkt_loss_cmd, + "no packet-loss", + NO_STR + "Disbale Unidirectional Link Packet Loss on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Packet Loss */ + link_param_cmd_unset(ifp, LP_PKT_LOSS); + + return CMD_SUCCESS; +} + +DEFUN (link_params_res_bw, + link_params_res_bw_cmd, + "res-bw BANDWIDTH", + "Unidirectional Residual Bandwidth\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + float bw; + + if (sscanf (argv[0], "%g", &bw) != 1) + { + vty_out (vty, "link_params_res_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter */ + if (bw > iflp->max_bw) + { + vty_out (vty, + "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)%s", + iflp->max_bw, VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->res_bw, LP_RES_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_res_bw, + no_link_params_res_bw_cmd, + "no res-bw", + NO_STR + "Disbale Unidirectional Residual Bandwidth on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Residual Bandwidth */ + link_param_cmd_unset(ifp, LP_RES_BW); + + return CMD_SUCCESS; +} + +DEFUN (link_params_ava_bw, + link_params_ava_bw_cmd, + "ava-bw BANDWIDTH", + "Unidirectional Available Bandwidth\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + float bw; + + if (sscanf (argv[0], "%g", &bw) != 1) + { + vty_out (vty, "link_params_ava_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter */ + if (bw > iflp->max_bw) + { + vty_out (vty, + "Available Bandwidth could not be greater than Maximum Bandwidth (%g)%s", + iflp->max_bw, VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->ava_bw, LP_AVA_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_ava_bw, + no_link_params_ava_bw_cmd, + "no ava-bw", + NO_STR + "Disbale Unidirectional Available Bandwidth on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Available Bandwidth */ + link_param_cmd_unset(ifp, LP_AVA_BW); + + return CMD_SUCCESS; +} + +DEFUN (link_params_use_bw, + link_params_use_bw_cmd, + "use-bw BANDWIDTH", + "Unidirectional Utilised Bandwidth\n" + "Bytes/second (IEEE floating point format)\n") +{ + struct interface *ifp = (struct interface *) vty->index; + struct if_link_params *iflp = if_link_params_get (ifp); + float bw; + + if (sscanf (argv[0], "%g", &bw) != 1) + { + vty_out (vty, "link_params_use_bw: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter */ + if (bw > iflp->max_bw) + { + vty_out (vty, + "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)%s", + iflp->max_bw, VTY_NEWLINE); + return CMD_WARNING; + } + + /* Update Utilized Bandwidth if needed */ + link_param_cmd_set_float (ifp, &iflp->use_bw, LP_USE_BW, bw); + + return CMD_SUCCESS; +} + +DEFUN (no_link_params_use_bw, + no_link_params_use_bw_cmd, + "no use-bw", + NO_STR + "Disbale Unidirectional Utilised Bandwidth on this interface\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + /* Unset Utilised Bandwidth */ + link_param_cmd_unset(ifp, LP_USE_BW); + + return CMD_SUCCESS; +} + static int ip_address_install (struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, @@ -2054,6 +2787,58 @@ DEFUN (no_ipv6_address, } #endif /* HAVE_IPV6 */ +static int +link_params_config_write (struct vty *vty, struct interface *ifp) +{ + int i; + + if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) + return -1; + + struct if_link_params *iflp = ifp->link_params; + + vty_out (vty, " link-params%s", VTY_NEWLINE); + vty_out(vty, " enable%s", VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_TE)) + vty_out(vty, " metric %u%s",iflp->te_metric, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_MAX_BW)) + vty_out(vty, " max-bw %g%s", iflp->max_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + vty_out(vty, " max-rsv-bw %g%s", iflp->max_rsv_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) + { + for (i = 0; i < 8; i++) + vty_out(vty, " unrsv-bw %d %g%s", + i, iflp->unrsv_bw[i], VTY_NEWLINE); + } + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " admin-grp %u%s", iflp->admin_grp, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_DELAY)) + { + vty_out(vty, " delay %u", iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) + { + vty_out(vty, " min %u", iflp->min_delay); + vty_out(vty, " max %u", iflp->max_delay); + } + vty_out(vty, "%s", VTY_NEWLINE); + } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, " delay-variation %u%s", iflp->delay_var, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " packet-loss %g%s", iflp->pkt_loss, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " ava-bw %g%s", iflp->ava_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " res-bw %g%s", iflp->res_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " use-bw %g%s", iflp->use_bw, VTY_NEWLINE); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " neighbor %s as %u%s", inet_ntoa(iflp->rmt_ip), + iflp->rmt_as, VTY_NEWLINE); + return 0; +} + static int if_config_write (struct vty *vty) { @@ -2134,6 +2919,8 @@ if_config_write (struct vty *vty) irdp_config_write (vty, ifp); #endif /* IRDP */ + link_params_config_write (vty, ifp); + vty_out (vty, "!%s", VTY_NEWLINE); } return 0; @@ -2166,6 +2953,7 @@ zebra_if_init (void) /* Install configuration write function. */ install_node (&interface_node, if_config_write); + install_node (&link_params_node, NULL); install_node (&vrf_node, vrf_config_write); install_element (VIEW_NODE, &show_interface_cmd); @@ -2209,9 +2997,26 @@ zebra_if_init (void) install_element (INTERFACE_NODE, &ip_address_label_cmd); install_element (INTERFACE_NODE, &no_ip_address_label_cmd); #endif /* HAVE_NETLINK */ - + install_element(INTERFACE_NODE, &link_params_cmd); + install_default(LINK_PARAMS_NODE); + install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); + install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); + install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_mm_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); + install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); + install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); + install_element (CONFIG_NODE, &zebra_vrf_cmd); install_element (CONFIG_NODE, &no_vrf_cmd); install_default (VRF_NODE); - } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 2864e0b8a5..fb9fa0216a 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -385,9 +385,11 @@ zebra_interface_up_update (struct interface *ifp) if (ifp->ptm_status || !ifp->ptm_enable) { for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp); - } + if (client->ifinfo) + { + zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp); + zsend_interface_link_params (client, ifp); + } } } @@ -418,10 +420,12 @@ zebra_interface_add_update (struct interface *ifp) zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - client->ifadd_cnt++; - zsend_interface_add (client, ifp); - } + if (client->ifinfo) + { + client->ifadd_cnt++; + zsend_interface_add (client, ifp); + zsend_interface_link_params (client, ifp); + } } void @@ -797,3 +801,18 @@ zebra_import_table_rm_update () return; } + +/* Interface parameters update */ +void +zebra_interface_parameters_update (struct interface *ifp) +{ + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", ifp->name); + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + if (client->ifinfo) + zsend_interface_link_params (client, ifp); +} diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 5e3cf1bfd3..e3bce7af46 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -49,6 +49,7 @@ extern void zebra_interface_address_add_update (struct interface *, struct connected *); extern void zebra_interface_address_delete_update (struct interface *, struct connected *c); +extern void zebra_interface_parameters_update (struct interface *); extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id); extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id); diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c index c21ee44702..85d3bd2f1b 100644 --- a/zebra/redistribute_null.c +++ b/zebra/redistribute_null.c @@ -60,6 +60,10 @@ void zebra_interface_address_delete_update (struct interface *a, struct connected *b) { return; } +/* Interface parameters update */ +void zebra_interface_parameters_update (struct interface *ifp) +{ return; }; + void zebra_interface_vrf_update_del (struct interface *a, vrf_id_t new_vrf_id) { return; } diff --git a/zebra/zserv.c b/zebra/zserv.c index 989bca0788..d8579a2d06 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -165,6 +165,16 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); + zlog_info("Try to set TE Link Param"); + /* Then, Traffic Engineering parameters if any */ + if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) + { + stream_putc (s, 1); + zebra_interface_link_params_write (s, ifp); + } + else + stream_putc (s, 0); + /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); } @@ -252,6 +262,35 @@ zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf) return zebra_server_send_message (client); } +int +zsend_interface_link_params (struct zserv *client, struct interface *ifp) +{ + struct stream *s; + + /* Check this client need interface information. */ + if (! client->ifinfo) + return 0; + + if (!ifp->link_params) + return 0; + s = client->obuf; + stream_reset (s); + + zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); + + /* Add Interface Index */ + stream_putl (s, ifp->ifindex); + + /* Then TE Link Parameters */ + if (zebra_interface_link_params_write (s, ifp) == 0) + return 0; + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); + + return zebra_server_send_message (client); +} + /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * diff --git a/zebra/zserv.h b/zebra/zserv.h index 737795ad54..3667f5b2b6 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -165,6 +165,8 @@ extern int zsend_router_id_update (struct zserv *, struct prefix *, extern int zsend_interface_vrf_update (struct zserv *, struct interface *, vrf_id_t); +extern int zsend_interface_link_params (struct zserv *, struct interface *); + extern pid_t pid; extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id); From f8c06e2c5270144ea6d1a3fbc70b42979db836db Mon Sep 17 00:00:00 2001 From: Olivier Dugeon Date: Tue, 19 Apr 2016 19:03:05 +0200 Subject: [PATCH 181/226] Add support of Traffic Engineering to IS-IS These patches is an implementation of RFC5305 that enable the support of Traffic Engineering in IS-IS * isisd/Makefile.am: Add new files isis_te.c and isis_te.h * isisd/isis_circuit.[c,h]: Add new mpls_te_circuit structure to isis_circuit structure to handle new Traffic Engineering TLVs * isisd/isis_lsp.c: Update LSP handler to mux/demux Traffic Engineering TLVs * isisd/isis_main.c: Add initialisation of ISIS TE * isisd/isis_pdu.c: Update function process_p2p_hello() to retrieve remote IP address to populate Traffic Engineering TLV. * isisd/isis_te.[c,]: Implementation of RFC5305 * isisd/isis_tlv.[c,h]: Update TLV definition and function to handle Traffic Engineering ones * isisd/isis_zebra.c: Add new function isis_zebra_link_params() to retrieve the link parameters of interfaces from ZBus to populate the Traffic Engineering TLVs * isisd/isisd.[c,h]: Add Traffic Engineering support with new debug command Signed-off-by: Olivier Dugeon --- isisd/AUTHORS | 1 + isisd/Makefile.am | 4 +- isisd/isis_circuit.c | 9 + isisd/isis_circuit.h | 3 +- isisd/isis_lsp.c | 81 +++ isisd/isis_lsp.h | 2 + isisd/isis_main.c | 3 + isisd/isis_pdu.c | 10 + isisd/isis_te.c | 1372 ++++++++++++++++++++++++++++++++++++++++++ isisd/isis_te.h | 331 ++++++++++ isisd/isis_tlv.c | 35 +- isisd/isis_tlv.h | 20 +- isisd/isis_zebra.c | 26 + isisd/isisd.c | 13 +- isisd/isisd.h | 4 + 15 files changed, 1896 insertions(+), 18 deletions(-) create mode 100644 isisd/isis_te.c create mode 100644 isisd/isis_te.h diff --git a/isisd/AUTHORS b/isisd/AUTHORS index 05fc0a5073..80b3a28e19 100644 --- a/isisd/AUTHORS +++ b/isisd/AUTHORS @@ -2,3 +2,4 @@ Sampo Saaristo Ofer Wald Hannes Gredler Subbaiah Venkata +Olivier Dugeon diff --git a/isisd/Makefile.am b/isisd/Makefile.am index 6dd132d49a..bfe2e94779 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -16,7 +16,7 @@ libisis_a_SOURCES = \ isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ - isis_spf.c isis_redist.c isis_route.c isis_routemap.c \ + isis_spf.c isis_redist.c isis_route.c isis_routemap.c isis_te.c \ isis_vty.c @@ -25,7 +25,7 @@ noinst_HEADERS = \ isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \ isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \ iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \ - isis_route.h isis_routemap.h \ + isis_route.h isis_routemap.h isis_te.h \ include-netbsd/clnp.h include-netbsd/esis.h include-netbsd/iso.h isisd_SOURCES = \ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 7138b42318..4f22a5e558 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -37,6 +37,7 @@ #include "linklist.h" #include "command.h" #include "thread.h" +#include "vty.h" #include "hash.h" #include "prefix.h" #include "stream.h" @@ -58,6 +59,7 @@ #include "isisd/isisd.h" #include "isisd/isis_csm.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" /* * Prototypes. @@ -96,6 +98,8 @@ isis_circuit_new () circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC; } + circuit->mtc = mpls_te_circuit_new(); + return circuit; } @@ -222,6 +226,10 @@ isis_circuit_add_addr (struct isis_circuit *circuit, ipv4->prefixlen = connected->address->prefixlen; ipv4->prefix = connected->address->u.prefix4; listnode_add (circuit->ip_addrs, ipv4); + + /* Update MPLS TE Local IP address parameter */ + set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix); + if (circuit->area) lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); @@ -518,6 +526,7 @@ isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp) assert (ifp->info == circuit); else ifp->info = circuit; + isis_link_params_update (circuit, ifp); } void diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 9d6e426d41..9ada1e26a3 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -112,13 +112,14 @@ struct isis_circuit */ struct isis_passwd passwd; /* Circuit rx/tx password */ int is_type; /* circuit is type == level of circuit - * diffrenciated from circuit type (media) */ + * differentiated from circuit type (media) */ u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ u_int8_t metric[2]; u_int32_t te_metric[2]; + struct mpls_te_circuit *mtc; /* Support for MPLS-TE parameters - see isis_te.[c,h] */ int ip_router; /* Route IP ? */ int is_passive; /* Is Passive ? */ struct list *ip_addrs; /* our IP addresses */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 81f1958e63..0177a9423a 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -52,6 +52,7 @@ #include "isisd/isis_csm.h" #include "isisd/isis_adjacency.h" #include "isisd/isis_spf.h" +#include "isisd/isis_te.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -981,6 +982,8 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost) lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0); vty_out (vty, " Metric : %-8d IS-Extended : %s%s", GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE); + if (IS_MPLS_TE(isisMplsTE)) + mpls_te_print_detail(vty, te_is_neigh); } /* TE IPv4 tlv */ @@ -1091,6 +1094,64 @@ lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, return; } +/* Process IS_NEIGHBOURS TLV with TE subTLVs */ +void +lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, int frag_thold) +{ + int count, size = 0; + struct listnode *node, *nextnode; + struct te_is_neigh *elem; + + /* Start computing real size of TLVs */ + for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem)) + size = size + elem->sub_tlvs_length + IS_NEIGHBOURS_LEN; + + /* can we fit all ? */ + if (!FRAG_NEEDED (lsp->pdu, frag_thold, size)) + { + tlv_add_te_is_neighs (*from, lsp->pdu); + if (listcount (*to) != 0) + { + for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem)) + { + listnode_add (*to, elem); + list_delete_node (*from, node); + } + } + else + { + list_free (*to); + *to = *from; + *from = NULL; + } + } + else + { + /* fit all we can */ + /* Compute remaining place in LSP PDU */ + count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 - + (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu)); + /* Determine size of TE SubTLVs */ + elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from)); + count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN; + if (count > 0) + { + while (count > 0) + { + listnode_add (*to, listgetdata ((struct listnode *)listhead (*from))); + listnode_delete (*from, listgetdata ((struct listnode *)listhead (*from))); + + elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from)); + count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN; + } + + tlv_add_te_is_neighs (*to, lsp->pdu); + } + } + lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); + return; +} + static u_int16_t lsp_rem_lifetime (struct isis_area *area, int level) { @@ -1631,6 +1692,14 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) } else { + /* Check if MPLS_TE is activate */ + if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) + /* Add SubTLVs & Adjust real size of SubTLVs */ + te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); + else + /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ + te_is_neigh->sub_tlvs_length = 0; + listnode_add (tlv_data.te_is_neighs, te_is_neigh); lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor", area->area_tag, sysid_print(te_is_neigh->neigh_id), @@ -1679,6 +1748,18 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); metric = circuit->te_metric[level - 1]; SET_TE_METRIC(te_is_neigh, metric); + /* Check if MPLS_TE is activate */ + if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) + /* Update Local and Remote IP address for MPLS TE circuit parameters */ + /* NOTE sure that it is the pertinent place for that updates */ + /* Local IP address could be updated in isis_circuit.c - isis_circuit_add_addr() */ + /* But, where update remote IP address ? in isis_pdu.c - process_p2p_hello() ? */ + + /* Add SubTLVs & Adjust real size of SubTLVs */ + te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); + else + /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ + te_is_neigh->sub_tlvs_length = 0; listnode_add (tlv_data.te_is_neighs, te_is_neigh); lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag, sysid_print(te_is_neigh->neigh_id)); diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index a35bfa7622..7b2286b189 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -112,6 +112,8 @@ void lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost); int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost); const char *lsp_bits2string (u_char *); +void lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, + struct list **to, int frag_thold); /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags (struct isis_lsp *lsp); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 234e516db5..81ca1e20c6 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -50,6 +50,8 @@ #include "isisd/isis_route.h" #include "isisd/isis_routemap.h" #include "isisd/isis_zebra.h" +#include "isisd/isis_tlv.h" +#include "isisd/isis_te.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" @@ -348,6 +350,7 @@ main (int argc, char **argv, char **envp) isis_spf_cmds_init (); isis_redist_init (); isis_route_map_init(); + isis_mpls_te_init(); /* create the global 'isis' instance */ isis_new (1); diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 0401e44a9a..1dfb4623f6 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -53,6 +53,7 @@ #include "isisd/iso_checksum.h" #include "isisd/isis_csm.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" #define ISIS_MINIMUM_FIXED_HDR_LEN 15 #define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */ @@ -630,6 +631,15 @@ process_p2p_hello (struct isis_circuit *circuit) if (found & TLVFLAG_IPV4_ADDR) tlvs_to_adj_ipv4_addrs (&tlvs, adj); + /* Update MPLS TE Remote IP address parameter if possible */ + if (IS_MPLS_TE(isisMplsTE) && circuit->mtc && IS_CIRCUIT_TE(circuit->mtc)) + if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) + { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr (circuit->mtc, *ip_addr); + } + #ifdef HAVE_IPV6 if (found & TLVFLAG_IPV6_ADDR) tlvs_to_adj_ipv6_addrs (&tlvs, adj); diff --git a/isisd/isis_te.c b/isisd/isis_te.c new file mode 100644 index 0000000000..247d699b1e --- /dev/null +++ b/isisd/isis_te.c @@ -0,0 +1,1372 @@ +/* + * IS-IS Rout(e)ing protocol - isis_te.c + * + * This is an implementation of RFC5305 + * + * Copyright (C) 2014 Orange Labs + * http://www.orange.com + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include + +#include "linklist.h" +#include "thread.h" +#include "vty.h" +#include "stream.h" +#include "memory.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "hash.h" +#include "if.h" +#include "vrf.h" +#include "checksum.h" +#include "md5.h" +#include "sockunion.h" +#include "network.h" + +#include "isisd/dict.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_common.h" +#include "isisd/isis_flags.h" +#include "isisd/isis_circuit.h" +#include "isisd/isisd.h" +#include "isisd/isis_tlv.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_pdu.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_csm.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_te.h" + +/* Global varial for MPLS TE management */ +struct isis_mpls_te isisMplsTE; + +const char *mode2text[] = { "Disable", "Area", "AS", "Emulate" }; + +/*------------------------------------------------------------------------* + * Followings are control functions for MPLS-TE parameters management. + *------------------------------------------------------------------------*/ + +/* Search MPLS TE Circuit context from Interface */ +static struct mpls_te_circuit * +lookup_mpls_params_by_ifp (struct interface *ifp) +{ + struct isis_circuit *circuit; + + if ((circuit = circuit_scan_by_ifp (ifp)) == NULL) + return NULL; + + return circuit->mtc; +} + +/* Create new MPLS TE Circuit context */ +struct mpls_te_circuit * +mpls_te_circuit_new() +{ + struct mpls_te_circuit *mtc; + + zlog_debug ("ISIS MPLS-TE: Create new MPLS TE Circuit context"); + + mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof (struct mpls_te_circuit)); + + if (mtc == NULL) + return NULL; + + mtc->status = disable; + mtc->type = STD_TE; + mtc->length = 0; + + return mtc; + +} + +/* Copy SUB TLVs parameters into a buffer - No space verification are performed */ +/* Caller must verify before that there is enough free space in the buffer */ +u_char +add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) +{ + u_char size, *tlvs = buf; + + zlog_debug ("ISIS MPLS-TE: Add TE Sub TLVs to buffer"); + + if (mtc == NULL) + { + zlog_debug("ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified"); + return 0; + } + + /* Create buffer if not provided */ + if (buf == NULL) + { + zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified"); + return 0; + } + + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) + { + size = SUBTLV_SIZE (&(mtc->admin_grp.header)); + memcpy(tlvs, &(mtc->admin_grp), size); + tlvs += size; + } + + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) + { + size = SUBTLV_SIZE (&(mtc->llri.header)); + memcpy(tlvs, &(mtc->llri), size); + tlvs += size; + } + + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + { + size = SUBTLV_SIZE (&(mtc->local_ipaddr.header)); + memcpy(tlvs, &(mtc->local_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + { + size = SUBTLV_SIZE (&(mtc->rmt_ipaddr.header)); + memcpy(tlvs, &(mtc->rmt_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->max_bw.header)); + memcpy(tlvs, &(mtc->max_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->max_rsv_bw.header)); + memcpy(tlvs, &(mtc->max_rsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->unrsv_bw.header)); + memcpy(tlvs, &(mtc->unrsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) + { + size = SUBTLV_SIZE (&(mtc->te_metric.header)); + memcpy(tlvs, &(mtc->te_metric), size); + tlvs += size; + } + + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) + { + size = SUBTLV_SIZE (&(mtc->av_delay.header)); + memcpy(tlvs, &(mtc->av_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) + { + size = SUBTLV_SIZE (&(mtc->mm_delay.header)); + memcpy(tlvs, &(mtc->mm_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) + { + size = SUBTLV_SIZE (&(mtc->delay_var.header)); + memcpy(tlvs, &(mtc->delay_var), size); + tlvs += size; + } + + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) + { + size = SUBTLV_SIZE (&(mtc->pkt_loss.header)); + memcpy(tlvs, &(mtc->pkt_loss), size); + tlvs += size; + } + + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->res_bw.header)); + memcpy(tlvs, &(mtc->res_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->ava_bw.header)); + memcpy(tlvs, &(mtc->ava_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) + { + size = SUBTLV_SIZE (&(mtc->use_bw.header)); + memcpy(tlvs, &(mtc->use_bw), size); + tlvs += size; + } + + /* Update SubTLVs length */ + mtc->length = subtlvs_len(mtc); + + zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length); + + return mtc->length; +} + +/* Compute total Sub-TLVs size */ +u_char +subtlvs_len (struct mpls_te_circuit *mtc) +{ + int length = 0; + + /* Sanity Check */ + if (mtc == NULL) + return 0; + + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) + length += SUBTLV_SIZE (&(mtc->admin_grp.header)); + + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) + length += SUBTLV_SIZE (&mtc->llri.header); + + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + length += SUBTLV_SIZE (&mtc->local_ipaddr.header); + + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + length += SUBTLV_SIZE (&mtc->rmt_ipaddr.header); + + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) + length += SUBTLV_SIZE (&mtc->max_bw.header); + + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) + length += SUBTLV_SIZE (&mtc->max_rsv_bw.header); + + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) + length += SUBTLV_SIZE (&mtc->unrsv_bw.header); + + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) + length += SUBTLV_SIZE (&mtc->te_metric.header); + + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) + length += SUBTLV_SIZE (&mtc->av_delay.header); + + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) + length += SUBTLV_SIZE (&mtc->mm_delay.header); + + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) + length += SUBTLV_SIZE (&mtc->delay_var.header); + + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) + length += SUBTLV_SIZE (&mtc->pkt_loss.header); + + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) + length += SUBTLV_SIZE (&mtc->res_bw.header); + + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) + length += SUBTLV_SIZE (&mtc->ava_bw.header); + + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) + length += SUBTLV_SIZE (&mtc->use_bw.header); + + /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */ + if (length > MAX_SUBTLV_SIZE) + { + mtc->length = 0; + return 0; + } + + mtc->length = (u_char)length; + + return mtc->length; +} + +/* Following are various functions to set MPLS TE parameters */ +static void +set_circuitparams_admin_grp (struct mpls_te_circuit *mtc, u_int32_t admingrp) +{ + SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP; + SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE; + mtc->admin_grp.value = htonl(admingrp); + return; +} + +static void __attribute__ ((unused)) +set_circuitparams_llri (struct mpls_te_circuit *mtc, u_int32_t local, u_int32_t remote) +{ + SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI; + SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE; + mtc->llri.local = htonl(local); + mtc->llri.remote = htonl(remote); +} + +void +set_circuitparams_local_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +{ + + SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR; + SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE; + mtc->local_ipaddr.value.s_addr = addr.s_addr; + return; +} + +void +set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +{ + + SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR; + SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE; + mtc->rmt_ipaddr.value.s_addr = addr.s_addr; + return; +} + +static void +set_circuitparams_max_bw (struct mpls_te_circuit *mtc, float fp) +{ + SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW; + SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE; + mtc->max_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_max_rsv_bw (struct mpls_te_circuit *mtc, float fp) +{ + SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW; + SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE; + mtc->max_rsv_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_unrsv_bw (struct mpls_te_circuit *mtc, int priority, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW; + SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE; + mtc->unrsv_bw.value[priority] = htonf(fp); + return; +} + +static void +set_circuitparams_te_metric (struct mpls_te_circuit *mtc, u_int32_t te_metric) +{ + SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC; + SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE; + mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF; + mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF; + mtc->te_metric.value[2] = te_metric & 0xFF; + return; +} + +static void +set_circuitparams_inter_as (struct mpls_te_circuit *mtc, struct in_addr addr, u_int32_t as) +{ + + /* Set the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP; + SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE; + mtc->rip.value.s_addr = addr.s_addr; + + SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS; + SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE; + mtc->ras.value = htonl(as); +} + +static void +unset_circuitparams_inter_as (struct mpls_te_circuit *mtc) +{ + + /* Reset the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = 0; + SUBTLV_LEN(mtc->rip) = 0; + mtc->rip.value.s_addr = 0; + + SUBTLV_TYPE(mtc->ras) = 0; + SUBTLV_LEN(mtc->ras) = 0; + mtc->ras.value = 0; +} + +static void +set_circuitparams_av_delay (struct mpls_te_circuit *mtc, u_int32_t delay, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY; + SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE; + tmp = delay & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->av_delay.value = htonl(tmp); + return; +} + +static void +set_circuitparams_mm_delay (struct mpls_te_circuit *mtc, u_int32_t low, u_int32_t high, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY; + SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE; + tmp = low & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->mm_delay.low = htonl(tmp); + mtc->mm_delay.high = htonl(high); + return; +} + +static void +set_circuitparams_delay_var (struct mpls_te_circuit *mtc, u_int32_t jitter) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR; + SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE; + mtc->delay_var.value = htonl(jitter & TE_EXT_MASK); + return; +} + +static void +set_circuitparams_pkt_loss (struct mpls_te_circuit *mtc, u_int32_t loss, u_char anormal) +{ + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS; + SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE; + tmp = loss & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->pkt_loss.value = htonl(tmp); + return; +} + +static void +set_circuitparams_res_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW; + SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE; + mtc->res_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_ava_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW; + SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE; + mtc->ava_bw.value = htonf(fp); + return; +} + +static void +set_circuitparams_use_bw (struct mpls_te_circuit *mtc, float fp) +{ + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW; + SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE; + mtc->use_bw.value = htonf(fp); + return; +} + +/* Main initialization / update function of the MPLS TE Circuit context */ +/* Call when interface TE Link parameters are modified */ +void +isis_link_params_update (struct isis_circuit *circuit, struct interface *ifp) +{ + int i; + struct prefix_ipv4 *addr; + struct mpls_te_circuit *mtc; + + /* Sanity Check */ + if ((circuit == NULL) || (ifp == NULL)) + return; + + zlog_info ("MPLS-TE: Initialize circuit parameters for interface %s", ifp->name); + + /* Check if MPLS TE Circuit context has not been already created */ + if (circuit->mtc == NULL) + circuit->mtc = mpls_te_circuit_new(); + + mtc = circuit->mtc; + + /* Fulfil MTC TLV from ifp TE Link parameters */ + if (HAS_LINK_PARAMS(ifp)) + { + mtc->status = enable; + /* STD_TE metrics */ + if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) + set_circuitparams_admin_grp (mtc, ifp->link_params->admin_grp); + else + SUBTLV_TYPE(mtc->admin_grp) = 0; + + /* If not already set, register local IP addr from ip_addr list if it exists */ + if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) + { + if (circuit->ip_addrs != NULL && listcount(circuit->ip_addrs) != 0) + { + addr = (struct prefix_ipv4 *)listgetdata ((struct listnode *)listhead (circuit->ip_addrs)); + set_circuitparams_local_ipaddr (mtc, addr->prefix); + } + } + + /* If not already set, try to determine Remote IP addr if circuit is P2P */ + if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0) && (circuit->circ_type == CIRCUIT_T_P2P)) + { + struct isis_adjacency *adj = circuit->u.p2p.neighbor; + if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) + { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr (mtc, *ip_addr); + } + } + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) + set_circuitparams_max_bw (mtc, ifp->link_params->max_bw); + else + SUBTLV_TYPE(mtc->max_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) + set_circuitparams_max_rsv_bw (mtc, ifp->link_params->max_rsv_bw); + else + SUBTLV_TYPE(mtc->max_rsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) + for (i = 0; i < MAX_CLASS_TYPE; i++) + set_circuitparams_unrsv_bw (mtc, i, ifp->link_params->unrsv_bw[i]); + else + SUBTLV_TYPE(mtc->unrsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_TE)) + set_circuitparams_te_metric(mtc, ifp->link_params->te_metric); + else + SUBTLV_TYPE(mtc->te_metric) = 0; + + /* TE metric Extensions */ + if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) + set_circuitparams_av_delay(mtc, ifp->link_params->av_delay, 0); + else + SUBTLV_TYPE(mtc->av_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) + set_circuitparams_mm_delay(mtc, ifp->link_params->min_delay, ifp->link_params->max_delay, 0); + else + SUBTLV_TYPE(mtc->mm_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) + set_circuitparams_delay_var(mtc, ifp->link_params->delay_var); + else + SUBTLV_TYPE(mtc->delay_var) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) + set_circuitparams_pkt_loss(mtc, ifp->link_params->pkt_loss, 0); + else + SUBTLV_TYPE(mtc->pkt_loss) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) + set_circuitparams_res_bw(mtc, ifp->link_params->res_bw); + else + SUBTLV_TYPE(mtc->res_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) + set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw); + else + SUBTLV_TYPE(mtc->ava_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) + set_circuitparams_use_bw(mtc, ifp->link_params->use_bw); + else + SUBTLV_TYPE(mtc->use_bw) = 0; + + /* INTER_AS */ + if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) + set_circuitparams_inter_as(mtc, ifp->link_params->rmt_ip, ifp->link_params->rmt_as); + else + /* reset inter-as TE params */ + unset_circuitparams_inter_as (mtc); + + /* Compute total length of SUB TLVs */ + mtc->length = subtlvs_len(mtc); + + } + else + mtc->status = disable; + + /* Finally Update LSP */ +#if 0 + if (IS_MPLS_TE(isisMplsTE) && circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); +#endif + return; +} + +void +isis_mpls_te_update (struct interface *ifp) +{ + struct isis_circuit *circuit; + + /* Sanity Check */ + if (ifp == NULL) + return; + + /* Get circuit context from interface */ + if ((circuit = circuit_scan_by_ifp(ifp)) == NULL) + return; + + /* Update TE TLVs ... */ + isis_link_params_update(circuit, ifp); + + /* ... and LSP */ + if (IS_MPLS_TE(isisMplsTE) && circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty session control functions. + *------------------------------------------------------------------------*/ + +static u_char +show_vty_subtlv_admin_grp (struct vty *vty, struct te_subtlv_admin_grp *tlv) +{ + + if (vty != NULL) + vty_out (vty, " Administrative Group: 0x%x%s", + (u_int32_t) ntohl (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Administrative Group: 0x%x", + (u_int32_t) ntohl (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_llri (struct vty *vty, struct te_subtlv_llri *tlv) +{ + if (vty != NULL) + { + vty_out (vty, " Link Local ID: %d%s", (u_int32_t) ntohl (tlv->local), + VTY_NEWLINE); + vty_out (vty, " Link Remote ID: %d%s", (u_int32_t) ntohl (tlv->remote), + VTY_NEWLINE); + } + else + { + zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (tlv->local)); + zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (tlv->remote)); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE); +} + +static u_char +show_vty_subtlv_local_ipaddr (struct vty *vty, struct te_subtlv_local_ipaddr *tlv) +{ + if (vty != NULL) + vty_out (vty, " Local Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Local Interface IP Address(es): %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_rmt_ipaddr (struct vty *vty, struct te_subtlv_rmt_ipaddr *tlv) +{ + if (vty != NULL) + vty_out (vty, " Remote Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Remote Interface IP Address(es): %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_max_bw (struct vty *vty, struct te_subtlv_max_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_max_rsv_bw (struct vty *vty, struct te_subtlv_max_rsv_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, + VTY_NEWLINE); + else + zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_unrsv_bw (struct vty *vty, struct te_subtlv_unrsv_bw *tlv) +{ + float fval1, fval2; + int i; + + if (vty != NULL) + vty_out (vty, " Unreserved Bandwidth:%s",VTY_NEWLINE); + else + zlog_debug (" Unreserved Bandwidth:"); + + for (i = 0; i < MAX_CLASS_TYPE; i+=2) + { + fval1 = ntohf (tlv->value[i]); + fval2 = ntohf (tlv->value[i+1]); + if (vty != NULL) + vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s", i, fval1, i+1, fval2, VTY_NEWLINE); + else + zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", i, fval1, i+1, fval2); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE); +} + +static u_char +show_vty_subtlv_te_metric (struct vty *vty, struct te_subtlv_te_metric *tlv) +{ + u_int32_t te_metric; + + te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16; + if (vty != NULL) + vty_out (vty, " Traffic Engineering Metric: %u%s", te_metric, VTY_NEWLINE); + else + zlog_debug (" Traffic Engineering Metric: %u", te_metric); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_ras (struct vty *vty, struct te_subtlv_ras *tlv) +{ + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote AS number: %u%s", ntohl (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_rip (struct vty *vty, struct te_subtlv_rip *tlv) +{ + if (vty != NULL) + vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s%s", inet_ntoa (tlv->value), VTY_NEWLINE); + else + zlog_debug (" Inter-AS TE Remote ASBR IP address: %s", inet_ntoa (tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_av_delay (struct vty *vty, struct te_subtlv_av_delay *tlv) +{ + u_int32_t delay; + u_int32_t A; + + delay = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Average Link Delay: %d (micro-sec)%s", A ? "Anomalous" : "Normal", delay, VTY_NEWLINE); + else + zlog_debug (" %s Average Link Delay: %d (micro-sec)", A ? "Anomalous" : "Normal", delay); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_mm_delay (struct vty *vty, struct te_subtlv_mm_delay *tlv) +{ + u_int32_t low, high; + u_int32_t A; + + low = (u_int32_t) ntohl (tlv->low) & TE_EXT_MASK; + A = (u_int32_t) ntohl (tlv->low) & TE_EXT_ANORMAL; + high = (u_int32_t) ntohl (tlv->high) & TE_EXT_MASK; + + if (vty != NULL) + vty_out (vty, " %s Min/Max Link Delay: %d / %d (micro-sec)%s", A ? "Anomalous" : "Normal", low, high, VTY_NEWLINE); + else + zlog_debug (" %s Min/Max Link Delay: %d / %d (micro-sec)", A ? "Anomalous" : "Normal", low, high); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_delay_var (struct vty *vty, struct te_subtlv_delay_var *tlv) +{ + u_int32_t jitter; + + jitter = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + + if (vty != NULL) + vty_out (vty, " Delay Variation: %d (micro-sec)%s", jitter, VTY_NEWLINE); + else + zlog_debug (" Delay Variation: %d (micro-sec)", jitter); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_pkt_loss (struct vty *vty, struct te_subtlv_pkt_loss *tlv) +{ + u_int32_t loss; + u_int32_t A; + float fval; + + loss = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + fval = (float) (loss * LOSS_PRECISION); + A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out (vty, " %s Link Packet Loss: %g (%%)%s", A ? "Anomalous" : "Normal", fval, VTY_NEWLINE); + else + zlog_debug (" %s Link Packet Loss: %g (%%)", A ? "Anomalous" : "Normal", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_res_bw (struct vty *vty, struct te_subtlv_res_bw *tlv) +{ + float fval; + + fval = ntohf(tlv->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Residual Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Residual Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_ava_bw (struct vty *vty, struct te_subtlv_ava_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_subtlv_use_bw (struct vty *vty, struct te_subtlv_use_bw *tlv) +{ + float fval; + + fval = ntohf (tlv->value); + + if (vty != NULL) + vty_out (vty, " Unidirectional Utilized Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE); + else + zlog_debug (" Unidirectional Utilized Bandwidth: %g (Bytes/sec)", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); +} + +static u_char +show_vty_unknown_tlv (struct vty *vty, struct subtlv_header *tlvh) +{ + int i, rtn = 1; + u_char *v = (u_char *)tlvh; + + if (vty != NULL) + { + if (tlvh->length != 0) + { + vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]%s", + tlvh->type, tlvh->length, VTY_NEWLINE); + vty_out(vty, " Dump: [00]"); + rtn = 1; /* initialize end of line counter */ + for (i = 0; i < tlvh->length; i++) + { + vty_out (vty, " %#.2x", v[i]); + if (rtn == 8) + { + vty_out (vty, "%s [%.2x]", VTY_NEWLINE, i + 1); + rtn = 1; + } + else + rtn++; + } + vty_out (vty, "%s", VTY_NEWLINE); + } + else + vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]%s", + tlvh->type, tlvh->length, VTY_NEWLINE); + } + else + { + zlog_debug (" Unknown TLV: [type(%#.2x), length(%#.2x)]", + tlvh->type, tlvh->length); + } + + return SUBTLV_SIZE(tlvh); +} + +/* Main Show function */ +void +mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) +{ + struct subtlv_header *tlvh, *next; + u_int16_t sum = 0; + + zlog_debug ("ISIS MPLS-TE: Show database TE detail"); + + if (te->sub_tlvs == NULL) + return; + + tlvh = (struct subtlv_header *)te->sub_tlvs; + + for (; sum < te->sub_tlvs_length; tlvh = (next ? next : SUBTLV_HDR_NEXT (tlvh))) + { + next = NULL; + + switch (tlvh->type) + { + case TE_SUBTLV_ADMIN_GRP: + sum += show_vty_subtlv_admin_grp (vty, (struct te_subtlv_admin_grp *)tlvh); + break; + case TE_SUBTLV_LLRI: + sum += show_vty_subtlv_llri (vty, (struct te_subtlv_llri *)tlvh); + break; + case TE_SUBTLV_LOCAL_IPADDR: + sum += show_vty_subtlv_local_ipaddr (vty, (struct te_subtlv_local_ipaddr *)tlvh); + break; + case TE_SUBTLV_RMT_IPADDR: + sum += show_vty_subtlv_rmt_ipaddr (vty, (struct te_subtlv_rmt_ipaddr *)tlvh); + break; + case TE_SUBTLV_MAX_BW: + sum += show_vty_subtlv_max_bw (vty, (struct te_subtlv_max_bw *)tlvh); + break; + case TE_SUBTLV_MAX_RSV_BW: + sum += show_vty_subtlv_max_rsv_bw (vty, (struct te_subtlv_max_rsv_bw *)tlvh); + break; + case TE_SUBTLV_UNRSV_BW: + sum += show_vty_subtlv_unrsv_bw (vty, (struct te_subtlv_unrsv_bw *)tlvh); + break; + case TE_SUBTLV_TE_METRIC: + sum += show_vty_subtlv_te_metric (vty, (struct te_subtlv_te_metric *)tlvh); + break; + case TE_SUBTLV_RAS: + sum += show_vty_subtlv_ras (vty, (struct te_subtlv_ras *)tlvh); + break; + case TE_SUBTLV_RIP: + sum += show_vty_subtlv_rip (vty, (struct te_subtlv_rip *)tlvh); + break; + case TE_SUBTLV_AV_DELAY: + sum += show_vty_subtlv_av_delay (vty, (struct te_subtlv_av_delay *)tlvh); + break; + case TE_SUBTLV_MM_DELAY: + sum += show_vty_subtlv_mm_delay (vty, (struct te_subtlv_mm_delay *)tlvh); + break; + case TE_SUBTLV_DELAY_VAR: + sum += show_vty_subtlv_delay_var (vty, (struct te_subtlv_delay_var *)tlvh); + break; + case TE_SUBTLV_PKT_LOSS: + sum += show_vty_subtlv_pkt_loss (vty, (struct te_subtlv_pkt_loss *)tlvh); + break; + case TE_SUBTLV_RES_BW: + sum += show_vty_subtlv_res_bw (vty, (struct te_subtlv_res_bw *)tlvh); + break; + case TE_SUBTLV_AVA_BW: + sum += show_vty_subtlv_ava_bw (vty, (struct te_subtlv_ava_bw *)tlvh); + break; + case TE_SUBTLV_USE_BW: + sum += show_vty_subtlv_use_bw (vty, (struct te_subtlv_use_bw *)tlvh); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + return; +} + +/* Specific MPLS TE router parameters write function */ +void +isis_mpls_te_config_write_router (struct vty *vty) +{ + + zlog_debug ("ISIS MPLS-TE: Write ISIS router configuration"); + + if (IS_MPLS_TE(isisMplsTE)) + { + vty_out (vty, " mpls-te on%s", VTY_NEWLINE); + vty_out (vty, " mpls-te router-address %s%s", + inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE); + } + + return; +} + + +/*------------------------------------------------------------------------* + * Followings are vty command functions. + *------------------------------------------------------------------------*/ + +DEFUN (isis_mpls_te_on, + isis_mpls_te_on_cmd, + "mpls-te on", + MPLS_TE_STR + "Enable MPLS-TE functionality\n") +{ + struct listnode *node; + struct isis_circuit *circuit; + + if (IS_MPLS_TE(isisMplsTE)) + return CMD_SUCCESS; + + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug ("ISIS MPLS-TE: OFF -> ON"); + + isisMplsTE.status = enable; + + /* + * Following code is intended to handle two cases; + * + * 1) MPLS-TE was disabled at startup time, but now become enabled. + * In this case, we must enable MPLS-TE Circuit regarding interface MPLS_TE flag + * 2) MPLS-TE was once enabled then disabled, and now enabled again. + */ + for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) + { + if (circuit->mtc == NULL || IS_FLOOD_AS (circuit->mtc->type)) + continue; + + if ((circuit->mtc->status == disable) + && HAS_LINK_PARAMS(circuit->interface)) + circuit->mtc->status = enable; + else + continue; + + /* Reoriginate STD_TE & GMPLS circuits */ + if (circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + } + + return CMD_SUCCESS; +} + +DEFUN (no_isis_mpls_te_on, + no_isis_mpls_te_on_cmd, + "no mpls-te", + NO_STR + "Disable the MPLS-TE functionality\n") +{ + struct listnode *node; + struct isis_circuit *circuit; + + if (isisMplsTE.status == disable) + return CMD_SUCCESS; + + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug ("ISIS MPLS-TE: ON -> OFF"); + + isisMplsTE.status = disable; + + /* Flush LSP if circuit engage */ + for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) + { + if (circuit->mtc == NULL || (circuit->mtc->status == disable)) + continue; + + /* disable MPLS_TE Circuit */ + circuit->mtc->status = disable; + + /* Re-originate circuit without STD_TE & GMPLS parameters */ + if (circuit->area) + lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + } + + return CMD_SUCCESS; +} + +DEFUN (isis_mpls_te_router_addr, + isis_mpls_te_router_addr_cmd, + "mpls-te router-address A.B.C.D", + MPLS_TE_STR + "Stable IP address of the advertising router\n" + "MPLS-TE router address in IPv4 address format\n") +{ + struct in_addr value; + struct listnode *node; + struct isis_area *area; + + if (! inet_aton (argv[0], &value)) + { + vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + isisMplsTE.router_id.s_addr = value.s_addr; + + if (isisMplsTE.status == disable) + return CMD_SUCCESS; + + /* Update main Router ID in isis global structure */ + isis->router_id = value.s_addr; + /* And re-schedule LSP update */ + for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) + if (listcount (area->area_addrs) > 0) + lsp_regenerate_schedule (area, area->is_type, 0); + + return CMD_SUCCESS; +} + +DEFUN (isis_mpls_te_inter_as, + isis_mpls_te_inter_as_cmd, + "mpls-te inter-as (level-1|level-1-2|level-2-only)", + MPLS_TE_STR + "Configure MPLS-TE Inter-AS support\n" + "AREA native mode self originate INTER-AS LSP with L1 only flooding scope)\n" + "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n" + "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n") +{ + vty_out (vty, "Not yet supported%s", VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (no_isis_mpls_te_inter_as, + no_isis_mpls_te_inter_as_cmd, + "no mpls-te inter-as", + NO_STR + "Disable the MPLS-TE functionality\n" + "Disable MPLS-TE Inter-AS support\n") +{ + + vty_out (vty, "Not yet supported%s", VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (show_isis_mpls_te_router, + show_isis_mpls_te_router_cmd, + "show isis mpls-te router", + SHOW_STR + ISIS_STR + MPLS_TE_STR + "Router information\n") +{ + if (IS_MPLS_TE(isisMplsTE)) + { + vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE); + + if (vty != NULL) + { + if (ntohs (isisMplsTE.router_id.s_addr) != 0) + vty_out (vty, " Router-Address: %s%s", inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE); + else + vty_out (vty, " N/A%s", VTY_NEWLINE); + } + } + else + vty_out (vty, " MPLS-TE is disable on this router%s", VTY_NEWLINE); + + return CMD_SUCCESS; +} + +static void +show_mpls_te_sub (struct vty *vty, struct interface *ifp) +{ + struct mpls_te_circuit *mtc; + + if ((IS_MPLS_TE(isisMplsTE)) + && ((mtc = lookup_mpls_params_by_ifp (ifp)) != NULL)) + { + /* Continue only if interface is not passive or support Inter-AS TEv2 */ + if (mtc->status != enable) + { + if (IS_INTER_AS(mtc->type)) + { + vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --%s", + ifp->name, VTY_NEWLINE); + } + else + { + /* MPLS-TE is not activate on this interface */ + /* or this interface is passive and Inter-AS TEv2 is not activate */ + vty_out (vty, " %s: MPLS-TE is disabled on this interface%s", + ifp->name, VTY_NEWLINE); + return; + } + } + else + { + vty_out (vty, "-- MPLS-TE link parameters for %s --%s", + ifp->name, VTY_NEWLINE); + } + + show_vty_subtlv_admin_grp (vty, &mtc->admin_grp); + + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + show_vty_subtlv_local_ipaddr (vty, &mtc->local_ipaddr); + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + show_vty_subtlv_rmt_ipaddr (vty, &mtc->rmt_ipaddr); + + show_vty_subtlv_max_bw (vty, &mtc->max_bw); + show_vty_subtlv_max_rsv_bw (vty, &mtc->max_rsv_bw); + show_vty_subtlv_unrsv_bw (vty, &mtc->unrsv_bw); + show_vty_subtlv_te_metric (vty, &mtc->te_metric); + + if (IS_INTER_AS(mtc->type)) + { + if (SUBTLV_TYPE(mtc->ras) != 0) + show_vty_subtlv_ras (vty, &mtc->ras); + if (SUBTLV_TYPE(mtc->rip) != 0) + show_vty_subtlv_rip (vty, &mtc->rip); + } + + show_vty_subtlv_av_delay (vty, &mtc->av_delay); + show_vty_subtlv_mm_delay (vty, &mtc->mm_delay); + show_vty_subtlv_delay_var (vty, &mtc->delay_var); + show_vty_subtlv_pkt_loss (vty, &mtc->pkt_loss); + show_vty_subtlv_res_bw (vty, &mtc->res_bw); + show_vty_subtlv_ava_bw (vty, &mtc->ava_bw); + show_vty_subtlv_use_bw (vty, &mtc->use_bw); + vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE); + } + else + { + vty_out (vty, " %s: MPLS-TE is disabled on this interface%s", + ifp->name, VTY_NEWLINE); + } + + return; +} + +DEFUN (show_isis_mpls_te_interface, + show_isis_mpls_te_interface_cmd, + "show isis mpls-te interface [INTERFACE]", + SHOW_STR + ISIS_STR + MPLS_TE_STR + "Interface information\n" + "Interface name\n") +{ + struct interface *ifp; + struct listnode *node; + + /* Show All Interfaces. */ + if (argc == 0) + { + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + show_mpls_te_sub (vty, ifp); + } + /* Interface name is specified. */ + else + { + if ((ifp = if_lookup_by_name (argv[0])) == NULL) + vty_out (vty, "No such interface name%s", VTY_NEWLINE); + else + show_mpls_te_sub (vty, ifp); + } + + return CMD_SUCCESS; +} + +/* Initialize MPLS_TE */ +void +isis_mpls_te_init (void) +{ + + zlog_debug("ISIS MPLS-TE: Initialize"); + + /* Initialize MPLS_TE structure */ + isisMplsTE.status = disable; + isisMplsTE.level = 0; + isisMplsTE.inter_as = off; + isisMplsTE.interas_areaid.s_addr = 0; + isisMplsTE.cir_list = list_new(); + isisMplsTE.router_id.s_addr = 0; + + /* Register new VTY commands */ + install_element (VIEW_NODE, &show_isis_mpls_te_router_cmd); + install_element (VIEW_NODE, &show_isis_mpls_te_interface_cmd); + install_element (ENABLE_NODE, &show_isis_mpls_te_router_cmd); + install_element (ENABLE_NODE, &show_isis_mpls_te_interface_cmd); + + install_element (ISIS_NODE, &isis_mpls_te_on_cmd); + install_element (ISIS_NODE, &no_isis_mpls_te_on_cmd); + install_element (ISIS_NODE, &isis_mpls_te_router_addr_cmd); + install_element (ISIS_NODE, &isis_mpls_te_inter_as_cmd); + install_element (ISIS_NODE, &no_isis_mpls_te_inter_as_cmd); + + return; +} diff --git a/isisd/isis_te.h b/isisd/isis_te.h new file mode 100644 index 0000000000..4cec1735ae --- /dev/null +++ b/isisd/isis_te.h @@ -0,0 +1,331 @@ +/* + * IS-IS Rout(e)ing protocol - isis_te.c + * + * This is an implementation of RFC5305, RFC 5307 and draft-ietf-isis-te-metric-extensions-11 + * + * Copyright (C) 2014 Orange Labs + * http://www.orange.com + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_ISIS_MPLS_TE_H +#define _ZEBRA_ISIS_MPLS_TE_H + +/* + * Traffic Engineering information are transport through LSP: + * - Extended IS Reachability TLV = 22 + * - Traffic Engineering Router ID TLV = 134 + * - Extended IP Reachability TLV = 135 + * - Inter-AS Reachability Information TLV = 141 + * + * and support following sub-TLV: + * + * Name Value Status + * _________________________________________________ + * Administartive group (color) 3 RFC5305 + * Link Local/Remote Identifiers 4 RFC5307 + * IPv4 interface address 6 RFC5305 + * IPv4 neighbor address 8 RFC5305 + * Maximum link bandwidth 9 RFC5305 + * Reservable link bandwidth 10 RFC5305 + * Unreserved bandwidth 11 RFC5305 + * TE Default metric 18 RFC5305 + * Link Protection Type 20 RFC5307 + * Interface Switching Capability 21 RFC5307 + * Remote AS number 24 RFC5316 + * IPv4 Remote ASBR identifier 25 RFC5316 + * + */ + +/* NOTE: RFC5316 is not yet supported in this version */ + +/* Following define the type of TE link regarding the various RFC */ +#define STD_TE 0x01 +#define GMPLS 0x02 +#define INTER_AS 0x04 +#define FLOOD_L1 0x10 +#define FLOOD_L2 0x20 +#define FLOOD_AS 0x40 +#define EMULATED 0x80 + +#define IS_STD_TE(x) (x & STD_TE) +#define IS_INTER_AS(x) (x & INTER_AS) +#define IS_EMULATED(x) (x & EMULATED) +#define IS_FLOOD_L1(x) (x & FLOOD_L1) +#define IS_FLOOD_L2(x) (x & FLOOD_L2) +#define IS_FLOOD_AS(x) (x & FLOOD_AS) +#define IS_INTER_AS_EMU(x) (x & INTER_AS & EMULATED) +#define IS_INTER_AS_AS(x) (x & INTER_AS & FLOOD_AS) + +/* + * Following section defines subTLV (tag, length, value) structures, + * used for Traffic Engineering. + */ +struct subtlv_header +{ + u_char type; /* sub_TLV_XXX type (see above) */ + u_char length; /* Value portion only, in byte */ +}; + +#define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */ + +#define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length) + +#define SUBTLV_HDR_TOP(lsph) (struct subtlv_header *)((char *)(lsph) + ISIS_LSP_HEADER_SIZE) + +#define SUBTLV_HDR_NEXT(stlvh) (struct subtlv_header *)((char *)(stlvh) + SUBTLV_SIZE(stlvh)) + +#define SUBTLV_TYPE(stlvh) stlvh.header.type +#define SUBTLV_LEN(stlvh) stlvh.header.length +#define SUBTLV_VAL(stlvh) stlvh.value +#define SUBTLV_DATA(stlvh) stlvh + SUBTLV_HDR_SIZE + +#define SUBTLV_DEF_SIZE 4 + +/* Link Sub-TLV: Resource Class/Color - RFC 5305 */ +#define TE_SUBTLV_ADMIN_GRP 3 +struct te_subtlv_admin_grp +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Admin. group membership. */ +} __attribute__((__packed__)); + +/* Link Local/Remote Identifiers - RFC 5307 */ +#define TE_SUBTLV_LLRI 4 +#define TE_SUBTLV_LLRI_SIZE 8 +struct te_subtlv_llri +{ + struct subtlv_header header; /* Value length is 8 octets. */ + u_int32_t local; /* Link Local Identifier */ + u_int32_t remote; /* Link Remote Identifier */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Local Interface IP Address - RFC 5305 */ +#define TE_SUBTLV_LOCAL_IPADDR 6 +struct te_subtlv_local_ipaddr +{ + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Local IP address(es). */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Neighbor Interface IP Address - RFC 5305 */ +#define TE_SUBTLV_RMT_IPADDR 8 +struct te_subtlv_rmt_ipaddr +{ + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Neighbor's IP address(es). */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Maximum Bandwidth - RFC 5305 */ +#define TE_SUBTLV_MAX_BW 9 +struct te_subtlv_max_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Maximum Reservable Bandwidth - RFC 5305 */ +#define TE_SUBTLV_MAX_RSV_BW 10 +struct te_subtlv_max_rsv_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unreserved Bandwidth - RFC 5305 */ +#define TE_SUBTLV_UNRSV_BW 11 +#define TE_SUBTLV_UNRSV_SIZE 32 +struct te_subtlv_unrsv_bw +{ + struct subtlv_header header; /* Value length is 32 octets. */ + float value[8]; /* One for each priority level. */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Traffic Engineering Metric - RFC 5305 */ +#define TE_SUBTLV_TE_METRIC 18 +#define TE_SUBTLV_TE_METRIC_SIZE 3 +struct te_subtlv_te_metric +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_char value[3]; /* Link metric for TE purpose. */ +} __attribute__((__packed__)); + +/* Remote AS Number sub-TLV - RFC5316 */ +#define TE_SUBTLV_RAS 24 +struct te_subtlv_ras +{ + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Remote AS number */ +} __attribute__((__packed__)); + +/* IPv4 Remote ASBR ID Sub-TLV - RFC5316 */ +#define TE_SUBTLV_RIP 25 +struct te_subtlv_rip +{ + struct subtlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Remote ASBR IP address */ +} __attribute__((__packed__)); + + +/* draft-ietf-isis-te-metric-extensions-11.txt */ +/* Link Sub-TLV: Average Link Delay */ +#define TE_SUBTLV_AV_DELAY 33 +struct te_subtlv_av_delay +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* Average delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit (A) as Upper most bit */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Low/High Link Delay */ +#define TE_SUBTLV_MM_DELAY 34 +#define TE_SUBTLV_MM_DELAY_SIZE 8 +struct te_subtlv_mm_delay +{ + struct subtlv_header header; /* Value length is 8 bytes. */ + u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit (A) as Upper most bit */ + u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Link Delay Variation i.e. Jitter */ +#define TE_SUBTLV_DELAY_VAR 35 +struct te_subtlv_delay_var +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... 16777215 */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */ +#define TE_SUBTLV_PKT_LOSS 36 +struct te_subtlv_pkt_loss +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* in percentage of total traffic only 24 bits (2^24 - 2) + with Anomalous Bit (A) as Upper most bit */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */ +#define TE_SUBTLV_RES_BW 37 +struct te_subtlv_res_bw +{ + struct subtlv_header header; /* Value length is 4 bytes. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */ +#define TE_SUBTLV_AVA_BW 38 +struct te_subtlv_ava_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */ +#define TE_SUBTLV_USE_BW 39 +struct te_subtlv_use_bw +{ + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +} __attribute__((__packed__)); + +#define TE_SUBTLV_MAX 40 /* Last SUBTLV + 1 */ + +/* Following declaration concerns the MPLS-TE and LINk-TE management */ +typedef enum _status_t { disable, enable, learn } status_t; + +/* Mode for Inter-AS LSP */ /* TODO: Check how if LSP is flooded in RFC5316 */ +typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t; + +#define IS_MPLS_TE(m) (m.status == enable) +#define IS_CIRCUIT_TE(c) (c->status == enable) + +/* Following structure are internal use only. */ +struct isis_mpls_te +{ + /* Status of MPLS-TE: enable or disable */ + status_t status; + + /* L1, L1-L2, L2-Only */ + u_int8_t level; + + /* RFC5316 */ + interas_mode_t inter_as; + struct in_addr interas_areaid; + + /* Circuit list on which TE are enable */ + struct list *cir_list; + + /* MPLS_TE router ID */ + struct in_addr router_id; +}; + +extern struct isis_mpls_te isisMplsTE; + +struct mpls_te_circuit +{ + + /* Status of MPLS-TE on this interface */ + status_t status; + + /* Type of MPLS-TE circuit: STD_TE(RFC5305), INTER_AS(RFC5316), INTER_AS_EMU(RFC5316 emulated) */ + u_int8_t type; + + /* Total size of sub_tlvs */ + u_char length; + + /* Store subTLV in network byte order. */ + /* RFC5305 */ + struct te_subtlv_admin_grp admin_grp; + /* RFC5307 */ + struct te_subtlv_llri llri; + /* RFC5305 */ + struct te_subtlv_local_ipaddr local_ipaddr; + struct te_subtlv_rmt_ipaddr rmt_ipaddr; + struct te_subtlv_max_bw max_bw; + struct te_subtlv_max_rsv_bw max_rsv_bw; + struct te_subtlv_unrsv_bw unrsv_bw; + struct te_subtlv_te_metric te_metric; + /* RFC5316 */ + struct te_subtlv_ras ras; + struct te_subtlv_rip rip; + /* draft-ietf-isis-te-metric-extension */ + struct te_subtlv_av_delay av_delay; + struct te_subtlv_mm_delay mm_delay; + struct te_subtlv_delay_var delay_var; + struct te_subtlv_pkt_loss pkt_loss; + struct te_subtlv_res_bw res_bw; + struct te_subtlv_ava_bw ava_bw; + struct te_subtlv_use_bw use_bw; +}; + +/* Prototypes. */ +void isis_mpls_te_init (void); +struct mpls_te_circuit *mpls_te_circuit_new(void); +void mpls_te_print_detail(struct vty *, struct te_is_neigh *); +void set_circuitparams_local_ipaddr (struct mpls_te_circuit *, struct in_addr); +void set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *, struct in_addr); +u_char subtlvs_len (struct mpls_te_circuit *); +u_char add_te_subtlvs(u_char *, struct mpls_te_circuit *); +u_char build_te_subtlvs(u_char *, struct isis_circuit *); +void isis_link_params_update(struct isis_circuit *, struct interface *); +void isis_mpls_te_update(struct interface *); +void isis_mpls_te_config_write_router (struct vty *); + +#endif /* _ZEBRA_ISIS_MPLS_TE_H */ diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c index b4017b5f45..1d29d78287 100644 --- a/isisd/isis_tlv.c +++ b/isisd/isis_tlv.c @@ -42,6 +42,7 @@ #include "isisd/isis_misc.h" #include "isisd/isis_pdu.h" #include "isisd/isis_lsp.h" +#include "isisd/isis_te.h" void free_tlv (void *val) @@ -229,9 +230,23 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, while (length > value_len) { te_is_nei = (struct te_is_neigh *) pnt; - value_len += 11; - pnt += 11; - /* FIXME - subtlvs are handled here, for now we skip */ + value_len += IS_NEIGHBOURS_LEN; + pnt += IS_NEIGHBOURS_LEN; + /* FIXME - subtlvs are handled here, for now we skip */ + /* FIXME: All TE SubTLVs are not necessary present in LSP PDU. */ + /* So, it must be copied in a new te_is_neigh structure */ + /* rather than just initialize pointer to the original LSP PDU */ + /* to avoid consider the rest of lspdu as subTLVs or buffer overflow */ + if (IS_MPLS_TE(isisMplsTE)) + { + struct te_is_neigh *new = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh)); + memcpy(new->neigh_id, te_is_nei->neigh_id, ISIS_SYS_ID_LEN + 1); + memcpy(new->te_metric, te_is_nei->te_metric, 3); + new->sub_tlvs_length = te_is_nei->sub_tlvs_length; + memcpy(new->sub_tlvs, pnt, te_is_nei->sub_tlvs_length); + te_is_nei = new; + } + /* Skip SUB TLVs payload */ value_len += te_is_nei->sub_tlvs_length; pnt += te_is_nei->sub_tlvs_length; @@ -845,8 +860,8 @@ tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream) for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh)) { - /* FIXME: This will be wrong if we are going to add TE sub TLVs. */ - if (pos - value + IS_NEIGHBOURS_LEN > 255) + /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */ + if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255) { retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); if (retval != ISIS_OK) @@ -858,9 +873,15 @@ tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream) pos += ISIS_SYS_ID_LEN + 1; memcpy (pos, te_is_neigh->te_metric, 3); pos += 3; - /* Sub TLVs length. */ - *pos = 0; + /* Set the total size of Sub TLVs */ + *pos = te_is_neigh->sub_tlvs_length; pos++; + /* Copy Sub TLVs if any */ + if (te_is_neigh->sub_tlvs_length > 0) + { + memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length); + pos += te_is_neigh->sub_tlvs_length; + } } return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h index 619003a0e3..5a39d564dc 100644 --- a/isisd/isis_tlv.h +++ b/isisd/isis_tlv.h @@ -39,7 +39,7 @@ * LSP Entries 9 n n y ISO10589 * Authentication 10 y y y ISO10589, RFC3567 * Checksum 12 y n y RFC3358 - * TE IS Reachability 22 n y n RFC5305 + * Extended IS Reachability 22 n y n RFC5305 * IS Alias 24 n y n RFC3786 * IP Int. Reachability 128 n y n RFC1195 * Protocols Supported 129 y y n RFC1195 @@ -50,6 +50,7 @@ * Extended IP Reachability 135 n y n RFC5305 * Dynamic Hostname 137 n y n RFC2763 * Shared Risk Link Group 138 n y y RFC5307 + * Inter-AS Reachability 141 n y n RFC5316 * Restart TLV 211 y n n RFC3847 * MT IS Reachability 222 n y n RFC5120 * MT Supported 229 y y n RFC5120 @@ -59,10 +60,10 @@ * MT IPv6 IP Reachability 237 n y n RFC5120 * P2P Adjacency State 240 y n n RFC3373 * IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence - * Router Capability 242 - - - draft-ietf-isis-caps + * Router Capability 242 n y n RFC4971 * * - * IS Reachability sub-TLVs we (should) support. + * IS Reachability sub-TLVs we support (See isis_te.[c,h]) * ____________________________________________________________________________ * Name Value Status * ____________________________________________________________________________ @@ -76,6 +77,8 @@ * TE Default metric 18 RFC5305 * Link Protection Type 20 RFC5307 * Interface Switching Capability 21 RFC5307 + * Remote AS number 24 RFC5316 + * IPv4 Remote ASBR identifier 25 RFC5316 * * * IP Reachability sub-TLVs we (should) support. @@ -109,6 +112,7 @@ #define IPV6_ADDR 232 #define IPV6_REACHABILITY 236 #define WAY3_HELLO 240 +#define ROUTER_INFORMATION 242 #define AUTH_INFO_HDRLEN 3 @@ -121,6 +125,8 @@ #define IPV6_REACH_LEN 22 #define TE_IPV4_REACH_LEN 9 +#define MAX_SUBTLV_SIZE 256 + /* struct for neighbor */ struct is_neigh { @@ -128,12 +134,18 @@ struct is_neigh u_char neigh_id[ISIS_SYS_ID_LEN + 1]; }; -/* struct for te is neighbor */ +/* struct for te metric */ struct te_is_neigh { u_char neigh_id[ISIS_SYS_ID_LEN + 1]; u_char te_metric[3]; u_char sub_tlvs_length; + /* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8 bits */ + /* Practically, 118 bytes are necessary to store all supported TE parameters */ + /* FIXME: A pointer will use less memory, but need to be free */ + /* which is hard to fix, especially within free_tlvs() function */ + /* and malloc() / free() as a CPU cost compared to the memory usage */ + u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */ }; /* Decode and encode three-octet metric into host byte order integer */ diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 0e5a7ff3b7..569ff70d8d 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -49,6 +49,7 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" +#include "isisd/isis_te.h" struct zclient *zclient = NULL; @@ -61,6 +62,13 @@ isis_router_id_update_zebra (int command, struct zclient *zclient, struct listnode *node; struct prefix router_id; + /* + * If ISIS TE is enable, TE Router ID is set through specific command. + * See mpls_te_router_addr() command in isis_te.c + */ + if (IS_MPLS_TE(isisMplsTE)) + return 0; + zebra_router_id_update_read (zclient->ibuf, &router_id); if (isis->router_id == router_id.u.prefix4.s_addr) return 0; @@ -228,6 +236,23 @@ isis_zebra_if_address_del (int command, struct zclient *client, return 0; } +static int +isis_zebra_link_params (int command, struct zclient *zclient, + zebra_size_t length) +{ + struct interface *ifp; + + ifp = zebra_interface_link_params_read (zclient->ibuf); + + if (ifp == NULL) + return 0; + + /* Update TE TLV */ + isis_mpls_te_update(ifp); + + return 0; +} + static void isis_zebra_route_add_ipv4 (struct prefix *prefix, struct isis_route_info *route_info) @@ -680,6 +705,7 @@ isis_zebra_init (struct thread_master *master) zclient->interface_down = isis_zebra_if_state_down; zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_delete = isis_zebra_if_address_del; + zclient->interface_link_params = isis_zebra_link_params; zclient->ipv4_route_add = isis_zebra_read_ipv4; zclient->ipv4_route_delete = isis_zebra_read_ipv4; zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; diff --git a/isisd/isisd.c b/isisd/isisd.c index 0d0b805a20..5a90115127 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -54,6 +54,7 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" +#include "isisd/isis_te.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -98,6 +99,7 @@ isis_new (unsigned long process_id) * uncomment the next line for full debugs */ /* isis->debugs = 0xFFFF; */ + isisMplsTE.status = disable; /* Only support TE metric */ } struct isis_area * @@ -781,14 +783,16 @@ print_debug (struct vty *vty, int flags, int onoff) } DEFUN (show_debugging, - show_debugging_cmd, + show_debugging_isis_cmd, "show debugging isis", SHOW_STR "State of each debugging option\n" ISIS_STR) { - vty_out (vty, "IS-IS:%s", VTY_NEWLINE); - print_debug (vty, isis->debugs, 1); + if (isis->debugs) { + vty_out (vty, "IS-IS:%s", VTY_NEWLINE); + print_debug (vty, isis->debugs, 1); + } return CMD_SUCCESS; } @@ -2282,6 +2286,7 @@ isis_config_write (struct vty *vty) #endif /* TOPOLOGY_GENERATE */ } + isis_mpls_te_config_write_router(vty); } return write; @@ -2336,7 +2341,7 @@ isis_init () install_element (ENABLE_NODE, &show_database_arg_detail_cmd); install_element (ENABLE_NODE, &show_database_detail_cmd); install_element (ENABLE_NODE, &show_database_detail_arg_cmd); - install_element (ENABLE_NODE, &show_debugging_cmd); + install_element (ENABLE_NODE, &show_debugging_isis_cmd); install_node (&debug_node, config_write_debug); diff --git a/isisd/isisd.h b/isisd/isisd.h index 69a0100d50..9a4f360a2b 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -197,4 +197,8 @@ extern struct thread_master *master; } \ while (0) +#define DEBUG_TE (1<<13) + +#define IS_DEBUG_ISIS(x) (isis->debugs & x) + #endif /* ISISD_H */ From 4b547606e8dfc4bbc883ff797e116f43077b68bf Mon Sep 17 00:00:00 2001 From: Olivier Dugeon Date: Tue, 19 Apr 2016 19:18:18 +0200 Subject: [PATCH 182/226] Update documentation for Traffic Engineering Signed-off-by: Olivier Dugeon --- doc/install.texi | 11 +- doc/isisd.texi | 432 ++++++++++++++++++++++++++++++++++ doc/main.texi | 75 +++++- doc/mpls/ChangeLog.opaque.txt | 13 + doc/mpls/ospfd.conf | 1 + doc/ospfd.texi | 203 ++++++++++++++++ doc/quagga.texi | 2 + 7 files changed, 729 insertions(+), 8 deletions(-) create mode 100644 doc/isisd.texi diff --git a/doc/install.texi b/doc/install.texi index 7349e92cbe..811ad9ae89 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -83,8 +83,17 @@ OSPF-API is enabled if --enable-opaque-lsa is set. @item --disable-ospfclient Disable building of the example OSPF-API client. @item --disable-ospf-te -Disable support for OSPF Traffic Engineering Extension (internet-draft) this +Disable support for OSPF Traffic Engineering Extension (RFC3630) this requires support for Opaque LSAs. +@item --disable-ospf-ri +Disable support for OSPF Router Information (RFC4970 & RFC5088) this +requires support for Opaque LSAs and Traffic Engineering. +@item --enable-isisd +Build isisd. +@item --enable-isis-topology +Enable IS-IS topology generator. +@item --enable-isis-te +Enable Traffic Engineering Extension for ISIS (RFC5305) @item --enable-multipath=@var{ARG} Enable support for Equal Cost Multipath. @var{ARG} is the maximum number of ECMP paths to allow, set to 0 to allow unlimited number of paths. diff --git a/doc/isisd.texi b/doc/isisd.texi new file mode 100644 index 0000000000..bbc2896755 --- /dev/null +++ b/doc/isisd.texi @@ -0,0 +1,432 @@ +@cindex ISIS +@node ISIS +@chapter ISIS + +@acronym{ISIS,Intermediate System to Intermediate System} is a routing protocol +which is described in @cite{ISO10589, RFC1195, RFC5308}. ISIS is an +@acronym{IGP,Interior Gateway Protocol}. Compared with @acronym{RIP}, +@acronym{ISIS} can provide scalable network support and faster +convergence times like @acronym{OSPF}. ISIS is widely used in large networks such as +@acronym{ISP,Internet Service Provider} and carrier backbone networks. + +@menu +* Configuring isisd:: +* ISIS router:: +* ISIS Timer:: +* ISIS region:: +* ISIS interface:: +* Showing ISIS information:: +* ISIS Traffic Engineering:: +* Debugging ISIS:: +* ISIS Configuration Examples:: +@end menu + +@node Configuring isisd +@section Configuring isisd + +There are no @command{isisd} specific options. Common options can be +specified (@pxref{Common Invocation Options}) to @command{isisd}. +@command{isisd} needs to acquire interface information from +@command{zebra} in order to function. Therefore @command{zebra} must be +running before invoking @command{isisd}. Also, if @command{zebra} is +restarted then @command{isisd} must be too. + +Like other daemons, @command{isisd} configuration is done in @acronym{ISIS} +specific configuration file @file{isisd.conf}. + +@node ISIS router +@section ISIS router + +To start ISIS process you have to specify the ISIS router. As of this +writing, @command{isisd} does not support multiple ISIS processes. + +@deffn Command {router isis WORD} {} +@deffnx Command {no router isis WORD} {} +@anchor{router isis WORD}Enable or disable the ISIS process by specifying the ISIS domain with 'WORD'. +@command{isisd} does not yet support multiple ISIS processes but you must specify +the name of ISIS process. The ISIS process name 'WORD' is then used for interface +(see command @ref{ip router isis WORD}). +@end deffn + +@deffn {ISIS Command} {net XX.XXXX. ... .XXX.XX} {} +@deffnx {ISIS Command} {no net XX.XXXX. ... .XXX.XX} {} +Set/Unset network entity title (NET) provided in ISO format. +@end deffn + +@deffn {ISIS Command} {hostname dynamic} {} +@deffnx {ISIS Command} {no hostname dynamic} {} +Enable support for dynamic hostname. +@end deffn + +@deffn {ISIS Command} {area-password [clear | md5] } {} +@deffnx {ISIS Command} {domain-password [clear | md5] } {} +@deffnx {ISIS Command} {no area-password} {} +@deffnx {ISIS Command} {no domain-password} {} +Configure the authentication password for an area, respectively a domain, +as clear text or md5 one. +@end deffn + +@deffn {ISIS Command} {log-adjacency-changes} {} +@deffnx {ISIS Command} {no log-adjacency-changes} {} +Log changes in adjacency state. +@end deffn + +@deffn {ISIS Command} {metric-style [narrow | transition | wide]} {} +@deffnx {ISIS Command} {no metric-style} {} +@anchor{metric-style}Set old-style (ISO 10589) or new-style packet formats: + - narrow Use old style of TLVs with narrow metric + - transition Send and accept both styles of TLVs during transition + - wide Use new style of TLVs to carry wider metric +@end deffn + +@deffn {ISIS Command} {set-overload-bit} {} +@deffnx {ISIS Command} {no set-overload-bit} {} +Set overload bit to avoid any transit traffic. +@end deffn + +@node ISIS Timer +@section ISIS Timer + +@deffn {ISIS Command} {lsp-gen-interval <1-120>} {} +@deffnx {ISIS Command} {lsp-gen-interval [level-1 | level-2] <1-120>} {} +@deffnx {ISIS Command} {no lsp-gen-interval} {} +@deffnx {ISIS Command} {no lsp-gen-interval [level-1 | level-2]} {} +Set minimum interval in seconds between regenerating same LSP, +globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {lsp-refresh-interval <1-65235>} {} +@deffnx {ISIS Command} {lsp-refresh-interval [level-1 | level-2] <1-65235>} {} +@deffnx {ISIS Command} {no lsp-refresh-interval} {} +@deffnx {ISIS Command} {no lsp-refresh-interval [level-1 | level-2]} {} +Set LSP refresh interval in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {lsp-refresh-interval <1-65235>} {} +@deffnx {ISIS Command} {lsp-refresh-interval [level-1 | level-2] <1-65235>} {} +@deffnx {ISIS Command} {no lsp-refresh-interval} {} +@deffnx {ISIS Command} {no lsp-refresh-interval [level-1 | level-2]} {} +Set LSP refresh interval in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {max-lsp-lifetime <360-65535>} {} +@deffnx {ISIS Command} {max-lsp-lifetime [level-1 | level-2] <360-65535>} {} +@deffnx {ISIS Command} {no max-lsp-lifetime} {} +@deffnx {ISIS Command} {no max-lsp-lifetime [level-1 | level-2]} {} +Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {ISIS Command} {spf-interval <1-120>} {} +@deffnx {ISIS Command} {spf-interval [level-1 | level-2] <1-120>} {} +@deffnx {ISIS Command} {no spf-interval} {} +@deffnx {ISIS Command} {no spf-interval [level-1 | level-2]} {} +Set minimum interval between consecutive SPF calculations in seconds. +@end deffn + +@node ISIS region +@section ISIS region + +@deffn {ISIS Command} {is-type [level-1 | level-1-2 | level-2-only]} {} +@deffnx {ISIS Command} {no is-type} {} +Define the ISIS router behavior: + - level-1 Act as a station router only + - level-1-2 Act as both a station router and an area router + - level-2-only Act as an area router only +@end deffn + +@node ISIS interface +@section ISIS interface + +@deffn {Interface Command} {ip router isis WORD} {} +@deffnx {Interface Command} {no ip router isis WORD} {} +@anchor{ip router isis WORD}Activate ISIS adjacency on this interface. Note that the name +of ISIS instance must be the same as the one used to configure the ISIS process +(see command @ref{router isis WORD}). +@end deffn + +@deffn {Interface Command} {isis circuit-type [level-1 | level-1-2 | level-2]} {} +@deffnx {Interface Command} {no isis circuit-type} {} +Configure circuit type for interface: + - level-1 Level-1 only adjacencies are formed + - level-1-2 Level-1-2 adjacencies are formed + - level-2-only Level-2 only adjacencies are formed +@end deffn + +@deffn {Interface Command} {isis csnp-interval <1-600>} {} +@deffnx {Interface Command} {isis csnp-interval <1-600> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis csnp-interval} {} +@deffnx {Interface Command} {no isis csnp-interval [level-1 | level-2]} {} +Set CSNP interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis hello padding} {} +Add padding to IS-IS hello packets. +@end deffn + +@deffn {Interface Command} {isis hello-interval <1-600>} {} +@deffnx {Interface Command} {isis hello-interval <1-600> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis hello-interval} {} +@deffnx {Interface Command} {no isis hello-interval [level-1 | level-2]} {} +Set Hello interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis hello-multiplier <2-100>} {} +@deffnx {Interface Command} {isis hello-multiplier <2-100> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis hello-multiplier} {} +@deffnx {Interface Command} {no isis hello-multiplier [level-1 | level-2]} {} +Set multiplier for Hello holding time globally, for an area (level-1) or a domain (level-2). +@end deffn + +@deffn {Interface Command} {isis metric [<0-255> | <0-16777215>]} {} +@deffnx {Interface Command} {isis metric [<0-255> | <0-16777215>] [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis metric} {} +@deffnx {Interface Command} {no isis metric [level-1 | level-2]} {} +Set default metric value globally, for an area (level-1) or a domain (level-2). +Max value depend if metric support narrow or wide value (see command @ref{metric-style}). +@end deffn + +@deffn {Interface Command} {isis network point-to-point} {} +@deffnx {Interface Command} {no isis network point-to-point} {} +Set network type to 'Point-to-Point' (broadcast by default). +@end deffn + +@deffn {Interface Command} {isis passive} {} +@deffnx {Interface Command} {no isis passive} {} +Configure the passive mode for this interface. +@end deffn + +@deffn {Interface Command} {isis password [clear | md5] } {} +@deffnx {Interface Command} {no isis password} {} +Configure the authentication password (clear or encoded text) for the interface. +@end deffn + +@deffn {Interface Command} {isis priority <0-127>} {} +@deffnx {Interface Command} {isis priority <0-127> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis priority} {} +@deffnx {Interface Command} {no isis priority [level-1 | level-2]} {} +Set priority for Designated Router election, globally, for the area (level-1) +or the domain (level-2). +@end deffn + +@deffn {Interface Command} {isis psnp-interval <1-120>} {} +@deffnx {Interface Command} {isis psnp-interval <1-120> [level-1 | level-2]} {} +@deffnx {Interface Command} {no isis psnp-interval} {} +@deffnx {Interface Command} {no isis psnp-interval [level-1 | level-2]} {} +Set PSNP interval in seconds globally, for an area (level-1) or a domain (level-2). +@end deffn + +@node Showing ISIS information +@section Showing ISIS information + +@deffn {Command} {show isis summary} {} +Show summary information about ISIS. +@end deffn + +@deffn {Command} {show isis hostname} {} +Show information about ISIS node. +@end deffn + +@deffn {Command} {show isis interface} {} +@deffnx {Command} {show isis interface detail} {} +@deffnx {Command} {show isis interface } {} +Show state and configuration of ISIS specified interface, or all +interfaces if no interface is given with or without details. +@end deffn + +@deffn {Command} {show isis neighbor} {} +@deffnx {Command} {show isis neighbor } {} +@deffnx {Command} {show isis neighbor detail} {} +Show state and information of ISIS specified neighbor, or all +neighbors if no system id is given with or without details. +@end deffn + +@deffn {Command} {show isis database} {} +@deffnx {Command} {show isis database [detail]} {} +@deffnx {Command} {show isis database [detail]} {} +@deffnx {Command} {show isis database detail } {} +Show the ISIS database globally, for a specific LSP id without or with details. +@end deffn + +@deffn {Command} {show isis topology} {} +@deffnx {Command} {show isis topology [level-1|level-2]} {} +Show topology IS-IS paths to Intermediate Systems, globally, +in area (level-1) or domain (level-2). +@end deffn + +@deffn {Command} {show ip route isis} {} +Show the ISIS routing table, as determined by the most recent SPF calculation. +@end deffn + +@node ISIS Traffic Engineering +@section Traffic Engineering + +@deffn {ISIS Command} {mpls-te on} {} +@deffnx {ISIS Command} {no mpls-te} {} +Enable Traffic Engineering LSP flooding. +@end deffn + +@deffn {ISIS Command} {mpls-te router-address } {} +@deffnx {ISIS Command} {no mpls-te router-address} {} +Configure stable IP address for MPLS-TE. +@end deffn + +@deffn {Command} {show isis mpls-te interface} {} +@deffnx {Command} {show isis mpls-te interface @var{interface}} {} +Show MPLS Traffic Engineering parameters for all or specified interface. +@end deffn + +@deffn {Command} {show isis mpls-te router} {} +Show Traffic Engineering router parameters. +@end deffn + +@node Debugging ISIS +@section Debugging ISIS + +@deffn {Command} {debug isis adj-packets} {} +@deffnx {Command} {no debug isis adj-packets} {} +IS-IS Adjacency related packets. +@end deffn + +@deffn {Command} {debug isis checksum-errors} {} +@deffnx {Command} {no debug isis checksum-errors} {} +IS-IS LSP checksum errors. +@end deffn + +@deffn {Command} {debug isis events} {} +@deffnx {Command} {no debug isis events} {} +IS-IS Events. +@end deffn + +@deffn {Command} {debug isis local-updates} {} +@deffnx {Command} {no debug isis local-updates} {} +IS-IS local update packets. +@end deffn + +@deffn {Command} {debug isis packet-dump} {} +@deffnx {Command} {no debug isis packet-dump} {} +IS-IS packet dump. +@end deffn + +@deffn {Command} {debug isis protocol-errors} {} +@deffnx {Command} {no debug isis protocol-errors} {} +IS-IS LSP protocol errors. +@end deffn + +@deffn {Command} {debug isis route-events} {} +@deffnx {Command} {no debug isis route-events} {} +IS-IS Route related events. +@end deffn + +@deffn {Command} {debug isis snp-packets} {} +@deffnx {Command} {no debug isis snp-packets} {} +IS-IS CSNP/PSNP packets. +@end deffn + +@deffn {Command} {debug isis spf-events} {} +@deffnx {Command} {debug isis spf-statistics} {} +@deffnx {Command} {debug isis spf-triggers} {} +@deffnx {Command} {no debug isis spf-events} {} +@deffnx {Command} {no debug isis spf-statistics} {} +@deffnx {Command} {no debug isis spf-triggers} {} +IS-IS Shortest Path First Events, Timing and Statistic Data +and triggering events. +@end deffn + +@deffn {Command} {debug isis update-packets} {} +@deffnx {Command} {no debug isis update-packets} {} +Update related packets. +@end deffn + +@deffn {Command} {show debugging isis} {} +Print which ISIS debug level is activate. +@end deffn + +@node ISIS Configuration Examples +@section ISIS Configuration Examples +A simple example, with MD5 authentication enabled: + +@example +@group +! +interface eth0 + ip router isis FOO + isis network point-to-point + isis circuit-type level-2-only +! +router isis FOO +net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00 + metric-style wide + is-type level-2-only +@end group +@end example + + +A Traffic Engineering configuration, with Inter-ASv2 support. + + - First, the 'zebra.conf' part: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/zebra.log +! +interface eth0 + ip address 10.2.2.2/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab +! +interface eth1 + ip address 10.1.1.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab + mpls-te neighbor 10.1.1.2 as 65000 +@end group +@end example + + - Then the 'isisd.conf' itself: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/isisd.log +! +! +interface eth0 + ip router isis FOO +! +interface eth1 + ip router isis FOO +! +! +router isis FOO + isis net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00 + mpls-te on + mpls-te router-address 10.1.1.1 +! +line vty +@end group +@end example diff --git a/doc/main.texi b/doc/main.texi index 4c11d2440d..29ed17c82b 100644 --- a/doc/main.texi +++ b/doc/main.texi @@ -42,6 +42,14 @@ When program terminates, retain routes added by zebra. @node Interface Commands @section Interface Commands +@menu +* Standard Commands:: +* Link Parameters Commands:: +@end menu + +@node Standard Commands +@subsection Standard Commands + @deffn Command {interface @var{ifname}} {} @end deffn @@ -74,18 +82,71 @@ Enable or disables multicast flag for the interface. @deffn {Interface Command} {bandwidth <1-10000000>} {} @deffnx {Interface Command} {no bandwidth <1-10000000>} {} -Set bandwidth value of the interface in kilobits/sec. This is for -calculating OSPF cost. This command does not affect the actual device +Set bandwidth value of the interface in kilobits/sec. This is for +calculating OSPF cost. This command does not affect the actual device configuration. @end deffn @deffn {Interface Command} {link-detect} {} @deffnx {Interface Command} {no link-detect} {} -Enable/disable link-detect on platforms which support this. Currently +Enable/disable link-detect on platforms which support this. Currently only Linux and Solaris, and only where network interface drivers support reporting link-state via the IFF_RUNNING flag. @end deffn +@node Link Parameters Commands +@subsection Link Parameters Commands + +@deffn {Interface Command} {link-params} {} +@deffnx {Interface Command} {no link-param} {} +Enter into the link parameters sub node. At least 'enable' must be set to activate the link parameters, +and consequently Traffic Engineering on this interface. MPLS-TE must be enable at the OSPF (@ref{OSPF Traffic Engineering}) +or ISIS (@ref{ISIS Traffic Engineering}) router level in complement to this. +Disable link parameters for this interface. +@end deffn + +Under link parameter statement, the following commands set the different TE values: + +@deffn link-params {enable} +Enable link parameters for this interface. +@end deffn + +@deffn link-params {metric <0-4294967295>} {} +@deffnx link-params {max-bw @var{bandwidth}} {} +@deffnx link-params {max-rsv-bw @var{bandwidth}} {} +@deffnx link-params {unrsv-bw <0-7> @var{bandwidth}} {} +@deffnx link-params {admin-grp @var{bandwidth}} {} +These commands specifies the Traffic Engineering parameters of the interface in conformity to RFC3630 (OSPF) +or RFC5305 (ISIS). +There are respectively the TE Metric (different from the OSPF or ISIS metric), Maximum Bandwidth (interface speed +by default), Maximum Reservable Bandwidth, Unreserved Bandwidth for each 0-7 priority and Admin Group (ISIS) or +Resource Class/Color (OSPF). + +Note that @var{bandwidth} are specified in IEEE floating point format and express in Bytes/second. +@end deffn + +@deffn link-param {delay <0-16777215> [min <0-16777215> | max <0-16777215>]} {} +@deffnx link-param {delay-variation <0-16777215>} {} +@deffnx link-param {packet-loss @var{percentage}} {} +@deffnx link-param {res-bw @var{bandwidth}} {} +@deffnx link-param {ava-bw @var{bandwidth}} {} +@deffnx link-param {use-bw @var{bandwidth}} {} +These command specifies additionnal Traffic Engineering parameters of the interface in conformity to +draft-ietf-ospf-te-metrics-extension-05.txt and draft-ietf-isis-te-metrics-extension-03.txt. There are +respectively the delay, jitter, loss, available bandwidth, reservable bandwidth and utilized bandwidth. + +Note that @var{bandwidth} are specified in IEEE floating point format and express in Bytes/second. +Delays and delay variation are express in micro-second (µs). Loss is specified in @var{percentage} ranging +from 0 to 50.331642% by step of 0.000003. +@end deffn + +@deffn link-param {neighbor as <0-65535>} {} +@deffnx link-param {no neighbor} {} +Specifies the remote ASBR IP address and Autonomous System (AS) number for InterASv2 link in OSPF (RFC5392). +Note that this option is not yet supported for ISIS (RFC5316). +@end deffn + + @node Static Route Commands @section Static Route Commands @@ -162,7 +223,7 @@ prevent traffic destined for a prefix to match less-specific routes (eg default) should the specified gateways not be reachable. Eg: @example -zebra> show ip route 10.0.0.0/8 +zebra> show ip route 10.0.0.0/8 Routing entry for 10.0.0.0/8 Known via "static", distance 1, metric 0 10.0.0.2 inactive @@ -182,7 +243,7 @@ These behave similarly to their ipv4 counterparts. @deffn Command {table @var{tableno}} {} Select the primary kernel routing table to be used. This only works for kernels supporting multiple routing tables (like GNU/Linux 2.2.x -and later). After setting @var{tableno} with this command, +and later). After setting @var{tableno} with this command, static routes defined after this are added to the specified table. @end deffn @@ -365,8 +426,8 @@ Display current routes which zebra holds in its database. @example @group -Router# show ip route -Codes: K - kernel route, C - connected, S - static, R - RIP, +Router# show ip route +Codes: K - kernel route, C - connected, S - static, R - RIP, B - BGP * - FIB route. K* 0.0.0.0/0 203.181.89.241 diff --git a/doc/mpls/ChangeLog.opaque.txt b/doc/mpls/ChangeLog.opaque.txt index 68ddf4c817..afcfaa3590 100644 --- a/doc/mpls/ChangeLog.opaque.txt +++ b/doc/mpls/ChangeLog.opaque.txt @@ -1,3 +1,16 @@ +----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- +Changes 2013.07.01 + +1. Feature enhancements + + 1.1 Update ospf_te.[c,h] in conformance to RFC3630 and clean the code. + Add new directive to enable MPLS-TE per interface instead of globally + + 1.2 Add support for RFC4970 "Router Information" and RFC5088 "PCE + Capabilities announcement". + + 1.3 Incorporate the mpls documentation into the main stream doc. + ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- * ----- Changes 2001.12.03 diff --git a/doc/mpls/ospfd.conf b/doc/mpls/ospfd.conf index 6be11f9120..2b15fa4d00 100644 --- a/doc/mpls/ospfd.conf +++ b/doc/mpls/ospfd.conf @@ -17,6 +17,7 @@ debug ospf packet all detail interface fxp0 ip ospf hello-interval 60 ip ospf dead-interval 240 + mpls-te on mpls-te link metric 999 mpls-te link max-bw 1.25e+06 mpls-te link max-rsv-bw 1.25e+06 diff --git a/doc/ospfd.texi b/doc/ospfd.texi index 45d1ad7cd2..96dffe0000 100644 --- a/doc/ospfd.texi +++ b/doc/ospfd.texi @@ -1,3 +1,4 @@ + @cindex OSPFv2 @node OSPFv2 @chapter OSPFv2 @@ -18,6 +19,9 @@ networks. * OSPF interface:: * Redistribute routes to OSPF:: * Showing OSPF information:: +* Opaque LSA:: +* OSPF Traffic Engineering:: +* Router Information:: * Debugging OSPF:: * OSPF Configuration Examples:: @end menu @@ -616,35 +620,137 @@ interfaces if no interface is given. Show the OSPF routing table, as determined by the most recent SPF calculation. @end deffn +@node Opaque LSA +@section Opaque LSA + +@deffn {OSPF Command} {ospf opaque-lsa} {} +@deffnx {OSPF Command} {capability opaque} {} +@deffnx {OSPF Command} {no ospf opaque-lsa} {} +@deffnx {OSPF Command} {no capability opaque} {} +@command{ospfd} support Opaque LSA (RFC2370) as fondment for MPLS Traffic Engineering LSA. Prior to used MPLS TE, opaque-lsa must be enable in the configuration file. Alternate command could be "mpls-te on" (@ref{OSPF Traffic Engineering}). +@end deffn + +@deffn {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external)} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id} adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) @var{link-state-id} self-originate} {} +@deffnx {Command} {show ip ospf database (opaque-link|opaque-area|opaque-external) self-originate} {} +Show Opaque LSA from the database. +@end deffn + +@node OSPF Traffic Engineering +@section Traffic Engineering + +@deffn {OSPF Command} {mpls-te on} {} +@deffnx {OSPF Command} {no mpls-te} {} +Enable Traffic Engineering LSA flooding. +@end deffn + +@deffn {OSPF Command} {mpls-te router-address } {} +@deffnx {OSPF Command} {no mpls-te} {} +Configure stable IP address for MPLS-TE. This IP address is then advertise in Opaque LSA Type-10 TLV=1 (TE) +option 1 (Router-Address). +@end deffn + +@deffn {OSPF Command} {mpls-te inter-as area |as} {} +@deffnx {OSPF Command} {no mpls-te inter-as} {} +Enable RFC5392 suuport - Inter-AS TE v2 - to flood Traffic Engineering parameters of Inter-AS link. +2 modes are supported: AREA and AS; LSA are flood in AREA with Opaque Type-10, +respectively in AS with Opaque Type-11. In all case, Opaque-LSA TLV=6. +@end deffn + +@deffn {Command} {show ip ospf mpls-te interface} {} +@deffnx {Command} {show ip ospf mpls-te interface @var{interface}} {} +Show MPLS Traffic Engineering parameters for all or specified interface. +@end deffn + +@deffn {Command} {show ip ospf mpls-te router} {} +Show Traffic Engineering router parameters. +@end deffn + +@node Router Information +@section Router Information + +@deffn {OSPF Command} {router-info [as | area ]} {} +@deffnx {OSPF Command} {no router-info} {} +Enable Router Information (RFC4970) LSA advertisement with AS scope (default) or Area scope flooding +when area is specified. +@end deffn + +@deffn {OSPF Command} {pce address } {} +@deffnx {OSPF Command} {no pce address} {} +@deffnx {OSPF Command} {pce domain as <0-65535>} {} +@deffnx {OSPF Command} {no pce domain as <0-65535>} {} +@deffnx {OSPF Command} {pce neighbor as <0-65535>} {} +@deffnx {OSPF Command} {no pce neighbor as <0-65535>} {} +@deffnx {OSPF Command} {pce flag BITPATTERN} {} +@deffnx {OSPF Command} {no pce flag} {} +@deffnx {OSPF Command} {pce scope BITPATTERN} {} +@deffnx {OSPF Command} {no pce scope} {} +The commands are conform to RFC 5088 and allow OSPF router announce Path Compuatation Elemenent (PCE) capabilities +through the Router Information (RI) LSA. Router Information must be enable prior to this. The command set/unset +respectively the PCE IP adress, Autonomous System (AS) numbers of controlled domains, neighbor ASs, flag and scope. +For flag and scope, please refer to RFC5088 for the BITPATTERN recognition. Multiple 'pce neighbor' command could +be specified in order to specify all PCE neighbours. +@end deffn + +@deffn {Command} {show ip ospf router-info} {} +Show Router Capabilities flag. +@end deffn +@deffn {Command} {show ip ospf router-info pce} {} +Show Router Capabilities PCE parameters. +@end deffn + @node Debugging OSPF @section Debugging OSPF @deffn {Command} {debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} @deffnx {Command} {no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} +Dump Packet for debugging @end deffn @deffn {Command} {debug ospf ism} {} @deffnx {Command} {debug ospf ism (status|events|timers)} {} @deffnx {Command} {no debug ospf ism} {} @deffnx {Command} {no debug ospf ism (status|events|timers)} {} +Show debug information of Interface State Machine @end deffn @deffn {Command} {debug ospf nsm} {} @deffnx {Command} {debug ospf nsm (status|events|timers)} {} @deffnx {Command} {no debug ospf nsm} {} @deffnx {Command} {no debug ospf nsm (status|events|timers)} {} +Show debug information of Network State Machine +@end deffn + +@deffn {Command} {debug ospf event} {} +@deffnx {Command} {no debug ospf event} {} +Show debug information of OSPF event +@end deffn + +@deffn {Command} {debug ospf nssa} {} +@deffnx {Command} {no debug ospf nssa} {} +Show debug information about Not So Stub Area @end deffn @deffn {Command} {debug ospf lsa} {} @deffnx {Command} {debug ospf lsa (generate|flooding|refresh)} {} @deffnx {Command} {no debug ospf lsa} {} @deffnx {Command} {no debug ospf lsa (generate|flooding|refresh)} {} +Show debug detail of Link State messages +@end deffn + +@deffn {Command} {debug ospf te} {} +@deffnx {Command} {no debug ospf te} {} +Show debug information about Traffic Engineering LSA @end deffn @deffn {Command} {debug ospf zebra} {} @deffnx {Command} {debug ospf zebra (interface|redistribute)} {} @deffnx {Command} {no debug ospf zebra} {} @deffnx {Command} {no debug ospf zebra (interface|redistribute)} {} +Show debug information of ZEBRA API @end deffn @deffn {Command} {show debugging ospf} {} @@ -702,3 +808,100 @@ router ospf ! @end group @end example + +A Traffic Engineering configuration, with Inter-ASv2 support. + + - First, the 'zebra.conf' part: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/zebra.log +! +interface eth0 + ip address 198.168.1.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab +! +interface eth1 + ip address 192.168.2.1/24 + mpls-te on + mpls-te link metric 10 + mpls-te link max-bw 1.25e+06 + mpls-te link max-rsv-bw 1.25e+06 + mpls-te link unrsv-bw 0 1.25e+06 + mpls-te link unrsv-bw 1 1.25e+06 + mpls-te link unrsv-bw 2 1.25e+06 + mpls-te link unrsv-bw 3 1.25e+06 + mpls-te link unrsv-bw 4 1.25e+06 + mpls-te link unrsv-bw 5 1.25e+06 + mpls-te link unrsv-bw 6 1.25e+06 + mpls-te link unrsv-bw 7 1.25e+06 + mpls-te link rsc-clsclr 0xab + mpls-te neighbor 192.168.2.2 as 65000 +@end group +@end example + + - Then the 'ospfd.conf' itself: + +@example +@group +hostname HOSTNAME +password PASSWORD +log file /var/log/ospfd.log +! +! +interface eth0 + ip ospf hello-interval 60 + ip ospf dead-interval 240 +! +interface eth1 + ip ospf hello-interval 60 + ip ospf dead-interval 240 +! +! +router ospf + ospf router-id 192.168.1.1 + network 192.168.0.0/16 area 1 + ospf opaque-lsa + mpls-te + mpls-te router-address 192.168.1.1 + mpls-te inter-as area 1 +! +line vty +@end group +@end example + +A router information example with PCE advsertisement: + +@example +@group +! +router ospf + ospf router-id 192.168.1.1 + network 192.168.0.0/16 area 1 + capability opaque + mpls-te + mpls-te router-address 192.168.1.1 + router-info area 0.0.0.1 + pce address 192.168.1.1 + pce flag 0x80 + pce domain as 65400 + pce neighbor as 65500 + pce neighbor as 65200 + pce scope 0x80 +! +@end group +@end example diff --git a/doc/quagga.texi b/doc/quagga.texi index 65089621a3..6831b30cdf 100644 --- a/doc/quagga.texi +++ b/doc/quagga.texi @@ -85,6 +85,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of * RIPng:: * OSPFv2:: * OSPFv3:: +* ISIS:: * BGP:: * Configuring Quagga as a Route Server:: * VTY shell:: @@ -109,6 +110,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of @include ripngd.texi @include ospfd.texi @include ospf6d.texi +@include isisd.texi @include bgpd.texi @include routeserver.texi @include vtysh.texi From 0ef4bcdca0861ac183e9cd73ee9dd68054993c15 Mon Sep 17 00:00:00 2001 From: Olivier Dugeon Date: Tue, 19 Apr 2016 19:21:17 +0200 Subject: [PATCH 183/226] Add support Router Capabilities support to OSPF This is an implementation of RFC4970 (Router Information) and RFC5088 (PCE Capabilities announcement) * ospfd/Makefile.am: Add new file ospf_ri.c and ospf_ri.h * ospfd/ospf_opaque.c: Add new Router Capabilities code point * ospfd/ospf_ri.[c,h]: Implementation of RFC4970 & RFC5088 Signed-off-by: Olivier Dugeon --- ospfd/Makefile.am | 6 +- ospfd/ospf_opaque.c | 9 + ospfd/ospf_ri.c | 1639 +++++++++++++++++++++++++++++++++++++++++++ ospfd/ospf_ri.h | 191 +++++ 4 files changed, 1842 insertions(+), 3 deletions(-) create mode 100644 ospfd/ospf_ri.c create mode 100644 ospfd/ospf_ri.h diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 9eb166a3d6..55f9bf2d8e 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -16,7 +16,7 @@ libospf_la_SOURCES = \ ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ - ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c \ + ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \ ospf_bfd.c ospfdheaderdir = $(pkgincludedir)/ospfd @@ -28,12 +28,12 @@ ospfdheader_HEADERS = \ noinst_HEADERS = \ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h \ + ospf_flood.h ospf_snmp.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ ospf_bfd.h ospfd_SOURCES = ospf_main.c -ospfd_LDADD = libospf.la ../lib/libzebra.la @LIBCAP@ +ospfd_LDADD = libospf.la ../lib/libzebra.la @LIBCAP@ @LIBM@ EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 8c6ec892c4..9b395b3e8e 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -62,6 +62,7 @@ *------------------------------------------------------------------------*/ #include "ospfd/ospf_te.h" +#include "ospfd/ospf_ri.h" #ifdef SUPPORT_OSPF_API int ospf_apiserver_init (void); @@ -87,6 +88,9 @@ ospf_opaque_init (void) if (ospf_mpls_te_init () != 0) exit (1); + if (ospf_router_info_init () != 0) + exit (1); + #ifdef SUPPORT_OSPF_API if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0)) exit (1); @@ -100,6 +104,8 @@ ospf_opaque_term (void) { ospf_mpls_te_term (); + ospf_router_info_term (); + #ifdef SUPPORT_OSPF_API ospf_apiserver_term (); #endif /* SUPPORT_OSPF_API */ @@ -216,6 +222,9 @@ ospf_opaque_type_name (u_char opaque_type) case OPAQUE_TYPE_INTER_AS_LSA: name = "Inter-AS TE-v2 LSA"; break; + case OPAQUE_TYPE_ROUTER_INFORMATION_LSA: + name = "Router Information LSA"; + break; default: if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type)) name = "Unassigned"; diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c new file mode 100644 index 0000000000..8fefd2bdb8 --- /dev/null +++ b/ospfd/ospf_ri.c @@ -0,0 +1,1639 @@ +/* + * This is an implementation of RFC4970 Router Information + * with support of RFC5088 PCE Capabilites announcement + * + * Module name: Router Information + * Version: 0.99.22 + * Created: 2012-02-01 by Olivier Dugeon + * Copyright (C) 2012 Orange Labs http://www.orange.com/ + * + * This file is part of GNU Quagga. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include + +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "memory.h" +#include "command.h" +#include "vty.h" +#include "stream.h" +#include "log.h" +#include "thread.h" +#include "hash.h" +#include "sockunion.h" /* for inet_aton() */ + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_spf.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" +#include "ospfd/ospf_ase.h" +#include "ospfd/ospf_zebra.h" +#include "ospfd/ospf_ri.h" +#include "ospfd/ospf_te.h" + +struct ospf_pce_info +{ + + /* Store Router Information PCE TLV and SubTLV in network byte order. */ + struct ri_tlv_pce pce_header; + struct ri_pce_subtlv_address pce_address; + struct ri_pce_subtlv_path_scope pce_scope; + struct list *pce_domain; + struct list *pce_neighbor; + struct ri_pce_subtlv_cap_flag pce_cap_flag; +}; + +/* Following structure are internal use only. */ +struct ospf_router_info +{ + status_t status; + + u_int8_t registered; + u_int8_t scope; + + /* Flags to manage this router information. */ +#define RIFLG_LOOKUP_DONE 0x1 +#define RIFLG_LSA_ENGAGED 0x2 +#define RIFLG_LSA_FORCED_REFRESH 0x4 + u_int32_t flags; + + /* area pointer if flooding is Type 10 Null if flooding is AS scope */ + struct ospf_area *area; + struct in_addr area_id; + + /* Store Router Information Capabilities LSA */ + struct ri_tlv_router_cap router_cap; + + /* Store PCE capability LSA */ + struct ospf_pce_info pce_info; +}; + +/* + * Global variable to manage Opaque-LSA/Router Information on this node. + * Note that all parameter values are stored in network byte order. + */ +static struct ospf_router_info OspfRI; + +/*------------------------------------------------------------------------------* + * Followings are initialize/terminate functions for Router Information handling. + *------------------------------------------------------------------------------*/ + +static void ospf_router_info_ism_change (struct ospf_interface *oi, + int old_status); +static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr, + int old_status); +static void ospf_router_info_config_write_router (struct vty *vty); +static void ospf_router_info_show_info (struct vty *vty, + struct ospf_lsa *lsa); +static int ospf_router_info_lsa_originate (void *arg); +static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa); +static void ospf_router_info_lsa_schedule (opcode_t opcode); +static void ospf_router_info_register_vty (void); +static void del_pce_info (void *val); + +int +ospf_router_info_init (void) +{ + + memset (&OspfRI, 0, sizeof (struct ospf_router_info)); + OspfRI.status = disabled; + OspfRI.registered = 0; + OspfRI.scope = OSPF_OPAQUE_AS_LSA; + OspfRI.flags = 0; + + /* Initialize pce domain and neighbor list */ + OspfRI.pce_info.pce_domain = list_new (); + OspfRI.pce_info.pce_domain->del = del_pce_info; + OspfRI.pce_info.pce_neighbor = list_new (); + OspfRI.pce_info.pce_neighbor->del = del_pce_info; + + ospf_router_info_register_vty (); + + return 0; +} + +static int +ospf_router_info_register (u_int8_t scope) +{ + int rc = 0; + + if (OspfRI.registered) + return 0; + + zlog_info ("Register Router Information with scope %s(%d)", + scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope); + rc = ospf_register_opaque_functab (scope, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA, + NULL, /* new interface */ + NULL, /* del interface */ + ospf_router_info_ism_change, + ospf_router_info_nsm_change, + ospf_router_info_config_write_router, + NULL, /* Config. write interface */ + NULL, /* Config. write debug */ + ospf_router_info_show_info, + ospf_router_info_lsa_originate, + ospf_router_info_lsa_refresh, + NULL, /* new_lsa_hook */ + NULL); /* del_lsa_hook */ + + if (rc != 0) + { + zlog_warn ("ospf_router_info_init: Failed to register functions"); + return rc; + } + + OspfRI.registered = 1; + OspfRI.scope = scope; + return 0; +} + +static int +ospf_router_info_unregister () +{ + + if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA) + && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) + { + zlog_warn ("Unable to unregister Router Info functions: Wrong scope!"); + return -1; + } + + ospf_delete_opaque_functab (OspfRI.scope, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + + OspfRI.registered = 0; + return 0; + +} + +void +ospf_router_info_term (void) +{ + + list_delete (OspfRI.pce_info.pce_domain); + list_delete (OspfRI.pce_info.pce_neighbor); + + OspfRI.pce_info.pce_domain = NULL; + OspfRI.pce_info.pce_neighbor = NULL; + OspfRI.status = disabled; + + ospf_router_info_unregister (); + + return; +} + +static void +del_pce_info (void *val) +{ + XFREE (MTYPE_OSPF_PCE_PARAMS, val); + return; +} + +/*------------------------------------------------------------------------* + * Followings are control functions for ROUTER INFORMATION parameters management. + *------------------------------------------------------------------------*/ + +static void +set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap) +{ + ric->header.type = htons (RI_TLV_CAPABILITIES); + ric->header.length = htons (RI_TLV_LENGTH); + ric->value = htonl (cap); + return; +} + +static int +set_pce_header (struct ospf_pce_info *pce) +{ + u_int16_t length = 0; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + /* PCE Address */ + if (ntohs (pce->pce_address.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_address.header); + + /* PCE Path Scope */ + if (ntohs (pce->pce_scope.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_scope.header); + + /* PCE Domain */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (ntohs (domain->header.type) != 0) + length += RI_TLV_SIZE (&domain->header); + } + + /* PCE Neighbor */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (ntohs (neighbor->header.type) != 0) + length += RI_TLV_SIZE (&neighbor->header); + } + + /* PCE Capabilities */ + if (ntohs (pce->pce_cap_flag.header.type) != 0) + length += RI_TLV_SIZE (&pce->pce_cap_flag.header); + + if (length != 0) + { + pce->pce_header.header.type = htons (RI_TLV_PCE); + pce->pce_header.header.length = htons (length); + } + else + { + pce->pce_header.header.type = 0; + pce->pce_header.header.length = 0; + } + + return length; +} + +static void +set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Address */ + pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS); + pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4); + pce->pce_address.address.value = ipv4; + + return; +} + +static void +set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Scope */ + pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE); + pce->pce_scope.header.length = htons (RI_TLV_LENGTH); + pce->pce_scope.value = htonl (scope); + + return; +} + +static void +set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + + struct ri_pce_subtlv_domain *new; + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + + /* Create new domain info */ + new = + XCALLOC (MTYPE_OSPF_PCE_PARAMS, + sizeof (struct ri_pce_subtlv_domain)); + + new->header.type = htons (RI_PCE_SUBTLV_DOMAIN); + new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + new->type = htons (type); + new->value = htonl (domain); + + /* Add new domain to the list */ + listnode_add (pce->pce_domain, new); + + return; +} + +static void +unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + struct listnode *node; + struct ri_pce_subtlv_domain *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old)) + { + if ((old->type == htons (type)) && (old->value == htonl (domain))) + { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) + { + listnode_delete (pce->pce_domain, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount (pce->pce_domain) == 0) + pce->pce_domain->head = pce->pce_domain->tail = NULL; + + /* Finally free the old domain */ + XFREE (MTYPE_OSPF_PCE_PARAMS, old); + } +} + +static void +set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +{ + + struct ri_pce_subtlv_neighbor *new; + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + + /* Create new neighbor info */ + new = + XCALLOC (MTYPE_OSPF_PCE_PARAMS, + sizeof (struct ri_pce_subtlv_neighbor)); + + new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR); + new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); + new->type = htons (type); + new->value = htonl (domain); + + /* Add new domain to the list */ + listnode_add (pce->pce_neighbor, new); + + return; +} + +static void +unset_pce_neighbor (u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) +{ + struct listnode *node; + struct ri_pce_subtlv_neighbor *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old)) + { + if ((old->type == htons (type)) && (old->value == htonl (domain))) + { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) + { + listnode_delete (pce->pce_neighbor, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount (pce->pce_neighbor) == 0) + pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL; + + /* Finally free the old domain */ + XFREE (MTYPE_OSPF_PCE_PARAMS, old); + } +} + +static void +set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce) +{ + + /* Enable PCE Info */ + pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Set PCE Capabilities flag */ + pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG); + pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH); + pce->pce_cap_flag.value = htonl (cap); + + return; +} + + +static void +unset_param (struct ri_tlv_header *tlv) +{ + + tlv->type = 0; + /* Fill the Value to 0 */ + memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv)); + tlv->length = 0; + + return; +} + +static void +initialize_params (struct ospf_router_info *ori) +{ + u_int32_t cap; + struct ospf *top; + + /* + * Initialize default Router Information Capabilities. + */ + cap = 0; + cap = cap | RI_TE_SUPPORT; + + set_router_info_capabilities (&ori->router_cap, cap); + + /* If Area address is not null and exist, retrieve corresponding structure */ + top = ospf_lookup (); + zlog_info ("RI-> Initialize Router Info for %s scope within area %s", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", + inet_ntoa (OspfRI.area_id)); + + /* Try to get the Area context at this step. Do it latter if not available */ + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) + OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); + + /* + * Initialize default PCE Information values + */ + /* PCE address == OSPF Router ID */ + set_pce_address (top->router_id, &ori->pce_info); + + /* PCE scope */ + cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */ + set_pce_path_scope (cap, &ori->pce_info); + + /* PCE Capabilities */ + cap = + PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES | + PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ; + set_pce_cap_flag (cap, &ori->pce_info); + + /* Finally compute PCE header */ + set_pce_header (&ori->pce_info); + + return; +} + +static int +is_mandated_params_set (struct ospf_router_info ori) +{ + int rc = 0; + + if (ntohs (ori.router_cap.header.type) == 0) + goto out; + + if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE) + && (ntohs (ori.pce_info.pce_address.header.type) == 0) + && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0)) + goto out; + + rc = 1; + +out: + return rc; +} + +/*------------------------------------------------------------------------* + * Followings are callback functions against generic Opaque-LSAs handling. + *------------------------------------------------------------------------*/ +static void +ospf_router_info_ism_change (struct ospf_interface *oi, int old_state) +{ + /* So far, nothing to do here. */ + return; + +} + +static void +ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state) +{ + + /* So far, nothing to do here. */ + return; +} + +/*------------------------------------------------------------------------* + * Followings are OSPF protocol processing functions for ROUTER INFORMATION + *------------------------------------------------------------------------*/ + +static void +build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh) +{ + + stream_put (s, tlvh, sizeof (struct ri_tlv_header)); + return; +} + +static void +build_tlv (struct stream *s, struct ri_tlv_header *tlvh) +{ + + if (ntohs (tlvh->type) != 0) + { + build_tlv_header (s, tlvh); + stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh)); + } + return; +} + +static void +ospf_router_info_lsa_body_set (struct stream *s) +{ + + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + /* Build Router Information TLV */ + build_tlv (s, &OspfRI.router_cap.header); + + /* Add RI PCE TLV if it is set */ + /* Compute PCE Info header first */ + if ((set_pce_header (&OspfRI.pce_info)) != 0) + { + + /* Build PCE TLV */ + build_tlv_header (s, &OspfRI.pce_info.pce_header.header); + + /* Build PCE address sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_address.header); + + /* Build PCE path scope sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_scope.header); + + /* Build PCE domain sub-tlv */ + for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain)) + build_tlv (s, &domain->header); + + /* Build PCE neighbor sub-tlv */ + for (ALL_LIST_ELEMENTS_RO + (OspfRI.pce_info.pce_neighbor, node, neighbor)) + build_tlv (s, &neighbor->header); + + /* Build PCE cap flag sub-tlv */ + build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header); + } + + return; +} + +/* Create new opaque-LSA. */ +static struct ospf_lsa * +ospf_router_info_lsa_new () +{ + struct ospf *top; + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new = NULL; + u_char options, lsa_type; + struct in_addr lsa_id; + u_int32_t tmp; + u_int16_t length; + + /* Create a stream for LSA. */ + if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: stream_new() ?"); + goto out; + } + lsah = (struct lsa_header *) STREAM_DATA (s); + + options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */ + options |= OSPF_OPTION_O; /* Don't forget this :-) */ + + lsa_type = OspfRI.scope; + /* LSA ID == 0 for Router Information see RFC 4970 */ + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsa_id.s_addr = htonl (tmp); + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_debug + ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance", + lsa_type, inet_ntoa (lsa_id)); + + top = ospf_lookup (); + + /* Set opaque-LSA header fields. */ + lsa_header_set (s, options, lsa_type, lsa_id, top->router_id); + + /* Set opaque-LSA body fields. */ + ospf_router_info_lsa_body_set (s); + + /* Set length. */ + length = stream_get_endp (s); + lsah->length = htons (length); + + /* Now, create an OSPF LSA instance. */ + if ((new = ospf_lsa_new ()) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?"); + stream_free (s); + goto out; + } + if ((new->data = ospf_lsa_data_new (length)) == NULL) + { + zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_unlock (&new); + new = NULL; + stream_free (s); + goto out; + } + + new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */ + + SET_FLAG (new->flags, OSPF_LSA_SELF); + memcpy (new->data, lsah, length); + stream_free (s); + +out:return new; +} + +static int +ospf_router_info_lsa_originate1 (void *arg) +{ + struct ospf_lsa *new; + struct ospf *top; + struct ospf_area *area; + int rc = -1; + + /* First check if the area is known if flooding scope is Area */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + { + area = (struct ospf_area *) arg; + if (area->area_id.s_addr != OspfRI.area_id.s_addr) + { + zlog_debug + ("RI -> This is not the Router Information Area. Stop processing"); + goto out; + } + OspfRI.area = area; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new ()) == NULL) + { + zlog_warn + ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?"); + goto out; + } + + /* Get ospf info */ + top = ospf_lookup (); + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) + { + zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?"); + ospf_lsa_unlock (&new); + goto out; + } + + /* Now this Router Info parameter entry has associated LSA. */ + SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED); + + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AS. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as (top, NULL /*nbr */ , new); + else + ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + + rc = 0; +out:return rc; +} + +static int +ospf_router_info_lsa_originate (void *arg) +{ + + int rc = -1; + + if (OspfRI.status == disabled) + { + zlog_info + ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + /* Check if Router Information LSA is already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + { + if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH) + { + OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH; + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + } + else + { + if (!is_mandated_params_set (OspfRI)) + zlog_warn + ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters"); + + /* Ok, let's try to originate an LSA */ + if (ospf_router_info_lsa_originate1 (arg) != 0) + goto out; + } + + rc = 0; +out:return rc; +} + +static struct ospf_lsa * +ospf_router_info_lsa_refresh (struct ospf_lsa *lsa) +{ + struct ospf_lsa *new = NULL; + struct ospf *top; + + if (OspfRI.status == disabled) + { + /* + * This LSA must have flushed before due to ROUTER INFORMATION status change. + * It seems a slip among routers in the routing domain. + */ + zlog_info + ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now."); + lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* Verify that the Router Information ID is supported */ + if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0) + { + zlog_warn + ("ospf_router_info_lsa_refresh: Unsupported Router Information ID"); + goto out; + } + + /* If the lsa's age reached to MaxAge, start flushing procedure. */ + if (IS_LSA_MAXAGE (lsa)) + { + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule (lsa); + goto out; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new ()) == NULL) + { + zlog_warn + ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?"); + goto out; + } + new->data->ls_seqnum = lsa_seqnum_increment (lsa); + + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + top = ospf_lookup (); + if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) + { + zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); + ospf_lsa_unlock (&new); + goto out; + } + + /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as (top, NULL /*nbr */ , new); + else + ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + +out:return new; +} + +static void +ospf_router_info_lsa_schedule (opcode_t opcode) +{ + struct ospf_lsa lsa; + struct lsa_header lsah; + struct ospf *top; + u_int32_t tmp; + + memset (&lsa, 0, sizeof (lsa)); + memset (&lsah, 0, sizeof (lsah)); + + zlog_debug ("RI-> LSA schedule %s%s%s", + opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "", + opcode == REFRESH_THIS_LSA ? "Refresh" : "", + opcode == FLUSH_THIS_LSA ? "Flush" : ""); + + top = ospf_lookup (); + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) + { + zlog_warn + ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); + OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); + } + lsa.area = OspfRI.area; + lsa.data = &lsah; + lsah.type = OspfRI.scope; + + /* LSA ID is set to 0 for the Router Information. See RFC 4970 */ + tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsah.id.s_addr = htonl (tmp); + + switch (opcode) + { + case REORIGINATE_THIS_LSA: + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area, + OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + else + ospf_opaque_lsa_reoriginate_schedule ((void *) top, + OSPF_OPAQUE_AS_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + break; + case REFRESH_THIS_LSA: + ospf_opaque_lsa_refresh_schedule (&lsa); + break; + case FLUSH_THIS_LSA: + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule (&lsa); + break; + default: + zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)", + opcode); + break; + } + + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty session control functions. + *------------------------------------------------------------------------*/ + +static u_int16_t +show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh; + + if (vty != NULL) + vty_out (vty, " Router Capabilities: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh; + + if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4) + { + if (vty != NULL) + vty_out (vty, " PCE Address: %s%s", inet_ntoa (top->address.value), + VTY_NEWLINE); + else + zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value)); + } + else + { + /* TODO: Add support to IPv6 with inet_ntop() */ + if (vty != NULL) + vty_out (vty, " PCE Address: 0x%x%s", + ntohl (top->address.value.s_addr), VTY_NEWLINE); + else + zlog_debug (" PCE Address: 0x%x", + ntohl (top->address.value.s_addr)); + } + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_path_scope *top = + (struct ri_pce_subtlv_path_scope *) tlvh; + + if (vty != NULL) + vty_out (vty, " PCE Path Scope: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh; + struct in_addr tmp; + + if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out (vty, " PCE domain Area: %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + else + zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp)); + } + else + { + if (vty != NULL) + vty_out (vty, " PCE domain AS: %d%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE domain AS: %d", ntohl (top->value)); + } + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh) +{ + + struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh; + struct in_addr tmp; + + if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out (vty, " PCE neighbor Area: %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + else + zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp)); + } + else + { + if (vty != NULL) + vty_out (vty, " PCE neighbor AS: %d%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE neighbor AS: %d", ntohl (top->value)); + } + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh) +{ + struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh; + + if (vty != NULL) + vty_out (vty, " PCE Capabilities Flag: 0x%x%s", ntohl (top->value), + VTY_NEWLINE); + else + zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh) +{ + if (vty != NULL) + vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s", + ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE); + else + zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", + ntohs (tlvh->type), ntohs (tlvh->length)); + + return RI_TLV_SIZE (tlvh); +} + +static u_int16_t +show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total) +{ + struct ri_tlv_header *tlvh; + u_int16_t sum = 0; + + for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh)) + { + switch (ntohs (tlvh->type)) + { + case RI_PCE_SUBTLV_ADDRESS: + sum += show_vty_pce_subtlv_address (vty, tlvh); + break; + case RI_PCE_SUBTLV_PATH_SCOPE: + sum += show_vty_pce_subtlv_path_scope (vty, tlvh); + break; + case RI_PCE_SUBTLV_DOMAIN: + sum += show_vty_pce_subtlv_domain (vty, tlvh); + break; + case RI_PCE_SUBTLV_NEIGHBOR: + sum += show_vty_pce_subtlv_neighbor (vty, tlvh); + break; + case RI_PCE_SUBTLV_CAP_FLAG: + sum += show_vty_pce_subtlv_cap_flag (vty, tlvh); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + return sum; +} + +static void +ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa) +{ + struct lsa_header *lsah = (struct lsa_header *) lsa->data; + struct ri_tlv_header *tlvh; + u_int16_t length = 0, sum = 0; + + /* Initialize TLV browsing */ + length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE; + + for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length; + tlvh = RI_TLV_HDR_NEXT (tlvh)) + { + switch (ntohs (tlvh->type)) + { + case RI_TLV_CAPABILITIES: + sum += show_vty_router_cap (vty, tlvh); + break; + case RI_TLV_PCE: + tlvh++; + sum += RI_TLV_HDR_SIZE; + sum += show_vty_pce_info (vty, tlvh, length - sum); + break; + default: + sum += show_vty_unknown_tlv (vty, tlvh); + break; + } + } + + return; +} + +static void +ospf_router_info_config_write_router (struct vty *vty) +{ + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + struct in_addr tmp; + + if (OspfRI.status == enabled) + { + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + vty_out (vty, " router-info as%s", VTY_NEWLINE); + else + vty_out (vty, " router-info area %s%s", inet_ntoa (OspfRI.area_id), + VTY_NEWLINE); + + if (pce->pce_address.header.type != 0) + vty_out (vty, " pce address %s%s", + inet_ntoa (pce->pce_address.address.value), VTY_NEWLINE); + + if (pce->pce_cap_flag.header.type != 0) + vty_out (vty, " pce flag 0x%x%s", ntohl (pce->pce_cap_flag.value), + VTY_NEWLINE); + + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (domain->header.type != 0) + { + if (domain->type == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = domain->value; + vty_out (vty, " pce domain area %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + } + else + { + vty_out (vty, " pce domain as %d%s", ntohl (domain->value), + VTY_NEWLINE); + } + } + } + + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (neighbor->header.type != 0) + { + if (neighbor->type == PCE_DOMAIN_TYPE_AREA) + { + tmp.s_addr = neighbor->value; + vty_out (vty, " pce neighbor area %s%s", inet_ntoa (tmp), + VTY_NEWLINE); + } + else + { + vty_out (vty, " pce neighbor as %d%s", + ntohl (neighbor->value), VTY_NEWLINE); + } + } + } + + if (pce->pce_scope.header.type != 0) + vty_out (vty, " pce scope 0x%x%s", + ntohl (OspfRI.pce_info.pce_scope.value), VTY_NEWLINE); + } + return; +} + +/*------------------------------------------------------------------------* + * Followings are vty command functions. + *------------------------------------------------------------------------*/ + +DEFUN (router_info, + router_info_area_cmd, + "router-info area A.B.C.D", + OSPF_RI_STR + "Enable the Router Information functionality with Area flooding scope\n" + "OSPF area ID in IP format") +{ + + u_int8_t scope; + + if (OspfRI.status == enabled) + return CMD_SUCCESS; + + /* Check and get Area value if present */ + if (argc == 1) + { + if (!inet_aton (argv[0], &OspfRI.area_id)) + { + vty_out (vty, "Please specify Router Info Area by A.B.C.D%s", + VTY_NEWLINE); + return CMD_WARNING; + } + scope = OSPF_OPAQUE_AREA_LSA; + } + else + { + OspfRI.area_id.s_addr = 0; + scope = OSPF_OPAQUE_AS_LSA; + } + + /* First start to register Router Information callbacks */ + if ((ospf_router_info_register (scope)) != 0) + { + zlog_warn ("Enable to register Router Information callbacks. Abort!"); + return CMD_WARNING; + } + + OspfRI.status = enabled; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS"); + + /* + * Following code is intended to handle two cases; + * + * 1) Router Information was disabled at startup time, but now become enabled. + * 2) Router Information was once enabled then disabled, and now enabled again. + */ + + initialize_params (&OspfRI); + + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + { + zlog_debug ("RI-> Initial origination following configuration"); + ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA); + } + return CMD_SUCCESS; + +} + +ALIAS (router_info, + router_info_as_cmd, + "router-info as", + OSPF_RI_STR + "Enable the Router Information functionality with AS flooding scope\n") + +DEFUN (no_router_info, + no_router_info_cmd, + "no router-info", + NO_STR + "Disable the Router Information functionality\n") +{ + + if (OspfRI.status == disabled) + return CMD_SUCCESS; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("RI-> Router Information: ON -> OFF"); + + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule (FLUSH_THIS_LSA); + + /* Unregister the callbacks */ + ospf_router_info_unregister (); + + OspfRI.status = disabled; + + return CMD_SUCCESS; +} + +DEFUN (pce_address, + pce_address_cmd, + "pce address A.B.C.D", + PCE_STR + "Stable IP address of the PCE\n" + "PCE address in IPv4 address format\n") +{ + struct in_addr value; + struct ospf_pce_info *pi = &OspfRI.pce_info; + + if (!inet_aton (argv[0], &value)) + { + vty_out (vty, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohs (pi->pce_address.header.type) == 0 + || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr)) + { + + set_pce_address (value, pi); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_address, + no_pce_address_cmd, + "no pce address", + NO_STR + PCE_STR + "Disable PCE address\n") +{ + + unset_param (&OspfRI.pce_info.pce_address.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_path_scope, + pce_path_scope_cmd, + "pce scope BITPATTERN", + PCE_STR + "Path scope visibilities of the PCE for path computation\n" + "32-bit Hexadecimal value\n") +{ + uint32_t scope; + struct ospf_pce_info *pi = &OspfRI.pce_info; + + if (sscanf (argv[0], "0x%x", &scope) != 1) + { + vty_out (vty, "pce_path_scope: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value) + { + set_pce_path_scope (scope, pi); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_path_scope, + no_pce_path_scope_cmd, + "no pce scope", + NO_STR + PCE_STR + "Disable PCE path scope\n") +{ + + unset_param (&OspfRI.pce_info.pce_address.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_domain, + pce_domain_cmd, + "pce domain as <0-65535>", + PCE_STR + "Configure PCE domain AS number\n" + "AS number where the PCE as visibilities for path computation\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "pce_domain: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (ntohl (domain->header.type) == 0 && as == domain->value) + goto out; + } + + /* Create new domain if not found */ + set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + +out:return CMD_SUCCESS; +} + +DEFUN (no_pce_domain, + no_pce_domain_cmd, + "no pce domain as <0-65535>", + NO_STR + PCE_STR + "Disable PCE domain AS number\n" + "AS number where the PCE as visibilities for path computation\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "no_pce_domain: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Unset corresponding PCE domain */ + unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_neigbhor, + pce_neighbor_cmd, + "pce neighbor as <0-65535>", + PCE_STR + "Configure PCE neighbor domain AS number\n" + "AS number of PCE neighbors\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_neighbor *neighbor; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "pce_neighbor: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (ntohl (neighbor->header.type) == 0 && as == neighbor->value) + goto out; + } + + /* Create new domain if not found */ + set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + +out:return CMD_SUCCESS; +} + +DEFUN (no_pce_neighbor, + no_pce_neighbor_cmd, + "no pce neighbor as <0-65535>", + NO_STR + PCE_STR + "Disable PCE neighbor AS number\n" + "AS number of PCE neighbor\n" + "AS number in decimal <0-65535>\n") +{ + + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "%d", &as) != 1) + { + vty_out (vty, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Unset corresponding PCE domain */ + unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (pce_cap_flag, + pce_cap_flag_cmd, + "pce flag BITPATTERN", + PCE_STR + "Capabilities of the PCE for path computation\n" + "32-bit Hexadecimal value\n") +{ + + uint32_t cap; + struct ospf_pce_info *pce = &OspfRI.pce_info; + + if (sscanf (argv[0], "0x%x", &cap) != 1) + { + vty_out (vty, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (ntohl (pce->pce_cap_flag.header.type) == 0 + || cap != pce->pce_cap_flag.value) + { + set_pce_cap_flag (cap, pce); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + } + + return CMD_SUCCESS; +} + +DEFUN (no_pce_cap_flag, + no_pce_cap_flag_cmd, + "no pce flag", + NO_STR + PCE_STR + "Disable PCE capabilities\n") +{ + + unset_param (&OspfRI.pce_info.pce_cap_flag.header); + + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_router_info, + show_ip_ospf_router_info_cmd, + "show ip ospf router-info", + SHOW_STR + IP_STR + OSPF_STR + "Router Information\n") +{ + + if (OspfRI.status == enabled) + { + vty_out (vty, "--- Router Information parameters ---%s", VTY_NEWLINE); + show_vty_router_cap (vty, &OspfRI.router_cap.header); + } + else + { + if (vty != NULL) + vty_out (vty, " Router Information is disabled on this router%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +DEFUN (show_ip_opsf_router_info_pce, + show_ip_ospf_router_info_pce_cmd, + "show ip ospf router-info pce", + SHOW_STR + IP_STR + OSPF_STR + "Router Information\n" + "PCE information\n") +{ + + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + if (OspfRI.status == enabled) + { + vty_out (vty, "--- PCE parameters ---%s", VTY_NEWLINE); + + if (pce->pce_address.header.type != 0) + show_vty_pce_subtlv_address (vty, &pce->pce_address.header); + + if (pce->pce_scope.header.type != 0) + show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header); + + for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) + { + if (domain->header.type != 0) + show_vty_pce_subtlv_domain (vty, &domain->header); + } + + for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) + { + if (neighbor->header.type != 0) + show_vty_pce_subtlv_neighbor (vty, &neighbor->header); + } + + if (pce->pce_cap_flag.header.type != 0) + show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header); + + } + else + { + vty_out (vty, " Router Information is disabled on this router%s", + VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + +/* Install new CLI commands */ +static void +ospf_router_info_register_vty (void) +{ + install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd); + install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_router_info_cmd); + install_element (ENABLE_NODE, &show_ip_ospf_router_info_pce_cmd); + + install_element (OSPF_NODE, &router_info_area_cmd); + install_element (OSPF_NODE, &router_info_as_cmd); + install_element (OSPF_NODE, &no_router_info_cmd); + install_element (OSPF_NODE, &pce_address_cmd); + install_element (OSPF_NODE, &pce_path_scope_cmd); + install_element (OSPF_NODE, &pce_domain_cmd); + install_element (OSPF_NODE, &no_pce_domain_cmd); + install_element (OSPF_NODE, &pce_neighbor_cmd); + install_element (OSPF_NODE, &no_pce_neighbor_cmd); + install_element (OSPF_NODE, &pce_cap_flag_cmd); + + return; +} diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h new file mode 100644 index 0000000000..3f898ac598 --- /dev/null +++ b/ospfd/ospf_ri.h @@ -0,0 +1,191 @@ +/* + * This is an implementation of RFC4970 Router Information + * with support of RFC5088 PCE Capabilites announcement + * + * Module name: Router Information + * Version: 0.99.22 + * Created: 2012-02-01 by Olivier Dugeon + * Copyright (C) 2012 Orange Labs http://www.orange.com/ + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_OSPF_ROUTER_INFO_H +#define _ZEBRA_OSPF_ROUTER_INFO_H + +/* + * Opaque LSA's link state ID for Router Information is + * structured as follows. + * + * 24 16 8 0 + * +--------+--------+--------+--------+ + * | 1 | MBZ |........|........| + * +--------+--------+--------+--------+ + * |<-Type->||<-- Instance --->| + * + * + * Type: IANA has assigned '4' for Router Information. + * MBZ: Reserved, must be set to zero. + * Instance: User may select an arbitrary 16-bit value. + * + */ + +/* + * 24 16 8 0 + * +--------+--------+--------+--------+ --- + * | LS age |Options | 9,10,11| A + * +--------+--------+--------+--------+ | + * | 4 | 0 | Instance | | + * +--------+--------+--------+--------+ | + * | Advertising router | | Standard (Opaque) LSA header; + * +--------+--------+--------+--------+ | Type 9,10 or 11 are used. + * | LS sequence number | | + * +--------+--------+--------+--------+ | + * | LS checksum | Length | V + * +--------+--------+--------+--------+ --- + * | Type | Length | A + * +--------+--------+--------+--------+ | TLV part for Router Information; Values might be + * | Values ... | V structured as a set of sub-TLVs. + * +--------+--------+--------+--------+ --- + */ + +/* + * Following section defines TLV (tag, length, value) structures, + * used for Router Information. + */ +struct ri_tlv_header +{ + u_int16_t type; /* RI_TLV_XXX (see below) */ + u_int16_t length; /* Value portion only, in byte */ +}; + +#define RI_TLV_HDR_SIZE (sizeof (struct ri_tlv_header)) +#define RI_TLV_BODY_SIZE(tlvh) (ROUNDUP (ntohs ((tlvh)->length), sizeof (u_int32_t))) +#define RI_TLV_SIZE(tlvh) (RI_TLV_HDR_SIZE + RI_TLV_BODY_SIZE(tlvh)) +#define RI_TLV_HDR_TOP(lsah) (struct ri_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE) +#define RI_TLV_HDR_NEXT(tlvh) (struct ri_tlv_header *)((char *)(tlvh) + RI_TLV_SIZE(tlvh)) + +/* + * Following section defines TLV body parts. + */ + +/* Up to now, 8 code point have been assigned to Router Information */ +/* Only type 1 Router Capabilities and 6 PCE are supported with this code */ +#define RI_IANA_MAX_TYPE 8 + +/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */ +#define RI_TLV_CAPABILITIES 1 + +struct ri_tlv_router_cap +{ + struct ri_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; +}; + +#define RI_GRACE_RESTART 0x01 +#define RI_GRACE_HELPER 0x02 +#define RI_STUB_SUPPORT 0x04 +#define RI_TE_SUPPORT 0x08 +#define RI_P2P_OVER_LAN 0x10 +#define RI_TE_EXPERIMENTAL 0x20 + +#define RI_TLV_LENGTH 4 + +/* RFC5088: PCE Capabilities TLV */ /* Optional */ +/* RI PCE TLV */ +#define RI_TLV_PCE 6 + +struct ri_tlv_pce +{ + struct ri_tlv_header header; +/* A set of PCE-sub-TLVs will follow. */ +}; + +/* PCE Address Sub-TLV */ /* Mandatory */ +#define RI_PCE_SUBTLV_ADDRESS 1 +struct ri_pce_subtlv_address +{ + struct ri_tlv_header header; /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ +#define PCE_ADDRESS_LENGTH_IPV4 8 +#define PCE_ADDRESS_LENGTH_IPV6 20 + struct + { + u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ +#define PCE_ADDRESS_TYPE_IPV4 1 +#define PCE_ADDRESS_TYPE_IPV6 2 + u_int16_t reserved; + struct in_addr value; /* PCE address */ + } address; +}; + +/* PCE Path-Scope Sub-TLV */ /* Mandatory */ +#define RI_PCE_SUBTLV_PATH_SCOPE 2 +struct ri_pce_subtlv_path_scope +{ + struct ri_tlv_header header; /* Type = 2; Length = 4 bytes. */ + u_int32_t value; /* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY bits see RFC5088 page 9 */ +}; + +/* PCE Domain Sub-TLV */ /* Optional */ +#define RI_PCE_SUBTLV_DOMAIN 3 + +#define PCE_DOMAIN_TYPE_AREA 1 +#define PCE_DOMAIN_TYPE_AS 2 + +struct ri_pce_subtlv_domain +{ + struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; +}; + +/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */ +#define RI_PCE_SUBTLV_NEIGHBOR 4 +struct ri_pce_subtlv_neighbor +{ + struct ri_tlv_header header; /* Type = 4; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; +}; + +/* PCE Capabilities Flags Sub-TLV */ /* Optional */ +#define RI_PCE_SUBTLV_CAP_FLAG 5 + +#define PCE_CAP_GMPLS_LINK 0x0001 +#define PCE_CAP_BIDIRECTIONAL 0x0002 +#define PCE_CAP_DIVERSE_PATH 0x0004 +#define PCE_CAP_LOAD_BALANCE 0x0008 +#define PCE_CAP_SYNCHRONIZED 0x0010 +#define PCE_CAP_OBJECTIVES 0x0020 +#define PCE_CAP_ADDITIVE 0x0040 +#define PCE_CAP_PRIORIZATION 0x0080 +#define PCE_CAP_MULTIPLE_REQ 0x0100 + +struct ri_pce_subtlv_cap_flag +{ + struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */ + u_int32_t value; +}; + +/* Prototypes. */ +extern int ospf_router_info_init (void); +extern void ospf_router_info_term (void); + +#endif /* _ZEBRA_OSPF_ROUTER_INFO_H */ From 7c101d199eb952a4325645a426d1663bcfaf594e Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Fri, 6 May 2016 17:20:25 -0400 Subject: [PATCH 184/226] lib: fix memory leak in zprivs_caps_init --- lib/privs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/privs.c b/lib/privs.c index e6d76b600b..3fb96aed12 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -307,11 +307,18 @@ zprivs_caps_init (struct zebra_privs_t *zprivs) current_caps = cap_get_proc(); if (current_caps) + { current_caps_text = cap_to_text(current_caps, NULL); + cap_free(current_caps); + } wanted_caps_text = cap_to_text(zprivs_state.caps, NULL); fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???"); fprintf(stderr, "Have caps: %s\n", current_caps_text ? current_caps_text : "???"); + if (current_caps_text) + cap_free(current_caps_text); + if (wanted_caps_text) + cap_free(wanted_caps_text); exit (1); } From 0f2b4f4da393dcb48d88fe46012c7646530ddc1c Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Wed, 20 Apr 2016 08:11:05 -0400 Subject: [PATCH 185/226] bgpd: cleanup clang uninitialized variable warning --- bgpd/bgp_attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index dc157ba7d0..242b287176 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1947,7 +1947,7 @@ bgp_attr_encap( } while (length >= 4) { - uint16_t subtype; + uint16_t subtype = 0; uint16_t sublength = 0; struct bgp_attr_encap_subtlv *tlv; From cebb7440e077cb78f95af2f350de612dd6be5507 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sat, 7 May 2016 10:35:21 -0400 Subject: [PATCH 186/226] bgp: add "debug bgp allow-martians" next hops and related code/commands --- bgpd/bgp_attr.c | 3 ++- bgpd/bgp_debug.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_debug.h | 3 +++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 242b287176..3cb52ef911 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1315,7 +1315,8 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) gets ignored in any of these cases. */ nexthop_n = stream_get_ipv4 (peer->ibuf); nexthop_h = ntohl (nexthop_n); - if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) + if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) + && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */ { char buf[INET_ADDRSTRLEN]; inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 7427afed7b..dc0f539847 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -49,6 +49,7 @@ unsigned long conf_bgp_debug_keepalive; unsigned long conf_bgp_debug_update; unsigned long conf_bgp_debug_bestpath; unsigned long conf_bgp_debug_zebra; +unsigned long conf_bgp_debug_allow_martians; unsigned long conf_bgp_debug_nht; unsigned long conf_bgp_debug_update_groups; @@ -61,6 +62,7 @@ unsigned long term_bgp_debug_keepalive; unsigned long term_bgp_debug_update; unsigned long term_bgp_debug_bestpath; unsigned long term_bgp_debug_zebra; +unsigned long term_bgp_debug_allow_martians; unsigned long term_bgp_debug_nht; unsigned long term_bgp_debug_update_groups; @@ -1519,6 +1521,48 @@ DEFUN (no_debug_bgp_zebra_prefix, return CMD_SUCCESS; } +DEFUN (debug_bgp_allow_martians, + debug_bgp_allow_martians_cmd, + "debug bgp allow-martians", + DEBUG_STR + BGP_STR + "BGP allow martian next hops\n") +{ + if (vty->node == CONFIG_NODE) + DEBUG_ON (allow_martians, ALLOW_MARTIANS); + else + { + TERM_DEBUG_ON (allow_martians, ALLOW_MARTIANS); + vty_out (vty, "BGP allow_martian next hop debugging is on%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +DEFUN (no_debug_bgp_allow_martians, + no_debug_bgp_allow_martians_cmd, + "no debug bgp allow-martians", + NO_STR + DEBUG_STR + BGP_STR + "BGP allow martian next hops\n") +{ + if (vty->node == CONFIG_NODE) + DEBUG_OFF (allow_martians, ALLOW_MARTIANS); + else + { + TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); + vty_out (vty, "BGP allow martian next hop debugging is off%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +ALIAS (no_debug_bgp_allow_martians, + undebug_bgp_allow_martians_cmd, + "undebug bgp allow-martians", + UNDEBUG_STR + BGP_STR + "BGP allow martian next hops\n") + /* debug bgp update-groups */ DEFUN (debug_bgp_update_groups, debug_bgp_update_groups_cmd, @@ -1581,6 +1625,7 @@ DEFUN (no_debug_bgp, TERM_DEBUG_OFF (as4, AS4_SEGMENT); TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); TERM_DEBUG_OFF (zebra, ZEBRA); + TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE); return CMD_SUCCESS; @@ -1635,6 +1680,8 @@ DEFUN (show_debugging_bgp, bgp_debug_list_print (vty, " BGP zebra debugging is on", bgp_debug_zebra_prefixes); + if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) + vty_out (vty, " BGP allow martian next hop debugging is on%s", VTY_NEWLINE); vty_out (vty, "%s", VTY_NEWLINE); return CMD_SUCCESS; } @@ -1718,6 +1765,12 @@ bgp_config_write_debug (struct vty *vty) } } + if (CONF_BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) + { + vty_out (vty, "debug bgp allow-martians%s", VTY_NEWLINE); + write++; + } + return write; } @@ -1750,6 +1803,8 @@ bgp_debug_init (void) install_element (CONFIG_NODE, &debug_bgp_update_cmd); install_element (ENABLE_NODE, &debug_bgp_zebra_cmd); install_element (CONFIG_NODE, &debug_bgp_zebra_cmd); + install_element (ENABLE_NODE, &debug_bgp_allow_martians_cmd); + install_element (CONFIG_NODE, &debug_bgp_allow_martians_cmd); install_element (ENABLE_NODE, &debug_bgp_update_groups_cmd); install_element (CONFIG_NODE, &debug_bgp_update_groups_cmd); install_element (ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd); @@ -1806,6 +1861,9 @@ bgp_debug_init (void) install_element (CONFIG_NODE, &no_debug_bgp_update_cmd); install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd); install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_allow_martians_cmd); + install_element (ENABLE_NODE, &undebug_bgp_allow_martians_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_allow_martians_cmd); install_element (ENABLE_NODE, &no_debug_bgp_update_groups_cmd); install_element (CONFIG_NODE, &no_debug_bgp_update_groups_cmd); install_element (ENABLE_NODE, &no_debug_bgp_cmd); diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 8372c7e3f5..835d585735 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -66,6 +66,7 @@ extern unsigned long conf_bgp_debug_keepalive; extern unsigned long conf_bgp_debug_update; extern unsigned long conf_bgp_debug_bestpath; extern unsigned long conf_bgp_debug_zebra; +extern unsigned long conf_bgp_debug_allow_martians; extern unsigned long conf_bgp_debug_nht; extern unsigned long conf_bgp_debug_update_groups; @@ -76,6 +77,7 @@ extern unsigned long term_bgp_debug_keepalive; extern unsigned long term_bgp_debug_update; extern unsigned long term_bgp_debug_bestpath; extern unsigned long term_bgp_debug_zebra; +extern unsigned long term_bgp_debug_allow_martians; extern unsigned long term_bgp_debug_nht; extern unsigned long term_bgp_debug_update_groups; @@ -104,6 +106,7 @@ struct bgp_debug_filter #define BGP_DEBUG_UPDATE_OUT 0x02 #define BGP_DEBUG_UPDATE_PREFIX 0x04 #define BGP_DEBUG_ZEBRA 0x01 +#define BGP_DEBUG_ALLOW_MARTIANS 0x01 #define BGP_DEBUG_NHT 0x01 #define BGP_DEBUG_UPDATE_GROUPS 0x01 From b645912484b3f0e1fa0736e2c1cd45bf7b8d6799 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 19 Apr 2016 12:42:25 -0400 Subject: [PATCH 187/226] lib: dump memory stats on core --- lib/sigevent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sigevent.c b/lib/sigevent.c index c80a729012..a120028d81 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -237,6 +237,8 @@ core_handler(int signo , siginfo, program_counter(context) #endif ); + /* dump memory stats on core */ + log_memstats_stderr ("core_handler"); abort(); } From 32ac65d9fa2e9565d4a0251f9e39e8e64526322d Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 19 Apr 2016 16:08:59 -0400 Subject: [PATCH 188/226] lib: add AF_ETHERNET/AFI_ETHER --- bgpd/bgp_open.c | 3 ++ lib/plist.c | 5 +++ lib/prefix.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++- lib/prefix.h | 43 ++++++++++++++++++ lib/zebra.h | 3 +- 5 files changed, 165 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 915757e622..6001092ce2 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -196,6 +196,9 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) return 1; } break; + case AFI_ETHER: + default: + break; } zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); diff --git a/lib/plist.c b/lib/plist.c index a1289801c4..7bb80fa2a4 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -958,6 +958,11 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, return CMD_WARNING; } break; + case AFI_ETHER: + default: + vty_out (vty, "%% Unrecognized AFI (%d)%s", afi, VTY_NEWLINE); + return CMD_WARNING; + break; } /* ge and le check. */ diff --git a/lib/prefix.c b/lib/prefix.c index c311b94eef..d2bb028315 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -194,8 +194,9 @@ str2family(const char *string) return AF_INET; else if (!strcmp("ipv6", string)) return AF_INET6; - else - return -1; + else if (!strcmp("ethernet", string)) + return AF_ETHERNET; + return -1; } /* Address Famiy Identifier to Address Family converter. */ @@ -208,6 +209,8 @@ afi2family (afi_t afi) else if (afi == AFI_IP6) return AF_INET6; #endif /* HAVE_IPV6 */ + else if (afi == AFI_ETHER) + return AF_ETHERNET; return 0; } @@ -220,9 +223,27 @@ family2afi (int family) else if (family == AF_INET6) return AFI_IP6; #endif /* HAVE_IPV6 */ + else if (family == AF_ETHERNET) + return AFI_ETHER; return 0; } +const char * +afi2str(afi_t afi) +{ + switch (afi) { + case AFI_IP: + return "IPv4"; + case AFI_IP6: + return "IPv6"; + case AFI_ETHER: + return "ethernet"; + default: + break; + } + return NULL; +} + const char * safi2str(safi_t safi) { @@ -286,6 +307,10 @@ prefix_copy (struct prefix *dest, const struct prefix *src) dest->u.lp.id = src->u.lp.id; dest->u.lp.adv_router = src->u.lp.adv_router; } + else if (src->family == AF_ETHERNET) + { + dest->u.prefix_eth = src->u.prefix_eth; + } else { zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d", @@ -321,6 +346,10 @@ prefix_same (const struct prefix *p1, const struct prefix *p2) if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr)) return 1; #endif /* HAVE_IPV6 */ + if (p1->family == AF_ETHERNET) { + if (!memcmp(p1->u.prefix_eth.octet, p2->u.prefix_eth.octet, ETHER_ADDR_LEN)) + return 1; + } } return 0; } @@ -412,6 +441,8 @@ prefix_family_str (const struct prefix *p) if (p->family == AF_INET6) return "inet6"; #endif /* HAVE_IPV6 */ + if (p->family == AF_ETHERNET) + return "ether"; return "unspec"; } @@ -482,6 +513,60 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) return ret; } +/* When string format is invalid return 0. */ +int +str2prefix_eth (const char *str, struct prefix_eth *p) +{ + int ret = 0; + int plen = 48; + char *pnt; + char *cp = NULL; + const char *str_addr = str; + unsigned int a[6]; + int i; + + /* Find slash inside string. */ + pnt = strchr (str, '/'); + + if (pnt) + { + /* Get prefix length. */ + plen = (u_char) atoi (++pnt); + if (plen > 48) + { + ret = 0; + goto done; + } + + cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); + strncpy (cp, str, pnt - str); + *(cp + (pnt - str)) = '\0'; + + str_addr = cp; + } + + /* Convert string to prefix. */ + if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x", + a+0, a+1, a+2, a+3, a+4, a+5) != 6) + { + ret = 0; + goto done; + } + for (i = 0; i < 6; ++i) + { + p->eth_addr.octet[i] = a[i] & 0xff; + } + p->prefixlen = plen; + p->family = AF_ETHERNET; + ret = 1; + +done: + if (cp) + XFREE (MTYPE_TMP, cp); + + return ret; +} + /* Convert masklen into IP address's netmask (network byte order). */ void masklen2ip (const int masklen, struct in_addr *netmask) @@ -768,6 +853,8 @@ prefix_blen (const struct prefix *p) return IPV6_MAX_BYTELEN; break; #endif /* HAVE_IPV6 */ + case AF_ETHERNET: + return ETHER_ADDR_LEN; } return 0; } @@ -790,6 +877,11 @@ str2prefix (const char *str, struct prefix *p) return ret; #endif /* HAVE_IPV6 */ + /* Next we try to convert string to struct prefix_eth. */ + ret = str2prefix_eth (str, (struct prefix_eth *) p); + if (ret) + return ret; + return 0; } @@ -799,6 +891,24 @@ prefix2str (union prefix46constptr pu, char *str, int size) const struct prefix *p = pu.p; char buf[PREFIX2STR_BUFFER]; + if (p->family == AF_ETHERNET) { + int i; + char *s = str; + + assert(size > (3*ETHER_ADDR_LEN) + 1 /* slash */ + 3 /* plen */ ); + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + sprintf(s, "%02x", p->u.prefix_eth.octet[i]); + if (i < (ETHER_ADDR_LEN - 1)) { + *(s+2) = ':'; + s += 3; + } else { + s += 2; + } + } + sprintf(s, "/%d", p->prefixlen); + return 0; + } + snprintf (str, size, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER), p->prefixlen); diff --git a/lib/prefix.h b/lib/prefix.h index 39c2b62019..85488ccea7 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -23,8 +23,30 @@ #ifndef _ZEBRA_PREFIX_H #define _ZEBRA_PREFIX_H +#ifdef SUNOS_5 +# include +#else +# ifdef GNU_LINUX +# include +# else +# include +# endif +#endif #include "sockunion.h" +#ifndef ETHER_ADDR_LEN +#define ETHER_ADDR_LEN ETHERADDRL +#endif + +/* + * there isn't a portable ethernet address type. We define our + * own to simplify internal handling + */ +struct ethaddr { + u_char octet[ETHER_ADDR_LEN]; +} __packed; + + /* * A struct prefix contains an address family, a prefix length, and an * address. This can represent either a 'network prefix' as defined @@ -34,6 +56,15 @@ * interface. */ +/* different OSes use different names */ +#if defined(AF_PACKET) +#define AF_ETHERNET AF_PACKET +#else +#if defined(AF_LINK) +#define AF_ETHERNET AF_LINK +#endif +#endif + /* IPv4 and IPv6 unified prefix structure. */ struct prefix { @@ -51,6 +82,7 @@ struct prefix struct in_addr id; struct in_addr adv_router; } lp; + struct ethaddr prefix_eth; /* AF_ETHERNET */ u_char val[8]; uintptr_t ptr; } u __attribute__ ((aligned (8))); @@ -90,6 +122,14 @@ struct prefix_rd u_char val[8] __attribute__ ((aligned (8))); }; +/* Prefix for ethernet. */ +struct prefix_eth +{ + u_char family; + u_char prefixlen; + struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */ +}; + /* Prefix for a generic pointer */ struct prefix_ptr { @@ -174,6 +214,7 @@ extern int str2family(const char *); extern int afi2family (afi_t); extern afi_t family2afi (int); extern const char *safi2str(safi_t safi); +extern const char *afi2str(afi_t afi); /* Check bit of the prefix. */ extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen); @@ -205,6 +246,8 @@ extern struct prefix *sockunion2prefix (const union sockunion *dest, extern struct prefix *sockunion2hostprefix (const union sockunion *, struct prefix *p); extern void prefix2sockunion (const struct prefix *, union sockunion *); +extern int str2prefix_eth (const char *, struct prefix_eth *); + extern struct prefix_ipv4 *prefix_ipv4_new (void); extern void prefix_ipv4_free (struct prefix_ipv4 *); extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *); diff --git a/lib/zebra.h b/lib/zebra.h index 94158013ec..fdfd471825 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -502,7 +502,8 @@ extern const char *zserv_command_string (unsigned int command); typedef enum { AFI_IP = 1, AFI_IP6 = 2, -#define AFI_MAX 3 + AFI_ETHER = 3, /* RFC 1700 has "6" for 802.* */ + AFI_MAX = 4 } afi_t; /* Subsequent Address Family Identifier. */ From 6e13ed4af9d908a416c6c70274aec5429fae6370 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 11 May 2016 15:26:39 +0300 Subject: [PATCH 189/226] bgpd: fix wrong help strings of "match peer" and "no match peer" commands Signed-off-by: Igor Ryzhov Signed-off-by: Igor Ryzhov Tested-by: NetDEF CI System --- bgpd/bgp_routemap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index e4fd730cf0..fea9ae6b18 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2997,8 +2997,8 @@ DEFUN (match_peer, "match peer (A.B.C.D|X:X::X:X)", MATCH_STR "Match peer address\n" - "IPv6 address of peer\n" - "IP address of peer\n") + "IP address of peer\n" + "IPv6 address of peer\n") { return bgp_route_match_add (vty, vty->index, "peer", argv[0], RMAP_EVENT_MATCH_ADDED); @@ -3036,8 +3036,8 @@ ALIAS (no_match_peer, NO_STR MATCH_STR "Match peer address\n" - "IPv6 address of peer\n" - "IP address of peer\n") + "IP address of peer\n" + "IPv6 address of peer\n") ALIAS (no_match_peer, no_match_peer_local_cmd, From eb6f1b41e8b80526d5209850c30a187dc3af9aa0 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 24 May 2016 16:52:02 +0200 Subject: [PATCH 190/226] bgpd: Add new configuration cli for graceful restart. There is support to configure graceful restart timer. This is the time to wait to delete stale routes before a BGP open message is received. bgp graceful-restart restart-time <1-3600> no bgp graceful-restart [<1-255>] * bgpd/bgp_vty.c * Define command strings for above CLI * bgpd/bgpd.c * bgp_config_write(): Output graceful restart-time configuration Signed-off-by: Philippe Guibert Signed-off-by: Philippe Guibert Tested-by: NetDEF CI System --- bgpd/bgp_vty.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgpd.c | 3 +++ 2 files changed, 53 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 276fe16e78..c83d751743 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1816,6 +1816,26 @@ DEFUN (bgp_graceful_restart_stalepath_time, return CMD_SUCCESS; } +DEFUN (bgp_graceful_restart_restart_time, + bgp_graceful_restart_restart_time_cmd, + "bgp graceful-restart restart-time <1-3600>", + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n" + "Delay value (seconds)\n") +{ + struct bgp *bgp; + u_int32_t restart; + + bgp = vty->index; + if (! bgp) + return CMD_WARNING; + + VTY_GET_INTEGER_RANGE ("restart-time", restart, argv[0], 1, 3600); + bgp->restart_time = restart; + return CMD_SUCCESS; +} + DEFUN (no_bgp_graceful_restart_stalepath_time, no_bgp_graceful_restart_stalepath_time_cmd, "no bgp graceful-restart stalepath-time", @@ -1834,6 +1854,24 @@ DEFUN (no_bgp_graceful_restart_stalepath_time, return CMD_SUCCESS; } +DEFUN (no_bgp_graceful_restart_restart_time, + no_bgp_graceful_restart_restart_time_cmd, + "no bgp graceful-restart restart-time", + NO_STR + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n") +{ + struct bgp *bgp; + + bgp = vty->index; + if (! bgp) + return CMD_WARNING; + + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + return CMD_SUCCESS; +} + ALIAS (no_bgp_graceful_restart_stalepath_time, no_bgp_graceful_restart_stalepath_time_val_cmd, "no bgp graceful-restart stalepath-time <1-3600>", @@ -1843,6 +1881,15 @@ ALIAS (no_bgp_graceful_restart_stalepath_time, "Set the max time to hold onto restarting peer's stale paths\n" "Delay value (seconds)\n") +ALIAS (no_bgp_graceful_restart_restart_time, + no_bgp_graceful_restart_restart_time_val_cmd, + "no bgp graceful-restart restart-time <1-3600>", + NO_STR + "BGP specific commands\n" + "Graceful restart capability parameters\n" + "Set the time to wait to delete stale routes before a BGP open message is received\n" + "Delay value (seconds)\n") + /* "bgp fast-external-failover" configuration. */ DEFUN (bgp_fast_external_failover, bgp_fast_external_failover_cmd, @@ -14532,6 +14579,9 @@ bgp_vty_init (void) install_element (BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd); install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd); install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_val_cmd); + install_element (BGP_NODE, &bgp_graceful_restart_restart_time_cmd); + install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd); + install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_val_cmd); /* "bgp fast-external-failover" commands */ install_element (BGP_NODE, &bgp_fast_external_failover_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index f63f3f8f94..3af35e5378 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7221,6 +7221,9 @@ bgp_config_write (struct vty *vty) if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) vty_out (vty, " bgp graceful-restart stalepath-time %d%s", bgp->stalepath_time, VTY_NEWLINE); + if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) + vty_out (vty, " bgp graceful-restart restart-time %d%s", + bgp->restart_time, VTY_NEWLINE); if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART)) vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE); From 50cfc0d2d7445bccf3f137dcaf4bf3ef56fe0f69 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Fri, 1 Apr 2016 12:54:38 +0200 Subject: [PATCH 191/226] build: detect and create AM_SILENT_RULES macro if needed Older libs have problem with that: configure.ac:17: warning: macro `AM_SILENT_RULES' not found in library ... configure.ac:24: error: possibly undefined macro: AM_SILENT_RULES Tested-by: NetDEF CI System --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index edd77b2b8a..e01af9e55e 100755 --- a/configure.ac +++ b/configure.ac @@ -21,6 +21,7 @@ AC_CANONICAL_HOST() AC_CANONICAL_TARGET() AM_INIT_AUTOMAKE(1.6) +m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])]) AM_SILENT_RULES([yes]) AC_CONFIG_HEADERS(config.h) From 58a902757002af97ad35444abca82e1d78b45f11 Mon Sep 17 00:00:00 2001 From: Balaji Date: Wed, 20 Jan 2016 22:59:26 +0530 Subject: [PATCH 192/226] bgpd: Addition of dampening show commands under v4 unicast/multicast tree Patch contains addition of show ip bgp ipv4 (unicast| multicast) dampening tree. Signed-off-by: Balaji Gurudoss Signed-off-by: Balaji Gurudoss --- bgpd/bgp_route.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f47e2f6074..c5a351491d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9310,6 +9310,66 @@ DEFUN (show_ip_bgp_dampening_info, return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); } + +DEFUN (show_ip_bgp_ipv4_dampening_parameters, + show_ip_bgp_ipv4_dampening_parameters_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening parameters", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display detail of configured dampening parameters\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_MULTICAST); + + return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); +} + + +DEFUN (show_ip_bgp_ipv4_dampening_flap_stats, + show_ip_bgp_ipv4_dampening_flap_stats_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening flap-statistics", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display flap statistics of routes\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_flap_statistics, NULL, 0); + + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_flap_statistics, NULL, 0); +} + +DEFUN (show_ip_bgp_ipv4_dampening_dampd_paths, + show_ip_bgp_ipv4_dampening_dampd_paths_cmd, + "show ip bgp ipv4 (unicast|multicast) dampening dampened-paths", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display detailed information about dampening\n" + "Display paths suppressed due to dampening\n") +{ + if (strncmp(argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_dampend_paths, NULL, 0); + + return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, + bgp_show_type_dampend_paths, NULL, 0); +} + static int bgp_show_route_map (struct vty *vty, const char *name, const char *rmap_str, afi_t afi, @@ -14444,7 +14504,10 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd); install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_dampd_paths_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_flap_stats_cmd); install_element (VIEW_NODE, &show_ip_bgp_damp_dampened_paths_cmd); install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd); install_element (VIEW_NODE, &show_ip_bgp_damp_flap_statistics_cmd); @@ -14597,6 +14660,9 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); install_element (ENABLE_NODE, &show_ip_bgp_dampening_params_cmd); install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_dampd_paths_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_dampening_flap_stats_cmd); install_element (ENABLE_NODE, &show_ip_bgp_damp_dampened_paths_cmd); install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd); install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_statistics_cmd); From 5c9e5a8df8cfc038de2cd39ba592d4f68382aed1 Mon Sep 17 00:00:00 2001 From: Balaji Date: Wed, 20 Jan 2016 22:59:27 +0530 Subject: [PATCH 193/226] bgpd: Addition of bgp dampening configuration commands under IPv4 Multicast address family mode. Signed-off-by: Balaji Gurudoss Signed-off-by: Balaji Gurudoss Tested-by: NetDEF CI System --- bgpd/bgp_route.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c5a351491d..b692734c78 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -15072,6 +15072,13 @@ bgp_route_init (void) install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset3_cmd); + + /* IPv4 Multicast Mode */ + install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_set2_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_set3_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + install_element (BGP_IPV4M_NODE, &bgp_damp_unset2_cmd); } void From 9cc8cd02790ce8d7cac29963cfd2a35c42b5301f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 27 Jun 2012 17:18:08 -0300 Subject: [PATCH 194/226] bgpd: fix bug in ecommunity_match The offset used to compare extended communities should be increased by steps of ECOMMUNITY_SIZE and not one by one. --- bgpd/bgp_ecommunity.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index e55ce3528c..926e2650a2 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -770,7 +770,9 @@ ecommunity_match (const struct ecommunity *ecom1, /* Every community on com2 needs to be on com1 for this to match */ while (i < ecom1->size && j < ecom2->size) { - if (memcmp (ecom1->val + i, ecom2->val + j, ECOMMUNITY_SIZE) == 0) + if (memcmp (ecom1->val + i * ECOMMUNITY_SIZE, + ecom2->val + j * ECOMMUNITY_SIZE, + ECOMMUNITY_SIZE) == 0) j++; i++; } @@ -780,4 +782,3 @@ ecommunity_match (const struct ecommunity *ecom1, else return 0; } - From 8b7131f0b76cb792e18d085419befd80d739df3a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 4 Sep 2016 18:46:27 -0400 Subject: [PATCH 195/226] zebra: Remove unnecessary log Removing unnecessary zlog_info line from zebra. Signed-off-by: Donald Sharp --- zebra/zserv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index d8579a2d06..020a252371 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -165,7 +165,6 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); - zlog_info("Try to set TE Link Param"); /* Then, Traffic Engineering parameters if any */ if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) { From 0adfc788726fcc9585b01d56927a226ab7f86884 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 4 Sep 2016 20:05:16 -0400 Subject: [PATCH 196/226] bgpd: Fix crash in 'show ip nexthop' With the addition of the AFI_ETHER we need to initialize the appropriate tables for nexthop's. Signed-off-by: Donald Sharp --- bgpd/bgp_nexthop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index c38d54ef7d..1e5c4cf8b0 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -564,12 +564,13 @@ bgp_scan_init (struct bgp *bgp) bgp->connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); bgp->import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); -#ifdef HAVE_IPV6 bgp->nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp->connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp->import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); -#endif /* HAVE_IPV6 */ + bgp->nexthop_cache_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); + bgp->connected_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); + bgp->import_check_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); } void From 7f80b49ae060867542506503da79023dadca5830 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 4 Sep 2016 20:13:43 -0400 Subject: [PATCH 197/226] isisd: Remove impossible code te->sub_tlvs can never be NULL as that it is an array. Remove dead code. Signed-off-by: Donald Sharp --- isisd/isis_te.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 247d699b1e..deaaa7104b 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -990,9 +990,6 @@ mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) zlog_debug ("ISIS MPLS-TE: Show database TE detail"); - if (te->sub_tlvs == NULL) - return; - tlvh = (struct subtlv_header *)te->sub_tlvs; for (; sum < te->sub_tlvs_length; tlvh = (next ? next : SUBTLV_HDR_NEXT (tlvh))) From 3064bf43a7d8162dadada2934132f915a45d2bcb Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:35:19 -0700 Subject: [PATCH 198/226] bgpd: Fix route install upon non-best nexthop change After BGP path selection, even if the best route entry selected has not changed, ensure that the route is installed again in zebra if any non-best but multipath route entry has a nexthop resolution change. In the absence of this fix, if a non-best multipath route entry had a nexthop resolution change (such as being resolved over two first hops instead of one), the route would get reinstalled into zebra only in some situations (i.e., when the best route entry had its IGP change flag set). If the route does not get reinstalled by BGP, the corresponding route in the zebra RIB would not have all the first hops. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Reviewed-by: Sid Khot Ticket: CM-12390 Reviewed By: CCR-5134 Testing Done: Manual, bgp-smoke --- bgpd/bgp_nht.c | 2 -- bgpd/bgp_route.c | 55 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 11b59fb3e1..cdee80a0bb 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -680,8 +680,6 @@ evaluate_paths (struct bgp_nexthop_cache *bnc) if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); - else - UNSET_FLAG (path->flags, BGP_INFO_IGP_CHANGED); bgp_process(bgp, rn, afi, SAFI_UNICAST); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index b692734c78..1ac35d9df8 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1657,7 +1657,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, if (debug) zlog_debug("%s: %s is the bestpath, add to the multipath list", pfx_buf, path_buf); - bgp_mp_list_add (&mp_list, ri); + bgp_mp_list_add (&mp_list, ri); continue; } @@ -1749,6 +1749,50 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp, return 0; } +/* + * Clear IGP changed flag for a route (all paths). This is called at + * the end of route processing. + */ +static void +bgp_zebra_clear_route_change_flags (struct bgp_node *rn) +{ + struct bgp_info *ri; + + for (ri = rn->info; ri; ri = ri->next) + { + if (BGP_INFO_HOLDDOWN (ri)) + continue; + UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); + } +} + +/* + * Has the route changed from the RIB's perspective? This is invoked only + * if the route selection returns the same best route as earlier - to + * determine if we need to update zebra or not. + */ +static int +bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) +{ + struct bgp_info *mpinfo; + + /* There is a multipath change or best path has some nexthop change. */ + if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || + CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) + return 1; + + /* If this is multipath, check all selected paths for any nexthop change */ + for (mpinfo = bgp_info_mpath_first (selected); mpinfo; + mpinfo = bgp_info_mpath_next (mpinfo)) + { + if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED)) + return 1; + } + + /* Nothing has changed from the RIB's perspective. */ + return 0; +} + struct bgp_process_queue { struct bgp *bgp; @@ -1799,11 +1843,11 @@ bgp_process_main (struct work_queue *wq, void *data) !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && !bgp->addpath_tx_used[afi][safi]) { - if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) || - CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG)) + if (bgp_zebra_has_route_changed (rn, old_select)) bgp_zebra_announce (p, old_select, bgp, afi, safi); UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_zebra_clear_route_change_flags (rn); UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); return WQ_SUCCESS; } @@ -1856,7 +1900,10 @@ bgp_process_main (struct work_queue *wq, void *data) bgp_zebra_withdraw (p, old_select, safi); } } - + + /* Clear any route change flags. */ + bgp_zebra_clear_route_change_flags (rn); + /* Reap old select bgp_info, if it has been removed */ if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); From e10720512ef744483ffed8a6ef3b529ec97e130d Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:49:16 -0700 Subject: [PATCH 199/226] bgpd: Fix route install upon multipath nexthop change In multipath selection, there can be a scenario where the set of route entries selected as multipath can be the same (i.e., from the same peers) but one or more of these may have a change to the BGP next hop. In this case, the route needs to be installed again in zebra even if the best route entry selected has not changed, otherwise the zebra RIB may have a different set of next hops (and first hops) than what the routing protocol selected. This patch handles this scenario by re-installing the route if any BGP attribute has changed for any of the multipaths. Not all BGP attributes are of relevance to the zebra RIB, but this approach follows existing logic used in the code (e.g., when BGP attributes for the best route entry has changed). Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Reviewed-by: Sid Khot Ticket: CM-12390 Reviewed By: CCR-5135 Testing Done: Manual, bgp-smoke --- bgpd/bgp_route.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 1ac35d9df8..af8c2cf706 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1750,8 +1750,8 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp, } /* - * Clear IGP changed flag for a route (all paths). This is called at - * the end of route processing. + * Clear IGP changed flag and attribute changed flag for a route (all paths). + * This is called at the end of route processing. */ static void bgp_zebra_clear_route_change_flags (struct bgp_node *rn) @@ -1763,6 +1763,7 @@ bgp_zebra_clear_route_change_flags (struct bgp_node *rn) if (BGP_INFO_HOLDDOWN (ri)) continue; UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); + UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); } } @@ -1776,7 +1777,12 @@ bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) { struct bgp_info *mpinfo; - /* There is a multipath change or best path has some nexthop change. */ + /* If this is multipath, check all selected paths for any nexthop change or + * attribute change. Some attribute changes (e.g., community) aren't of + * relevance to the RIB, but we'll update zebra to ensure we handle the + * case of BGP nexthop change. This is the behavior when the best path has + * an attribute change anyway. + */ if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) return 1; @@ -1785,7 +1791,8 @@ bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) for (mpinfo = bgp_info_mpath_first (selected); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { - if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED)) + if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED) + || CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED)) return 1; } From a6086ad4084a9dfbf930ef48e2987772767063bd Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:53:06 -0700 Subject: [PATCH 200/226] bgpd: Enhance path selection logs Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-12390 Reviewed By: CCR-5136 Testing Done: Manual --- bgpd/bgp_mpath.c | 38 ++++++++++++++++++++++++++++++++------ bgpd/bgp_route.c | 32 +++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 9d742204f6..e7272cc0aa 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -468,6 +468,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, bgp_info_mpath_dequeue (old_best); } + if (debug) + zlog_debug("%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d", + pfx_buf, new_best ? new_best->peer->host : "NONE", + listcount (mp_list), old_mpath_count); + /* * We perform an ordered walk through both lists in parallel. * The reason for the ordered walk is that if there are paths @@ -481,6 +486,8 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, */ while (mp_node || cur_mpath) { + struct bgp_info *tmp_info; + /* * We can bail out of this loop if all existing paths on the * multipath list have been visited (for cleanup purposes) and @@ -491,6 +498,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, mp_next_node = mp_node ? listnextnode (mp_node) : NULL; next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL; + tmp_info = mp_node ? listgetdata (mp_node) : NULL; + + if (debug) + zlog_debug("%s: comparing candidate %s with existing mpath %s", + pfx_buf, tmp_info ? tmp_info->peer->host : "NONE", + cur_mpath ? cur_mpath->peer->host : "NONE"); /* * If equal, the path was a multipath and is still a multipath. @@ -506,6 +519,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, bgp_info_mpath_enqueue (prev_mpath, cur_mpath); prev_mpath = cur_mpath; mpath_count++; + if (debug) + { + bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); + zlog_debug("%s: %s is still multipath, cur count %d", + pfx_buf, path_buf, mpath_count); + } } else { @@ -513,10 +532,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &cur_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } } mp_node = mp_next_node; @@ -539,10 +559,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &cur_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } cur_mpath = next_mpath; } @@ -575,10 +596,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(new_mpath, path_buf); - zlog_debug ("%s add mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: add mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &new_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } } mp_node = mp_next_node; @@ -587,6 +609,10 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (new_best) { + if (debug) + zlog_debug("%s: New mpath count (incl newbest) %d mpath-change %s", + pfx_buf, mpath_count, mpath_changed ? "YES" : "NO"); + bgp_info_mpath_count_set (new_best, mpath_count-1); if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count)) SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index af8c2cf706..7295ff147f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -376,7 +376,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, } if (debug) - bgp_info_path_with_addpath_rx_str (exist, exist_buf); + { + bgp_info_path_with_addpath_rx_str (exist, exist_buf); + zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", + pfx_buf, new_buf, new->flags, exist_buf, exist->flags); + } newattr = new->attr; existattr = exist->attr; @@ -705,6 +709,15 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, * TODO: If unequal cost ibgp multipath is enabled we can * mark the paths as equal here instead of returning */ + if (debug) + { + if (ret == 1) + zlog_debug("%s: %s wins over %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + else + zlog_debug("%s: %s loses to %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + } return ret; } @@ -1638,14 +1651,19 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, /* Now that we know which path is the bestpath see if any of the other paths * qualify as multipaths */ + if (debug) + { + if (new_select) + bgp_info_path_with_addpath_rx_str (new_select, path_buf); + else + sprintf (path_buf, "NONE"); + zlog_debug("%s: After path selection, newbest is %s oldbest was %s", + pfx_buf, path_buf, + old_select ? old_select->peer->host : "NONE"); + } + if (do_mpath && new_select) { - if (debug) - { - bgp_info_path_with_addpath_rx_str (new_select, path_buf); - zlog_debug("%s: %s is the bestpath, now find multipaths", pfx_buf, path_buf); - } - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) { From 5e6d589c37ecf9c2d390e38718b8a42f766fd374 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Sep 2016 20:03:19 -0400 Subject: [PATCH 201/226] bgpd: Fix call of bgp_address_destroy We were prematurely deleting the bgp->address_hash. Signed-off-by: Donald Sharp --- bgpd/bgpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 3af35e5378..87e5c54ea2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3178,8 +3178,6 @@ bgp_delete (struct bgp *bgp) /* Free interfaces in this instance. */ bgp_if_finish (bgp); - bgp_address_destroy (bgp); - thread_master_free_unused(bm->master); bgp_unlock(bgp); /* initial reference */ @@ -3229,6 +3227,8 @@ bgp_free (struct bgp *bgp) bgp_table_finish (&bgp->rib[afi][safi]); } + bgp_address_destroy (bgp); + /* If Default instance or VRF, unlink from the VRF structure. */ vrf = bgp_vrf_lookup_by_instance_type (bgp); if (vrf) From c80266bea253a2339de2130f132e7f92c5774ecb Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 29 Aug 2016 19:59:53 +0000 Subject: [PATCH 202/226] json support for "show ip route" for "show ipv6 route" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12633 (cherry picked from commit 18a4ded2a72cc5613f54845dd29c1ee7d05bbf04) --- zebra/zebra_vty.c | 360 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 297 insertions(+), 63 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index e9090cbed2..6d846c3ecb 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -35,13 +35,18 @@ #include "zebra/zebra_rnh.h" #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" +#include "lib/json.h" extern int allow_delete; -static int do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi); +static int do_show_ip_route(struct vty *vty, const char *vrf_name, + safi_t safi, u_char use_json); static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast); +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND 60*60*24*7 + /* General function for static route. */ static int zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, @@ -278,7 +283,7 @@ DEFUN (show_ip_rpf, IP_STR "Display RPF information for multicast source\n") { - return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST); + return do_show_ip_route(vty, VRF_DEFAULT_NAME, SAFI_MULTICAST, 0); } DEFUN (show_ip_rpf_addr, @@ -1944,8 +1949,6 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) vty_out (vty, ", reject"); vty_out (vty, "%s", VTY_NEWLINE); -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 if (rib->type == ZEBRA_ROUTE_RIP || rib->type == ZEBRA_ROUTE_OSPF || rib->type == ZEBRA_ROUTE_ISIS @@ -2048,12 +2051,151 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) } static void -vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) +vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, + json_object *json) { struct nexthop *nexthop, *tnexthop; int recursing; int len = 0; char buf[BUFSIZ]; + json_object *json_nexthops = NULL; + json_object *json_nexthop = NULL; + json_object *json_route = NULL; + + if (json) + { + json_route = json_object_new_object(); + json_nexthops = json_object_new_array(); + + json_object_string_add(json_route, "prefix", prefix2str (&rn->p, buf, sizeof buf)); + json_object_string_add(json_route, "protocol", zebra_route_string(rib->type)); + + if (rib->instance) + json_object_int_add(json_route, "instance", rib->instance); + + if (rib->vrf_id) + json_object_int_add(json_route, "vrfId", rib->vrf_id); + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) + json_object_boolean_true_add(json_route, "selected"); + + if (rib->type != ZEBRA_ROUTE_CONNECT && rib->type != ZEBRA_ROUTE_KERNEL) + { + json_object_int_add(json_route, "distance", rib->distance); + json_object_int_add(json_route, "metric", rib->metric); + } + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) + json_object_boolean_true_add(json_route, "blackhole"); + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) + json_object_boolean_true_add(json_route, "reject"); + + if (rib->type == ZEBRA_ROUTE_RIP + || rib->type == ZEBRA_ROUTE_OSPF + || rib->type == ZEBRA_ROUTE_ISIS + || rib->type == ZEBRA_ROUTE_TABLE + || rib->type == ZEBRA_ROUTE_BGP) + { + time_t uptime; + struct tm *tm; + + uptime = time (NULL); + uptime -= rib->uptime; + tm = gmtime (&uptime); + + if (uptime < ONE_DAY_SECOND) + sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, tm->tm_min); + else + sprintf(buf, "%02dw%dd%02dh", tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); + + json_object_string_add(json_route, "uptime", buf); + } + + for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) + { + json_nexthop = json_object_new_object(); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + json_object_boolean_true_add(json_nexthop, "fib"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(json_nexthop, "ip", inet_ntoa (nexthop->gate.ipv4)); + json_object_string_add(json_nexthop, "afi", "ipv4"); + + if (nexthop->ifindex) + { + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add(json_nexthop, "ip", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + json_object_string_add(json_nexthop, "afi", "ipv6"); + + if (nexthop->ifindex) + { + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + } + break; + + case NEXTHOP_TYPE_IFINDEX: + json_object_boolean_true_add(json_nexthop, "directlyConnected"); + json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + json_object_boolean_true_add(json_nexthop, "blackhole"); + break; + default: + break; + } + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + json_object_boolean_true_add(json_nexthop, "active"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) + json_object_boolean_true_add(json_nexthop, "onLink"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + json_object_boolean_true_add(json_nexthop, "recursive"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) + { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) + json_object_string_add(json_nexthop, "source", buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) + json_object_string_add(json_nexthop, "source", buf); + } + break; + default: + break; + } + + json_object_array_add(json_nexthops, json_nexthop); + } + + json_object_object_add(json_route, "nexthops", json_nexthops); + json_object_array_add(json, json_route); + return; + } /* Nexthop information. */ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) @@ -2160,9 +2302,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) uptime -= rib->uptime; tm = gmtime (&uptime); -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 - if (uptime < ONE_DAY_SECOND) vty_out (vty, ", %02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -2180,62 +2319,112 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) DEFUN (show_ip_route, show_ip_route_cmd, - "show ip route", + "show ip route {json}", SHOW_STR IP_STR "IP routing table\n") { - return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST); + return do_show_ip_route (vty, VRF_DEFAULT_NAME, SAFI_UNICAST, use_json(argc, argv)); } static int -do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi) +do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi, + u_char use_json) { struct route_table *table; struct route_node *rn; struct rib *rib; int first = 1; struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; if (!(zvrf = zebra_vrf_list_lookup_by_name (vrf_name))) { - vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE); + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s not defined%s", vrf_name, VTY_NEWLINE); return CMD_SUCCESS; } if (zvrf->vrf_id == VRF_UNKNOWN) { - vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE); + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s inactive%s", vrf_name, VTY_NEWLINE); return CMD_SUCCESS; } table = zebra_vrf_table (AFI_IP, safi, zvrf->vrf_id); if (! table) - return CMD_SUCCESS; + { + if (use_json) + vty_out (vty, "{}%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + if (use_json) + { + json = json_object_new_object(); + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (!json_prefix) + json_prefix = json_object_new_array(); + vty_show_ip_route (vty, rn, rib, json_prefix); + } + + if (json_prefix) + { + prefix2str (&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } + else + { + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); + } + } + } - /* Show all IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } return CMD_SUCCESS; } DEFUN (show_ip_route_vrf, show_ip_route_vrf_cmd, - "show ip route " VRF_CMD_STR, + "show ip route " VRF_CMD_STR " {json}", SHOW_STR IP_STR "IP routing table\n" VRF_CMD_HELP_STR) { - return do_show_ip_route (vty, argv[0], SAFI_UNICAST); + u_char uj = use_json(argc, argv); + + if (argc == 1 && uj) + return do_show_ip_route (vty, NULL, SAFI_UNICAST, uj); + else + return do_show_ip_route (vty, argv[0], SAFI_UNICAST, uj); } DEFUN (show_ip_nht, @@ -2430,7 +2619,7 @@ DEFUN (show_ip_route_tag, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2490,7 +2679,7 @@ DEFUN (show_ip_route_prefix_longer, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2542,7 +2731,7 @@ DEFUN (show_ip_route_supernets, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } return CMD_SUCCESS; @@ -2600,7 +2789,7 @@ DEFUN (show_ip_route_protocol, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -2645,7 +2834,7 @@ DEFUN (show_ip_route_ospf_instance, vty_out (vty, SHOW_ROUTE_V4_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -3014,7 +3203,7 @@ DEFUN (show_ip_route_vrf_all, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3068,7 +3257,7 @@ DEFUN (show_ip_route_vrf_all_tag, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3124,7 +3313,7 @@ DEFUN (show_ip_route_vrf_all_prefix_longer, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -3177,7 +3366,7 @@ DEFUN (show_ip_route_vrf_all_supernets, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } vrf_header = 1; @@ -3233,7 +3422,7 @@ DEFUN (show_ip_route_vrf_all_protocol, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -4544,7 +4733,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref_tag_vrf, DEFUN (show_ipv6_route, show_ipv6_route_cmd, - "show ipv6 route", + "show ipv6 route {json}", SHOW_STR IP_STR "IPv6 routing table\n") @@ -4555,18 +4744,28 @@ DEFUN (show_ipv6_route, int first = 1; vrf_id_t vrf_id = VRF_DEFAULT; struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; + u_char uj = use_json(argc, argv); - if (argc > 0) + if (argc > 0 && argv[0] && strcmp(argv[0], "json") != 0) { if (!(zvrf = zebra_vrf_list_lookup_by_name (argv[0]))) { - vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE); + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s not defined%s", argv[0], VTY_NEWLINE); return CMD_SUCCESS; } if (zvrf->vrf_id == VRF_UNKNOWN) { - vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE); + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "vrf %s inactive%s", argv[0], VTY_NEWLINE); return CMD_SUCCESS; } else @@ -4575,25 +4774,60 @@ DEFUN (show_ipv6_route, table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) - return CMD_SUCCESS; + { + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + if (uj) + { + json = json_object_new_object(); + + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (!json_prefix) + json_prefix = json_object_new_array(); + vty_show_ip_route (vty, rn, rib, json_prefix); + } + + if (json_prefix) + { + prefix2str (&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } + else + { + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); + } + } + } - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } return CMD_SUCCESS; } ALIAS (show_ipv6_route, show_ipv6_route_vrf_cmd, - "show ipv6 route " VRF_CMD_STR, + "show ipv6 route " VRF_CMD_STR " {json}", SHOW_STR IP_STR "IPv6 routing table\n" @@ -4639,7 +4873,7 @@ DEFUN (show_ipv6_route_tag, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4699,7 +4933,7 @@ DEFUN (show_ipv6_route_prefix_longer, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4757,7 +4991,7 @@ DEFUN (show_ipv6_route_protocol, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -4983,7 +5217,7 @@ DEFUN (show_ipv6_mroute, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } return CMD_SUCCESS; } @@ -5033,7 +5267,7 @@ DEFUN (show_ipv6_route_vrf_all, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5087,7 +5321,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5144,7 +5378,7 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5199,7 +5433,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol, vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); vrf_header = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } vrf_header = 1; } @@ -5343,7 +5577,7 @@ DEFUN (show_ipv6_mroute_vrf_all, vty_out (vty, SHOW_ROUTE_V6_HEADER); first = 0; } - vty_show_ip_route (vty, rn, rib); + vty_show_ip_route (vty, rn, rib, NULL); } } return CMD_SUCCESS; From 19380819fc2b9361230053c19a0e27e7e9d0cee1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 6 Sep 2016 15:31:24 -0400 Subject: [PATCH 203/226] zebra: Line up help output better The -g, --group line of help didn't line up properly with the other help output of zebra. Fix this. Signed-off-by: Donald Sharp --- zebra/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/main.c b/zebra/main.c index 8a9857a04d..d8892f582a 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -150,7 +150,7 @@ usage (char *progname, int status) "-r, --retain When program terminates, retain added route "\ "by zebra.\n"\ "-u, --user User to run as\n"\ - "-g, --group Group to run as\n", progname); + "-g, --group Group to run as\n", progname); #ifdef HAVE_NETLINK printf ("-s, --nl-bufsize Set netlink receive buffer size\n"); #endif /* HAVE_NETLINK */ From 9374cd9b5b395ee97d0c376f83add1f8950f060b Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 31 Aug 2016 12:31:47 +0000 Subject: [PATCH 204/226] Quagga won't advertise 0.0.0.0/0 with network statement Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12561 (cherry picked from commit 337299a936d9db8951825dcbf3acc4bd3b89ac32) --- zebra/zebra_rnh.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 03ae466997..216a9d1cee 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -353,18 +353,17 @@ zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type, if (!rn) return NULL; - /* Do not resolve over default route unless allowed && - * match route to be exact if so specified + /* When resolving nexthops, do not resolve via the default route unless + * 'ip nht resolve-via-default' is configured. */ if ((type == RNH_NEXTHOP_TYPE) && (is_default_prefix (&rn->p) && !nh_resolve_via_default(rn->p.family))) rib = NULL; - else if ((type == RNH_IMPORT_CHECK_TYPE) && - ((is_default_prefix(&rn->p)) || - ((CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) && - !prefix_same(&nrn->p, &rn->p)))) - rib = NULL; + else if ((type == RNH_IMPORT_CHECK_TYPE) && + CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) && + !prefix_same(&nrn->p, &rn->p)) + rib = NULL; else { /* Identify appropriate route entry. */ From f4b6d7e9bf3e2e5c575c85060d86d1403a08bd30 Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:35:19 -0700 Subject: [PATCH 205/226] bgpd: Fix route install upon non-best nexthop change After BGP path selection, even if the best route entry selected has not changed, ensure that the route is installed again in zebra if any non-best but multipath route entry has a nexthop resolution change. In the absence of this fix, if a non-best multipath route entry had a nexthop resolution change (such as being resolved over two first hops instead of one), the route would get reinstalled into zebra only in some situations (i.e., when the best route entry had its IGP change flag set). If the route does not get reinstalled by BGP, the corresponding route in the zebra RIB would not have all the first hops. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Reviewed-by: Sid Khot Ticket: CM-12390 Reviewed By: CCR-5134 Testing Done: Manual, bgp-smoke (cherry picked from commit 3064bf43a7d8162dadada2934132f915a45d2bcb) --- bgpd/bgp_nht.c | 2 -- bgpd/bgp_route.c | 55 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9d8d8f3b52..23c64731aa 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -681,8 +681,6 @@ evaluate_paths (struct bgp_nexthop_cache *bnc) if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); - else - UNSET_FLAG (path->flags, BGP_INFO_IGP_CHANGED); bgp_process(bgp, rn, afi, SAFI_UNICAST); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f47e2f6074..26b5ef86d6 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1657,7 +1657,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, if (debug) zlog_debug("%s: %s is the bestpath, add to the multipath list", pfx_buf, path_buf); - bgp_mp_list_add (&mp_list, ri); + bgp_mp_list_add (&mp_list, ri); continue; } @@ -1749,6 +1749,50 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp, return 0; } +/* + * Clear IGP changed flag for a route (all paths). This is called at + * the end of route processing. + */ +static void +bgp_zebra_clear_route_change_flags (struct bgp_node *rn) +{ + struct bgp_info *ri; + + for (ri = rn->info; ri; ri = ri->next) + { + if (BGP_INFO_HOLDDOWN (ri)) + continue; + UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); + } +} + +/* + * Has the route changed from the RIB's perspective? This is invoked only + * if the route selection returns the same best route as earlier - to + * determine if we need to update zebra or not. + */ +static int +bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) +{ + struct bgp_info *mpinfo; + + /* There is a multipath change or best path has some nexthop change. */ + if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || + CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) + return 1; + + /* If this is multipath, check all selected paths for any nexthop change */ + for (mpinfo = bgp_info_mpath_first (selected); mpinfo; + mpinfo = bgp_info_mpath_next (mpinfo)) + { + if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED)) + return 1; + } + + /* Nothing has changed from the RIB's perspective. */ + return 0; +} + struct bgp_process_queue { struct bgp *bgp; @@ -1799,11 +1843,11 @@ bgp_process_main (struct work_queue *wq, void *data) !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && !bgp->addpath_tx_used[afi][safi]) { - if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) || - CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG)) + if (bgp_zebra_has_route_changed (rn, old_select)) bgp_zebra_announce (p, old_select, bgp, afi, safi); UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_zebra_clear_route_change_flags (rn); UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); return WQ_SUCCESS; } @@ -1856,7 +1900,10 @@ bgp_process_main (struct work_queue *wq, void *data) bgp_zebra_withdraw (p, old_select, safi); } } - + + /* Clear any route change flags. */ + bgp_zebra_clear_route_change_flags (rn); + /* Reap old select bgp_info, if it has been removed */ if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); From a60b9a3718274a065e825ca881eb4be32d38221c Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:49:16 -0700 Subject: [PATCH 206/226] bgpd: Fix route install upon multipath nexthop change In multipath selection, there can be a scenario where the set of route entries selected as multipath can be the same (i.e., from the same peers) but one or more of these may have a change to the BGP next hop. In this case, the route needs to be installed again in zebra even if the best route entry selected has not changed, otherwise the zebra RIB may have a different set of next hops (and first hops) than what the routing protocol selected. This patch handles this scenario by re-installing the route if any BGP attribute has changed for any of the multipaths. Not all BGP attributes are of relevance to the zebra RIB, but this approach follows existing logic used in the code (e.g., when BGP attributes for the best route entry has changed). Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Reviewed-by: Sid Khot Ticket: CM-12390 Reviewed By: CCR-5135 Testing Done: Manual, bgp-smoke (cherry picked from commit e10720512ef744483ffed8a6ef3b529ec97e130d) --- bgpd/bgp_route.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 26b5ef86d6..da50da9b1a 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1750,8 +1750,8 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp, } /* - * Clear IGP changed flag for a route (all paths). This is called at - * the end of route processing. + * Clear IGP changed flag and attribute changed flag for a route (all paths). + * This is called at the end of route processing. */ static void bgp_zebra_clear_route_change_flags (struct bgp_node *rn) @@ -1763,6 +1763,7 @@ bgp_zebra_clear_route_change_flags (struct bgp_node *rn) if (BGP_INFO_HOLDDOWN (ri)) continue; UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); + UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); } } @@ -1776,7 +1777,12 @@ bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) { struct bgp_info *mpinfo; - /* There is a multipath change or best path has some nexthop change. */ + /* If this is multipath, check all selected paths for any nexthop change or + * attribute change. Some attribute changes (e.g., community) aren't of + * relevance to the RIB, but we'll update zebra to ensure we handle the + * case of BGP nexthop change. This is the behavior when the best path has + * an attribute change anyway. + */ if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) return 1; @@ -1785,7 +1791,8 @@ bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) for (mpinfo = bgp_info_mpath_first (selected); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { - if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED)) + if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED) + || CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED)) return 1; } From 72a5e63bad506506073e06d452badcf35930f812 Mon Sep 17 00:00:00 2001 From: vivek Date: Mon, 5 Sep 2016 10:53:06 -0700 Subject: [PATCH 207/226] bgpd: Enhance path selection logs Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-12390 Reviewed By: CCR-5136 Testing Done: Manual (cherry picked from commit a6086ad4084a9dfbf930ef48e2987772767063bd) --- bgpd/bgp_mpath.c | 38 ++++++++++++++++++++++++++++++++------ bgpd/bgp_route.c | 32 +++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 8397177f8f..2395a66689 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -467,6 +467,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, bgp_info_mpath_dequeue (old_best); } + if (debug) + zlog_debug("%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d", + pfx_buf, new_best ? new_best->peer->host : "NONE", + listcount (mp_list), old_mpath_count); + /* * We perform an ordered walk through both lists in parallel. * The reason for the ordered walk is that if there are paths @@ -480,6 +485,8 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, */ while (mp_node || cur_mpath) { + struct bgp_info *tmp_info; + /* * We can bail out of this loop if all existing paths on the * multipath list have been visited (for cleanup purposes) and @@ -490,6 +497,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, mp_next_node = mp_node ? listnextnode (mp_node) : NULL; next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL; + tmp_info = mp_node ? listgetdata (mp_node) : NULL; + + if (debug) + zlog_debug("%s: comparing candidate %s with existing mpath %s", + pfx_buf, tmp_info ? tmp_info->peer->host : "NONE", + cur_mpath ? cur_mpath->peer->host : "NONE"); /* * If equal, the path was a multipath and is still a multipath. @@ -505,6 +518,12 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, bgp_info_mpath_enqueue (prev_mpath, cur_mpath); prev_mpath = cur_mpath; mpath_count++; + if (debug) + { + bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); + zlog_debug("%s: %s is still multipath, cur count %d", + pfx_buf, path_buf, mpath_count); + } } else { @@ -512,10 +531,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &cur_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } } mp_node = mp_next_node; @@ -538,10 +558,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s remove mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &cur_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } cur_mpath = next_mpath; } @@ -574,10 +595,11 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (debug) { bgp_info_path_with_addpath_rx_str(new_mpath, path_buf); - zlog_debug ("%s add mpath nexthop %s %s", pfx_buf, + zlog_debug ("%s: add mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, inet_ntop (AF_INET, &new_mpath->attr->nexthop, nh_buf[0], sizeof (nh_buf[0])), - path_buf); + mpath_count); } } mp_node = mp_next_node; @@ -586,6 +608,10 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, if (new_best) { + if (debug) + zlog_debug("%s: New mpath count (incl newbest) %d mpath-change %s", + pfx_buf, mpath_count, mpath_changed ? "YES" : "NO"); + bgp_info_mpath_count_set (new_best, mpath_count-1); if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count)) SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index da50da9b1a..f767fae1a9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -376,7 +376,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, } if (debug) - bgp_info_path_with_addpath_rx_str (exist, exist_buf); + { + bgp_info_path_with_addpath_rx_str (exist, exist_buf); + zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", + pfx_buf, new_buf, new->flags, exist_buf, exist->flags); + } newattr = new->attr; existattr = exist->attr; @@ -705,6 +709,15 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, * TODO: If unequal cost ibgp multipath is enabled we can * mark the paths as equal here instead of returning */ + if (debug) + { + if (ret == 1) + zlog_debug("%s: %s wins over %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + else + zlog_debug("%s: %s loses to %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + } return ret; } @@ -1638,14 +1651,19 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, /* Now that we know which path is the bestpath see if any of the other paths * qualify as multipaths */ + if (debug) + { + if (new_select) + bgp_info_path_with_addpath_rx_str (new_select, path_buf); + else + sprintf (path_buf, "NONE"); + zlog_debug("%s: After path selection, newbest is %s oldbest was %s", + pfx_buf, path_buf, + old_select ? old_select->peer->host : "NONE"); + } + if (do_mpath && new_select) { - if (debug) - { - bgp_info_path_with_addpath_rx_str (new_select, path_buf); - zlog_debug("%s: %s is the bestpath, now find multipaths", pfx_buf, path_buf); - } - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) { From 51f2d198c24107a91a32764bf0930c2d50954574 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 8 Sep 2016 13:16:25 +0000 Subject: [PATCH 208/226] quagga-reload.py fails for "net add debug ospf6 lsa as-ext" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12773 - change "as-ext" to "as-external" - drop "grp-mbr" option, it does not have a handler - drop "type7" option, it does not have a handler --- ospf6d/ospf6_lsa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 3f008d3d9f..35e5a91544 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -818,7 +818,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h) DEFUN (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_cmd, - "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)", + "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -862,7 +862,7 @@ DEFUN (debug_ospf6_lsa_type, ALIAS (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_detail_cmd, - "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)", + "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown) (originate|examine|flooding)", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -871,7 +871,7 @@ ALIAS (debug_ospf6_lsa_type, DEFUN (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_cmd, - "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)", + "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)", NO_STR DEBUG_STR OSPF6_STR @@ -915,7 +915,7 @@ DEFUN (no_debug_ospf6_lsa_type, ALIAS (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_detail_cmd, - "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)", + "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix) (originate|examine|flooding)", NO_STR DEBUG_STR OSPF6_STR From 80c2442a9b959afce944d75c62565a9659bf84f9 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 8 Sep 2016 09:38:53 -0700 Subject: [PATCH 209/226] lib, bgpd: Log next hops Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-12390 Reviewed By: CCR-5156 Testing Done: Manual --- bgpd/bgp_nht.c | 19 +++++++++++++++++-- lib/nexthop.c | 33 +++++++++++++++++++++++++++++++++ lib/nexthop.h | 4 ++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 23c64731aa..caf6fc2b41 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -370,8 +370,8 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id) { char buf[PREFIX2STR_BUFFER]; prefix2str(&p, buf, sizeof (buf)); - zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf, - metric, nexthop_num); + zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)", + vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num); } if (metric != bnc->metric) @@ -420,6 +420,13 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id) break; } + if (BGP_DEBUG(nht, NHT)) + { + char buf[NEXTHOP_STRLEN]; + zlog_debug(" nhop via %s", + nexthop2str (nexthop, buf, sizeof (buf))); + } + if (nhlist_tail) { nhlist_tail->next = nexthop; @@ -642,6 +649,14 @@ evaluate_paths (struct bgp_nexthop_cache *bnc) int afi; struct peer *peer = (struct peer *)bnc->nht_info; + if (BGP_DEBUG(nht, NHT)) + { + char buf[PREFIX2STR_BUFFER]; + bnc_str(bnc, buf, PREFIX2STR_BUFFER); + zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths", + buf, bnc->flags, bnc->change_flags); + } + LIST_FOREACH(path, &(bnc->paths), nh_thread) { if (!(path->type == ZEBRA_ROUTE_BGP && diff --git a/lib/nexthop.c b/lib/nexthop.c index 5853884218..14486ea157 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -153,3 +153,36 @@ nexthops_free (struct nexthop *nexthop) nexthop_free (nh); } } + +const char * +nexthop2str (struct nexthop *nexthop, char *str, int size) +{ + switch (nexthop->type) + { + case NEXTHOP_TYPE_IFINDEX: + snprintf (str, size, "if %u", nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV4: + snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + snprintf (str, size, "%s if %u", + inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6)); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + snprintf (str, size, "%s if %u", + inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex); + break; + case NEXTHOP_TYPE_BLACKHOLE: + snprintf (str, size, "blackhole"); + break; + default: + snprintf (str, size, "unknown"); + break; + } + + return str; +} diff --git a/lib/nexthop.h b/lib/nexthop.h index eb9b27ea9e..725eb537af 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -26,6 +26,9 @@ #include "prefix.h" +/* Maximum next hop string length - gateway + ifindex */ +#define NEXTHOP_STRLEN (INET6_ADDRSTRLEN + 30) + union g_addr { struct in_addr ipv4; struct in6_addr ipv6; @@ -97,4 +100,5 @@ void nexthops_free (struct nexthop *nexthop); extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type); extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2); +extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size); #endif /*_LIB_NEXTHOP_H */ From 8c4f63817a1861adf8dba97849c4ef60b17432bc Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 8 Sep 2016 10:03:30 -0700 Subject: [PATCH 210/226] bgpd: Process directly connected IBGP peers upon interface down When we have a single-hop BFD session for any peering, it really means that the peering is directly connected (maybe over a L2 network), whether it is IBGP or EBGP. In such a case, upon link down, immediately process IBGP peers too (and bring them down), not just EBGP peers. This change eliminates some peculiar state transitions in specific IBGP topologies, thus getting rid of the problem of nexthops remaining inactive in the zebra RIB. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-12390 Reviewed By: CCR-5156 Testing Done: Manual, bgp-smoke --- bgpd/bgp_bfd.c | 2 +- bgpd/bgp_bfd.h | 3 +++ bgpd/bgp_zebra.c | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index b8b0053695..aeac93e7b3 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -71,7 +71,7 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) /* * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop. */ -static int +int bgp_bfd_is_peer_multihop(struct peer *peer) { struct bfd_info *bfd_info; diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index 4e554af696..e872637e3e 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -42,4 +42,7 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh); +extern int +bgp_bfd_is_peer_multihop(struct peer *peer); + #endif /* _QUAGGA_BGP_BFD_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index b4bac840e3..6e17d778ab 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */ #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_nht.h" +#include "bgpd/bgp_bfd.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -358,7 +359,16 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { +#if defined(HAVE_CUMULUS) + /* Take down directly connected EBGP peers as well as 1-hop BFD + * tracked (directly connected) IBGP peers. + */ + if ((peer->ttl != 1) && (peer->gtsm_hops != 1) && + (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer))) +#else + /* Take down directly connected EBGP peers */ if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) +#endif continue; if (ifp == peer->nexthop.ifp) From dcaf0c593f8967cc2d9b3960abc525632d217c6c Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 8 Sep 2016 13:16:25 +0000 Subject: [PATCH 211/226] quagga-reload.py fails for "net add debug ospf6 lsa as-ext" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12773 - change "as-ext" to "as-external" - drop "grp-mbr" option, it does not have a handler - drop "type7" option, it does not have a handler (cherry picked from commit 51f2d198c24107a91a32764bf0930c2d50954574) --- ospf6d/ospf6_lsa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 3f008d3d9f..35e5a91544 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -818,7 +818,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h) DEFUN (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_cmd, - "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)", + "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -862,7 +862,7 @@ DEFUN (debug_ospf6_lsa_type, ALIAS (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_detail_cmd, - "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)", + "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown) (originate|examine|flooding)", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -871,7 +871,7 @@ ALIAS (debug_ospf6_lsa_type, DEFUN (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_cmd, - "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)", + "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown)", NO_STR DEBUG_STR OSPF6_STR @@ -915,7 +915,7 @@ DEFUN (no_debug_ospf6_lsa_type, ALIAS (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_detail_cmd, - "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)", + "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-external|link|intra-prefix) (originate|examine|flooding)", NO_STR DEBUG_STR OSPF6_STR From b5826a12a2a4c4a9e4ccd267f47e2711683355f7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Sep 2016 18:48:02 -0400 Subject: [PATCH 212/226] bgpd: Allow bgp to work standalone Signed-off-by: Donald Sharp --- bgpd/bgp_fsm.c | 2 ++ bgpd/bgp_network.c | 6 ++++++ configure.ac | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index ae77ac421a..046767177b 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1332,8 +1332,10 @@ bgp_start (struct peer *peer) if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s [FSM] Waiting for NHT", peer->host); +#if !defined (HAVE_BGP_STANDALONE) BGP_EVENT_ADD(peer, TCP_connection_open_failed); return 0; +#endif } status = bgp_connect (peer); diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 58761a11d0..ecfc3f9fe8 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -253,9 +253,13 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len); if (rc != 0) { +#if !defined (HAVE_BGP_STANDALONE) zlog_err ("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", safe_strerror (errno), sock); return -1; +#else + strcpy (name, VRF_DEFAULT_NAME); +#endif } if (!strlen(name)) @@ -671,7 +675,9 @@ bgp_getsockname (struct peer *peer) { zlog_err ("%s: nexthop_set failed, resetting connection - intf %p", peer->host, peer->nexthop.ifp); +#if !defined (HAVE_BGP_STANDALONE) return -1; +#endif } return 0; diff --git a/configure.ac b/configure.ac index e01af9e55e..b1ea4821e2 100755 --- a/configure.ac +++ b/configure.ac @@ -317,6 +317,8 @@ AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)])) AC_ARG_ENABLE(cumulus, AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions])) +AC_ARG_ENABLE(bgp-standalone, + AS_HELP_STRING([--enable-bgp-standalone], [Modify code to allow BGP to work without Zebra])) AC_ARG_ENABLE(rr-semantics, AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics])) @@ -368,6 +370,10 @@ if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) fi +if test "${enable_bgp_standalone}" = "yes" ; then + AC_DEFINE(HAVE_BGP_STANDALONE,,Allow BGP to work without Zebra) +fi + if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) fi From 1bce440338a30a20ec06b3dbf7b8fa5031ad363a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 14:46:34 -0400 Subject: [PATCH 213/226] quagga: remove refix directory from git status During one of our build processes we are getting a refix directory in some places. Remove these from files that git considers Signed-off-by: Donald Sharp (cherry picked from commit 844cbf5d6cdfc6961e99e1c9ed35b826f3aa7562) --- doc/.gitignore | 1 + lib/.gitignore | 1 + ospfclient/.gitignore | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/.gitignore b/doc/.gitignore index 5071f98707..66c43c73e6 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -32,3 +32,4 @@ stamp-vti .arch-ids *~ *.loT +refix diff --git a/lib/.gitignore b/lib/.gitignore index 02aa432ce1..a25bae5aae 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -16,3 +16,4 @@ gitversion.h.tmp *.loT memtypes.h route_types.h +refix diff --git a/ospfclient/.gitignore b/ospfclient/.gitignore index 191322b6a1..a6000f8021 100644 --- a/ospfclient/.gitignore +++ b/ospfclient/.gitignore @@ -13,4 +13,4 @@ TAGS .arch-ids *~ *.loT - +refix From bc06d287d100c0845eb065b96838c81aebf83468 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 9 Sep 2016 08:48:23 -0400 Subject: [PATCH 214/226] bgpd: Fix standalone to better handle getsockopt failure When getsockopt(...,SO_BINDTODEVICE,...); fails assume the bgp instance we are interested is the default one. Signed-off-by: Donald Sharp --- bgpd/bgp_network.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index ecfc3f9fe8..a6e9b7de00 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -257,13 +257,14 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) zlog_err ("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", safe_strerror (errno), sock); return -1; -#else - strcpy (name, VRF_DEFAULT_NAME); #endif } if (!strlen(name)) - return 0; /* default instance. */ + { + *bgp_inst = bgp_get_default (); + return 0; /* default instance. */ + } /* First try match to instance; if that fails, check for interfaces. */ bgp = bgp_lookup_by_name (name); From 7709c62dc6bf7cea59d756bcffe1efd1f85646f8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 9 Sep 2016 09:46:28 -0400 Subject: [PATCH 215/226] bgpd: Display 'no neighbor 192.168.33.44 activate' Since the default for ipv4 unicast is to now assume that the neighbor is activated, print out the no neighbor 192.168.33.44 activate line when it is explicitly turned off. Ticket: CM-12809 Reported-by: Lou Berger Signed-off-by: Donald Sharp Reviewed-by: --- bgpd/bgpd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 87e5c54ea2..bfde53d3e4 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6739,6 +6739,18 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, " neighbor %s activate%s", addr, VTY_NEWLINE); } + else + { + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) + { + if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s activate%s", + addr, VTY_NEWLINE); + } + } + } } /* addpath TX knobs */ From 1d808091d34785df0d8e62f5b388a25af48f9a93 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 9 Sep 2016 11:02:54 -0400 Subject: [PATCH 216/226] bgpd: Allow connections with no v4|6 addr's in some conditions When compiling/running in with --enable-bgp-standalone=yes allow v4 sessions to be established with no v4 address configured. Additionally allow v6 connections with no v6 addresses configured. Signed-off-by: Donald Sharp --- bgpd/bgp_packet.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 937623a30b..2f9fdd5a75 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1163,10 +1163,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) { if (!peer->nexthop.v4.s_addr) { +#if !defined (HAVE_BGP_STANDALONE) zlog_err ("%s: No local IPv4 addr resetting connection, fd %d", peer->host, peer->fd); bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); return -1; +#endif } } if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] || @@ -1176,10 +1178,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) { if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global)) { +#if !defined (HAVE_BGP_STANDALONE) zlog_err ("%s: No local IPv6 addr resetting connection, fd %d", peer->host, peer->fd); bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); return -1; +#endif } } peer->rtt = sockopt_tcp_rtt (peer->fd); From 020a8459245c9b1ed707cf36ce3b19c286105748 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Wed, 24 Aug 2016 15:32:00 +0200 Subject: [PATCH 217/226] zebra: remove unused code from zebra netlink --- zebra/kernel_null.c | 3 -- zebra/rt.h | 5 +- zebra/rt_ioctl.c | 110 -------------------------------------------- 3 files changed, 1 insertion(+), 117 deletions(-) diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index b90c6f57f9..17b3c7bc8d 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -39,9 +39,6 @@ int kernel_add_ipv6 (struct prefix *a, struct rib *b) { return 0; } int kernel_update_ipv6 (struct prefix *a, struct rib *b) { return 0; } int kernel_delete_ipv6 (struct prefix *a, struct rib *b) { return 0; } -int kernel_add_route (struct prefix_ipv4 *a, struct in_addr *b, int c, int d) -{ return 0; } - int kernel_address_add_ipv4 (struct interface *a, struct connected *b) { zlog_debug ("%s", __func__); diff --git a/zebra/rt.h b/zebra/rt.h index 4515d56a38..46e71fa46e 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -30,16 +30,13 @@ extern int kernel_add_ipv4 (struct prefix *, struct rib *); extern int kernel_update_ipv4 (struct prefix *, struct rib *); extern int kernel_delete_ipv4 (struct prefix *, struct rib *); -extern int kernel_add_route (struct prefix_ipv4 *, struct in_addr *, int, int); + extern int kernel_address_add_ipv4 (struct interface *, struct connected *); extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); extern int kernel_neigh_update (int, int, uint32_t, char *, int); -#ifdef HAVE_IPV6 extern int kernel_add_ipv6 (struct prefix *, struct rib *); extern int kernel_update_ipv6 (struct prefix *, struct rib *); extern int kernel_delete_ipv6 (struct prefix *, struct rib *); -#endif /* HAVE_IPV6 */ - #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_ioctl.c b/zebra/rt_ioctl.c index 383c5f71ac..597392c38a 100644 --- a/zebra/rt_ioctl.c +++ b/zebra/rt_ioctl.c @@ -46,121 +46,11 @@ kernel_read (int sock) return; } -#if 0 -/* Initialization prototype of struct sockaddr_in. */ -static struct sockaddr_in sin_proto = -{ -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sizeof (struct sockaddr_in), -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - AF_INET, 0, {0}, {0} -}; -#endif /* 0 */ - /* Solaris has ortentry. */ #ifdef HAVE_OLD_RTENTRY #define rtentry ortentry #endif /* HAVE_OLD_RTENTRY */ -/* Interface to ioctl route message. */ -int -kernel_add_route (struct prefix_ipv4 *dest, struct in_addr *gate, - int index, int flags) -{ - int ret; - int sock; - struct rtentry rtentry; - struct sockaddr_in sin_dest, sin_mask, sin_gate; - - memset (&rtentry, 0, sizeof (struct rtentry)); - - /* Make destination. */ - memset (&sin_dest, 0, sizeof (struct sockaddr_in)); - sin_dest.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_dest.sin_len = sizeof (struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sin_dest.sin_addr = dest->prefix; - - /* Make gateway. */ - if (gate) - { - memset (&sin_gate, 0, sizeof (struct sockaddr_in)); - sin_gate.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin_len = sizeof (struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sin_gate.sin_addr = *gate; - } - - memset (&sin_mask, 0, sizeof (struct sockaddr_in)); - sin_mask.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin_len = sizeof (struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - masklen2ip (dest->prefixlen, &sin_mask.sin_addr); - - /* Set destination address, mask and gateway.*/ - memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in)); - if (gate) - memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in)); -#ifndef SUNOS_5 - memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in)); -#endif /* SUNOS_5 */ - - /* Routing entry flag set. */ - if (dest->prefixlen == 32) - rtentry.rt_flags |= RTF_HOST; - - if (gate && gate->s_addr != INADDR_ANY) - rtentry.rt_flags |= RTF_GATEWAY; - - rtentry.rt_flags |= RTF_UP; - - /* Additional flags */ - rtentry.rt_flags |= flags; - - - /* For tagging route. */ - /* rtentry.rt_flags |= RTF_DYNAMIC; */ - - /* Open socket for ioctl. */ - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_warn ("can't make socket\n"); - return -1; - } - - /* Send message by ioctl(). */ - ret = ioctl (sock, SIOCADDRT, &rtentry); - if (ret < 0) - { - switch (errno) - { - case EEXIST: - close (sock); - return ZEBRA_ERR_RTEXIST; - break; - case ENETUNREACH: - close (sock); - return ZEBRA_ERR_RTUNREACH; - break; - case EPERM: - close (sock); - return ZEBRA_ERR_EPERM; - break; - } - - close (sock); - zlog_warn ("write : %s (%d)", safe_strerror (errno), errno); - return 1; - } - close (sock); - - return ret; -} - /* Interface to ioctl route message. */ static int kernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family) From bab85d4fcbc55577019bd746b9cc9073778721ce Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Wed, 24 Aug 2016 17:09:14 +0200 Subject: [PATCH 218/226] zebra: assorted parts of 0abf6796c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Author: Timo Teräs Date: Fri Jan 15 17:36:29 2016 +0200 zebra: atomic FIB updates This commit updates the kernel API so that route changes are atomically updated using change/replaces messages instead of first sending a withdraw followed with update. Same for zclient updates, changes are sent as single ADD instead of DELETE + ADD. Signed-off-by: Timo Teräs --- zebra/zebra_rib.c | 105 ++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 23ec8dab9a..3812101431 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1574,6 +1574,48 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } +/* Check if 'alternate' RIB entry is better than 'current'. */ +static struct rib * +rib_choose_best (struct rib *current, struct rib *alternate) +{ + if (current == NULL) + return alternate; + + /* filter route selection in following order: + * - connected beats other types + * - lower distance beats higher + * - lower metric beats higher for equal distance + * - last, hence oldest, route wins tie break. + */ + + /* Connected routes. Pick the last connected + * route of the set of lowest metric connected routes. + */ + if (alternate->type == ZEBRA_ROUTE_CONNECT) + { + if (current->type != ZEBRA_ROUTE_CONNECT + || alternate->metric <= current->metric) + return alternate; + + return current; + } + + if (current->type == ZEBRA_ROUTE_CONNECT) + return current; + + /* higher distance loses */ + if (alternate->distance < current->distance) + return alternate; + if (current->distance < alternate->distance) + return current; + + /* metric tie-breaks equal distance */ + if (alternate->metric <= current->metric) + return alternate; + + return current; +} + /* Core function for processing routing information base. */ static void rib_process (struct route_node *rn) @@ -1583,6 +1625,7 @@ rib_process (struct route_node *rn) struct rib *fib = NULL; struct rib *select = NULL; struct rib *del = NULL; + struct rib *best = NULL; char buf[INET6_ADDRSTRLEN]; rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; @@ -1683,62 +1726,12 @@ rib_process (struct route_node *rn) continue; } - /* Newly selected rib, the common case. */ - if (!select) - { - select = rib; - continue; - } - - /* filter route selection in following order: - * - connected beats other types - * - lower distance beats higher - * - lower metric beats higher for equal distance - * - last, hence oldest, route wins tie break. - */ - - /* Connected routes. Pick the last connected - * route of the set of lowest metric connected routes. - */ - if (rib->type == ZEBRA_ROUTE_CONNECT) - { - if (select->type != ZEBRA_ROUTE_CONNECT - || rib->metric <= select->metric) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - } - else - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - else if (select->type == ZEBRA_ROUTE_CONNECT) - { - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - - /* higher distance loses */ - if (rib->distance > select->distance) - { - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - - /* lower wins */ - if (rib->distance < select->distance) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - continue; - } - - /* metric tie-breaks equal distance */ - if (rib->metric <= select->metric) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - } + best = rib_choose_best(select, rib); + if (select && best != select) + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); + if (best != rib) + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); + select = best; } /* RNODE_FOREACH_RIB_SAFE */ /* After the cycle is finished, the following pointers will be set: From 32bcb8b0a54e1468e8fe9e303ba78a71ce05cf3d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 3 Sep 2016 20:45:35 -0400 Subject: [PATCH 219/226] lib: Create ns.c Create the ns.c files from the original vrf.c code to allow us to create the 'logical-router' command to work within namespaces. Signed-off-by: Donald Sharp --- lib/Makefile.am | 4 +- lib/memtypes.c | 3 + lib/ns.c | 503 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/ns.h | 142 ++++++++++++++ 4 files changed, 650 insertions(+), 2 deletions(-) create mode 100644 lib/ns.c create mode 100644 lib/ns.h diff --git a/lib/Makefile.am b/lib/Makefile.am index ada31a0d21..5a970c881d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ libzebra_la_SOURCES = \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \ - ptm_lib.c csv.c bfd.c vrf.c systemd.c + ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c BUILT_SOURCES = memtypes.h route_types.h gitversion.h @@ -30,7 +30,7 @@ pkginclude_HEADERS = \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ workqueue.h route_types.h libospf.h nexthop.h json.h \ - ptm_lib.h csv.h bfd.h vrf.h systemd.h bitfield.h + ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h noinst_HEADERS = \ plist_int.h diff --git a/lib/memtypes.c b/lib/memtypes.c index 56d4faead5..510312f336 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -77,6 +77,9 @@ struct memory_list memory_list_lib[] = { MTYPE_VRF, "VRF" }, { MTYPE_VRF_NAME, "VRF name" }, { MTYPE_VRF_BITMAP, "VRF bit-map" }, + { MTYPE_NS, "Logical-Router" }, + { MTYPE_NS_NAME, "Logical-Router Name" }, + { MTYPE_NS_BITMAP, "Logical-Router bit-map" }, { MTYPE_IF_LINK_PARAMS, "Informational Link Parameters" }, { -1, NULL }, }; diff --git a/lib/ns.c b/lib/ns.c new file mode 100644 index 0000000000..daaffc6b09 --- /dev/null +++ b/lib/ns.c @@ -0,0 +1,503 @@ +/* + * NS functions. + * Copyright (C) 2014 6WIND S.A. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "if.h" +#include "ns.h" +#include "prefix.h" +#include "table.h" +#include "log.h" +#include "memory.h" + +#define NS_DEFAULT_NAME "Default-logical-router" + +struct ns +{ + /* Identifier, same as the vector index */ + ns_id_t ns_id; + /* Name */ + char *name; + + /* Master list of interfaces belonging to this NS */ + struct list *iflist; + + /* User data */ + void *info; +}; + +/* Holding NS hooks */ +struct ns_master +{ + int (*ns_new_hook) (ns_id_t, void **); + int (*ns_delete_hook) (ns_id_t, void **); + int (*ns_enable_hook) (ns_id_t, void **); + int (*ns_disable_hook) (ns_id_t, void **); +} ns_master = {0,}; + +/* NS table */ +struct route_table *ns_table = NULL; + +static int ns_is_enabled (struct ns *ns); +static int ns_enable (struct ns *ns); +static void ns_disable (struct ns *ns); + + +/* Build the table key */ +static void +ns_build_key (ns_id_t ns_id, struct prefix *p) +{ + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4.s_addr = ns_id; +} + +/* Get a NS. If not found, create one. */ +static struct ns * +ns_get (ns_id_t ns_id) +{ + struct prefix p; + struct route_node *rn; + struct ns *ns; + + ns_build_key (ns_id, &p); + rn = route_node_get (ns_table, &p); + if (rn->info) + { + ns = (struct ns *)rn->info; + route_unlock_node (rn); /* get */ + return ns; + } + + ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); + ns->ns_id = ns_id; + rn->info = ns; + + /* + * Initialize interfaces. + * + * I'm not sure if this belongs here or in + * the vrf code. + */ + // if_init (&ns->iflist); + + zlog_info ("NS %u is created.", ns_id); + + if (ns_master.ns_new_hook) + (*ns_master.ns_new_hook) (ns_id, &ns->info); + + return ns; +} + +/* Delete a NS. This is called in ns_terminate(). */ +static void +ns_delete (struct ns *ns) +{ + zlog_info ("NS %u is to be deleted.", ns->ns_id); + + if (ns_is_enabled (ns)) + ns_disable (ns); + + if (ns_master.ns_delete_hook) + (*ns_master.ns_delete_hook) (ns->ns_id, &ns->info); + + /* + * I'm not entirely sure if the vrf->iflist + * needs to be moved into here or not. + */ + //if_terminate (&ns->iflist); + + if (ns->name) + XFREE (MTYPE_NS_NAME, ns->name); + + XFREE (MTYPE_NS, ns); +} + +/* Look up a NS by identifier. */ +static struct ns * +ns_lookup (ns_id_t ns_id) +{ + struct prefix p; + struct route_node *rn; + struct ns *ns = NULL; + + ns_build_key (ns_id, &p); + rn = route_node_lookup (ns_table, &p); + if (rn) + { + ns = (struct ns *)rn->info; + route_unlock_node (rn); /* lookup */ + } + return ns; +} + +/* + * Check whether the NS is enabled - that is, whether the NS + * is ready to allocate resources. Currently there's only one + * type of resource: socket. + */ +static int +ns_is_enabled (struct ns *ns) +{ + return ns && ns->ns_id == NS_DEFAULT; +} + +/* + * Enable a NS - that is, let the NS be ready to use. + * The NS_ENABLE_HOOK callback will be called to inform + * that they can allocate resources in this NS. + * + * RETURN: 1 - enabled successfully; otherwise, 0. + */ +static int +ns_enable (struct ns *ns) +{ + /* Till now, only the default NS can be enabled. */ + if (ns->ns_id == NS_DEFAULT) + { + zlog_info ("NS %u is enabled.", ns->ns_id); + + if (ns_master.ns_enable_hook) + (*ns_master.ns_enable_hook) (ns->ns_id, &ns->info); + + return 1; + } + + return 0; +} + +/* + * Disable a NS - that is, let the NS be unusable. + * The NS_DELETE_HOOK callback will be called to inform + * that they must release the resources in the NS. + */ +static void +ns_disable (struct ns *ns) +{ + if (ns_is_enabled (ns)) + { + zlog_info ("NS %u is to be disabled.", ns->ns_id); + + /* Till now, nothing to be done for the default NS. */ + + if (ns_master.ns_disable_hook) + (*ns_master.ns_disable_hook) (ns->ns_id, &ns->info); + } +} + + +/* Add a NS hook. Please add hooks before calling ns_init(). */ +void +ns_add_hook (int type, int (*func)(ns_id_t, void **)) +{ + switch (type) { + case NS_NEW_HOOK: + ns_master.ns_new_hook = func; + break; + case NS_DELETE_HOOK: + ns_master.ns_delete_hook = func; + break; + case NS_ENABLE_HOOK: + ns_master.ns_enable_hook = func; + break; + case NS_DISABLE_HOOK: + ns_master.ns_disable_hook = func; + break; + default: + break; + } +} + +/* Return the iterator of the first NS. */ +ns_iter_t +ns_first (void) +{ + struct route_node *rn; + + for (rn = route_top (ns_table); rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* top/next */ + return (ns_iter_t)rn; + } + return NS_ITER_INVALID; +} + +/* Return the next NS iterator to the given iterator. */ +ns_iter_t +ns_next (ns_iter_t iter) +{ + struct route_node *rn = NULL; + + /* Lock it first because route_next() will unlock it. */ + if (iter != NS_ITER_INVALID) + rn = route_next (route_lock_node ((struct route_node *)iter)); + + for (; rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* next */ + return (ns_iter_t)rn; + } + return NS_ITER_INVALID; +} + +/* Return the NS iterator of the given NS ID. If it does not exist, + * the iterator of the next existing NS is returned. */ +ns_iter_t +ns_iterator (ns_id_t ns_id) +{ + struct prefix p; + struct route_node *rn; + + ns_build_key (ns_id, &p); + rn = route_node_get (ns_table, &p); + if (rn->info) + { + /* OK, the NS exists. */ + route_unlock_node (rn); /* get */ + return (ns_iter_t)rn; + } + + /* Find the next NS. */ + for (rn = route_next (rn); rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* next */ + return (ns_iter_t)rn; + } + + return NS_ITER_INVALID; +} + +/* Obtain the NS ID from the given NS iterator. */ +ns_id_t +ns_iter2id (ns_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct ns *)rn->info)->ns_id : NS_DEFAULT; +} + +/* Obtain the data pointer from the given NS iterator. */ +void * +ns_iter2info (ns_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct ns *)rn->info)->info : NULL; +} + +/* Obtain the interface list from the given NS iterator. */ +struct list * +ns_iter2iflist (ns_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct ns *)rn->info)->iflist : NULL; +} + +/* Get the data pointer of the specified NS. If not found, create one. */ +void * +ns_info_get (ns_id_t ns_id) +{ + struct ns *ns = ns_get (ns_id); + return ns->info; +} + +/* Look up the data pointer of the specified NS. */ +void * +ns_info_lookup (ns_id_t ns_id) +{ + struct ns *ns = ns_lookup (ns_id); + return ns ? ns->info : NULL; +} + +/* Look up the interface list in a NS. */ +struct list * +ns_iflist (ns_id_t ns_id) +{ + struct ns * ns = ns_lookup (ns_id); + return ns ? ns->iflist : NULL; +} + +/* Get the interface list of the specified NS. Create one if not find. */ +struct list * +ns_iflist_get (ns_id_t ns_id) +{ + struct ns * ns = ns_get (ns_id); + return ns->iflist; +} + +/* + * NS bit-map + */ + +#define NS_BITMAP_NUM_OF_GROUPS 8 +#define NS_BITMAP_NUM_OF_BITS_IN_GROUP \ + (UINT16_MAX / NS_BITMAP_NUM_OF_GROUPS) +#define NS_BITMAP_NUM_OF_BYTES_IN_GROUP \ + (NS_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ + +#define NS_BITMAP_GROUP(_id) \ + ((_id) / NS_BITMAP_NUM_OF_BITS_IN_GROUP) +#define NS_BITMAP_BIT_OFFSET(_id) \ + ((_id) % NS_BITMAP_NUM_OF_BITS_IN_GROUP) + +#define NS_BITMAP_INDEX_IN_GROUP(_bit_offset) \ + ((_bit_offset) / CHAR_BIT) +#define NS_BITMAP_FLAG(_bit_offset) \ + (((u_char)1) << ((_bit_offset) % CHAR_BIT)) + +struct ns_bitmap +{ + u_char *groups[NS_BITMAP_NUM_OF_GROUPS]; +}; + +ns_bitmap_t +ns_bitmap_init (void) +{ + return (ns_bitmap_t) XCALLOC (MTYPE_NS_BITMAP, sizeof (struct ns_bitmap)); +} + +void +ns_bitmap_free (ns_bitmap_t bmap) +{ + struct ns_bitmap *bm = (struct ns_bitmap *) bmap; + int i; + + if (bmap == NS_BITMAP_NULL) + return; + + for (i = 0; i < NS_BITMAP_NUM_OF_GROUPS; i++) + if (bm->groups[i]) + XFREE (MTYPE_NS_BITMAP, bm->groups[i]); + + XFREE (MTYPE_NS_BITMAP, bm); +} + +void +ns_bitmap_set (ns_bitmap_t bmap, ns_id_t ns_id) +{ + struct ns_bitmap *bm = (struct ns_bitmap *) bmap; + u_char group = NS_BITMAP_GROUP (ns_id); + u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); + + if (bmap == NS_BITMAP_NULL) + return; + + if (bm->groups[group] == NULL) + bm->groups[group] = XCALLOC (MTYPE_NS_BITMAP, + NS_BITMAP_NUM_OF_BYTES_IN_GROUP); + + SET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], + NS_BITMAP_FLAG (offset)); +} + +void +ns_bitmap_unset (ns_bitmap_t bmap, ns_id_t ns_id) +{ + struct ns_bitmap *bm = (struct ns_bitmap *) bmap; + u_char group = NS_BITMAP_GROUP (ns_id); + u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); + + if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) + return; + + UNSET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], + NS_BITMAP_FLAG (offset)); +} + +int +ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id) +{ + struct ns_bitmap *bm = (struct ns_bitmap *) bmap; + u_char group = NS_BITMAP_GROUP (ns_id); + u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); + + if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) + return 0; + + return CHECK_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], + NS_BITMAP_FLAG (offset)) ? 1 : 0; +} + +/* Initialize NS module. */ +void +ns_init (void) +{ + struct ns *default_ns; + + /* Allocate NS table. */ + ns_table = route_table_init (); + + /* The default NS always exists. */ + default_ns = ns_get (NS_DEFAULT); + if (!default_ns) + { + zlog_err ("ns_init: failed to create the default NS!"); + exit (1); + } + + /* Set the default NS name. */ + default_ns->name = XSTRDUP (MTYPE_NS_NAME, NS_DEFAULT_NAME); + + /* Enable the default NS. */ + if (!ns_enable (default_ns)) + { + zlog_err ("ns_init: failed to enable the default NS!"); + exit (1); + } +} + +/* Terminate NS module. */ +void +ns_terminate (void) +{ + struct route_node *rn; + struct ns *ns; + + for (rn = route_top (ns_table); rn; rn = route_next (rn)) + if ((ns = rn->info) != NULL) + ns_delete (ns); + + route_table_finish (ns_table); + ns_table = NULL; +} + +/* Create a socket for the NS. */ +int +ns_socket (int domain, int type, int protocol, ns_id_t ns_id) +{ + int ret = -1; + + if (!ns_is_enabled (ns_lookup (ns_id))) + { + errno = ENOSYS; + return -1; + } + + if (ns_id == NS_DEFAULT) + ret = socket (domain, type, protocol); + else + errno = ENOSYS; + + return ret; +} + diff --git a/lib/ns.h b/lib/ns.h new file mode 100644 index 0000000000..81e24562c3 --- /dev/null +++ b/lib/ns.h @@ -0,0 +1,142 @@ +/* + * NS related header. + * Copyright (C) 2014 6WIND S.A. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ZEBRA_NS_H +#define _ZEBRA_NS_H + +#include "linklist.h" + +typedef u_int16_t ns_id_t; + +/* The default NS ID */ +#define NS_DEFAULT 0 + +/* + * The command strings + */ + +#define NS_CMD_STR "logical-router <0-65535>" +#define NS_CMD_HELP_STR "Specify the Logical-Router\nThe Logical-Router ID\n" + +#define NS_ALL_CMD_STR "logical-router all" +#define NS_ALL_CMD_HELP_STR "Specify the logical-router\nAll logical-router's\n" + +/* + * NS hooks + */ + +#define NS_NEW_HOOK 0 /* a new logical-router is just created */ +#define NS_DELETE_HOOK 1 /* a logical-router is to be deleted */ +#define NS_ENABLE_HOOK 2 /* a logical-router is ready to use */ +#define NS_DISABLE_HOOK 3 /* a logical-router is to be unusable */ + +/* + * Add a specific hook ns module. + * @param1: hook type + * @param2: the callback function + * - param 1: the NS ID + * - param 2: the address of the user data pointer (the user data + * can be stored in or freed from there) + */ +extern void ns_add_hook (int, int (*)(ns_id_t, void **)); + +/* + * NS iteration + */ + +typedef void * ns_iter_t; +#define NS_ITER_INVALID NULL /* invalid value of the iterator */ + +/* + * NS iteration utilities. Example for the usage: + * + * ns_iter_t iter = ns_first(); + * for (; iter != NS_ITER_INVALID; iter = ns_next (iter)) + * + * or + * + * ns_iter_t iter = ns_iterator (); + * for (; iter != NS_ITER_INVALID; iter = ns_next (iter)) + */ + +/* Return the iterator of the first NS. */ +extern ns_iter_t ns_first (void); +/* Return the next NS iterator to the given iterator. */ +extern ns_iter_t ns_next (ns_iter_t); +/* Return the NS iterator of the given NS ID. If it does not exist, + * the iterator of the next existing NS is returned. */ +extern ns_iter_t ns_iterator (ns_id_t); + +/* + * NS iterator to properties + */ +extern ns_id_t ns_iter2id (ns_iter_t); +extern void *ns_iter2info (ns_iter_t); +extern struct list *ns_iter2iflist (ns_iter_t); + +/* + * Utilities to obtain the user data + */ + +/* Get the data pointer of the specified NS. If not found, create one. */ +extern void *ns_info_get (ns_id_t); +/* Look up the data pointer of the specified NS. */ +extern void *ns_info_lookup (ns_id_t); + +/* + * Utilities to obtain the interface list + */ + +/* Look up the interface list of the specified NS. */ +extern struct list *ns_iflist (ns_id_t); +/* Get the interface list of the specified NS. Create one if not find. */ +extern struct list *ns_iflist_get (ns_id_t); + +/* + * NS bit-map: maintaining flags, one bit per NS ID + */ + +typedef void * ns_bitmap_t; +#define NS_BITMAP_NULL NULL + +extern ns_bitmap_t ns_bitmap_init (void); +extern void ns_bitmap_free (ns_bitmap_t); +extern void ns_bitmap_set (ns_bitmap_t, ns_id_t); +extern void ns_bitmap_unset (ns_bitmap_t, ns_id_t); +extern int ns_bitmap_check (ns_bitmap_t, ns_id_t); + +/* + * NS initializer/destructor + */ +/* Please add hooks before calling ns_init(). */ +extern void ns_init (void); +extern void ns_terminate (void); + +/* + * NS utilities + */ + +/* Create a socket serving for the given NS */ +extern int ns_socket (int, int, int, ns_id_t); + +#endif /*_ZEBRA_NS_H*/ + From 13460c44a22415dd55846aca6fc31cf8607c90e9 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Thu, 3 Jul 2014 18:24:34 +0800 Subject: [PATCH 220/226] lib, vtysh: support multiple VRFs by using linux netns We realize VRFs with linux netns by default. The main job is to associate a VRF with a netns. Currently this is done by the configuration: [no] vrf N netns This command is also available in vtysh and goes to only zebra, because presently only zebra supports multiple VRF. A file descriptor is added to "struct vrf". This is for the associated netns file. Once the command "vrf N netns NAME" is executed, the specified file is opened and the file descriptor is stored in the VRF N. In this way the association is formed. In vrf_socket(), we first switch to the specified VRF by using the stored file descriptor, and then can allocate a socket which is working in the associated netns. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel (cherry picked from commit 55cfa2f190620f7c711944637659bc208970324d) --- configure.ac | 8 ++ lib/command.c | 2 + lib/command.h | 1 + lib/ns.c | 247 +++++++++++++++++++++++++++++++++++++++---- lib/ns.h | 2 +- vtysh/Makefile.am | 3 +- vtysh/extract.pl.in | 3 + vtysh/vtysh.c | 41 +++++++ vtysh/vtysh.h | 1 + vtysh/vtysh_config.c | 3 + zebra/zebra_ns.c | 3 + zebra/zebra_ns.h | 5 +- 12 files changed, 296 insertions(+), 23 deletions(-) diff --git a/configure.ac b/configure.ac index b1ea4821e2..9cfb5d37d3 100755 --- a/configure.ac +++ b/configure.ac @@ -852,6 +852,14 @@ AC_CHECK_FUNCS([dup2 ftruncate getcwd gethostbyname getpagesize gettimeofday \ if_nametoindex if_indextoname getifaddrs \ uname fcntl getgrouplist]) +AC_CHECK_HEADER([asm-generic/unistd.h], + [AC_CHECK_DECL(__NR_setns, + AC_DEFINE(HAVE_NETNS,, Have netns),, + QUAGGA_INCLUDES [#include + ]) + AC_CHECK_FUNCS(setns, AC_DEFINE(HAVE_SETNS,, Have setns))] + ) + dnl ------------------------------------ dnl Determine routing get and set method dnl ------------------------------------ diff --git a/lib/command.c b/lib/command.c index 0e921bd636..f97e37e8c6 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2902,6 +2902,7 @@ DEFUN (config_exit, vty_config_unlock (vty); break; case INTERFACE_NODE: + case NS_NODE: case VRF_NODE: case ZEBRA_NODE: case BGP_NODE: @@ -2960,6 +2961,7 @@ DEFUN (config_end, break; case CONFIG_NODE: case INTERFACE_NODE: + case NS_NODE: case VRF_NODE: case ZEBRA_NODE: case RIP_NODE: diff --git a/lib/command.h b/lib/command.h index 8f20a92807..0415834b09 100644 --- a/lib/command.h +++ b/lib/command.h @@ -74,6 +74,7 @@ enum node_type AAA_NODE, /* AAA node. */ KEYCHAIN_NODE, /* Key-chain node. */ KEYCHAIN_KEY_NODE, /* Key-chain key node. */ + NS_NODE, /* Logical-Router node. */ VRF_NODE, /* VRF mode node. */ INTERFACE_NODE, /* Interface mode node. */ ZEBRA_NODE, /* zebra connection node. */ diff --git a/lib/ns.c b/lib/ns.c index daaffc6b09..6fb124181b 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -22,6 +22,13 @@ #include +#ifdef HAVE_NETNS +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include +#endif + #include "if.h" #include "ns.h" #include "prefix.h" @@ -29,14 +36,43 @@ #include "log.h" #include "memory.h" +#include "command.h" +#include "vty.h" + +#ifdef HAVE_NETNS + +#ifndef CLONE_NEWNET +#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ +#endif + +#ifndef HAVE_SETNS +static inline int setns(int fd, int nstype) +{ +#ifdef __NR_setns + return syscall(__NR_setns, fd, nstype); +#else + errno = ENOSYS; + return -1; +#endif +} +#endif /* HAVE_SETNS */ + +#define NS_DEFAULT_NAME "/proc/self/ns/net" + +#else /* !HAVE_NETNS */ + #define NS_DEFAULT_NAME "Default-logical-router" +#endif /* HAVE_NETNS */ + struct ns { /* Identifier, same as the vector index */ ns_id_t ns_id; /* Name */ char *name; + /* File descriptor */ + int fd; /* Master list of interfaces belonging to this NS */ struct list *iflist; @@ -90,6 +126,7 @@ ns_get (ns_id_t ns_id) ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); ns->ns_id = ns_id; + ns->fd = -1; rn->info = ns; /* @@ -114,8 +151,7 @@ ns_delete (struct ns *ns) { zlog_info ("NS %u is to be deleted.", ns->ns_id); - if (ns_is_enabled (ns)) - ns_disable (ns); + ns_disable (ns); if (ns_master.ns_delete_hook) (*ns_master.ns_delete_hook) (ns->ns_id, &ns->info); @@ -158,7 +194,11 @@ ns_lookup (ns_id_t ns_id) static int ns_is_enabled (struct ns *ns) { - return ns && ns->ns_id == NS_DEFAULT; +#ifdef HAVE_NETNS + return ns && ns->fd >= 0; +#else + return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT; +#endif } /* @@ -171,18 +211,34 @@ ns_is_enabled (struct ns *ns) static int ns_enable (struct ns *ns) { - /* Till now, only the default NS can be enabled. */ - if (ns->ns_id == NS_DEFAULT) - { - zlog_info ("NS %u is enabled.", ns->ns_id); + if (!ns_is_enabled (ns)) + { +#ifdef HAVE_NETNS + ns->fd = open (ns->name, O_RDONLY); +#else + ns->fd = -2; /* Remember that ns_enable_hook has been called */ + errno = -ENOTSUP; +#endif + + if (!ns_is_enabled (ns)) + { + zlog_err ("Can not enable NS %u: %s!", + ns->ns_id, safe_strerror (errno)); + return 0; + } + +#ifdef HAVE_NETNS + zlog_info ("NS %u is associated with NETNS %s.", + ns->ns_id, ns->name); +#endif + + zlog_info ("NS %u is enabled.", ns->ns_id); if (ns_master.ns_enable_hook) (*ns_master.ns_enable_hook) (ns->ns_id, &ns->info); - - return 1; } - return 0; + return 1; } /* @@ -197,10 +253,13 @@ ns_disable (struct ns *ns) { zlog_info ("NS %u is to be disabled.", ns->ns_id); - /* Till now, nothing to be done for the default NS. */ - if (ns_master.ns_disable_hook) (*ns_master.ns_disable_hook) (ns->ns_id, &ns->info); + +#ifdef HAVE_NETNS + close (ns->fd); +#endif + ns->fd = -1; } } @@ -438,6 +497,144 @@ ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id) NS_BITMAP_FLAG (offset)) ? 1 : 0; } +#ifdef HAVE_NETNS +/* + * NS realization with NETNS + */ + +static char * +ns_netns_pathname (struct vty *vty, const char *name) +{ + static char pathname[PATH_MAX]; + char *result; + + if (name[0] == '/') /* absolute pathname */ + result = realpath (name, pathname); + else /* relevant pathname */ + { + char tmp_name[PATH_MAX]; + snprintf (tmp_name, PATH_MAX, "%s/%s", NS_RUN_DIR, name); + result = realpath (tmp_name, pathname); + } + + if (! result) + { + vty_out (vty, "Invalid pathname: %s%s", safe_strerror (errno), + VTY_NEWLINE); + return NULL; + } + return pathname; +} + +DEFUN (ns_netns, + ns_netns_cmd, + "logical-router <1-65535> ns NAME", + "Enable a logical-router\n" + "Specify the logical-router indentifier\n" + "The Name Space\n" + "The file name in " NS_RUN_DIR ", or a full pathname\n") +{ + ns_id_t ns_id = NS_DEFAULT; + struct ns *ns = NULL; + char *pathname = ns_netns_pathname (vty, argv[1]); + + if (!pathname) + return CMD_WARNING; + + VTY_GET_INTEGER ("NS ID", ns_id, argv[0]); + ns = ns_get (ns_id); + + if (ns->name && strcmp (ns->name, pathname) != 0) + { + vty_out (vty, "NS %u is already configured with NETNS %s%s", + ns->ns_id, ns->name, VTY_NEWLINE); + return CMD_WARNING; + } + + if (!ns->name) + ns->name = XSTRDUP (MTYPE_NS_NAME, pathname); + + if (!ns_enable (ns)) + { + vty_out (vty, "Can not associate NS %u with NETNS %s%s", + ns->ns_id, ns->name, VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN (no_ns_netns, + no_ns_netns_cmd, + "no logical-router <1-65535> ns NAME", + NO_STR + "Enable a Logical-Router\n" + "Specify the Logical-Router identifier\n" + "The Name Space\n" + "The file name in " NS_RUN_DIR ", or a full pathname\n") +{ + ns_id_t ns_id = NS_DEFAULT; + struct ns *ns = NULL; + char *pathname = ns_netns_pathname (vty, argv[1]); + + if (!pathname) + return CMD_WARNING; + + VTY_GET_INTEGER ("NS ID", ns_id, argv[0]); + ns = ns_lookup (ns_id); + + if (!ns) + { + vty_out (vty, "NS %u is not found%s", ns_id, VTY_NEWLINE); + return CMD_SUCCESS; + } + + if (ns->name && strcmp (ns->name, pathname) != 0) + { + vty_out (vty, "Incorrect NETNS file name%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ns_disable (ns); + + if (ns->name) + { + XFREE (MTYPE_NS_NAME, ns->name); + ns->name = NULL; + } + + return CMD_SUCCESS; +} + +/* NS node. */ +static struct cmd_node ns_node = +{ + NS_NODE, + "", /* NS node has no interface. */ + 1 +}; + +/* NS configuration write function. */ +static int +ns_config_write (struct vty *vty) +{ + struct route_node *rn; + struct ns *ns; + int write = 0; + + for (rn = route_top (ns_table); rn; rn = route_next (rn)) + if ((ns = rn->info) != NULL && + ns->ns_id != NS_DEFAULT && ns->name) + { + vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, VTY_NEWLINE); + write++; + } + + return write; +} + +#endif /* HAVE_NETNS */ + /* Initialize NS module. */ void ns_init (void) @@ -464,6 +661,13 @@ ns_init (void) zlog_err ("ns_init: failed to enable the default NS!"); exit (1); } + +#ifdef HAVE_NETNS + /* Install NS commands. */ + install_node (&ns_node, ns_config_write); + install_element (CONFIG_NODE, &ns_netns_cmd); + install_element (CONFIG_NODE, &no_ns_netns_cmd); +#endif } /* Terminate NS module. */ @@ -485,19 +689,26 @@ ns_terminate (void) int ns_socket (int domain, int type, int protocol, ns_id_t ns_id) { + struct ns *ns = ns_lookup (ns_id); int ret = -1; - if (!ns_is_enabled (ns_lookup (ns_id))) + if (!ns_is_enabled (ns)) { errno = ENOSYS; return -1; } - if (ns_id == NS_DEFAULT) - ret = socket (domain, type, protocol); - else - errno = ENOSYS; +#ifdef HAVE_NETNS + ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0; + if (ret >= 0) + { + ret = socket (domain, type, protocol); + if (ns_id != NS_DEFAULT) + setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET); + } +#else + ret = socket (domain, type, protocol); +#endif return ret; } - diff --git a/lib/ns.h b/lib/ns.h index 81e24562c3..3fac739861 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -33,7 +33,7 @@ typedef u_int16_t ns_id_t; /* * The command strings */ - +#define NS_RUN_DIR "/var/run/netns" #define NS_CMD_STR "logical-router <0-65535>" #define NS_CMD_HELP_STR "Specify the Logical-Router\nThe Logical-Router ID\n" diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am index d4a74487ec..ed49acca47 100644 --- a/vtysh/Makefile.am +++ b/vtysh/Makefile.am @@ -54,8 +54,9 @@ vtysh_cmd_FILES = $(vtysh_scan) \ $(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \ $(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \ $(top_srcdir)/lib/distribute.c $(top_srcdir)/lib/if_rmap.c \ - $(top_srcdir)/lib/vty.c $(top_srcdir)/zebra/debug.c \ $(top_srcdir)/lib/vrf.c \ + $(top_srcdir)/lib/vty.c $(top_srcdir)/zebra/debug.c \ + $(top_srcdir)/lib/ns.c \ $(top_srcdir)/zebra/interface.c \ $(top_srcdir)/zebra/irdp_interface.c \ $(top_srcdir)/zebra/rtadv.c $(top_srcdir)/zebra/zebra_vty.c \ diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 4ead722213..31ab3b3ad8 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -129,6 +129,9 @@ foreach (@ARGV) { elsif ($file =~ /lib\/filter\.c$/) { $protocol = "VTYSH_ALL"; } + elsif ($file =~ /lib\/ns\.c$/) { + $protocol = "VTYSH_ZEBRA"; + } elsif ($file =~ /lib\/plist\.c$/) { if ($defun_array[1] =~ m/ipv6/) { $protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA"; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 5cf27facb8..2436c6182d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -41,6 +41,7 @@ #include "vtysh/vtysh.h" #include "log.h" #include "bgpd/bgp_vty.h" +#include "ns.h" #include "vrf.h" /* Struct VTY. */ @@ -936,6 +937,12 @@ static struct cmd_node interface_node = "%s(config-if)# ", }; +static struct cmd_node ns_node = +{ + NS_NODE, + "%s(config-logical-router)# ", +}; + static struct cmd_node vrf_node = { VRF_NODE, @@ -1391,6 +1398,7 @@ vtysh_exit (struct vty *vty) vty->node = ENABLE_NODE; break; case INTERFACE_NODE: + case NS_NODE: case VRF_NODE: case ZEBRA_NODE: case BGP_NODE: @@ -1622,6 +1630,19 @@ DEFSH (VTYSH_ZEBRA, "Interface's name\n" VRF_CMD_HELP_STR) +DEFUNSH (VTYSH_NS, + vtysh_ns, + vtysh_ns_cmd, + "logical-router <1-65535 ns NAME", + "Enable a logical-router\n" + "Specify the logical-router indentifier\n" + "The Name Space\n" + "The file name in " NS_RUN_DIR ", or a full pathname\n") +{ + vty->node = NS_NODE; + return CMD_SUCCESS; +} + DEFUNSH (VTYSH_VRF, vtysh_vrf, vtysh_vrf_cmd, @@ -1640,6 +1661,20 @@ DEFSH (VTYSH_ZEBRA, "Delete a pseudo vrf's configuration\n" "VRF's name\n") +DEFUNSH (VTYSH_NS, + vtysh_exit_ns, + vtysh_exit_ns_cmd, + "exit", + "Exit current mode and down to previous mode\n") +{ + return vtysh_exit (vty); +} + +ALIAS (vtysh_exit_ns, + vtysh_quit_ns_cmd, + "quit", + "Exit current mode and down to previous mode\n") + DEFUNSH (VTYSH_VRF, vtysh_exit_vrf, vtysh_exit_vrf_cmd, @@ -2864,6 +2899,7 @@ vtysh_init_vty (void) install_node (&rip_node, NULL); install_node (&interface_node, NULL); install_node (&link_params_node, NULL); + install_node (&ns_node, NULL); install_node (&vrf_node, NULL); install_node (&rmap_node, NULL); install_node (&zebra_node, NULL); @@ -2894,6 +2930,7 @@ vtysh_init_vty (void) vtysh_install_default (RIP_NODE); vtysh_install_default (INTERFACE_NODE); vtysh_install_default (LINK_PARAMS_NODE); + vtysh_install_default (NS_NODE); vtysh_install_default (VRF_NODE); vtysh_install_default (RMAP_NODE); vtysh_install_default (ZEBRA_NODE); @@ -2991,6 +3028,10 @@ vtysh_init_vty (void) install_element (LINK_PARAMS_NODE, &vtysh_exit_interface_cmd); install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd); + install_element (NS_NODE, &vtysh_end_all_cmd); + install_element (NS_NODE, &vtysh_exit_ns_cmd); + install_element (NS_NODE, &vtysh_quit_ns_cmd); + install_element (VRF_NODE, &vtysh_end_all_cmd); install_element (VRF_NODE, &vtysh_exit_vrf_cmd); install_element (VRF_NODE, &vtysh_quit_vrf_cmd); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index e974cf331c..75822b1363 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -34,6 +34,7 @@ #define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD #define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD #define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD +#define VTYSH_NS VTYSH_ZEBRA #define VTYSH_VRF VTYSH_ZEBRA /* vtysh local configuration file. */ diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index e678fc1a8b..4a1b323686 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -171,6 +171,7 @@ vtysh_config_parse_line (const char *line) { if (config->index == RMAP_NODE || config->index == INTERFACE_NODE || + config->index == NS_NODE || config->index == VRF_NODE || config->index == VTY_NODE) config_add_line_uniq (config->line, line); @@ -183,6 +184,8 @@ vtysh_config_parse_line (const char *line) default: if (strncmp (line, "interface", strlen ("interface")) == 0) config = config_get (INTERFACE_NODE, line); + else if (strncmp (line, "ns", strlen ("ns")) == 0) + config = config_get (NS_NODE, line); else if (strncmp (line, "vrf", strlen ("vrf")) == 0) config = config_get (VRF_NODE, line); else if (strncmp (line, "router-id", strlen ("router-id")) == 0) diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 6b04aa741a..084a5d181f 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -21,6 +21,7 @@ */ #include "zebra.h" +#include "lib/ns.h" #include "lib/vrf.h" #include "lib/prefix.h" #include "lib/memory.h" @@ -86,6 +87,8 @@ zebra_ns_init (void) { dzns = XCALLOC (MTYPE_ZEBRA_NS, sizeof (struct zebra_ns)); + ns_init (); + zebra_vrf_init (); zebra_ns_enable (0, (void **)&dzns); diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 07fcfcdac1..8a821c465a 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -23,6 +23,8 @@ #if !defined(__ZEBRA_NS_H__) #define __ZEBRA_NS_H__ +#include + #ifdef HAVE_NETLINK /* Socket interface to kernel */ struct nlsock @@ -34,9 +36,6 @@ struct nlsock }; #endif -/* NetNS ID type. */ -typedef u_int16_t ns_id_t; - struct zebra_ns { /* net-ns name. */ From c253dcb5d80aa60112bb31ab95ae9839081064d3 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 3 Sep 2015 10:47:43 +0200 Subject: [PATCH 221/226] vrf: add a runtime check before playing with netns This patch adds a runtime check to determine if netns are available. Some systems like OpenWRT have the system call setns() but don't have the kernel option CONFIG_NET_NS enabled. Reported-by: Christian Franke Signed-off-by: Nicolas Dichtel Tested-by: Christian Franke (cherry picked from commit 04a3aabf58d95d01c4c8168eeff43cf9d9892eee) --- lib/ns.c | 94 +++++++++++++++++++++++++++----------------- vtysh/vtysh_config.c | 2 +- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/lib/ns.c b/lib/ns.c index 6fb124181b..4765a18ef2 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -39,7 +39,6 @@ #include "command.h" #include "vty.h" -#ifdef HAVE_NETNS #ifndef CLONE_NEWNET #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ @@ -57,7 +56,10 @@ static inline int setns(int fd, int nstype) } #endif /* HAVE_SETNS */ +#ifdef HAVE_NETNS + #define NS_DEFAULT_NAME "/proc/self/ns/net" +static int have_netns_enabled = -1; #else /* !HAVE_NETNS */ @@ -65,6 +67,27 @@ static inline int setns(int fd, int nstype) #endif /* HAVE_NETNS */ +static int have_netns(void) +{ +#ifdef HAVE_NETNS + if (have_netns_enabled < 0) + { + int fd = open (NS_DEFAULT_NAME, O_RDONLY); + + if (fd < 0) + have_netns_enabled = 0; + else + { + have_netns_enabled = 1; + close(fd); + } + } + return have_netns_enabled; +#else + return 0; +#endif +} + struct ns { /* Identifier, same as the vector index */ @@ -194,11 +217,10 @@ ns_lookup (ns_id_t ns_id) static int ns_is_enabled (struct ns *ns) { -#ifdef HAVE_NETNS - return ns && ns->fd >= 0; -#else - return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT; -#endif + if (have_netns()) + return ns && ns->fd >= 0; + else + return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT; } /* @@ -214,12 +236,12 @@ ns_enable (struct ns *ns) if (!ns_is_enabled (ns)) { -#ifdef HAVE_NETNS - ns->fd = open (ns->name, O_RDONLY); -#else - ns->fd = -2; /* Remember that ns_enable_hook has been called */ - errno = -ENOTSUP; -#endif + if (have_netns()) { + ns->fd = open (ns->name, O_RDONLY); + } else { + ns->fd = -2; /* Remember that ns_enable_hook has been called */ + errno = -ENOTSUP; + } if (!ns_is_enabled (ns)) { @@ -228,10 +250,9 @@ ns_enable (struct ns *ns) return 0; } -#ifdef HAVE_NETNS - zlog_info ("NS %u is associated with NETNS %s.", - ns->ns_id, ns->name); -#endif + if (have_netns()) + zlog_info ("NS %u is associated with NETNS %s.", + ns->ns_id, ns->name); zlog_info ("NS %u is enabled.", ns->ns_id); if (ns_master.ns_enable_hook) @@ -256,9 +277,9 @@ ns_disable (struct ns *ns) if (ns_master.ns_disable_hook) (*ns_master.ns_disable_hook) (ns->ns_id, &ns->info); -#ifdef HAVE_NETNS - close (ns->fd); -#endif + if (have_netns()) + close (ns->fd); + ns->fd = -1; } } @@ -497,7 +518,6 @@ ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id) NS_BITMAP_FLAG (offset)) ? 1 : 0; } -#ifdef HAVE_NETNS /* * NS realization with NETNS */ @@ -633,8 +653,6 @@ ns_config_write (struct vty *vty) return write; } -#endif /* HAVE_NETNS */ - /* Initialize NS module. */ void ns_init (void) @@ -662,12 +680,13 @@ ns_init (void) exit (1); } -#ifdef HAVE_NETNS - /* Install NS commands. */ - install_node (&ns_node, ns_config_write); - install_element (CONFIG_NODE, &ns_netns_cmd); - install_element (CONFIG_NODE, &no_ns_netns_cmd); -#endif + if (have_netns()) + { + /* Install NS commands. */ + install_node (&ns_node, ns_config_write); + install_element (CONFIG_NODE, &ns_netns_cmd); + install_element (CONFIG_NODE, &no_ns_netns_cmd); + } } /* Terminate NS module. */ @@ -698,17 +717,18 @@ ns_socket (int domain, int type, int protocol, ns_id_t ns_id) return -1; } -#ifdef HAVE_NETNS - ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0; - if (ret >= 0) + if (have_netns()) { - ret = socket (domain, type, protocol); - if (ns_id != NS_DEFAULT) - setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET); + ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0; + if (ret >= 0) + { + ret = socket (domain, type, protocol); + if (ns_id != NS_DEFAULT) + setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET); + } } -#else - ret = socket (domain, type, protocol); -#endif + else + ret = socket (domain, type, protocol); return ret; } diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 4a1b323686..118b7ba035 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -184,7 +184,7 @@ vtysh_config_parse_line (const char *line) default: if (strncmp (line, "interface", strlen ("interface")) == 0) config = config_get (INTERFACE_NODE, line); - else if (strncmp (line, "ns", strlen ("ns")) == 0) + else if (strncmp (line, "logical-router", strlen ("ns")) == 0) config = config_get (NS_NODE, line); else if (strncmp (line, "vrf", strlen ("vrf")) == 0) config = config_get (VRF_NODE, line); From b8dfa5447828b06df05eadfa11174fe7d272a0d2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 9 Sep 2016 12:41:35 -0400 Subject: [PATCH 222/226] ospfd: Fix crash with usage of incorrect command Entering 'show ip ospf interface json' causes ospf to crash. Entering 'show ip ospf interface json' causes ospf to crash if intf has no neighbors on the otherside Modify the code to not crash in these cases. Ticket: CM-12776 Signed-off-by: Donald Sharp Reviewed-by: Daniel Walton --- ospfd/ospf_vty.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 264249b4c0..1b26c67866 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3871,7 +3871,13 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface { struct timeval result; unsigned long time_store = 0; - result = tv_sub (oi->t_hello->u.sands, recent_relative_time()); + if (oi->t_hello) + result = tv_sub (oi->t_hello->u.sands, recent_relative_time()); + else + { + result.tv_sec = 0; + result.tv_usec = 0; + } time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); json_object_int_add(json_interface_sub, "timerHelloInMsecs", time_store); } @@ -3933,20 +3939,29 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, if (ospf_oi_count(ifp)) { show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); + if (use_json) + json_object_object_add (json, ifp->name, json_interface_sub); } } } else if (argv[iface_argv] && strcmp(argv[iface_argv], "json") == 0) { + if (!use_json) + { + json = json_object_new_object(); + json_interface_sub = json_object_new_object (); + use_json = 1; + } /* Show All Interfaces. */ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { if (ospf_oi_count(ifp)) { show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); - json_object_object_add(json, ifp->name, json_interface_sub); - } - } + if (use_json) + json_object_object_add(json, ifp->name, json_interface_sub); + } + } } else { From 03809024fddcb94a020f2f6d9eb8dff8210e3b21 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 9 Sep 2016 16:01:27 -0400 Subject: [PATCH 223/226] bgpd: Fix startup a bit more There were several issues here. The zprivs_init is being called *before* the cli is read in to influence the user we are running as. This needs to be rectified. Additionally we need to move the log creation till after cli arguments are read. Signed-off-by: Donald Sharp --- bgpd/bgp_main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 20fa138ce8..54e7329772 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -415,13 +415,6 @@ main (int argc, char **argv) /* Preserve name of myself. */ progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); - zlog_default = openzlog (progname, ZLOG_BGP, 0, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - zprivs_init (&bgpd_privs); -#if defined(HAVE_CUMULUS) - zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); -#endif - /* BGP master init. */ bgp_master_init (); @@ -502,6 +495,12 @@ main (int argc, char **argv) } } + zlog_default = openzlog (progname, ZLOG_BGP, 0, + LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + zprivs_init (&bgpd_privs); +#if defined(HAVE_CUMULUS) + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); +#endif /* Initializations. */ srandom (time (NULL)); From a008f49a85c3891eb4ac469346bec24036fd0e87 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 6 Sep 2016 10:52:31 -0400 Subject: [PATCH 224/226] bgpd: Add flag to not change e{u,g}id on startup and run as unprivileged user * bgp_main.c: add -S / --skip_runas flag to not change effective user/group on start up. Enables bgpd to be run by unprivileged user. --- bgpd/bgp_main.c | 19 ++++++++++++++++--- doc/bgpd.8 | 5 ++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 54e7329772..5ef8154faf 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -68,6 +68,7 @@ static const struct option longopts[] = { "no_kernel", no_argument, NULL, 'n'}, { "user", required_argument, NULL, 'u'}, { "group", required_argument, NULL, 'g'}, + { "skip_runas", no_argument, NULL, 'S'}, { "version", no_argument, NULL, 'v'}, { "dryrun", no_argument, NULL, 'C'}, { "help", no_argument, NULL, 'h'}, @@ -163,6 +164,7 @@ redistribution between different routing protocols.\n\n\ -n, --no_kernel Do not install route to kernel.\n\ -u, --user User to run as\n\ -g, --group Group to run as\n\ +-S, --skip_runas Skip user and group run as\n\ -v, --version Print program version\n\ -C, --dryrun Check configuration for validity and exit\n\ -h, --help Display this help and exit\n\ @@ -200,9 +202,12 @@ sigint (void) zlog_notice ("Terminating on signal"); if (! retain_mode) - bgp_terminate (); + { + bgp_terminate (); + if (bgpd_privs.user) /* NULL if skip_runas flag set */ + zprivs_terminate (&bgpd_privs); + } - zprivs_terminate (&bgpd_privs); bgp_exit (0); exit (0); @@ -408,6 +413,7 @@ main (int argc, char **argv) char *progname; struct thread thread; int tmp_port; + int skip_runas = 0; /* Set umask before anything for security */ umask (0027); @@ -421,7 +427,7 @@ main (int argc, char **argv) /* Command line argument treatment. */ while (1) { - opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vC", longopts, 0); + opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vCS", longopts, 0); if (opt == EOF) break; @@ -479,6 +485,9 @@ main (int argc, char **argv) case 'g': bgpd_privs.group = optarg; break; + case 'S': /* skip run as = override bgpd_privs */ + skip_runas = 1; + break; case 'v': print_version (progname); exit (0); @@ -497,7 +506,11 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_BGP, 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + + if (skip_runas) + memset (&bgpd_privs, 0, sizeof (bgpd_privs)); zprivs_init (&bgpd_privs); + #if defined(HAVE_CUMULUS) zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); #endif diff --git a/doc/bgpd.8 b/doc/bgpd.8 index 67143c2c59..7e90eaec5b 100644 --- a/doc/bgpd.8 +++ b/doc/bgpd.8 @@ -6,7 +6,7 @@ software .SH SYNOPSIS .B bgpd [ -.B \-dhrv +.B \-dhrSv ] [ .B \-f .I config-file @@ -74,6 +74,9 @@ Specify the user to run as. Default is \fIquagga\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBbgpd\fR. .TP +\fB\-S\fR, \fB\-\-skip_runas\fR +Skip setting the process effective user and group. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES From 28b0c6b377e56e76c674c27e384238a755b173b2 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Fri, 9 Sep 2016 20:24:31 +0000 Subject: [PATCH 225/226] Unable to remove route-map from quagga Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12816 pim was missing route-map hooks --- pimd/pim_routemap.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ pimd/pimd.c | 2 ++ pimd/pimd.h | 1 + vtysh/extract.pl.in | 4 ++-- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/pimd/pim_routemap.c b/pimd/pim_routemap.c index ced7c87484..adfd4fd2c3 100644 --- a/pimd/pim_routemap.c +++ b/pimd/pim_routemap.c @@ -26,9 +26,56 @@ #include "pimd.h" + +static void +pim_route_map_mark_update (const char *rmap_name) +{ + // placeholder + return; +} + +static void +pim_route_map_add (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + +static void +pim_route_map_delete (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 1) == 0) + pim_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); +} + +static void +pim_route_map_event (route_map_event_t event, const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + void pim_route_map_init (void) { route_map_init (); route_map_init_vty (); + route_map_add_hook (pim_route_map_add); + route_map_delete_hook (pim_route_map_delete); + route_map_event_hook (pim_route_map_event); +} + +void +pim_route_map_terminate (void) +{ + route_map_add_hook (NULL); + route_map_delete_hook (NULL); + route_map_event_hook (NULL); + route_map_finish(); } diff --git a/pimd/pimd.c b/pimd/pimd.c index 5b6824da58..91d8d56afc 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -87,6 +87,8 @@ static void pim_free() if (qpim_static_route_list) list_free(qpim_static_route_list); + + pim_route_map_terminate(); } void pim_init() diff --git a/pimd/pimd.h b/pimd/pimd.h index 0a376aa905..6d48d83621 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -177,5 +177,6 @@ void pim_init(void); void pim_terminate(void); extern void pim_route_map_init (void); +extern void pim_route_map_terminate(void); #endif /* PIMD_H */ diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 31ab3b3ad8..7563daa506 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -121,7 +121,7 @@ foreach (@ARGV) { $protocol = "VTYSH_RIPD"; } elsif ($file =~ /lib\/routemap\.c$/) { - $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA"; + $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD"; } elsif ($file =~ /lib\/vrf\.c$/) { $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA"; @@ -136,7 +136,7 @@ foreach (@ARGV) { if ($defun_array[1] =~ m/ipv6/) { $protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA"; } else { - $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA"; + $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD"; } } elsif ($file =~ /lib\/distribute\.c$/) { From 039dc61292de5f3ed5f46316b1940ab6bb184c3f Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 9 Sep 2016 21:58:33 +0000 Subject: [PATCH 226/226] lib: Fix tab completions memleak, memory stats corruption Reviewed-by: Donald Sharp Signed-off-by: Quentin Young --- lib/command.c | 14 ++++++++++---- vtysh/vtysh.c | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/command.c b/lib/command.c index f97e37e8c6..e67007ae2f 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2416,8 +2416,11 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status, int islib /* Only one matched */ if (vector_slot (matchvec, 1) == NULL) { - match_str = (char **) matchvec->index; - vector_only_wrapper_free (matchvec); + size_t index_size = matchvec->alloced * sizeof (void *); + match_str = XMALLOC (MTYPE_TMP, index_size); + memcpy (match_str, matchvec->index, index_size); + vector_free (matchvec); + *status = CMD_COMPLETE_FULL_MATCH; return match_str; } @@ -2459,8 +2462,11 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status, int islib /* Make new matchvec. */ matchvec = vector_init (INIT_MATCHVEC_SIZE); vector_set (matchvec, lcdstr); - match_str = (char **) matchvec->index; - vector_only_wrapper_free (matchvec); + + size_t index_size = matchvec->alloced * sizeof (void *); + match_str = XMALLOC (MTYPE_TMP, index_size); + memcpy (match_str, matchvec->index, index_size); + vector_free (matchvec); *status = CMD_COMPLETE_MATCH; return match_str; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 2436c6182d..d01a1bcebb 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -885,7 +885,10 @@ command_generator (const char *text, int state) if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1])) vector_set (vline, NULL); + if (matched) + XFREE (MTYPE_TMP, matched); matched = cmd_complete_command (vline, vty, &complete_status); + cmd_free_strvec (vline); } if (matched && matched[index])