diff --git a/COMMUNITY.md b/COMMUNITY.md index 52777da968..704c47a95e 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -2,6 +2,16 @@ [TOC] +## General note on this document + +This document is "descriptive/post-factual" in that it documents pratices that +are in use; it is not "definitive/pre-factual" in prescribing practices. + +This means that when a procedure changes, it is agreed upon, then put into +practice, and then documented here. If this document doesn't match reality, +it's the document that needs to be updated, not reality. + + ## Git Structure The master Git for PROJECT resides on Github at @@ -10,20 +20,21 @@ The master Git for PROJECT resides on Github at ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") -There are 3 main branches for development and a release branch for each +There is one main branch for development and a release branch for each major release. -New contributions are done against the head of the Develop branch. The CI +New contributions are done against the head of the master branch. The CI systems will pick up the Github Pull Requests or the new patch from -Patchwork, run some basic build and functional tests and will merge them -into the branch automatically on success. - -Code on the develop branch will then be further tested and reviewed by the -community and merged to master on a regular interval. +Patchwork, run some basic build and functional tests. For each major release (1.0, 1.1 etc) a new release branch is created based on the master. +There was an attempt to use a "develop" branch automatically maintained by +the CI system. This is not currently in active use, though the system is +operational. If the "develop" branch is in active use and this paragraph +is still here, this document obviously wasn't updated. + ## Programming language, Tools and Libraries @@ -250,16 +261,72 @@ Portions: ### Code styling / format -GNU coding standards apply. Indentation follows the result of invoking GNU -indent (as of 2.2.8a) with the `-nut -nfc1` arguments. +Coding style standards in FRR vary depending on location. Pre-existing +code uses GNU coding standards. New code may use Linux kernel coding style. + +GNU coding style apply to the following parts: + +* lib/ +* zebra/ +* bgpd/ +* ospfd/ +* ospf6d/ +* isisd/ +* ripd/ +* ripngd/ +* vtysh/ + +Linux kernel coding style applies to: + +* nhrpd/ +* watchfrr/ +* pimd/ +* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch] + +BSD coding style applies to: + +* ldpd/ + +**Whitespace changes in untouched parts of the code are not acceptable in +patches that change actual code.** To change/fix formatting issues, please +create a separate patch that only does formatting changes and nothing else. + +It is acceptable to rewrap entire files to Linux kernel style, but this +**MUST** come as a separate patch that does nothing other than this +reformatting. + + +#### GNU style + +For GNU coding style, Indentation follows the result of invoking GNU indent: ``` indent -nut -nfc1 file_for_submission.c ``` -Please don’t reformat existing files (or only sections modified by your -changes), even if they don’t follow the standard. This makes it very hard to -highlight the changes +Originally, tabs were used instead of spaces, with tabs are every 8 columns. +However, tab interoperability issues mean space characters are now preferred for +new changes. We generally only clean up whitespace when code is unmaintainable +due to whitespace issues, to minimise merging conflicts. + + +#### Linux kernel & BSD style + +These styles are documented externally: + +* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle). +* [http://man.openbsd.org/style](http://man.openbsd.org/style) + +They are relatively similar but differ in details. + +pimd deviates from Linux kernel style in using 2 spaces for indentation, with +Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`. +It is acceptable to convert indentation in pimd/ to Linux kernel style, but +please convert an entire file at a time. (Rationale: apart from 2-space +indentation, the styles are sufficiently close to not upset when mixed.) + +Unlike GNU style, these styles use tabs, not spaces. + ### Compile-Time conditional code @@ -307,4 +374,4 @@ of their debugs. CLI's are a complicated ugly beast. Additions or changes to the CLI should use a DEFUN to encapsulate one setting as much as is possible. Additionally as new DEFUN's are added to the system, documentation -should be provided for the new commands. \ No newline at end of file +should be provided for the new commands. diff --git a/ChangeLog b/ChangeLog index a201bb6819..ec7e6cdde8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -ChangeLog information for FreeRangeRouting is for now recorded in source-code +ChangeLog information for FRRouting is for now recorded in source-code management system. Please see: - http://www.freerangerouting.org/ + http://www.frrouting.org/ diff --git a/Makefile.am b/Makefile.am index aeacd4c3ce..c0efa1925a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,3 +18,5 @@ EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \ tools/zebra.el tools/multiple-bgpd.sh ACLOCAL_AMFLAGS = -I m4 + +noinst_HEADERS = defaults.h diff --git a/REPORTING-BUGS b/REPORTING-BUGS index ea36ff5eed..01f25a2051 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -1,5 +1,5 @@ -This file describes the procedure for reporting FreeRangeRouting bugs. You are not -obliged to follow this format, but it would be great help for FreeRangeRouting developers +This file describes the procedure for reporting FRRouting bugs. You are not +obliged to follow this format, but it would be great help for FRRouting developers if you report a bug as described below. Bugs submitted with woefully incomplete information may be summarily @@ -10,10 +10,10 @@ non-response to requests to reconfirm or supply additional information. Report bugs on Github Issue Tracker at - https://github.com/freerangerouting/frr/issues + https://github.com/frrouting/frr/issues Please supply the following information: -1. Your FreeRangeRouting version or if it is from git then the commit reference. +1. Your FRRouting version or if it is from git then the commit reference. Please try to report bugs against git master or the latest release. 2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any specific options you compiled Quagga with. diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 50afc7ed64..b6ed9a4d6d 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libbgp.a +module_LTLIBRARIES = sbin_PROGRAMS = bgpd bin_PROGRAMS = bgp_btoa @@ -75,7 +76,7 @@ libbgp_a_SOURCES = \ bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \ bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ - bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \ + bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \ bgp_mplsvpn.c bgp_nexthop.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ @@ -89,7 +90,7 @@ noinst_HEADERS = \ bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ bgp_ecommunity.h bgp_lcommunity.h \ bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ - bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \ + bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h @@ -101,6 +102,15 @@ bgp_btoa_SOURCES = bgp_btoa.c bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) +if SNMP +module_LTLIBRARIES += bgpd_snmp.la +endif + +bgpd_snmp_la_SOURCES = bgp_snmp.c +bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la + examplesdir = $(exampledir) dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 7dc7f053d6..2bbdca595c 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_dump.h" #include "bgpd/bgp_open.h" #include "bgpd/bgp_advertise.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" +DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DEFINE_HOOK(peer_established, (struct peer *peer), (peer)) + /* Definition of display strings corresponding to FSM events. This should be * kept consistent with the events defined in bgpd.h */ @@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer) zlog_debug ("%s remove from all update group", peer->host); update_group_remove_peer_afs(peer); -#ifdef HAVE_SNMP - bgpTrapBackwardTransition (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_backward_transition, peer); /* Reset peer synctime */ peer->synctime = 0; @@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer) zlog_debug ("%s graceful restart timer stopped", peer->host); } -#ifdef HAVE_SNMP - bgpTrapEstablished (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_established, peer); /* Reset uptime, send keepalive, send current table. */ peer->uptime = bgp_clock (); diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index e47d07702b..4d0b48f529 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *); */ extern void bgp_adjust_routeadv (struct peer *); +#include "hook.h" +DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DECLARE_HOOK(peer_established, (struct peer *peer), (peer)) + #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 1358ebc5ef..46ae882b2e 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -262,7 +262,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) continue; - ifp = if_lookup_by_name_vrf (name, bgp->vrf_id); + ifp = if_lookup_by_name (name, bgp->vrf_id); if (ifp) { *bgp_inst = bgp; @@ -544,7 +544,7 @@ bgp_update_source (struct peer *peer) /* Source is specified with interface name. */ if (peer->update_if) { - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); if (! ifp) return -1; @@ -617,7 +617,7 @@ bgp_connect (struct peer *peer) } if (peer->conf_if || peer->ifname) - ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname); + ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s [Event] Connect start to %s fd %d", diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 0cf96101c2..9300345899 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -415,7 +415,7 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) vty_out(vty, " gate %s, if %s%s", inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex), + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4: @@ -425,13 +425,13 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " if %s%s", - ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " gate %s, if %s%s", inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; default: vty_out (vty, " invalid nexthop type %u%s", diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 5e6218e8a3..f45d683848 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include -#ifdef HAVE_SNMP #include #include @@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "thread.h" #include "smux.h" #include "filter.h" +#include "hook.h" +#include "libfrr.h" +#include "version.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_fsm.h" -#include "bgpd/bgp_snmp.h" /* BGP4-MIB described in RFC1657. */ #define BGP4MIB 1,3,6,1,2,1,15 @@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] = {3, {3, 1, BGPPEERSTATE}} }; -void +static int bgpTrapEstablished (struct peer *peer) { int ret; @@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPESTABLISHED); + return 0; } -void +static int bgpTrapBackwardTransition (struct peer *peer) { int ret; @@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPBACKWARDTRANSITION); + return 0; } -void -bgp_snmp_init (void) +static int +bgp_snmp_init (struct thread_master *tm) { - smux_init (bm->master); + smux_init (tm); REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +bgp_snmp_module_init (void) +{ + hook_register(peer_established, bgpTrapEstablished); + hook_register(peer_backward_transition, bgpTrapBackwardTransition); + hook_register(frr_late_init, bgp_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "bgpd_snmp", + .version = FRR_VERSION, + .description = "bgpd AgentX SNMP module", + .init = bgp_snmp_module_init +) diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h deleted file mode 100644 index 7a0d9dd007..0000000000 --- a/bgpd/bgp_snmp.h +++ /dev/null @@ -1,28 +0,0 @@ -/* BGP4 SNMP support - Copyright (C) 1999, 2000 Kunihiro Ishiguro - -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 _QUAGGA_BGP_SNMP_H -#define _QUAGGA_BGP_SNMP_H - -extern void bgp_snmp_init (void); -extern void bgpTrapEstablished (struct peer *); -extern void bgpTrapBackwardTransition (struct peer *); - -#endif /* _QUAGGA_BGP_SNMP_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index dba336051a..e94de682d5 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -806,7 +806,7 @@ DEFUN (no_auto_summary, } /* "router bgp" commands. */ -DEFUN (router_bgp, +DEFUN_NOSH (router_bgp, router_bgp_cmd, "router bgp [(1-4294967295) [ WORD]]", ROUTER_STR @@ -5647,7 +5647,7 @@ DEFUN (no_neighbor_addpath_tx_bestpath_per_as, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); } -DEFUN (address_family_ipv4_safi, +DEFUN_NOSH (address_family_ipv4_safi, address_family_ipv4_safi_cmd, "address-family ipv4 []", "Enter Address Family command mode\n" @@ -5680,7 +5680,7 @@ DEFUN (address_family_ipv4_safi, return CMD_SUCCESS; } -DEFUN (address_family_ipv6_safi, +DEFUN_NOSH (address_family_ipv6_safi, address_family_ipv6_safi_cmd, "address-family ipv6 []", "Enter Address Family command mode\n" @@ -5714,7 +5714,7 @@ DEFUN (address_family_ipv6_safi, } #ifdef KEEP_OLD_VPN_COMMANDS -DEFUN (address_family_vpnv4, +DEFUN_NOSH (address_family_vpnv4, address_family_vpnv4_cmd, "address-family vpnv4 [unicast]", "Enter Address Family command mode\n" @@ -5725,7 +5725,7 @@ DEFUN (address_family_vpnv4, return CMD_SUCCESS; } -DEFUN (address_family_vpnv6, +DEFUN_NOSH (address_family_vpnv6, address_family_vpnv6_cmd, "address-family vpnv6 [unicast]", "Enter Address Family command mode\n" @@ -5737,7 +5737,7 @@ DEFUN (address_family_vpnv6, } #endif -DEFUN (address_family_encap, +DEFUN_NOSH (address_family_encap, address_family_encap_cmd, "address-family ", "Enter Address Family command mode\n" @@ -5749,7 +5749,7 @@ DEFUN (address_family_encap, } -DEFUN (address_family_encapv6, +DEFUN_NOSH (address_family_encapv6, address_family_encapv6_cmd, "address-family encapv6", "Enter Address Family command mode\n" @@ -5759,7 +5759,7 @@ DEFUN (address_family_encapv6, return CMD_SUCCESS; } -DEFUN (address_family_evpn, +DEFUN_NOSH (address_family_evpn, address_family_evpn_cmd, "address-family ", "Enter Address Family command mode\n" @@ -5771,7 +5771,7 @@ DEFUN (address_family_evpn, return CMD_SUCCESS; } -DEFUN (exit_address_family, +DEFUN_NOSH (exit_address_family, exit_address_family_cmd, "exit-address-family", "Exit from Address Family configuration mode\n") diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a513dda25..72bd081a7e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -570,7 +570,7 @@ bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t len } } - if_update_vrf (ifp, ifp->name, strlen (ifp->name), new_vrf_id); + if_update (ifp, ifp->name, strlen (ifp->name), new_vrf_id); bgp = bgp_lookup_by_vrf_id (new_vrf_id); if (!bgp) @@ -1026,7 +1026,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, { nexthop->v4 = local->sin.sin_addr; if (peer->update_if) - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); else ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr, peer->bgp->vrf_id); } @@ -1035,10 +1035,10 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { if (peer->conf_if || peer->ifname) - ifp = if_lookup_by_name_vrf (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); } else if (peer->update_if) - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); else ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr, local->sin6.sin6_scope_id, @@ -1509,7 +1509,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (!ifindex) { if (mpinfo->peer->conf_if || mpinfo->peer->ifname) - ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname); + ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname, bgp->vrf_id); else if (mpinfo->peer->nexthop.ifp) ifindex = mpinfo->peer->nexthop.ifp->ifindex; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ce0718df5a..3f81c1c50c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nht.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" @@ -1435,7 +1432,7 @@ bgp_peer_conf_if_to_su_update (struct peer *peer) return; prev_family = peer->su.sa.sa_family; - if ((ifp = if_lookup_by_name_vrf (peer->conf_if, peer->bgp->vrf_id))) + if ((ifp = if_lookup_by_name (peer->conf_if, peer->bgp->vrf_id))) { peer->ifp = ifp; /* If BGP unnumbered is not "v6only", we first see if we can derive the @@ -2937,10 +2934,18 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; bgp->dynamic_neighbors_count = 0; +#if DFLT_BGP_IMPORT_CHECK bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); +#endif +#if DFLT_BGP_SHOW_HOSTNAME bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); +#endif +#if DFLT_BGP_LOG_NEIGHBOR_CHANGES bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); +#endif +#if DFLT_BGP_DETERMINISTIC_MED bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); +#endif bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; bgp->as = *as; @@ -5016,8 +5021,28 @@ int peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) { struct peer_group *group; + struct peer *tmp_peer; struct listnode *node, *nnode; + /* If this is a peer-group we must first clear the flags for all of the + * peer-group members + */ + if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) + { + if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || + CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + tmp_peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change (tmp_peer, afi, safi, 0); + } + } + } + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) { @@ -5027,21 +5052,6 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) peer_on_policy_change (peer, afi, safi, 0); } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - } return 0; } @@ -7379,8 +7389,11 @@ bgp_config_write (struct vty *vty) inet_ntoa (bgp->router_id_static), VTY_NEWLINE); /* BGP log-neighbor-changes. */ - if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) + != DFLT_BGP_LOG_NEIGHBOR_CHANGES) + vty_out (vty, " %sbgp log-neighbor-changes%s", + bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no ", + VTY_NEWLINE); /* BGP configuration. */ if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) @@ -7396,8 +7409,11 @@ bgp_config_write (struct vty *vty) bgp->default_local_pref, VTY_NEWLINE); /* BGP default show-hostname */ - if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)) - vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE); + if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + != DFLT_BGP_SHOW_HOSTNAME) + vty_out (vty, " %sbgp default show-hostname%s", + bgp_flag_check (bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no ", + VTY_NEWLINE); /* BGP default subgroup-pkt-queue-max. */ if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) @@ -7440,8 +7456,11 @@ bgp_config_write (struct vty *vty) vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE); /* BGP deterministic-med. */ - if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) + != DFLT_BGP_DETERMINISTIC_MED) + vty_out (vty, " %sbgp deterministic-med%s", + bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no ", + VTY_NEWLINE); /* BGP update-delay. */ bgp_config_write_update_delay (vty, bgp); @@ -7517,8 +7536,11 @@ bgp_config_write (struct vty *vty) } /* BGP network import check. */ - if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) - vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) + != DFLT_BGP_IMPORT_CHECK) + vty_out (vty, " %sbgp network import-check%s", + bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no ", + VTY_NEWLINE); /* BGP flag dampening. */ if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], @@ -7647,6 +7669,8 @@ bgp_if_finish (struct bgp *bgp) } } +extern void bgp_snmp_init (void); + void bgp_init (void) { @@ -7695,10 +7719,6 @@ bgp_init (void) /* Community list initialize. */ bgp_clist = community_list_init (); -#ifdef HAVE_SNMP - bgp_snmp_init (); -#endif /* HAVE_SNMP */ - /* BFD init */ bgp_bfd_init(); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9ccc0e39de..a72974bc1d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "routemap.h" #include "linklist.h" +#include "defaults.h" #include "bgp_memory.h" #define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */ @@ -1068,12 +1069,13 @@ struct bgp_nlri #define BGP_EVENTS_MAX 15 /* BGP timers default value. */ +/* note: the DFLT_ ones depend on compile-time "defaults" selection */ #define BGP_INIT_START_TIMER 1 -#define BGP_DEFAULT_HOLDTIME 9 -#define BGP_DEFAULT_KEEPALIVE 3 +#define BGP_DEFAULT_HOLDTIME DFLT_BGP_HOLDTIME +#define BGP_DEFAULT_KEEPALIVE DFLT_BGP_KEEPALIVE #define BGP_DEFAULT_EBGP_ROUTEADV 0 #define BGP_DEFAULT_IBGP_ROUTEADV 0 -#define BGP_DEFAULT_CONNECT_RETRY 10 +#define BGP_DEFAULT_CONNECT_RETRY DFLT_BGP_TIMERS_CONNECT /* BGP default local preference. */ #define BGP_DEFAULT_LOCAL_PREF 100 diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 71086c8758..aa48b4924a 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -323,7 +323,7 @@ DEFUN (vnc_advertise_un_method, *-----------------------------------------------------------------------*/ -DEFUN (vnc_defaults, +DEFUN_NOSH (vnc_defaults, vnc_defaults_cmd, "vnc defaults", VNC_CONFIG_STR "Configure default NVE group\n") { @@ -2419,7 +2419,7 @@ vnc_routemap_event (route_map_event_t type, /* ignored */ *-----------------------------------------------------------------------*/ -DEFUN (vnc_nve_group, +DEFUN_NOSH (vnc_nve_group, vnc_nve_group_cmd, "vnc nve-group NAME", VNC_CONFIG_STR "Configure a NVE group\n" "Group name\n") @@ -3223,7 +3223,7 @@ DEFUN (vnc_nve_group_responselifetime, * with the lack of rigorous level control in the command handler. * TBD fix command handler. */ -DEFUN (exit_vnc, +DEFUN_NOSH (exit_vnc, exit_vnc_cmd, "exit-vnc", "Exit VNC configuration mode\n") @@ -3255,7 +3255,7 @@ static struct cmd_node bgp_vnc_nve_group_node = { * Note there are two types of NVEs, one for VPNs one for RFP NVEs *-----------------------------------------------------------------------*/ -DEFUN (vnc_vrf_policy, +DEFUN_NOSH (vnc_vrf_policy, vnc_vrf_policy_cmd, "vrf-policy NAME", "Configure a VRF policy group\n" @@ -3720,7 +3720,7 @@ DEFUN (vnc_vrf_policy_rd, return CMD_SUCCESS; } -DEFUN (exit_vrf_policy, +DEFUN_NOSH (exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy", "Exit VRF policy configuration mode\n") @@ -3743,7 +3743,7 @@ static struct cmd_node bgp_vrf_policy_node = { *-----------------------------------------------------------------------*/ -DEFUN (vnc_l2_group, +DEFUN_NOSH (vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n") diff --git a/configure.ac b/configure.ac index 821e0e230b..ec5442d065 100755 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ ## -## Configure template file for FreeRangeRouting. +## Configure template file for FRRouting. ## autoconf will generate configure script. ## ## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro @@ -7,9 +7,9 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.1-dev, [https://github.com/freerangerouting/frr/issues]) -PACKAGE_URL="https://freerangerouting.org/" -PACKAGE_FULLNAME="FreeRangeRouting" +AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues]) +PACKAGE_URL="https://frrouting.org/" +PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) CONFIG_ARGS="$ac_configure_args" @@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow AC_SUBST(pkgsrcdir) AC_SUBST(pkgsrcrcdir) +AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [ + moduledir="$withval" +], [ + moduledir="\${libdir}/frr/modules" +]) +AC_SUBST([moduledir], [$moduledir]) + AC_ARG_ENABLE(tcmalloc, AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]), [case "${enableval}" in @@ -66,6 +73,10 @@ LIBS="$LIBS -ltcmalloc_minimal" esac],[tcmalloc_enabled=false]) +dnl Thanks autoconf, but we don't want a default -g -O2. We have our own +dnl flag determination logic. +CFLAGS="${CFLAGS:-}" + dnl -------------------- dnl Check CC and friends dnl -------------------- @@ -78,6 +89,7 @@ AM_PROG_CC_C_O dnl remove autoconf default "-g -O2" CFLAGS="$orig_cflags" AC_PROG_CC_C99 +dnl NB: see C11 below AC_PROG_EGREP PKG_PROG_PKG_CONFIG @@ -89,7 +101,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false]) dnl try and enable CFLAGS that are useful for Quagga dnl - specifically, options to control warnings -AC_USE_SYSTEM_EXTENSIONS() +AC_USE_SYSTEM_EXTENSIONS AC_DEFUN([AC_C_FLAG], [{ AC_LANG_PUSH(C) ac_c_flag_save="$CFLAGS" @@ -115,6 +127,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006 dnl need to do this first so we get useful results for the other options AC_C_FLAG([-diag-error 10006]) +dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something +ac_cc="$CC" +CC="${CC% -std=gnu99}" +CC="${CC% -std=c99}" + +AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) + dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here if test "z$orig_cflags" = "z"; then AC_C_FLAG([-g]) @@ -170,6 +189,18 @@ AC_LINK_IFELSE( ]) AC_LANG_POP(C) +dnl ---------- +dnl Essentials +dnl ---------- + +AX_PTHREAD([ + CC="$PTHREAD_CC" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" +], [ + AC_MSG_FAILURE([This Quagga version needs pthreads]) +]) + dnl -------------- dnl Check programs dnl -------------- @@ -354,15 +385,18 @@ AC_SUBST(MPLS_METHOD) if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) + DFLT_NAME="datacenter" +else + DFLT_NAME="traditional" fi +AC_SUBST(DFLT_NAME) +AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set) if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) fi -if test "${enable_fpm}" = "yes"; then - AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support) -fi +AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) if test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) @@ -531,6 +565,72 @@ AC_CHECK_HEADERS([stropts.h sys/ksym.h \ linux/version.h asm/types.h \ sys/cdefs.h]) +ac_stdatomic_ok=false +AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs]) +AC_CHECK_HEADER([stdatomic.h],[ + + AC_MSG_CHECKING([whether _Atomic qualifier works]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#include +int main(int argc, char **argv) { + _Atomic int i = 0; + return i; +} +]])], [ + AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h]) + AC_MSG_RESULT([yes]) + ac_stdatomic_ok=true + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AS_IF([$ac_stdatomic_ok], [true], [ + AC_MSG_CHECKING([for __atomic_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __atomic_store_n (&i, 0, __ATOMIC_RELEASE); + return __atomic_load_n (&i, __ATOMIC_ACQUIRE); +} +]])], [ + AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + dnl FreeBSD 9 has a broken stdatomic.h where _Atomic doesn't work + AC_MSG_CHECKING([for __sync_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __sync_fetch_and_sub (&i, 1); + return __sync_val_compare_and_swap (&i, 0, 1); +} +]])], [ + AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins]) + AC_MSG_RESULT([yes]) + + AC_MSG_CHECKING([for __sync_swap builtin]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + return __sync_swap (&i, 2); +} +]])], [ + AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + ], [ + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([stdatomic.h unavailable and $CC has neither __atomic nor __sync builtins]) + ]) + ]) +]) + dnl Utility macro to avoid retyping includes all the time m4_define([FRR_INCLUDES], [#ifdef SUNOS_5 @@ -1327,8 +1427,8 @@ if test "${enable_snmp}" != ""; then if test x"$NETSNMP_CONFIG" = x"no"; then AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config]) fi - LIBS="$LIBS `${NETSNMP_CONFIG} --agent-libs`" - CFLAGS="`${NETSNMP_CONFIG} --base-cflags` $CFLAGS" + SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" + SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`" AC_MSG_CHECKING([whether we can link to Net-SNMP]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ int main(void); @@ -1340,7 +1440,6 @@ int main(void); ])],[AC_MSG_RESULT(yes)],[ AC_MSG_RESULT(no) AC_MSG_ERROR([--enable-snmp given but not usable])]) - AC_DEFINE(HAVE_SNMP,,SNMP) case "${enable_snmp}" in yes) SNMP_METHOD=agentx @@ -1356,6 +1455,53 @@ int main(void); AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd]) AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi +AM_CONDITIONAL([SNMP], [test "x${SNMP_METHOD}" != "x"]) +AC_SUBST(SNMP_LIBS) +AC_SUBST(SNMP_CFLAGS) + +dnl --------------- +dnl dlopen & dlinfo +dnl --------------- +AC_SEARCH_LIBS(dlopen, [dl dld], [], [ + AC_MSG_ERROR([unable to find the dlopen()]) +]) + +AC_CHECK_HEADERS([link.h]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_ORIGIN)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + char origin[1]; + dlinfo (NULL, RTLD_DI_ORIGIN, &origin); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN]) +], [ + AC_MSG_RESULT(no) +]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_LINKMAP)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + struct link_map *lm = NULL; + dlinfo (NULL, RTLD_DI_LINKMAP, &lm); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP]) +], [ + AC_MSG_RESULT(no) +]) + dnl --------------------------- dnl sockaddr and netinet checks @@ -1656,14 +1802,18 @@ AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary) CFG_SYSCONF="$sysconfdir" CFG_SBIN="$sbindir" CFG_STATE="$frr_statedir" +CFG_MODULE="$moduledir" for I in 1 2 3 4 5 6 7 8 9 10; do eval CFG_SYSCONF="\"$CFG_SYSCONF\"" eval CFG_SBIN="\"$CFG_SBIN\"" eval CFG_STATE="\"$CFG_STATE\"" + eval CFG_MODULE="\"$CFG_MODULE\"" done AC_SUBST(CFG_SYSCONF) AC_SUBST(CFG_SBIN) AC_SUBST(CFG_STATE) +AC_SUBST(CFG_MODULE) +AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules) dnl --------------------------- dnl Check htonl works correctly @@ -1692,6 +1842,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile snapcraft/Makefile snapcraft/snapcraft.yaml lib/version.h + tests/lib/cli/test_cli.refout doc/defines.texi doc/bgpd.8 doc/isisd.8 @@ -1728,7 +1879,7 @@ AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl]) AC_OUTPUT echo " -FreeRangeRouting configuration +FRRouting configuration ------------------------------ FRR version : ${PACKAGE_VERSION} host operating system : ${host_os} @@ -1740,6 +1891,7 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM} state file directory : ${frr_statedir} config file directory : `eval echo \`echo ${sysconfdir}\`` example directory : `eval echo \`echo ${exampledir}\`` +module directory : ${CFG_MODULE} user to run as : ${enable_user} group to run as : ${enable_group} group for vty sockets : ${enable_vty_group} diff --git a/debian/README.Debian b/debian/README.Debian index caded52075..4cf35d7e32 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -14,7 +14,7 @@ available forcing you to explicitly type "apt-get install frr" to upgrade it. * What is frr? ================= -http://www.freerangerouting.org/ +http://www.frrouting.org/ FRR is a routing software suite, providing implementations of OSPFv2, OSPFv3, RIP v1 and v2, RIPng, ISIS, PIM, BGP and LDP for Unix platforms, particularly FreeBSD and Linux and also NetBSD, to mention a few. FRR is a fork of Quagga diff --git a/debian/copyright b/debian/copyright index 6a5ed98f91..7b873abd31 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,7 +1,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Frr -Upstream-Contact: maintainers@freerangerouting.org, security@freerangerouting.org -Source: http://www.freerangerouting.org/ +Upstream-Contact: maintainers@frrouting.org, security@frrouting.org +Source: http://www.frrouting.org/ Files: * Copyright: 1996-2003 by the original Zebra authors: diff --git a/defaults.h b/defaults.h new file mode 100644 index 0000000000..57e35f3ce6 --- /dev/null +++ b/defaults.h @@ -0,0 +1,54 @@ +/* + * FRR switchable defaults. + * Copyright (C) 2017 David Lamparter for NetDEF, Inc. + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FRR_DEFAULTS_H +#define _FRR_DEFAULTS_H + +#include "config.h" + +#ifdef HAVE_CUMULUS + +#define DFLT_BGP_IMPORT_CHECK 1 +#define DFLT_BGP_TIMERS_CONNECT 10 +#define DFLT_BGP_HOLDTIME 9 +#define DFLT_BGP_KEEPALIVE 3 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1 +#define DFLT_BGP_SHOW_HOSTNAME 1 +#define DFLT_BGP_DETERMINISTIC_MED 1 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1 + +#else /* !HAVE_CUMULUS */ + +#define DFLT_BGP_IMPORT_CHECK 0 +#define DFLT_BGP_TIMERS_CONNECT 120 +#define DFLT_BGP_HOLDTIME 180 +#define DFLT_BGP_KEEPALIVE 60 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0 +#define DFLT_BGP_SHOW_HOSTNAME 0 +#define DFLT_BGP_DETERMINISTIC_MED 0 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0 + +#endif /* !HAVE_CUMULUS */ + +#endif /* _FRR_DEFAULTS_H */ diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index ccb07fb2ac..9f40418fff 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -18,7 +18,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - flex pytest + flex c-ares-devel epel-release rpm-build libcap-devel texi2html Install newer version of bison (CentOS 6 package source is too old) from CentOS 7 @@ -48,16 +48,16 @@ Install newer version of autoconf and automake (Package versions are too old) Install `Python 2.7` in parallel to default 2.6 (needed for `make check` to run unittests). -Pick correct EPEL based on CentOS version used. Then install current `pytest` +Make sure you've install EPEL (`epel-release` as above). Then install current +`python2.7` and `pytest` - rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm - yum install python27 python27-pip + yum install python27 python27-devel python27-pip pip2.7 install pytest Please note that `CentOS 6` needs to keep python pointing to version 2.6 for `yum` to keep working, so don't create a symlink for python2.7 to python - + Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -69,7 +69,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -78,9 +78,8 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --sysconfdir=/etc/frr \ diff --git a/doc/Building_FRR_on_CentOS7.md b/doc/Building_FRR_on_CentOS7.md index cd10a91ed7..0ab5c0ff54 100644 --- a/doc/Building_FRR_on_CentOS7.md +++ b/doc/Building_FRR_on_CentOS7.md @@ -10,12 +10,16 @@ CentOS 7 restrictions: Install required packages ------------------------- - + Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - bison flex pytest + bison flex pytest c-ares-devel python-devel rpm-build + +To build from git (in difference to building from distribution tar.gz as created by `make dist`), the python development libraries are needed. (Make sure you've installed EPEL libraries as shown above for this to work) + + yum install python34-devel Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -28,7 +32,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -37,9 +41,8 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --sysconfdir=/etc/frr \ diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 902f8c623a..b902033d5e 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -10,12 +10,12 @@ Debian 8 restrictions: Install required packages ------------------------- - + Add packages: sudo apt-get install git autoconf automake libtool make gawk \ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \ - python-pip + python-pip libc-ares-dev python3-dev Install newer pytest (>3.0) from pip @@ -32,16 +32,15 @@ any packages** sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 85 frrvty sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ - --gecos "FRR FreeRangeRouting suite" --shell /bin/false frr + --gecos "FRR FRRouting suite" --shell /bin/false frr sudo usermode ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --enable-exampledir=/usr/share/doc/frr/examples/ \ diff --git a/doc/Building_FRR_on_Fedora24.md b/doc/Building_FRR_on_Fedora24.md index 9617afc733..941126da42 100644 --- a/doc/Building_FRR_on_Fedora24.md +++ b/doc/Building_FRR_on_Fedora24.md @@ -8,7 +8,8 @@ Add packages: sudo dnf install git autoconf automake libtool make gawk \ readline-devel texinfo net-snmp-devel groff pkgconfig \ - json-c-devel pam-devel perl-XML-LibXML pytest + json-c-devel pam-devel perl-XML-LibXML c-ares-devel \ + python3-devel Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -21,7 +22,7 @@ using any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -30,9 +31,8 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --sysconfdir=/etc/frr \ diff --git a/doc/Building_FRR_on_FreeBSD10.md b/doc/Building_FRR_on_FreeBSD10.md index 696b7d5d2e..36ef573bb0 100644 --- a/doc/Building_FRR_on_FreeBSD10.md +++ b/doc/Building_FRR_on_FreeBSD10.md @@ -16,7 +16,7 @@ Add packages: install and asked) pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ - bison flex py27-pytest + bison flex py27-pytest c-ares python3 Make sure there is no /usr/bin/flex preinstalled (and use the newly installed in /usr/local/bin): @@ -41,9 +41,8 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh export MAKE=gmake export LDFLAGS="-L/usr/local/lib" diff --git a/doc/Building_FRR_on_FreeBSD11.md b/doc/Building_FRR_on_FreeBSD11.md index d0b8a7bf88..d6affd688b 100644 --- a/doc/Building_FRR_on_FreeBSD11.md +++ b/doc/Building_FRR_on_FreeBSD11.md @@ -16,7 +16,7 @@ Add packages: install and asked) pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ - bison flex py27-pytest + bison flex py27-pytest c-ares python3 Make sure there is no /usr/bin/flex preinstalled (and use the newly installed in /usr/local/bin): @@ -41,9 +41,8 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh export MAKE=gmake export LDFLAGS="-L/usr/local/lib" diff --git a/doc/Building_FRR_on_FreeBSD9.md b/doc/Building_FRR_on_FreeBSD9.md index d470d0046a..41d3148ad7 100644 --- a/doc/Building_FRR_on_FreeBSD9.md +++ b/doc/Building_FRR_on_FreeBSD9.md @@ -16,7 +16,8 @@ Add packages: install and asked) pkg install -y git autoconf automake libtool gmake gawk \ - pkgconf texinfo json-c bison flex py27-pytest + pkgconf texinfo json-c bison flex py27-pytest c-ares \ + python3 Make sure there is no /usr/bin/flex preinstalled (and use the newly installed in /usr/local/bin): @@ -25,6 +26,13 @@ takes preference in path) rm -f /usr/bin/flex +For building with clang (instead of gcc), upgrade clang from 3.4 default to 3.6 *This is needed to build FreeBSD packages as well - for packages clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during compile) + + pkg install clang36 + pkg delete clang34 + mv /usr/bin/clang /usr/bin/clang34 + ln -s /usr/local/bin/clang36 /usr/bin/clang + Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -41,9 +49,8 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh export MAKE=gmake export LDFLAGS="-L/usr/local/lib" diff --git a/doc/Building_FRR_on_NetBSD6.md b/doc/Building_FRR_on_NetBSD6.md index 03d04ce954..542a7f489e 100644 --- a/doc/Building_FRR_on_NetBSD6.md +++ b/doc/Building_FRR_on_NetBSD6.md @@ -18,7 +18,7 @@ Configure Package location: Add packages: sudo pkg_add git autoconf automake libtool gmake gawk openssl \ - pkg-config json-c p5-XML-LibXML python27 py27-test + pkg-config json-c p5-XML-LibXML python27 py27-test python35 Install SSL Root Certificates (for git https access): @@ -45,9 +45,8 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh MAKE=gmake export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" diff --git a/doc/Building_FRR_on_NetBSD7.md b/doc/Building_FRR_on_NetBSD7.md index d9b4b47ea6..821a6109f2 100644 --- a/doc/Building_FRR_on_NetBSD7.md +++ b/doc/Building_FRR_on_NetBSD7.md @@ -12,7 +12,7 @@ Install required packages ------------------------- sudo pkgin install git autoconf automake libtool gmake gawk openssl \ - pkg-config json-c p5-XML-LibXML python27 py27-test + pkg-config json-c p5-XML-LibXML python27 py27-test python35 Install SSL Root Certificates (for git https access): @@ -39,9 +39,8 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh MAKE=gmake export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" diff --git a/doc/Building_FRR_on_OmniOS.md b/doc/Building_FRR_on_OmniOS.md index f158c80a75..2e9871467b 100644 --- a/doc/Building_FRR_on_OmniOS.md +++ b/doc/Building_FRR_on_OmniOS.md @@ -41,7 +41,7 @@ Add additional Solaris packages: /opt/csw/bin/pkgutil -y -i texinfo /opt/csw/bin/pkgutil -y -i perl /opt/csw/bin/pkgutil -y -i libjson_c_dev - /opt/csw/bin/pkgutil -y -i python27 py_pip + /opt/csw/bin/pkgutil -y -i python27 py_pip python27_dev Add libjson to Solaris equivalent of ld.so.conf @@ -61,7 +61,7 @@ Select Python 2.7 as default (required for pytest) rm -f /usr/bin/python ln -s /opt/csw/bin/python2.7 /usr/bin/python - + Fix PATH for all users and non-interactive sessions. Edit `/etc/default/login` and add the following default PATH: @@ -87,13 +87,13 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh export MAKE=gmake export LDFLAGS="-L/opt/csw/lib" export CPPFLAGS="-I/opt/csw/include" + export PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig ./configure \ --sysconfdir=/etc/frr \ --enable-exampledir=/usr/share/doc/frr/examples/ \ diff --git a/doc/Building_FRR_on_OpenBSD6.md b/doc/Building_FRR_on_OpenBSD6.md index 9e13d5ce45..a59452a72b 100644 --- a/doc/Building_FRR_on_OpenBSD6.md +++ b/doc/Building_FRR_on_OpenBSD6.md @@ -1,12 +1,6 @@ Building FRR on OpenBSD 6 from Git Source ========================================= -OpenBSD restrictions: ---------------------- - -- MPLS is not tested on `OpenBSD`. It may work as it shares the - sources with the LDPd on OpenBSD. Bug reports and fixes are welcome - Install required packages ------------------------- @@ -40,9 +34,8 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh export LDFLAGS="-L/usr/local/lib" export CPPFLAGS="-I/usr/local/include" @@ -61,7 +54,6 @@ an example) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion gmake @@ -99,6 +91,18 @@ Add the following lines to the end of `/etc/rc.conf`: **Reboot** to apply the config to the system +### Enable MPLS Forwarding + +To enable MPLS forwarding on a given interface, use the following command: + + sudo ifconfig em0 mpls + +Alternatively, to make MPLS forwarding persistent across reboots, add the "mpls" +keyword in the hostname.* files of the desired interfaces. Example: + + cat /etc/hostname.em0 + inet 10.0.1.1 255.255.255.0 mpls + ### Install rc.d init files (create them in /etc/rc.d - no example are included at this time with FRR source) diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index 3312a2c9c8..154907d9df 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -12,8 +12,8 @@ Install required packages Add packages: apt-get install git autoconf automake libtool make gawk libreadline-dev \ - texinfo libpam0g-dev dejagnu libjson0 pkg-config libpam0g-dev \ - libjson0-dev flex python-pip + texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \ + libjson0-dev flex python-pip libc-ares-dev python3-dev Install newer bison from 14.04 package source (Ubuntu 12.04 package source is too old) @@ -72,9 +72,8 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --enable-exampledir=/usr/share/doc/frr/examples/ \ @@ -94,7 +93,6 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make @@ -104,20 +102,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index ac0a45acdf..33ef896a9a 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -8,12 +8,12 @@ Building FRR on Ubuntu 14.04LTS from Git Source Install required packages ------------------------- - + Add packages: apt-get install git autoconf automake libtool make gawk libreadline-dev \ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \ - python-pytest + python-pytest libc-ares-dev python3-dev Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -32,9 +32,8 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --enable-exampledir=/usr/share/doc/frr/examples/ \ @@ -63,19 +62,19 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index d1e1a377d0..18724859fb 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -14,7 +14,7 @@ Add packages: apt-get install git autoconf automake libtool make gawk libreadline-dev \ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \ - python-pytest + python-pytest libc-ares-dev python3-dev Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -33,9 +33,8 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/2.0 ./bootstrap.sh ./configure \ --enable-exampledir=/usr/share/doc/frr/examples/ \ @@ -55,7 +54,6 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make @@ -65,20 +63,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/basic.texi b/doc/basic.texi index cea33eaa81..05d72bc80f 100644 --- a/doc/basic.texi +++ b/doc/basic.texi @@ -18,6 +18,7 @@ daemons. * Config Commands:: Commands used in config files * Terminal Mode Commands:: Common commands used in a VTY * Common Invocation Options:: Starting the daemons +* Loadable Module Support:: Using extension modules * Virtual Terminal Interfaces:: Interacting with the daemons @end menu @@ -372,6 +373,51 @@ Print program version. @end table +@node Loadable Module Support +@section Loadable Module Support + +FRR supports loading extension modules at startup. Loading, reloading or +unloading modules at runtime is not supported (yet). To load a module, use +the following command line option at daemon startup: + +@table @samp +@item -M @var{module:options} +@itemx --module @var{module:options} + +Load the specified module, optionally passing options to it. If the module +name contains a slash (/), it is assumed to be a full pathname to a file to +be loaded. If it does not contain a slash, the +@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of +the given name; first with the daemon name prepended (e.g. @code{zebra_mod} +for @code{mod}), then without the daemon name prepended. + +This option is available on all daemons, though some daemons may not have +any modules available to be loaded. +@end table + + +@subsection The SNMP Module + +If SNMP is enabled during compile-time and installed as part of the package, +the @code{snmp} module can be loaded for the @command{zebra}, +@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons. + +The module ignores any options passed to it. Refer to @ref{SNMP Support} +for information on its usage. + + +@subsection The FPM Module + +If FPM is enabled during compile-time and installed as part of the package, +the @code{fpm} module can be loaded for the @command{zebra} daemon. This +provides the Forwarding Plane Manager ("FPM") API. + +The module expects its argument to be either @code{netlink} or +@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the +default, and @code{protobuf} may not be available if the module was built +without protobuf support. Refer to @ref{zebra FIB push interface} for more +information. + @node Virtual Terminal Interfaces @section Virtual Terminal Interfaces diff --git a/doc/bgpd.8.in b/doc/bgpd.8.in index 9026f2cdee..0df1b1dcea 100644 --- a/doc/bgpd.8.in +++ b/doc/bgpd.8.in @@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@ ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B bgpd @@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR. \fB\-S\fR, \fB\-\-skip_runas\fR Skip setting the process effective user and group. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBbgpd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/defines.texi.in b/doc/defines.texi.in index 43d7442939..0fadba964a 100644 --- a/doc/defines.texi.in +++ b/doc/defines.texi.in @@ -13,6 +13,7 @@ @set INSTALL_PREFIX_ETC @CFG_SYSCONF@ @set INSTALL_PREFIX_SBIN @CFG_SBIN@ @set INSTALL_PREFIX_STATE @CFG_STATE@ +@set INSTALL_PREFIX_MODULES @CFG_MODULE@ @set INSTALL_USER @enable_user@ @set INSTALL_GROUP @enable_group@ @set INSTALL_VTY_GROUP @enable_vty_group@ diff --git a/doc/dev-modules.md b/doc/dev-modules.md new file mode 100644 index 0000000000..87bc963188 --- /dev/null +++ b/doc/dev-modules.md @@ -0,0 +1,119 @@ +# Module and Hook support (developer docs) + +## What it does + +It uses `dlopen()` to load DSOs at startup. + + +## Limitations + +* can't load, unload, or reload during runtime. This just needs some work + and can probably be done in the future. +* doesn't fix any of the "things need to be changed in the code in the library" + issues. Most prominently, you can't add a CLI node because CLI nodes are + listed in the library... +* if your module crashes, the daemon crashes. Should be obvious. +* **does not provide a stable API or ABI**. Your module must match a version + of FRR and you may have to update it frequently to match changes. +* **does not create a license boundary**. Your module will need to link + libzebra and include header files from the daemons, meaning it will be + GPL-encumbered. + + +## Installation + +Look for `moduledir` in `configure.ac`, default is normally +`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`. + +The daemon's name is prepended when looking for a module, e.g. "snmp" tries +to find "zebra_snmp" first when used in zebra. This is just to make it nicer +for the user, with the snmp module having the same name everywhere. + +Modules can be packaged separately from FRR. The SNMP and FPM modules are +good candidates for this because they have dependencies (net-snmp / protobuf) +that are not FRR dependencies. However, any distro packages should have an +"exact-match" dependency onto the FRR package. Using a module from a +different FRR version will probably blow up nicely. + +For snapcraft (and during development), modules can be loaded with full path +(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output +files in the .libs directory, so during development you have to use +`./zebra -M .libs/zebra_snmp.so`. + + +## Creating a module + +... best to look at the existing SNMP or FPM modules. + +Basic boilerplate: + +``` +#include "hook.h" +#include "module.h" + +static int +module_init (void) +{ + hook_register(frr_late_init, module_late_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "my module", + .version = "0.0", + .description = "my module", + .init = module_init, +) +``` + +The `frr_late_init` hook will be called after the daemon has finished its +other startup and is about to enter the main event loop; this is the best +place for most initialisation. + + +## Compiler & Linker magic + +There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility` +attributes to restrict it to the current module. If you get a linker error +with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be +possible, though one way to get it would be to not include libzebra (which +provides a fallback definition for the symbol). + +libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable +modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use +the definition in libzebra; same applies if the main executable doesn't use +`FRR_DAEMON_INFO` (e.g. all testcases). + +The deciding factor here is "what dynamic linker unit are you using the symbol +from." If you're in a library function and want to know who called you, you +can't use `THIS_MODULE` (because that'll just tell you you're in the library). +Put a macro around your function that adds `THIS_MODULE` in the *caller's +code calling your function*. + +The idea is to use this in the future for module unloading. Hooks already +remember which module they were installed by, as groundwork for a function +that removes all of a module's installed hooks. + +There's also the `frr_module` symbol in modules, pretty much a standard entry +point for loadable modules. + + +## Hooks + +Hooks are just points in the code where you can register your callback to +be called. The parameter list is specific to the hook point. Since there is +no stable API, the hook code has some extra type safety checks making sure +you get a compiler warning when the hook parameter list doesn't match your +callback. Don't ignore these warnings. + + +## Relation to MTYPE macros + +The MTYPE macros, while primarily designed to decouple MTYPEs from the library +and beautify the code, also work very nicely with loadable modules -- both +constructors and destructors are executed when loading/unloading modules. + +This means there is absolutely no change required to MTYPEs, you can just use +them in a module and they will even clean up themselves when we implement +module unloading and an unload happens. In fact, it's impossible to create +a bug where unloading fails to de-register a MTYPE. diff --git a/doc/frr.texi b/doc/frr.texi index a64dc9e729..b08bb6fd04 100644 --- a/doc/frr.texi +++ b/doc/frr.texi @@ -7,7 +7,7 @@ @setfilename frr.info @c Set variables - sourced from defines.texi @include defines.texi -@settitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} +@settitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @c %**end of header @c automake will automatically generate version.texi @@ -48,16 +48,16 @@ This file documents the Frr Software Routing Suite which manages common TCP/IP routing protocols. This is Edition @value{EDITION}, last updated @value{UPDATED} of -@cite{The Frr Manual}, for @uref{http://www.freerangerouting.org/,,@value{PACKAGE_NAME}} +@cite{The Frr Manual}, for @uref{http://www.frrouting.org/,,@value{PACKAGE_NAME}} Version @value{VERSION}. @insertcopying @end ifinfo @titlepage -@title @uref{http://www.freerangerouting.org,,Frr} +@title @uref{http://www.frrouting.org,,Frr} @subtitle A routing software package for TCP/IP networks -@subtitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} @value{VERSION} +@subtitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @value{VERSION} @subtitle @value{UPDATED-MONTH} @author @value{AUTHORS} @@ -72,9 +72,9 @@ Version @value{VERSION}. @node Top @top Frr -- With Virtual Network Control -@uref{http://www.freerangerouting.org,,Frr} is an advanced routing software package +@uref{http://www.frrouting.org,,Frr} is an advanced routing software package that provides a suite of TCP/IP based routing protocols. This is the Manual -for @value{PACKAGE_STRING}. @uref{http://www.freerangerouting.org,,Frr} is a fork of +for @value{PACKAGE_STRING}. @uref{http://www.frrouting.org,,Frr} is a fork of @uref{http://www.quagga.net,,Quagga}. @insertcopying diff --git a/doc/git_branches.svg b/doc/git_branches.svg index 3943eeacc8..0c2c96e39e 100644 --- a/doc/git_branches.svg +++ b/doc/git_branches.svg @@ -1,3 +1,720 @@ - -1.0ReleaseBranchMaster(Stable)Develop1.1ReleaseBranchVersion 1.0.a1Version 1.1.a1Version 1.1.a2Version 1.1.b1Patch Email (Patchwork)Github Pull RequestGithub Pull RequestPatch Email (Patchwork)Patch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestPatch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestVersion 1.0.a2Version 1.0.b1Version 1.0.0Version 1.1.0Version 1.1.1Version 1.1.2 + + + + + image/svg+xml + + + + + + + + + + + + + + + 1.0ReleaseBranch + + + + + + + + + + Master(Stable) + + + + + + + + + 1.1ReleaseBranch + Version 1.0.a1 + Version 1.1.a1 + Version 1.1.a2 + + + + + Version 1.1.b1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + + + + + + + + + Version 1.0.a2 + Version 1.0.b1 + Version 1.0.0 + Version 1.1.0 + Version 1.1.1 + Version 1.1.2 + + + + + + + + + + + + + + + + + + diff --git a/doc/isisd.8.in b/doc/isisd.8.in index 9ffcbc618d..542c289935 100644 --- a/doc/isisd.8.in +++ b/doc/isisd.8.in @@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B isisd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBisisd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ldpd.8.in b/doc/ldpd.8.in index 1683de46ca..2d68a31a50 100644 --- a/doc/ldpd.8.in +++ b/doc/ldpd.8.in @@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ldpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBldpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/main.texi b/doc/main.texi index dfe02e1b5d..706baa25f7 100644 --- a/doc/main.texi +++ b/doc/main.texi @@ -385,7 +385,8 @@ ip protocol rip route-map RM1 Zebra supports a 'FIB push' interface that allows an external component to learn the forwarding information computed by the Frr -routing suite. +routing suite. This is a loadable module that needs to be enabled +at startup as described in @ref{Loadable Module Support}. In Frr, the Routing Information Base (RIB) resides inside zebra. Routing protocols communicate their best routes to zebra, and @@ -440,9 +441,9 @@ independently. @end itemize As mentioned before, zebra encodes routes sent to the FPM in netlink -format by default. The format can be controlled via the -@code{--fpm_format} command-line option to zebra, which currently -takes the values @code{netlink} and @code{protobuf}. +format by default. The format can be controlled via the FPM module's +load-time option to zebra, which currently takes the values @code{netlink} +and @code{protobuf}. The zebra FPM interface uses replace semantics. That is, if a 'route add' message for a prefix is followed by another 'route add' message, diff --git a/doc/nhrpd.8.in b/doc/nhrpd.8.in index c5e4f7e324..09b662ae7c 100644 --- a/doc/nhrpd.8.in +++ b/doc/nhrpd.8.in @@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B nhrpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBnhrpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospf6d.8.in b/doc/ospf6d.8.in index 7f94782bea..02d9d8083d 100644 --- a/doc/ospf6d.8.in +++ b/doc/ospf6d.8.in @@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospf6d @@ -64,6 +67,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospf6d\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospfd.8.in b/doc/ospfd.8.in index 1b86551ca5..6bad777711 100644 --- a/doc/ospfd.8.in +++ b/doc/ospfd.8.in @@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospfd @@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-a\fR, \fB\-\-apiserver \fR Enable OSPF apiserver. Default is disabled. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospfd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/overview.texi b/doc/overview.texi index 370ada3f8a..7ecf3d95c3 100644 --- a/doc/overview.texi +++ b/doc/overview.texi @@ -2,7 +2,7 @@ @chapter Overview @cindex Overview - @uref{http://www.freerangerouting.org,,Frr} is a routing software package that + @uref{http://www.frrouting.org,,Frr} is a routing software package that provides TCP/IP based routing services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+ (@pxref{Supported RFCs}). Frr also supports special BGP Route Reflector and Route Server @@ -275,12 +275,12 @@ November 1995.} The official Frr web-site is located at: -@uref{http://www.freerangerouting.org/} +@uref{http://www.frrouting.org/} and contains further information, as well as links to additional resources. -@uref{http://www.freerangerouting.org/,Frr} is a fork of Quagga, whose +@uref{http://www.frrouting.org/,Frr} is a fork of Quagga, whose web-site is located at: @uref{http://www.quagga.net/}. @@ -298,7 +298,7 @@ comments or suggestions to Frr, please subscribe to: @uref{http://lists.nox.tf/listinfo/frr-users}. -The @uref{http://www.freerangerouting.org/,,Frr} site has further information on +The @uref{http://www.frrouting.org/,,Frr} site has further information on the available mailing lists, see: @uref{http://lists.nox.tf/lists.php} @@ -315,7 +315,7 @@ the available mailing lists, see: If you think you have found a bug, please send a bug report to: -@uref{http://github.com/freerangerouting/frr/issues} +@uref{http://github.com/frrouting/frr/issues} When you send a bug report, please be careful about the points below. @@ -334,4 +334,4 @@ arguments to the configure script please note that too. Bug reports are very important for us to improve the quality of Frr. Frr is still in the development stage, but please don't hesitate to -send a bug report to @uref{http://github.com/freerangerouting/frr/issues}. +send a bug report to @uref{http://github.com/frrouting/frr/issues}. diff --git a/doc/pimd.8.in b/doc/pimd.8.in index 60b844b1e7..3fb060e564 100644 --- a/doc/pimd.8.in +++ b/doc/pimd.8.in @@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B pimd @@ -70,6 +73,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBpimd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .TP diff --git a/doc/ripd.8.in b/doc/ripd.8.in index 6db5ac3649..a84668e6dd 100644 --- a/doc/ripd.8.in +++ b/doc/ripd.8.in @@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBripd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ripngd.8.in b/doc/ripngd.8.in index 4c5f2bb114..98039219a7 100644 --- a/doc/ripngd.8.in +++ b/doc/ripngd.8.in @@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripngd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBripngd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/snmp.texi b/doc/snmp.texi index c2c889de76..d9656941d0 100644 --- a/doc/snmp.texi +++ b/doc/snmp.texi @@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol (@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the routing protocol MIBs available through it. +Note that SNMP Support needs to be enabled at compile-time and loaded as +module on daemon startup. Refer to @ref{Loadable Module Support} on +the latter. + @menu * Getting and installing an SNMP agent:: * AgentX configuration:: diff --git a/doc/watchfrr.8.in b/doc/watchfrr.8.in index 813f87abd3..82098e1b0d 100644 --- a/doc/watchfrr.8.in +++ b/doc/watchfrr.8.in @@ -108,13 +108,13 @@ Set the logging (LOG_DEBUG), but higher number can be supplied if extra debugging messages are required. .TP -.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number +.BI \-\-min\-restart\-interval " number Set the minimum .I number of seconds to wait between invocations of the daemon restart commands (the default value is "60"). .TP -.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number +.BI \-\-max\-restart\-interval " number Set the maximum .I number of seconds to wait between invocations of the daemon restart commands (the diff --git a/doc/zebra.8.in b/doc/zebra.8.in index 4599a85635..f5b8bd4d80 100644 --- a/doc/zebra.8.in +++ b/doc/zebra.8.in @@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B zebra @@ -86,6 +89,14 @@ maximum before starting zebra. Note that this affects Linux only. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR and \fBfpm\fR modules may be +available for \fBzebra\fR, if the package was built with SNMP and FPM support +respectively. The \fBfpm\fR module takes an additional colon-separated +argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR. +It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 6ec7771ec2..dd07a9c6f5 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -279,6 +279,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), MSG_DONTWAIT, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + + if (bytesread < 0) + zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; } /* @@ -322,10 +326,10 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) addr_len = sizeof (s_addr); /* we can read directly to the stream */ - bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd, - circuit->interface->mtu, 0, - (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); + stream_recvfrom (circuit->rcv_stream, circuit->fd, + circuit->interface->mtu, 0, + (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); if (s_addr.sll_pkttype == PACKET_OUTGOING) { diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index db46078f20..554fa563ad 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -68,7 +68,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->sys_type < adj->sys_type) { excess = node; - candidate = adj; continue; } if (candidate->sys_type > adj->sys_type) @@ -78,7 +77,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } if (comp < 0) @@ -87,7 +85,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->circuit->circuit_id > adj->circuit->circuit_id) { excess = node; - candidate = adj; continue; } @@ -98,7 +95,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } } diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 830ccb37c6..b04d0db3ca 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -1323,7 +1323,7 @@ DEFUN (show_isis_mpls_te_interface, /* Interface name is specified. */ else { - if ((ifp = if_lookup_by_name (argv[idx_interface]->arg)) == NULL) + if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL) vty_out (vty, "No such interface name%s", VTY_NEWLINE); else show_mpls_te_sub (vty, ifp); diff --git a/isisd/isisd.c b/isisd/isisd.c index 2863d2f678..f226c4a1f3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1576,7 +1576,7 @@ DEFUN (show_database, /* * 'router isis' command */ -DEFUN (router_isis, +DEFUN_NOSH (router_isis, router_isis_cmd, "router isis WORD", ROUTER_STR diff --git a/ldpd/Makefile.am b/ldpd/Makefile.am index 42e54138aa..19f819ae36 100644 --- a/ldpd/Makefile.am +++ b/ldpd/Makefile.am @@ -24,7 +24,9 @@ noinst_HEADERS = \ control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h ldp_vty_cmds.c: $(srcdir)/ldp_vty.xml $(srcdir)/../tools/xml2cli.pl - @PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml > $@ + @PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml | \ + sed -e 's%DEFUN \((ldp_\(interface_\|mpls_ldp\|address_family\|l2vpn_word\|member_pseudo\)\)%DEFUN_NOSH \1%' \ + > $@ ldpd_SOURCES = ldpd.c ldpd_LDADD = libldp.a ../lib/libfrr.la @LIBCAP@ diff --git a/ldpd/address.c b/ldpd/address.c index ad23ca690b..584240de84 100644 --- a/ldpd/address.c +++ b/ldpd/address.c @@ -104,6 +104,18 @@ send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list, } evbuf_enqueue(&nbr->tcp->wbuf, buf); + + /* no errors - update per neighbor message counters */ + switch (msg_type) { + case MSG_TYPE_ADDR: + nbr->stats.addr_sent++; + break; + case MSG_TYPE_ADDRWITHDRAW: + nbr->stats.addrwdraw_sent++; + break; + default: + break; + } } nbr_fsm(nbr, NBR_EVT_PDU_SENT); diff --git a/ldpd/adjacency.c b/ldpd/adjacency.c index 2e7b43296a..8659202ee4 100644 --- a/ldpd/adjacency.c +++ b/ldpd/adjacency.c @@ -41,6 +41,16 @@ RB_GENERATE(tnbr_head, tnbr, entry, tnbr_compare) static __inline int adj_compare(struct adj *a, struct adj *b) { + if (adj_get_af(a) < adj_get_af(b)) + return (-1); + if (adj_get_af(a) > adj_get_af(b)) + return (1); + + if (ntohl(a->lsr_id.s_addr) < ntohl(b->lsr_id.s_addr)) + return (-1); + if (ntohl(a->lsr_id.s_addr) > ntohl(b->lsr_id.s_addr)) + return (1); + if (a->source.type < b->source.type) return (-1); if (a->source.type > b->source.type) @@ -54,21 +64,13 @@ adj_compare(struct adj *a, struct adj *b) if (strcmp(a->source.link.ia->iface->name, b->source.link.ia->iface->name) > 0) return (1); - if (a->source.link.ia->af < b->source.link.ia->af) - return (-1); - if (a->source.link.ia->af > b->source.link.ia->af) - return (1); return (ldp_addrcmp(a->source.link.ia->af, &a->source.link.src_addr, &b->source.link.src_addr)); case HELLO_TARGETED: - if (a->source.target->af < b->source.target->af) - return (-1); - if (a->source.target->af > b->source.target->af) - return (1); return (ldp_addrcmp(a->source.target->af, &a->source.target->addr, &b->source.target->addr)); default: - fatalx("adj_get_af: unknown hello type"); + fatalx("adj_compare: unknown hello type"); } return (0); @@ -150,9 +152,10 @@ adj_del(struct adj *adj, uint32_t notif_status) } struct adj * -adj_find(struct hello_source *source) +adj_find(struct in_addr lsr_id, struct hello_source *source) { struct adj adj; + adj.lsr_id = lsr_id; adj.source = *source; return (RB_FIND(global_adj_head, &global.adj_tree, &adj)); } @@ -372,13 +375,17 @@ adj_to_ctl(struct adj *adj) case HELLO_LINK: memcpy(actl.ifname, adj->source.link.ia->iface->name, sizeof(actl.ifname)); + actl.src_addr = adj->source.link.src_addr; break; case HELLO_TARGETED: actl.src_addr = adj->source.target->addr; break; } actl.holdtime = adj->holdtime; + actl.holdtime_remaining = + thread_timer_remain_second(adj->inactivity_timer); actl.trans_addr = adj->trans_addr; + actl.ds_tlv = adj->ds_tlv; return (&actl); } diff --git a/ldpd/control.c b/ldpd/control.c index 0bfe0abc9d..5c530e1b70 100644 --- a/ldpd/control.c +++ b/ldpd/control.c @@ -242,6 +242,9 @@ control_dispatch_imsg(struct thread *thread) case IMSG_CTL_SHOW_DISCOVERY: ldpe_adj_ctl(c); break; + case IMSG_CTL_SHOW_DISCOVERY_DTL: + ldpe_adj_detail_ctl(c); + break; case IMSG_CTL_SHOW_LIB: case IMSG_CTL_SHOW_L2VPN_PW: case IMSG_CTL_SHOW_L2VPN_BINDING: diff --git a/ldpd/hello.c b/ldpd/hello.c index e7935899b7..dd67f68f70 100644 --- a/ldpd/hello.c +++ b/ldpd/hello.c @@ -291,7 +291,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, source.link.src_addr = *src; } - adj = adj_find(&source); + adj = adj_find(lsr_id, &source); nbr = nbr_find_ldpid(lsr_id.s_addr); /* check dual-stack tlv */ @@ -373,6 +373,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj); } } + adj->ds_tlv = ds_tlv; /* * If the hello adjacency's address-family doesn't match the local diff --git a/ldpd/init.c b/ldpd/init.c index bc3a69edc7..8b2abe85e5 100644 --- a/ldpd/init.c +++ b/ldpd/init.c @@ -261,6 +261,7 @@ send_capability(struct nbr *nbr, uint16_t capability, int enable) evbuf_enqueue(&nbr->tcp->wbuf, buf); nbr_fsm(nbr, NBR_EVT_PDU_SENT); + nbr->stats.capability_sent++; } int diff --git a/ldpd/interface.c b/ldpd/interface.c index 8fea91b878..b7f473d396 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -49,37 +49,48 @@ iface_compare(struct iface *a, struct iface *b) } struct iface * -if_new(struct kif *kif) +if_new(const char *name) { struct iface *iface; if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("if_new: calloc"); - strlcpy(iface->name, kif->ifname, sizeof(iface->name)); - LIST_INIT(&iface->addr_list); - if (kif->ifindex) - if_update_info(iface, kif); + strlcpy(iface->name, name, sizeof(iface->name)); /* ipv4 */ iface->ipv4.af = AF_INET; iface->ipv4.iface = iface; iface->ipv4.enabled = 0; - iface->ipv4.state = IF_STA_DOWN; - RB_INIT(&iface->ipv4.adj_tree); /* ipv6 */ iface->ipv6.af = AF_INET6; iface->ipv6.iface = iface; iface->ipv6.enabled = 0; - iface->ipv6.state = IF_STA_DOWN; - RB_INIT(&iface->ipv6.adj_tree); return (iface); } void -if_exit(struct iface *iface) +ldpe_if_init(struct iface *iface) +{ + log_debug("%s: interface %s", __func__, iface->name); + + LIST_INIT(&iface->addr_list); + + /* ipv4 */ + iface->ipv4.iface = iface; + iface->ipv4.state = IF_STA_DOWN; + RB_INIT(&iface->ipv4.adj_tree); + + /* ipv6 */ + iface->ipv6.iface = iface; + iface->ipv6.state = IF_STA_DOWN; + RB_INIT(&iface->ipv6.adj_tree); +} + +void +ldpe_if_exit(struct iface *iface) { struct if_addr *if_addr; @@ -206,7 +217,7 @@ if_addr_add(struct kaddr *ka) if (if_addr_lookup(&iface->addr_list, ka) == NULL) { if_addr = if_addr_new(ka); LIST_INSERT_HEAD(&iface->addr_list, if_addr, entry); - if_update(iface, if_addr->af); + ldp_if_update(iface, if_addr->af); } } } @@ -227,7 +238,7 @@ if_addr_del(struct kaddr *ka) if_addr = if_addr_lookup(&iface->addr_list, ka); if (if_addr) { LIST_REMOVE(if_addr, entry); - if_update(iface, if_addr->af); + ldp_if_update(iface, if_addr->af); free(if_addr); } } @@ -368,7 +379,7 @@ if_update_af(struct iface_af *ia, int link_ok) } void -if_update(struct iface *iface, int af) +ldp_if_update(struct iface *iface, int af) { int link_ok; @@ -386,7 +397,7 @@ if_update_all(int af) struct iface *iface; RB_FOREACH(iface, iface_head, &leconf->iface_tree) - if_update(iface, af); + ldp_if_update(iface, af); } uint16_t diff --git a/ldpd/keepalive.c b/ldpd/keepalive.c index f9a7d850fd..ba5f223316 100644 --- a/ldpd/keepalive.c +++ b/ldpd/keepalive.c @@ -40,6 +40,7 @@ send_keepalive(struct nbr *nbr) debug_kalive_send("keepalive: lsr-id %s", inet_ntoa(nbr->id)); evbuf_enqueue(&nbr->tcp->wbuf, buf); + nbr->stats.kalive_sent++; } int diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 3f4e21e685..92d865210a 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b) } struct l2vpn_if * -l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; @@ -125,33 +125,27 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_if_new: calloc"); lif->l2vpn = l2vpn; - strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); - lif->ifindex = kif->ifindex; - lif->flags = kif->flags; + strlcpy(lif->ifname, ifname, sizeof(lif->ifname)); return (lif); } struct l2vpn_if * -l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) -{ - struct l2vpn_if *lif; - - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) - if (lif->ifindex == ifindex) - return (lif); - - return (NULL); -} - -struct l2vpn_if * -l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname) +l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if lif; strlcpy(lif.ifname, ifname, sizeof(lif.ifname)); return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif)); } +void +l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif) +{ + lif->ifindex = kif->ifindex; + lif->flags = kif->flags; + memcpy(lif->mac, kif->mac, sizeof(lif->mac)); +} + void l2vpn_if_update(struct l2vpn_if *lif) { @@ -186,7 +180,7 @@ l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b) } struct l2vpn_pw * -l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; @@ -194,29 +188,13 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_pw_new: calloc"); pw->l2vpn = l2vpn; - strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); - pw->ifindex = kif->ifindex; + strlcpy(pw->ifname, ifname, sizeof(pw->ifname)); return (pw); } struct l2vpn_pw * -l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) -{ - struct l2vpn_pw *pw; - - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) - if (pw->ifindex == ifindex) - return (pw); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) - if (pw->ifindex == ifindex) - return (pw); - - return (NULL); -} - -struct l2vpn_pw * -l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) +l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; struct l2vpn_pw s; @@ -228,6 +206,30 @@ l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } +struct l2vpn_pw * +l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname) +{ + struct l2vpn_pw s; + + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s)); +} + +struct l2vpn_pw * +l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) +{ + struct l2vpn_pw s; + + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); +} + +void +l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif) +{ + pw->ifindex = kif->ifindex; +} + void l2vpn_pw_init(struct l2vpn_pw *pw) { @@ -282,9 +284,6 @@ l2vpn_pw_reset(struct l2vpn_pw *pw) int l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) { - struct fec fec; - struct fec_node *fn; - /* check for a remote label */ if (fnh->remote_label == NO_LABEL) return (0); @@ -298,34 +297,6 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) pw->remote_status != PW_FORWARDING) return (0); - /* check for a working lsp to the nexthop */ - memset(&fec, 0, sizeof(fec)); - switch (pw->af) { - case AF_INET: - fec.type = FEC_TYPE_IPV4; - fec.u.ipv4.prefix = pw->addr.v4; - fec.u.ipv4.prefixlen = 32; - break; - case AF_INET6: - fec.type = FEC_TYPE_IPV6; - fec.u.ipv6.prefix = pw->addr.v6; - fec.u.ipv6.prefixlen = 128; - break; - default: - fatalx("l2vpn_pw_ok: unknown af"); - } - - fn = (struct fec_node *)fec_find(&ft, &fec); - if (fn == NULL || fn->local_label == NO_LABEL) - return (0); - /* - * Need to ensure that there's a label binding for all nexthops. - * Otherwise, ECMP for this route could render the pseudowire unusable. - */ - LIST_FOREACH(fnh, &fn->nexthops, entry) - if (fnh->remote_label == NO_LABEL) - return (0); - return (1); } @@ -503,37 +474,6 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm) } } -void -l2vpn_sync_pws(int af, union ldpd_addr *addr) -{ - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; - struct fec fec; - struct fec_node *fn; - struct fec_nh *fnh; - - RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) - continue; - - l2vpn_pw_fec(pw, &fec); - fn = (struct fec_node *)fec_find(&ft, &fec); - if (fn == NULL) - continue; - fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *) - &pw->lsr_id, 0, 0); - if (fnh == NULL) - continue; - - if (l2vpn_pw_ok(pw, fnh)) - lde_send_change_klabel(fn, fnh); - else - lde_send_delete_klabel(fn, fnh); - } - } -} - void l2vpn_pw_ctl(pid_t pid) { diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c index e8ce7fbdf5..f53bc8333d 100644 --- a/ldpd/labelmapping.c +++ b/ldpd/labelmapping.c @@ -26,13 +26,13 @@ #include "mpls.h" -static void enqueue_pdu(struct nbr *, struct ibuf *, uint16_t); +static void enqueue_pdu(struct nbr *, uint16_t, struct ibuf *, uint16_t); static int gen_label_tlv(struct ibuf *, uint32_t); static int gen_reqid_tlv(struct ibuf *, uint32_t); static void log_msg_mapping(int, uint16_t, struct nbr *, struct map *); static void -enqueue_pdu(struct nbr *nbr, struct ibuf *buf, uint16_t size) +enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size) { struct ldp_hdr *ldp_hdr; @@ -81,7 +81,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) /* maximum pdu length exceeded, we need a new ldp pdu */ if (size + msg_size > nbr->max_pdu_len) { - enqueue_pdu(nbr, buf, size); + enqueue_pdu(nbr, type, buf, size); first = 1; continue; } @@ -108,11 +108,32 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) log_msg_mapping(1, type, nbr, &me->map); + /* no errors - update per neighbor message counters */ + switch (type) { + case MSG_TYPE_LABELMAPPING: + nbr->stats.labelmap_sent++; + break; + case MSG_TYPE_LABELREQUEST: + nbr->stats.labelreq_sent++; + break; + case MSG_TYPE_LABELWITHDRAW: + nbr->stats.labelwdraw_sent++; + break; + case MSG_TYPE_LABELRELEASE: + nbr->stats.labelrel_sent++; + break; + case MSG_TYPE_LABELABORTREQ: + nbr->stats.labelabreq_sent++; + break; + default: + break; + } + TAILQ_REMOVE(mh, me, entry); free(me); } - enqueue_pdu(nbr, buf, size); + enqueue_pdu(nbr, type, buf, size); nbr_fsm(nbr, NBR_EVT_PDU_SENT); } diff --git a/ldpd/lde.c b/ldpd/lde.c index 08339c720a..d8a2924b31 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -33,6 +33,10 @@ #include "privs.h" #include "sigevent.h" #include "mpls.h" +#include +#include "zclient.h" +#include "stream.h" +#include "network.h" static void lde_shutdown(void); static int lde_dispatch_imsg(struct thread *); @@ -50,6 +54,11 @@ static void lde_map_free(void *); static int lde_address_add(struct lde_nbr *, struct lde_addr *); static int lde_address_del(struct lde_nbr *, struct lde_addr *); static void lde_address_list_free(struct lde_nbr *); +static void zclient_sync_init (u_short instance); +static void lde_label_list_init(void); +static int lde_get_label_chunk (void); +static void on_get_label_chunk_response(uint32_t start, uint32_t end); +static uint32_t lde_get_next_label(void); RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare) @@ -83,6 +92,10 @@ static struct zebra_privs_t lde_privs = .cap_num_i = 0 }; +/* List of chunks of labels externally assigned by Zebra */ +struct list *label_chunk_list; +struct listnode *current_label_chunk; + /* SIGINT / SIGTERM handler. */ static void sigint(void) @@ -92,6 +105,10 @@ sigint(void) static struct quagga_signal_t lde_signals[] = { + { + .signal = SIGHUP, + /* ignore */ + }, { .signal = SIGINT, .handler = &sigint, @@ -102,9 +119,38 @@ static struct quagga_signal_t lde_signals[] = }, }; +static void +lde_sleep (void) +{ + sleep(1); + if (lde_signals[0].caught || lde_signals[1].caught) + lde_shutdown(); +} +struct zclient *zclient_sync = NULL; +static void +zclient_sync_init(u_short instance) +{ + /* Initialize special zclient for synchronous message exchanges. */ + log_debug("Initializing synchronous zclient for label manager"); + zclient_sync = zclient_new(master); + zclient_sync->sock = -1; + zclient_sync->redist_default = ZEBRA_ROUTE_LDP; + zclient_sync->instance = instance; + while (zclient_socket_connect (zclient_sync) < 0) { + fprintf(stderr, "Error connecting synchronous zclient!\n"); + lde_sleep(); + } + + /* Connect to label manager */ + while (lm_label_manager_connect (zclient_sync) != 0) { + fprintf(stderr, "Error connecting to label manager!\n"); + lde_sleep(); + } +} + /* label decision engine */ void -lde(const char *user, const char *group) +lde(const char *user, const char *group, u_short instance) { struct thread thread; struct timeval now; @@ -124,7 +170,7 @@ lde(const char *user, const char *group) zprivs_init(&lde_privs); #ifdef HAVE_PLEDGE - if (pledge("stdio recvfd", NULL) == -1) + if (pledge("stdio recvfd unix", NULL) == -1) fatal("pledge"); #endif @@ -152,6 +198,10 @@ lde(const char *user, const char *group) gettimeofday(&now, NULL); global.uptime = now.tv_sec; + /* Init synchronous zclient and label list */ + zclient_sync_init(instance); + lde_label_list_init(); + /* Fetch next active thread. */ while (thread_fetch(master, &thread)) thread_call(&thread); @@ -389,13 +439,14 @@ static int lde_dispatch_parent(struct thread *thread) { static struct ldpd_conf *nconf; - struct iface *niface; + struct iface *iface, *niface; struct tnbr *ntnbr; struct nbr_params *nnbrp; - static struct l2vpn *nl2vpn; - struct l2vpn_if *nlif; - struct l2vpn_pw *npw; + static struct l2vpn *l2vpn, *nl2vpn; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; + struct kif *kif; struct kroute *kr; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -418,6 +469,31 @@ lde_dispatch_parent(struct thread *thread) break; switch (imsg.hdr.type) { + case IMSG_IFSTATUS: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct kif)) + fatalx("IFSTATUS imsg with wrong len"); + kif = imsg.data; + + iface = if_lookup_name(ldeconf, kif->ifname); + if (iface) { + if_update_info(iface, kif); + break; + } + + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { + lif = l2vpn_if_find(l2vpn, kif->ifname); + if (lif) { + l2vpn_if_update_info(lif, kif); + break; + } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } + } + break; case IMSG_NETWORK_ADD: case IMSG_NETWORK_UPDATE: if (imsg.hdr.len != IMSG_HEADER_SIZE + @@ -490,12 +566,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(niface, imsg.data, sizeof(struct iface)); - LIST_INIT(&niface->addr_list); - RB_INIT(&niface->ipv4.adj_tree); - RB_INIT(&niface->ipv6.adj_tree); - niface->ipv4.iface = niface; - niface->ipv6.iface = niface; - RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: @@ -528,7 +598,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); - nlif->l2vpn = nl2vpn; RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: @@ -536,7 +605,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: @@ -544,11 +612,11 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(ldeconf, nconf); + ldp_clear_config(nconf); nconf = NULL; break; case IMSG_DEBUG_UPDATE: @@ -587,7 +655,6 @@ lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen) uint32_t lde_update_label(struct fec_node *fn) { - static uint32_t label = MPLS_LABEL_RESERVED_MAX; struct fec_nh *fnh; int connected = 0; @@ -652,12 +719,7 @@ lde_update_label(struct fec_node *fn) fn->local_label > MPLS_LABEL_RESERVED_MAX) return (fn->local_label); - /* - * TODO: request label to zebra or define a range of labels for ldpd. - */ - - label++; - return (label); + return lde_get_next_label (); } void @@ -681,10 +743,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -699,10 +757,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: if (fn->local_label == NO_LABEL || @@ -748,10 +802,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -766,10 +816,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: pw = (struct l2vpn_pw *) fn->data; @@ -1533,3 +1579,102 @@ lde_address_list_free(struct lde_nbr *ln) free(lde_addr); } } + +static void +lde_del_label_chunk(void *val) +{ + free(val); +} +static int +lde_get_label_chunk(void) +{ + int ret; + uint32_t start, end; + + log_debug("Getting label chunk"); + ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end); + if (ret < 0) + { + log_warnx("Error getting label chunk!"); + close(zclient_sync->sock); + zclient_sync->sock = -1; + return -1; + } + + on_get_label_chunk_response(start, end); + + return 0; +} +static void +lde_label_list_init(void) +{ + label_chunk_list = list_new(); + label_chunk_list->del = lde_del_label_chunk; + + /* get first chunk */ + while (lde_get_label_chunk () != 0) { + fprintf(stderr, "Error getting first label chunk!\n"); + lde_sleep(); + } +} + +static void +on_get_label_chunk_response(uint32_t start, uint32_t end) +{ + struct label_chunk *new_label_chunk; + + log_debug("Label Chunk assign: %u - %u", start, end); + + new_label_chunk = calloc(1, sizeof(struct label_chunk)); + if (!new_label_chunk) { + log_warn("Error trying to allocate label chunk %u - %u", start, end); + return; + } + + new_label_chunk->start = start; + new_label_chunk->end = end; + new_label_chunk->used_mask = 0; + + listnode_add(label_chunk_list, (void *)new_label_chunk); + + /* let's update current if needed */ + if (!current_label_chunk) + current_label_chunk = listtail(label_chunk_list); +} + +static uint32_t +lde_get_next_label(void) +{ + struct label_chunk *label_chunk; + uint32_t i, pos, size; + uint32_t label = NO_LABEL; + + while (current_label_chunk) { + label_chunk = listgetdata(current_label_chunk); + if (!label_chunk) + goto end; + + /* try to get next free label in currently used label chunk */ + size = label_chunk->end - label_chunk->start + 1; + for (i = 0, pos = 1; i < size; i++, pos <<= 1) { + if (!(pos & label_chunk->used_mask)) { + label_chunk->used_mask |= pos; + label = label_chunk->start + i; + goto end; + } + } + current_label_chunk = listnextnode(current_label_chunk); + } + +end: + /* we moved till the last chunk, or were not able to find a label, + so let's ask for another one */ + if (!current_label_chunk || current_label_chunk == listtail(label_chunk_list) + || label == NO_LABEL) { + if (lde_get_label_chunk() != 0) + log_warn("%s: Error getting label chunk!", __func__); + + } + + return label; +} diff --git a/ldpd/lde.h b/ldpd/lde.h index b5bcb42c8b..57791cd1b0 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -124,6 +124,13 @@ struct fec_node { void *data; /* fec specific data */ }; +#define CHUNK_SIZE 64 +struct label_chunk { + uint32_t start; + uint32_t end; + uint64_t used_mask; +}; + #define LDE_GC_INTERVAL 300 extern struct ldpd_conf *ldeconf; @@ -132,7 +139,7 @@ extern struct nbr_tree lde_nbrs; extern struct thread *gc_timer; /* lde.c */ -void lde(const char *, const char *); +void lde(const char *, const char *, u_short instance); int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t); int lde_acl_check(char *, int, union ldpd_addr *, uint8_t); @@ -205,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *); void l2vpn_del(struct l2vpn *); void l2vpn_init(struct l2vpn *); void l2vpn_exit(struct l2vpn *); -struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *); -struct l2vpn_if *l2vpn_if_find(struct l2vpn *, unsigned int); -struct l2vpn_if *l2vpn_if_find_name(struct l2vpn *, const char *); +struct l2vpn_if *l2vpn_if_new(struct l2vpn *, const char *); +struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); +void l2vpn_if_update_info(struct l2vpn_if *, struct kif *); void l2vpn_if_update(struct l2vpn_if *); -struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); -struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, unsigned int); -struct l2vpn_pw *l2vpn_pw_find_name(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *); +void l2vpn_pw_update_info(struct l2vpn_pw *, struct kif *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); @@ -224,7 +233,6 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t, void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *); void l2vpn_recv_pw_status_wcard(struct lde_nbr *, struct notify_msg *); -void l2vpn_sync_pws(int, union ldpd_addr *); void l2vpn_pw_ctl(pid_t); void l2vpn_binding_ctl(pid_t); diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 4444a1e1ac..db2682a173 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -162,7 +162,7 @@ rt_dump(pid_t pid) RB_EMPTY(&fn->downstream)) continue; - rtctl.first = 1; + memset(&rtctl, 0, sizeof(rtctl)); switch (fn->fec.type) { case FEC_TYPE_IPV4: rtctl.af = AF_INET; @@ -179,23 +179,30 @@ rt_dump(pid_t pid) } rtctl.local_label = fn->local_label; - RB_FOREACH(me, lde_map_head, &fn->downstream) { - rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop); - rtctl.nexthop = me->nexthop->id; - rtctl.remote_label = me->map.label; - - lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid, - &rtctl, sizeof(rtctl)); - rtctl.first = 0; - } if (RB_EMPTY(&fn->downstream)) { rtctl.in_use = 0; rtctl.nexthop.s_addr = INADDR_ANY; rtctl.remote_label = NO_LABEL; + rtctl.no_downstream = 1; + } + lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN, 0, pid, &rtctl, + sizeof(rtctl)); - lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid, + RB_FOREACH(me, lde_map_head, &fn->upstream) { + rtctl.nexthop = me->nexthop->id; + lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT, 0, pid, &rtctl, sizeof(rtctl)); } + + RB_FOREACH(me, lde_map_head, &fn->downstream) { + rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop); + rtctl.nexthop = me->nexthop->id; + rtctl.remote_label = me->map.label; + lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD, 0, pid, + &rtctl, sizeof(rtctl)); + } + lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END, 0, pid, &rtctl, + sizeof(rtctl)); } } diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index b0dc291434..8510a394ec 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -71,6 +71,7 @@ int ldp_vty_l2vpn_pw_pwstatus(struct vty *, struct vty_arg *[]); int ldp_vty_show_binding(struct vty *, struct vty_arg *[]); int ldp_vty_show_discovery(struct vty *, struct vty_arg *[]); int ldp_vty_show_interface(struct vty *, struct vty_arg *[]); +int ldp_vty_show_capabilities(struct vty *, struct vty_arg *[]); int ldp_vty_show_neighbor(struct vty *, struct vty_arg *[]); int ldp_vty_show_atom_binding(struct vty *, struct vty_arg *[]); int ldp_vty_show_atom_vc(struct vty *, struct vty_arg *[]); @@ -79,6 +80,5 @@ int ldp_vty_debug(struct vty *, struct vty_arg *[]); int ldp_vty_show_debugging(struct vty *, struct vty_arg *[]); void ldp_vty_init(void); -void ldp_vty_if_init(void); #endif /* _LDP_VTY_H_ */ diff --git a/ldpd/ldp_vty.xml b/ldpd/ldp_vty.xml index 966b634c27..cd5c92c7b1 100644 --- a/ldpd/ldp_vty.xml +++ b/ldpd/ldp_vty.xml @@ -333,11 +333,17 @@ - - + +