conftest.err
aclocal.m4
Makefile.in
-zebra-[0-9.][0-9.][0-9.]*.tar.gz
-quagga-[0-9.][0-9.][0-9.]*.tar.gz
-quagga-[0-9.][0-9.][0-9.]*.tar.gz.asc
+*.tar.gz
+*.tar.gz.asc
.nfs*
libtool
.arch-inventory
As such debugs MUST be guarded in such a way that they can be turned off.
This PROJECT has the ability to turn on/off debugs from the CLI and it is
expected that the developer will use this convention to allow control
-of their debugs.
\ No newline at end of file
+of their debugs.
+
+### CLI-Changes
+
+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
+++ /dev/null
---------------------------------------------------------------------------
-Building and Installing Quagga from releases or snapshots:
-
-The 'INSTALL' file contains generic instructions on how to use 'configure'
-scripts.
-
-Quagga requires a C compiler (and associated header files and
-libraries) supporting the C99 standard.
-
-Quagga requires a reasonable make. It is considered a bug if quagga
-does not compile with the system make on recent FreeBSD, NetBSD or
-OpenBSD, and a very serious bug if it does not compile with GNU make.
-
-Quagga expects a POSIX.2 compliant system, more or less. Clean
-workarounds for POSIX non-compliance are welcome.
-
-It is considered a bug if Quagga fails to build and run on any of the
-following systems (where .x indicates the most recent release), or
-such systems "-current" versions. Or, it might be that this list is
-out of date and will be updated. (Note that considering it a bug is
-not a guarantee of support, merely "we agree that it is broken".)
-
- Dragonfly ?
- FreeBSD (stable branches currently supported, plus perhaps one)
- FreeBSD-current
- Linux [kernel/distribution information needed]
- NetBSD 4.x
- NetBSD 5.x
- NetBSD 6.x
- NetBSD-current
- OpenBSD ? [info needed on what should work]
- Solaris (modern/supported versions, including OpenSolaris forks)
-
-On BSD systems, installing libexecinfo is strongly recommended in order
-to get backtrace support.
-
-For further Quagga specific information on 'configure' and build-time
-configuration of the software, please read the Quagga info
-documentation, (doc/quagga.info). To read the info page included with
-the Quagga sources without first installing Quagga:
-
- cd doc
- # one of the following, depending on your info viewer preferences
- info quagga.info
- pinfo -r quagga.info
- emacs -eval '(info "quagga.info")'
-
-The Quagga website (http://www.quagga.net) currently has the info
-files available in various formats.
-
---------------------------------------------------------------------------
-Building Quagga from git checkouts:
-
-In order to build from git, you will need recent versions of several GNU
-tools, particularly autoconf, automake, libtool, GNU awk and texinfo. Note
-that the CVS snapshots on the Quagga website should not require these tools;
-everything is already setup ready to run 'configure'. If you have trouble
-building from CVS checkout it is recommended that you try a CVS snapshot
-instead.
-
-We declare that the following versions should work for building from
-CVS checkouts. Earlier versions may work, but failure to do so is not
-a bug. Required versions can be moved earlier if no problems, or
-later after a judgement that a system without a higher version is
-deficient is made.
-
- [TODO: this list is out of date as of 2013-07]
- automake: 1.9.6 (released 2005-07-10)
- autoconf: 2.59 (2.60 on 2006-06-26 is too recent to require)
- libtool: 1.5.22 (released 2005-12-18)
- texinfo: 4.7 (released 2004-04-10; 4.8 is not yet common)
-
-For running tests, one also needs:
-
- DejaGnu:
-
-[TODO: texinfo 4.6 is now ancient and this should be revisited/fixed]
-Because some systems provide texinfo 4.6 (4.7 is new), quagga.info is
-checked in so that texinfo will generally not be invoked. When
-texinfo 4.7 is widespread, quagga.info will be removed from CVS and
-texinfo will become required again. (4.7 has figure support, needed
-for the route server docs, which is why 4.6 doesn't work.)
-
-In order to create PostScript or PDF versions of the Texinfo documentation,
-you will need the convert utility, from the ImageMagick toolset installed,
-and epstopdf from the TeTeX suite.
-
-To create the required autotools files (Makefile.in, configure, etc.),
-run "./bootstrap.sh". After this you may run configure as for a
-snapshot or release.
-
-Please refer to "Building and Installing Quagga" above for further
-instructions.
-
---------------------------------------------------------------------------
-Notes on required versions:
-
-The general goal is to use a modern baseline of tools, while not
-imposing pain on those tracking supported (or almost supported) stable
-distributions. The notes below explain what versions are present in
-various environments.
-
-NetBSD 4 provides texinfo 4.7.
-NetBSD 5 and 6 provides texinfo 4.8
-
-Fedora Core ? provides autoconf 2.59.
-
-OpenBSD 3.6 provides texinfo 4.2.
-OpenBSD [3.6] ports provides automake 1.4-p6 autoconf 2.5.9 libtool 1.5.8
-
---------------------------------------------------------------------------
SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \
@BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
- @ISISD@ @PIMD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
+ @ISISD@ @PIMD@ @WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
redhat @SOLARIS@ tests tools cumulus
DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
- isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
+ isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
solaris pimd @LIBRFP@ @RFPTEST@ tools cumulus
-EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS INSTALL.quagga.txt \
+EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \
update-autotools \
vtysh/Makefile.in vtysh/Makefile.am \
tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
Currently Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1,
RIPv2, RIPng, PIM-SSM and LDP as well as very early support for IS-IS.
-
-See the file INSTALL.quagga.txt for building and installation instructions.
-
+
See the file REPORTING-BUGS to report bugs.
-
+
Quagga is free software. See the file COPYING for copying conditions.
#!/bin/sh
-# $QuaggaId: Format:%an, %ai, %h$ $
-
# This file is helpful for building quagga from cvs on NetBSD, and
# probably on any system using pkgsrc.
# One should have readline installed already (pkgsrc/devel/readline).
ospfapi 2607/tcp
isisd 2608/tcp
pimd 2611/tcp
+ldpd 2612/tcp
cluster_hash = NULL;
}
+static struct hash *encap_hash = NULL;
+#if ENABLE_BGP_VNC
+static struct hash *vnc_hash = NULL;
+#endif
+
struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
{
struct bgp_attr_encap_subtlv *p;
struct bgp_attr_encap_subtlv *q;
- if (!h1 && !h2)
- return 1;
- if (h1 && !h2)
- return 0;
- if (!h1 && h2)
- return 0;
if (h1 == h2)
return 1;
+ if (h1 == NULL || h2 == NULL)
+ return 0;
for (p = h1; p; p = p->next) {
for (q = h2; q; q = q->next) {
return 1;
}
+static void *
+encap_hash_alloc (void *p)
+{
+ /* Encap structure is already allocated. */
+ return p;
+}
+
+typedef enum
+{
+ ENCAP_SUBTLV_TYPE,
+#if ENABLE_BGP_VNC
+ VNC_SUBTLV_TYPE
+#endif
+} encap_subtlv_type;
+
+static struct bgp_attr_encap_subtlv *
+encap_intern (struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
+{
+ struct bgp_attr_encap_subtlv *find;
+ struct hash *hash = encap_hash;
+#if ENABLE_BGP_VNC
+ if (type == VNC_SUBTLV_TYPE)
+ hash = vnc_hash;
+#endif
+
+ find = hash_get (hash, encap, encap_hash_alloc);
+ if (find != encap)
+ encap_free (encap);
+ find->refcnt++;
+
+ return find;
+}
+
+static void
+encap_unintern (struct bgp_attr_encap_subtlv **encapp, encap_subtlv_type type)
+{
+ struct bgp_attr_encap_subtlv *encap = *encapp;
+ if (encap->refcnt)
+ encap->refcnt--;
+
+ if (encap->refcnt == 0)
+ {
+ struct hash *hash = encap_hash;
+#if ENABLE_BGP_VNC
+ if (type == VNC_SUBTLV_TYPE)
+ hash = vnc_hash;
+#endif
+ hash_release (hash, encap);
+ encap_free (encap);
+ *encapp = NULL;
+ }
+}
+
+static unsigned int
+encap_hash_key_make (void *p)
+{
+ const struct bgp_attr_encap_subtlv * encap = p;
+
+ return jhash(encap->value, encap->length, 0);
+}
+
+static int
+encap_hash_cmp (const void *p1, const void *p2)
+{
+ return encap_same((struct bgp_attr_encap_subtlv *)p1,
+ (struct bgp_attr_encap_subtlv *)p2);
+}
+
+static void
+encap_init (void)
+{
+ encap_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
+#if ENABLE_BGP_VNC
+ vnc_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
+#endif
+}
+
+static void
+encap_finish (void)
+{
+ hash_clean (encap_hash, (void (*)(void *))encap_free);
+ hash_free (encap_hash);
+ encap_hash = NULL;
+#if ENABLE_BGP_VNC
+ hash_clean (vnc_hash, (void (*)(void *))encap_free);
+ hash_free (vnc_hash);
+ vnc_hash = NULL;
+#endif
+}
+
/* Unknown transit attribute. */
static struct hash *transit_hash;
{
if (attr->extra)
{
- if (attr->extra->encap_subtlvs) {
- encap_free(attr->extra->encap_subtlvs);
- attr->extra->encap_subtlvs = NULL;
- }
-#if ENABLE_BGP_VNC
- if (attr->extra->vnc_subtlvs) {
- encap_free(attr->extra->vnc_subtlvs);
- attr->extra->vnc_subtlvs = NULL;
- }
-#endif
XFREE (MTYPE_ATTR_EXTRA, attr->extra);
attr->extra = NULL;
}
memset(new->extra, 0, sizeof(struct attr_extra));
if (orig->extra) {
*new->extra = *orig->extra;
- if (orig->extra->encap_subtlvs) {
- new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
- }
-#if ENABLE_BGP_VNC
- if (orig->extra->vnc_subtlvs) {
- new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
- }
-#endif
}
}
else if (orig->extra)
{
new->extra = bgp_attr_extra_new();
*new->extra = *orig->extra;
- if (orig->extra->encap_subtlvs) {
- new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
- }
-#if ENABLE_BGP_VNC
- if (orig->extra->vnc_subtlvs) {
- new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
- }
-#endif
}
}
new->extra->cluster = cluster_dup(orig->extra->cluster);
if (orig->extra->transit)
new->extra->transit = transit_dup(orig->extra->transit);
+ if (orig->extra->encap_subtlvs)
+ new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
+#if ENABLE_BGP_VNC
+ if (orig->extra->vnc_subtlvs)
+ new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
+#endif
}
}
cluster_free(attr->extra->cluster);
if (attr->extra->transit)
transit_free(attr->extra->transit);
+ if (attr->extra->encap_subtlvs)
+ encap_free(attr->extra->encap_subtlvs);
+#if ENABLE_BGP_VNC
+ if (attr->extra->vnc_subtlvs)
+ encap_free(attr->extra->vnc_subtlvs);
+#endif
}
}
MIX(cluster_hash_key_make (extra->cluster));
if (extra->transit)
MIX(transit_hash_key_make (extra->transit));
-
+ if (extra->encap_subtlvs)
+ MIX(encap_hash_key_make (extra->encap_subtlvs));
+#if ENABLE_BGP_VNC
+ if (extra->vnc_subtlvs)
+ MIX(encap_hash_key_make (extra->vnc_subtlvs));
+#endif
#ifdef HAVE_IPV6
MIX(extra->mp_nexthop_len);
key = jhash(extra->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
{
attr->extra = bgp_attr_extra_new ();
*attr->extra = *val->extra;
-
- if (attr->extra->encap_subtlvs) {
- attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
+ if (val->extra->encap_subtlvs) {
+ val->extra->encap_subtlvs = NULL;
}
#if ENABLE_BGP_VNC
- if (attr->extra->vnc_subtlvs) {
- attr->extra->vnc_subtlvs = encap_tlv_dup(attr->extra->vnc_subtlvs);
+ if (val->extra->vnc_subtlvs) {
+ val->extra->vnc_subtlvs = NULL;
}
#endif
}
else
attre->transit->refcnt++;
}
+ if (attre->encap_subtlvs)
+ {
+ if (! attre->encap_subtlvs->refcnt)
+ attre->encap_subtlvs = encap_intern (attre->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+ else
+ attre->encap_subtlvs->refcnt++;
+ }
+#if ENABLE_BGP_VNC
+ if (attre->vnc_subtlvs)
+ {
+ if (! attre->vnc_subtlvs->refcnt)
+ attre->vnc_subtlvs = encap_intern (attre->vnc_subtlvs, VNC_SUBTLV_TYPE);
+ else
+ attre->vnc_subtlvs->refcnt++;
+ }
+#endif
}
find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
find->refcnt++;
-
+
return find;
}
if (attre->transit)
attre->transit->refcnt++;
+
+ if (attre->encap_subtlvs)
+ attre->encap_subtlvs->refcnt++;
+
+#if ENABLE_BGP_VNC
+ if (attre->vnc_subtlvs)
+ attre->vnc_subtlvs->refcnt++;
+#endif
}
attr->refcnt++;
return attr;
if (attr->extra->transit)
transit_unintern (attr->extra->transit);
+
+ if (attr->extra->encap_subtlvs)
+ encap_unintern (&attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+
+#if ENABLE_BGP_VNC
+ if (attr->extra->vnc_subtlvs)
+ encap_unintern (&attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
+#endif
}
}
transit_free (attre->transit);
attre->transit = NULL;
}
- encap_free(attre->encap_subtlvs);
- attre->encap_subtlvs = NULL;
+ if (attre->encap_subtlvs && ! attre->encap_subtlvs->refcnt)
+ {
+ encap_free(attre->encap_subtlvs);
+ attre->encap_subtlvs = NULL;
+ }
#if ENABLE_BGP_VNC
- encap_free(attre->vnc_subtlvs);
- attre->vnc_subtlvs = NULL;
+ if (attre->vnc_subtlvs && ! attre->vnc_subtlvs->refcnt)
+ {
+ encap_free(attre->vnc_subtlvs);
+ attre->vnc_subtlvs = NULL;
+ }
#endif
}
}
if (ret != BGP_ATTR_PARSE_PROCEED)
return ret;
}
-
- /* Finally intern unknown attribute. */
- if (attr->extra && attr->extra->transit)
- attr->extra->transit = transit_intern (attr->extra->transit);
+ if (attr->extra)
+ {
+ /* Finally intern unknown attribute. */
+ if (attr->extra->transit)
+ attr->extra->transit = transit_intern (attr->extra->transit);
+ if (attr->extra->encap_subtlvs)
+ attr->extra->encap_subtlvs = encap_intern (attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+#if ENABLE_BGP_VNC
+ if (attr->extra->vnc_subtlvs)
+ attr->extra->vnc_subtlvs = encap_intern (attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
+#endif
+ }
return BGP_ATTR_PARSE_PROCEED;
}
ecommunity_init ();
cluster_init ();
transit_init ();
+ encap_init ();
}
void
ecommunity_finish ();
cluster_finish ();
transit_finish ();
+ encap_finish ();
}
/* Make attribute packet. */
struct bgp_attr_encap_subtlv {
struct bgp_attr_encap_subtlv *next; /* for chaining */
+ /* Reference count of this attribute. */
+ unsigned long refcnt;
uint16_t type;
uint16_t length;
uint8_t value[1]; /* will be extended */
struct zebra_privs_t bgpd_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
ecom = NULL;
}
+static void
+ecommunity_hash_free (struct ecommunity *ecom)
+{
+ ecommunity_free(&ecom);
+}
+
+
/* Add a new Extended Communities value to Extended Communities
Attribute structure. When the value is already exists in the
structure, we don't add the value. Newly added value is sorted by
void
ecommunity_finish (void)
{
+ hash_clean (ecomhash, (void (*)(void *))ecommunity_hash_free);
hash_free (ecomhash);
ecomhash = NULL;
}
vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
}
else
- vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
+ vty_out (vty, "%sDisplayed %ld routes and %ld total paths%s",
VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
return CMD_SUCCESS;
/* NSF delete stale route */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
/* NSF delete stale route */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
peer->nsf[afi][safi] = 0;
}
/* graceful restart */
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
{
if (peer->afc_nego[afi][safi]
&& CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
struct zebra_privs_t bgpd_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
/* Print banner. */
- zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
+ zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", FRR_COPYRIGHT,
vty_port,
(bm->address ? bm->address : "<all>"),
bm->port);
-/* $QuaggaId: Format:%an, %ai, %h$ $
- *
+/*
* BGP Multipath
* Copyright (C) 2010 Google Inc.
*
-/* $QuaggaId: Format:%an, %ai, %h$ $
- *
+/*
* BGP Multipath
* Copyright (C) 2010 Google Inc.
*
if (output_count == 0)
vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
else
- vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
+ vty_out (vty, "%sDisplayed %ld routes and %ld total paths%s",
VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
}
if (peer->afc[afi][safi])
{
stream_putw (s, afi);
- stream_putc (s, safi);
- stream_putc (s, 0); //Forwarding is not retained as of now.
+ stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
+ if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD))
+ stream_putc (s, RESTART_F_BIT);
+ else
+ stream_putc (s, 0);
}
}
stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
stream_putc (s, 3);
stream_putw (s, afi);
- stream_putc (s, safi);
+ stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
}
bgp_packet_set_size (s);
if (!(PAF_SUBGRP(paf))->t_coalesce &&
peer->afc_nego[afi][safi] && peer->synctime
&& ! CHECK_FLAG (peer->af_sflags[afi][safi],
- PEER_STATUS_EOR_SEND)
- && safi != SAFI_MPLS_VPN)
+ PEER_STATUS_EOR_SEND))
{
SET_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND);
{
if (peer_sort (new->peer) == BGP_PEER_IBGP
&& peer_sort (exist->peer) == BGP_PEER_IBGP
- && CHECK_FLAG (mpath_cfg->ibgp_flags,
- BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))
+ && (mpath_cfg == NULL ||
+ CHECK_FLAG (mpath_cfg->ibgp_flags,
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN)))
{
newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
afi_t afi, safi_t safi)
{
int paths_eq;
- struct bgp_maxpaths_cfg mpath_cfg;
int ret;
- ret = bgp_info_cmp (bgp, new, exist, &paths_eq, &mpath_cfg, 0, __func__);
+ ret = bgp_info_cmp (bgp, new, exist, &paths_eq, NULL, 0, __func__);
if (paths_eq)
ret = 0;
PEER_STATUS_ORF_WAIT_REFRESH))
return 0;
+ memset(&extra, 0, sizeof(struct attr_extra));
/* It's initialized in bgp_announce_check() */
attr.extra = &extra;
struct bgp_info *ri;
struct bgp_table *table;
- table = peer->bgp->rib[afi][safi];
+ if ( safi == SAFI_MPLS_VPN)
+ {
+ for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn))
+ {
+ struct bgp_node *rm;
+ struct bgp_info *ri;
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ /* look for neighbor in tables */
+ if ((table = rn->info) != NULL)
+ {
+ for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+ for (ri = rm->info; ri; ri = ri->next)
+ if (ri->peer == peer)
+ {
+ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
+ bgp_rib_remove (rm, ri, peer, afi, safi);
+ break;
+ }
+ }
+ }
+ }
+ else
{
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer)
- {
- if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- bgp_rib_remove (rn, ri, peer, afi, safi);
- break;
- }
+ for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn))
+ for (ri = rn->info; ri; ri = ri->next)
+ if (ri->peer == peer)
+ {
+ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
+ bgp_rib_remove (rn, ri, peer, afi, safi);
+ break;
+ }
}
}
return 0;
}
-
DEFUN (bgp_table_map,
bgp_table_map_cmd,
"table-map WORD",
vty_out (vty, "No BGP prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
}
else
- vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
+ vty_out (vty, "%sDisplayed %ld routes and %ld total paths%s",
VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
}
/* BGP route print out function. */
DEFUN (show_ip_bgp_ipv4,
show_ip_bgp_ipv4_cmd,
- "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>]\
+ "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]]\
[<\
cidr-only\
|dampening <flap-statistics|dampened-paths|parameters>\
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
- "Address Family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family modifier\n"
"Display only routes with non-natural netmasks\n"
"Display detailed information about dampening\n"
{
afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
- safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
}
else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx))
{
DEFUN (show_ip_bgp_route,
show_ip_bgp_route_cmd,
- "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>]"
+ "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]]"
"<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
SHOW_STR
IP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
- "Address Family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family modifier\n"
"Network in the BGP routing table to display\n"
"IPv4 prefix\n"
DEFUN (show_ip_bgp_regexp,
show_ip_bgp_regexp_cmd,
- "show [ip] bgp [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>] regexp REGEX...",
+ "show [ip] bgp [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]|encap [unicast]|vpnv4 [unicast]>] regexp REGEX...",
SHOW_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
"Address Family\n"
char *vrf = NULL;
char *rmap_name = NULL;
char *peerstr = NULL;
- int rcvd;
+ int rcvd = 0;
struct peer *peer;
install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd);
-
- install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd);
-
- /* Restricted node: VIEW_NODE - (set of dangerous commands) */
- install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
SUBGRP_FOREACH_ADJ_SAFE (subgrp, aout, taout)
{
- bgp_adj_out_remove_subgroup (aout->rn, aout, subgrp);
- bgp_unlock_node (aout->rn);
+ struct bgp_node *rn = aout->rn;
+ bgp_adj_out_remove_subgroup (rn, aout, subgrp);
+ bgp_unlock_node (rn);
}
}
return -1;
}
+/* supports (unicast|multicast|vpn|encap) */
+safi_t
+bgp_vty_safi_from_arg(const char *safi_str)
+{
+ safi_t safi = SAFI_MAX; /* unknown */
+ if (strncmp (safi_str, "m", 1) == 0)
+ safi = SAFI_MULTICAST;
+ else if (strncmp (safi_str, "u", 1) == 0)
+ safi = SAFI_UNICAST;
+ else if (strncmp (safi_str, "e", 1) == 0)
+ safi = SAFI_ENCAP;
+ else if (strncmp (safi_str, "v", 1) == 0)
+ safi = SAFI_MPLS_VPN;
+ return safi;
+}
+
int
bgp_parse_safi(const char *str, safi_t *safi)
{
- if (!strcmp(str, "encap")) {
- *safi = SAFI_ENCAP;
- return 0;
- }
- if (!strcmp(str, "multicast")) {
- *safi = SAFI_MULTICAST;
- return 0;
- }
- if (!strcmp(str, "unicast")) {
- *safi = SAFI_UNICAST;
- return 0;
- }
- if (!strcmp(str, "vpn")) {
- *safi = SAFI_MPLS_VPN;
- return 0;
- }
+ *safi = bgp_vty_safi_from_arg(str);
+ if (*safi != SAFI_MAX)
+ return 0;
+ else
return -1;
}
return CMD_SUCCESS;
}
+DEFUN (bgp_graceful_restart_preserve_fw,
+ bgp_graceful_restart_preserve_fw_cmd,
+ "bgp graceful-restart preserve-fw-state",
+ "BGP specific commands\n"
+ "Graceful restart capability parameters\n"
+ "Sets F-bit indication that fib is preserved while doing Graceful Restart\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_flag_set(bgp, BGP_FLAG_GR_PRESERVE_FWD);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_preserve_fw,
+ no_bgp_graceful_restart_preserve_fw_cmd,
+ "no bgp graceful-restart preserve-fw-state",
+ NO_STR
+ "BGP specific commands\n"
+ "Graceful restart capability parameters\n"
+ "Unsets F-bit indication that fib is preserved while doing Graceful Restart\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_flag_unset(bgp, BGP_FLAG_GR_PRESERVE_FWD);
+ return CMD_SUCCESS;
+}
+
/* "bgp fast-external-failover" configuration. */
DEFUN (bgp_fast_external_failover,
bgp_fast_external_failover_cmd,
DEFUN (address_family_ipv4_safi,
address_family_ipv4_safi_cmd,
- "address-family ipv4 <unicast|multicast>",
+ "address-family ipv4 <unicast|multicast|vpn|encap>",
"Enter Address Family command mode\n"
"Address Family\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family modifier\n")
{
int idx_safi = 2;
- if (strncmp (argv[idx_safi]->arg, "m", 1) == 0)
- vty->node = BGP_IPV4M_NODE;
- else
- vty->node = BGP_IPV4_NODE;
+ switch (bgp_vty_safi_from_arg(argv[idx_safi]->arg))
+ {
+ case SAFI_MULTICAST:
+ vty->node = BGP_IPV4M_NODE;
+ break;
+ case SAFI_ENCAP:
+ vty->node = BGP_ENCAP_NODE;
+ break;
+ case SAFI_MPLS_VPN:
+ vty->node = BGP_VPNV4_NODE;
+ break;
+ case SAFI_UNICAST:
+ default:
+ vty->node = BGP_IPV4_NODE;
+ break;
+ }
return CMD_SUCCESS;
}
DEFUN (address_family_ipv6_safi,
address_family_ipv6_safi_cmd,
- "address-family ipv6 <unicast|multicast>",
+ "address-family ipv6 <unicast|multicast|vpn|encap>",
"Enter Address Family command mode\n"
"Address Family\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family modifier\n")
{
int idx_safi = 2;
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
+ "clear [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
CLEAR_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
"Address Family\n"
{
afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
- safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
}
else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx))
{
afi = AFI_IP;
- safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
// advance idx if necessary
argv_find (argv, argc, "unicast", &idx);
}
DEFUN (clear_bgp_ipv6_safi_prefix,
clear_bgp_ipv6_safi_prefix_cmd,
- "clear [ip] bgp ipv6 <unicast|multicast> prefix X:X::X:X/M",
+ "clear [ip] bgp ipv6 <unicast|multicast|vpn|encap> prefix X:X::X:X/M",
CLEAR_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Clear bestpath and re-advertise\n"
"IPv6 prefix\n")
{
int idx_safi = 3;
int idx_ipv6_prefixlen = 5;
- if (strncmp (argv[idx_safi]->arg, "m", 1) == 0)
- return bgp_clear_prefix (vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, SAFI_MULTICAST, NULL);
- else
- return bgp_clear_prefix (vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, SAFI_UNICAST, NULL);
+ safi_t safi = bgp_vty_safi_from_arg (argv[idx_safi]->arg);
+ return bgp_clear_prefix (vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, safi, NULL);
}
DEFUN (clear_bgp_instance_ipv6_safi_prefix,
clear_bgp_instance_ipv6_safi_prefix_cmd,
- "clear [ip] bgp <view|vrf> WORD ipv6 <unicast|multicast> prefix X:X::X:X/M",
+ "clear [ip] bgp <view|vrf> WORD ipv6 <unicast|multicast|vpn|encap> prefix X:X::X:X/M",
CLEAR_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Clear bestpath and re-advertise\n"
"IPv6 prefix\n")
{
int idx_word = 3;
int idx_safi = 5;
int idx_ipv6_prefixlen = 7;
- if (strncmp (argv[idx_safi]->arg, "m", 1) == 0)
- return bgp_clear_prefix (vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, SAFI_MULTICAST, NULL);
- else
- return bgp_clear_prefix (vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, SAFI_UNICAST, NULL);
+ safi_t safi = bgp_vty_safi_from_arg (argv[idx_safi]->text);
+ return bgp_clear_prefix (vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, safi, NULL);
}
DEFUN (show_bgp_views,
if (peer->afc[afi][safi])
{
+ memset(dn_flag, '\0', sizeof(dn_flag));
+ if (peer_dynamic_neighbor(peer))
+ dn_flag[0] = '*';
+
if (peer->hostname && bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
sprintf(neighbor_buf, "%s%s(%s) ", dn_flag, peer->hostname, peer->host);
else
/* `show [ip] bgp summary' commands. */
DEFUN (show_ip_bgp_summary,
show_ip_bgp_summary_cmd,
- "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 <all|rd ASN:nn_or_IP-address:nn>>] summary [json]",
+ "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]|vpnv4 <all|rd ASN:nn_or_IP-address:nn>>] summary [json]",
SHOW_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Display information about all VPNv4 NLRIs\n"
"Display information for a route distinguisher\n"
{
afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
- safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
}
else if (argv_find (argv, argc, "encap", &idx))
{
same.*/
DEFUN (show_ip_bgp_paths,
show_ip_bgp_paths_cmd,
- "show [ip] bgp [<unicast|multicast>] paths",
+ "show [ip] bgp [<unicast|multicast|vpn|encap>] paths",
SHOW_STR
IP_STR
BGP_STR
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Path information\n")
{
vty_out (vty, "Address Refcnt Path%s", VTY_NEWLINE);
DEFUN (show_ip_bgp_updgrps,
show_ip_bgp_updgrps_cmd,
- "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>] update-groups [SUBGROUP-ID]",
+ "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast|vpn|encap>]|ipv6 [<unicast|multicast|vpn|encap>]|vpnv4 [unicast]>] update-groups [SUBGROUP-ID]",
SHOW_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Address Family\n"
"Address Family modifier\n"
"Detailed info about dynamic update groups\n"
{
afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
- safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
}
else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx))
{
afi = AFI_IP;
- safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN;
+ safi = bgp_vty_safi_from_arg (argv[idx]->text);
// advance idx if necessary
argv_find (argv, argc, "unicast", &idx);
}
DEFUN (show_bgp_updgrps_afi_adj,
show_bgp_updgrps_afi_adj_cmd,
- "show [ip] bgp <ipv4|ipv6> <unicast|multicast> update-groups <advertise-queue|advertised-routes|packet-queue>",
+ "show [ip] bgp <ipv4|ipv6> <unicast|multicast|vpn|encap> update-groups <advertise-queue|advertised-routes|packet-queue>",
SHOW_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Detailed info about dynamic update groups\n"
"Advertisement queue\n"
"Announced routes\n"
safi_t safi;
afi = (strcmp(argv[idx_afi]->arg, "ipv4") == 0) ? AFI_IP : AFI_IP6;
- safi = (strncmp (argv[idx_safi]->arg, "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ safi = bgp_vty_safi_from_arg(argv[idx_safi]->arg);
show_bgp_updgrps_adj_info_aux(vty, NULL, afi, safi, argv[idx_type]->arg, 0);
return CMD_SUCCESS;
}
DEFUN (show_bgp_updgrps_afi_adj_s,
show_bgp_updgrps_afi_adj_s_cmd,
- "show [ip] bgp <ipv4|ipv6> <unicast|multicast> update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
+ "show [ip] bgp <ipv4|ipv6> <unicast|multicast|vpn|encap> update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
SHOW_STR
IP_STR
BGP_STR
"Address Family\n"
"Address Family modifier\n"
"Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Detailed info about dynamic update groups\n"
"Specific subgroup to display info for\n"
"Advertisement queue\n"
uint64_t subgrp_id;
afi = (strmatch(argv[idx_afi]->text, "ipv4")) ? AFI_IP : AFI_IP6;
- safi = (strmatch(argv[idx_safi]->text, "unicast")) ? SAFI_UNICAST : SAFI_MULTICAST;
+ safi = bgp_vty_safi_from_arg(argv[idx_safi]->text);
VTY_GET_ULL("subgroup-id", subgrp_id, argv[idx_subgroup_id]->arg);
show_bgp_updgrps_adj_info_aux(vty, NULL, afi, safi, argv[idx_type]->arg, subgrp_id);
bgp_redistribute_ipv4_cmd,
"redistribute <kernel|connected|static|rip|ospf|isis|pim|table>",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD)
+ FRR_IP_REDIST_HELP_STR_BGPD)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_protocol = 1;
bgp_redistribute_ipv4_rmap_cmd,
"redistribute <kernel|connected|static|rip|ospf|isis|pim|table> route-map WORD",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD
+ FRR_IP_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n")
{
bgp_redistribute_ipv4_metric_cmd,
"redistribute <kernel|connected|static|rip|ospf|isis|pim|table> metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD
+ FRR_IP_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n")
{
bgp_redistribute_ipv4_rmap_metric_cmd,
"redistribute <kernel|connected|static|rip|ospf|isis|pim|table> route-map WORD metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD
+ FRR_IP_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n"
"Metric for redistributed routes\n"
bgp_redistribute_ipv4_metric_rmap_cmd,
"redistribute <kernel|connected|static|rip|ospf|isis|pim|table> metric (0-4294967295) route-map WORD",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD
+ FRR_IP_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n"
"Route map reference\n"
"no redistribute <kernel|connected|static|rip|ospf|isis|pim|table> [metric (0-4294967295)] [route-map WORD]",
NO_STR
"Redistribute information from another routing protocol\n"
- QUAGGA_IP_REDIST_HELP_STR_BGPD
+ FRR_IP_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n"
"Route map reference\n"
bgp_redistribute_ipv6_cmd,
"redistribute <kernel|connected|static|ripng|ospf6|isis|table>",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD)
+ FRR_IP6_REDIST_HELP_STR_BGPD)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_protocol = 1;
bgp_redistribute_ipv6_rmap_cmd,
"redistribute <kernel|connected|static|ripng|ospf6|isis|table> route-map WORD",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD
+ FRR_IP6_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n")
{
bgp_redistribute_ipv6_metric_cmd,
"redistribute <kernel|connected|static|ripng|ospf6|isis|table> metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD
+ FRR_IP6_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n")
{
bgp_redistribute_ipv6_rmap_metric_cmd,
"redistribute <kernel|connected|static|ripng|ospf6|isis|table> route-map WORD metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD
+ FRR_IP6_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n"
"Metric for redistributed routes\n"
bgp_redistribute_ipv6_metric_rmap_cmd,
"redistribute <kernel|connected|static|ripng|ospf6|isis|table> metric (0-4294967295) route-map WORD",
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD
+ FRR_IP6_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n"
"Route map reference\n"
"no redistribute <kernel|connected|static|ripng|ospf6|isis|table> [metric (0-4294967295)] [route-map WORD]",
NO_STR
"Redistribute information from another routing protocol\n"
- QUAGGA_IP6_REDIST_HELP_STR_BGPD
+ FRR_IP6_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n"
"Route map reference\n"
return bgp_redistribute_unset (bgp, AFI_IP6, type, 0);
}
-
-
-
-
#endif /* HAVE_IPV6 */
int
install_element (BGP_NODE, &bgp_graceful_restart_restart_time_cmd);
install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd);
+ install_element (BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd);
+ install_element (BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
+
/* "bgp fast-external-failover" commands */
install_element (BGP_NODE, &bgp_fast_external_failover_cmd);
install_element (BGP_NODE, &no_bgp_fast_external_failover_cmd);
install_element (ENABLE_NODE, &clear_bgp_instance_ipv6_safi_prefix_cmd);
/* "show [ip] bgp summary" commands. */
- install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_cmd);
install_element (VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_bgp_updgrps_adj_cmd);
install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
- install_element (VIEW_NODE, &show_bgp_updgrps_adj_s_cmd);
install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd);
- install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_cmd);
- install_element (VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd);
+ install_element (VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd);
install_element (VIEW_NODE, &show_bgp_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd);
- install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
install_element (VIEW_NODE, &show_bgp_updgrps_adj_s_cmd);
- install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd);
+ install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd);
install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd);
install_element (VIEW_NODE, &show_bgp_updgrps_stats_cmd);
- install_element (VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_updgrps_cmd);
/* "show [ip] bgp neighbors" commands. */
install_element (VIEW_NODE, &show_ip_bgp_neighbors_cmd);
#define BGP_INSTANCE_HELP_STR "BGP view\nBGP VRF\nView/VRF name\n"
#define BGP_INSTANCE_ALL_HELP_STR "BGP view\nBGP VRF\nAll Views/VRFs\n"
+#define AFI_SAFI_STR \
+ "Address family\n" \
+ "Address Family modifier\n" \
+ "Address Family modifier\n" \
+ "Address Family modifier\n" \
+ "Address Family modifier\n"
+
extern void bgp_vty_init (void);
extern const char *afi_safi_print (afi_t, safi_t);
extern int bgp_config_write_update_delay (struct vty *, struct bgp *);
extern int
bgp_parse_safi(const char *str, safi_t *safi);
+extern safi_t
+bgp_vty_safi_from_arg(const char *safi_str);
+
#endif /* _QUAGGA_BGP_VTY_H */
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
peer->nsf[afi][safi] = 0;
if (peer->t_gr_restart)
if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
+ /* BGP graceful-restart Preserve State F bit. */
+ if (bgp_flag_check (bgp, BGP_FLAG_GR_PRESERVE_FWD))
+ vty_out (vty, " bgp graceful-restart preserve-fw-state%s", VTY_NEWLINE);
+
/* BGP bestpath method. */
if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
#define BGP_FLAG_MULTIPATH_RELAX_AS_SET (1 << 17)
#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18)
#define BGP_FLAG_SHOW_HOSTNAME (1 << 19)
+#define BGP_FLAG_GR_PRESERVE_FWD (1 << 20)
/* BGP Per AF flags */
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
1
};
-static struct rfapi_l2_group_cfg *
+struct rfapi_l2_group_cfg *
bgp_rfapi_get_group_by_lni_label (
struct bgp *bgp,
uint32_t logical_net_id,
extern struct rfapi_cfg *
bgp_rfapi_get_config (struct bgp *bgp);
+extern struct rfapi_l2_group_cfg *
+bgp_rfapi_get_group_by_lni_label (
+ struct bgp *bgp,
+ uint32_t logical_net_id,
+ uint32_t label);
+
extern struct ecommunity *
bgp_rfapi_get_ecommunity_by_lni_label (
struct bgp *bgp,
* If mac address is set, add an RT based on the registered LNI
*/
memset ((char *) &ecom_value, 0, sizeof (ecom_value));
- ecom_value.val[1] = 0x02;
+ ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
ecom_value.val[5] = (l2o->logical_net_id >> 16) & 0xff;
ecom_value.val[6] = (l2o->logical_net_id >> 8) & 0xff;
ecom_value.val[7] = (l2o->logical_net_id >> 0) & 0xff;
rtlist = ecommunity_new();
ecommunity_add_val (rtlist, &ecom_value);
}
+ if (l2o->tag_id)
+ {
+ as_t as = bgp->as;
+ uint16_t val = l2o->tag_id;
+ memset ((char *) &ecom_value, 0, sizeof (ecom_value));
+ ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
+ if (as > BGP_AS_MAX)
+ {
+ ecom_value.val[0] = ECOMMUNITY_ENCODE_AS4;
+ ecom_value.val[2] = (as >>24) & 0xff;
+ ecom_value.val[3] = (as >>16) & 0xff;
+ ecom_value.val[4] = (as >>8) & 0xff;
+ ecom_value.val[5] = as & 0xff;
+ }
+ else
+ {
+ ecom_value.val[0] = ECOMMUNITY_ENCODE_AS;
+ ecom_value.val[2] = (as >>8) & 0xff;
+ ecom_value.val[3] = as & 0xff;
+ }
+ ecom_value.val[6] = (val >> 8) & 0xff;
+ ecom_value.val[7] = val & 0xff;
+ if (rtlist == NULL)
+ rtlist = ecommunity_new();
+ ecommunity_add_val (rtlist, &ecom_value);
+ }
}
/*
uint32_t logical_net_id; /* ~= EVPN Ethernet Segment Id,
must not be zero for mac regis. */
uint8_t local_nve_id;
+ uint16_t tag_id; /* EVPN Ethernet Tag ID, 0 = none */
};
typedef enum
return ENOENT;
}
+int
+rfapiEcommunityGetEthernetTag (struct ecommunity *ecom, uint16_t * tag_id)
+{
+ struct bgp *bgp = bgp_get_default ();
+ *tag_id = 0; /* default to untagged */
+ if (ecom)
+ {
+ int i;
+ for (i = 0; i < ecom->size; ++i)
+ {
+ as_t as = 0;
+ int encode = 0;
+ uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
+
+ /* High-order octet of type. */
+ encode = *p++;
+
+ if (*p++ == ECOMMUNITY_ROUTE_TARGET) {
+ if (encode == ECOMMUNITY_ENCODE_AS4)
+ {
+ as = (*p++ << 24);
+ as |= (*p++ << 16);
+ as |= (*p++ << 8);
+ as |= (*p++);
+ }
+ else if (encode == ECOMMUNITY_ENCODE_AS)
+ {
+ as = (*p++ << 8);
+ as |= (*p++);
+ p += 2; /* skip next two, tag/vid always in lowest bytes */
+ }
+ if (as == bgp->as)
+ {
+ *tag_id = *p++ << 8;
+ *tag_id |= (*p++);
+ return 0;
+ }
+ }
+ }
+ }
+ return ENOENT;
+}
+
static int
rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt)
{
{
(void) rfapiEcommunityGetLNI (bi->attr->extra->ecommunity,
&vo->v.l2addr.logical_net_id);
+ (void) rfapiEcommunityGetEthernetTag (bi->attr->extra->ecommunity,
+ &vo->v.l2addr.tag_id);
}
/* local_nve_id comes from lower byte of RD type */
info_new->next = next;
if (next)
next->prev = info_new;
+ bgp_attr_intern (info_new->attr);
}
static void
/*
* Remove the route (doubly-linked)
*/
+ // bgp_attr_unintern (&bi->attr);
if (bi->next)
bi->next->prev = bi->prev;
if (bi->prev)
__func__, import_table, vpn_bi, afi, rn, m);
RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0);
+ bgp_attr_intern (vpn_bi->attr);
}
static void
wcb->node = rn;
wcb->info = bi;
wcb->import_table = import_table;
+ bgp_attr_intern (bi->attr);
if (VNC_DEBUG(VERBOSE))
{
struct ecommunity *ecom,
uint32_t *lni);
+extern int rfapiEcommunityGetEthernetTag (
+ struct ecommunity *ecom,
+ uint16_t * tag_id);
/* enable for debugging; disable for performance */
#if 0
{
(void) rfapiEcommunityGetLNI (bi->attr->extra->ecommunity,
&vo->v.l2addr.logical_net_id);
+ (void) rfapiEcommunityGetEthernetTag (bi->attr->extra->ecommunity,
+ &vo->v.l2addr.tag_id);
}
/* local_nve_id comes from RD */
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295) .LNH_OPTIONS",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255) .LNH_OPTIONS",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) .LNH_OPTIONS",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) .LNH_OPTIONS",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> .LNH_OPTIONS",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255)",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
"Add registration\n"
"VNC Information\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"VN address of NVE\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255) lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"UN address of NVE\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"Administrative cost [default: 255]\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"UN address of NVE\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"Registration lifetime [default: infinite]\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"UN address of NVE\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"Administrative cost [default: 255]\n" "Administrative cost\n")
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M>",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"UN address of NVE\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
- "Add/modify prefix related infomation\n"
+ "Add/modify prefix related information\n"
"IPv4 prefix\n" "IPv6 prefix\n")
{
/* pfx vn un cost life */
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
"Add registration\n"
"VNC Information\n"
- "Add/modify mac address infomation\n"
+ "Add/modify mac address information\n"
"MAC address\n"
"Virtual Network Identifier follows\n"
"Virtual Network Identifier\n"
"clear vnc nve vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"VN address of NVE\n"
"VN IPv4 interface address\n"
"VN IPv6 interface address\n"
"clear vnc nve un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"UN address of NVE\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
"clear vnc nve vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"VN address of NVE\n"
"VN IPv4 interface address\n" "VN IPv6 interface address\n")
{
"clear vnc nve un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"UN address of NVE\n"
"UN IPv4 interface address\n" "UN IPv6 interface address\n")
{
"clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> *",
"clear\n"
"VNC Information\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> *",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"All UN addresses\n"
"UN IPv4 interface address\n"
"UN IPv6 interface address\n"
- "Clear prefix registration infomation\n"
+ "Clear prefix registration information\n"
"All prefixes\n"
"IPv4 prefix\n"
"IPv6 prefix\n")
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M> prefix <*|A.B.C.D/M|X:X::X:X/M>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
"clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> prefix <*|A.B.C.D/M|X:X::X:X/M>",
"clear\n"
"VNC Information\n"
- "Clear mac registration infomation\n"
+ "Clear mac registration information\n"
"All macs\n"
"MAC address\n"
"VNI keyword\n"
memset (new, 0, sizeof (struct attr));
bgp_attr_dup (new, orig);
bgp_attr_extra_get (new);
- bgp_attr_flush_encap (new);
/*
* Set nexthop
##
-## Configure template file for Quagga.
+## Configure template file for FreeRangeRouting.
## autoconf will generate configure script.
##
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
##
AC_PREREQ(2.60)
-AC_INIT(Quagga, 2.0.999, [https://bugzilla.quagga.net])
+AC_INIT(frr, 2.0-rc0, [https://bugzilla.quagga.net])
+PACKAGE_URL="https://freerangerouting.org/"
+PACKAGE_FULLNAME="FreeRangeRouting"
+AC_SUBST(PACKAGE_FULLNAME)
+
CONFIG_ARGS="$ac_configure_args"
AC_SUBST(CONFIG_ARGS)
+
AC_CONFIG_SRCDIR(lib/zebra.h)
AC_CONFIG_MACRO_DIR([m4])
AS_HELP_STRING([--disable-ospf6d], [do not build ospf6d]))
AC_ARG_ENABLE(ldpd,
AS_HELP_STRING([--enable-ldpd], [build ldpd]))
-AC_ARG_ENABLE(watchquagga,
- AS_HELP_STRING([--disable-watchquagga], [do not build watchquagga]))
+AC_ARG_ENABLE(watchfrr,
+ AS_HELP_STRING([--disable-watchfrr], [do not build watchfrr]))
AC_ARG_ENABLE(isisd,
AS_HELP_STRING([--disable-isisd], [do not build isisd]))
AC_ARG_ENABLE(pimd,
AC_ARG_ENABLE(multipath,
AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit]))
AC_ARG_ENABLE(user,
- AS_HELP_STRING([--enable-user=USER], [user to run Quagga suite as (default quagga)]))
+ AS_HELP_STRING([--enable-user=USER], [user to run FRR suite as (default frr)]))
AC_ARG_ENABLE(group,
- AS_HELP_STRING([--enable-group=GROUP], [group to run Quagga suite as (default quagga)]))
+ AS_HELP_STRING([--enable-group=GROUP], [group to run FRR suite as (default frr)]))
AC_ARG_ENABLE(vty_group,
AS_HELP_STRING([--enable-vty-group=ARG], [set vty sockets to have specified group as owner]))
AC_ARG_ENABLE(configfile_mask,
enable_user=""
else
if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then
- enable_user="quagga"
+ enable_user="frr"
fi
- AC_DEFINE_UNQUOTED(QUAGGA_USER, "${enable_user}", Quagga User)
+ AC_DEFINE_UNQUOTED(FRR_USER, "${enable_user}", frr User)
fi
if test x"${enable_group}" = x"no"; then
enable_group=""
else
if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then
- enable_group="quagga"
+ enable_group="frr"
fi
- AC_DEFINE_UNQUOTED(QUAGGA_GROUP, "${enable_group}", Quagga Group)
+ AC_DEFINE_UNQUOTED(FRR_GROUP, "${enable_group}", frr Group)
fi
if test x"${enable_vty_group}" = x"yes" ; then
sys/cdefs.h])
dnl Utility macro to avoid retyping includes all the time
-m4_define([QUAGGA_INCLUDES],
+m4_define([FRR_INCLUDES],
[#ifdef SUNOS_5
#define _XPG4_2
#define __EXTENSIONS__
dnl HAVE_NETINET_IN_VAR_H depend upon. But if_var.h depends on if.h, hence
dnl an additional round for it.
-AC_CHECK_HEADERS([net/if_var.h], [], [], QUAGGA_INCLUDES)
+AC_CHECK_HEADERS([net/if_var.h], [], [], FRR_INCLUDES)
-m4_define([QUAGGA_INCLUDES],
-QUAGGA_INCLUDES
+m4_define([FRR_INCLUDES],
+FRR_INCLUDES
[#if HAVE_NET_IF_VAR_H
# include <net/if_var.h>
#endif
net/if_dl.h net/netopt.h \
inet/nd.h netinet/ip_icmp.h \
sys/sysctl.h sys/sockio.h kvm.h sys/conf.h],
- [], [], QUAGGA_INCLUDES)
+ [], [], FRR_INCLUDES)
AC_CHECK_HEADERS([ucontext.h], [], [],
[#ifndef __USE_GNU
#define __USE_GNU
#endif /* __USE_GNU */
-QUAGGA_INCLUDES
+FRR_INCLUDES
])
m4_define([UCONTEXT_INCLUDES],
AC_CHECK_MEMBERS([ucontext_t.uc_mcontext.gregs],
[], [], [UCONTEXT_INCLUDES])
-m4_define([QUAGGA_INCLUDES],
-QUAGGA_INCLUDES
+m4_define([FRR_INCLUDES],
+FRR_INCLUDES
[
#include <sys/un.h>
#include <netinet/in_systm.h>
AC_DEFINE(PAM_CONV_FUNC,misc_conv,Have misc_conv)
pam_conv_func="misc_conv"
],
- [], QUAGGA_INCLUDES)
+ [], FRR_INCLUDES)
AC_CHECK_HEADER([security/openpam.h],
[AC_DEFINE(HAVE_OPENPAM_H,,Have openpam.h)
AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
pam_conv_func="openpam_ttyconv"
],
- [], QUAGGA_INCLUDES[#include <security/pam_appl.h>])
+ [], FRR_INCLUDES[#include <security/pam_appl.h>])
if test -z "$ac_cv_header_security_pam_misc_h$ac_cv_header_security_openpam_h" ; then
AC_MSG_WARN([*** pam support will not be built ***])
with_libpam="no"
AC_CHECK_HEADER([asm-generic/unistd.h],
[AC_CHECK_DECL(__NR_setns,
AC_DEFINE(HAVE_NETNS,, Have netns),,
- QUAGGA_INCLUDES [#include <asm-generic/unistd.h>
+ FRR_INCLUDES [#include <asm-generic/unistd.h>
])
AC_CHECK_FUNCS(setns)]
)
dnl ------------------------------
dnl check kernel route read method
dnl ------------------------------
-AC_CACHE_CHECK([route read method], [quagga_cv_rtread_method],
+AC_CACHE_CHECK([route read method], [frr_cv_rtread_method],
[if test "x$netlink" = xyes; then
- quagga_cv_rtread_method="netlink"
+ frr_cv_rtread_method="netlink"
else
-for quagga_cv_rtread_method in /dev/ip /dev/null;
+for frr_cv_rtread_method in /dev/ip /dev/null;
do
- test x`ls $quagga_cv_rtread_method 2>/dev/null` = x"$quagga_cv_rtread_method" && break
+ test x`ls $frr_cv_rtread_method 2>/dev/null` = x"$frr_cv_rtread_method" && break
done
-case $quagga_cv_rtread_method in
+case $frr_cv_rtread_method in
"/dev/ip")
case "$host" in
- *-freebsd*) quagga_cv_rtread_method="sysctl";;
- *) quagga_cv_rtread_method="getmsg";;
+ *-freebsd*) frr_cv_rtread_method="sysctl";;
+ *) frr_cv_rtread_method="getmsg";;
esac;;
*)
- quagga_cv_rtread_method="sysctl";;
+ frr_cv_rtread_method="sysctl";;
esac
fi])
-RTREAD_METHOD=rtread_${quagga_cv_rtread_method}.o
+RTREAD_METHOD=rtread_${frr_cv_rtread_method}.o
AC_SUBST(RTREAD_METHOD)
dnl -----------------------------
dnl ---------------------------------------------------------------
dnl figure out how to specify an interface in multicast sockets API
dnl ---------------------------------------------------------------
-AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], QUAGGA_INCLUDES)
+AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], FRR_INCLUDES)
AC_CHECK_HEADERS([linux/mroute.h], [], [],[
#include <sys/socket.h>
#include <linux/types.h>
])
-m4_define([QUAGGA_INCLUDES],
-QUAGGA_INCLUDES
+m4_define([FRR_INCLUDES],
+FRR_INCLUDES
[#if HAVE_LINUX_MROUTE_H
# include <linux/mroute.h>
#endif
#include <net/route.h>
])
-m4_define([QUAGGA_INCLUDES],
-QUAGGA_INCLUDES
+m4_define([FRR_INCLUDES],
+FRR_INCLUDES
[#if HAVE_NETINET_IP_MROUTE_H
# include <netinet/ip_mroute.h>
#endif
dnl ---------------------------------------------------------------
AC_CHECK_HEADER( [net/if_media.h],
[m4_define([LINK_DETECT_INCLUDES],
- QUAGGA_INCLUDES
+ FRR_INCLUDES
[#include <net/if_media.h>
])
AC_CHECK_MEMBERS( [struct ifmediareq.ifm_status],
AC_DEFINE(HAVE_BSD_LINK_DETECT,,[BSD link-detect]),
[], LINK_DETECT_INCLUDES)],
[],
- QUAGGA_INCLUDES)
+ FRR_INCLUDES)
dnl ---------------------------------------------------------------
dnl Additional, newer way to check link-state using ifi_link_state.
dnl ---------------------------------------------------------------
AC_CHECK_MEMBERS([struct if_data.ifi_link_state],
AC_DEFINE(HAVE_BSD_IFI_LINK_STATE,,[BSD ifi_link_state available]),
- [], QUAGGA_INCLUDES)
+ [], FRR_INCLUDES)
dnl ------------------------
dnl TCP_MD5SIG socket option
AC_CHECK_HEADER([netinet/tcp.h],
[m4_define([MD5_INCLUDES],
- QUAGGA_INCLUDES
+ FRR_INCLUDES
[#include <netinet/tcp.h>
])
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)],
[],
- QUAGGA_INCLUDES)
+ FRR_INCLUDES)
if test $ac_cv_have_decl_TCP_MD5SIG = no; then
AC_CHECK_HEADER([linux/tcp.h],
[m4_define([MD5_INCLUDES],
- QUAGGA_INCLUDES
+ FRR_INCLUDES
[#include <linux/tcp.h>
])
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)])
dnl -----------------------------
dnl check ipforward detect method
dnl -----------------------------
-AC_CACHE_CHECK([ipforward method], [quagga_cv_ipforward_method],
+AC_CACHE_CHECK([ipforward method], [frr_cv_ipforward_method],
[if test x$cross_compiling = xyes; then
if test x"$opsys" = x"gnu-linux"; then
- quagga_cv_ipforward_method=/proc/net/snmp
+ frr_cv_ipforward_method=/proc/net/snmp
else
- quagga_cv_ipforward_method=/dev/ip
+ frr_cv_ipforward_method=/dev/ip
fi
else
- for quagga_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
+ for frr_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
do
- test x`ls $quagga_cv_ipforward_method 2>/dev/null` = x"$quagga_cv_ipforward_method" && break
+ test x`ls $frr_cv_ipforward_method 2>/dev/null` = x"$frr_cv_ipforward_method" && break
done
fi
-case $quagga_cv_ipforward_method in
- "/proc/net/snmp") quagga_cv_ipforward_method="proc";;
+case $frr_cv_ipforward_method in
+ "/proc/net/snmp") frr_cv_ipforward_method="proc";;
"/dev/ip")
case "$host" in
- *-freebsd*) quagga_cv_ipforward_method="sysctl";;
- *) quagga_cv_ipforward_method="solaris";;
+ *-freebsd*) frr_cv_ipforward_method="sysctl";;
+ *) frr_cv_ipforward_method="solaris";;
esac;;
- *) quagga_cv_ipforward_method="sysctl";;
+ *) frr_cv_ipforward_method="sysctl";;
esac])
-IPFORWARD=ipforward_${quagga_cv_ipforward_method}.o
+IPFORWARD=ipforward_${frr_cv_ipforward_method}.o
AC_SUBST(IPFORWARD)
dnl ----------------------------------------------------------------------------
dnl ------------------
AC_CHECK_HEADERS([netinet6/in6.h netinet/in6_var.h \
netinet6/in6_var.h netinet6/nd6.h], [], [],
- QUAGGA_INCLUDES)
+ FRR_INCLUDES)
-m4_define([QUAGGA_INCLUDES],dnl
-QUAGGA_INCLUDES
+m4_define([FRR_INCLUDES],dnl
+FRR_INCLUDES
[#if HAVE_NETINET6_IN6_H
#include <netinet6/in6.h>
#endif
fi
AM_CONDITIONAL(LDPD, test "x$LDPD" = "xldpd")
-if test "${enable_watchquagga}" = "no";then
- WATCHQUAGGA=""
+if test "${enable_watchfrr}" = "no";then
+ WATCHFRR=""
else
- WATCHQUAGGA="watchquagga"
+ WATCHFRR="watchfrr"
fi
-AM_CONDITIONAL(WATCHQUAGGA, test "x$WATCHQUAGGA" = "xwatchquagga")
+AM_CONDITIONAL(WATCHFRR, test "x$WATCHFRR" = "xwatchfrr")
OSPFCLIENT=""
if test "${enable_ospfapi}" != "no";then
AC_SUBST(OSPFD)
AC_SUBST(OSPF6D)
AC_SUBST(LDPD)
-AC_SUBST(WATCHQUAGGA)
+AC_SUBST(WATCHFRR)
AC_SUBST(ISISD)
AC_SUBST(PIMD)
AC_SUBST(SOLARIS)
struct ifaliasreq, struct if6_aliasreq, struct in6_aliasreq,
struct nd_opt_adv_interval, struct rt_addrinfo,
struct nd_opt_homeagent_info, struct nd_opt_adv_interval],
- [], [], QUAGGA_INCLUDES)
+ [], [], FRR_INCLUDES)
AC_CHECK_MEMBERS([struct sockaddr.sa_len,
struct sockaddr_in.sin_len, struct sockaddr_un.sun_len,
struct sockaddr_dl.sdl_len,
struct if6_aliasreq.ifra_lifetime,
struct nd_opt_adv_interval.nd_opt_ai_type],
- [], [], QUAGGA_INCLUDES)
+ [], [], FRR_INCLUDES)
dnl ---------------------------
dnl IRDP/pktinfo/icmphdr checks
fi],
[if test "${enable_irdp}" = "yes"; then
AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!'])
- fi], [QUAGGA_INCLUDES])],
+ fi], [FRR_INCLUDES])],
[if test "${enable_irdp}" = "yes"; then
AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!'])
- fi], [QUAGGA_INCLUDES])
+ fi], [FRR_INCLUDES])
dnl -----------------------
dnl checking for IP_PKTINFO
AC_CHECK_DECL(CLOCK_MONOTONIC,
[AC_CHECK_LIB(rt, clock_gettime, [LIBS="$LIBS -lrt"])
AC_DEFINE(HAVE_CLOCK_MONOTONIC,, Have monotonic clock)
-], [AC_MSG_RESULT(no)], [QUAGGA_INCLUDES])
+], [AC_MSG_RESULT(no)], [FRR_INCLUDES])
dnl --------------------------------------
dnl checking for flex and bison
AC_TRY_COMPILE([#include <sys/prctl.h>],[prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PR_SET_KEEPCAPS,,prctl)
- quagga_ac_keepcaps="yes"],
+ frr_ac_keepcaps="yes"],
AC_MSG_RESULT(no)
)
- if test x"${quagga_ac_keepcaps}" = x"yes"; then
+ if test x"${frr_ac_keepcaps}" = x"yes"; then
AC_CHECK_HEADERS(sys/capability.h)
fi
if test x"${ac_cv_header_sys_capability_h}" = x"yes"; then
AC_CHECK_LIB(cap, cap_init,
[AC_DEFINE(HAVE_LCAPS,1,Capabilities)
LIBCAP="-lcap"
- quagga_ac_lcaps="yes"]
+ frr_ac_lcaps="yes"]
)
else
AC_CHECK_HEADERS(priv.h,
AC_TRY_COMPILE([#include <priv.h>],[getpflags(PRIV_AWARE);],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOLARIS_CAPABILITIES,1,getpflags)
- quagga_ac_scaps="yes"],
+ frr_ac_scaps="yes"],
AC_MSG_RESULT(no)
)
]
)
fi
- if test x"${quagga_ac_scaps}" = x"yes" \
- -o x"${quagga_ac_lcaps}" = x"yes"; then
+ if test x"${frr_ac_scaps}" = x"yes" \
+ -o x"${frr_ac_lcaps}" = x"yes"; then
AC_DEFINE(HAVE_CAPABILITIES,1,capabilities)
fi
fi
AC_DEFINE(HAVE_MALLINFO,,mallinfo)],
AC_MSG_RESULT(no)
)
- ], [], QUAGGA_INCLUDES)
+ ], [], FRR_INCLUDES)
dnl ----------
dnl configure date
dnl ------------------------------
AC_MSG_CHECKING(directory to use for state file)
if test "${prefix}" = "NONE"; then
- quagga_statedir_prefix="";
+ frr_statedir_prefix="";
else
- quagga_statedir_prefix=${prefix}
+ frr_statedir_prefix=${prefix}
fi
if test "${localstatedir}" = '${prefix}/var'; then
- for QUAGGA_STATE_DIR in ${quagga_statedir_prefix}/var/run dnl
- ${quagga_statedir_prefix}/var/adm dnl
- ${quagga_statedir_prefix}/etc dnl
+ for FRR_STATE_DIR in ${frr_statedir_prefix}/var/run dnl
+ ${frr_statedir_prefix}/var/adm dnl
+ ${frr_statedir_prefix}/etc dnl
/var/run dnl
/var/adm dnl
/etc dnl
/dev/null;
do
- test -d $QUAGGA_STATE_DIR && break
+ test -d $FRR_STATE_DIR && break
done
- quagga_statedir=$QUAGGA_STATE_DIR
+ frr_statedir=$FRR_STATE_DIR
else
- quagga_statedir=${localstatedir}
+ frr_statedir=${localstatedir}
fi
-if test $quagga_statedir = "/dev/null"; then
+if test $frr_statedir = "/dev/null"; then
AC_MSG_ERROR('STATE DIRECTORY NOT FOUND! FIX OR SPECIFY --localstatedir!')
fi
-AC_MSG_RESULT(${quagga_statedir})
-AC_SUBST(quagga_statedir)
-
-AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$quagga_statedir/zebra.pid",zebra PID)
-AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$quagga_statedir/ripd.pid",ripd PID)
-AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$quagga_statedir/ripngd.pid",ripngd PID)
-AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$quagga_statedir/bgpd.pid",bgpd PID)
-AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$quagga_statedir/ospfd.pid",ospfd PID)
-AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$quagga_statedir/ospf6d.pid",ospf6d PID)
-AC_DEFINE_UNQUOTED(PATH_LDPD_PID, "$quagga_statedir/ldpd.pid",ldpd PID)
-AC_DEFINE_UNQUOTED(LDPD_SOCKET, "$quagga_statedir/ldpd.sock",ldpd control socket)
-AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$quagga_statedir/isisd.pid",isisd PID)
-AC_DEFINE_UNQUOTED(PATH_PIMD_PID, "$quagga_statedir/pimd.pid",pimd PID)
-AC_DEFINE_UNQUOTED(PATH_WATCHQUAGGA_PID, "$quagga_statedir/watchquagga.pid",watchquagga PID)
-AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$quagga_statedir/zserv.api",zebra api socket)
-AC_DEFINE_UNQUOTED(ZEBRA_VTYSH_PATH, "$quagga_statedir/zebra.vty",zebra vty socket)
-AC_DEFINE_UNQUOTED(RIP_VTYSH_PATH, "$quagga_statedir/ripd.vty",rip vty socket)
-AC_DEFINE_UNQUOTED(RIPNG_VTYSH_PATH, "$quagga_statedir/ripngd.vty",ripng vty socket)
-AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$quagga_statedir/bgpd.vty",bgpd vty socket)
-AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$quagga_statedir/ospfd.vty",ospfd vty socket)
-AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$quagga_statedir/ospf6d.vty",ospf6d vty socket)
-AC_DEFINE_UNQUOTED(LDP_VTYSH_PATH, "$quagga_statedir/ldpd.vty",ldpd vty socket)
-AC_DEFINE_UNQUOTED(ISIS_VTYSH_PATH, "$quagga_statedir/isisd.vty",isisd vty socket)
-AC_DEFINE_UNQUOTED(PIM_VTYSH_PATH, "$quagga_statedir/pimd.vty",pimd vty socket)
-AC_DEFINE_UNQUOTED(WATCHQUAGGA_VTYSH_PATH, "$quagga_statedir/watchquagga.vty",watchquagga vty socket)
-AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$quagga_statedir",daemon vty directory)
+AC_MSG_RESULT(${frr_statedir})
+AC_SUBST(frr_statedir)
+
+AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$frr_statedir/zebra.pid",zebra PID)
+AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$frr_statedir/ripd.pid",ripd PID)
+AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$frr_statedir/ripngd.pid",ripngd PID)
+AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$frr_statedir/bgpd.pid",bgpd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$frr_statedir/ospfd.pid",ospfd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$frr_statedir/ospf6d.pid",ospf6d PID)
+AC_DEFINE_UNQUOTED(PATH_LDPD_PID, "$frr_statedir/ldpd.pid",ldpd PID)
+AC_DEFINE_UNQUOTED(LDPD_SOCKET, "$frr_statedir/ldpd.sock",ldpd control socket)
+AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$frr_statedir/isisd.pid",isisd PID)
+AC_DEFINE_UNQUOTED(PATH_PIMD_PID, "$frr_statedir/pimd.pid",pimd PID)
+AC_DEFINE_UNQUOTED(PATH_WATCHFRR_PID, "$frr_statedir/watchfrr.pid",watchfrr PID)
+AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$frr_statedir/zserv.api",zebra api socket)
+AC_DEFINE_UNQUOTED(ZEBRA_VTYSH_PATH, "$frr_statedir/zebra.vty",zebra vty socket)
+AC_DEFINE_UNQUOTED(RIP_VTYSH_PATH, "$frr_statedir/ripd.vty",rip vty socket)
+AC_DEFINE_UNQUOTED(RIPNG_VTYSH_PATH, "$frr_statedir/ripngd.vty",ripng vty socket)
+AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$frr_statedir/bgpd.vty",bgpd vty socket)
+AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$frr_statedir/ospfd.vty",ospfd vty socket)
+AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$frr_statedir/ospf6d.vty",ospf6d vty socket)
+AC_DEFINE_UNQUOTED(LDP_VTYSH_PATH, "$frr_statedir/ldpd.vty",ldpd vty socket)
+AC_DEFINE_UNQUOTED(ISIS_VTYSH_PATH, "$frr_statedir/isisd.vty",isisd vty socket)
+AC_DEFINE_UNQUOTED(PIM_VTYSH_PATH, "$frr_statedir/pimd.vty",pimd vty socket)
+AC_DEFINE_UNQUOTED(WATCHFRR_VTYSH_PATH, "$frr_statedir/watchfrr.vty",watchfrr vty socket)
+AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$frr_statedir",daemon vty directory)
dnl autoconf does this, but it does it too late...
test "x$prefix" = xNONE && prefix=$ac_default_prefix
done
AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary)
+CFG_SYSCONF="$sysconfdir"
+CFG_SBIN="$sbindir"
+CFG_STATE="$frr_statedir"
+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\""
+done
+AC_SUBST(CFG_SYSCONF)
+AC_SUBST(CFG_SBIN)
+AC_SUBST(CFG_STATE)
+
dnl -------------------------------
dnl Quagga sources should always be
dnl current wrt interfaces. Dont
dnl ---------------------------
AC_MSG_CHECKING(for working htonl)
AC_CACHE_VAL(ac_cv_htonl_works,
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([QUAGGA_INCLUDES],[htonl (0);])],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES],[htonl (0);])],
[ac_cv_htonl_works=yes], [ac_cv_htonl_works=no])
]
)
AC_MSG_RESULT($ac_cv_htonl_works)
AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
- ripngd/Makefile bgpd/Makefile ospfd/Makefile watchquagga/Makefile
+ ripngd/Makefile bgpd/Makefile ospfd/Makefile watchfrr/Makefile
ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
pimd/Makefile
cumulus/Makefile
pkgsrc/Makefile
fpm/Makefile
- redhat/quagga.spec
+ redhat/frr.spec
lib/version.h
doc/defines.texi
+ doc/bgpd.8
+ doc/isisd.8
+ doc/ospf6d.8
+ doc/ospfclient.8
+ doc/ospfd.8
+ doc/ldpd.8
+ doc/ripd.8
+ doc/ripngd.8
+ doc/pimd.8
+ doc/vtysh.1
+ doc/watchfrr.8
+ doc/zebra.8
+ doc/frr.1
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh])
AC_OUTPUT
echo "
-Quagga configuration
---------------------
-quagga version : ${PACKAGE_VERSION}
+FreeRangeRouting configuration
+------------------------------
+FRR version : ${PACKAGE_VERSION}
host operating system : ${host_os}
source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
make : ${MAKE-make}
linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
-state file directory : ${quagga_statedir}
+state file directory : ${frr_statedir}
config file directory : `eval echo \`echo ${sysconfdir}\``
example directory : `eval echo \`echo ${exampledir}\``
-user to run as : ${enable_user}
-group to run as : ${enable_group}
-group for vty sockets : ${enable_vty_group}
+user to run as : ${enable_user}
+group to run as : ${enable_group}
+group for vty sockets : ${enable_vty_group}
config file mask : ${enable_configfile_mask}
log file mask : ${enable_logfile_mask}
zebra protobuf enabled : ${have_protobuf:-no}
sbin_PROGRAMS = ssd
-EXTRA_DIST = etc/quagga/debian.conf etc/quagga/daemons etc/default/quagga
+EXTRA_DIST = etc/frr/debian.conf etc/frr/daemons etc/default/frr
ssd_SOURCES = start-stop-daemon.c
--- /dev/null
+MAX_INSTANCES=5
+MAX_FDS=1024
+ZEBRA_OPTIONS="-s 16777216 -A 127.0.0.1"
+BGPD_OPTIONS="-A 127.0.0.1"
+OSPFD_OPTIONS="-A 127.0.0.1"
+OSPF6D_OPTIONS="-A ::1"
+RIPD_OPTIONS="-A 127.0.0.1"
+RIPNGD_OPTIONS="-A ::1"
+ISISD_OPTIONS="-A 127.0.0.1"
+++ /dev/null
-MAX_INSTANCES=5
-MAX_FDS=1024
-ZEBRA_OPTIONS="-s 16777216 -A 127.0.0.1"
-BGPD_OPTIONS="-A 127.0.0.1"
-OSPFD_OPTIONS="-A 127.0.0.1"
-OSPF6D_OPTIONS="-A ::1"
-RIPD_OPTIONS="-A 127.0.0.1"
-RIPNGD_OPTIONS="-A ::1"
-ISISD_OPTIONS="-A 127.0.0.1"
--- /dev/null
+log file /var/log/frr/frr.log
+log timestamp precision 6
--- /dev/null
+# This file tells the frr package which daemons to start.
+#
+# Entries are in the format: <daemon>=(yes|no|priority)
+# 0, "no" = disabled
+# 1, "yes" = highest priority
+# 2 .. 10 = lower priorities
+# Read /usr/share/doc/frr/README.Debian for details.
+#
+# Sample configurations for these daemons can be found in
+# /usr/share/doc/frr/examples/.
+#
+# ATTENTION:
+#
+# When activation a daemon at the first time, a config file, even if it is
+# empty, has to be present *and* be owned by the user and group "frr", else
+# the daemon will not be started by /etc/init.d/frr. The permissions should
+# be u=rw,g=r,o=.
+# When using "vtysh" such a config file is also needed. It should be owned by
+# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
+#
+# The watchfrr daemon is always started. Per default in monitoring-only but
+# that can be changed via /etc/frr/debian.conf.
+#
+zebra=no
+bgpd=no
+ospfd=no
+ospf6d=no
+ripd=no
+ripngd=no
+isisd=no
+
--- /dev/null
+#
+# If this option is set the /etc/init.d/frr script automatically loads
+# the config via "vtysh -b" when the servers are started.
+# Check /etc/pam.d/frr if you intend to use "vtysh"!
+#
+vtysh_enable=yes
+zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
+bgpd_options=" --daemon -A 127.0.0.1"
+ospfd_options=" --daemon -A 127.0.0.1"
+ospf6d_options=" --daemon -A ::1"
+ripd_options=" --daemon -A 127.0.0.1"
+ripngd_options=" --daemon -A ::1"
+isisd_options=" --daemon -A 127.0.0.1"
+pimd_options=" --daemon -A 127.0.0.1"
+
+# The list of daemons to watch is automatically generated by the init script.
+watchfrr_enable=yes
+watchfrr_options=(-adz -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB -t 30)
--- /dev/null
+service integrated-vtysh-config
+username cumulus nopassword
+++ /dev/null
-log file /var/log/quagga/quagga.log
-log timestamp precision 6
+++ /dev/null
-# This file tells the quagga package which daemons to start.
-#
-# Entries are in the format: <daemon>=(yes|no|priority)
-# 0, "no" = disabled
-# 1, "yes" = highest priority
-# 2 .. 10 = lower priorities
-# Read /usr/share/doc/quagga/README.Debian for details.
-#
-# Sample configurations for these daemons can be found in
-# /usr/share/doc/quagga/examples/.
-#
-# ATTENTION:
-#
-# When activation a daemon at the first time, a config file, even if it is
-# empty, has to be present *and* be owned by the user and group "quagga", else
-# the daemon will not be started by /etc/init.d/quagga. The permissions should
-# be u=rw,g=r,o=.
-# When using "vtysh" such a config file is also needed. It should be owned by
-# group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too.
-#
-# The watchquagga daemon is always started. Per default in monitoring-only but
-# that can be changed via /etc/quagga/debian.conf.
-#
-zebra=no
-bgpd=no
-ospfd=no
-ospf6d=no
-ripd=no
-ripngd=no
-isisd=no
-
+++ /dev/null
-#
-# If this option is set the /etc/init.d/quagga script automatically loads
-# the config via "vtysh -b" when the servers are started.
-# Check /etc/pam.d/quagga if you intend to use "vtysh"!
-#
-vtysh_enable=yes
-zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
-bgpd_options=" --daemon -A 127.0.0.1"
-ospfd_options=" --daemon -A 127.0.0.1"
-ospf6d_options=" --daemon -A ::1"
-ripd_options=" --daemon -A 127.0.0.1"
-ripngd_options=" --daemon -A ::1"
-isisd_options=" --daemon -A 127.0.0.1"
-pimd_options=" --daemon -A 127.0.0.1"
-
-# The list of daemons to watch is automatically generated by the init script.
-watchquagga_enable=yes
-watchquagga_options=(-adz -r /usr/sbin/servicebBquaggabBrestartbB%s -s /usr/sbin/servicebBquaggabBstartbB%s -k /usr/sbin/servicebBquaggabBstopbB%s -b bB -t 30)
+++ /dev/null
-service integrated-vtysh-config
-username cumulus nopassword
--- /dev/null
+Defaults env_keep += VTYSH_PAGER
+
+# Allow user in group frr to run vtysh show commands
+# without a password by uncommenting the "%frr" line below.
+
+# Subshell commands need to be disallowed, including
+# preventing the user passing command line args like 'start-shell'
+# Since vtysh allows minimum non-conflicting prefix'es, that means
+# anything beginning with the string "st" in any arg. That's a bit
+# restrictive.
+# Instead, use NOEXEC, to prevent any exec'ed commands.
+
+Cmnd_Alias VTY_SHOW = /usr/bin/vtysh -c show *
+# %frr ALL = (root) NOPASSWD:NOEXEC: VTY_SHOW
+
+++ /dev/null
-Defaults env_keep += VTYSH_PAGER
-
-# Allow user in group quagga to run vtysh show commands
-# without a password by uncommenting the "%quagga" line below.
-
-# Subshell commands need to be disallowed, including
-# preventing the user passing command line args like 'start-shell'
-# Since vtysh allows minimum non-conflicting prefix'es, that means
-# anything beginning with the string "st" in any arg. That's a bit
-# restrictive.
-# Instead, use NOEXEC, to prevent any exec'ed commands.
-
-Cmnd_Alias VTY_SHOW = /usr/bin/vtysh -c show *
-# %quagga ALL = (root) NOPASSWD:NOEXEC: VTY_SHOW
-
==================
Please consider setting this package "on hold" by typing
- echo "quagga hold" | dpkg --set-selections
+ echo "frr hold" | dpkg --set-selections
and verifying this using
dpkg --get-selections | grep 'hold$'
Setting a package "on hold" means that it will not automatically be upgraded.
Instead apt-get only displays a warning saying that a new version would be
-available forcing you to explicitly type "apt-get install quagga" to upgrade it.
+available forcing you to explicitly type "apt-get install frr" to upgrade it.
-* What is quagga?
+* What is frr?
=================
-http://www.quagga.net/
-> Quagga is a routing software suite, providing implementations of OSPFv2,
+http://www.freerangerouting.net/
+> Frr is a routing software suite, providing implementations of OSPFv2,
> OSPFv3, RIP v1 and v2, RIPv3 and BGPv4 for Unix platforms, particularly
-> FreeBSD and Linux and also NetBSD, to mention a few. Quagga is a fork of GNU
+> FreeBSD and Linux and also NetBSD, to mention a few. Frr is a fork of GNU
> Zebra which was developed by Kunihiro Ishiguro. Development of GNU Zebra
> slowed dramatically to the point where eventually GNU Zebra was forked into
-> Quagga.
+> Frr.
-> The Quagga tree is an attempt to provide a zebra tree with at least the
+> The Frr tree is an attempt to provide a zebra tree with at least the
> bug-fixes, which have accumulated, applied, while tracking any significant
> changes made to the zebra.org tree. Ultimately, this tree hopes to revitalise
> development of this code base.
-I packaged zebra-pj which was then renamed to quagga to get people used to it
+I packaged zebra-pj which was then renamed to frr to get people used to it
and offer Debian users the choice which versions they like to use. I hope this
-brings quagga some feedback and helps it evolving to a good successor of the
+brings frr some feedback and helps it evolving to a good successor of the
orphaned zebra.
-- Christian Hammers <ch@debian.org>, Jul/Aug 2003
* Why has SNMP support been disabled?
=====================================
-Quagga used to link against the NetSNMP libraries to provide SNMP
+Frr used to link against the NetSNMP libraries to provide SNMP
support. Those libraries sadly link against the OpenSSL libraries
to provide crypto support for SNMPv3 among others.
OpenSSL now is not compatible with the GNU GENERAL PUBLIC LICENSE (GPL)
-licence that Quagga is distributed under. For more explanation read:
+licence that Frr is distributed under. For more explanation read:
http://www.gnome.org/~markmc/openssl-and-the-gpl.html
http://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs
Updating the licence to explecitly allow linking against OpenSSL
would requite the affirmation of all people that ever contributed
-a significant part to Zebra or Quagga and thus are the collective
+a significant part to Zebra or Frr and thus are the collective
"copyright holder". That's too much work. Using a shrinked down
version of NetSNMP without OpenSSL or convincing the NetSNMP people
to change to GnuTLS are maybe good solutions but not reachable
*BUT*
It is allowed by the used licence mix that you fetch the sources and
-build Quagga yourself with SNMP with
- <remove the "grep ^smux" block at the end of debian/quagga.preinst>
+build Frr yourself with SNMP with
+ <remove the "grep ^smux" block at the end of debian/frr.preinst>
# export WANT_SNMP=1
- # apt-get -b source quagga
+ # apt-get -b source frr
Just distributing it in binary form, linked against OpenSSL, is forbidden.
* Daemon selection:
===================
-The Debian package uses /etc/quagga/daemons to tell the
+The Debian package uses /etc/frr/daemons to tell the
initscript which daemons to start. It's in the format
<daemon>=<yes|no|priority>
with no spaces (it's simply source-d into the initscript).
system's routing table if not set up properly.
Priorities were suggested by Dancer <dancer@zeor.simegen.com>.
-They're used to start the Quagga daemons in more than one step
+They're used to start the Frr daemons in more than one step
(for example start one or two at network initialization and the
-rest later). The number of Quagga daemons being small, priorities
+rest later). The number of Frr daemons being small, priorities
must be between 1 and 9, inclusive (or the initscript has to be
-changed). /etc/init.d/quagga then can be started as
+changed). /etc/init.d/frr then can be started as
-/etc/init.d/quagga <start|stop|restart|<priority>>
+/etc/init.d/frr <start|stop|restart|<priority>>
where priority 0 is the same as 'stop', priority 10 or 'start'
means 'start all'
=====================================================================
If this message occurs the receive buffer should be increased by adding the
-following to /etc/sysctl.conf and "--nl-bufsize" to /etc/quagga/debian.conf.
+following to /etc/sysctl.conf and "--nl-bufsize" to /etc/frr/debian.conf.
> net.core.rmem_default = 262144
> net.core.rmem_max = 262144
-See message #4525 from 2005-05-09 in the quagga-users mailing list.
+See message #4525 from 2005-05-09 in the frr-users mailing list.
* vtysh immediately exists:
===========================
-Check /etc/pam.d/quagga, it probably denies access to your user. The passwords
-configured in /etc/quagga/Quagga.conf are only for telnet access.
+Check /etc/pam.d/frr, it probably denies access to your user. The passwords
+configured in /etc/frr/Frr.conf are only for telnet access.
for i in debian/patches/*.diff; do echo -e "#\n# $i\n#"; patch --fuzz=3 --dry-run -p1 < $i; done
#
-# Filename transition from zebra to quagga
+# Filename transition from zebra to frr
#
Files that keep their names
/usr/bin/vtysh
Files that got an -pj suffix
- /etc/default/zebra -> /etc/quagga/debian.conf
- /etc/init.d/zebra -> /etc/init.d/quagga
- /etc/zebra/ -> /etc/quagga/
- /usr/share/doc/zebra/ -> /usr/share/doc/quagga/
- /var/log/zebra/ -> /var/log/quagga/
- /var/run/ -> /var/run/quagga/
+ /etc/default/zebra -> /etc/frr/debian.conf
+ /etc/init.d/zebra -> /etc/init.d/frr
+ /etc/zebra/ -> /etc/frr/
+ /usr/share/doc/zebra/ -> /usr/share/doc/frr/
+ /var/log/zebra/ -> /var/log/frr/
+ /var/run/ -> /var/run/frr/
Files that were moved
- /usr/sbin/* -> /usr/lib/quagga/
+ /usr/sbin/* -> /usr/lib/frr/
+frr (2.0) Released; urgency=medium
+
+ * Switchover to FRR
+
quagga (0.99.24+cl3u5) RELEASED; urgency=medium
* Closes: CM-12846 - Resolve Memory leaks in 'show ip bgp neighbor json'
-Source: quagga
+Source: frr
Section: net
Priority: optional
Maintainer: Christian Hammers <ch@debian.org>
Uploaders: Florian Weimer <fw@debian.org>
Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), imagemagick, ghostscript, groff, po-debconf, autotools-dev, hardening-wrapper, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson0, libjson0-dev, dh-systemd, libsystemd-dev, python-ipaddr, bison, flex
Standards-Version: 3.9.6
-Homepage: http://www.quagga.net/
+Homepage: http://www.frr.net/
XS-Testsuite: autopkgtest
-Package: quagga
+Package: frr
Architecture: any
Depends: ${shlibs:Depends}, logrotate (>= 3.2-11), iproute, ${misc:Depends}
Pre-Depends: adduser
Replaces: zebra, zebra-pj
Suggests: snmpd
Description: BGP/OSPF/RIP routing daemon
- GNU Quagga is free software which manages TCP/IP based routing protocols.
+ Frr is free software which manages TCP/IP based routing protocols.
It supports BGP4, BGP4+, OSPFv2, OSPFv3, IS-IS, RIPv1, RIPv2, and RIPng as
well as the IPv6 versions of these.
.
- As the precessor Zebra has been considered orphaned, the Quagga project
- has been formed by members of the zebra mailing list and the former
- zebra-pj project to continue developing.
- .
- Quagga uses threading if the kernel supports it, but can also run on
+ Frr uses threading if the kernel supports it, but can also run on
kernels that do not support threading. Each protocol has its own daemon.
.
It is more than a routed replacement, it can be used as a Route Server and
a Route Reflector.
-Package: quagga-dbg
+Package: frr-dbg
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, quagga (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, frr (= ${binary:Version})
Priority: extra
Section: debug
Description: BGP/OSPF/RIP routing daemon (debug symbols)
This package provides debugging symbols for all binary packages built from
- quagga source package. It's highly recommended to have this package installed
- before reporting any Quagga crashes to either Quagga developers or Debian
+ frr source package. It's highly recommended to have this package installed
+ before reporting any Frr crashes to either Frr developers or Debian
package maintainers.
-Package: quagga-doc
+Package: frr-doc
Section: net
Architecture: all
Depends: ${misc:Depends}
-Suggests: quagga
-Description: documentation files for quagga
- This package includes info files for quagga, a free software which manages
+Suggests: frr
+Description: documentation files for frr
+ This package includes info files for frr, a free software which manages
TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3,
IS-IS, RIPv1, RIPv2, and RIPng as well as the IPv6 versions of these.
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: Quagga
-Upstream-Contact: maintainers@quagga.net, security@quagga.net
-Source: http://www.quagga.net/
+Upstream-Name: Frr
+Upstream-Contact: maintainers@freerangerouting.net, security@freerangerouting.net
+Source: http://www.freerangerouting.net/
Files: *
Copyright: 1996-2003 by the original Zebra authors:
--- /dev/null
+AUTHORS
+NEWS
+README
+REPORTING-BUGS
+doc/BGP-TypeCode
+doc/draft-zebra-00.txt
+doc/mpls/
+bgpd/BGP4-MIB.txt
--- /dev/null
+doc/frr.info*
--- /dev/null
+usr/share/info
--- /dev/null
+frr-doc: wrong-section-according-to-package-name frr-doc => doc
--- /dev/null
+# Create the /run/frr directory at boot or from systemd-tmpfiles on install
+d /run/frr 0755 frr frr
--- /dev/null
+#!/bin/bash -e
+
+. /usr/share/debconf/confmodule
+
--- /dev/null
+etc/logrotate.d/
+etc/frr/
+usr/share/doc/frr/
+usr/share/doc/frr/examples/
+usr/share/lintian/overrides/
+usr/share/snmp/mibs/
+var/log/frr/
--- /dev/null
+tools
+debian/README.Debian
--- /dev/null
+etc/frr/
+usr/bin/vtysh
+usr/include/frr/
+usr/lib/
+tools/frr-reload.py usr/lib/frr/
+tools/frr usr/lib/frr
+usr/share/doc/frr/
+usr/share/man/man1/vtysh.1
+usr/share/man/man1/frr.1
+usr/share/man/man8
+usr/share/man/man8/bgpd.8
+usr/share/man/man8/ospf6d.8
+usr/share/man/man8/ospfd.8
+usr/share/man/man8/ripd.8
+usr/share/man/man8/ripngd.8
+usr/share/man/man8/zebra.8
+usr/share/man/man8/isisd.8
+usr/share/man/man8/watchfrr.8
+usr/share/snmp/mibs/
+cumulus/etc/* etc/
+tools/*.service lib/systemd/system
+debian/frr.conf usr/lib/tmpfiles.d
--- /dev/null
+frr: non-dev-pkg-with-shlib-symlink usr/lib/libospfapiclient.so.0.0.0 usr/lib/libospfapiclient.so
+frr: non-dev-pkg-with-shlib-symlink usr/lib/libospf.so.0.0.0 usr/lib/libospf.so
+frr: non-dev-pkg-with-shlib-symlink usr/lib/libzebra.so.0.0.0 usr/lib/libzebra.so
+frr: package-name-doesnt-match-sonames libospf0 libospfapiclient0 libzebra0
--- /dev/null
+/var/log/frr/*.log {
+ size 500k
+ sharedscripts
+ missingok
+ compress
+ rotate 14
+ create 640 frr frrvty
+
+ postrotate
+ for i in zebra bgpd ripd ospfd ripngd ospf6d isisd pimd; do
+ if [ -e /var/run/frr/$i.pid ] ; then
+ kill -USR1 `cat /var/run/frr/$i.pid`
+ fi
+
+ done
+ endscript
+}
--- /dev/null
+doc/bgpd.8
+doc/ospf6d.8
+doc/ospfd.8
+doc/ripd.8
+doc/ripngd.8
+doc/vtysh.1
+doc/zebra.8
+doc/isisd.8
+doc/watchfrr.8
--- /dev/null
+# Any user may call vtysh but only those belonging to the group frrvty can
+# actually connect to the socket and use the program.
+auth sufficient pam_permit.so
--- /dev/null
+#!/bin/bash -e
+
+######################
+PASSWDFILE=/etc/passwd
+GROUPFILE=/etc/group
+
+frruid=`egrep "^frr:" $PASSWDFILE | awk -F ":" '{ print $3 }'`
+frrgid=`egrep "^frr:" $GROUPFILE | awk -F ":" '{ print $3 }'`
+frrvtygid=`egrep "^frrvty:" $GROUPFILE | awk -F ":" '{ print $3 }'`
+
+[ -n ${frruid} ] || (echo "No uid for frr in ${PASSWDFILE}" && /bin/false)
+[ -n ${frrgid} ] || (echo "No gid for frr in ${GROUPFILE}" && /bin/false)
+[ -n ${frrVTYgid} ] || (echo "No gid for frrvty in ${GROUPFILE}" && /bin/false)
+
+chown -R ${frruid}:${frrgid} /etc/frr
+touch /etc/frr/vtysh.conf
+chgrp ${frrvtygid} /etc/frr/vtysh*
+chmod 440 /etc/sudoers.d/frr_sudoers
+chmod 644 /etc/frr/*
+
+ENVIRONMENTFILE=/etc/environment
+if ! grep --quiet VTYSH_PAGER=/bin/cat ${ENVIRONMENTFILE}; then
+ echo "VTYSH_PAGER=/bin/cat" >> ${ENVIRONMENTFILE}
+fi
+##################################################
+
+if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
+${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
+
+# This is most likely due to the answer "no" to the "really stop the server"
+# question in the prerm script.
+if [ "$1" = "abort-upgrade" ]; then
+ exit 0
+fi
+
+. /usr/share/debconf/confmodule
+
+db_stop
+
+#DEBHELPER#
+
--- /dev/null
+#!/bin/bash -e
+
+if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
+${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
+# set -u not because of debhelper
+
+if [ "$1" = "purge" ]; then
+ rm -rf /etc/frr /var/run/frr /var/log/frr
+ userdel frr >/dev/null 2>&1 || true
+fi
+
+#DEBHELPER#
--- /dev/null
+#!/bin/bash
+
+if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
+${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
+set -e
+set -u
+
+# creating frrvty group if it isn't already there
+if ! getent group frrvty >/dev/null; then
+ addgroup --system frrvty >/dev/null
+fi
+
+# creating frr group if it isn't already there
+if ! getent group frr >/dev/null; then
+ addgroup --system frr >/dev/null
+fi
+
+# creating frr user if he isn't already there
+if ! getent passwd frr >/dev/null; then
+ adduser \
+ --system \
+ --ingroup frr \
+ --home /var/run/frr/ \
+ --gecos "Frr routing suite" \
+ --shell /bin/false \
+ frr >/dev/null
+fi
+
+# We may be installing over an older version of
+# frr and as such we need to intelligently
+# check to see if the frr user is in the frrvty
+# group.
+if ! /usr/bin/id frr | grep &>/dev/null 'frrvty'; then
+ usermod -a -G frrvty frr >/dev/null
+fi
+
+# Do not change permissions when upgrading as it would violate policy.
+if [ "$1" = "install" ]; then
+ # Logfiles are group readable in case users were put into the frr group.
+ d=/var/log/frr/
+ mkdir -p $d
+ chown -R frr:frr $d
+ chmod u=rwx,go=rx $d
+ find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,g=r,o=
+
+ # Strict permissions for the sockets.
+ d=/var/run/frr/
+ mkdir -p $d
+ chown -R frr:frr $d
+ chmod u=rwx,go=rx $d
+ find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,go=
+
+ # Config files. Vtysh does not have access to the individual daemons config file
+ d=/etc/frr/
+ mkdir -p $d
+ chown frr:frrvty $d
+ chmod ug=rwx,o=rx $d
+ find $d -type f -print0 | xargs -0 --no-run-if-empty chown frr:frr
+ find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,g=r,o=
+
+ # Exceptions for vtysh.
+ f=$d/vtysh.conf
+ if [ -f $f ]; then
+ chown frr:frrvty $f
+ chmod u=rw,g=r,o= $f
+ fi
+
+ # Exceptions for vtysh.
+ f=$d/Frr.conf
+ if [ -f $d/Zebra.conf ]; then
+ mv $d/Zebra.conf $f
+ fi
+ if [ -f $f ]; then
+ chown frr:frrvty $f
+ chmod u=rw,g=r,o= $f
+ fi
+fi
+
+#DEBHELPER#
--- /dev/null
+#!/bin/bash -e
+
+. /usr/share/debconf/confmodule
+
+if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
+${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
+
+# prerm remove
+# old-prerm upgrade new-version
+# new-prerm failed-upgrade old-version
+# conflictor's-prerm remove in-favour package new-version
+# deconfigured's-prerm deconfigure in-favour package-being-installed version removing conflicting-package
+case $1 in
+ remove|upgrade)
+ ;;
+
+ failed-upgrade)
+ # If frr/really_stop was negated then this script exits with return
+ # code 1 and is called again with "failed-upgrade". Well, exit again.
+ exit 1
+ ;;
+
+esac
+
+#DEBHELPER#
+++ /dev/null
-AUTHORS
-NEWS
-README
-REPORTING-BUGS
-doc/BGP-TypeCode
-doc/draft-zebra-00.txt
-doc/mpls/
-bgpd/BGP4-MIB.txt
+++ /dev/null
-doc/quagga.info*
+++ /dev/null
-usr/share/info
+++ /dev/null
-quagga-doc: wrong-section-according-to-package-name quagga-doc => doc
+++ /dev/null
-# Create the /run/quagga directory at boot or from systemd-tmpfiles on install
-d /run/quagga 0755 quagga quagga
+++ /dev/null
-#!/bin/bash -e
-
-. /usr/share/debconf/confmodule
-
+++ /dev/null
-etc/logrotate.d/
-etc/quagga/
-usr/share/doc/quagga/
-usr/share/doc/quagga/examples/
-usr/share/lintian/overrides/
-usr/share/snmp/mibs/
-var/log/quagga/
+++ /dev/null
-tools
-debian/README.Debian
+++ /dev/null
-etc/quagga/
-usr/bin/vtysh
-usr/include/quagga/
-usr/lib/
-tools/quagga-reload.py usr/lib/quagga/
-tools/quagga usr/lib/quagga
-usr/share/doc/quagga/
-usr/share/man/man1/vtysh.1
-usr/share/man/man1/quagga.1
-usr/share/man/man8
-usr/share/man/man8/bgpd.8
-usr/share/man/man8/ospf6d.8
-usr/share/man/man8/ospfd.8
-usr/share/man/man8/ripd.8
-usr/share/man/man8/ripngd.8
-usr/share/man/man8/zebra.8
-usr/share/man/man8/isisd.8
-usr/share/man/man8/watchquagga.8
-usr/share/snmp/mibs/
-cumulus/etc/* etc/
-tools/*.service lib/systemd/system
-debian/quagga.conf usr/lib/tmpfiles.d
+++ /dev/null
-quagga: non-dev-pkg-with-shlib-symlink usr/lib/libospfapiclient.so.0.0.0 usr/lib/libospfapiclient.so
-quagga: non-dev-pkg-with-shlib-symlink usr/lib/libospf.so.0.0.0 usr/lib/libospf.so
-quagga: non-dev-pkg-with-shlib-symlink usr/lib/libzebra.so.0.0.0 usr/lib/libzebra.so
-quagga: package-name-doesnt-match-sonames libospf0 libospfapiclient0 libzebra0
+++ /dev/null
-/var/log/quagga/*.log {
- size 500k
- sharedscripts
- missingok
- compress
- rotate 14
- create 640 quagga quaggavty
-
- postrotate
- for i in zebra bgpd ripd ospfd ripngd ospf6d isisd pimd; do
- if [ -e /var/run/quagga/$i.pid ] ; then
- kill -USR1 `cat /var/run/quagga/$i.pid`
- fi
-
- done
- endscript
-}
+++ /dev/null
-doc/bgpd.8
-doc/ospf6d.8
-doc/ospfd.8
-doc/ripd.8
-doc/ripngd.8
-doc/vtysh.1
-doc/zebra.8
-doc/isisd.8
-doc/watchquagga.8
+++ /dev/null
-# Any user may call vtysh but only those belonging to the group quaggavty can
-# actually connect to the socket and use the program.
-auth sufficient pam_permit.so
+++ /dev/null
-#!/bin/bash -e
-
-######################
-PASSWDFILE=/etc/passwd
-GROUPFILE=/etc/group
-
-quaggauid=`egrep "^quagga:" $PASSWDFILE | awk -F ":" '{ print $3 }'`
-quaggagid=`egrep "^quagga:" $GROUPFILE | awk -F ":" '{ print $3 }'`
-quaggavtygid=`egrep "^quaggavty:" $GROUPFILE | awk -F ":" '{ print $3 }'`
-
-[ -n ${quaggauid} ] || (echo "No uid for quagga in ${PASSWDFILE}" && /bin/false)
-[ -n ${quaggagid} ] || (echo "No gid for quagga in ${GROUPFILE}" && /bin/false)
-[ -n ${quaggaVTYgid} ] || (echo "No gid for quaggavty in ${GROUPFILE}" && /bin/false)
-
-chown -R ${quaggauid}:${quaggagid} /etc/quagga
-touch /etc/quagga/vtysh.conf
-chgrp ${quaggavtygid} /etc/quagga/vtysh*
-chmod 440 /etc/sudoers.d/quagga_sudoers
-chmod 644 /etc/quagga/*
-
-ENVIRONMENTFILE=/etc/environment
-if ! grep --quiet VTYSH_PAGER=/bin/cat ${ENVIRONMENTFILE}; then
- echo "VTYSH_PAGER=/bin/cat" >> ${ENVIRONMENTFILE}
-fi
-##################################################
-
-if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
-${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
-
-# This is most likely due to the answer "no" to the "really stop the server"
-# question in the prerm script.
-if [ "$1" = "abort-upgrade" ]; then
- exit 0
-fi
-
-. /usr/share/debconf/confmodule
-
-db_stop
-
-#DEBHELPER#
-
+++ /dev/null
-#!/bin/bash -e
-
-if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
-${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
-# set -u not because of debhelper
-
-if [ "$1" = "purge" ]; then
- rm -rf /etc/quagga /var/run/quagga /var/log/quagga
- userdel quagga >/dev/null 2>&1 || true
-fi
-
-#DEBHELPER#
+++ /dev/null
-#!/bin/bash
-
-if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
-${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
-set -e
-set -u
-
-# creating quaggavty group if it isn't already there
-if ! getent group quaggavty >/dev/null; then
- addgroup --system quaggavty >/dev/null
-fi
-
-# creating quagga group if it isn't already there
-if ! getent group quagga >/dev/null; then
- addgroup --system quagga >/dev/null
-fi
-
-# creating quagga user if he isn't already there
-if ! getent passwd quagga >/dev/null; then
- adduser \
- --system \
- --ingroup quagga \
- --home /var/run/quagga/ \
- --gecos "Quagga routing suite" \
- --shell /bin/false \
- quagga >/dev/null
-fi
-
-# We may be installing over an older version of
-# quagga and as such we need to intelligently
-# check to see if the quagga user is in the quaggavty
-# group.
-if ! /usr/bin/id quagga | grep &>/dev/null 'quaggavty'; then
- usermod -a -G quaggavty quagga >/dev/null
-fi
-
-# Do not change permissions when upgrading as it would violate policy.
-if [ "$1" = "install" ]; then
- # Logfiles are group readable in case users were put into the quagga group.
- d=/var/log/quagga/
- mkdir -p $d
- chown -R quagga:quagga $d
- chmod u=rwx,go=rx $d
- find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,g=r,o=
-
- # Strict permissions for the sockets.
- d=/var/run/quagga/
- mkdir -p $d
- chown -R quagga:quagga $d
- chmod u=rwx,go=rx $d
- find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,go=
-
- # Config files. Vtysh does not have access to the individual daemons config file
- d=/etc/quagga/
- mkdir -p $d
- chown quagga:quaggavty $d
- chmod ug=rwx,o=rx $d
- find $d -type f -print0 | xargs -0 --no-run-if-empty chown quagga:quagga
- find $d -type f -print0 | xargs -0 --no-run-if-empty chmod u=rw,g=r,o=
-
- # Exceptions for vtysh.
- f=$d/vtysh.conf
- if [ -f $f ]; then
- chown quagga:quaggavty $f
- chmod u=rw,g=r,o= $f
- fi
-
- # Exceptions for vtysh.
- f=$d/Quagga.conf
- if [ -f $d/Zebra.conf ]; then
- mv $d/Zebra.conf $f
- fi
- if [ -f $f ]; then
- chown quagga:quaggavty $f
- chmod u=rw,g=r,o= $f
- fi
-fi
-
-#DEBHELPER#
+++ /dev/null
-#!/bin/bash -e
-
-. /usr/share/debconf/confmodule
-
-if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
-${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"}
-
-# prerm remove
-# old-prerm upgrade new-version
-# new-prerm failed-upgrade old-version
-# conflictor's-prerm remove in-favour package new-version
-# deconfigured's-prerm deconfigure in-favour package-being-installed version removing conflicting-package
-case $1 in
- remove|upgrade)
- ;;
-
- failed-upgrade)
- # If quagga/really_stop was negated then this script exits with return
- # code 1 and is called again with "failed-upgrade". Well, exit again.
- exit 1
- ;;
-
-esac
-
-#DEBHELPER#
endif
%:
- dh $@ --with=systemd,autoreconf --parallel --dbg-package=quagga-dbg --list-missing
+ dh $@ --with=systemd,autoreconf --parallel --dbg-package=frr-dbg --list-missing
override_dh_auto_configure:
- # Quagga needs /proc to check some BSD vs Linux specific stuff.
+ # Frr needs /proc to check some BSD vs Linux specific stuff.
# Else it fails with an obscure error message pointing out that
# IPCTL_FORWARDING is an undefined symbol which is not very helpful.
@if ! [ -d /proc/1 ]; then \
if ! [ -e config.status ]; then \
dh_auto_configure -- \
- --enable-exampledir=/usr/share/doc/quagga/examples/ \
- --localstatedir=/var/run/quagga \
- --sbindir=/usr/lib/quagga \
- --sysconfdir=/etc/quagga \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
$(USE_SNMP) \
--enable-ospfapi=yes \
--enable-vtysh=yes \
--enable-isisd=yes \
--enable-multipath=256 \
- --enable-user=quagga \
- --enable-group=quagga \
- --enable-vty-group=quaggavty \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
--enable-configfile-mask=0640 \
--enable-logfile-mask=0640 \
--enable-werror \
--enable-systemd=yes \
--enable-poll=yes \
--enable-cumulus=yes \
- --enable-pimd=no \
+ --enable-pimd=yes \
--enable-dependency-tracking \
--enable-bgp-vnc=no; \
fi
# doc/ is a bit crazy
ifeq ($(GENERATE_PDF), 1)
- dh_auto_build -- -C doc quagga.pdf || true # pdfetex fails with exit code 1 but still produces a good looking .pdf
+ dh_auto_build -- -C doc frr.pdf || true # pdfetex fails with exit code 1 but still produces a good looking .pdf
endif
- rm -vf doc/quagga.info
- dh_auto_build -- -C doc quagga.info
- rm -vf doc/quagga.info.html*
+ rm -vf doc/frr.info
+ dh_auto_build -- -C doc frr.info
+ rm -vf doc/frr.info.html*
override_dh_auto_test:
rm -f debian/tmp/usr/share/info/dir*
# install config files
- mkdir -p debian/tmp/etc/quagga/
- perl -pi -e 's#^!log file #!log file /var/log/quagga/#' debian/tmp/usr/share/doc/quagga/examples/*sample*
+ mkdir -p debian/tmp/etc/frr/
+ perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
- # installing the Quagga specific SNMP MIB
+ # installing the Frr specific SNMP MIB
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
# cleaning .la files
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
override_dh_systemd_start:
- dh_systemd_start quagga.service
+ dh_systemd_start frr.service
override_dh_systemd_enable:
- dh_systemd_enable quagga.service
+ dh_systemd_enable frr.service
Tests: daemons
-Depends: quagga
+Depends: frr
Restrictions: needs-root
#!/bin/bash
#---------------
-# Testing quagga
+# Testing frr
#---------------
set -e
# modify config file to enable all daemons and copy config files
-CONFIG_FILE=/etc/quagga/daemons
+CONFIG_FILE=/etc/frr/daemons
DAEMONS=("zebra" "bgpd" "ospfd" "ospf6d" "ripd" "ripngd" "isisd" "pimd")
for daemon in "${DAEMONS[@]}"
do
sed -i -e "s/${daemon}=no/${daemon}=yes/g" $CONFIG_FILE
- cp /usr/share/doc/quagga/examples/${daemon}.conf.sample /etc/quagga/${daemon}.conf
+ cp /usr/share/doc/frr/examples/${daemon}.conf.sample /etc/frr/${daemon}.conf
done
-# reload quagga
-/etc/init.d/quagga restart > /dev/null 2>&1
+# reload frr
+/etc/init.d/frr restart > /dev/null 2>&1
# check daemons
for daemon in "${DAEMONS[@]}"
# Site Directory Pattern Version Script
version=3
opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|b|a)[\-\.]?\d*)$/$1~$2/ \
- http://download.savannah.gnu.org/releases/quagga/quagga-(\d.*)\.(?:tgz|tar\.(?:gz|bz2|xz))
+ http://download.savannah.gnu.org/releases/frr/quagga-(\d.*)\.(?:tgz|tar\.(?:gz|bz2|xz))
# Bart Martens <bartm@debian.org> Fri, 25 Jan 2013 06:38:53 +0000
--- /dev/null
+check process watchfrr with pidfile /var/run/frr/watchfrr.pid
+ start program = "/etc/init.d/frr start watchfrr" with timeout 120 seconds
+ stop program = "/etc/init.d/frr stop watchfrr"
+ if 3 restarts within 10 cycles then timeout
+++ /dev/null
-check process watchquagga with pidfile /var/run/quagga/watchquagga.pid
- start program = "/etc/init.d/quagga start watchquagga" with timeout 120 seconds
- stop program = "/etc/init.d/quagga stop watchquagga"
- if 3 restarts within 10 cycles then timeout
Makefile.in
mdate-sh
draft-zebra-00.txt
-quagga.info-*
+frr.info-*
zebra.html
defines.texi
version.texi
texinfo.tex
-quagga.html
-quagga.info
+frr.html
+frr.info
*.pdf
*.eps
-quagga.ps
-quagga.dvi
+frr.ps
+frr.dvi
stamp-vti
.nfs*
*.aux
*.toc
*.tp
*.vr
+*.8
+*.1
.arch-inventory
.arch-ids
*~
#
# Here we use 'convert' from the well known 'ImageMagick' package
# to do conversion from png to eps/pdf for figures.
-# PDF form is required for quagga.pdf, using PDFTex at least.
+# PDF form is required for frr.pdf, using PDFTex at least.
#
# TeX implementation, which we depend on already anyway.
#
EPSTOPDF = epstopdf
VNCFIGURES_PNG =
-VNCFIGURES_DIA = -vnc-mesh -vnc-quagga-route-reflector \
+VNCFIGURES_DIA = -vnc-mesh -vnc-frr-route-reflector \
-vnc-commercial-route-reflector -vnc-redundant-route-reflectors \
-vnc-gw -vnc-gw-rr
figures_txt = $(figures_names_parts:%=fig%.txt)
# rather twisted logic because we have to build PDFs of the EPS figures for
-# PDFTex and yet build one PDF, quagga.pdf, from texi source. Which means we
+# PDFTex and yet build one PDF, frr.pdf, from texi source. Which means we
# cant rely on a single automatic rule for *.pdf, eg the one automatically
# provided by automake. If you are an automake wizard, please feel free to
# compact it somehow.
# Built from defines.texi.in
BUILT_SOURCES = defines.texi
-info_TEXINFOS = quagga.texi
+info_TEXINFOS = frr.texi
-# Have to manually specify the quagga.pdf rule in order to allow
+# Have to manually specify the frr.pdf rule in order to allow
# us to have a generic automatic .pdf rule to build the figure sources
# because it cant just work from the png's directly it seems - contrary
# to the documentation...
-quagga.pdf: $(info_TEXINFOS) $(figures_pdf) $(quagga_TEXINFOS)
+frr.pdf: $(info_TEXINFOS) $(figures_pdf) $(frr_TEXINFOS)
$(TEXI2PDF) -o "$@" $< || true
-quagga_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
+frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
vnc.texi \
install.texi ipv6.texi kernel.texi main.texi ospf6d.texi ospfd.texi \
overview.texi protocol.texi ripd.texi ripngd.texi routemap.texi \
.dia.png:
$(DIATOPNG) "$@" $<
-man_MANS = quagga.1
+man_MANS = frr.1
if PIMD
man_MANS += pimd.8
man_MANS += vtysh.1
endif
-if WATCHQUAGGA
-man_MANS += watchquagga.8
+if WATCHFRR
+man_MANS += watchfrr.8
endif
if ZEBRA
endif
EXTRA_DIST = BGP-TypeCode draft-zebra-00.ms draft-zebra-00.txt \
- bgpd.8 isisd.8 ospf6d.8 ospfclient.8 ospfd.8 ldpd.8 ripd.8 \
- ripngd.8 pimd.8 vtysh.1 watchquagga.8 zebra.8 quagga.1 \
+ \
+ bgpd.8.in \
+ isisd.8.in \
+ ospf6d.8.in \
+ ospfclient.8.in \
+ ospfd.8.in \
+ ldpd.8.in \
+ ripd.8.in \
+ ripngd.8.in \
+ pimd.8.in \
+ vtysh.1.in \
+ watchfrr.8.in \
+ zebra.8.in \
+ frr.1.in \
+ \
mpls/ChangeLog.opaque.txt mpls/cli_summary.txt \
mpls/opaque_lsa.txt mpls/ospfd.conf \
$(figures_sources) $(figures_png) $(figures_txt)
If you want to log into a file, please specify @code{filename} as
in this example:
@example
-log file /var/log/quagga/bgpd.log informational
+log file /var/log/frr/bgpd.log informational
@end example
If the optional second argument specifying the
logging level is not present, the default logging level (typically debugging,
Note: if you do not configure any file logging, and a daemon crashes due
to a signal or an assertion failure, it will attempt to save the crash
-information in a file named /var/tmp/quagga.<daemon name>.crashlog.
+information in a file named /var/tmp/frr.<daemon name>.crashlog.
For security reasons, this will not happen if the file exists already, so
it is important to delete the file after reporting the crash information.
@end deffn
+++ /dev/null
-.TH BGPD 8 "25 November 2004" "Quagga BGPD daemon" "Version 0.97.3"
-.SH NAME
-bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with Quagga routing
-software
-
-.SH SYNOPSIS
-.B bgpd
-[
-.B \-dhrSv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-p
-.I bgp-port-number
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B bgpd
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B bgpd
-command:
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/bgpd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When bgpd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart bgpd. The likely default is \fB\fI/var/run/bgpd.pid\fR.
-.TP
-\fB\-p\fR, \fB\-\-bgp_port \fR\fIbgp-port-number\fR
-Set the port that bgpd will listen to for bgp data.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the bgpd VTY will listen on. This defaults to
-2605, as specified in \fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the bgpd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-r\fR, \fB\-\-retain\fR
-When the program terminates, retain routes added by \fBbgpd\fR.
-.TP
-\fB\-S\fR, \fB\-\-skip_runas\fR
-Skip setting the process effective user and group.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/bgpd
-The default location of the
-.B bgpd
-binary.
-.TP
-.BI /etc/quagga/bgpd.conf
-The default location of the
-.B bgpd
-config file.
-.TP
-.BI $(PWD)/bgpd.log
-If the
-.B bgpd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBbgpd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The bgpd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBbgpd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B bgpd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH BGPD 8 "25 November 2004" "@PACKAGE_FULLNAME@ BGPD daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@.
+
+.SH SYNOPSIS
+.B bgpd
+[
+.B \-dhrSv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-p
+.I bgp-port-number
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B bgpd
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B bgpd
+command:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/bgpd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When bgpd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart bgpd. The default is \fB\fI@CFG_STATE@/bgpd.pid\fR.
+.TP
+\fB\-p\fR, \fB\-\-bgp_port \fR\fIbgp-port-number\fR
+Set the port that bgpd will listen to for bgp data.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the bgpd VTY will listen on. This defaults to
+2605, as specified in \fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the bgpd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-r\fR, \fB\-\-retain\fR
+When the program terminates, retain routes added by \fBbgpd\fR.
+.TP
+\fB\-S\fR, \fB\-\-skip_runas\fR
+Skip setting the process effective user and group.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/bgpd
+The default location of the
+.B bgpd
+binary.
+.TP
+.BI @CFG_SYSCONF@/bgpd.conf
+The default location of the
+.B bgpd
+config file.
+.TP
+.BI $(PWD)/bgpd.log
+If the
+.B bgpd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBbgpd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The bgpd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBbgpd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B bgpd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
@c -*-texinfo-*-
-@c This is part of the Quagga Manual.
+@c This is part of the Frr Manual.
@c @value{COPYRIGHT_STR}
@c Portions:
@c Copyright @copyright{} 2015 Hewlett Packard Enterprise Development LP
-@c See file quagga.texi for copying conditions.
+@c See file frr.texi for copying conditions.
@node BGP
@chapter BGP
@node BGP decision process
@subsection BGP decision process
-The decision process Quagga BGP uses to select routes is as follows:
+The decision process Frr BGP uses to select routes is as follows:
@table @asis
@item 1. Weight check
cause subtle convergence problems in BGP. These properties and problems
have proven to be hard to understand, at least historically, and may still
not be widely understood. The following attempts to collect together and
-present what is known about MED, to help operators and Quagga users in
+present what is known about MED, to help operators and Frr users in
designing and configuring their networks.
The BGP @acronym{MED, Multi_Exit_Discriminator} attribute is intended to
administrators, with different frames of reference.
The default behaviour of BGP therefore is to not compare MED values across
-routes received from different neighbouring ASes. In Quagga this is done by
+routes received from different neighbouring ASes. In Frr this is done by
comparing the neighbouring, left-most AS in the received AS_PATHs of the
routes and only comparing MED if those are the same.
A deterministic order of evaluation tends to imply an additional overhead of
sorting over any set of n routes to a destination. The implementation of
-deterministic MED in Quagga scales significantly worse than most sorting
+deterministic MED in Frr scales significantly worse than most sorting
algorithms at present, with the number of paths to a given destination.
That number is often low enough to not cause any issues, but where there are
many paths, the deterministic comparison may quickly become increasingly
This particular type of oscillation in full-mesh iBGP topologies can be
avoided by speakers preferring already selected, external routes rather than
choosing to update to new a route based on a post-MED metric (e.g.
-router-ID), at the cost of a non-deterministic selection process. Quagga
+router-ID), at the cost of a non-deterministic selection process. Frr
implements this, as do many other implementations, so long as it is not
overridden by setting @ref{bgp bestpath compare-routerid}, and see also
@ref{BGP decision process}, .
in.
Setting this option will have a performance cost that may be noticeable when
-there are many routes for each destination. Currently in Quagga it is
+there are many routes for each destination. Currently in Frr it is
implemented in a way that scales poorly as the number of routes per
destination increases.
Negotiation packets (at least not unless other optional BGP features
require capability negotation).
-By default, Quagga will bring up peering with minimal common capability
+By default, Frr will bring up peering with minimal common capability
for the both sides. For example, local router has unicast and
multicast capabilitie and remote router has unicast capability. In
this case, the local router will establish the connection with unicast
-only capability. When there are no common capabilities, Quagga sends
+only capability. When there are no common capabilities, Frr sends
Unsupported Capability error and then resets the connection.
If you want to completely match capabilities with remote peer. Please
``network'' and ``aggregate-address'' argument is displayed as
``A.B.C.D M.M.M.M''
-Quagga: network 10.0.0.0/8
+Frr: network 10.0.0.0/8
Cisco: network 10.0.0.0
-Quagga: aggregate-address 192.168.0.0/24
+Frr: aggregate-address 192.168.0.0/24
Cisco: aggregate-address 192.168.0.0 255.255.255.0
Community attribute handling is also different. If there is no
@end example
@deffn {Command} {bgp config-type zebra} {}
-Quagga style BGP configuration. This is default.
+Frr style BGP configuration. This is default.
@end deffn
@node BGP instance and view
@set COPYRIGHT_STR Copyright @copyright{} @value{COPYRIGHT_YEAR} @value{AUTHORS}
@c These may vary with installation environment.
-@set INSTALL_PREFIX_ETC /etc/quagga
-@set INSTALL_PREFIX_SBIN /usr/sbin
-@set INSTALL_PREFIX_STATE /var/run/quagga
+@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
+@set INSTALL_PREFIX_SBIN @CFG_SBIN@
+@set INSTALL_PREFIX_STATE @CFG_STATE@
+@set INSTALL_USER @enable_user@
+@set INSTALL_GROUP @enable_group@
@set INSTALL_VTY_GROUP @enable_vty_group@
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+ <dia:diagramdata>
+ <dia:attribute name="background">
+ <dia:color val="#ffffff"/>
+ </dia:attribute>
+ <dia:attribute name="pagebreak">
+ <dia:color val="#000099"/>
+ </dia:attribute>
+ <dia:attribute name="paper">
+ <dia:composite type="paper">
+ <dia:attribute name="name">
+ <dia:string>#Letter#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="tmargin">
+ <dia:real val="2.5399999618530273"/>
+ </dia:attribute>
+ <dia:attribute name="bmargin">
+ <dia:real val="2.5399999618530273"/>
+ </dia:attribute>
+ <dia:attribute name="lmargin">
+ <dia:real val="2.5399999618530273"/>
+ </dia:attribute>
+ <dia:attribute name="rmargin">
+ <dia:real val="2.5399999618530273"/>
+ </dia:attribute>
+ <dia:attribute name="is_portrait">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ <dia:attribute name="scaling">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="fitto">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="grid">
+ <dia:composite type="grid">
+ <dia:attribute name="width_x">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="width_y">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="visible_x">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="visible_y">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:composite type="color"/>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#d8e5e5"/>
+ </dia:attribute>
+ <dia:attribute name="guides">
+ <dia:composite type="guides">
+ <dia:attribute name="hguides"/>
+ <dia:attribute name="vguides"/>
+ </dia:composite>
+ </dia:attribute>
+ </dia:diagramdata>
+ <dia:layer name="Background" visible="true" active="true">
+ <dia:object type="Standard - Box" version="0" id="O0">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,39.145"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="57.1801,39.095;64.0901,42.445"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="57.2301,39.145"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O1">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,34.2475"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="57.1801,34.1975;64.0901,37.5475"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="57.2301,34.2475"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O2">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,29.35"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="57.1801,29.3;64.0901,32.65"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="57.2301,29.35"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O3">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2.1126,39.295"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.0626,39.245;8.9726,42.595"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="2.1126,39.295"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O4">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2.1126,34.3975"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.0626,34.3475;8.9726,37.6975"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="2.1126,34.3975"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O5">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2.1126,29.5"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.0626,29.45;8.9726,32.8"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="2.1126,29.5"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="6.8100000000000023"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.2500000000000018"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O6">
+ <dia:attribute name="obj_pos">
+ <dia:point val="22.5347,32.178"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="22.4642,23.359;30.091,32.2485"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="22.5347,32.178"/>
+ <dia:point val="30.0205,23.4295"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O7">
+ <dia:attribute name="obj_pos">
+ <dia:point val="43.1205,32.4705"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="36.8099,23.3599;43.1901,32.5401"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="43.1205,32.4705"/>
+ <dia:point val="36.8795,23.4295"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O8">
+ <dia:attribute name="obj_pos">
+ <dia:point val="16.5501,5.5"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="16.5501,4.905;16.5501,5.6525"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="16.5501,5.5"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O9">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5.5176,31.125"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="3.29385,30.5113;7.76004,32.1149"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 4
+VN 172.16.4.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="5.5176,31.125"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O5" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O10">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5.5176,36.0225"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.88385,35.4088;8.17004,37.0124"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 5
+VN 172.16.130.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="5.5176,36.0225"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O4" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O11">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5.5176,40.92"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.8826,40.3063;8.17129,41.9099"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 6
+VN 172.16.132.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="5.5176,40.92"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O3" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O12">
+ <dia:attribute name="obj_pos">
+ <dia:point val="60.6351,30.975"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="58.4101,30.3613;62.8788,31.9649"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 7
+VN 172.16.6.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="60.6351,30.975"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O2" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O13">
+ <dia:attribute name="obj_pos">
+ <dia:point val="60.6351,35.8725"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="58.4101,35.2588;62.8788,36.8624"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 8
+VN 172.16.8.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="60.6351,35.8725"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O1" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O14">
+ <dia:attribute name="obj_pos">
+ <dia:point val="60.6351,40.77"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="58.0026,40.1563;63.2863,41.7599"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVE 9
+VN 172.16.134.1#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="60.6351,40.77"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O0" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O15">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8.9226,31.125"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8.86406,31.0665;15.979,32.529"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="8.9226,31.125"/>
+ <dia:point val="15.9205,32.4705"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O5" connection="4"/>
+ <dia:connection handle="1" to="O23" connection="0"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O16">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8.9226,36.0225"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8.87151,35.8489;14.5511,36.0736"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="8.9226,36.0225"/>
+ <dia:point val="14.5,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O4" connection="4"/>
+ <dia:connection handle="1" to="O23" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O17">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8.9226,40.92"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8.86276,39.2697;15.9803,40.9798"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="8.9226,40.92"/>
+ <dia:point val="15.9205,39.3295"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O3" connection="4"/>
+ <dia:connection handle="1" to="O23" connection="5"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O18">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,30.975"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="49.9204,30.9159;57.2892,32.5296"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="57.2301,30.975"/>
+ <dia:point val="49.9795,32.4705"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O2" connection="3"/>
+ <dia:connection handle="1" to="O25" connection="2"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O19">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,35.8725"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="51.3498,35.8223;57.2803,35.9502"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="57.2301,35.8725"/>
+ <dia:point val="51.4,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O1" connection="3"/>
+ <dia:connection handle="1" to="O25" connection="4"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O20">
+ <dia:attribute name="obj_pos">
+ <dia:point val="57.2301,40.77"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="50.9399,37.8657;57.2963,40.8362"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="57.2301,40.77"/>
+ <dia:point val="51.0061,37.9319"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O0" connection="3"/>
+ <dia:connection handle="1" to="O25" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:group>
+ <dia:object type="Standard - Ellipse" version="0" id="O21">
+ <dia:attribute name="obj_pos">
+ <dia:point val="28.6,15.15"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="28.55,15.1;38.35,24.9"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="28.6,15.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="9.7000026702880859"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="9.7000026702880859"/>
+ </dia:attribute>
+ <dia:attribute name="aspect">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O22">
+ <dia:attribute name="obj_pos">
+ <dia:point val="33.45,20"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="29.9225,19.405;36.9775,20.9525"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#BGP Route Reflector 1
+192.168.1.100#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="33.45,20"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O21" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ </dia:group>
+ <dia:group>
+ <dia:object type="Standard - Ellipse" version="0" id="O23">
+ <dia:attribute name="obj_pos">
+ <dia:point val="14.5,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="14.45,31;24.25,40.8"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="14.5,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="9.7000007629394531"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="9.7000007629394531"/>
+ </dia:attribute>
+ <dia:attribute name="aspect">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O24">
+ <dia:attribute name="obj_pos">
+ <dia:point val="19.35,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="17.0013,35.305;21.6988,36.8525"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVA 2
+192.168.1.101#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="19.35,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O23" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ </dia:group>
+ <dia:group>
+ <dia:object type="Standard - Ellipse" version="0" id="O25">
+ <dia:attribute name="obj_pos">
+ <dia:point val="41.7,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="41.65,31;51.45,40.8"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="41.7,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="9.7000026702880859"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="9.7000026702880859"/>
+ </dia:attribute>
+ <dia:attribute name="aspect">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O26">
+ <dia:attribute name="obj_pos">
+ <dia:point val="46.55,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="44.2012,35.305;48.8987,36.8525"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#NVA 3
+192.168.1.102#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="46.55,35.9"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O25" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ </dia:group>
+ </dia:layer>
+</dia:diagram>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
- <dia:diagramdata>
- <dia:attribute name="background">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="pagebreak">
- <dia:color val="#000099"/>
- </dia:attribute>
- <dia:attribute name="paper">
- <dia:composite type="paper">
- <dia:attribute name="name">
- <dia:string>#Letter#</dia:string>
- </dia:attribute>
- <dia:attribute name="tmargin">
- <dia:real val="2.5399999618530273"/>
- </dia:attribute>
- <dia:attribute name="bmargin">
- <dia:real val="2.5399999618530273"/>
- </dia:attribute>
- <dia:attribute name="lmargin">
- <dia:real val="2.5399999618530273"/>
- </dia:attribute>
- <dia:attribute name="rmargin">
- <dia:real val="2.5399999618530273"/>
- </dia:attribute>
- <dia:attribute name="is_portrait">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="scaling">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="fitto">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="grid">
- <dia:composite type="grid">
- <dia:attribute name="width_x">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="width_y">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_x">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_y">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:composite type="color"/>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#d8e5e5"/>
- </dia:attribute>
- <dia:attribute name="guides">
- <dia:composite type="guides">
- <dia:attribute name="hguides"/>
- <dia:attribute name="vguides"/>
- </dia:composite>
- </dia:attribute>
- </dia:diagramdata>
- <dia:layer name="Background" visible="true" active="true">
- <dia:object type="Standard - Box" version="0" id="O0">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,39.145"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="57.1801,39.095;64.0901,42.445"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="57.2301,39.145"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O1">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,34.2475"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="57.1801,34.1975;64.0901,37.5475"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="57.2301,34.2475"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O2">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,29.35"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="57.1801,29.3;64.0901,32.65"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="57.2301,29.35"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O3">
- <dia:attribute name="obj_pos">
- <dia:point val="2.1126,39.295"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.0626,39.245;8.9726,42.595"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="2.1126,39.295"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O4">
- <dia:attribute name="obj_pos">
- <dia:point val="2.1126,34.3975"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.0626,34.3475;8.9726,37.6975"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="2.1126,34.3975"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O5">
- <dia:attribute name="obj_pos">
- <dia:point val="2.1126,29.5"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.0626,29.45;8.9726,32.8"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="2.1126,29.5"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="6.8100000000000023"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2500000000000018"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O6">
- <dia:attribute name="obj_pos">
- <dia:point val="22.5347,32.178"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="22.4642,23.359;30.091,32.2485"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="22.5347,32.178"/>
- <dia:point val="30.0205,23.4295"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O7">
- <dia:attribute name="obj_pos">
- <dia:point val="43.1205,32.4705"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="36.8099,23.3599;43.1901,32.5401"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="43.1205,32.4705"/>
- <dia:point val="36.8795,23.4295"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O8">
- <dia:attribute name="obj_pos">
- <dia:point val="16.5501,5.5"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.5501,4.905;16.5501,5.6525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="16.5501,5.5"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O9">
- <dia:attribute name="obj_pos">
- <dia:point val="5.5176,31.125"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.29385,30.5113;7.76004,32.1149"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 4
-VN 172.16.4.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="5.5176,31.125"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O5" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O10">
- <dia:attribute name="obj_pos">
- <dia:point val="5.5176,36.0225"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.88385,35.4088;8.17004,37.0124"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 5
-VN 172.16.130.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="5.5176,36.0225"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O4" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O11">
- <dia:attribute name="obj_pos">
- <dia:point val="5.5176,40.92"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.8826,40.3063;8.17129,41.9099"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 6
-VN 172.16.132.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="5.5176,40.92"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O3" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O12">
- <dia:attribute name="obj_pos">
- <dia:point val="60.6351,30.975"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="58.4101,30.3613;62.8788,31.9649"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 7
-VN 172.16.6.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="60.6351,30.975"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O2" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O13">
- <dia:attribute name="obj_pos">
- <dia:point val="60.6351,35.8725"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="58.4101,35.2588;62.8788,36.8624"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 8
-VN 172.16.8.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="60.6351,35.8725"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O1" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O14">
- <dia:attribute name="obj_pos">
- <dia:point val="60.6351,40.77"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="58.0026,40.1563;63.2863,41.7599"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVE 9
-VN 172.16.134.1#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="60.6351,40.77"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O0" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O15">
- <dia:attribute name="obj_pos">
- <dia:point val="8.9226,31.125"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="8.86406,31.0665;15.979,32.529"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="8.9226,31.125"/>
- <dia:point val="15.9205,32.4705"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O5" connection="4"/>
- <dia:connection handle="1" to="O23" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O16">
- <dia:attribute name="obj_pos">
- <dia:point val="8.9226,36.0225"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="8.87151,35.8489;14.5511,36.0736"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="8.9226,36.0225"/>
- <dia:point val="14.5,35.9"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O4" connection="4"/>
- <dia:connection handle="1" to="O23" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O17">
- <dia:attribute name="obj_pos">
- <dia:point val="8.9226,40.92"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="8.86276,39.2697;15.9803,40.9798"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="8.9226,40.92"/>
- <dia:point val="15.9205,39.3295"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O3" connection="4"/>
- <dia:connection handle="1" to="O23" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O18">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,30.975"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="49.9204,30.9159;57.2892,32.5296"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="57.2301,30.975"/>
- <dia:point val="49.9795,32.4705"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O2" connection="3"/>
- <dia:connection handle="1" to="O25" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O19">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,35.8725"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="51.3498,35.8223;57.2803,35.9502"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="57.2301,35.8725"/>
- <dia:point val="51.4,35.9"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O1" connection="3"/>
- <dia:connection handle="1" to="O25" connection="4"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O20">
- <dia:attribute name="obj_pos">
- <dia:point val="57.2301,40.77"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="50.9399,37.8657;57.2963,40.8362"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="57.2301,40.77"/>
- <dia:point val="51.0061,37.9319"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O0" connection="3"/>
- <dia:connection handle="1" to="O25" connection="8"/>
- </dia:connections>
- </dia:object>
- <dia:group>
- <dia:object type="Standard - Ellipse" version="0" id="O21">
- <dia:attribute name="obj_pos">
- <dia:point val="28.6,15.15"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="28.55,15.1;38.35,24.9"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="28.6,15.15"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="9.7000026702880859"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="9.7000026702880859"/>
- </dia:attribute>
- <dia:attribute name="aspect">
- <dia:enum val="2"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O22">
- <dia:attribute name="obj_pos">
- <dia:point val="33.45,20"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="29.9225,19.405;36.9775,20.9525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#BGP Route Reflector 1
-192.168.1.100#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="33.45,20"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O21" connection="8"/>
- </dia:connections>
- </dia:object>
- </dia:group>
- <dia:group>
- <dia:object type="Standard - Ellipse" version="0" id="O23">
- <dia:attribute name="obj_pos">
- <dia:point val="14.5,31.05"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="14.45,31;24.25,40.8"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="14.5,31.05"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="9.7000007629394531"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="9.7000007629394531"/>
- </dia:attribute>
- <dia:attribute name="aspect">
- <dia:enum val="2"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O24">
- <dia:attribute name="obj_pos">
- <dia:point val="19.35,35.9"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="17.0013,35.305;21.6988,36.8525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVA 2
-192.168.1.101#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="19.35,35.9"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O23" connection="8"/>
- </dia:connections>
- </dia:object>
- </dia:group>
- <dia:group>
- <dia:object type="Standard - Ellipse" version="0" id="O25">
- <dia:attribute name="obj_pos">
- <dia:point val="41.7,31.05"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="41.65,31;51.45,40.8"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="41.7,31.05"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="9.7000026702880859"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="9.7000026702880859"/>
- </dia:attribute>
- <dia:attribute name="aspect">
- <dia:enum val="2"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O26">
- <dia:attribute name="obj_pos">
- <dia:point val="46.55,35.9"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="44.2012,35.305;48.8987,36.8525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#NVA 3
-192.168.1.102#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="46.55,35.9"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="1"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O25" connection="8"/>
- </dia:connections>
- </dia:object>
- </dia:group>
- </dia:layer>
-</dia:diagram>
@comment node-name, next, previous, up
@chapter Filtering
-Quagga provides many very flexible filtering features. Filtering is used
+Frr provides many very flexible filtering features. Filtering is used
for both input and output of the routing information. Once filtering is
defined, it can be applied in any direction.
--- /dev/null
+.TH Frr 1 "27 July 2006" "@PACKAGE_FULLNAME@ Systemd Script" "Version @PACKAGE_VERSION@"
+.SH NAME
+frr \- a systemd interaction script
+.SH SYNOPSIS
+.B frr
+[
+.B start
+]
+.br
+.B frr
+[
+.B stop
+]
+.br
+.B frr
+[
+.B reload
+]
+.br
+.B frr
+[
+.B restart
+]
+.br
+.B frr
+[
+.B status
+]
+.br
+.SH DESCRIPTION
+.B @PACKAGE_NAME@
+is a systemd interaction script for the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B frr
+command:
+.IP start
+Start enabled Frr daemons
+.IP stop
+Stop enabled Frr daemons
+.IP reload
+Reload modified configuration files
+.IP restart
+Stop all running daemons and then restart them
+.IP status
+Status of all the daemons
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8)
+.SH BUGS
+.B frr
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
--- /dev/null
+\input texinfo @c -*- texinfo -*-
+
+@c Set variables - sourced from defines.texi
+@include defines.texi
+
+@c %**start of header
+@setfilename frr.info
+@c Set variables - sourced from defines.texi
+@include defines.texi
+@settitle @uref{http://www.freerangerouting.net,,@value{PACKAGE_NAME}}
+@c %**end of header
+
+@c automake will automatically generate version.texi
+@c and set EDITION, VERSION, UPDATED and UPDATED-MONTH
+@include version.texi
+
+@copying
+@value{COPYRIGHT_STR}
+@quotation
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by Kunihiro Ishiguro.
+
+@end quotation
+@end copying
+
+@c Info entry
+@dircategory Routing Software:
+@direntry
+* @value{PACKAGE_NAME}: (frr). The Frr Suite
+@end direntry
+
+@c @smallbook
+
+@ifinfo
+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.net/,,@value{PACKAGE_NAME}}
+Version @value{VERSION}.
+
+@insertcopying
+@end ifinfo
+
+@titlepage
+@title @uref{http://www.freerangerouting.net,,Frr}
+@subtitle A routing software package for TCP/IP networks
+@subtitle @uref{http://www.freerangerouting.net,,@value{PACKAGE_NAME}} @value{VERSION}
+@subtitle @value{UPDATED-MONTH}
+@author @value{AUTHORS}
+
+@page
+@vskip 0pt plus 1filll
+
+@insertcopying
+@end titlepage
+@page
+
+@ifnottex
+@node Top
+@top Frr -- With Virtual Network Control
+
+@uref{http://www.freerangerouting.net,,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.net,,Frr} is a fork of
+@uref{http://www.quagga.net,,Quagga}.
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Overview::
+* Installation::
+* Basic commands::
+* Zebra::
+* RIP::
+* RIPng::
+* OSPFv2::
+* OSPFv3::
+* ISIS::
+* BGP::
+* Configuring Frr as a Route Server::
+* VNC and VNC-GW::
+* VTY shell::
+* Filtering::
+* Route Map::
+* IPv6 Support::
+* Kernel Interface::
+* SNMP Support::
+* Zebra Protocol::
+* Packet Binary Dump Format::
+* Command Index::
+* VTY Key Index::
+* Index::
+@end menu
+@contents
+
+@include overview.texi
+@include install.texi
+@include basic.texi
+@include main.texi
+@include ripd.texi
+@include ripngd.texi
+@include ospfd.texi
+@include ospf6d.texi
+@include isisd.texi
+@include bgpd.texi
+@include routeserver.texi
+@include vnc.texi
+@include vtysh.texi
+@include filter.texi
+@include routemap.texi
+@include ipv6.texi
+@include kernel.texi
+@include snmp.texi
+@include protocol.texi
+@include appendix.texi
+
+@node Command Index
+@unnumbered Command Index
+
+@printindex fn
+
+@node VTY Key Index
+@unnumbered VTY Key Index
+
+@printindex ky
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+@bye
@node Installation
@chapter Installation
-@cindex How to install Quagga
+@cindex How to install Frr
@cindex Installation
-@cindex Installing Quagga
+@cindex Installing Frr
@cindex Building the system
-@cindex Making Quagga
+@cindex Making Frr
There are three steps for installing the software: configuration,
compilation, and installation.
* Install the Software::
@end menu
-The easiest way to get Quagga running is to issue the following
+The easiest way to get Frr running is to issue the following
commands:
@example
@cindex Distribution configuration
@cindex Options to @code{./configure}
-Quagga has an excellent configure script which automatically detects most
+Frr has an excellent configure script which automatically detects most
host configurations. There are several additional configure options to
customize the build to include or exclude specific features and dependencies.
@node Least-Privilege support
@subsection Least-Privilege support
-@cindex Quagga Least-Privileges
-@cindex Quagga Privileges
+@cindex Frr Least-Privileges
+@cindex Frr Privileges
Additionally, you may configure zebra to drop its elevated privileges
shortly after startup and switch to another user. The configure script will
automatically try to configure this support. There are three configure
-options to control the behaviour of Quagga daemons.
+options to control the behaviour of Frr daemons.
@table @option
@item --enable-user=@var{user}
this group.
@end table
-The default user and group which will be configured is 'quagga' if no user
+The default user and group which will be configured is 'frr' if no user
or group is specified. Note that this user or group requires write access to
the local state directory (see --localstatedir) and requires at least read
access, and write access if you wish to allow daemons to write out their
configuration, to the configuration directory (see --sysconfdir).
On systems which have the 'libcap' capabilities manipulation library
-(currently only linux), the quagga system will retain only minimal
+(currently only linux), the frr system will retain only minimal
capabilities required, further it will only raise these capabilities for
-brief periods. On systems without libcap, quagga will run as the user
+brief periods. On systems without libcap, frr will run as the user
specified and only raise its uid back to uid 0 for brief periods.
@node Linux notes
@subsection Linux Notes
-@cindex Configuring Quagga
+@cindex Configuring Frr
@cindex Building on Linux boxes
@cindex Linux configurations
There are several options available only to @sc{gnu}/Linux systems:
@footnote{@sc{gnu}/Linux has very flexible kernel configuration features}. If
you use @sc{gnu}/Linux, make sure that the current kernel configuration is
-what you want. Quagga will run with any kernel configuration but some
+what you want. Frr will run with any kernel configuration but some
recommendations do exist.
@table @var
@end table
IPv6 support has been added in @sc{gnu}/Linux kernel version 2.2. If you
-try to use the Quagga IPv6 feature on a @sc{gnu}/Linux kernel, please
+try to use the Frr IPv6 feature on a @sc{gnu}/Linux kernel, please
make sure the following libraries have been installed. Please note that
these libraries will not be needed when you uses @sc{gnu} C library 2.1
or upper.
installation process has completed, these files have been copied
from your work directory to @file{/usr/local/bin}, and @file{/usr/local/etc}.
-To install the Quagga suite, issue the following command at your shell
+To install the Frr suite, issue the following command at your shell
prompt: @command{make install}.
@example
%
@end example
-Quagga daemons have their own terminal interface or VTY. After
+Frr daemons have their own terminal interface or VTY. After
installation, you have to setup each beast's port number to connect to
them. Please add the following entries to @file{/etc/services}.
@node IPv6 Support
@chapter IPv6 Support
-Quagga fully supports IPv6 routing. As described so far, Quagga supports
+Frr fully supports IPv6 routing. As described so far, Frr supports
RIPng, OSPFv3, and BGP-4+. You can give IPv6 addresses to an interface
-and configure static IPv6 routing information. Quagga IPv6 also provides
+and configure static IPv6 routing information. Frr IPv6 also provides
automatic address configuration via a feature called @code{address
auto configuration}. To do it, the router must send router advertisement
messages to the all nodes that exist on the network.
-Previous versions of Quagga could be built without IPv6 support. This is
+Previous versions of Frr could be built without IPv6 support. This is
no longer possible.
@menu
+++ /dev/null
-.TH IS-IS 8 "25 November 2004" "Quagga IS-IS daemon" "Version 0.97.3"
-.SH NAME
-isisd \- an IS-IS routing engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B isisd
-[
-.B \-dhv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B isisd
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B isisd
-command:
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/isisd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When isisd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart isisd. The likely default is \fB\fI/var/run/isisd.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the isisd VTY will listen on. This defaults to
-2608, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the isisd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/isisd
-The default location of the
-.B isisd
-binary.
-.TP
-.BI /etc/quagga/isisd.conf
-The default location of the
-.B isisd
-config file.
-.TP
-.BI $(PWD)/isisd.log
-If the
-.B isisd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBisisd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The isisd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBisisd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-\fBisisd\fR is ALPHA quality at the moment and hasn't any way ready for
-production use.
-
-.B isisd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://isisd.sourceforge.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH IS-IS 8 "25 November 2004" "@PACKAGE_FULLNAME@ IS-IS daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B isisd
+[
+.B \-dhv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B isisd
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B isisd
+command:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/isisd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When isisd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart isisd. The default is \fB\fI@CFG_STATE@/isisd.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the isisd VTY will listen on. This defaults to
+2608, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the isisd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/isisd
+The default location of the
+.B isisd
+binary.
+.TP
+.BI @CFG_SYSCONF@/isisd.conf
+The default location of the
+.B isisd
+config file.
+.TP
+.BI $(PWD)/isisd.log
+If the
+.B isisd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBisisd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The isisd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBisisd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+\fBisisd\fR is ALPHA quality at the moment and hasn't any way ready for
+production use.
+
+.B isisd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://isisd.sourceforge.net
+or the Info file for an accurate list of authors.
+
@item netlink
On recent Linux kernels (2.0.x and 2.2.x), there is a kernel/user
communication support called @code{netlink}. It makes asynchronous
-communication between kernel and Quagga possible, similar to a routing
+communication between kernel and Frr possible, similar to a routing
socket on BSD systems.
Before you use this feature, be sure to select (in kernel configuration)
Today, the /dev/route special device file is obsolete. Netlink
communication is done by reading/writing over netlink socket.
-After the kernel configuration, please reconfigure and rebuild Quagga.
-You can use netlink as a dynamic routing update channel between Quagga
+After the kernel configuration, please reconfigure and rebuild Frr.
+You can use netlink as a dynamic routing update channel between Frr
and the kernel.
@end table
# ip -6 route add 3:3:3::3/128 via 2001:db8:4::3
```
-6 - Edit /etc/quagga/ospfd.conf:
+6 - Edit /etc/frr/ospfd.conf:
```
router ospf
network 4.4.4.4/32 area 0.0.0.0
!
```
-7 - Edit /etc/quagga/ldpd.conf:
+7 - Edit /etc/frr/ldpd.conf:
```
debug mpls ldp messages recv
debug mpls ldp messages sent
# route -n add 2:2:2::2/128 2001:db8:2::2
```
-6 - Edit /etc/quagga/ospfd.conf:
+6 - Edit /etc/frr/ospfd.conf:
```
router ospf
network 10.0.2.3/24 area 0
!
```
-7 - Edit /etc/quagga/ldpd.conf:
+7 - Edit /etc/frr/ldpd.conf:
```
debug mpls ldp messages recv
debug mpls ldp messages sent
+++ /dev/null
-.TH LDPD 8 "29 March 2016" "Quagga LDP daemon" "Version 1.0.20160309"
-.SH NAME
-ldpd \- an LDP engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B ldpd
-[
-.B \-dhv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B ldpd
-is a component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B ldpd
-command:
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/ldpd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When ldpd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart ldpd. The likely default is \fB\fI/var/run/ldpd.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the ldpd VTY will listen on. This defaults to
-2612, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the ldpd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/local/sbin/ldpd
-The default location of the
-.B ldpd
-binary.
-.TP
-.BI /usr/local/etc/ldpd.conf
-The default location of the
-.B ldpd
-config file.
-.TP
-.BI $(PWD)/ldpd.log
-If the
-.B ldpd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBldpd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The ldpd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBldpd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B ldpd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH LDPD 8 "29 March 2016" "@PACKAGE_FULLNAME@ LDP daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B ldpd
+[
+.B \-dhv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B ldpd
+is a component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B ldpd
+command:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/ldpd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When ldpd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart ldpd. The default is \fB\fI@CFG_STATE@/ldpd.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the ldpd VTY will listen on. This defaults to
+2612, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the ldpd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/ldpd
+The default location of the
+.B ldpd
+binary.
+.TP
+.BI @CFG_SYSCONF@/ldpd.conf
+The default location of the
+.B ldpd
+config file.
+.TP
+.BI $(PWD)/ldpd.log
+If the
+.B ldpd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBldpd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The ldpd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBldpd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B ldpd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
This table is fully separate from the default unicast table. However,
RPF lookup can include the unicast table.
-WARNING: RPF lookup results are non-responsive in this version of Quagga,
+WARNING: RPF lookup results are non-responsive in this version of Frr,
i.e. multicast routing does not actively react to changes in underlying
unicast topology!
@node zebra Route Filtering
@section zebra Route Filtering
Zebra supports @command{prefix-list} and @command{route-map} to match
-routes received from other quagga components. The
+routes received from other frr components. The
@command{permit}/@command{deny} facilities provided by these commands
can be used to filter which routes zebra will install in the kernel.
@section zebra FIB push interface
Zebra supports a 'FIB push' interface that allows an external
-component to learn the forwarding information computed by the Quagga
+component to learn the forwarding information computed by the Frr
routing suite.
-In Quagga, the Routing Information Base (RIB) resides inside
+In Frr, the Routing Information Base (RIB) resides inside
zebra. Routing protocols communicate their best routes to zebra, and
zebra computes the best route across protocols for each prefix. This
latter information makes up the Forwarding Information Base
(FIB). Zebra feeds the FIB to the kernel, which allows the IP stack in
the kernel to forward packets according to the routes computed by
-Quagga. The kernel FIB is updated in an OS-specific way. For example,
+Frr. The kernel FIB is updated in an OS-specific way. For example,
the @code{netlink} interface is used on Linux, and route sockets are
used on FreeBSD.
kernel continues to receive FIB updates as before.
The encapsulation header for the messages exchanged with the FPM is
-defined by the file @file{fpm/fpm.h} in the quagga tree. The routes
+defined by the file @file{fpm/fpm.h} in the frr tree. The routes
themselves are encoded in netlink or protobuf format, with netlink
being the default.
0. Introduction
This is the design specification for next hop tracking feature in
-Quagga.
+Frr.
1. Background
5. User interface changes
-quagga# show ip nht
+frr# show ip nht
3.3.3.3
resolved via kernel
via 11.0.0.6, swp1
via 10.0.1.2, eth0
Client list: bgp(fd 12)
-quagga# show ip bgp nexthop
+frr# show ip bgp nexthop
Current BGP nexthop cache:
3.3.3.3 valid [IGP metric 0], #paths 3
Last update: Wed Oct 16 04:43:49 2013
11.11.11.11 valid [IGP metric 0], #paths 1
Last update: Wed Oct 16 04:43:47 2013
-quagga# show ipv6 nht
-quagga# show ip bgp nexthop detail
+frr# show ipv6 nht
+frr# show ip bgp nexthop detail
-quagga# debug bgp nht
-quagga# debug zebra nht
+frr# debug bgp nht
+frr# debug zebra nht
6. Sample test cases
+++ /dev/null
-.TH OSPF6D 8 "25 November 2004" "Quagga OSPFv3 daemon" "Version 0.97.3"
-.SH NAME
-ospf6d \- an OSPFv3 routing engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B ospf6d
-[
-.B \-dhv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B ospf6d
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B ospf6d
-command:
-.SH OPTIONS
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/ospf6d.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When ospf6d starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart ospf6d. The likely default is \fB\fI/var/run/ospf6d.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the ospf6d VTY will listen on. This defaults to
-2606, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the ospf6d VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/ospf6d
-The default location of the
-.B ospf6d
-binary.
-.TP
-.BI /etc/quagga/ospf6d.conf
-The default location of the
-.B ospf6d
-config file.
-.TP
-.BI $(PWD)/ospf6d.log
-If the
-.B ospf6d
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBospf6d\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The ospf6d process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBospf6d\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B ospf6d
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH OSPF6D 8 "25 November 2004" "@PACKAGE_FULLNAME@ OSPFv3 daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B ospf6d
+[
+.B \-dhv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B ospf6d
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B ospf6d
+command:
+.SH OPTIONS
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/ospf6d.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When ospf6d starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart ospf6d. The default is \fB\fI@CFG_STATE@/ospf6d.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the ospf6d VTY will listen on. This defaults to
+2606, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the ospf6d VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/ospf6d
+The default location of the
+.B ospf6d
+binary.
+.TP
+.BI @CFG_SYSCONF@/ospf6d.conf
+The default location of the
+.B ospf6d
+config file.
+.TP
+.BI $(PWD)/ospf6d.log
+If the
+.B ospf6d
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBospf6d\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The ospf6d process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBospf6d\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B ospf6d
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
+++ /dev/null
-.\" This file was originally generated by help2man 1.36.
-.TH OSPFCLIENT "1" "July 2010"
-.SH NAME
-ospfclient \- an example ospf-api client
-.SH SYNOPSIS
-.B ospfclient
-.I ospfd
-.I lsatype
-.I opaquetype
-.I opaqueid
-.I ifaddr
-.I areaid
-.SH DESCRIPTION
-.B ospfclient
-is a an example ospf-api client to test the ospfd daemon.
-.SH OPTIONS
-.TP
-.I ospfd
-A router where the API\-enabled OSPF daemon is running.
-.TP
-.I lsatype
-The value has to be either "9", "10", or "11", depending on the flooding
-scope.
-.TP
-.I opaquetype
-The value has to be in the range of 0\-255 (for example, experimental
-applications use
-.I opaquetype
-larger than 128).
-.TP
-.I opaqueid
-Arbitrary application instance (24 bits).
-.TP
-.I ifaddr
-Interface IP address for type 9, otherwise it will be ignored.
-.TP
-.I areaid
-Area in the IP address format for type 10, otherwise it will be ignored.
-.SH "SEE ALSO"
-.BR ospfd (8).
-.SH AUTHORS
-See the project homepage at <http://www.quagga.net/>.
--- /dev/null
+.\" This file was originally generated by help2man 1.36.
+.TH OSPFCLIENT "1" "July 2010"
+.SH NAME
+ospfclient \- an example ospf-api client
+.SH SYNOPSIS
+.B ospfclient
+.I ospfd
+.I lsatype
+.I opaquetype
+.I opaqueid
+.I ifaddr
+.I areaid
+.SH DESCRIPTION
+.B ospfclient
+is a an example ospf-api client to test the ospfd daemon.
+.SH OPTIONS
+.TP
+.I ospfd
+A router where the API\-enabled OSPF daemon is running.
+.TP
+.I lsatype
+The value has to be either "9", "10", or "11", depending on the flooding
+scope.
+.TP
+.I opaquetype
+The value has to be in the range of 0\-255 (for example, experimental
+applications use
+.I opaquetype
+larger than 128).
+.TP
+.I opaqueid
+Arbitrary application instance (24 bits).
+.TP
+.I ifaddr
+Interface IP address for type 9, otherwise it will be ignored.
+.TP
+.I areaid
+Area in the IP address format for type 10, otherwise it will be ignored.
+.SH "SEE ALSO"
+.BR ospfd (8).
+.SH AUTHORS
+See the project homepage at <@PACKAGE_URL@>.
+++ /dev/null
-.TH OSPFD 8 "25 November 2004" "Quagga OSPFv2 daemon" "Version 0.97.3"
-.SH NAME
-ospfd \- an OSPFv2 routing engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B ospfd
-[
-.B \-dhlv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B ospfd
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B ospfd
-command:
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/ospfd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When ospfd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart ospfd. The likely default is \fB\fI/var/run/ospfd.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the ospfd VTY will listen on. This defaults to
-2604, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the ospfd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-a\fR, \fB\-\-apiserver \fR
-Enable OSPF apiserver. Default is disabled.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/ospfd
-The default location of the
-.B ospfd
-binary.
-.TP
-.BI /etc/quagga/ospfd.conf
-The default location of the
-.B ospfd
-config file.
-.TP
-.BI $(PWD)/ospfd.log
-If the
-.B ospfd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBospfd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The ospfd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBospfd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B ospfd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH OSPFD 8 "25 November 2004" "@PACKAGE_FULLNAME@ OSPFv2 daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B ospfd
+[
+.B \-dhlv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B ospfd
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B ospfd
+command:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/ospfd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When ospfd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart ospfd. The default is \fB\fI@CFG_STATE@/ospfd.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the ospfd VTY will listen on. This defaults to
+2604, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the ospfd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-a\fR, \fB\-\-apiserver \fR
+Enable OSPF apiserver. Default is disabled.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/ospfd
+The default location of the
+.B ospfd
+binary.
+.TP
+.BI @CFG_SYSCONF@/ospfd.conf
+The default location of the
+.B ospfd
+config file.
+.TP
+.BI $(PWD)/ospfd.log
+If the
+.B ospfd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBospfd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The ospfd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBospfd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B ospfd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
to ensure routing-loops are avoided.
With the "Cisco" or "IBM" ABR type, the default in this release of
-Quagga, this restriction is lifted, allowing an ABR to consider
+Frr, this restriction is lifted, allowing an ABR to consider
summaries learnt from other ABRs through non-backbone areas, and hence
route via non-backbone areas as a last resort when, and only when,
backbone links are down.
hold-time increasing by 400ms each time an SPF-triggering event occurs
within the hold-time of the previous SPF calculation.
-This command supercedes the @command{timers spf} command in previous Quagga
+This command supercedes the @command{timers spf} command in previous Frr
releases.
@end deffn
announced to other areas. This command can be used only in ABR and ONLY
router-LSAs (Type-1) and network-LSAs (Type-2) (ie. LSAs with scope area) can
be summarized. Type-5 AS-external-LSAs can't be summarized - their scope is AS.
-Summarizing Type-7 AS-external-LSAs isn't supported yet by Quagga.
+Summarizing Type-7 AS-external-LSAs isn't supported yet by Frr.
@example
@group
@group
!
password ABCDEF
-log file /var/log/quagga/ospfd.log
+log file /var/log/frr/ospfd.log
service advanced-vty
!
interface eth0
@chapter Overview
@cindex Overview
- @uref{http://www.quagga.net,,Quagga} is a routing software package that
+ @uref{http://www.freerangerouting.net,,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}). Quagga also supports special BGP Route Reflector and Route Server
-behavior. In addition to traditional IPv4 routing protocols, Quagga also
+RFCs}). Frr also supports special BGP Route Reflector and Route Server
+behavior. In addition to traditional IPv4 routing protocols, Frr also
supports IPv6 routing protocols. With SNMP daemon which supports SMUX and AgentX
-protocol, Quagga provides routing protocol MIBs (@pxref{SNMP Support}).
+protocol, Frr provides routing protocol MIBs (@pxref{SNMP Support}).
- Quagga uses an advanced software architecture to provide you with a high
-quality, multi server routing engine. Quagga has an interactive user
+ Frr uses an advanced software architecture to provide you with a high
+quality, multi server routing engine. Frr has an interactive user
interface for each routing protocol and supports common client commands.
-Due to this design, you can add new protocol daemons to Quagga easily. You
-can use Quagga library as your program's client user interface.
+Due to this design, you can add new protocol daemons to Frr easily. You
+can use Frr library as your program's client user interface.
- Quagga is distributed under the @sc{gnu} General Public License.
+ Frr is distributed under the @sc{gnu} General Public License.
@menu
-* About Quagga:: Basic information about Quagga
-* System Architecture:: The Quagga system architecture
+* About Frr:: Basic information about Frr
+* System Architecture:: The Frr system architecture
* Supported Platforms:: Supported platforms and future plans
* Supported RFCs:: Supported RFCs
-* How to get Quagga::
+* How to get Frr::
* Mailing List:: Mailing list information
* Bug Reports:: Mail address for bug data
@end menu
-@node About Quagga
+@node About Frr
@comment node-name, next, previous, up
-@section About Quagga
-@cindex About Quagga
+@section About Frr
+@cindex About Frr
Today, TCP/IP networks are covering all of the world. The Internet has
been deployed in many countries, companies, and to the home. When you
connect to the Internet your packet will pass many routers which have TCP/IP
routing functionality.
- A system with Quagga installed acts as a dedicated router. With Quagga,
+ A system with Frr installed acts as a dedicated router. With Frr,
your machine exchanges routing information with other routers using routing
-protocols. Quagga uses this information to update the kernel routing table
+protocols. Frr uses this information to update the kernel routing table
so that the right data goes to the right place. You can dynamically change
-the configuration and you may view routing table information from the Quagga
+the configuration and you may view routing table information from the Frr
terminal interface.
- Adding to routing protocol support, Quagga can setup interface's flags,
+ Adding to routing protocol support, Frr can setup interface's flags,
interface's address, static routes and so on. If you have a small network,
-or a stub network, or xDSL connection, configuring the Quagga routing
+or a stub network, or xDSL connection, configuring the Frr routing
software is very easy. The only thing you have to do is to set up the
interfaces and put a few commands about static routes and/or default routes.
If the network is rather large, or if the network structure changes
-frequently, you will want to take advantage of Quagga's dynamic routing
+frequently, you will want to take advantage of Frr's dynamic routing
protocol support for protocols such as RIP, OSPF, IS-IS or BGP.
Traditionally, UNIX based router configuration is done by
@command{ifconfig} and @command{route} commands. Status of routing
table is displayed by @command{netstat} utility. Almost of these commands
-work only if the user has root privileges. Quagga has a different system
-administration method. There are two user modes in Quagga. One is normal
+work only if the user has root privileges. Frr has a different system
+administration method. There are two user modes in Frr. One is normal
mode, the other is enable mode. Normal mode user can only view system
status, enable mode user can change system configuration. This UNIX account
independent feature will be great help to the router administrator.
- Currently, Quagga supports common unicast routing protocols, that is BGP,
+ Currently, Frr supports common unicast routing protocols, that is BGP,
OSPF, RIP and IS-IS. Upcoming for MPLS support, an implementation of LDP is
currently being prepared for merging. Implementations of BFD and PIM-SSM
(IPv4) also exist, but are not actively being worked on.
- The ultimate goal of the Quagga project is making a productive, quality, free
+ The ultimate goal of the Frr project is making a productive, quality, free
TCP/IP routing software package.
@node System Architecture
@cindex Software internals
Traditional routing software is made as a one process program which
-provides all of the routing protocol functionalities. Quagga takes a
+provides all of the routing protocol functionalities. Frr takes a
different approach. It is made from a collection of several daemons that
work together to build the routing table. There may be several
protocol-specific routing daemons and zebra the kernel routing manager.
| |
+------------------------------+
- Quagga System Architecture
+ Frr System Architecture
@end group
@end example
terminal interface. When you configure a static route, it must be done in
@command{zebra} configuration file. When you configure BGP network it must
be done in @command{bgpd} configuration file. This can be a very annoying
-thing. To resolve the problem, Quagga provides integrated user interface
+thing. To resolve the problem, Frr provides integrated user interface
shell called @command{vtysh}. @command{vtysh} connects to each daemon with
UNIX domain socket and then works as a proxy for user input.
-Quagga was planned to use multi-threaded mechanism when it runs with a
+Frr was planned to use multi-threaded mechanism when it runs with a
kernel that supports multi-threads. But at the moment, the thread library
which comes with @sc{gnu}/Linux or FreeBSD has some problems with running
reliable services such as routing software, so we don't use threads at all.
@section Supported Platforms
@cindex Supported platforms
-@cindex Quagga on other systems
+@cindex Frr on other systems
@cindex Compatibility with other systems
-@cindex Operating systems that support Quagga
+@cindex Operating systems that support Frr
-Currently Quagga supports @sc{gnu}/Linux and BSD. Porting Quagga
+Currently Frr supports @sc{gnu}/Linux and BSD. Porting Frr
to other platforms is not too difficult as platform dependent code should
most be limited to the @command{zebra} daemon. Protocol daemons are mostly
-platform independent. Please let us know when you find out Quagga runs on a
+platform independent. Please let us know when you find out Frr runs on a
platform which is not listed below.
The list of officially supported platforms are listed below. Note that
-Quagga may run correctly on other platforms, and may run with partial
+Frr may run correctly on other platforms, and may run with partial
functionality on further platforms.
@sp 1
@end itemize
Also note that, in particular regarding proprietary platforms, compiler
-and C library choice will affect Quagga. Only recent versions of the
+and C library choice will affect Frr. Only recent versions of the
following C compilers are well-tested:
@sp 1
@end table
-@node How to get Quagga
+@node How to get Frr
@comment node-name, next, previous, up
-@section How to get Quagga
+@section How to get Frr
-The official Quagga web-site is located at:
+The official Frr web-site is located at:
-@uref{http://www.quagga.net/}
+@uref{http://www.freerangerouting.net/}
and contains further information, as well as links to additional
resources.
-@uref{http://www.quagga.net/,Quagga} is a fork of GNU Zebra, whose
+@uref{http://www.freerangerouting.net/,Frr} is a fork of Quagga, whose
web-site is located at:
-@uref{http://www.zebra.org/}.
+@uref{http://www.quagga.net/}.
@node Mailing List
@comment node-name, next, previous, up
@section Mailing List
-@cindex How to get in touch with Quagga
-@cindex Mailing Quagga
+@cindex How to get in touch with Frr
+@cindex Mailing Frr
@cindex Contact information
@cindex Mailing lists
-There is a mailing list for discussions about Quagga. If you have any
-comments or suggestions to Quagga, please subscribe to:
+There is a mailing list for discussions about Frr. If you have any
+comments or suggestions to Frr, please subscribe to:
-@uref{http://lists.quagga.net/mailman/listinfo/quagga-users}.
+@uref{http://lists.nox.tf/listinfo/frr-users}.
-The @uref{http://www.quagga.net/,,Quagga} site has further information on
+The @uref{http://www.freerangerouting.net/,,Frr} site has further information on
the available mailing lists, see:
- @uref{http://www.quagga.net/lists.php}
+ @uref{http://lists.nox.tf/lists.php}
@node Bug Reports
@section Bug Reports
If you think you have found a bug, please send a bug report to:
-@uref{http://bugzilla.quagga.net}
+@uref{http://github.com/freerangerouting/frr/issues}
When you send a bug report, please be careful about the points below.
arguments to the configure script please note that too.
@end itemize
- Bug reports are very important for us to improve the quality of Quagga.
-Quagga is still in the development stage, but please don't hesitate to
-send a bug report to @uref{http://bugzilla.quagga.net}.
+ 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}.
+++ /dev/null
-.TH PIM 8 "10 December 2008" "Quagga PIM daemon" "Version 0.99.11"
-.SH NAME
-pimd \- a PIM routing for use with Quagga Routing Suite.
-.SH SYNOPSIS
-.B pimd
-[
-.B \-dhvZ
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-z
-.I path
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B pimd
-is a protocol-independent multicast component that works with the
-.B Quagga
-Routing Suite.
-.SH OPTIONS
-Options available for the
-.B pimd
-command:
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/pimd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When pimd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart pimd. The likely default is \fB\fI/var/run/pimd.pid\fR.
-.TP
-\fB\-z\fR, \fB\-\-socket \fR\fIpath\fR
-Specify the socket path for contacting the zebra daemon.
-The likely default is \fB\fI/var/run/zserv.api\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the pimd VTY will listen on. This defaults to
-2611, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the pimd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.TP
-\fB\-Z\fR, \fB\-\-debug_zclient\fR
-Enable logging information for zclient debugging.
-.SH FILES
-.TP
-.BI /usr/local/sbin/pimd
-The default location of the
-.B pimd
-binary.
-.TP
-.BI /usr/local/etc/pimd.conf
-The default location of the
-.B pimd
-config file.
-.TP
-.BI /var/run/pimd.pid
-The default location of the
-.B pimd
-pid file.
-.TP
-.BI /var/run/zserv.api
-The default location of the
-.B zebra
-unix socket file.
-.TP
-.BI $(PWD)/pimd.log
-If the
-.B pimd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBpimd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options.
-.SH DIAGNOSTICS
-The pimd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs.
-.SH "SEE ALSO"
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-\fBpimd\fR is in early development at the moment and is not ready for
-production use.
-
-.B pimd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI https://github.com/udhos/qpimd
-.SH AUTHORS
-See
-.BI https://github.com/udhos/qpimd
-for an accurate list of authors.
-
--- /dev/null
+.TH PIM 8 "10 December 2008" "@PACKAGE_FULLNAME@ PIM daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+pimd \- a PIM routing for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B pimd
+[
+.B \-dhvZ
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-z
+.I path
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B pimd
+is a protocol-independent multicast component that works with the
+.B @PACKAGE_FULLNAME@
+Routing Suite.
+.SH OPTIONS
+Options available for the
+.B pimd
+command:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/pimd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When pimd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart pimd. The default is \fB\fI@CFG_STATE@/pimd.pid\fR.
+.TP
+\fB\-z\fR, \fB\-\-socket \fR\fIpath\fR
+Specify the socket path for contacting the zebra daemon.
+The default is \fB\fI@CFG_STATE@/zserv.api\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the pimd VTY will listen on. This defaults to
+2611, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the pimd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.TP
+\fB\-Z\fR, \fB\-\-debug_zclient\fR
+Enable logging information for zclient debugging.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/pimd
+The default location of the
+.B pimd
+binary.
+.TP
+.BI @CFG_SYSCONF@/pimd.conf
+The default location of the
+.B pimd
+config file.
+.TP
+.BI @CFG_STATE@/pimd.pid
+The default location of the
+.B pimd
+pid file.
+.TP
+.BI @CFG_STATE@/zserv.api
+The default location of the
+.B zebra
+unix socket file.
+.TP
+.BI $(PWD)/pimd.log
+If the
+.B pimd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBpimd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options.
+.SH DIAGNOSTICS
+The pimd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs.
+.SH "SEE ALSO"
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+\fBpimd\fR is in early development at the moment and is not ready for
+production use.
+
+.B pimd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI https://github.com/udhos/qpimd
+.SH AUTHORS
+See
+.BI https://github.com/udhos/qpimd
+for an accurate list of authors.
+
seperate commands.
Version 0 is used by all versions of GNU Zebra as of this writing, and
-versions of Quagga up to and including Quagga 0.98. Version 1 will be
-used as of Quagga 1.0.
+versions of Quagga up to and including Quagga 0.98. Version 2 was created
+for 0.99.21 of Quagga. Version 3 designates VRF compatibility and was
+released in 1.0. Version 4 will be used as of Frr 2.0 to indicate that
+we are a different Routing Suite now and to hopefully prevent accidental
+Quagga <-> FRR issues.
@appendixsection Zebra Protocol Definition
@appendixsubsec Zebra Protocol Header (version 0)
+++ /dev/null
-.TH Quagga 1 "27 July 2006" "Quagga Systemd Script" "Version 0.99.23.1"
-.SH NAME
-quagga \- a systemd interaction script
-.SH SYNOPSIS
-.B quagga
-[
-.B start
-]
-.br
-.B quagga
-[
-.B stop
-]
-.br
-.B quagga
-[
-.B reload
-]
-.br
-.B quagga
-[
-.B restart
-]
-.br
-.B quagga
-[
-.B status
-]
-.br
-.SH DESCRIPTION
-.B Quagga
-is a systemd interaction script for the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B quagga
-command:
-.IP start
-Start enabled Quagga daemons
-.IP stop
-Stop enabled Quagga daemons
-.IP reload
-Reload modified configuration files
-.IP restart
-Stop all running daemons and then restart them
-.IP status
-Status of all the daemons
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8)
-.SH BUGS
-.B quagga
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
+++ /dev/null
-\input texinfo @c -*- texinfo -*-
-
-@c Set variables - sourced from defines.texi
-@include defines.texi
-
-@c %**start of header
-@setfilename quagga.info
-@c Set variables - sourced from defines.texi
-@include defines.texi
-@settitle @uref{http://www.quagga.net,,@value{PACKAGE_NAME}}
-@c %**end of header
-
-@c automake will automatically generate version.texi
-@c and set EDITION, VERSION, UPDATED and UPDATED-MONTH
-@include version.texi
-
-@copying
-@value{COPYRIGHT_STR}
-@quotation
-
-Permission is granted to make and distribute verbatim copies of this
-manual provided the copyright notice and this permission notice are
-preserved on all copies.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions,
-except that this permission notice may be stated in a translation
-approved by Kunihiro Ishiguro.
-
-@end quotation
-@end copying
-
-@c Info entry
-@dircategory Routing Software:
-@direntry
-* @value{PACKAGE_NAME}: (quagga). The Quagga Software Routing Suite
-@end direntry
-
-@c @smallbook
-
-@ifinfo
-This file documents the Quagga Software Routing Suite which manages common
-TCP/IP routing protocols.
-
-This is Edition @value{EDITION}, last updated @value{UPDATED} of
-@cite{The Quagga Manual}, for @uref{http://www.quagga.net/,,@value{PACKAGE_NAME}}
-Version @value{VERSION}.
-
-@insertcopying
-@end ifinfo
-
-@titlepage
-@title @uref{http://www.quagga.net,,Quagga}
-@subtitle A routing software package for TCP/IP networks
-@subtitle @uref{http://www.quagga.net,,@value{PACKAGE_NAME}} @value{VERSION}
-@subtitle @value{UPDATED-MONTH}
-@author @value{AUTHORS}
-
-@page
-@vskip 0pt plus 1filll
-
-@insertcopying
-@end titlepage
-@page
-
-@ifnottex
-@node Top
-@top Quagga -- With Virtual Network Control
-
-@uref{http://www.quagga.net,,Quagga} 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.quagga.net,,Quagga} is a fork of
-@uref{http://www.zebra.org,,GNU Zebra}.
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Overview::
-* Installation::
-* Basic commands::
-* Zebra::
-* RIP::
-* RIPng::
-* OSPFv2::
-* OSPFv3::
-* ISIS::
-* BGP::
-* Configuring Quagga as a Route Server::
-* VNC and VNC-GW::
-* VTY shell::
-* Filtering::
-* Route Map::
-* IPv6 Support::
-* Kernel Interface::
-* SNMP Support::
-* Zebra Protocol::
-* Packet Binary Dump Format::
-* Command Index::
-* VTY Key Index::
-* Index::
-@end menu
-@contents
-
-@include overview.texi
-@include install.texi
-@include basic.texi
-@include main.texi
-@include ripd.texi
-@include ripngd.texi
-@include ospfd.texi
-@include ospf6d.texi
-@include isisd.texi
-@include bgpd.texi
-@include routeserver.texi
-@include vnc.texi
-@include vtysh.texi
-@include filter.texi
-@include routemap.texi
-@include ipv6.texi
-@include kernel.texi
-@include snmp.texi
-@include protocol.texi
-@include appendix.texi
-
-@node Command Index
-@unnumbered Command Index
-
-@printindex fn
-
-@node VTY Key Index
-@unnumbered VTY Key Index
-
-@printindex ky
-
-@node Index
-@unnumbered Index
-
-@printindex cp
-@bye
+++ /dev/null
-.TH RIPD 8 "25 November 2004" "Quagga RIP daemon" "Version 0.97.3"
-.SH NAME
-ripd \- a RIP routing engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B ripd
-[
-.B \-dhrv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B ripd
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B ripd
-command:
-.SH OPTIONS
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/ripd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When ripd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart ripd. The likely default is \fB\fI/var/run/ripd.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the ripd VTY will listen on. This defaults to
-2602, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the ripd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-r\fR, \fB\-\-retain\fR
-When the program terminates, retain routes added by \fBripd\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/ripd
-The default location of the
-.B ripd
-binary.
-.TP
-.BI /etc/quagga/ripd.conf
-The default location of the
-.B ripd
-config file.
-.TP
-.BI $(PWD)/ripd.log
-If the
-.B ripd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBripd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The ripd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBripd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B ripd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
--- /dev/null
+.TH RIPD 8 "25 November 2004" "@PACKAGE_FULLNAME@ RIP daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B ripd
+[
+.B \-dhrv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B ripd
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B ripd
+command:
+.SH OPTIONS
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/ripd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When ripd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart ripd. The default is \fB\fI@CFG_STATE@/ripd.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the ripd VTY will listen on. This defaults to
+2602, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the ripd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-r\fR, \fB\-\-retain\fR
+When the program terminates, retain routes added by \fBripd\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/ripd
+The default location of the
+.B ripd
+binary.
+.TP
+.BI @CFG_SYSCONF@/ripd.conf
+The default location of the
+.B ripd
+config file.
+.TP
+.BI $(PWD)/ripd.log
+If the
+.B ripd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBripd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The ripd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBripd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B ripd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
@c -*-texinfo-*-
-@c This is part of the Quagga Manual.
+@c This is part of the Frr Manual.
@c @value{COPYRIGHT_STR}
-@c See file quagga.texi for copying conditions.
+@c See file frr.texi for copying conditions.
@node RIP
@chapter RIP
Version 2 of RIP supports a variable length subnet mask (VLSM). By
extending the subnet mask, the mask can be divided and reused. Each
subnet can be used for different purposes such as large to middle size
-LANs and WAN links. Quagga @command{ripd} does not support the non-sequential
+LANs and WAN links. Frr @command{ripd} does not support the non-sequential
netmasks that are included in RIP Version 2.
In a case of similar information with the same prefix and metric, the
@deffn {RIP command} {route @var{a.b.c.d/m}} {}
@deffnx {RIP command} {no route @var{a.b.c.d/m}} {}
-This command is specific to Quagga. The @code{route} command makes a static
+This command is specific to Frr. The @code{route} command makes a static
route only inside RIP. This command should be used only by advanced
users who are particularly knowledgeable about the RIP protocol. In
-most cases, we recommend creating a static route in Quagga and
+most cases, we recommend creating a static route in Frr and
redistributing it in RIP using @code{redistribute static}.
@end deffn
@end example
Cisco applies route-map _before_ routes will exported to rip route table.
-In current Quagga's test implementation, @command{ripd} applies route-map
+In current Frr's test implementation, @command{ripd} applies route-map
after routes are listed in the route table and before routes will be
announced to an interface (something like output filter). I think it is not
so clear, but it is draft and it may be changed at future.
+++ /dev/null
-.TH RIPNGD 8 "25 November 2004" "Quagga RIPNG daemon" "Version 0.97.3"
-.SH NAME
-ripngd \- a RIPNG routing engine for use with Quagga routing software.
-.SH SYNOPSIS
-.B ripngd
-[
-.B \-dhlrv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B ripngd
-is a routing component that works with the
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B ripngd
-command:
-.SH OPTIONS
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/ripngd.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When ripngd starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart ripngd. The likely default is \fB\fI/var/run/ripngd.pid\fR.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the ripngd VTY will listen on. This defaults to
-2603, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the ripngd VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-r\fR, \fB\-\-retain\fR
-When the program terminates, retain routes added by \fBripd\fR.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/ripngd
-The default location of the
-.B ripngd
-binary.
-.TP
-.BI /etc/quagga/ripngd.conf
-The default location of the
-.B ripngd
-config file.
-.TP
-.BI $(PWD)/ripngd.log
-If the
-.B ripngd
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBripngd\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The ripngd process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBripngd\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8),
-.BR vtysh (1)
-.SH BUGS
-.B ripngd
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH RIPNGD 8 "25 November 2004" "@PACKAGE_FULLNAME@ RIPNG daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B ripngd
+[
+.B \-dhlrv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B ripngd
+is a routing component that works with the
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B ripngd
+command:
+.SH OPTIONS
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/ripngd.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When ripngd starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart ripngd. The default is \fB\fI@CFG_STATE@/ripngd.pid\fR.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the ripngd VTY will listen on. This defaults to
+2603, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the ripngd VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-r\fR, \fB\-\-retain\fR
+When the program terminates, retain routes added by \fBripd\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/ripngd
+The default location of the
+.B ripngd
+binary.
+.TP
+.BI @CFG_SYSCONF@/ripngd.conf
+The default location of the
+.B ripngd
+config file.
+.TP
+.BI $(PWD)/ripngd.log
+If the
+.B ripngd
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBripngd\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The ripngd process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBripngd\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8),
+.BR vtysh (1)
+.SH BUGS
+.B ripngd
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
@c -*-texinfo-*-
-@c This is part of the Quagga Manual.
+@c This is part of the Frr Manual.
@c @value{COPYRIGHT_STR}
-@c See file quagga.texi for copying conditions.
+@c See file frr.texi for copying conditions.
@node RIPng
@chapter RIPng
@c -*-texinfo-*-
@c @value{COPYRIGHT_STR}
-@c See file quagga.texi for copying conditions.
+@c See file frr.texi for copying conditions.
@c
@c This file is a modified version of Jose Luis Rubio's TeX sources
@c of his RS-Manual document
-@node Configuring Quagga as a Route Server
-@chapter Configuring Quagga as a Route Server
+@node Configuring Frr as a Route Server
+@chapter Configuring Frr as a Route Server
The purpose of a Route Server is to centralize the peerings between BGP
speakers. For example if we have an exchange point scenario with four BGP
each of the four establishes a single BGP peering against the Route Server
(@pxref{fig:route-server}).
-We will first describe briefly the Route Server model implemented by Quagga.
+We will first describe briefly the Route Server model implemented by Frr.
We will explain the commands that have been added for configuring that
-model. And finally we will show a full example of Quagga configured as Route
+model. And finally we will show a full example of Frr configured as Route
Server.
@menu
modify some BGP attributes (next-hop, as-path and MED) that are usually
modified by standard BGP speakers before announcing a route.
-The announcement processing model implemented by Quagga is shown in
+The announcement processing model implemented by Frr is shown in
@ref{fig:rs-processing}. The figure shows a mixture of RS-clients (B, C and D)
with normal BGP peers (A). There are some details that worth additional
comments:
@node Commands for configuring a Route Server
@section Commands for configuring a Route Server
-Now we will describe the commands that have been added to quagga
+Now we will describe the commands that have been added to frr
in order to support the route server features.
@deffn {Route-Server} {neighbor @var{peer-group} route-server-client} {}
This command configures the peer given by @var{peer}, @var{A.B.C.D} or
@var{X:X::X:X} as an RS-client.
-Actually this command is not new, it already existed in standard Quagga. It
+Actually this command is not new, it already existed in standard Frr. It
enables the transparent mode for the specified peer. This means that some
BGP attributes (as-path, next-hop and MED) of the routes announced to that
peer are not modified.
@node Example of Route Server Configuration
@section Example of Route Server Configuration
-Finally we are going to show how to configure a Quagga daemon to act as a
+Finally we are going to show how to configure a Frr daemon to act as a
Route Server. For this purpose we are going to present a scenario without
route server, and then we will show how to use the configurations of the BGP
routers to generate the configuration of the route server.
@acronym{SNMP,Simple Network Managing Protocol} is a widely implemented
feature for collecting network information from router and/or host.
-Quagga itself does not support SNMP agent (server daemon) functionality
+Frr itself does not support SNMP agent (server daemon) functionality
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.
It is free and open software and available at @uref{http://www.net-snmp.org/}
and as binary package for most Linux distributions.
@code{net-snmp} has to be compiled with @code{--with-mib-modules=agentx} to
-be able to accept connections from Quagga using AgentX protocol or with
+be able to accept connections from Frr using AgentX protocol or with
@code{--with-mib-modules=smux} to use SMUX protocol.
Nowadays, SMUX is a legacy protocol. The AgentX protocol should be
@node AgentX configuration
@section AgentX configuration
-To enable AgentX protocol support, Quagga must have been build with the
+To enable AgentX protocol support, Frr must have been build with the
@code{--enable-snmp} or @code{--enable-snmp=agentx} option. Both the
-master SNMP agent (snmpd) and each of the Quagga daemons must be
+master SNMP agent (snmpd) and each of the Frr daemons must be
configured. In @code{/etc/snmp/snmpd.conf}, @code{master agentx}
-directive should be added. In each of the Quagga daemons, @code{agentx}
+directive should be added. In each of the Frr daemons, @code{agentx}
command will enable AgentX support.
@example
#
master agentx
-/etc/quagga/ospfd.conf:
+/etc/frr/ospfd.conf:
! ... the rest of ospfd.conf has been omitted for clarity ...
!
agentx
@end example
Upon successful connection, you should get something like this in the
-log of each Quagga daemons:
+log of each Frr daemons:
@example
2012/05/25 11:39:08 ZEBRA: snmp[info]: NET-SNMP version 5.4.3 AgentX subagent connected
The AgentX protocol can be transported over a Unix socket or using TCP
or UDP. It usually defaults to a Unix socket and depends on how NetSNMP
-was built. If need to configure Quagga to use another transport, you can
-configure it through @code{/etc/snmp/quagga.conf}:
+was built. If need to configure Frr to use another transport, you can
+configure it through @code{/etc/snmp/frr.conf}:
@example
-/etc/snmp/quagga.conf:
+/etc/snmp/frr.conf:
[snmpd]
# Use a remote master agent
agentXSocket tcp:192.168.15.12:705
@node SMUX configuration
@section SMUX configuration
-To enable SMUX protocol support, Quagga must have been build with the
+To enable SMUX protocol support, Frr must have been build with the
@code{--enable-snmp=smux} option.
A separate connection has then to be established between the
-SNMP agent (snmpd) and each of the Quagga daemons. This connections
+SNMP agent (snmpd) and each of the Frr daemons. This connections
each use different OID numbers and passwords. Be aware that this OID
number is not the one that is used in queries by clients, it is solely
used for the intercommunication of the daemons.
In the following example the ospfd daemon will be connected to the
-snmpd daemon using the password "quagga_ospfd". For testing it is
+snmpd daemon using the password "frr_ospfd". For testing it is
recommending to take exactly the below snmpd.conf as wrong access
restrictions can be hard to debug.
view all included .1 80
access MyROGroup "" any noauth exact all none none
#
- # the following line is relevant for Quagga
+ # the following line is relevant for Frr
#
- smuxpeer .1.3.6.1.4.1.3317.1.2.5 quagga_ospfd
+ smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
-/etc/quagga/ospf:
+/etc/frr/ospf:
! ... the rest of ospfd.conf has been omitted for clarity ...
!
- smux peer .1.3.6.1.4.1.3317.1.2.5 quagga_ospfd
+ smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
!
@end example
-After restarting snmpd and quagga, a successful connection can be verified in
+After restarting snmpd and frr, a successful connection can be verified in
the syslog and by querying the SNMP daemon:
@example
snmpd[12300]: [smux_accept] accepted fd 12 from 127.0.0.1:36255
snmpd[12300]: accepted smux peer: \
- oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, quagga-0.96.5
+ oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, frr-0.96.5
# snmpwalk -c public -v1 localhost .1.3.6.1.2.1.14.1.1
OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109
@section MIB and command reference
The following OID numbers are used for the interprocess communication of snmpd and
-the Quagga daemons with SMUX only.
+the Frr daemons with SMUX only.
@example
(OIDs below .iso.org.dod.internet.private.enterprises)
zebra .1.3.6.1.4.1.3317.1.2.1 .gnome.gnomeProducts.zebra.zserv
ospf6d .1.3.6.1.3.102 .iso.org.dod.internet.experimental.ospfv3
@end example
-The following syntax is understood by the Quagga daemons for configuring SNMP using SMUX:
+The following syntax is understood by the Frr daemons for configuring SNMP using SMUX:
@deffn {Command} {smux peer @var{oid}} {}
@deffnx {Command} {no smux peer @var{oid}} {}
@end deffn
-@c Documentation on configuring Quagga and snmpd for SNMP traps
+@c Documentation on configuring Frr and snmpd for SNMP traps
@c contributed by Jeroen Simonetti, jsimonetti@denit.net
@node Handling SNMP Traps
@section Handling SNMP Traps
-To handle snmp traps make sure your snmp setup of quagga works
-correctly as described in the quagga documentation in @xref{SNMP Support}.
+To handle snmp traps make sure your snmp setup of frr works
+correctly as described in the frr documentation in @xref{SNMP Support}.
The BGP4 mib will send traps on peer up/down events. These should be
visible in your snmp logs with a message similar to:
@c -*-texinfo-*-
-@c This is part of the Quagga Manual.
+@c This is part of the Frr Manual.
@c @value{COPYRIGHT_STR}
-@c See file quagga.texi for copying conditions.
+@c See file frr.texi for copying conditions.
@node VNC and VNC-GW
@chapter VNC and VNC-GW
The protocol that is used to communicate routing and Ethernet / L2
forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). Currently, only a simple example RFP
-is included in Quagga. Developers may use this example as a starting
-point to integrate Quagga with an RFP of their choosing, e.g.,
+is included in Frr. Developers may use this example as a starting
+point to integrate Frr with an RFP of their choosing, e.g.,
@code{OpenFlow}. The example code includes the following sample
configuration:
It is important to note that when exporting routes to other protocols,
the downstream protocol must also be configured to import the routes.
For example, when VNC routes are exported to unicast BGP, the BGP
-configuration must include a corresponding @code{redistribute vpn}
+configuration must include a corresponding @code{redistribute vnc-direct}
statement.
@deffn {VNC} {export bgp|zebra mode none|group-nve|registering-nve|ce}
@menu
* Mesh NVA Configuration::
* Mesh NVA and VNC-GW Configuration::
-* VNC with Quagga Route Reflector Configuration::
+* VNC with Frr Route Reflector Configuration::
* VNC with Commercial Route Reflector Configuration::
* VNC with Redundant Route Reflectors Configuration::
@c * Interfacing VNC to an IGP::
NVEs. Note that this example is showing a more complex configuration
where VNC-GW is separated from normal NVA functions; it is equally
possible to simplify the configuration and combine NVA and VNC-GW
-functions in a single quagga instance.
+functions in a single frr instance.
@float Figure,fig:fig-vnc-gw
-@center @image{fig-vnc-gw,400pt,,Quagga VNC Gateway}
+@center @image{fig-vnc-gw,400pt,,Frr VNC Gateway}
@caption{Meshed NVEs and VNC-GWs}
@end float
router bgp 64512
bgp router-id 192.168.1.101
bgp cluster-id 1.2.3.4
- redistribute vpn
+ redistribute vnc-direct
neighbor 192.168.1.102 remote-as 64512
no neighbor 192.168.1.102 activate
neighbor 192.168.1.103 remote-as 64512
@c TBD make this its own example:
@c
@c @float Figure,fig:fig-vnc-gw-rr
-@c @center @image{fig-vnc-gw-rr,400pt,,Quagga VNC Gateway with RR}
+@c @center @image{fig-vnc-gw-rr,400pt,,Frr VNC Gateway with RR}
@c @end float
@c An NVA can also import unicast routes from BGP without advertising the
@c imported routes as VPN routes. Such imported routes, while not
@c vnc redistribute ipv4 bgp-direct-to-nve-groups
@c @end verbatim
-@node VNC with Quagga Route Reflector Configuration
-@subsection VNC with Quagga Route Reflector Configuration
+@node VNC with Frr Route Reflector Configuration
+@subsection VNC with Frr Route Reflector Configuration
A route reflector eliminates the need for a fully meshed NVA
network by acting as the hub between NVAs.
-@ref{fig:fig-vnc-quagga-route-reflector} shows BGP route reflector
+@ref{fig:fig-vnc-frr-route-reflector} shows BGP route reflector
@code{BGP Route Reflector 1} (192.168.1.100) as a route reflector for
NVAs @code{NVA 2}(192.168.1.101) and @code{NVA 3}
(192.168.1.102).
-@float Figure,fig:fig-vnc-quagga-route-reflector
-@center @image{fig-vnc-quagga-route-reflector,400pt,,Quagga Route Reflector}
+@float Figure,fig:fig-vnc-frr-route-reflector
+@center @image{fig-vnc-frr-route-reflector,400pt,,Frr Route Reflector}
@caption{Two NVAs and a BGP Route Reflector}
@end float
@node VNC with Commercial Route Reflector Configuration
@subsection VNC with Commercial Route Reflector Configuration
-This example is identical to @ref{VNC with Quagga Route Reflector
+This example is identical to @ref{VNC with Frr Route Reflector
Configuration} with the exception that the route reflector is a
commercial router. Only the
VNC-relevant configuration is provided.
@node VNC with Redundant Route Reflectors Configuration
@subsection VNC with Redundant Route Reflectors Configuration
-This example combines the previous two (@ref{VNC with Quagga Route
+This example combines the previous two (@ref{VNC with Frr Route
Reflector Configuration} and @ref{VNC with Commercial Route Reflector
Configuration}) into a redundant route reflector configuration. BGP
route reflectors @code{BGP Route Reflector 1} and @code{Commercial Router}
@float Figure,fig:fig-vnc-redundant-route-reflectors
@center @image{fig-vnc-redundant-route-reflectors,400pt,,Redundant Route Reflectors}
-@caption{Quagga-based NVA with redundant route reflectors}
+@caption{Frr-based NVA with redundant route reflectors}
@end float
@file{bgpd.conf} for @code{Bgpd Route Reflector 1} on 192.168.1.100:
+++ /dev/null
-.TH VTYSH 1 "27 July 2006" "Quagga VTY shell" "Version 0.96.5"
-.SH NAME
-vtysh \- a integrated shell for Quagga routing software
-.SH SYNOPSIS
-.B vtysh
-[
-.B \-b
-]
-.br
-.B vtysh
-[
-.B \-E
-] [
-.B \-d
-.I daemon
-]
-] [
-.B \-c
-.I command
-]
-.SH DESCRIPTION
-.B vtysh
-is a integrated shell for
-.B Quagga
-routing engine.
-.SH OPTIONS
-Options available for the
-.B vtysh
-command:
-.IP "\fB\-b, \-\-boot\fP"
-Execute boot startup configuration. It makes sense only if integrated config
-file is in use (not default in Quagga). See Info file \fBQuagga\fR for more
-info.
-.IP "\fB\-c, \-\-command \fIcommand\fP"
-Specify command to be executed under batch mode. It behaves like -c option in
-any other shell -
-.I command
-is executed and
-.B vtysh
-exits.
-
-It's useful for gathering info from Quagga routing software or reconfiguring
-daemons from inside shell scripts, etc.
-Note that multiple commands may be executed by using more than one
--c option and/or embedding linefeed characters inside the
-.I command
-string.
-.IP "\fB\-d, \-\-daemon \fIdaemon_name\fP"
-Specify which daemon to connect to. By default,
-.B vtysh
-attempts to connect to all Quagga daemons running on the system. With this
-flag, one can specify a single daemon to connect to instead. For example,
-specifying '-d ospfd' will connect only to ospfd. This can be particularly
-useful inside scripts with -c where the command is targeted for a single daemon.
-.IP "\fB\-e, \-\-execute \fIcommand\fP"
-Alias for -c. It's here only for compatibility with Zebra routing software and
-older Quagga versions. This will be removed in future.
-.IP "\fB\-E, \-\-echo\fP"
-When the -c option is being used, this flag will cause the standard
-.B vtysh
-prompt and command to be echoed prior to displaying the results.
-This is particularly useful to separate the results
-when executing multiple commands.
-.IP "\fB\-h, \-\-help\fP"
-Display a usage message on standard output and exit.
-.SH ENVIRONMENT VARIABLES
-.IP "\fBVTYSH_PAGER\fR"
-This should be the name of the pager to use. Default is \fBmore\fR.
-.SH FILES
-.TP
-.BI /etc/quagga/vtysh.conf
-The default location of the
-.B vtysh
-config file.
-.TP
-.BI /etc/quagga/Quagga.conf
-The default location of the integrated Quagga routing engine config file
-if integrated config file is in use (not default).
-.TP
-.BI ${HOME}/.history_quagga
-Location of history of commands entered via cli
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR zebra (8)
-.SH BUGS
-.B vtysh
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH VTYSH 1 "27 July 2006" "@PACKAGE_FULLNAME@ VTY shell" "Version @PACKAGE_VERSION@"
+.SH NAME
+vtysh \- a integrated shell for @PACKAGE_FULLNAME@.
+.SH SYNOPSIS
+.B vtysh
+[
+.B \-b
+]
+.br
+.B vtysh
+[
+.B \-E
+] [
+.B \-d
+.I daemon
+]
+] [
+.B \-c
+.I command
+]
+.SH DESCRIPTION
+.B vtysh
+is a integrated shell for
+.B @PACKAGE_FULLNAME@
+routing engine.
+.SH OPTIONS
+Options available for the
+.B vtysh
+command:
+.IP "\fB\-b, \-\-boot\fP"
+Execute boot startup configuration. It makes sense only if integrated config
+file is in use (not default in @PACKAGE_FULLNAME@). See Info file
+\fB@PACKAGE_NAME@\fR for more info.
+.IP "\fB\-c, \-\-command \fIcommand\fP"
+Specify command to be executed under batch mode. It behaves like -c option in
+any other shell -
+.I command
+is executed and
+.B vtysh
+exits.
+
+It's useful for gathering info from @PACKAGE_FULLNAME@ daemons or reconfiguring
+daemons from inside shell scripts, etc.
+Note that multiple commands may be executed by using more than one
+-c option and/or embedding linefeed characters inside the
+.I command
+string.
+.IP "\fB\-d, \-\-daemon \fIdaemon_name\fP"
+Specify which daemon to connect to. By default,
+.B vtysh
+attempts to connect to all @PACKAGE_FULLNAME@ daemons running on the system. With this
+flag, one can specify a single daemon to connect to instead. For example,
+specifying '-d ospfd' will connect only to ospfd. This can be particularly
+useful inside scripts with -c where the command is targeted for a single daemon.
+.IP "\fB\-e, \-\-execute \fIcommand\fP"
+Alias for -c. It's here only for compatibility with Zebra routing software and
+older Frr versions. This will be removed in future.
+.IP "\fB\-E, \-\-echo\fP"
+When the -c option is being used, this flag will cause the standard
+.B vtysh
+prompt and command to be echoed prior to displaying the results.
+This is particularly useful to separate the results
+when executing multiple commands.
+.IP "\fB\-h, \-\-help\fP"
+Display a usage message on standard output and exit.
+.SH ENVIRONMENT VARIABLES
+.IP "\fBVTYSH_PAGER\fR"
+This should be the name of the pager to use. Default is \fBmore\fR.
+.SH FILES
+.TP
+.BI @CFG_SYSCONF@/vtysh.conf
+The default location of the
+.B vtysh
+config file.
+.TP
+.BI @CFG_SYSCONF@/Frr.conf
+The default location of the integrated @PACKAGE_FULLNAME@ routing engine config file
+if integrated config file is in use (not default).
+.TP
+.BI ${HOME}/.history_frr
+Location of history of commands entered via cli
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR zebra (8)
+.SH BUGS
+.B vtysh
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
* Integrated configuration mode::
@end menu
-@command{vtysh} provides a combined frontend to all Quagga daemons in a
+@command{vtysh} provides a combined frontend to all Frr daemons in a
single combined session. It is enabled by default at build time, but can
be disabled through the @option{--disable-vtysh} option to
@command{./configure}.
group (which is the group that the daemons will change ownership of their
sockets to).
-To restrict access to Quagga configuration, make sure no unauthorized users
+To restrict access to Frr configuration, make sure no unauthorized users
are members of the @emph{@value{INSTALL_VTY_GROUP}} group.
@subsection PAM support (experimental)
@section Integrated configuration mode
Integrated configuration mode uses a single configuration file,
-@file{Quagga.conf}, for all daemons. This replaces the individual files like
+@file{Frr.conf}, for all daemons. This replaces the individual files like
@file{zebra.conf} or @file{bgpd.conf}.
-@file{Quagga.conf} is located in @file{@value{INSTALL_PREFIX_ETC}}. All
+@file{Frr.conf} is located in @file{@value{INSTALL_PREFIX_ETC}}. All
daemons check for the existence of this file at startup, and if it exists
will not load their individual configuration files. Instead,
-@command{vtysh -b} must be invoked to process @file{Quagga.conf} and apply
+@command{vtysh -b} must be invoked to process @file{Frr.conf} and apply
its settings to the individual daemons.
@quotation Warning
@subsection Configuration saving, file ownership and permissions
-The @file{Quagga.conf} file is not written by any of the daemons; instead
+The @file{Frr.conf} file is not written by any of the daemons; instead
@command{vtysh} contains the neccessary logic to collect configuration from
all of the daemons, combine it and write it out.
@end quotation
Since the @command{vtysh} command may be running as ordinary user on the
-system, configuration writes will be tried through @command{watchquagga},
+system, configuration writes will be tried through @command{watchfrr},
using the @command{write integrated} command internally. Since
-@command{watchquagga} is running as superuser, @command{vtysh} is able to
-ensure correct ownership and permissions on @file{Quagga.conf}.
+@command{watchfrr} is running as superuser, @command{vtysh} is able to
+ensure correct ownership and permissions on @file{Frr.conf}.
-If @command{watchquagga} is not running or the configuration write fails,
+If @command{watchfrr} is not running or the configuration write fails,
@command{vtysh} will attempt to directly write to the file. This is likely
to fail if running as unprivileged user; alternatively it may leave the
file with incorrect owner or permissions.
Writing the configuration can be triggered directly by invoking
@command{vtysh -w}. This may be useful for scripting. Note this command
-should be run as either the superuser or the Quagga user.
+should be run as either the superuser or the Frr user.
We recommend you do not mix the use of the two types of files. Further, it
-is better not to use the integrated Quagga.conf file, as any syntax error in
+is better not to use the integrated Frr.conf file, as any syntax error in
it can lead to /all/ of your daemons being unable to start up. Per daemon
files are more robust as impact of errors in configuration are limited to
the daemon in whose file the error is made.
@deffn {Command} {service integrated-vtysh-config} {}
@deffnx {Command} {no service integrated-vtysh-config} {}
-Control whether integrated @file{Quagga.conf} file is written when
+Control whether integrated @file{Frr.conf} file is written when
'write file' is issued.
These commands need to be placed in @file{vtysh.conf} to have any effect.
-Note that since @file{vtysh.conf} is not written by Quagga itself, they
+Note that since @file{vtysh.conf} is not written by Frr itself, they
therefore need to be manually placed in that file.
This command has 3 states:
@item
@command{service integrated-vtysh-config}
-@command{vtysh} will always write @file{Quagga.conf}.
+@command{vtysh} will always write @file{Frr.conf}.
@item
@command{no service integrated-vtysh-config}
-@command{vtysh} will never write @file{Quagga.conf}; instead it will ask
+@command{vtysh} will never write @file{Frr.conf}; instead it will ask
daemons to write their individual configuration files.
@item
Neither option present (default)
-@command{vtysh} will check whether @file{Quagga.conf} exists. If it does,
+@command{vtysh} will check whether @file{Frr.conf} exists. If it does,
configuration writes will update that file. Otherwise, writes are performed
through the individual daemons.
@end itemize
@deffn {Command} {write integrated} {}
Unconditionally (regardless of @command{service integrated-vtysh-config}
-setting) write out integrated @file{Quagga.conf} file through
-@command{watchquagga}. If @command{watchquagga} is not running, this command
+setting) write out integrated @file{Frr.conf} file through
+@command{watchfrr}. If @command{watchfrr} is not running, this command
is unavailable.
@end deffn
Configuration changes made while some daemon is not running will be invisible
to that daemon. The daemon will start up with its saved configuration
-(either in its individual configuration file, or in @file{Quagga.conf}).
+(either in its individual configuration file, or in @file{Frr.conf}).
This is particularly troublesome for route-maps and prefix lists, which would
otherwise be synchronized between daemons.
--- /dev/null
+.\" This file was originally generated by help2man 1.36.
+.TH WATCHFRR 8 "July 2010"
+.SH NAME
+watchfrr \- a program to monitor the status of frr daemons
+.SH SYNOPSIS
+.B watchfrr
+.RI [ option ...]
+.IR daemon ...
+.br
+.B watchfrr
+.BR \-h " | " \-v
+.SH DESCRIPTION
+.B watchfrr
+is a watchdog program that monitors the status of supplied frr
+.IR daemon s
+and tries to restart them in case they become unresponsive or shut down.
+.PP
+To determine whether a daemon is running, it tries to connect to the
+daemon's VTY UNIX stream socket, and send echo commands to ensure the
+daemon responds. When the daemon crashes, EOF is received from the socket,
+so that watchfrr can react immediately.
+.PP
+This program can run in one of the following 5 modes:
+.TP
+.B Mode 0: monitor
+In this mode, the program serves as a monitor and reports status changes.
+.IP
+Example usage: watchfrr \-d zebra ospfd bgpd
+.TP
+.B Mode 1: global restart
+In this mode, whenever a daemon hangs or crashes, the given command is used
+to restart all watched daemons.
+.IP
+Example usage: watchfrr \-dz \e
+.br
+-R '/sbin/service zebra restart; /sbin/service ospfd restart' \e
+.br
+zebra ospfd
+.TP
+.B Mode 2: individual daemon restart
+In this mode, whenever a single daemon hangs or crashes, the given command
+is used to restart this daemon only.
+.IP
+Example usage: watchfrr \-dz \-r '/sbin/service %s restart' \e
+.br
+zebra ospfd bgpd
+.TP
+.B Mode 3: phased zebra restart
+In this mode, whenever a single daemon hangs or crashes, the given command
+is used to restart this daemon only. The only exception is the zebra
+daemon; in this case, the following steps are taken: (1) all other daemons
+are stopped, (2) zebra is restarted, and (3) other daemons are started
+again.
+.IP
+Example usage: watchfrr \-adz \-r '/sbin/service %s restart' \e
+.br
+\-s '/sbin/service %s start' \e
+.br
+\-k '/sbin/service %s stop' zebra ospfd bgpd
+.TP
+.B Mode 4: phased global restart for any failure
+In this mode, whenever a single daemon hangs or crashes, the following
+steps are taken: (1) all other daemons are stopped, (2) zebra is restarted,
+and (3) other daemons are started again.
+.IP
+Example usage: watchfrr \-Adz \-r '/sbin/service %s restart' \e
+.br
+\-s '/sbin/service %s start' \e
+.br
+\-k '/sbin/service %s stop' zebra ospfd bgpd
+.PP
+Important: It is believed that mode 2 (individual daemon restart) is not
+safe, and mode 3 (phased zebra restart) may not be safe with certain
+routing daemons.
+.PP
+In order to avoid restarting the daemons in quick succession, you can
+supply the
+.B \-m
+and
+.B \-M
+options to set the minimum and maximum delay between the restart commands.
+The minimum restart delay is recalculated each time a restart is attempted.
+If the time since the last restart attempt exceeds twice the value of
+.BR \-M ,
+the restart delay is set to the value of
+.BR \-m ,
+otherwise the interval is doubled (but capped at the value of
+.BR \-M ).
+.SH OPTIONS
+.TP
+.BR \-d ", " \-\-daemon
+Run in daemon mode. When supplied, error messages are sent to Syslog
+instead of standard output (stdout).
+.TP
+.BI \-S " directory" "\fR, \fB\-\-statedir " directory
+Set the VTY socket
+.I directory
+(the default value is "/var/run/frr").
+.TP
+.BR \-e ", " \-\-no\-echo
+Do not ping the daemons to test whether they respond. This option is
+necessary if one or more daemons do not support the echo command.
+.TP
+.BI \-l " level" "\fR, \fB\-\-loglevel " level
+Set the logging
+.I level
+(the default value is "6"). The value should range from 0 (LOG_EMERG) to 7
+(LOG_DEBUG), but higher number can be supplied if extra debugging messages
+are required.
+.TP
+.BI \-m " number" "\fR, \fB\-\-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
+Set the maximum
+.I number
+of seconds to wait between invocations of the daemon restart commands (the
+default value is "600").
+.TP
+.BI \-i " number" "\fR, \fB\-\-interval " number
+Set the status polling interval in seconds (the default value is "5").
+.TP
+.BI \-t " number" "\fR, \fB\-\-timeout " number
+Set the unresponsiveness timeout in seconds (the default value is "10").
+.TP
+.BI \-T " number" "\fR, \fB\-\-restart\-timeout " number
+Set the restart (kill) timeout in seconds (the default value is "20"). If
+any background jobs are still running after this period has elapsed, they
+will be killed.
+.TP
+.BI \-r " command" "\fR, \fB\-\-restart " command
+Supply a Bourne shell
+.I command
+to restart a single daemon. The command string should contain the '%s'
+placeholder to be substituted with the daemon name.
+.IP
+Note that
+.B \-r
+and
+.B \-R
+options are not compatible.
+.TP
+.BI \-s " command" "\fR, \fB\-\-start\-command " command
+Supply a Bourne shell
+.I command
+to start a single daemon. The command string should contain the '%s'
+placeholder to be substituted with the daemon name.
+.TP
+.BI \-k " command" "\fR, \fB\-\-kill\-command " command
+Supply a Bourne shell
+.I command
+to stop a single daemon. The command string should contain the '%s'
+placeholder to be substituted with the daemon name.
+.TP
+.BR \-R ", " \-\-restart\-all
+When one or more daemons are shut down, try to restart them using the
+Bourne shell command supplied on the command line.
+.IP
+Note that
+.B \-r
+and
+.B \-R
+options are not compatible.
+.TP
+.BR \-z ", " \-\-unresponsive\-restart
+When a daemon is in an unresponsive state, treat it as being shut down for
+the restart purposes.
+.TP
+.BR \-a ", " \-\-all\-restart
+When zebra hangs or crashes, restart all daemons taking the following
+steps: (1) stop all other daemons, (2) restart zebra, and (3) start other
+daemons again.
+.IP
+Note that this option also requires
+.BR \-r ,
+.BR \-s ,
+and
+.B \-k
+options to be specified.
+.TP
+.BR \-A ", " \-\-always\-all\-restart
+When any daemon (i.e., not just zebra) hangs or crashes, restart all
+daemons taking the following steps: (1) stop all other daemons, (2) restart
+zebra, and (3) start other daemons again.
+.IP
+Note that this option also requires
+.BR \-r ,
+.BR \-s ,
+and
+.B \-k
+options to be specified.
+.TP
+.BI \-p " filename" "\fR, \fB\-\-pid\-file " filename
+Set the process identifier
+.I filename
+(the default value is "/var/run/frr/watchfrr.pid").
+.TP
+.BI \-b " string" "\fR, \fB\-\-blank\-string " string
+When the supplied
+.I string
+is found in any of the command line option arguments (i.e.,
+.BR \-r ,
+.BR \-s ,
+.BR \-k ,
+or
+.BR \-R ),
+replace it with a space.
+.IP
+This is an ugly hack to circumvent problems with passing the command line
+arguments containing embedded spaces.
+.TP
+.BR \-v ", " \-\-version
+Display the version information and exit.
+.TP
+.BR \-h ", " \-\-help
+Display the usage information and exit.
+.SH SEE ALSO
+.BR zebra (8),
+.BR bgpd (8),
+.BR isisd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR ripd (8),
+.BR ripngd (8)
+.PP
+See the project homepage at <@PACKAGE_URL@>.
+.SH AUTHORS
+Copyright 2004 Andrew J. Schorr
+++ /dev/null
-.\" This file was originally generated by help2man 1.36.
-.TH WATCHQUAGGA 8 "July 2010"
-.SH NAME
-watchquagga \- a program to monitor the status of quagga daemons
-.SH SYNOPSIS
-.B watchquagga
-.RI [ option ...]
-.IR daemon ...
-.br
-.B watchquagga
-.BR \-h " | " \-v
-.SH DESCRIPTION
-.B watchquagga
-is a watchdog program that monitors the status of supplied quagga
-.IR daemon s
-and tries to restart them in case they become unresponsive or shut down.
-.PP
-To determine whether a daemon is running, it tries to connect to the
-daemon's VTY UNIX stream socket, and send echo commands to ensure the
-daemon responds. When the daemon crashes, EOF is received from the socket,
-so that watchquagga can react immediately.
-.PP
-This program can run in one of the following 5 modes:
-.TP
-.B Mode 0: monitor
-In this mode, the program serves as a monitor and reports status changes.
-.IP
-Example usage: watchquagga \-d zebra ospfd bgpd
-.TP
-.B Mode 1: global restart
-In this mode, whenever a daemon hangs or crashes, the given command is used
-to restart all watched daemons.
-.IP
-Example usage: watchquagga \-dz \e
-.br
--R '/sbin/service zebra restart; /sbin/service ospfd restart' \e
-.br
-zebra ospfd
-.TP
-.B Mode 2: individual daemon restart
-In this mode, whenever a single daemon hangs or crashes, the given command
-is used to restart this daemon only.
-.IP
-Example usage: watchquagga \-dz \-r '/sbin/service %s restart' \e
-.br
-zebra ospfd bgpd
-.TP
-.B Mode 3: phased zebra restart
-In this mode, whenever a single daemon hangs or crashes, the given command
-is used to restart this daemon only. The only exception is the zebra
-daemon; in this case, the following steps are taken: (1) all other daemons
-are stopped, (2) zebra is restarted, and (3) other daemons are started
-again.
-.IP
-Example usage: watchquagga \-adz \-r '/sbin/service %s restart' \e
-.br
-\-s '/sbin/service %s start' \e
-.br
-\-k '/sbin/service %s stop' zebra ospfd bgpd
-.TP
-.B Mode 4: phased global restart for any failure
-In this mode, whenever a single daemon hangs or crashes, the following
-steps are taken: (1) all other daemons are stopped, (2) zebra is restarted,
-and (3) other daemons are started again.
-.IP
-Example usage: watchquagga \-Adz \-r '/sbin/service %s restart' \e
-.br
-\-s '/sbin/service %s start' \e
-.br
-\-k '/sbin/service %s stop' zebra ospfd bgpd
-.PP
-Important: It is believed that mode 2 (individual daemon restart) is not
-safe, and mode 3 (phased zebra restart) may not be safe with certain
-routing daemons.
-.PP
-In order to avoid restarting the daemons in quick succession, you can
-supply the
-.B \-m
-and
-.B \-M
-options to set the minimum and maximum delay between the restart commands.
-The minimum restart delay is recalculated each time a restart is attempted.
-If the time since the last restart attempt exceeds twice the value of
-.BR \-M ,
-the restart delay is set to the value of
-.BR \-m ,
-otherwise the interval is doubled (but capped at the value of
-.BR \-M ).
-.SH OPTIONS
-.TP
-.BR \-d ", " \-\-daemon
-Run in daemon mode. When supplied, error messages are sent to Syslog
-instead of standard output (stdout).
-.TP
-.BI \-S " directory" "\fR, \fB\-\-statedir " directory
-Set the VTY socket
-.I directory
-(the default value is "/var/run/quagga").
-.TP
-.BR \-e ", " \-\-no\-echo
-Do not ping the daemons to test whether they respond. This option is
-necessary if one or more daemons do not support the echo command.
-.TP
-.BI \-l " level" "\fR, \fB\-\-loglevel " level
-Set the logging
-.I level
-(the default value is "6"). The value should range from 0 (LOG_EMERG) to 7
-(LOG_DEBUG), but higher number can be supplied if extra debugging messages
-are required.
-.TP
-.BI \-m " number" "\fR, \fB\-\-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
-Set the maximum
-.I number
-of seconds to wait between invocations of the daemon restart commands (the
-default value is "600").
-.TP
-.BI \-i " number" "\fR, \fB\-\-interval " number
-Set the status polling interval in seconds (the default value is "5").
-.TP
-.BI \-t " number" "\fR, \fB\-\-timeout " number
-Set the unresponsiveness timeout in seconds (the default value is "10").
-.TP
-.BI \-T " number" "\fR, \fB\-\-restart\-timeout " number
-Set the restart (kill) timeout in seconds (the default value is "20"). If
-any background jobs are still running after this period has elapsed, they
-will be killed.
-.TP
-.BI \-r " command" "\fR, \fB\-\-restart " command
-Supply a Bourne shell
-.I command
-to restart a single daemon. The command string should contain the '%s'
-placeholder to be substituted with the daemon name.
-.IP
-Note that
-.B \-r
-and
-.B \-R
-options are not compatible.
-.TP
-.BI \-s " command" "\fR, \fB\-\-start\-command " command
-Supply a Bourne shell
-.I command
-to start a single daemon. The command string should contain the '%s'
-placeholder to be substituted with the daemon name.
-.TP
-.BI \-k " command" "\fR, \fB\-\-kill\-command " command
-Supply a Bourne shell
-.I command
-to stop a single daemon. The command string should contain the '%s'
-placeholder to be substituted with the daemon name.
-.TP
-.BR \-R ", " \-\-restart\-all
-When one or more daemons are shut down, try to restart them using the
-Bourne shell command supplied on the command line.
-.IP
-Note that
-.B \-r
-and
-.B \-R
-options are not compatible.
-.TP
-.BR \-z ", " \-\-unresponsive\-restart
-When a daemon is in an unresponsive state, treat it as being shut down for
-the restart purposes.
-.TP
-.BR \-a ", " \-\-all\-restart
-When zebra hangs or crashes, restart all daemons taking the following
-steps: (1) stop all other daemons, (2) restart zebra, and (3) start other
-daemons again.
-.IP
-Note that this option also requires
-.BR \-r ,
-.BR \-s ,
-and
-.B \-k
-options to be specified.
-.TP
-.BR \-A ", " \-\-always\-all\-restart
-When any daemon (i.e., not just zebra) hangs or crashes, restart all
-daemons taking the following steps: (1) stop all other daemons, (2) restart
-zebra, and (3) start other daemons again.
-.IP
-Note that this option also requires
-.BR \-r ,
-.BR \-s ,
-and
-.B \-k
-options to be specified.
-.TP
-.BI \-p " filename" "\fR, \fB\-\-pid\-file " filename
-Set the process identifier
-.I filename
-(the default value is "/var/run/quagga/watchquagga.pid").
-.TP
-.BI \-b " string" "\fR, \fB\-\-blank\-string " string
-When the supplied
-.I string
-is found in any of the command line option arguments (i.e.,
-.BR \-r ,
-.BR \-s ,
-.BR \-k ,
-or
-.BR \-R ),
-replace it with a space.
-.IP
-This is an ugly hack to circumvent problems with passing the command line
-arguments containing embedded spaces.
-.TP
-.BR \-v ", " \-\-version
-Display the version information and exit.
-.TP
-.BR \-h ", " \-\-help
-Display the usage information and exit.
-.SH SEE ALSO
-.BR zebra (8),
-.BR bgpd (8),
-.BR isisd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR ripd (8),
-.BR ripngd (8)
-.PP
-See the project homepage at <http://www.quagga.net/>.
-.SH AUTHORS
-Copyright 2004 Andrew J. Schorr
+++ /dev/null
-.TH ZEBRA 8 "25 November 2004" "Zebra daemon" "Version 0.97.3"
-.SH NAME
-zebra \- a routing manager for use with associated Quagga components.
-.SH SYNOPSIS
-.B zebra
-[
-.B \-bdhklrv
-] [
-.B \-f
-.I config-file
-] [
-.B \-i
-.I pid-file
-] [
-.B \-P
-.I port-number
-] [
-.B \-A
-.I vty-address
-] [
-.B \-u
-.I user
-] [
-.B \-g
-.I group
-]
-.SH DESCRIPTION
-.B zebra
-is a routing manager that implements the
-.B zebra
-route engine.
-.B zebra
-supports RIPv1, RIPv2, RIPng, OSPF, OSPF6, IS-IS, BGP4+, and BGP4-.
-.SH OPTIONS
-Options available for the
-.B zebra
-command:
-.TP
-\fB\-b\fR, \fB\-\-batch\fR
-Runs in batch mode, \fBzebra\fR parses its config and exits.
-.TP
-\fB\-d\fR, \fB\-\-daemon\fR
-Runs in daemon mode, forking and exiting from tty.
-.TP
-\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
-Specifies the config file to use for startup. If not specified this
-option will likely default to \fB\fI/usr/local/etc/zebra.conf\fR.
-.TP
-\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
-Specify the group to run as. Default is \fIquagga\fR.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-A brief message.
-.TP
-\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
-When zebra starts its process identifier is written to
-\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
-restart zebra. The likely default is \fB\fI/var/run/zebra.pid\fR.
-.TP
-\fB\-k\fR, \fB\-\-keep_kernel\fR
-On startup, don't delete self inserted routes.
-.TP
-\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
-Specify the port that the zebra VTY will listen on. This defaults to
-2601, as specified in \fB\fI/etc/services\fR.
-.TP
-\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
-Specify the address that the zebra VTY will listen on. Default is all
-interfaces.
-.TP
-\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
-Specify the user to run as. Default is \fIquagga\fR.
-.TP
-\fB\-r\fR, \fB\-\-retain\fR
-When the program terminates, retain routes added by \fBzebra\fR.
-.TP
-\fB\-s\fR, \fB\-\-nl-bufsize \fR\fInetlink-buffer-size\fR
-Set netlink receive buffer size. There are cases where zebra daemon can't
-handle flood of netlink messages from kernel. If you ever see "recvmsg overrun"
-messages in zebra log, you are in trouble.
-
-Solution is to increase receive buffer of netlink socket. Note that kernel
-< 2.6.14 doesn't allow to increase it over maximum value defined in
-\fI/proc/sys/net/core/rmem_max\fR. If you want to do it, you have to increase
-maximum before starting zebra.
-
-Note that this affects Linux only.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Print the version and exit.
-.SH FILES
-.TP
-.BI /usr/lib/quagga/zebra
-The default location of the
-.B zebra
-binary.
-.TP
-.BI /etc/quagga/zebra.conf
-The default location of the
-.B zebra
-config file.
-.TP
-.BI $(PWD)/zebra.log
-If the
-.B zebra
-process is config'd to output logs to a file, then you will find this
-file in the directory where you started \fBzebra\fR.
-.SH WARNING
-This man page is intended to be a quick reference for command line
-options. The definitive document is the Info file \fBQuagga\fR.
-.SH DIAGNOSTICS
-The zebra process may log to standard output, to a VTY, to a log
-file, or through syslog to the system logs. \fBzebra\fR supports many
-debugging options, see the Info file, or the source for details.
-.SH "SEE ALSO"
-.BR bgpd (8),
-.BR ripd (8),
-.BR ripngd (8),
-.BR ospfd (8),
-.BR ospf6d (8),
-.BR isisd (8),
-.BR vtysh (1)
-.SH BUGS
-.B zebra
-eats bugs for breakfast. If you have food for the maintainers try
-.BI http://bugzilla.quagga.net
-.SH AUTHORS
-See
-.BI http://www.zebra.org
-and
-.BI http://www.quagga.net
-or the Info file for an accurate list of authors.
-
--- /dev/null
+.TH ZEBRA 8 "25 November 2004" "Zebra daemon" "Version @PACKAGE_VERSION@"
+.SH NAME
+zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components.
+.SH SYNOPSIS
+.B zebra
+[
+.B \-bdhklrv
+] [
+.B \-f
+.I config-file
+] [
+.B \-i
+.I pid-file
+] [
+.B \-P
+.I port-number
+] [
+.B \-A
+.I vty-address
+] [
+.B \-u
+.I user
+] [
+.B \-g
+.I group
+]
+.SH DESCRIPTION
+.B zebra
+is a routing manager that implements the
+.B zebra
+route engine.
+.B zebra
+supports RIPv1, RIPv2, RIPng, OSPF, OSPF6, IS-IS, BGP4+, and BGP4-.
+.SH OPTIONS
+Options available for the
+.B zebra
+command:
+.TP
+\fB\-b\fR, \fB\-\-batch\fR
+Runs in batch mode, \fBzebra\fR parses its config and exits.
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Runs in daemon mode, forking and exiting from tty.
+.TP
+\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR
+Specifies the config file to use for startup. If not specified this
+option will default to \fB\fI@CFG_SYSCONF@/zebra.conf\fR.
+.TP
+\fB\-g\fR, \fB\-\-group \fR\fIgroup\fR
+Specify the group to run as. Default is \fI@enable_group@\fR.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+A brief message.
+.TP
+\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR
+When zebra starts its process identifier is written to
+\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
+restart zebra. The default is \fB\fI@CFG_STATE@/zebra.pid\fR.
+.TP
+\fB\-k\fR, \fB\-\-keep_kernel\fR
+On startup, don't delete self inserted routes.
+.TP
+\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
+Specify the port that the zebra VTY will listen on. This defaults to
+2601, as specified in \fB\fI/etc/services\fR.
+.TP
+\fB\-A\fR, \fB\-\-vty_addr \fR\fIvty-address\fR
+Specify the address that the zebra VTY will listen on. Default is all
+interfaces.
+.TP
+\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
+Specify the user to run as. Default is \fI@enable_user@\fR.
+.TP
+\fB\-r\fR, \fB\-\-retain\fR
+When the program terminates, retain routes added by \fBzebra\fR.
+.TP
+\fB\-s\fR, \fB\-\-nl-bufsize \fR\fInetlink-buffer-size\fR
+Set netlink receive buffer size. There are cases where zebra daemon can't
+handle flood of netlink messages from kernel. If you ever see "recvmsg overrun"
+messages in zebra log, you are in trouble.
+
+Solution is to increase receive buffer of netlink socket. Note that kernel
+< 2.6.14 doesn't allow to increase it over maximum value defined in
+\fI/proc/sys/net/core/rmem_max\fR. If you want to do it, you have to increase
+maximum before starting zebra.
+
+Note that this affects Linux only.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version and exit.
+.SH FILES
+.TP
+.BI @CFG_SBIN@/zebra
+The default location of the
+.B zebra
+binary.
+.TP
+.BI @CFG_SYSCONF@/zebra.conf
+The default location of the
+.B zebra
+config file.
+.TP
+.BI $(PWD)/zebra.log
+If the
+.B zebra
+process is config'd to output logs to a file, then you will find this
+file in the directory where you started \fBzebra\fR.
+.SH WARNING
+This man page is intended to be a quick reference for command line
+options. The definitive document is the Info file \fB@PACKAGE_NAME@\fR.
+.SH DIAGNOSTICS
+The zebra process may log to standard output, to a VTY, to a log
+file, or through syslog to the system logs. \fBzebra\fR supports many
+debugging options, see the Info file, or the source for details.
+.SH "SEE ALSO"
+.BR bgpd (8),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR isisd (8),
+.BR vtysh (1)
+.SH BUGS
+.B zebra
+eats bugs for breakfast. If you have food for the maintainers try
+.BI @PACKAGE_BUGREPORT@
+.SH AUTHORS
+See
+.BI http://www.zebra.org
+and
+.BI @PACKAGE_URL@
+or the Info file for an accurate list of authors.
+
};
struct zebra_privs_t isisd_privs = {
-#if defined(QUAGGA_USER)
- .user = QUAGGA_USER,
+#if defined(FRR_USER)
+ .user = FRR_USER,
#endif
-#if defined QUAGGA_GROUP
- .group = QUAGGA_GROUP,
+#if defined FRR_GROUP
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);
/* Print banner. */
- zlog_notice ("Quagga-ISISd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ zlog_notice ("Quagga-ISISd %s starting: vty@%d", FRR_VERSION, vty_port);
/* Start finite state machine. */
while (thread_fetch (master, &thread))
REDIST_STR
"Redistribute IPv4 routes\n"
"Redistribute IPv6 routes\n"
- QUAGGA_REDIST_HELP_STR_ISISD
+ FRR_REDIST_HELP_STR_ISISD
"Redistribute into level-1\n"
"Redistribute into level-2\n"
"Metric for redistributed routes\n"
REDIST_STR
"Redistribute IPv4 routes\n"
"Redistribute IPv6 routes\n"
- QUAGGA_REDIST_HELP_STR_ISISD
+ FRR_REDIST_HELP_STR_ISISD
"Redistribute into level-1\n"
"Redistribute into level-2\n")
{
else
SUBTLV_TYPE(mtc->unrsv_bw) = 0;
- if (IS_PARAM_SET(ifp->link_params, LP_TE))
+ if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
set_circuitparams_te_metric(mtc, ifp->link_params->te_metric);
else
SUBTLV_TYPE(mtc->te_metric) = 0;
spftree_area_init (area);
- if (is_type & IS_LEVEL_1)
- lsp_generate (area, IS_LEVEL_1);
- if (is_type & IS_LEVEL_2)
- lsp_generate (area, IS_LEVEL_2);
+ if (listcount (area->area_addrs) > 0)
+ {
+ if (is_type & IS_LEVEL_1)
+ lsp_generate (area, IS_LEVEL_1);
+ if (is_type & IS_LEVEL_2)
+ lsp_generate (area, IS_LEVEL_2);
+ }
lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1);
return;
static struct zebra_privs_t lde_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
struct zebra_privs_t ldpd_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit(status);
vty_serv_sock(vty_addr, vty_port, LDP_VTYSH_PATH);
/* Print banner. */
- log_notice("LDPd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ log_notice("LDPd %s starting: vty@%d", FRR_VERSION, vty_port);
/* Fetch next active thread. */
while (thread_fetch(master, &thread))
struct zebra_privs_t ldpe_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
#include "smux.h"
#include "memory.h"
#include "linklist.h"
+#include "version.h"
static int agentx_enabled = 0;
{
if (!agentx_enabled)
{
- init_snmp("quagga");
+ init_snmp(FRR_SMUX_NAME);
events = list_new();
agentx_events_update ();
agentx_enabled = 1;
SNMP_CALLBACK_LOGGING,
agentx_log_callback,
NULL);
- init_agent ("quagga");
+ init_agent (FRR_SMUX_NAME);
install_node (&agentx_node, config_write_agentx);
install_element (CONFIG_NODE, &agentx_enable_cmd);
};
/* Default motd string. */
-static const char *default_motd =
-"\r\n\
-Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
-" QUAGGA_COPYRIGHT "\r\n\
-" GIT_INFO "\r\n";
-
+static const char *default_motd = FRR_DEFAULT_MOTD;
static const struct facility_map {
int facility;
void
print_version (const char *progname)
{
- printf ("%s version %s\n", progname, QUAGGA_VERSION);
- printf ("%s\n", QUAGGA_COPYRIGHT);
- printf ("configured with:\n\t%s\n", QUAGGA_CONFIG_ARGS);
+ printf ("%s version %s\n", progname, FRR_VERSION);
+ printf ("%s\n", FRR_COPYRIGHT);
+ printf ("configured with:\n\t%s\n", FRR_CONFIG_ARGS);
}
if (vector_slot (v, i))
strsize += strlen ((char *) vector_slot (v, i)) + 1;
+ if (strsize == 0)
+ return XSTRDUP (MTYPE_TMP, "");
+
char *concatenated = calloc (sizeof (char), strsize);
for (unsigned int i = 0; i < vector_active (v); i++)
{
SHOW_STR
"Displays zebra version\n")
{
- vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name?host.name:"",
- VTY_NEWLINE);
- vty_out (vty, "%s%s%s", QUAGGA_COPYRIGHT, GIT_INFO, VTY_NEWLINE);
+ vty_out (vty, "%s %s (%s).%s", FRR_FULL_NAME, FRR_VERSION,
+ host.name ? host.name : "",
+ VTY_NEWLINE);
+ vty_out (vty, "%s%s%s", FRR_COPYRIGHT, GIT_INFO, VTY_NEWLINE);
vty_out (vty, "configured with:%s %s%s", VTY_NEWLINE,
- QUAGGA_CONFIG_ARGS, VTY_NEWLINE);
+ FRR_CONFIG_ARGS, VTY_NEWLINE);
return CMD_SUCCESS;
}
*
* terminal = 0 -- vtysh / no logging, no config control
* terminal = 1 -- normal daemon
- * terminal = -1 -- watchquagga / no logging, but minimal config control */
+ * terminal = -1 -- watchfrr / no logging, but minimal config control */
void
cmd_init (int terminal)
{
struct cmd_token *
new_cmd_token (enum cmd_token_type type, u_char attr, char *text, char *desc)
{
- struct cmd_token *token = XMALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
+ struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
token->type = type;
token->attr = attr;
token->text = text;
token->desc = desc;
token->arg = NULL;
+ token->allowrepeat = false;
return token;
}
child = vector_slot (node->to, i);
size_t j;
struct cmd_token *token = child->data;
- if (!token->allowrepeat)
+ if (!token->allowrepeat && stack)
{
for (j = 0; j < stackpos; j++)
if (child == stack[j])
sizeof (struct if_link_params));
if (iflp == NULL) return NULL;
- /* Set TE metric == standard metric */
+ /* Set TE metric equal to standard metric */
iflp->te_metric = ifp->metric;
/* Compute default bandwidth based on interface */
iflp->unrsv_bw[i] = iflp->default_bw;
/* Update Link parameters status */
- iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
+ iflp->lp_status = LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
/* Finally attach newly created Link Parameters */
ifp->link_params = iflp;
#define MAX_CLASS_TYPE 8
#define MAX_PKT_LOSS 50.331642
-/* Link Parameters Status: 0: unset, 1: set, */
+/*
+ * Link Parameters Status:
+ * equal to 0: unset
+ * different from 0: set
+ */
#define LP_UNSET 0x0000
-#define LP_TE 0x0001
+#define LP_TE_METRIC 0x0001
#define LP_MAX_BW 0x0002
#define LP_MAX_RSV_BW 0x0004
#define LP_UNRSV_BW 0x0008
#define LP_RES_BW 0x0400
#define LP_AVA_BW 0x0800
#define LP_USE_BW 0x1000
-#define LP_TE_METRIC 0x2000
#define IS_PARAM_UNSET(lp, st) !(lp->lp_status & st)
#define IS_PARAM_SET(lp, st) (lp->lp_status & st)
* 02111-1307, USA.
*/
-#define QUAGGA_DEFINE_DESC_TABLE
+#define FRR_DEFINE_DESC_TABLE
#include <zebra.h>
"ISIS",
"PIM",
"RFP",
- "WATCHQUAGGA",
+ "WATCHFRR",
NULL,
};
return ZEBRA_ROUTE_BGP;
else if (strncmp (s, "ta", 2) == 0)
return ZEBRA_ROUTE_TABLE;
- else if (strncmp (s, "v", 1) == 0)
- return ZEBRA_ROUTE_VNC;
- else if (strncmp (s, "vd", 1) == 0)
+ else if (strcmp (s, "vnc-direct") == 0)
return ZEBRA_ROUTE_VNC_DIRECT;
+ else if (strcmp (s, "vnc") == 0)
+ return ZEBRA_ROUTE_VNC;
}
if (afi == AFI_IP6)
{
return ZEBRA_ROUTE_BGP;
else if (strncmp (s, "ta", 2) == 0)
return ZEBRA_ROUTE_TABLE;
- else if (strncmp (s, "v", 1) == 0)
- return ZEBRA_ROUTE_VNC;
- else if (strncmp (s, "vd", 1) == 0)
+ else if (strcmp (s, "vnc-direct") == 0)
return ZEBRA_ROUTE_VNC_DIRECT;
+ else if (strcmp (s, "vnc") == 0)
+ return ZEBRA_ROUTE_VNC;
}
return -1;
}
ZLOG_ISIS,
ZLOG_PIM,
ZLOG_RFP,
- ZLOG_WATCHQUAGGA,
+ ZLOG_WATCHFRR,
} zlog_proto_t;
/* If maxlvl is set to ZLOG_DISABLED, then no messages will be sent
strncpy (cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_pton (AF_INET6, cp, &p->prefix);
- free (cp);
+ XFREE (MTYPE_TMP, cp);
if (ret == 0)
return 0;
plen = (u_char) atoi (++pnt);
prefix2str (union prefix46constptr pu, char *str, int size)
{
const struct prefix *p = pu.p;
- char buf[PREFIX2STR_BUFFER];
-
- if (p->family == AF_ETHERNET) {
- int i;
- char *s = str;
-
- assert(size > (3*ETHER_ADDR_LEN) + 1 /* slash */ + 3 /* plen */ );
- for (i = 0; i < ETHER_ADDR_LEN; ++i) {
- sprintf(s, "%02x", p->u.prefix_eth.octet[i]);
- if (i < (ETHER_ADDR_LEN - 1)) {
- *(s+2) = ':';
- s += 3;
- } else {
- s += 2;
- }
+
+ if (p->family == AF_ETHERNET)
+ {
+ snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
+ p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
+ p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
+ p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
+ p->prefixlen);
+ }
+ else
+ {
+ char buf[PREFIX2STR_BUFFER];
+ inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
+ snprintf(str, size, "%s/%d", buf, p->prefixlen);
}
- sprintf(s, "/%d", p->prefixlen);
- return 0;
- }
- snprintf (str, size, "%s/%d",
- inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER),
- p->prefixlen);
return str;
}
# else: 7-field line
my @f = split(/,/, $_);
- unless (@f == 7) {
+ unless (@f == 7 || @f == 8) {
die "invalid input on route_types line $.\n";
}
"ipv4" => int($f[4]),
"ipv6" => int($f[5]),
"shorthelp" => $f[6],
+ "restrict2" => $f[7],
};
push @protos, $proto;
$daemons{$f[2]} = {
/* Auto-generated from route_types.txt by %s. */
/* Do not edit! */
-#ifndef _QUAGGA_ROUTE_TYPES_H
-#define _QUAGGA_ROUTE_TYPES_H
+#ifndef _FRR_ROUTE_TYPES_H
+#define _FRR_ROUTE_TYPES_H
/* Zebra route's' types. */
EOF
my (@names, @help) = ((), ());
for my $p (@protos) {
next if ($protodetail{$p}->{"daemon"} eq $daemon && $daemon ne "zebra");
+ next if ($protodetail{$p}->{"restrict2"} ne "" &&
+ $protodetail{$p}->{"restrict2"} ne $daemon);
next unless (($ipv4 && $protodetail{$p}->{"ipv4"})
|| ($ipv6 && $protodetail{$p}->{"ipv6"}));
push @names, $protodetail{$p}->{"cname"};
printf "/* %s */\n", $daemon;
if ($daemons{$daemon}->{"ipv4"} && $daemons{$daemon}->{"ipv6"}) {
my ($names, $help) = collect($daemon, 1, 1, 0);
- printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
($names, $help) = collect($daemon, 1, 0, 0);
- printf "#define QUAGGA_IP_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_IP_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_IP_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_IP_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
($names, $help) = collect($daemon, 0, 1, 0);
- printf "#define QUAGGA_IP6_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_IP6_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_IP6_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_IP6_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
if ($daemon eq "zebra") {
($names, $help) = collect($daemon, 1, 0, 1);
- printf "#define QUAGGA_IP_PROTOCOL_MAP_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_IP_PROTOCOL_MAP_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_IP_PROTOCOL_MAP_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_IP_PROTOCOL_MAP_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
($names, $help) = collect($daemon, 0, 1, 1);
- printf "#define QUAGGA_IP6_PROTOCOL_MAP_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_IP6_PROTOCOL_MAP_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_IP6_PROTOCOL_MAP_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
}
} else {
my ($names, $help) = collect($daemon,
$daemons{$daemon}->{"ipv4"}, $daemons{$daemon}->{"ipv6"}, 0);
- printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
- printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
+ printf "#define FRR_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
+ printf "#define FRR_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
}
print "\n";
}
print <<EOF;
-#ifdef QUAGGA_DEFINE_DESC_TABLE
+#ifdef FRR_DEFINE_DESC_TABLE
struct zebra_desc_table
{
};
#undef DESC_ENTRY
-#endif /* QUAGGA_DEFINE_DESC_TABLE */
+#endif /* FRR_DEFINE_DESC_TABLE */
-#endif /* _QUAGGA_ROUTE_TYPES_H */
+#endif /* _FRR_ROUTE_TYPES_H */
EOF
#vnc when sent to zebra
ZEBRA_ROUTE_VNC, vnc, NULL, 'v', 1, 1, "VNC"
# vnc when sent to bgp
-ZEBRA_ROUTE_VNC_DIRECT, vpn, NULL, 'V', 1, 1, "VPN"
-# vnc when sent to bgp (remote next hop?)
-ZEBRA_ROUTE_VNC_DIRECT_RH, vpn-rh, NULL, 'V', 0, 0, "VPN"
+ZEBRA_ROUTE_VNC_DIRECT, vnc-direct,NULL, 'V', 1, 1, "VNC-Direct", bgpd
+# vnc when sent to bgp (resolve NVE mode)
+ZEBRA_ROUTE_VNC_DIRECT_RH, vnc-rn, NULL, 'V', 0, 0, "VNC-RN"
# bgp unicast -> vnc
ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL, 'b', 0, 0, "BGP-Direct"
# bgp unicast -> vnc
ZEBRA_ROUTE_OLSR, "Optimised Link State Routing (OLSR)"
ZEBRA_ROUTE_TABLE, "Non-main Kernel Routing Table"
ZEBRA_ROUTE_LDP, "Label Distribution Protocol (LDP)"
-ZEBRA_ROUTE_VNC_DIRECT, "VPN routes(VPN)"
+ZEBRA_ROUTE_VNC_DIRECT, "VNC direct (not via zebra) routes"
/* Print the name of the protocol */
if (zlog_default)
+ {
vty_out (vty, "%s", zlog_proto_names[zlog_default->protocol]);
- if (zlog_default->instance)
- vty_out (vty, " %d", zlog_default->instance);
+ if (zlog_default->instance)
+ vty_out (vty, " %d", zlog_default->instance);
+ }
vty_out (vty, ":%s", VTY_NEWLINE);
for (index = map->head; index; index = index->next)
struct route_map_index *index = VTY_GET_CONTEXT (route_map_index);
const char *rmap = argv[idx_word]->arg;
- if (index)
+ assert(index);
+
+ if (index->nextrm)
{
- if (index->nextrm)
- {
- route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED,
- index->nextrm,
- index->map->name);
- XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm);
- }
- index->nextrm = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
+ route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED,
+ index->nextrm,
+ index->map->name);
+ XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm);
}
+ index->nextrm = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
/* Execute event hook. */
route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED,
}
for (i = 1; i < ROUTE_MAP_DEP_MAX; i++)
- hash_free(route_map_dep_hash[i]);
+ {
+ hash_free(route_map_dep_hash[i]);
+ route_map_dep_hash[i] = NULL;
+ }
hash_free (route_map_master_hash);
+ route_map_master_hash = NULL;
}
/* Initialization of route map vector. */
u_char *ptr;
size_t len;
long version;
- const char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION;
+ const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION;
if (debug_smux)
{
#define GIT_INFO ""
#endif
-#define QUAGGA_PROGNAME "@PACKAGE_NAME@"
-
-#define QUAGGA_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX
-
-#define ZEBRA_BUG_ADDRESS "@PACKAGE_BUGREPORT@"
-
-#define QUAGGA_URL "http://www.quagga.net"
-
-#define QUAGGA_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al."
-
-#define QUAGGA_CONFIG_ARGS "@CONFIG_ARGS@"
+#define FRR_PAM_NAME "@PACKAGE_NAME@"
+#define FRR_SMUX_NAME "@PACKAGE_NAME@"
+#define FRR_PTM_NAME "@PACKAGE_NAME@"
+
+#define FRR_FULL_NAME "FreeRangeRouting"
+#define FRR_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX
+#define FRR_BUG_ADDRESS "@PACKAGE_BUGREPORT@"
+#define FRR_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al."
+#define FRR_CONFIG_ARGS "@CONFIG_ARGS@"
+
+#define FRR_DEFAULT_MOTD \
+ "\r\n" \
+ "Hello, this is " FRR_FULL_NAME " (version " FRR_VERSION ").\r\n" \
+ FRR_COPYRIGHT "\r\n" \
+ GIT_INFO "\r\n"
pid_t pid_output (const char *);
if (ret == CMD_SUSPEND)
break;
- /* warning: watchquagga hardcodes this result write */
+ /* warning: watchfrr hardcodes this result write */
header[3] = ret;
buffer_put(vty->obuf, header, 4);
* always set to 255 in new zserv.
*/
uint8_t version;
-#define ZSERV_VERSION 3
+#define ZSERV_VERSION 4
vrf_id_t vrf_id;
uint16_t command;
};
* the command value in the old zserv header. To allow old and new
* Zserv headers to be distinguished from each other.
*/
-#define ZEBRA_HEADER_MARKER 255
+#define ZEBRA_HEADER_MARKER 254
/* Zebra route's types are defined in route_types.h */
#include "route_types.h"
/* Subsequent Address Family Identifier. */
#define SAFI_UNICAST 1
#define SAFI_MULTICAST 2
-#define SAFI_RESERVED_3 3
-#define SAFI_MPLS_VPN 4
+#define SAFI_MPLS_VPN 3
+#define SAFI_RESERVED_4 4
#define SAFI_ENCAP 7 /* per IANA */
+#define SAFI_RESERVED_5 5
#define SAFI_MAX 8
/* Default Administrative Distance of each protocol. */
ospf6_redistribute_cmd,
"redistribute <kernel|connected|static|ripng|isis|bgp|table>",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_OSPF6D)
+ FRR_REDIST_HELP_STR_OSPF6D)
{
int type;
ospf6_redistribute_routemap_cmd,
"redistribute <kernel|connected|static|ripng|isis|bgp|table> route-map WORD",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_OSPF6D
+ FRR_REDIST_HELP_STR_OSPF6D
"Route map reference\n"
"Route map name\n")
{
"no redistribute <kernel|connected|static|ripng|isis|bgp|table> [route-map WORD]",
NO_STR
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_OSPF6D
+ FRR_REDIST_HELP_STR_OSPF6D
"Route map reference\n"
"Route map name\n")
{
return CMD_SUCCESS;
}
-
int
ospf6_redistribute_config_write (struct vty *vty)
{
struct zebra_privs_t ospf6d_privs =
{
-#if defined(QUAGGA_USER)
- .user = QUAGGA_USER,
+#if defined(FRR_USER)
+ .user = FRR_USER,
#endif
-#if defined QUAGGA_GROUP
- .group = QUAGGA_GROUP,
+#if defined FRR_GROUP
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
/* Print start message */
zlog_notice ("OSPF6d (Quagga-%s ospf6d-%s) starts: vty@%d",
- QUAGGA_VERSION, OSPF6_DAEMON_VERSION,vty_port);
+ FRR_VERSION, OSPF6_DAEMON_VERSION,vty_port);
/* Start finite state machine, here we go! */
while (thread_fetch (master, &thread))
install_element (ENABLE_NODE, &show_debugging_ospf_instance_cmd);
install_element (ENABLE_NODE, &debug_ospf_packet_cmd);
install_element (ENABLE_NODE, &no_debug_ospf_packet_cmd);
- install_element (ENABLE_NODE, &debug_ospf_ism_cmd);
- install_element (ENABLE_NODE, &no_debug_ospf_ism_cmd);
install_element (ENABLE_NODE, &debug_ospf_instance_nsm_cmd);
install_element (ENABLE_NODE, &debug_ospf_instance_lsa_cmd);
install_element (ENABLE_NODE, &no_debug_ospf_instance_nssa_cmd);
install_element (ENABLE_NODE, &no_debug_ospf_cmd);
-
-
install_element (CONFIG_NODE, &debug_ospf_packet_cmd);
install_element (CONFIG_NODE, &no_debug_ospf_packet_cmd);
install_element (CONFIG_NODE, &debug_ospf_ism_cmd);
install_element (CONFIG_NODE, &debug_ospf_event_cmd);
install_element (CONFIG_NODE, &debug_ospf_nssa_cmd);
install_element (CONFIG_NODE, &debug_ospf_te_cmd);
- install_element (CONFIG_NODE, &no_debug_ospf_ism_cmd);
install_element (CONFIG_NODE, &no_debug_ospf_nsm_cmd);
install_element (CONFIG_NODE, &no_debug_ospf_lsa_cmd);
install_element (CONFIG_NODE, &no_debug_ospf_zebra_cmd);
struct zebra_privs_t ospfd_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
}
/* Create VTY socket */
if (instance)
{
- sprintf(pid_file, "/var/run/quagga/ospfd-%d.pid", instance);
- sprintf(vty_path, "/var/run/quagga/ospfd-%d.vty", instance);
+ sprintf(pid_file, "%s/ospfd-%d.pid", DAEMON_VTY_DIR, instance);
+ sprintf(vty_path, "%s/ospfd-%d.vty", DAEMON_VTY_DIR, instance);
}
else
{
vty_serv_sock (vty_addr, vty_port, vty_path);
/* Print banner. */
- zlog_notice ("OSPFd %s starting: vty@%d, %s", QUAGGA_VERSION, vty_port, vty_path);
+ zlog_notice ("OSPFd %s starting: vty@%d, %s", FRR_VERSION, vty_port, vty_path);
/* Fetch next active thread. */
while (thread_fetch (master, &thread))
else
TLV_TYPE(lp->unrsv_bw) = 0;
- if (IS_PARAM_SET(ifp->link_params, LP_TE))
+ if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
set_linkparams_te_metric(lp, ifp->link_params->te_metric);
else
TLV_TYPE(lp->te_metric) = 0;
ospf_redistribute_source_cmd,
"redistribute <kernel|connected|static|rip|isis|bgp|pim|table> [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
REDIST_STR
- QUAGGA_REDIST_HELP_STR_OSPFD
+ FRR_REDIST_HELP_STR_OSPFD
"Metric for redistributed routes\n"
"OSPF default metric\n"
"OSPF exterior metric type for redistributed routes\n"
"no redistribute <kernel|connected|static|rip|isis|bgp|pim|table> [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
NO_STR
REDIST_STR
- QUAGGA_REDIST_HELP_STR_OSPFD
+ FRR_REDIST_HELP_STR_OSPFD
"Metric for redistributed routes\n"
"OSPF default metric\n"
"OSPF exterior metric type for redistributed routes\n"
"Filter networks in routing updates\n"
"Access-list name\n"
OUT_STR
- QUAGGA_REDIST_HELP_STR_OSPFD)
+ FRR_REDIST_HELP_STR_OSPFD)
{
VTY_DECLVAR_CONTEXT(ospf, ospf);
int idx_word = 1;
"Filter networks in routing updates\n"
"Access-list name\n"
OUT_STR
- QUAGGA_REDIST_HELP_STR_OSPFD)
+ FRR_REDIST_HELP_STR_OSPFD)
{
VTY_DECLVAR_CONTEXT(ospf, ospf);
int idx_word = 2;
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
# Everton da Silva Marques <everton.marques@gmail.com>
$ more ~/.gitconfig
[user]
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
C1 IGMPv3 backward compatibility with IGMPv1 and IGMPv2 is not
implemented. See RFC 3376, 7.3. Multicast Router Behavior. That's
because only Source-Specific Multicast is currently targeted.
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
global configuration commands:
pimd:
ip multicast-routing Enable IP multicast forwarding
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
DEBUG HINTS
- Check the source is issuing multicast packets with TTL high enough
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
#
# The Linux Kernel MFC (Multicast Forwarding Cache)
#
## Process this file with automake to produce Makefile.in.
-## $QuaggaId: $Format:%an, %ai, %h$ $
# qpimd - pimd for quagga
# Copyright (C) 2008 Everton da Silva Marques
-#
-# $QuaggaId: $Format:%an, %ai, %h$ $
-#
-
INTRODUCTION
qpimd aims to implement a PIM (Protocol Independent Multicast)
-# $QuaggaId: $Format:%an, %ai, %h$ $
-
T1 DONE Implement debug command
test pim receive join
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_ASSERT_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_CMD_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_HELLO_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_IFACE_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_IFCHANNEL_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_IGMP_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_IGMP_JOIN_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_IGMPV3_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_INT_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_JOIN_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_MACRO_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
/* pimd privileges to run with */
struct zebra_privs_t pimd_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
break;
case 'v':
printf(PIMD_PROGNAME " version %s\n", PIMD_VERSION);
- print_version(QUAGGA_PROGNAME);
+ print_version(progname);
exit (0);
break;
#ifdef PIM_ZCLIENT_DEBUG
master = thread_master_create();
zlog_notice("Quagga %s " PIMD_PROGNAME " %s starting",
- QUAGGA_VERSION, PIMD_VERSION);
+ FRR_VERSION, PIMD_VERSION);
/*
* Initializations
vty_serv_sock(vty_addr, vty_port, PIM_VTYSH_PATH);
zlog_notice("Quagga %s " PIMD_PROGNAME " %s starting, VTY interface at port TCP %d",
- QUAGGA_VERSION, PIMD_VERSION, vty_port);
+ FRR_VERSION, PIMD_VERSION, vty_port);
#ifdef PIM_DEBUG_BYDEFAULT
zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands");
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_MROUTE_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_MSG_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_NEIGHBOR_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_OIL_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_PIM_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_RPF_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_SIGNALS_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_SOCK_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_SSMPINGD_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_STATIC_H_
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_STR_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_TIME_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_TLV_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_UPSTREAM_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_UTIL_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_VERSION_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_VTY_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_ZEBRA_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIM_ZLOOKUP_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
!
! pimd sample configuration file
-! $QuaggaId: $Format:%an, %ai, %h$ $
!
hostname quagga-pimd-router
password zebra
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#ifndef PIMD_H
along with this program; see the file COPYING; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA
-
- $QuaggaId: $Format:%an, %ai, %h$ $
*/
#include <zebra.h>
EXTRA_DIST = bgpd.init isisd.init \
ospf6d.init ospfd.init ldpd.init \
- quagga.logrotate quagga.pam quagga.spec \
- quagga.sysconfig ripd.init ripngd.init \
- watchquagga.init pimd.init zebra.init \
+ frr.logrotate frr.pam frr.spec \
+ frr.sysconfig ripd.init ripngd.init \
+ watchfrr.init pimd.init zebra.init \
README.rpm_build.md
-Building your own Quagga RPM
-============================
+Building your own FreeRangeRouting RPM
+======================================
(Tested on CentOS 6, CentOS 7 and Fedora 22.)
1. Install the following packages to build the RPMs:
(use `dnf install` on new Fedora instead of `yum install `)
-2. Checkout Quagga under a **unpriviledged** user account
+2. Checkout FRR under a **unpriviledged** user account
- git clone git://git.savannah.nongnu.org/quagga.git quagga
+ git clone https://github.com/freerangerouting/frr.git frr
3. Run Bootstrap and make distribution tar.gz
- cd quagga
+ cd frr
./bootstrap.sh
./configure --with-pkg-extra-version=-MyRPMVersion
make dist
mkdir rpmbuild/SOURCES
mkdir rpmbuild/SPECS
cp redhat/*.spec rpmbuild/SPECS/
- cp quagga*.tar.gz rpmbuild/SOURCES/
+ cp frr*.tar.gz rpmbuild/SOURCES/
-5. Edit rpm/SPECS/quagga.spec with configuration as needed
+5. Edit rpm/SPECS/frr.spec with configuration as needed
Look at the beginning of the file and adjust the following parameters to enable
or disable features as required:
- ################# Quagga configure options ####################
+ ################# frr configure options ####################
# with-feature options
%{!?with_snmp: %global with_snmp 1 }
%{!?with_vtysh: %global with_vtysh 1 }
%{!?with_ldpd: %global with_ldpd 0 }
%{!?with_shared: %global with_shared 1 }
%{!?with_multipath: %global with_multipath 64 }
- %{!?quagga_user: %global quagga_user quagga }
- %{!?vty_group: %global vty_group quaggavt }
+ %{!?frr_user: %global frr_user frr }
+ %{!?vty_group: %global vty_group frrvt }
%{!?with_fpm: %global with_fpm 0 }
- %{!?with_watchquagga: %global with_watchquagga 1 }
+ %{!?with_watchfrr: %global with_watchfrr 1 }
6. Build the RPM
- rpmbuild --define "_topdir `pwd`/rpmbuild" -ba rpmbuild/SPECS/quagga.spec
+ rpmbuild --define "_topdir `pwd`/rpmbuild" -ba rpmbuild/SPECS/frr.spec
DONE.
chkconfig bgpd on
... etc
-2. If you want to run `watchquagga`, then configure `/etc/sysconfig/quagga`
- and uncomment the line with the daemons for `watchquagga` to monitor,
- then enable watchquagga
+2. If you want to run `watchfrr`, then configure `/etc/sysconfig/frr`
+ and uncomment the line with the daemons for `watchfrr` to monitor,
+ then enable watchfrr
- chkconfig watchquagga on
+ chkconfig watchfrr on
3. Check your firewall / IPtables to make sure the routing protocols are
allowed.
service ospfd start
... etc
-Configuration is stored in `/etc/quagga/*.conf` files.
+Configuration is stored in `/etc/frr/*.conf` files.
### systemd based systems (ie CentOS 7, Fedora 22)
systemctl enable bgpd
... etc
- Note: There is no watchquagga on systemd based systems. Systemd contains
+ Note: There is no watchfrr on systemd based systems. Systemd contains
the functionality of monitoring and restarting daemons.
2. Check your firewall / IPtables to make sure the routing protocols are
systemctl start ospfd
... etc
-Configuration is stored in `/etc/quagga/*.conf` files.
+Configuration is stored in `/etc/frr/*.conf` files.
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/bgpd.conf
+# config: /etc/frr/bgpd.conf
### BEGIN INIT INFO
# Provides: bgpd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="bgpd"
cmd=bgpd
LOCK_FILE=/var/lock/subsys/bgpd
-CONF_FILE=/etc/quagga/bgpd.conf
+CONF_FILE=/etc/frr/bgpd.conf
case "$1" in
start)
--- /dev/null
+/var/log/frr/zebra.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/zebra.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/bgpd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/bgpd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/isisd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/isisd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/ospfd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/ospfd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/ospf6d.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/ospf6d.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/ripd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/ripd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/ripngd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/ripngd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
+/var/log/frr/ldpd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/ldpd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
--- /dev/null
+#%PAM-1.0
+#
+
+##### if running frr as root:
+# Only allow root (and possibly wheel) to use this because enable access
+# is unrestricted.
+auth sufficient pam_rootok.so
+
+# Uncomment the following line to implicitly trust users in the "wheel" group.
+#auth sufficient pam_wheel.so trust use_uid
+# Uncomment the following line to require a user to be in the "wheel" group.
+#auth required pam_wheel.so use_uid
+###########################################################
+
+# If using frr privileges and with a seperate group for vty access, then
+# access can be controlled via the vty access group, and pam can simply
+# check for valid user/password, eg:
+#
+# only allow local users.
+#auth required pam_securetty.so
+#auth include system-auth
+#auth required pam_nologin.so
+#account include system-auth
+#password include system-auth
+#session include system-auth
+#session optional pam_console.so
--- /dev/null
+# configure options
+#
+# Some can be overriden on rpmbuild commandline with:
+# rpmbuild --define 'variable value'
+# (use any value, ie 1 for flag "with_XXXX" definitions)
+#
+# E.g. rpmbuild --define 'release_rev 02' may be useful if building
+# rpms again and again on the same day, so the newer rpms can be installed.
+# bumping the number each time.
+
+####################### FreeRangeRouting (FRR) configure options #########################
+# with-feature options
+%{!?with_tcp_zebra: %global with_tcp_zebra 0 }
+%{!?with_pam: %global with_pam 0 }
+%{!?with_ospfclient: %global with_ospfclient 1 }
+%{!?with_ospfapi: %global with_ospfapi 1 }
+%{!?with_irdp: %global with_irdp 1 }
+%{!?with_rtadv: %global with_rtadv 1 }
+%{!?with_mpls: %global with_mpls 0 }
+%{!?with_ldpd: %global with_ldpd 0 }
+%{!?with_shared: %global with_shared 1 }
+%{!?with_multipath: %global with_multipath 256 }
+%{!?frr_user: %global frr_user frr }
+%{!?vty_group: %global vty_group frrvty }
+%{!?with_fpm: %global with_fpm 0 }
+%{!?with_watchfrr: %global with_watchfrr 1 }
+%{!?with_bgp_vnc: %global with_bgp_vnc 0 }
+
+# path defines
+%define _sysconfdir /etc/frr
+%define _sbindir /usr/lib/frr
+%define zeb_src %{_builddir}/%{name}-%{frrversion}
+%define zeb_rh_src %{zeb_src}/redhat
+%define zeb_docs %{zeb_src}/doc
+%define frr_tools %{zeb_src}/tools
+%define cumulus_dir %{zeb_src}/cumulus/etc
+
+# defines for configure
+%define _localstatedir /var/run/frr
+############################################################################
+
+#### Version String tweak
+# Remove invalid characters form version string and replace with _
+%{expand: %%global rpmversion %(echo '@VERSION@' | tr [:blank:]- _ )}
+%define frrversion @VERSION@
+
+#### Check version of texi2html
+# Old versions don't support "--number-footnotes" option.
+%{expand: %%global texi2htmlversion %(/usr/bin/texi2html --version | cut -d. -f1)}
+
+#### Check for systemd or init.d (upstart)
+# Check for init.d (upstart) as used in CentOS 6 or systemd (ie CentOS 7)
+%{expand: %%global initsystem %(if [[ `/sbin/init --version 2> /dev/null` =~ upstart ]]; then echo upstart; elif [[ `systemctl` =~ -\.mount ]]; then echo systemd; fi)}
+#
+# If init system is systemd, then always disable watchfrr
+#
+%if "%{initsystem}" == "systemd"
+ # Note: For systems with systemd, watchfrr will NOT be built. Systemd
+ # takes over the role of restarting crashed processes. Value will
+ # be overwritten with 0 below for systemd independent on the setting here
+ %global with_watchfrr 1
+%endif
+
+# if FPM is enabled, then enable tcp_zebra as well
+#
+%if %{with_fpm}
+ %global with_tcp_zebra 1
+%endif
+
+# misc internal defines
+%{!?frr_uid: %global frr_uid 92 }
+%{!?frr_gid: %global frr_gid 92 }
+%{!?vty_gid: %global vty_gid 85 }
+
+%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospfd6d
+
+%if %{with_ldpd}
+%define daemon_ldpd ldpd
+%else
+%define daemon_ldpd ""
+%endif
+
+%if %{with_watchfrr}
+%define daemon_watchfrr watchfrr
+%else
+%define daemon_watchfrr ""
+%endif
+
+%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_watchfrr}
+
+# allow build dir to be kept
+%{!?keep_build: %global keep_build 0 }
+
+#release sub-revision (the two digits after the CONFDATE)
+%{!?release_rev: %global release_rev 01 }
+
+Summary: Routing daemon
+Name: frr
+Version: %{rpmversion}
+Release: @CONFDATE@%{release_rev}%{?dist}
+License: GPLv2+
+Group: System Environment/Daemons
+Source0: http://www.freerangerouting.org/releases/frr/%{name}-%{frrversion}.tar.gz
+URL: http://www.freerangerouting.org
+Requires: ncurses json-c
+Requires(pre): /sbin/install-info
+Requires(preun): /sbin/install-info
+Requires(post): /sbin/install-info
+BuildRequires: texi2html texinfo autoconf patch libcap-devel groff
+BuildRequires: readline readline-devel ncurses ncurses-devel
+BuildRequires: json-c-devel bison flex
+Requires: ncurses initscripts
+%if %{with_pam}
+BuildRequires: pam-devel
+Requires: pam
+%endif
+%if "%{initsystem}" == "systemd"
+BuildRequires: systemd
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+%else
+# Initscripts > 5.60 is required for IPv6 support
+Requires(pre): initscripts >= 5.60
+%endif
+Provides: routingdaemon = %{version}-%{release}
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+Obsoletes: bird gated mrt zebra frr-sysvinit
+
+%description
+FreeRangeRouting is a free software that manages TCP/IP based routing
+protocol. It takes multi-server and multi-thread approach to resolve
+the current complexity of the Internet.
+
+FreeRangeRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM
+and LDP
+
+FreeRangeRouting is a fork of Quagga.
+
+%package contrib
+Summary: contrib tools for frr
+Group: System Environment/Daemons
+
+%description contrib
+Contributed/3rd party tools which may be of use with frr.
+
+%package devel
+Summary: Header and object files for frr development
+Group: System Environment/Daemons
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+The frr-devel package contains the header and object files neccessary for
+developing OSPF-API and frr applications.
+
+%prep
+%setup -q -n frr-%{frrversion}
+
+%build
+
+# For standard gcc verbosity, uncomment these lines:
+#CFLAGS="%{optflags} -Wall -Wsign-compare -Wpointer-arith"
+#CFLAGS="${CFLAGS} -Wbad-function-cast -Wwrite-strings"
+
+# For ultra gcc verbosity, uncomment these lines also:
+#CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes"
+#CFLAGS="${CFLAGS} -Wmissing-declarations -Wmissing-noreturn"
+#CFLAGS="${CFLAGS} -Wmissing-format-attribute -Wunreachable-code"
+#CFLAGS="${CFLAGS} -Wpacked -Wpadded"
+
+%configure \
+ --sbindir=%{_sbindir} \
+ --sysconfdir=%{_sysconfdir} \
+ --libdir=%{_libdir} \
+ --libexecdir=%{_libexecdir} \
+ --localstatedir=%{_localstatedir} \
+ --disable-werror \
+%if !%{with_shared}
+ --disable-shared \
+%endif
+%if %{with_multipath}
+ --enable-multipath=%{with_multipath} \
+%endif
+%if %{with_tcp_zebra}
+ --enable-tcp-zebra \
+%endif
+ --enable-vtysh \
+%if %{with_ospfclient}
+ --enable-ospfclient=yes \
+%else
+ --enable-ospfclient=no\
+%endif
+%if %{with_ospfapi}
+ --enable-ospfapi=yes \
+%else
+ --enable-ospfapi=no \
+%endif
+%if %{with_irdp}
+ --enable-irdp=yes \
+%else
+ --enable-irdp=no \
+%endif
+%if %{with_rtadv}
+ --enable-rtadv=yes \
+%else
+ --enable-rtadv=no \
+%endif
+%if %{with_mpls}
+ --enable-mpls=yes \
+%else
+ --disable-mpls \
+%endif
+%if %{with_ldpd}
+ --enable-ldpd \
+%else
+ --disable-ldpd \
+%endif
+%if %{with_pam}
+ --with-libpam \
+%endif
+%if 0%{?frr_user:1}
+ --enable-user=%frr_user \
+ --enable-group=%frr_user \
+%endif
+%if 0%{?vty_group:1}
+ --enable-vty-group=%vty_group \
+%endif
+%if %{with_fpm}
+ --enable-fpm \
+%else
+ --disable-fpm \
+%endif
+%if %{with_watchfrr}
+ --enable-watchfrr \
+%else
+ --disable-watchfrr \
+%endif
+%if %{with_bgp_vnc}
+ --enable-bgp-vnc \
+%else
+ --disable-bgp-vnc \
+%endif
+ --enable-gcc-rdynamic \
+ --enable-isisd=yes \
+ --enable-systemd=yes \
+ --enable-poll=yes
+
+make %{?_smp_mflags} MAKEINFO="makeinfo --no-split"
+
+pushd doc
+%if %{texi2htmlversion} < 5
+texi2html --number-sections frr.texi
+%else
+texi2html --number-footnotes --number-sections frr.texi
+%endif
+popd
+
+%install
+mkdir -p %{buildroot}/etc/{frr,sysconfig,logrotate.d,pam.d,default} \
+ %{buildroot}/var/log/frr %{buildroot}%{_infodir}
+make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install
+
+# Remove this file, as it is uninstalled and causes errors when building on RH9
+rm -rf %{buildroot}/usr/share/info/dir
+
+
+# install /etc sources
+%if "%{initsystem}" == "systemd"
+mkdir -p %{buildroot}%{_unitdir}
+install %{frr_tools}/frr.service \
+ %{buildroot}%{_unitdir}/frr.service
+%else
+mkdir -p %{buildroot}/etc/rc.d/init.d
+for daemon in %{all_daemons} ; do
+ if [ x"${daemon}" != x"" ] ; then
+ install %{zeb_rh_src}/${daemon}.init \
+ %{buildroot}/etc/rc.d/init.d/${daemon}
+ fi
+done
+%endif
+
+install %{cumulus_dir}/frr/debian.conf %{buildroot}/etc/frr
+install %{cumulus_dir}/frr/daemons %{buildroot}/etc/frr
+install -m644 %{cumulus_dir}/default/frr %{buildroot}/etc/default
+install -m644 %{zeb_rh_src}/frr.pam \
+ %{buildroot}/etc/pam.d/frr
+install -m644 %{zeb_rh_src}/frr.logrotate \
+ %{buildroot}/etc/logrotate.d/frr
+install -d -m750 %{buildroot}/var/run/frr
+
+%pre
+# add vty_group
+%if 0%{?vty_group:1}
+if getent group %vty_group > /dev/null ; then : ; else \
+ /usr/sbin/groupadd -r -g %vty_gid %vty_group > /dev/null || : ; fi
+%endif
+
+# add frr user and group
+%if 0%{?frr_user:1}
+# Ensure that frr_gid gets correctly allocated
+if getent group %frr_user >/dev/null; then : ; else \
+ /usr/sbin/groupadd -g %frr_gid %frr_user > /dev/null || : ; \
+fi
+if getent passwd %frr_user >/dev/null ; then : ; else \
+ /usr/sbin/useradd -u %frr_uid -g %frr_gid \
+ -M -r -s /sbin/nologin -c "FreeRangeRouting suite" \
+ -d %_localstatedir %frr_user 2> /dev/null || : ; \
+fi
+%if 0%{?vty_group:1}
+/usr/sbin/usermod -a -G %vty_group %frr_user
+%endif
+%endif
+
+
+%post
+# zebra_spec_add_service <service name> <port/proto> <comment>
+# e.g. zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
+
+zebra_spec_add_service ()
+{
+ # Add port /etc/services entry if it isn't already there
+ if [ -f /etc/services ] && \
+ ! %__sed -e 's/#.*$//' /etc/services | %__grep -wq $1 ; then
+ echo "$1 $2 # $3" >> /etc/services
+ fi
+}
+
+zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
+zebra_spec_add_service zebra 2601/tcp "zebra vty"
+zebra_spec_add_service ripd 2602/tcp "RIPd vty"
+zebra_spec_add_service ripngd 2603/tcp "RIPngd vty"
+zebra_spec_add_service ospfd 2604/tcp "OSPFd vty"
+zebra_spec_add_service bgpd 2605/tcp "BGPd vty"
+zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty"
+%if %{with_ospfapi}
+zebra_spec_add_service ospfapi 2607/tcp "OSPF-API"
+%endif
+zebra_spec_add_service isisd 2608/tcp "ISISd vty"
+zebra_spec_add_service pimd 2611/tcp "PIMd vty"
+%if %{with_ldpd}
+zebra_spec_add_service ldpd 2612/tcp "LDPd vty"
+%endif
+
+%if "%{initsystem}" == "systemd"
+for daemon in %all_daemons ; do
+ %systemd_post frr.service
+done
+%else
+for daemon in %all_daemons ; do
+ /sbin/chkconfig --add ${daemon}
+done
+%endif
+
+/sbin/install-info %{_infodir}/frr.info.gz %{_infodir}/dir
+
+# Create dummy files if they don't exist so basic functions can be used.
+if [ ! -e %{_sysconfdir}/zebra.conf ]; then
+ echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf
+%if 0%{?frr_user:1}
+ chown %frr_user:%frr_user %{_sysconfdir}/zebra.conf*
+%endif
+ chmod 640 %{_sysconfdir}/zebra.conf
+fi
+for daemon in %{all_daemons} ; do
+ if [ ! -e %{_sysconfdir}/${daemon}.conf ]; then
+ touch %{_sysconfdir}/${daemon}.conf
+ %if 0%{?frr_user:1}
+ chown %frr_user:%frr_user %{_sysconfdir}/${daemon}.conf*
+ %endif
+ fi
+done
+%if %{with_watchfrr}
+ # No config for watchfrr - this is part of /etc/sysconfig/frr
+ rm -f %{_sysconfdir}/watchfrr.*
+%endif
+
+if [ ! -e %{_sysconfdir}/vtysh.conf ]; then
+ touch %{_sysconfdir}/vtysh.conf
+ chmod 640 %{_sysconfdir}/vtysh.conf
+%if 0%{?vty_group:1}
+ chown frr:%{vty_group} %{_sysconfdir}/vtysh.conf*
+%endif
+fi
+
+%postun
+if [ "$1" -ge 1 ]; then
+ # Find out which daemons need to be restarted.
+ for daemon in %all_daemons ; do
+ if [ -f /var/lock/subsys/${daemon} ]; then
+ eval restart_${daemon}=yes
+ else
+ eval restart_${daemon}=no
+ fi
+ done
+ # Rename restart flags for daemons handled specially.
+ running_zebra="$restart_zebra"
+ restart_zebra=no
+ %if %{with_watchfrr}
+ running_watchfrr="$restart_watchfrr"
+ restart_watchfrr=no
+ %endif
+
+ %if "%{initsystem}" == "systemd"
+ ##
+ ## Systemd Version
+ ##
+ # No watchfrr for systemd version
+ #
+ # Stop all daemons other than zebra.
+ for daemon in %all_daemons ; do
+ eval restart=\$restart_${daemon}
+ [ "$restart" = yes ] && \
+ %systemd_postun ${daemon}.service
+ done
+ # Restart zebra.
+ [ "$running_zebra" = yes ] && \
+ %systemd_postun_with_restart $daemon.service
+ # Start all daemons other than zebra.
+ for daemon in %all_daemons ; do
+ eval restart=\$restart_${daemon}
+ [ "$restart" = yes ] && \
+ %systemd_post ${daemon}.service
+ done
+ %else
+ ##
+ ## init.d Version
+ ##
+ %if %{with_watchfrr}
+ # Stop watchfrr first.
+ [ "$running_watchfrr" = yes ] && \
+ /etc/rc.d/init.d/watchfrr stop >/dev/null 2>&1
+ %endif
+ # Stop all daemons other than zebra and watchfrr.
+ for daemon in %all_daemons ; do
+ eval restart=\$restart_${daemon}
+ [ "$restart" = yes ] && \
+ /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1
+ done
+ # Restart zebra.
+ [ "$running_zebra" = yes ] && \
+ /etc/rc.d/init.d/zebra restart >/dev/null 2>&1
+ # Start all daemons other than zebra and watchfrr.
+ for daemon in %all_daemons ; do
+ eval restart=\$restart_${daemon}
+ [ "$restart" = yes ] && \
+ /etc/rc.d/init.d/${daemon} start >/dev/null 2>&1
+ done
+ %if %{with_watchfrr}
+ # Start watchfrr last.
+ # Avoid postun scriptlet error if watchfrr is not running.
+ [ "$running_watchfrr" = yes ] && \
+ /etc/rc.d/init.d/watchfrr start >/dev/null 2>&1 || :
+ %endif
+ %endif
+fi
+
+%preun
+%if "%{initsystem}" == "systemd"
+ ##
+ ## Systemd Version
+ ##
+ if [ "$1" = "0" ]; then
+ for daemon in %all_daemons ; do
+ %systemd_preun ${daemon}.service
+ done
+ fi
+%else
+ ##
+ ## init.d Version
+ ##
+ if [ "$1" = "0" ]; then
+ for daemon in %all_daemons ; do
+ /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1
+ /sbin/chkconfig --del ${daemon}
+ done
+ fi
+%endif
+/sbin/install-info --delete %{_infodir}/frr.info.gz %{_infodir}/dir
+
+%clean
+%if !0%{?keep_build:1}
+rm -rf %{buildroot}
+%endif
+
+%files
+%defattr(-,root,root)
+%doc */*.sample* AUTHORS COPYING
+%doc doc/frr.html
+%doc doc/mpls
+%doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES
+%if 0%{?frr_user:1}
+%dir %attr(751,%frr_user,%frr_user) %{_sysconfdir}
+%dir %attr(750,%frr_user,%frr_user) /var/log/frr
+%dir %attr(751,%frr_user,%frr_user) /var/run/frr
+%else
+%dir %attr(750,root,root) %{_sysconfdir}
+%dir %attr(750,root,root) /var/log/frr
+%dir %attr(750,root,root) /var/run/frr
+%endif
+%if 0%{?vty_group:1}
+%attr(750,%frr_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample
+%endif
+%{_infodir}/frr.info.gz
+%{_mandir}/man*/*
+%{_sbindir}/zebra
+%{_sbindir}/ospfd
+%{_sbindir}/ripd
+%{_sbindir}/bgpd
+%{_sbindir}/ssd
+%{_sbindir}/frr
+%{_sbindir}/frr-reload.py
+%{_sbindir}/frr-reload.pyc
+%{_sbindir}/frr-reload.pyo
+%if %{with_watchfrr}
+ %{_sbindir}/watchfrr
+%endif
+%{_sbindir}/ripngd
+%{_sbindir}/ospf6d
+%{_sbindir}/pimd
+%{_sbindir}/isisd
+%if %{with_ldpd}
+%{_sbindir}/ldpd
+%endif
+%if %{with_shared}
+%attr(755,root,root) %{_libdir}/lib*.so
+%attr(755,root,root) %{_libdir}/lib*.so.*
+%endif
+%{_bindir}/*
+%config /etc/frr/[!v]*
+%if "%{initsystem}" == "systemd"
+ %config %{_unitdir}/frr.service
+%else
+ %config /etc/rc.d/init.d/zebra
+ %if %{with_watchfrr}
+ %config /etc/rc.d/init.d/watchfrr
+ %endif
+ %config /etc/rc.d/init.d/ripd
+ %config /etc/rc.d/init.d/ospfd
+ %config /etc/rc.d/init.d/bgpd
+ %config /etc/rc.d/init.d/ripngd
+ %config /etc/rc.d/init.d/ospf6d
+ %config /etc/rc.d/init.d/isisd
+ %config /etc/rc.d/init.d/pimd
+ %if %{with_ldpd}
+ %config /etc/rc.d/init.d/ldpd
+ %endif
+%endif
+%config(noreplace) /etc/default/frr
+%config(noreplace) /etc/pam.d/frr
+%config(noreplace) %attr(640,root,root) /etc/logrotate.d/*
+
+%files contrib
+%defattr(-,root,root)
+%doc tools
+
+%files devel
+%defattr(-,root,root)
+%if %{with_ospfclient}
+%{_sbindir}/ospfclient
+%endif
+%{_libdir}/*.a
+%{_libdir}/*.la
+%dir %attr(755,root,root) %{_includedir}/%{name}
+%{_includedir}/%name/*.h
+%dir %attr(755,root,root) %{_includedir}/%{name}/ospfd
+%{_includedir}/%name/ospfd/*.h
+%if %{with_ospfapi}
+%dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi
+%{_includedir}/%name/ospfapi/*.h
+%endif
+
+%changelog
+* Fri Jan 6 2017 Martin Winter <mwinter@opensourcerouting.org>
+- Renamed to frr for FreeRangeRouting fork of Quagga
+
+* Thu Feb 11 2016 Paul Jakma <paul@jakma.org> - %{version}
+- remove with_ipv6 conditionals, always build v6
+- Fix UTF-8 char in spec changelog
+- remove quagga.pam.stack, long deprecated.
+
+* Thu Oct 22 2015 Martin Winter <mwinter@opensourcerouting.org>
+- Cleanup configure: remove --enable-ipv6 (default now), --enable-nssa,
+ --enable-netlink
+- Remove support for old fedora 4/5
+- Fix for package nameing
+- Fix Weekdays of previous changelogs (bogus dates)
+- Add conditional logic to only build tex footnotes with supported texi2html
+- Added pimd to files section and fix double listing of /var/lib*/quagga
+- Numerous fixes to unify upstart/systemd startup into same spec file
+- Only allow use of watchfrr for non-systemd systems. no need with systemd
+
+* Fri Sep 4 2015 Paul Jakma <paul@jakma.org>
+- buildreq updates
+- add a default define for with_pimd
+
+* Mon Sep 12 2005 Paul Jakma <paul@dishone.st>
+- Steal some changes from Fedora spec file:
+- Add with_rtadv variable
+- Test for groups/users with getent before group/user adding
+- Readline need not be an explicit prerequisite
+- install-info delete should be postun, not preun
+
+* Wed Jan 12 2005 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+- on package upgrade, implement careful, phased restart logic
+- use gcc -rdynamic flag when linking for better backtraces
+
+* Wed Dec 22 2004 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+- daemonv6_list should contain only IPv6 daemons
+
+* Wed Dec 22 2004 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+- watchfrr added
+- on upgrade, all daemons should be condrestart'ed
+- on removal, all daemons should be stopped
+
+* Mon Nov 08 2004 Paul Jakma <paul@dishone.st>
+- Use makeinfo --html to generate quagga.html
+
+* Sun Nov 07 2004 Paul Jakma <paul@dishone.st>
+- Fix with_ipv6 set to 0 build
+
+* Sat Oct 23 2004 Paul Jakma <paul@dishone.st>
+- Update to 0.97.2
+
+* Sat Oct 23 2004 Andrew J. Schorr <aschorr@telemetry-investments.com>
+- Make directories be owned by the packages concerned
+- Update logrotate scripts to use correct path to killall and use pid files
+
+* Fri Oct 08 2004 Paul Jakma <paul@dishone.st>
+- Update to 0.97.0
+
+* Wed Sep 15 2004 Paul Jakma <paul@dishone.st>
+- build snmp support by default
+- build irdp support
+- build with shared libs
+- devel subpackage for archives and headers
+
+* Thu Jan 08 2004 Paul Jakma <paul@dishone.st>
+- updated sysconfig files to specify local dir
+- added ospf_dump.c crash quick fix patch
+- added ospfd persistent interface configuration patch
+
+* Tue Dec 30 2003 Paul Jakma <paul@dishone.st>
+- sync to CVS
+- integrate RH sysconfig patch to specify daemon options (RH)
+- default to have vty listen only to 127.1 (RH)
+- add user with fixed UID/GID (RH)
+- create user with shell /sbin/nologin rather than /bin/false (RH)
+- stop daemons on uninstall (RH)
+- delete info file on preun, not postun to avoid deletion on upgrade. (RH)
+- isisd added
+- cleanup tasks carried out for every daemon
+
+* Sun Nov 2 2003 Paul Jakma <paul@dishone.st>
+- Fix -devel package to include all files
+- Sync to 0.96.4
+
+* Tue Aug 12 2003 Paul Jakma <paul@dishone.st>
+- Renamed to Quagga
+- Sync to Quagga release 0.96
+
+* Thu Mar 20 2003 Paul Jakma <paul@dishone.st>
+- zebra privileges support
+
+* Tue Mar 18 2003 Paul Jakma <paul@dishone.st>
+- Fix mem leak in 'show thread cpu'
+- Ralph Keller's OSPF-API
+- Amir: Fix configure.ac for net-snmp
+
+* Sat Mar 1 2003 Paul Jakma <paul@dishone.st>
+- ospfd IOS prefix to interface matching for 'network' statement
+- temporary fix for PtP and IPv6
+- sync to zebra.org CVS
+
+* Mon Jan 20 2003 Paul Jakma <paul@dishone.st>
+- update to latest cvs
+- Yon's "show thread cpu" patch - 17217
+- walk up tree - 17218
+- ospfd NSSA fixes - 16681
+- ospfd nsm fixes - 16824
+- ospfd OLSA fixes and new feature - 16823
+- KAME and ifindex fixes - 16525
+- spec file changes to allow redhat files to be in tree
+
+* Sat Dec 28 2002 Alexander Hoogerhuis <alexh@ihatent.com>
+- Added conditionals for building with(out) IPv6, vtysh, RIP, BGP
+- Fixed up some build requirements (patch)
+- Added conditional build requirements for vtysh / snmp
+- Added conditional to files for _bindir depending on vtysh
+
+* Mon Nov 11 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add Greg Troxel's md5 buffer copy/dup fix
+- add RIPv1 fix
+- add Frank's multicast flag fix
+
+* Wed Oct 09 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- timestamped crypt_seqnum patch
+- oi->on_write_q fix
+
+* Mon Sep 30 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add vtysh 'write-config (integrated|daemon)' patch
+- always 'make rebuild' in vtysh/ to catch new commands
+
+* Fri Sep 13 2002 Paul Jakma <paulj@alphyra.ie>
+- update to 0.93b
+
+* Wed Sep 11 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add "/sbin/ip route flush proto zebra" to zebra RH init on startup
+
+* Sat Aug 24 2002 Paul Jakma <paulj@alphyra.ie>
+- update to current CVS
+- add OSPF point to multipoint patch
+- add OSPF bugfixes
+- add BGP hash optimisation patch
+
+* Fri Jun 14 2002 Paul Jakma <paulj@alphyra.ie>
+- update to 0.93-pre1 / CVS
+- add link state detection support
+- add generic PtP and RFC3021 support
+- various bug fixes
+
+* Thu Aug 09 2001 Elliot Lee <sopwith@redhat.com> 0.91a-6
+- Fix bug #51336
+
+* Wed Aug 1 2001 Trond Eivind Glomsrød <teg@redhat.com> 0.91a-5
+- Use generic initscript strings instead of initscript specific
+ ( "Starting foo: " -> "Starting $prog:" )
+
+* Fri Jul 27 2001 Elliot Lee <sopwith@redhat.com> 0.91a-4
+- Bump the release when rebuilding into the dist.
+
+* Tue Feb 6 2001 Tim Powers <timp@redhat.com>
+- built for Powertools
+
+* Sun Feb 4 2001 Pekka Savola <pekkas@netcore.fi>
+- Hacked up from PLD Linux 0.90-1, Mandrake 0.90-1mdk and one from zebra.org.
+- Update to 0.91a
+- Very heavy modifications to init.d/*, .spec, pam, i18n, logrotate, etc.
+- Should be quite Red Hat'isque now.
--- /dev/null
+#
+# Default: Bind all daemon vtys to the loopback(s) only
+#
+BGPD_OPTS="-A 127.0.0.1"
+ISISD_OPTS="-A ::1"
+OSPF6D_OPTS="-A ::1"
+OSPFD_OPTS="-A 127.0.0.1"
+RIPD_OPTS="-A 127.0.0.1"
+RIPNGD_OPTS="-A ::1"
+ZEBRA_OPTS="-A 127.0.0.1"
+PIMD_OPTS="-A 127.0.0.1"
+LDPD_OPTS="-A 127.0.0.1"
+
+# Watchfrr configuration for LSB initscripts
+#
+# (Not needed with systemd: the service files are configured to automatically
+# restart any daemon on failure. If zebra fails, all running daemons will be
+# stopped; zebra will be started again; and then the previously running daemons
+# will be started again.)
+#
+# Uncomment and edit this line to reflect the daemons you are actually using:
+#WATCH_DAEMONS="zebra bgpd ospfd ospf6d ripd ripngd"
+#
+# Timer values can be adjusting by editing this line:
+WATCH_OPTS="-Az -b_ -r/sbin/service_%s_restart -s/sbin/service_%s_start -k/sbin/service_%s_stop"
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/isisd.conf
+# config: /etc/frr/isisd.conf
### BEGIN INIT INFO
# Provides: isisd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="isisd"
cmd=isisd
LOCK_FILE=/var/lock/subsys/isisd
-CONF_FILE=/etc/quagga/isisd.conf
+CONF_FILE=/etc/frr/isisd.conf
case "$1" in
start)
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/ldpd.conf
+# config: /etc/frr/ldpd.conf
### BEGIN INIT INFO
# Provides: ldpd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="ldpd"
cmd=ldpd
LOCK_FILE=/var/lock/subsys/ldpd
-CONF_FILE=/etc/quagga/ldpd.conf
+CONF_FILE=/etc/frr/ldpd.conf
case "$1" in
start)
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/ospf6d.conf
+# config: /etc/frr/ospf6d.conf
### BEGIN INIT INFO
# Provides: ospf6d
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="ospf6d"
cmd=ospf6d
LOCK_FILE=/var/lock/subsys/ospf6d
-CONF_FILE=/etc/quagga/ospf6d.conf
+CONF_FILE=/etc/frr/ospf6d.conf
case "$1" in
start)
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/ospfd.conf
+# config: /etc/frr/ospfd.conf
### BEGIN INIT INFO
# Provides: ospfd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="ospfd"
cmd=ospfd
LOCK_FILE=/var/lock/subsys/ospfd
-CONF_FILE=/etc/quagga/ospfd.conf
+CONF_FILE=/etc/frr/ospfd.conf
case "$1" in
start)
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/pimd.conf
+# config: /etc/frr/pimd.conf
### BEGIN INIT INFO
# Provides: pimd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="pimd"
cmd=pimd
LOCK_FILE=/var/lock/subsys/pimd
-CONF_FILE=/etc/quagga/pimd.conf
+CONF_FILE=/etc/frr/pimd.conf
case "$1" in
start)
+++ /dev/null
-/var/log/quagga/zebra.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/zebra.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/bgpd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/bgpd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/isisd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/isisd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/ospfd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/ospfd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/ospf6d.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/ospf6d.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/ripd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/ripd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/ripngd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/ripngd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
-
-/var/log/quagga/ldpd.log {
- notifempty
- missingok
- postrotate
- /bin/kill -USR1 `cat /var/run/quagga/ldpd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
+++ /dev/null
-#%PAM-1.0
-#
-
-##### if running quagga as root:
-# Only allow root (and possibly wheel) to use this because enable access
-# is unrestricted.
-auth sufficient pam_rootok.so
-
-# Uncomment the following line to implicitly trust users in the "wheel" group.
-#auth sufficient pam_wheel.so trust use_uid
-# Uncomment the following line to require a user to be in the "wheel" group.
-#auth required pam_wheel.so use_uid
-###########################################################
-
-# If using quagga privileges and with a seperate group for vty access, then
-# access can be controlled via the vty access group, and pam can simply
-# check for valid user/password, eg:
-#
-# only allow local users.
-#auth required pam_securetty.so
-#auth include system-auth
-#auth required pam_nologin.so
-#account include system-auth
-#password include system-auth
-#session include system-auth
-#session optional pam_console.so
+++ /dev/null
-# configure options
-#
-# Some can be overriden on rpmbuild commandline with:
-# rpmbuild --define 'variable value'
-# (use any value, ie 1 for flag "with_XXXX" definitions)
-#
-# E.g. rpmbuild --define 'release_rev 02' may be useful if building
-# rpms again and again on the same day, so the newer rpms can be installed.
-# bumping the number each time.
-
-####################### Quagga configure options #########################
-# with-feature options
-%{!?with_tcp_zebra: %global with_tcp_zebra 0 }
-%{!?with_pam: %global with_pam 0 }
-%{!?with_ospfclient: %global with_ospfclient 1 }
-%{!?with_ospfapi: %global with_ospfapi 1 }
-%{!?with_irdp: %global with_irdp 1 }
-%{!?with_rtadv: %global with_rtadv 1 }
-%{!?with_mpls: %global with_mpls 0 }
-%{!?with_ldpd: %global with_ldpd 0 }
-%{!?with_shared: %global with_shared 1 }
-%{!?with_multipath: %global with_multipath 256 }
-%{!?quagga_user: %global quagga_user quagga }
-%{!?vty_group: %global vty_group quaggavty }
-%{!?with_fpm: %global with_fpm 0 }
-%{!?with_watchquagga: %global with_watchquagga 1 }
-%{!?with_bgp_vnc: %global with_bgp_vnc 0 }
-
-# path defines
-%define _sysconfdir /etc/quagga
-%define _sbindir /usr/lib/quagga
-%define zeb_src %{_builddir}/%{name}-%{quaggaversion}
-%define zeb_rh_src %{zeb_src}/redhat
-%define zeb_docs %{zeb_src}/doc
-%define quagga_tools %{zeb_src}/tools
-%define cumulus_dir %{zeb_src}/cumulus/etc
-
-# defines for configure
-%define _localstatedir /var/run/quagga
-############################################################################
-
-#### Version String tweak
-# Remove invalid characters form version string and replace with _
-%{expand: %%global rpmversion %(echo '@VERSION@' | tr [:blank:]- _ )}
-%define quaggaversion @VERSION@
-
-#### Check version of texi2html
-# Old versions don't support "--number-footnotes" option.
-%{expand: %%global texi2htmlversion %(/usr/bin/texi2html --version | cut -d. -f1)}
-
-#### Check for systemd or init.d (upstart)
-# Check for init.d (upstart) as used in CentOS 6 or systemd (ie CentOS 7)
-%{expand: %%global initsystem %(if [[ `/sbin/init --version 2> /dev/null` =~ upstart ]]; then echo upstart; elif [[ `systemctl` =~ -\.mount ]]; then echo systemd; fi)}
-#
-# If init system is systemd, then always disable watchquagga
-#
-%if "%{initsystem}" == "systemd"
- # Note: For systems with systemd, watchquagga will NOT be built. Systemd
- # takes over the role of restarting crashed processes. Value will
- # be overwritten with 0 below for systemd independent on the setting here
- %global with_watchquagga 1
-%endif
-
-# if FPM is enabled, then enable tcp_zebra as well
-#
-%if %{with_fpm}
- %global with_tcp_zebra 1
-%endif
-
-# misc internal defines
-%{!?quagga_uid: %global quagga_uid 92 }
-%{!?quagga_gid: %global quagga_gid 92 }
-%{!?vty_gid: %global vty_gid 85 }
-
-%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospfd6d
-
-%if %{with_ldpd}
-%define daemon_ldpd ldpd
-%else
-%define daemon_ldpd ""
-%endif
-
-%if %{with_watchquagga}
-%define daemon_watchquagga watchquagga
-%else
-%define daemon_watchquagga ""
-%endif
-
-%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_watchquagga}
-
-# allow build dir to be kept
-%{!?keep_build: %global keep_build 0 }
-
-#release sub-revision (the two digits after the CONFDATE)
-%{!?release_rev: %global release_rev 01 }
-
-Summary: Routing daemon
-Name: quagga
-Version: %{rpmversion}
-Release: @CONFDATE@%{release_rev}%{?dist}
-License: GPLv2+
-Group: System Environment/Daemons
-Source0: http://download.savannah.gnu.org/releases/quagga/%{name}-%{quaggaversion}.tar.gz
-URL: http://www.quagga.net
-Requires: ncurses
-Requires(pre): /sbin/install-info
-Requires(preun): /sbin/install-info
-Requires(post): /sbin/install-info
-BuildRequires: texi2html texinfo autoconf patch libcap-devel groff
-BuildRequires: readline readline-devel ncurses ncurses-devel
-Requires: ncurses initscripts
-%if %{with_pam}
-BuildRequires: pam-devel
-Requires: pam
-%endif
-%if "%{initsystem}" == "systemd"
-BuildRequires: systemd
-Requires(post): systemd
-Requires(preun): systemd
-Requires(postun): systemd
-%else
-# Initscripts > 5.60 is required for IPv6 support
-Requires(pre): initscripts >= 5.60
-%endif
-Provides: routingdaemon = %{version}-%{release}
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Obsoletes: bird gated mrt zebra quagga-sysvinit
-
-%description
-Quagga is a free software that manages TCP/IP based routing
-protocol. It takes multi-server and multi-thread approach to resolve
-the current complexity of the Internet.
-
-Quagga supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng and PIM.
-
-Quagga is intended to be used as a Route Server and a Route Reflector. It is
-not a toolkit, it provides full routing power under a new architecture.
-Quagga by design has a process for each protocol.
-
-Quagga is a fork of GNU Zebra.
-
-%package contrib
-Summary: contrib tools for quagga
-Group: System Environment/Daemons
-
-%description contrib
-Contributed/3rd party tools which may be of use with quagga.
-
-%package devel
-Summary: Header and object files for quagga development
-Group: System Environment/Daemons
-Requires: %{name} = %{version}-%{release}
-
-%description devel
-The quagga-devel package contains the header and object files neccessary for
-developing OSPF-API and quagga applications.
-
-%prep
-%setup -q -n quagga-%{quaggaversion}
-
-%build
-
-# For standard gcc verbosity, uncomment these lines:
-#CFLAGS="%{optflags} -Wall -Wsign-compare -Wpointer-arith"
-#CFLAGS="${CFLAGS} -Wbad-function-cast -Wwrite-strings"
-
-# For ultra gcc verbosity, uncomment these lines also:
-#CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes"
-#CFLAGS="${CFLAGS} -Wmissing-declarations -Wmissing-noreturn"
-#CFLAGS="${CFLAGS} -Wmissing-format-attribute -Wunreachable-code"
-#CFLAGS="${CFLAGS} -Wpacked -Wpadded"
-
-%configure \
- --sbindir=%{_sbindir} \
- --sysconfdir=%{_sysconfdir} \
- --libdir=%{_libdir} \
- --libexecdir=%{_libexecdir} \
- --localstatedir=%{_localstatedir} \
- --disable-werror \
-%if !%{with_shared}
- --disable-shared \
-%endif
-%if %{with_multipath}
- --enable-multipath=%{with_multipath} \
-%endif
-%if %{with_tcp_zebra}
- --enable-tcp-zebra \
-%endif
- --enable-vtysh \
-%if %{with_ospfclient}
- --enable-ospfclient=yes \
-%else
- --enable-ospfclient=no\
-%endif
-%if %{with_ospfapi}
- --enable-ospfapi=yes \
-%else
- --enable-ospfapi=no \
-%endif
-%if %{with_irdp}
- --enable-irdp=yes \
-%else
- --enable-irdp=no \
-%endif
-%if %{with_rtadv}
- --enable-rtadv=yes \
-%else
- --enable-rtadv=no \
-%endif
-%if %{with_mpls}
- --enable-mpls=yes \
-%else
- --disable-mpls \
-%endif
-%if %{with_ldpd}
- --enable-ldpd \
-%else
- --disable-ldpd \
-%endif
-%if %{with_pam}
- --with-libpam \
-%endif
-%if 0%{?quagga_user:1}
- --enable-user=%quagga_user \
- --enable-group=%quagga_user \
-%endif
-%if 0%{?vty_group:1}
- --enable-vty-group=%vty_group \
-%endif
-%if %{with_fpm}
- --enable-fpm \
-%else
- --disable-fpm \
-%endif
-%if %{with_watchquagga}
- --enable-watchquagga \
-%else
- --disable-watchquagga \
-%endif
-%if %{with_bgp_vnc}
- --enable-bgp-vnc \
-%else
- --disable-bgp-vnc \
-%endif
- --enable-gcc-rdynamic \
- --enable-isisd=yes \
- --enable-systemd=yes \
- --enable-poll=yes
-
-make %{?_smp_mflags} MAKEINFO="makeinfo --no-split"
-
-pushd doc
-%if %{texi2htmlversion} < 5
-texi2html --number-sections quagga.texi
-%else
-texi2html --number-footnotes --number-sections quagga.texi
-%endif
-popd
-
-%install
-mkdir -p %{buildroot}/etc/{quagga,sysconfig,logrotate.d,pam.d,default} \
- %{buildroot}/var/log/quagga %{buildroot}%{_infodir}
-make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install
-
-# Remove this file, as it is uninstalled and causes errors when building on RH9
-rm -rf %{buildroot}/usr/share/info/dir
-
-
-# install /etc sources
-%if "%{initsystem}" == "systemd"
-mkdir -p %{buildroot}%{_unitdir}
-install %{quagga_tools}/quagga.service \
- %{buildroot}%{_unitdir}/quagga.service
-%else
-mkdir -p %{buildroot}/etc/rc.d/init.d
-for daemon in %{all_daemons} ; do
- if [ x"${daemon}" != x"" ] ; then
- install %{zeb_rh_src}/${daemon}.init \
- %{buildroot}/etc/rc.d/init.d/${daemon}
- fi
-done
-%endif
-
-install %{cumulus_dir}/quagga/debian.conf %{buildroot}/etc/quagga
-install %{cumulus_dir}/quagga/daemons %{buildroot}/etc/quagga
-install -m644 %{cumulus_dir}/default/quagga %{buildroot}/etc/default
-install -m644 %{zeb_rh_src}/quagga.pam \
- %{buildroot}/etc/pam.d/quagga
-install -m644 %{zeb_rh_src}/quagga.logrotate \
- %{buildroot}/etc/logrotate.d/quagga
-install -d -m750 %{buildroot}/var/run/quagga
-
-%pre
-# add vty_group
-%if 0%{?vty_group:1}
-if getent group %vty_group > /dev/null ; then : ; else \
- /usr/sbin/groupadd -r -g %vty_gid %vty_group > /dev/null || : ; fi
-%endif
-
-# add quagga user and group
-%if 0%{?quagga_user:1}
-# Ensure that quagga_gid gets correctly allocated
-if getent group %quagga_user >/dev/null; then : ; else \
- /usr/sbin/groupadd -g %quagga_gid %quagga_user > /dev/null || : ; \
-fi
-if getent passwd %quagga_user >/dev/null ; then : ; else \
- /usr/sbin/useradd -u %quagga_uid -g %quagga_gid \
- -M -r -s /sbin/nologin -c "Quagga routing suite" \
- -d %_localstatedir %quagga_user 2> /dev/null || : ; \
-fi
-%if 0%{?vty_group:1}
-/usr/sbin/usermod -a -G %vty_group %quagga_user
-%endif
-%endif
-
-
-%post
-# zebra_spec_add_service <service name> <port/proto> <comment>
-# e.g. zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
-
-zebra_spec_add_service ()
-{
- # Add port /etc/services entry if it isn't already there
- if [ -f /etc/services ] && \
- ! %__sed -e 's/#.*$//' /etc/services | %__grep -wq $1 ; then
- echo "$1 $2 # $3" >> /etc/services
- fi
-}
-
-zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
-zebra_spec_add_service zebra 2601/tcp "zebra vty"
-zebra_spec_add_service ripd 2602/tcp "RIPd vty"
-zebra_spec_add_service ripngd 2603/tcp "RIPngd vty"
-zebra_spec_add_service ospfd 2604/tcp "OSPFd vty"
-zebra_spec_add_service bgpd 2605/tcp "BGPd vty"
-zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty"
-%if %{with_ospfapi}
-zebra_spec_add_service ospfapi 2607/tcp "OSPF-API"
-%endif
-zebra_spec_add_service isisd 2608/tcp "ISISd vty"
-zebra_spec_add_service pimd 2611/tcp "PIMd vty"
-%if %{with_ldpd}
-zebra_spec_add_service ldpd 2612/tcp "LDPd vty"
-%endif
-
-%if "%{initsystem}" == "systemd"
-for daemon in %all_daemons ; do
- %systemd_post quagga.service
-done
-%else
-for daemon in %all_daemons ; do
- /sbin/chkconfig --add ${daemon}
-done
-%endif
-
-/sbin/install-info %{_infodir}/quagga.info.gz %{_infodir}/dir
-
-# Create dummy files if they don't exist so basic functions can be used.
-if [ ! -e %{_sysconfdir}/zebra.conf ]; then
- echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf
-%if 0%{?quagga_user:1}
- chown %quagga_user:%quagga_user %{_sysconfdir}/zebra.conf*
-%endif
- chmod 640 %{_sysconfdir}/zebra.conf
-fi
-for daemon in %{all_daemons} ; do
- if [ ! -e %{_sysconfdir}/${daemon}.conf ]; then
- touch %{_sysconfdir}/${daemon}.conf
- %if 0%{?quagga_user:1}
- chown %quagga_user:%quagga_user %{_sysconfdir}/${daemon}.conf*
- %endif
- fi
-done
-%if %{with_watchquagga}
- # No config for watchquagga - this is part of /etc/sysconfig/quagga
- rm -f %{_sysconfdir}/watchquagga.*
-%endif
-
-if [ ! -e %{_sysconfdir}/vtysh.conf ]; then
- touch %{_sysconfdir}/vtysh.conf
- chmod 640 %{_sysconfdir}/vtysh.conf
-%if 0%{?vty_group:1}
- chown quagga:%{vty_group} %{_sysconfdir}/vtysh.conf*
-%endif
-fi
-
-%postun
-if [ "$1" -ge 1 ]; then
- # Find out which daemons need to be restarted.
- for daemon in %all_daemons ; do
- if [ -f /var/lock/subsys/${daemon} ]; then
- eval restart_${daemon}=yes
- else
- eval restart_${daemon}=no
- fi
- done
- # Rename restart flags for daemons handled specially.
- running_zebra="$restart_zebra"
- restart_zebra=no
- %if %{with_watchquagga}
- running_watchquagga="$restart_watchquagga"
- restart_watchquagga=no
- %endif
-
- %if "%{initsystem}" == "systemd"
- ##
- ## Systemd Version
- ##
- # No watchquagga for systemd version
- #
- # Stop all daemons other than zebra.
- for daemon in %all_daemons ; do
- eval restart=\$restart_${daemon}
- [ "$restart" = yes ] && \
- %systemd_postun ${daemon}.service
- done
- # Restart zebra.
- [ "$running_zebra" = yes ] && \
- %systemd_postun_with_restart $daemon.service
- # Start all daemons other than zebra.
- for daemon in %all_daemons ; do
- eval restart=\$restart_${daemon}
- [ "$restart" = yes ] && \
- %systemd_post ${daemon}.service
- done
- %else
- ##
- ## init.d Version
- ##
- %if %{with_watchquagga}
- # Stop watchquagga first.
- [ "$running_watchquagga" = yes ] && \
- /etc/rc.d/init.d/watchquagga stop >/dev/null 2>&1
- %endif
- # Stop all daemons other than zebra and watchquagga.
- for daemon in %all_daemons ; do
- eval restart=\$restart_${daemon}
- [ "$restart" = yes ] && \
- /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1
- done
- # Restart zebra.
- [ "$running_zebra" = yes ] && \
- /etc/rc.d/init.d/zebra restart >/dev/null 2>&1
- # Start all daemons other than zebra and watchquagga.
- for daemon in %all_daemons ; do
- eval restart=\$restart_${daemon}
- [ "$restart" = yes ] && \
- /etc/rc.d/init.d/${daemon} start >/dev/null 2>&1
- done
- %if %{with_watchquagga}
- # Start watchquagga last.
- # Avoid postun scriptlet error if watchquagga is not running.
- [ "$running_watchquagga" = yes ] && \
- /etc/rc.d/init.d/watchquagga start >/dev/null 2>&1 || :
- %endif
- %endif
-fi
-
-%preun
-%if "%{initsystem}" == "systemd"
- ##
- ## Systemd Version
- ##
- if [ "$1" = "0" ]; then
- for daemon in %all_daemons ; do
- %systemd_preun ${daemon}.service
- done
- fi
-%else
- ##
- ## init.d Version
- ##
- if [ "$1" = "0" ]; then
- for daemon in %all_daemons ; do
- /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1
- /sbin/chkconfig --del ${daemon}
- done
- fi
-%endif
-/sbin/install-info --delete %{_infodir}/quagga.info.gz %{_infodir}/dir
-
-%clean
-%if !0%{?keep_build:1}
-rm -rf %{buildroot}
-%endif
-
-%files
-%defattr(-,root,root)
-%doc */*.sample* AUTHORS COPYING
-%doc doc/quagga.html
-%doc doc/mpls
-%doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES
-%if 0%{?quagga_user:1}
-%dir %attr(751,%quagga_user,%quagga_user) %{_sysconfdir}
-%dir %attr(750,%quagga_user,%quagga_user) /var/log/quagga
-%dir %attr(751,%quagga_user,%quagga_user) /var/run/quagga
-%else
-%dir %attr(750,root,root) %{_sysconfdir}
-%dir %attr(750,root,root) /var/log/quagga
-%dir %attr(750,root,root) /var/run/quagga
-%endif
-%if 0%{?vty_group:1}
-%attr(750,%quagga_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample
-%endif
-%{_infodir}/quagga.info.gz
-%{_mandir}/man*/*
-%{_sbindir}/zebra
-%{_sbindir}/ospfd
-%{_sbindir}/ripd
-%{_sbindir}/bgpd
-%{_sbindir}/ssd
-%{_sbindir}/quagga
-%{_sbindir}/quagga-reload.py
-%{_sbindir}/quagga-reload.pyc
-%{_sbindir}/quagga-reload.pyo
-%if %{with_watchquagga}
- %{_sbindir}/watchquagga
-%endif
-%{_sbindir}/ripngd
-%{_sbindir}/ospf6d
-%{_sbindir}/pimd
-%{_sbindir}/isisd
-%if %{with_ldpd}
-%{_sbindir}/ldpd
-%endif
-%if %{with_shared}
-%attr(755,root,root) %{_libdir}/lib*.so
-%attr(755,root,root) %{_libdir}/lib*.so.*
-%endif
-%{_bindir}/*
-%config /etc/quagga/[!v]*
-%if "%{initsystem}" == "systemd"
- %config %{_unitdir}/quagga.service
-%else
- %config /etc/rc.d/init.d/zebra
- %if %{with_watchquagga}
- %config /etc/rc.d/init.d/watchquagga
- %endif
- %config /etc/rc.d/init.d/ripd
- %config /etc/rc.d/init.d/ospfd
- %config /etc/rc.d/init.d/bgpd
- %config /etc/rc.d/init.d/ripngd
- %config /etc/rc.d/init.d/ospf6d
- %config /etc/rc.d/init.d/isisd
- %config /etc/rc.d/init.d/pimd
- %if %{with_ldpd}
- %config /etc/rc.d/init.d/ldpd
- %endif
-%endif
-%config(noreplace) /etc/default/quagga
-%config(noreplace) /etc/pam.d/quagga
-%config(noreplace) %attr(640,root,root) /etc/logrotate.d/*
-
-%files contrib
-%defattr(-,root,root)
-%doc tools
-
-%files devel
-%defattr(-,root,root)
-%if %{with_ospfclient}
-%{_sbindir}/ospfclient
-%endif
-%{_libdir}/*.a
-%{_libdir}/*.la
-%dir %attr(755,root,root) %{_includedir}/%{name}
-%{_includedir}/%name/*.h
-%dir %attr(755,root,root) %{_includedir}/%{name}/ospfd
-%{_includedir}/%name/ospfd/*.h
-%if %{with_ospfapi}
-%dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi
-%{_includedir}/%name/ospfapi/*.h
-%endif
-
-%changelog
-* Thu Feb 11 2016 Paul Jakma <paul@jakma.org> - %{version}
-- remove with_ipv6 conditionals, always build v6
-- Fix UTF-8 char in spec changelog
-- remove quagga.pam.stack, long deprecated.
-
-* Thu Oct 22 2015 Martin Winter <mwinter@opensourcerouting.org>
-- Cleanup configure: remove --enable-ipv6 (default now), --enable-nssa,
- --enable-netlink
-- Remove support for old fedora 4/5
-- Fix for package nameing
-- Fix Weekdays of previous changelogs (bogus dates)
-- Add conditional logic to only build tex footnotes with supported texi2html
-- Added pimd to files section and fix double listing of /var/lib*/quagga
-- Numerous fixes to unify upstart/systemd startup into same spec file
-- Only allow use of watchquagga for non-systemd systems. no need with systemd
-
-* Fri Sep 4 2015 Paul Jakma <paul@jakma.org>
-- buildreq updates
-- add a default define for with_pimd
-
-* Mon Sep 12 2005 Paul Jakma <paul@dishone.st>
-- Steal some changes from Fedora spec file:
-- Add with_rtadv variable
-- Test for groups/users with getent before group/user adding
-- Readline need not be an explicit prerequisite
-- install-info delete should be postun, not preun
-
-* Wed Jan 12 2005 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
-- on package upgrade, implement careful, phased restart logic
-- use gcc -rdynamic flag when linking for better backtraces
-
-* Wed Dec 22 2004 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
-- daemonv6_list should contain only IPv6 daemons
-
-* Wed Dec 22 2004 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
-- watchquagga added
-- on upgrade, all daemons should be condrestart'ed
-- on removal, all daemons should be stopped
-
-* Mon Nov 08 2004 Paul Jakma <paul@dishone.st>
-- Use makeinfo --html to generate quagga.html
-
-* Sun Nov 07 2004 Paul Jakma <paul@dishone.st>
-- Fix with_ipv6 set to 0 build
-
-* Sat Oct 23 2004 Paul Jakma <paul@dishone.st>
-- Update to 0.97.2
-
-* Sat Oct 23 2004 Andrew J. Schorr <aschorr@telemetry-investments.com>
-- Make directories be owned by the packages concerned
-- Update logrotate scripts to use correct path to killall and use pid files
-
-* Fri Oct 08 2004 Paul Jakma <paul@dishone.st>
-- Update to 0.97.0
-
-* Wed Sep 15 2004 Paul Jakma <paul@dishone.st>
-- build snmp support by default
-- build irdp support
-- build with shared libs
-- devel subpackage for archives and headers
-
-* Thu Jan 08 2004 Paul Jakma <paul@dishone.st>
-- updated sysconfig files to specify local dir
-- added ospf_dump.c crash quick fix patch
-- added ospfd persistent interface configuration patch
-
-* Tue Dec 30 2003 Paul Jakma <paul@dishone.st>
-- sync to CVS
-- integrate RH sysconfig patch to specify daemon options (RH)
-- default to have vty listen only to 127.1 (RH)
-- add user with fixed UID/GID (RH)
-- create user with shell /sbin/nologin rather than /bin/false (RH)
-- stop daemons on uninstall (RH)
-- delete info file on preun, not postun to avoid deletion on upgrade. (RH)
-- isisd added
-- cleanup tasks carried out for every daemon
-
-* Sun Nov 2 2003 Paul Jakma <paul@dishone.st>
-- Fix -devel package to include all files
-- Sync to 0.96.4
-
-* Tue Aug 12 2003 Paul Jakma <paul@dishone.st>
-- Renamed to Quagga
-- Sync to Quagga release 0.96
-
-* Thu Mar 20 2003 Paul Jakma <paul@dishone.st>
-- zebra privileges support
-
-* Tue Mar 18 2003 Paul Jakma <paul@dishone.st>
-- Fix mem leak in 'show thread cpu'
-- Ralph Keller's OSPF-API
-- Amir: Fix configure.ac for net-snmp
-
-* Sat Mar 1 2003 Paul Jakma <paul@dishone.st>
-- ospfd IOS prefix to interface matching for 'network' statement
-- temporary fix for PtP and IPv6
-- sync to zebra.org CVS
-
-* Mon Jan 20 2003 Paul Jakma <paul@dishone.st>
-- update to latest cvs
-- Yon's "show thread cpu" patch - 17217
-- walk up tree - 17218
-- ospfd NSSA fixes - 16681
-- ospfd nsm fixes - 16824
-- ospfd OLSA fixes and new feature - 16823
-- KAME and ifindex fixes - 16525
-- spec file changes to allow redhat files to be in tree
-
-* Sat Dec 28 2002 Alexander Hoogerhuis <alexh@ihatent.com>
-- Added conditionals for building with(out) IPv6, vtysh, RIP, BGP
-- Fixed up some build requirements (patch)
-- Added conditional build requirements for vtysh / snmp
-- Added conditional to files for _bindir depending on vtysh
-
-* Mon Nov 11 2002 Paul Jakma <paulj@alphyra.ie>
-- update to latest CVS
-- add Greg Troxel's md5 buffer copy/dup fix
-- add RIPv1 fix
-- add Frank's multicast flag fix
-
-* Wed Oct 09 2002 Paul Jakma <paulj@alphyra.ie>
-- update to latest CVS
-- timestamped crypt_seqnum patch
-- oi->on_write_q fix
-
-* Mon Sep 30 2002 Paul Jakma <paulj@alphyra.ie>
-- update to latest CVS
-- add vtysh 'write-config (integrated|daemon)' patch
-- always 'make rebuild' in vtysh/ to catch new commands
-
-* Fri Sep 13 2002 Paul Jakma <paulj@alphyra.ie>
-- update to 0.93b
-
-* Wed Sep 11 2002 Paul Jakma <paulj@alphyra.ie>
-- update to latest CVS
-- add "/sbin/ip route flush proto zebra" to zebra RH init on startup
-
-* Sat Aug 24 2002 Paul Jakma <paulj@alphyra.ie>
-- update to current CVS
-- add OSPF point to multipoint patch
-- add OSPF bugfixes
-- add BGP hash optimisation patch
-
-* Fri Jun 14 2002 Paul Jakma <paulj@alphyra.ie>
-- update to 0.93-pre1 / CVS
-- add link state detection support
-- add generic PtP and RFC3021 support
-- various bug fixes
-
-* Thu Aug 09 2001 Elliot Lee <sopwith@redhat.com> 0.91a-6
-- Fix bug #51336
-
-* Wed Aug 1 2001 Trond Eivind Glomsrød <teg@redhat.com> 0.91a-5
-- Use generic initscript strings instead of initscript specific
- ( "Starting foo: " -> "Starting $prog:" )
-
-* Fri Jul 27 2001 Elliot Lee <sopwith@redhat.com> 0.91a-4
-- Bump the release when rebuilding into the dist.
-
-* Tue Feb 6 2001 Tim Powers <timp@redhat.com>
-- built for Powertools
-
-* Sun Feb 4 2001 Pekka Savola <pekkas@netcore.fi>
-- Hacked up from PLD Linux 0.90-1, Mandrake 0.90-1mdk and one from zebra.org.
-- Update to 0.91a
-- Very heavy modifications to init.d/*, .spec, pam, i18n, logrotate, etc.
-- Should be quite Red Hat'isque now.
+++ /dev/null
-#
-# Default: Bind all daemon vtys to the loopback(s) only
-#
-BGPD_OPTS="-A 127.0.0.1"
-ISISD_OPTS="-A ::1"
-OSPF6D_OPTS="-A ::1"
-OSPFD_OPTS="-A 127.0.0.1"
-RIPD_OPTS="-A 127.0.0.1"
-RIPNGD_OPTS="-A ::1"
-ZEBRA_OPTS="-A 127.0.0.1"
-PIMD_OPTS="-A 127.0.0.1"
-LDPD_OPTS="-A 127.0.0.1"
-
-# Watchquagga configuration for LSB initscripts
-#
-# (Not needed with systemd: the service files are configured to automatically
-# restart any daemon on failure. If zebra fails, all running daemons will be
-# stopped; zebra will be started again; and then the previously running daemons
-# will be started again.)
-#
-# Uncomment and edit this line to reflect the daemons you are actually using:
-#WATCH_DAEMONS="zebra bgpd ospfd ospf6d ripd ripngd"
-#
-# Timer values can be adjusting by editing this line:
-WATCH_OPTS="-Az -b_ -r/sbin/service_%s_restart -s/sbin/service_%s_start -k/sbin/service_%s_stop"
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/ripd.conf
+# config: /etc/frr/ripd.conf
### BEGIN INIT INFO
# Provides: ripd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="ripd"
cmd=ripd
LOCK_FILE=/var/lock/subsys/ripd
-CONF_FILE=/etc/quagga/ripd.conf
+CONF_FILE=/etc/frr/ripd.conf
case "$1" in
start)
#!/bin/bash
# chkconfig: - 16 84
-# config: /etc/quagga/ripngd.conf
+# config: /etc/frr/ripngd.conf
### BEGIN INIT INFO
# Provides: ripngd
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="ripngd"
cmd=ripngd
LOCK_FILE=/var/lock/subsys/ripngd
-CONF_FILE=/etc/quagga/ripngd.conf
+CONF_FILE=/etc/frr/ripngd.conf
case "$1" in
start)
--- /dev/null
+#!/bin/bash
+# chkconfig: 2345 17 83
+
+### BEGIN INIT INFO
+# Provides: watchfrr
+# Short-Description: Frr watchdog
+# Description: Frr watchdog for use with Zebra
+### END INIT INFO
+
+# source function library
+. /etc/rc.d/init.d/functions
+
+# Get network config
+. /etc/sysconfig/network
+
+# frr command line options
+. /etc/sysconfig/frr
+
+RETVAL=0
+PROG="watchfrr"
+cmd=watchfrr
+LOCK_FILE=/var/lock/subsys/watchfrr
+
+case "$1" in
+ start)
+ # Check that networking is up.
+ [ "${NETWORKING}" = "no" ] && exit 1
+
+ # Check that there are daemons to be monitored.
+ [ -z "$WATCH_DAEMONS" ] && exit 1
+
+ echo -n $"Starting $PROG: "
+ daemon $cmd -d $WATCH_OPTS $WATCH_DAEMONS
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] && touch $LOCK_FILE
+ echo
+ ;;
+ stop)
+ echo -n $"Shutting down $PROG: "
+ killproc $cmd
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] && rm -f $LOCK_FILE
+ echo
+ ;;
+ restart|reload|force-reload)
+ $0 stop
+ $0 start
+ RETVAL=$?
+ ;;
+ condrestart|try-restart)
+ if [ -f $LOCK_FILE ]; then
+ $0 stop
+ $0 start
+ fi
+ RETVAL=$?
+ ;;
+ status)
+ status $cmd
+ RETVAL=$?
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
+ exit 2
+esac
+
+exit $RETVAL
+++ /dev/null
-#!/bin/bash
-# chkconfig: 2345 17 83
-
-### BEGIN INIT INFO
-# Provides: watchquagga
-# Short-Description: Quagga watchdog
-# Description: Quagga watchdog for use with Zebra
-### END INIT INFO
-
-# source function library
-. /etc/rc.d/init.d/functions
-
-# Get network config
-. /etc/sysconfig/network
-
-# quagga command line options
-. /etc/sysconfig/quagga
-
-RETVAL=0
-PROG="watchquagga"
-cmd=watchquagga
-LOCK_FILE=/var/lock/subsys/watchquagga
-
-case "$1" in
- start)
- # Check that networking is up.
- [ "${NETWORKING}" = "no" ] && exit 1
-
- # Check that there are daemons to be monitored.
- [ -z "$WATCH_DAEMONS" ] && exit 1
-
- echo -n $"Starting $PROG: "
- daemon $cmd -d $WATCH_OPTS $WATCH_DAEMONS
- RETVAL=$?
- [ $RETVAL -eq 0 ] && touch $LOCK_FILE
- echo
- ;;
- stop)
- echo -n $"Shutting down $PROG: "
- killproc $cmd
- RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f $LOCK_FILE
- echo
- ;;
- restart|reload|force-reload)
- $0 stop
- $0 start
- RETVAL=$?
- ;;
- condrestart|try-restart)
- if [ -f $LOCK_FILE ]; then
- $0 stop
- $0 start
- fi
- RETVAL=$?
- ;;
- status)
- status $cmd
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
- exit 2
-esac
-
-exit $RETVAL
#!/bin/bash
# chkconfig: - 15 85
-# config: /etc/quagga/zebra.conf
+# config: /etc/frr/zebra.conf
### BEGIN INIT INFO
# Provides: zebra
# Get network config
. /etc/sysconfig/network
-# quagga command line options
-. /etc/sysconfig/quagga
+# frr command line options
+. /etc/sysconfig/frr
RETVAL=0
PROG="zebra"
cmd=zebra
LOCK_FILE=/var/lock/subsys/zebra
-CONF_FILE=/etc/quagga/zebra.conf
+CONF_FILE=/etc/frr/zebra.conf
case "$1" in
start)
struct zebra_privs_t ripd_privs =
{
-#if defined(QUAGGA_USER)
- .user = QUAGGA_USER,
+#if defined(FRR_USER)
+ .user = FRR_USER,
#endif
-#if defined QUAGGA_GROUP
- .group = QUAGGA_GROUP,
+#if defined FRR_GROUP
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
vty_serv_sock (vty_addr, vty_port, RIP_VTYSH_PATH);
/* Print banner. */
- zlog_notice ("RIPd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ zlog_notice ("RIPd %s starting: vty@%d", FRR_VERSION, vty_port);
/* Execute each thread. */
while (thread_fetch (master, &thread))
rip_redistribute_type_cmd,
"redistribute <kernel|connected|static|ospf|isis|bgp|pim|table>",
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD)
+ FRR_REDIST_HELP_STR_RIPD)
{
int i;
"no redistribute <kernel|connected|static|ospf|isis|bgp|pim|table>",
NO_STR
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD)
+ FRR_REDIST_HELP_STR_RIPD)
{
int i;
rip_redistribute_type_routemap_cmd,
"redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> route-map WORD",
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Route map reference\n"
"Pointer to route-map entries\n")
{
"no redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> route-map WORD",
NO_STR
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Route map reference\n"
"Pointer to route-map entries\n")
{
rip_redistribute_type_metric_cmd,
"redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> metric (0-16)",
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Metric\n"
"Metric value\n")
{
"no redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> metric (0-16)",
NO_STR
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Metric\n"
"Metric value\n")
{
rip_redistribute_type_metric_routemap_cmd,
"redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> metric (0-16) route-map WORD",
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Metric\n"
"Metric value\n"
"Route map reference\n"
"no redistribute <kernel|connected|static|ospf|isis|bgp|pim|table> metric (0-16) route-map WORD",
NO_STR
REDIST_STR
- QUAGGA_REDIST_HELP_STR_RIPD
+ FRR_REDIST_HELP_STR_RIPD
"Metric\n"
"Metric value\n"
"Route map reference\n"
struct zebra_privs_t ripngd_privs =
{
-#if defined(QUAGGA_USER)
- .user = QUAGGA_USER,
+#if defined(FRR_USER)
+ .user = FRR_USER,
#endif
-#if defined QUAGGA_GROUP
- .group = QUAGGA_GROUP,
+#if defined FRR_GROUP
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
}
pid_output (pid_file);
/* Print banner. */
- zlog_notice ("RIPNGd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ zlog_notice ("RIPNGd %s starting: vty@%d", FRR_VERSION, vty_port);
/* Fetch next active thread. */
while (thread_fetch (master, &thread))
ripng_redistribute_type_cmd,
"redistribute <kernel|connected|static|ospf6|isis|bgp|table>",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_RIPNGD)
+ FRR_REDIST_HELP_STR_RIPNGD)
{
int type;
"no redistribute <kernel|connected|static|ospf6|isis|bgp|table> [metric (0-16)] [route-map WORD]",
NO_STR
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_RIPNGD
+ FRR_REDIST_HELP_STR_RIPNGD
"Metric\n"
"Metric value\n"
"Route map reference\n"
ripng_redistribute_type_metric_cmd,
"redistribute <kernel|connected|static|ospf6|isis|bgp|table> metric (0-16)",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_RIPNGD
+ FRR_REDIST_HELP_STR_RIPNGD
"Metric\n"
"Metric value\n")
{
return CMD_SUCCESS;
}
-
DEFUN (ripng_redistribute_type_routemap,
ripng_redistribute_type_routemap_cmd,
"redistribute <kernel|connected|static|ospf6|isis|bgp|table> route-map WORD",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_RIPNGD
+ FRR_REDIST_HELP_STR_RIPNGD
"Route map reference\n"
"Pointer to route-map entries\n")
{
return CMD_SUCCESS;
}
-
DEFUN (ripng_redistribute_type_metric_routemap,
ripng_redistribute_type_metric_routemap_cmd,
"redistribute <kernel|connected|static|ospf6|isis|bgp|table> metric (0-16) route-map WORD",
"Redistribute\n"
- QUAGGA_REDIST_HELP_STR_RIPNGD
+ FRR_REDIST_HELP_STR_RIPNGD
"Metric\n"
"Metric value\n"
"Route map reference\n"
return CMD_SUCCESS;
}
-
void
ripng_redistribute_write (struct vty *vty, int config_mode)
{
f none @sbindir@/ripngd=$DESTDIR/@sbindir@/ripngd 0755 root bin
f none @sbindir@/ospfd=$DESTDIR/@sbindir@/ospfd 0755 root bin
f none @sbindir@/ospf6d=$DESTDIR/@sbindir@/ospf6d 0755 root bin
-f none @sbindir@/watchquagga=$DESTDIR/@sbindir@/watchquagga 0755 root bin
+f none @sbindir@/watchfrr=$DESTDIR/@sbindir@/watchfrr 0755 root bin
d none @sysconfdir@=$DESTDIR/@sysconfdir@ 0711 @enable_user@ @enable_group@
f none @sysconfdir@/zebra.conf.sample=$DESTDIR/@sysconfdir@/zebra.conf.sample 0644 root bin
f none @sysconfdir@/bgpd.conf.sample=$DESTDIR/@sysconfdir@/bgpd.conf.sample 0644 root bin
-/* $QuaggaId: Format:%an, %ai, %h$ $
- *
+/*
* BGP Multipath Unit Test
* Copyright (C) 2010 Google Inc.
*
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
}
-/* $QuaggaId: Format:%an, %ai, %h$ $
- *
+/*
* Routing table test
* Copyright (C) 2012 OSR.
*
struct zebra_privs_t test_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
-g, --group Group to run as\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
}
permutations_SOURCES = permutations.c
permutations_LDADD = ../lib/libzebra.la
-sbin_SCRIPTS = quagga-reload.py quagga
+sbin_SCRIPTS = frr-reload.py frr
-EXTRA_DIST = quagga.service quagga-reload.py quagga
+EXTRA_DIST = frr.service frr-reload.py frr
--- /dev/null
+#!/bin/bash
+#
+### BEGIN INIT INFO
+# Provides: frr
+# Required-Start: $local_fs $network $remote_fs $syslog
+# Required-Stop: $local_fs $network $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: start and stop the Frr routing suite
+# Description: Frr is a routing suite for IP routing protocols like
+# BGP, OSPF, RIP and others. This script contols the main
+# daemon "frr" as well as the individual protocol daemons.
+### END INIT INFO
+#
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+D_PATH=/usr/lib/frr
+C_PATH=/etc/frr
+V_PATH=/var/run/frr
+
+# Local Daemon selection may be done by using /etc/frr/daemons.
+# See /usr/share/doc/frr/README.Debian.gz for further information.
+# Keep zebra first and do not list watchfrr!
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd"
+MAX_INSTANCES=5
+RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
+
+. /lib/lsb/init-functions
+
+if [ -f /usr/lib/frr/ssd ]; then
+ SSD=/usr/lib/frr/ssd
+else
+ SSD=`which start-stop-daemon`
+fi
+
+# Print the name of the pidfile.
+pidfile()
+{
+ echo "$V_PATH/$1.pid"
+}
+
+# Print the name of the vtysh.
+vtyfile()
+{
+ echo "$V_PATH/$1.vty"
+}
+
+# Check if daemon is started by using the pidfile.
+started()
+{
+ [ ! -e `pidfile $1` ] && return 3
+ if [ -n "$2" ] && [ "$2" == "log" ]; then
+ status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $?
+ else
+ kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
+ return 0
+ fi
+}
+
+# Loads the config via vtysh -b if configured to do so.
+vtysh_b ()
+{
+ # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
+ if [ "$vtysh_enable" = 2 -a -f $C_PATH/Frr.conf ]; then
+ /usr/bin/vtysh -b -n
+ fi
+}
+
+# Check if the daemon is activated and if its executable and config files
+# are in place.
+# params: daemon name
+# returns: 0=ok, 1=error
+check_daemon()
+{
+ # If the integrated config file is used the others are not checked.
+ if [ -r "$C_PATH/Frr.conf" ]; then
+ return 0
+ fi
+
+ # vtysh_enable has no config file nor binary so skip check.
+ # (Not sure why vtysh_enable is in this list but does not hurt)
+ if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
+ # check for daemon binary
+ if [ ! -x "$D_PATH/$1" ]; then return 1; fi
+
+ # check for config file
+ if [ -n "$2" ]; then
+ if [ ! -r "$C_PATH/$1-$2.conf" ]; then
+ touch "$C_PATH/$1-$2.conf"
+ chown frr:frr "$C_PATH/$1-$2.conf"
+ fi
+ elif [ ! -r "$C_PATH/$1.conf" ]; then
+ touch "$C_PATH/$1.conf"
+ chown frr:frr "$C_PATH/$1.conf"
+ fi
+ fi
+ return 0
+}
+
+# Starts the server if it's not alrady running according to the pid file.
+# The Frr daemons creates the pidfile when starting.
+start()
+{
+ ulimit -n $MAX_FDS
+ if [ "$1" = "watchfrr" ]; then
+
+ # We may need to restart watchfrr if new daemons are added and/or
+ # removed
+ if started "$1" ; then
+ stop watchfrr
+ else
+ # Echo only once. watchfrr is printed in the stop above
+ echo -n " $1"
+ fi
+
+ if [ -e /var/run/frr/watchfrr.started ] ; then
+ rm /var/run/frr/watchfrr.started
+ fi
+ ${SSD} \
+ --start \
+ --pidfile=`pidfile $1` \
+ --exec "$D_PATH/$1" \
+ -- \
+ "${watchfrr_options[@]}"
+ for i in `seq 1 10`;
+ do
+ if [ -e /var/run/frr/watchfrr.started ] ; then
+ break
+ else
+ sleep 1
+ fi
+ done
+ elif [ -n "$2" ]; then
+ echo -n " $1-$2"
+ if ! check_daemon $1 $2 ; then
+ echo -n " (binary does not exist)"
+ return;
+ fi
+
+ ${SSD} \
+ --start \
+ --pidfile=`pidfile $1-$2` \
+ --exec "$D_PATH/$1" \
+ -- \
+ `eval echo "$""$1""_options"` -n "$2"
+ else
+ echo -n " $1"
+ if ! check_daemon $1; then
+ echo -n " (binary does not exist)"
+ return;
+ fi
+
+ ${SSD} \
+ --start \
+ --pidfile=`pidfile $1` \
+ --exec "$D_PATH/$1" \
+ -- \
+ `eval echo "$""$1""_options"`
+ fi
+}
+
+# Stop the daemon given in the parameter, printing its name to the terminal.
+stop()
+{
+ local inst
+
+ if [ -n "$2" ]; then
+ inst="$1-$2"
+ else
+ inst="$1"
+ fi
+
+ if ! started "$inst" ; then
+ echo -n " ($inst)"
+ return 0
+ else
+ PIDFILE=`pidfile $inst`
+ PID=`cat $PIDFILE 2>/dev/null`
+ ${SSD} --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
+ #
+ # Now we have to wait until $DAEMON has _really_ stopped.
+ #
+ if test -n "$PID" && kill -0 $PID 2>/dev/null; then
+ echo -n " (waiting) ."
+ cnt=0
+ while kill -0 $PID 2>/dev/null; do
+ cnt=`expr $cnt + 1`
+ if [ $cnt -gt 60 ]; then
+ # Waited 120 secs now, fail.
+ echo -n "Failed.. "
+ break
+ fi
+ sleep 2
+ echo -n "."
+ done
+ fi
+ echo -n " $inst"
+ rm -f `pidfile $inst`
+ rm -f `vtyfile $inst`
+ fi
+}
+
+# Converts values from /etc/frr/daemons to all-numeric values.
+convert_daemon_prios()
+{
+ for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
+ # First, assign the value set by the user to $value
+ eval value=\${${name}:0:3}
+
+ # Daemon not activated or entry missing?
+ if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
+
+ # These strings parsed for backwards compatibility.
+ if [ "$value" = "yes" -o "$value" = "true" ]; then
+ value=1;
+ fi
+
+ # Zebra is threatened special. It must be between 0=off and the first
+ # user assigned value "1" so we increase all other enabled daemons' values.
+ if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
+
+ # If e.g. name is zebra then we set "zebra=yes".
+ eval $name=$value
+ done
+}
+
+# Starts watchfrr for all wanted daemons.
+start_watchfrr()
+{
+ local daemon_name
+ local daemon_prio
+ local found_one
+ local daemon_inst
+
+ # Start the monitor daemon only if desired.
+ if [ 0 -eq "$watchfrr_enable" ]; then
+ return
+ fi
+
+ # Check variable type
+ if ! declare -p watchfrr_options | grep -q '^declare \-a'; then
+ echo
+ echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
+ echo "ERROR: Please convert config file and restart!"
+ exit 1
+ fi
+
+ # Which daemons have been started?
+ found_one=0
+ for daemon_name in $DAEMONS; do
+ eval daemon_prio=\$$daemon_name
+ if [ "$daemon_prio" -gt 0 ]; then
+ eval "daemon_inst=\${${daemon_name}_instances//,/ }"
+ if [ -n "$daemon_inst" ]; then
+ for inst in ${daemon_inst}; do
+ eval "inst_disable=\${${daemon_name}_${inst}}"
+ if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
+ if check_daemon $daemon_name $inst; then
+ watchfrr_options+=("${daemon_name}-${inst}")
+ fi
+ fi
+ done
+ else
+ if check_daemon $daemon_name; then
+ watchfrr_options+=($daemon_name)
+ fi
+ fi
+ found_one=1
+ fi
+ done
+
+ # Start if at least one daemon is activated.
+ if [ $found_one -eq 1 ]; then
+ echo -n "Starting Frr monitor daemon:"
+ start watchfrr
+ echo "."
+ fi
+}
+
+# Stopps watchfrr.
+stop_watchfrr()
+{
+ echo -n "Stopping Frr monitor daemon:"
+ stop watchfrr
+ echo "."
+}
+
+# Stops all daemons that have a lower level of priority than the given.
+# (technically if daemon_prio >= wanted_prio)
+stop_prio()
+{
+ local wanted_prio
+ local daemon_prio
+ local daemon_list
+ local daemon_inst
+ local inst
+
+ if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
+ daemon=${BASH_REMATCH[1]}
+ inst=${BASH_REMATCH[2]}
+ else
+ daemon="$2"
+ fi
+
+ wanted_prio=$1
+ daemon_list=${daemon:-$DAEMONS}
+
+ echo -n "Stopping Frr daemons (prio:$wanted_prio):"
+
+ for prio_i in `seq 10 -1 $wanted_prio`; do
+ for daemon_name in $daemon_list; do
+ eval daemon_prio=\${${daemon_name}:0:3}
+ daemon_inst=""
+ if [ $daemon_prio -eq $prio_i ]; then
+ eval "daemon_inst=\${${daemon_name}_instances//,/ }"
+ if [ -n "$daemon_inst" ]; then
+ for i in ${daemon_inst}; do
+ if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
+ stop "$daemon_name" "$inst"
+ elif [ x"$inst" == x ]; then
+ stop "$daemon_name" "$i"
+ fi
+ done
+ else
+ stop "$daemon_name"
+ fi
+ fi
+ done
+ done
+
+ echo "."
+ if [ -z "$inst" ]; then
+ # Now stop other daemons that're prowling, coz the daemons file changed
+ echo -n "Stopping other frr daemons"
+ if [ -n "$daemon" ]; then
+ eval "file_list_suffix="$V_PATH"/"$daemon*""
+ else
+ eval "file_list_suffix="$V_PATH/*""
+ fi
+ for pidfile in $file_list_suffix.pid; do
+ PID=`cat $pidfile 2>/dev/null`
+ ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
+ echo -n "."
+ rm -rf "$pidfile"
+ done
+ echo "."
+
+ echo -n "Removing remaining .vty files"
+ for vtyfile in $file_list_suffix.vty; do
+ rm -rf "$vtyfile"
+ done
+ echo "."
+ fi
+}
+
+# Starts all daemons that have a higher level of priority than the given.
+# (technically if daemon_prio <= wanted_prio)
+start_prio()
+{
+ local wanted_prio
+ local daemon_prio
+ local daemon_list
+ local daemon_name
+ local daemon_inst
+ local inst
+
+ if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
+ daemon=${BASH_REMATCH[1]}
+ inst=${BASH_REMATCH[2]}
+ else
+ daemon="$2"
+ fi
+
+ wanted_prio=$1
+ daemon_list=${daemon:-$DAEMONS}
+
+ echo -n "Starting Frr daemons (prio:$wanted_prio):"
+
+ for prio_i in `seq 1 $wanted_prio`; do
+ for daemon_name in $daemon_list; do
+ eval daemon_prio=\$${daemon_name}
+ daemon_inst=""
+ if [ $daemon_prio -eq $prio_i ]; then
+ eval "daemon_inst=\${${daemon_name}_instances//,/ }"
+ if [ -n "$daemon_inst" ]; then
+ if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
+ echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
+ exit 1
+ fi
+ # Check if we're starting again by switching from single instance
+ # to MI version
+ if started "$daemon_name"; then
+ PIDFILE=`pidfile $daemon_name`
+ ${SSD} \
+ --stop --quiet --oknodo \
+ --pidfile "$PIDFILE" \
+ --exec "$D_PATH/$daemon_name"
+
+ rm -f `pidfile $1`
+ rm -f `vtyfile $1`
+ fi
+
+ for i in ${daemon_inst}; do
+ if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
+ start "$daemon_name" "$inst"
+ elif [ x"$inst" == x ]; then
+ start "$daemon_name" "$i"
+ fi
+ done
+ else
+ # Check if we're starting again by switching from
+ # single instance to MI version
+ eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
+ for pidfile in $file_list_suffix.pid; do
+ ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
+ echo -n "."
+ rm -rf "$pidfile"
+ done
+ for vtyfile in $file_list_suffix.vty; do
+ rm -rf "$vtyfile"
+ done
+
+ start "$daemon_name"
+ fi
+ fi
+ done
+ done
+ echo "."
+}
+
+check_status()
+{
+ local daemon_name
+ local daemon_prio
+ local daemon_inst
+ local failed_status=0
+
+ if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
+ daemon=${BASH_REMATCH[1]}
+ inst=${BASH_REMATCH[2]}
+ else
+ daemon="$1"
+ fi
+
+ daemon_list=${daemon:-$DAEMONS}
+
+ # Which daemons have been started?
+ for daemon_name in $daemon_list; do
+ eval daemon_prio=\$$daemon_name
+ if [ "$daemon_prio" -gt 0 ]; then
+ eval "daemon_inst=\${${daemon_name}_instances//,/ }"
+ if [ -n "$daemon_inst" ]; then
+ for i in ${daemon_inst}; do
+ if [ -n "$inst" -a "$inst" = "$i" ]; then
+ started "$1" "log" || failed_status=$?
+ elif [ -z "$inst" ]; then
+ started "$daemon_name-$i" "log" || failed_status=$?
+ fi
+ done
+ else
+ started "$daemon_name" "log" || failed_status=$?
+ fi
+ fi
+ done
+
+ # All daemons that need to have been started are up and running
+ return $failed_status
+}
+
+#########################################################
+# Main program #
+#########################################################
+
+# Config broken but script must exit silently.
+[ ! -r "$C_PATH/daemons" ] && exit 0
+
+# Load configuration
+. "$C_PATH/daemons"
+. "$C_PATH/debian.conf"
+
+# Read configuration variable file if it is present
+[ -r /etc/default/frr ] && . /etc/default/frr
+
+MAX_INSTANCES=${MAX_INSTANCES:=5}
+
+# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
+convert_daemon_prios
+
+if [ ! -d $V_PATH ]; then
+ echo "Creating $V_PATH"
+ mkdir -p $V_PATH
+ chown frr:frr $V_PATH
+ chmod 755 /$V_PATH
+fi
+
+if [ -n "$3" ] && [ "$3" != "all" ]; then
+ dmn="$2"-"$3"
+elif [ -n "$2" ] && [ "$2" != "all" ]; then
+ dmn="$2"
+fi
+
+case "$1" in
+ start)
+ # Try to load this necessary (at least for 2.6) module.
+ if [ -d /lib/modules/`uname -r` ] ; then
+ echo "Loading capability module if not yet done."
+ set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e
+ fi
+
+ # Start all daemons
+ cd $C_PATH/
+ if [ "$2" != "watchfrr" ]; then
+ start_prio 10 $dmn
+ fi
+ start_watchfrr
+ vtysh_b
+ ;;
+
+ 1|2|3|4|5|6|7|8|9|10)
+ # Stop/start daemons for the appropriate priority level
+ stop_prio $1
+ start_prio $1
+ vtysh_b
+ ;;
+
+ stop|0)
+ # Stop all daemons at level '0' or 'stop'
+ stop_watchfrr
+ if [ "$dmn" != "watchfrr" ]; then
+ [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
+ stop_prio 0 $dmn
+ fi
+
+ if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
+ echo "Removing all routes made by zebra."
+ ip route flush proto zebra
+ else
+ [ -n "$dmn" ] && eval "${dmn/-/_}=0"
+ start_watchfrr
+ fi
+ ;;
+
+ reload)
+ # Just apply the commands that have changed, no restart necessary
+ [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
+ NEW_CONFIG_FILE="${2:-$C_PATH/Frr.conf}"
+ [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
+ echo "Applying only incremental changes to running configuration from Frr.conf"
+ "$RELOAD_SCRIPT" --reload /etc/frr/Frr.conf
+ exit $?
+ ;;
+
+ status)
+ check_status $dmn
+ exit $?
+ ;;
+
+ restart|force-reload)
+ $0 stop $dmn
+ sleep 1
+ $0 start $dmn
+ ;;
+
+ *)
+ echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
+ echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
+ echo " reload applies only modifications from the running config to all daemons."
+ echo " reload neither restarts starts any daemon nor starts any new ones."
+ echo " Read /usr/share/doc/frr/README.Debian for details."
+ exit 1
+ ;;
+esac
+
+echo "Exiting from the script"
+exit 0
--- /dev/null
+#!/usr/bin/python
+# Frr Reloader
+# Copyright (C) 2014 Cumulus Networks, Inc.
+#
+# This file is part of Frr.
+#
+# Frr is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+#
+# Frr is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Frr; see the file COPYING. If not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+"""
+This program
+- reads a frr configuration text file
+- reads frr's current running configuration via "vtysh -c 'show running'"
+- compares the two configs and determines what commands to execute to
+ synchronize frr's running configuration with the configuation in the
+ text file
+"""
+
+import argparse
+import copy
+import logging
+import os
+import random
+import re
+import string
+import subprocess
+import sys
+from collections import OrderedDict
+from ipaddr import IPv6Address
+from pprint import pformat
+
+
+log = logging.getLogger(__name__)
+
+
+class VtyshMarkException(Exception):
+ pass
+
+
+class Context(object):
+
+ """
+ A Context object represents a section of frr configuration such as:
+!
+interface swp3
+ description swp3 -> r8's swp1
+ ipv6 nd suppress-ra
+ link-detect
+!
+
+or a single line context object such as this:
+
+ip forwarding
+
+ """
+
+ def __init__(self, keys, lines):
+ self.keys = keys
+ self.lines = lines
+
+ # Keep a dictionary of the lines, this is to make it easy to tell if a
+ # line exists in this Context
+ self.dlines = OrderedDict()
+
+ for ligne in lines:
+ self.dlines[ligne] = True
+
+ def add_lines(self, lines):
+ """
+ Add lines to specified context
+ """
+
+ self.lines.extend(lines)
+
+ for ligne in lines:
+ self.dlines[ligne] = True
+
+
+class Config(object):
+
+ """
+ A frr configuration is stored in a Config object. A Config object
+ contains a dictionary of Context objects where the Context keys
+ ('router ospf' for example) are our dictionary key.
+ """
+
+ def __init__(self):
+ self.lines = []
+ self.contexts = OrderedDict()
+
+ def load_from_file(self, filename):
+ """
+ Read configuration from specified file and slurp it into internal memory
+ The internal representation has been marked appropriately by passing it
+ through vtysh with the -m parameter
+ """
+ log.info('Loading Config object from file %s', filename)
+
+ try:
+ file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename])
+ except subprocess.CalledProcessError as e:
+ raise VtyshMarkException(str(e))
+
+ for line in file_output.split('\n'):
+ line = line.strip()
+ if ":" in line:
+ qv6_line = get_normalized_ipv6_line(line)
+ self.lines.append(qv6_line)
+ else:
+ self.lines.append(line)
+
+ self.load_contexts()
+
+ def load_from_show_running(self):
+ """
+ Read running configuration and slurp it into internal memory
+ The internal representation has been marked appropriately by passing it
+ through vtysh with the -m parameter
+ """
+ log.info('Loading Config object from vtysh show running')
+
+ try:
+ config_text = subprocess.check_output(
+ "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -",
+ shell=True)
+ except subprocess.CalledProcessError as e:
+ raise VtyshMarkException(str(e))
+
+ for line in config_text.split('\n'):
+ line = line.strip()
+
+ if (line == 'Building configuration...' or
+ line == 'Current configuration:' or
+ not line):
+ continue
+
+ self.lines.append(line)
+
+ self.load_contexts()
+
+ def get_lines(self):
+ """
+ Return the lines read in from the configuration
+ """
+
+ return '\n'.join(self.lines)
+
+ def get_contexts(self):
+ """
+ Return the parsed context as strings for display, log etc.
+ """
+
+ for (_, ctx) in sorted(self.contexts.iteritems()):
+ print str(ctx) + '\n'
+
+ def save_contexts(self, key, lines):
+ """
+ Save the provided key and lines as a context
+ """
+
+ if not key:
+ return
+
+ if lines:
+ if tuple(key) not in self.contexts:
+ ctx = Context(tuple(key), lines)
+ self.contexts[tuple(key)] = ctx
+ else:
+ ctx = self.contexts[tuple(key)]
+ ctx.add_lines(lines)
+
+ else:
+ if tuple(key) not in self.contexts:
+ ctx = Context(tuple(key), [])
+ self.contexts[tuple(key)] = ctx
+
+ def load_contexts(self):
+ """
+ Parse the configuration and create contexts for each appropriate block
+ """
+
+ current_context_lines = []
+ ctx_keys = []
+
+ '''
+ The end of a context is flagged via the 'end' keyword:
+
+!
+interface swp52
+ ipv6 nd suppress-ra
+ link-detect
+!
+end
+router bgp 10
+ bgp router-id 10.0.0.1
+ bgp log-neighbor-changes
+ no bgp default ipv4-unicast
+ neighbor EBGP peer-group
+ neighbor EBGP advertisement-interval 1
+ neighbor EBGP timers connect 10
+ neighbor 2001:40:1:4::6 remote-as 40
+ neighbor 2001:40:1:8::a remote-as 40
+!
+end
+ address-family ipv6
+ neighbor IBGPv6 activate
+ neighbor 2001:10::2 peer-group IBGPv6
+ neighbor 2001:10::3 peer-group IBGPv6
+ exit-address-family
+!
+end
+router ospf
+ ospf router-id 10.0.0.1
+ log-adjacency-changes detail
+ timers throttle spf 0 50 5000
+!
+end
+ '''
+
+ # The code assumes that its working on the output from the "vtysh -m"
+ # command. That provides the appropriate markers to signify end of
+ # a context. This routine uses that to build the contexts for the
+ # config.
+ #
+ # There are single line contexts such as "log file /media/node/zebra.log"
+ # and multi-line contexts such as "router ospf" and subcontexts
+ # within a context such as "address-family" within "router bgp"
+ # In each of these cases, the first line of the context becomes the
+ # key of the context. So "router bgp 10" is the key for the non-address
+ # family part of bgp, "router bgp 10, address-family ipv6 unicast" is
+ # the key for the subcontext and so on.
+ ctx_keys = []
+ main_ctx_key = []
+ new_ctx = True
+
+ # the keywords that we know are single line contexts. bgp in this case
+ # is not the main router bgp block, but enabling multi-instance
+ oneline_ctx_keywords = ("access-list ",
+ "bgp ",
+ "debug ",
+ "dump ",
+ "enable ",
+ "hostname ",
+ "ip ",
+ "ipv6 ",
+ "log ",
+ "password ",
+ "ptm-enable",
+ "router-id ",
+ "service ",
+ "table ",
+ "username ",
+ "zebra ")
+
+ for line in self.lines:
+
+ if not line:
+ continue
+
+ if line.startswith('!') or line.startswith('#'):
+ continue
+
+ # one line contexts
+ if new_ctx is True and any(line.startswith(keyword) for keyword in oneline_ctx_keywords):
+ self.save_contexts(ctx_keys, current_context_lines)
+
+ # Start a new context
+ main_ctx_key = []
+ ctx_keys = [line, ]
+ current_context_lines = []
+
+ log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
+ self.save_contexts(ctx_keys, current_context_lines)
+ new_ctx = True
+
+ elif line == "end":
+ self.save_contexts(ctx_keys, current_context_lines)
+ log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
+
+ # Start a new context
+ new_ctx = True
+ main_ctx_key = []
+ ctx_keys = []
+ current_context_lines = []
+
+ elif line == "exit-address-family" or line == "exit":
+ # if this exit is for address-family ipv4 unicast, ignore the pop
+ if main_ctx_key:
+ self.save_contexts(ctx_keys, current_context_lines)
+
+ # Start a new context
+ ctx_keys = copy.deepcopy(main_ctx_key)
+ current_context_lines = []
+ log.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys)
+
+ elif new_ctx is True:
+ if not main_ctx_key:
+ ctx_keys = [line, ]
+ else:
+ ctx_keys = copy.deepcopy(main_ctx_key)
+ main_ctx_key = []
+
+ current_context_lines = []
+ new_ctx = False
+ log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
+
+ elif "address-family " in line:
+ main_ctx_key = []
+
+ # Save old context first
+ self.save_contexts(ctx_keys, current_context_lines)
+ current_context_lines = []
+ main_ctx_key = copy.deepcopy(ctx_keys)
+ log.debug('LINE %-50s: entering sub-context, append to ctx_keys', line)
+
+ if line == "address-family ipv6":
+ ctx_keys.append("address-family ipv6 unicast")
+ elif line == "address-family ipv4":
+ ctx_keys.append("address-family ipv4 unicast")
+ else:
+ ctx_keys.append(line)
+
+ else:
+ # Continuing in an existing context, add non-commented lines to it
+ current_context_lines.append(line)
+ log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys)
+
+ # Save the context of the last one
+ self.save_contexts(ctx_keys, current_context_lines)
+
+
+def line_to_vtysh_conft(ctx_keys, line, delete):
+ """
+ Return the vtysh command for the specified context line
+ """
+
+ cmd = []
+ cmd.append('vtysh')
+ cmd.append('-c')
+ cmd.append('conf t')
+
+ if line:
+ for ctx_key in ctx_keys:
+ cmd.append('-c')
+ cmd.append(ctx_key)
+
+ line = line.lstrip()
+
+ if delete:
+ cmd.append('-c')
+
+ if line.startswith('no '):
+ cmd.append('%s' % line[3:])
+ else:
+ cmd.append('no %s' % line)
+
+ else:
+ cmd.append('-c')
+ cmd.append(line)
+
+ # If line is None then we are typically deleting an entire
+ # context ('no router ospf' for example)
+ else:
+
+ if delete:
+
+ # Only put the 'no' on the last sub-context
+ for ctx_key in ctx_keys:
+ cmd.append('-c')
+
+ if ctx_key == ctx_keys[-1]:
+ cmd.append('no %s' % ctx_key)
+ else:
+ cmd.append('%s' % ctx_key)
+ else:
+ for ctx_key in ctx_keys:
+ cmd.append('-c')
+ cmd.append(ctx_key)
+
+ return cmd
+
+
+def line_for_vtysh_file(ctx_keys, line, delete):
+ """
+ Return the command as it would appear in Frr.conf
+ """
+ cmd = []
+
+ if line:
+ for (i, ctx_key) in enumerate(ctx_keys):
+ cmd.append(' ' * i + ctx_key)
+
+ line = line.lstrip()
+ indent = len(ctx_keys) * ' '
+
+ if delete:
+ if line.startswith('no '):
+ cmd.append('%s%s' % (indent, line[3:]))
+ else:
+ cmd.append('%sno %s' % (indent, line))
+
+ else:
+ cmd.append(indent + line)
+
+ # If line is None then we are typically deleting an entire
+ # context ('no router ospf' for example)
+ else:
+ if delete:
+
+ # Only put the 'no' on the last sub-context
+ for ctx_key in ctx_keys:
+
+ if ctx_key == ctx_keys[-1]:
+ cmd.append('no %s' % ctx_key)
+ else:
+ cmd.append('%s' % ctx_key)
+ else:
+ for ctx_key in ctx_keys:
+ cmd.append(ctx_key)
+
+ return '\n' + '\n'.join(cmd)
+
+
+def get_normalized_ipv6_line(line):
+ """
+ Return a normalized IPv6 line as produced by frr,
+ with all letters in lower case and trailing and leading
+ zeros removed
+ """
+ norm_line = ""
+ words = line.split(' ')
+ for word in words:
+ if ":" in word:
+ try:
+ norm_word = str(IPv6Address(word)).lower()
+ except:
+ norm_word = word
+ else:
+ norm_word = word
+ norm_line = norm_line + " " + norm_word
+
+ return norm_line.strip()
+
+
+def line_exist(lines, target_ctx_keys, target_line):
+ for (ctx_keys, line) in lines:
+ if ctx_keys == target_ctx_keys and line == target_line:
+ return True
+ return False
+
+
+def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
+
+ # Quite possibly the most confusing (while accurate) variable names in history
+ lines_to_add_to_del = []
+ lines_to_del_to_del = []
+
+ for (ctx_keys, line) in lines_to_del:
+ deleted = False
+
+ if ctx_keys[0].startswith('router bgp') and line and line.startswith('neighbor '):
+ """
+ BGP changed how it displays swpX peers that are part of peer-group. Older
+ versions of frr would display these on separate lines:
+ neighbor swp1 interface
+ neighbor swp1 peer-group FOO
+
+ but today we display via a single line
+ neighbor swp1 interface peer-group FOO
+
+ This change confuses frr-reload.py so check to see if we are deleting
+ neighbor swp1 interface peer-group FOO
+
+ and adding
+ neighbor swp1 interface
+ neighbor swp1 peer-group FOO
+
+ If so then chop the del line and the corresponding add lines
+ """
+
+ re_swpx_int_peergroup = re.search('neighbor (\S+) interface peer-group (\S+)', line)
+ re_swpx_int_v6only_peergroup = re.search('neighbor (\S+) interface v6only peer-group (\S+)', line)
+
+ if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup:
+ swpx_interface = None
+ swpx_peergroup = None
+
+ if re_swpx_int_peergroup:
+ swpx = re_swpx_int_peergroup.group(1)
+ peergroup = re_swpx_int_peergroup.group(2)
+ swpx_interface = "neighbor %s interface" % swpx
+ elif re_swpx_int_v6only_peergroup:
+ swpx = re_swpx_int_v6only_peergroup.group(1)
+ peergroup = re_swpx_int_v6only_peergroup.group(2)
+ swpx_interface = "neighbor %s interface v6only" % swpx
+
+ swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup)
+ found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
+ found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup)
+ tmp_ctx_keys = tuple(list(ctx_keys))
+
+ if not found_add_swpx_peergroup:
+ tmp_ctx_keys = list(ctx_keys)
+ tmp_ctx_keys.append('address-family ipv4 unicast')
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+ found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
+
+ if not found_add_swpx_peergroup:
+ tmp_ctx_keys = list(ctx_keys)
+ tmp_ctx_keys.append('address-family ipv6 unicast')
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+ found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
+
+ if found_add_swpx_interface and found_add_swpx_peergroup:
+ deleted = True
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, swpx_interface))
+ lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
+
+ """
+ In 3.0.1 we changed how we display neighbor interface command. Older
+ versions of frr would display the following:
+ neighbor swp1 interface
+ neighbor swp1 remote-as external
+ neighbor swp1 capability extended-nexthop
+
+ but today we display via a single line
+ neighbor swp1 interface remote-as external
+
+ and capability extended-nexthop is no longer needed because we
+ automatically enable it when the neighbor is of type interface.
+
+ This change confuses frr-reload.py so check to see if we are deleting
+ neighbor swp1 interface remote-as (external|internal|ASNUM)
+
+ and adding
+ neighbor swp1 interface
+ neighbor swp1 remote-as (external|internal|ASNUM)
+ neighbor swp1 capability extended-nexthop
+
+ If so then chop the del line and the corresponding add lines
+ """
+ re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
+ re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
+
+ if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
+ swpx_interface = None
+ swpx_remoteas = None
+
+ if re_swpx_int_remoteas:
+ swpx = re_swpx_int_remoteas.group(1)
+ remoteas = re_swpx_int_remoteas.group(2)
+ swpx_interface = "neighbor %s interface" % swpx
+ elif re_swpx_int_v6only_remoteas:
+ swpx = re_swpx_int_v6only_remoteas.group(1)
+ remoteas = re_swpx_int_v6only_remoteas.group(2)
+ swpx_interface = "neighbor %s interface v6only" % swpx
+
+ swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
+ found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
+ found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
+ tmp_ctx_keys = tuple(list(ctx_keys))
+
+ if found_add_swpx_interface and found_add_swpx_remoteas:
+ deleted = True
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, swpx_interface))
+ lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
+
+ if not deleted:
+ found_add_line = line_exist(lines_to_add, ctx_keys, line)
+
+ if found_add_line:
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, line))
+ else:
+ '''
+ We have commands that used to be displayed in the global part
+ of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
+
+ # old way
+ router bgp 64900
+ neighbor ISL advertisement-interval 0
+
+ vs.
+
+ # new way
+ router bgp 64900
+ address-family ipv4 unicast
+ neighbor ISL advertisement-interval 0
+
+ Look to see if we are deleting it in one format just to add it back in the other
+ '''
+ if ctx_keys[0].startswith('router bgp') and len(ctx_keys) > 1 and ctx_keys[1] == 'address-family ipv4 unicast':
+ tmp_ctx_keys = list(ctx_keys)[:-1]
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+
+ found_add_line = line_exist(lines_to_add, tmp_ctx_keys, line)
+
+ if found_add_line:
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((tmp_ctx_keys, line))
+
+ for (ctx_keys, line) in lines_to_del_to_del:
+ lines_to_del.remove((ctx_keys, line))
+
+ for (ctx_keys, line) in lines_to_add_to_del:
+ lines_to_add.remove((ctx_keys, line))
+
+ return (lines_to_add, lines_to_del)
+
+
+def compare_context_objects(newconf, running):
+ """
+ Create a context diff for the two specified contexts
+ """
+
+ # Compare the two Config objects to find the lines that we need to add/del
+ lines_to_add = []
+ lines_to_del = []
+ delete_bgpd = False
+
+ # Find contexts that are in newconf but not in running
+ # Find contexts that are in running but not in newconf
+ for (running_ctx_keys, running_ctx) in running.contexts.iteritems():
+
+ if running_ctx_keys not in newconf.contexts:
+
+ # We check that the len is 1 here so that we only look at ('router bgp 10')
+ # and not ('router bgp 10', 'address-family ipv4 unicast'). The
+ # latter could cause a false delete_bgpd positive if ipv4 unicast is in
+ # running but not in newconf.
+ if "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) == 1:
+ delete_bgpd = True
+ lines_to_del.append((running_ctx_keys, None))
+
+ # If this is an address-family under 'router bgp' and we are already deleting the
+ # entire 'router bgp' context then ignore this sub-context
+ elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd:
+ continue
+
+ # Non-global context
+ elif running_ctx_keys and not any("address-family" in key for key in running_ctx_keys):
+ lines_to_del.append((running_ctx_keys, None))
+
+ # Global context
+ else:
+ for line in running_ctx.lines:
+ lines_to_del.append((running_ctx_keys, line))
+
+ # Find the lines within each context to add
+ # Find the lines within each context to del
+ for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems():
+
+ if newconf_ctx_keys in running.contexts:
+ running_ctx = running.contexts[newconf_ctx_keys]
+
+ for line in newconf_ctx.lines:
+ if line not in running_ctx.dlines:
+ lines_to_add.append((newconf_ctx_keys, line))
+
+ for line in running_ctx.lines:
+ if line not in newconf_ctx.dlines:
+ lines_to_del.append((newconf_ctx_keys, line))
+
+ for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems():
+
+ if newconf_ctx_keys not in running.contexts:
+ lines_to_add.append((newconf_ctx_keys, None))
+
+ for line in newconf_ctx.lines:
+ lines_to_add.append((newconf_ctx_keys, line))
+
+ (lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del)
+
+ return (lines_to_add, lines_to_del)
+
+if __name__ == '__main__':
+ # Command line options
+ parser = argparse.ArgumentParser(description='Dynamically apply diff in frr configs')
+ parser.add_argument('--input', help='Read running config from file instead of "show running"')
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('--reload', action='store_true', help='Apply the deltas', default=False)
+ group.add_argument('--test', action='store_true', help='Show the deltas', default=False)
+ parser.add_argument('--debug', action='store_true', help='Enable debugs', default=False)
+ parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False)
+ parser.add_argument('filename', help='Location of new frr config file')
+ args = parser.parse_args()
+
+ # Logging
+ # For --test log to stdout
+ # For --reload log to /var/log/frr/frr-reload.log
+ if args.test or args.stdout:
+ logging.basicConfig(level=logging.INFO,
+ format='%(asctime)s %(levelname)5s: %(message)s')
+
+ # Color the errors and warnings in red
+ logging.addLevelName(logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR))
+ logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING))
+
+ elif args.reload:
+ if not os.path.isdir('/var/log/frr/'):
+ os.makedirs('/var/log/frr/')
+
+ logging.basicConfig(filename='/var/log/frr/frr-reload.log',
+ level=logging.INFO,
+ format='%(asctime)s %(levelname)5s: %(message)s')
+
+ # argparse should prevent this from happening but just to be safe...
+ else:
+ raise Exception('Must specify --reload or --test')
+ log = logging.getLogger(__name__)
+
+ # Verify the new config file is valid
+ if not os.path.isfile(args.filename):
+ print "Filename %s does not exist" % args.filename
+ sys.exit(1)
+
+ if not os.path.getsize(args.filename):
+ print "Filename %s is an empty file" % args.filename
+ sys.exit(1)
+
+ # Verify that 'service integrated-vtysh-config' is configured
+ vtysh_filename = '/etc/frr/vtysh.conf'
+ service_integrated_vtysh_config = True
+
+ if os.path.isfile(vtysh_filename):
+ with open(vtysh_filename, 'r') as fh:
+ for line in fh.readlines():
+ line = line.strip()
+
+ if line == 'no service integrated-vtysh-config':
+ service_integrated_vtysh_config = False
+ break
+
+ if not service_integrated_vtysh_config:
+ print "'service integrated-vtysh-config' is not configured, this is required for 'service frr reload'"
+ sys.exit(1)
+
+ if args.debug:
+ log.setLevel(logging.DEBUG)
+
+ log.info('Called via "%s"', str(args))
+
+ # Create a Config object from the config generated by newconf
+ newconf = Config()
+ newconf.load_from_file(args.filename)
+
+ if args.test:
+
+ # Create a Config object from the running config
+ running = Config()
+
+ if args.input:
+ running.load_from_file(args.input)
+ else:
+ running.load_from_show_running()
+
+ (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
+ lines_to_configure = []
+
+ if lines_to_del:
+ print "\nLines To Delete"
+ print "==============="
+
+ for (ctx_keys, line) in lines_to_del:
+
+ if line == '!':
+ continue
+
+ cmd = line_for_vtysh_file(ctx_keys, line, True)
+ lines_to_configure.append(cmd)
+ print cmd
+
+ if lines_to_add:
+ print "\nLines To Add"
+ print "============"
+
+ for (ctx_keys, line) in lines_to_add:
+
+ if line == '!':
+ continue
+
+ cmd = line_for_vtysh_file(ctx_keys, line, False)
+ lines_to_configure.append(cmd)
+ print cmd
+
+ elif args.reload:
+
+ log.debug('New Frr Config\n%s', newconf.get_lines())
+
+ # This looks a little odd but we have to do this twice...here is why
+ # If the user had this running bgp config:
+ #
+ # router bgp 10
+ # neighbor 1.1.1.1 remote-as 50
+ # neighbor 1.1.1.1 route-map FOO out
+ #
+ # and this config in the newconf config file
+ #
+ # router bgp 10
+ # neighbor 1.1.1.1 remote-as 999
+ # neighbor 1.1.1.1 route-map FOO out
+ #
+ #
+ # Then the script will do
+ # - no neighbor 1.1.1.1 remote-as 50
+ # - neighbor 1.1.1.1 remote-as 999
+ #
+ # The problem is the "no neighbor 1.1.1.1 remote-as 50" will also remove
+ # the "neighbor 1.1.1.1 route-map FOO out" line...so we compare the
+ # configs again to put this line back.
+
+ for x in range(2):
+ running = Config()
+ running.load_from_show_running()
+ log.debug('Running Frr Config (Pass #%d)\n%s', x, running.get_lines())
+
+ (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
+
+ if lines_to_del:
+ for (ctx_keys, line) in lines_to_del:
+
+ if line == '!':
+ continue
+
+ # 'no' commands are tricky, we can't just put them in a file and
+ # vtysh -f that file. See the next comment for an explanation
+ # of their quirks
+ cmd = line_to_vtysh_conft(ctx_keys, line, True)
+ original_cmd = cmd
+
+ # Some commands in frr are picky about taking a "no" of the entire line.
+ # OSPF is bad about this, you can't "no" the entire line, you have to "no"
+ # only the beginning. If we hit one of these command an exception will be
+ # thrown. Catch it and remove the last '-c', 'FOO' from cmd and try again.
+ #
+ # Example:
+ # frr(config-if)# ip ospf authentication message-digest 1.1.1.1
+ # frr(config-if)# no ip ospf authentication message-digest 1.1.1.1
+ # % Unknown command.
+ # frr(config-if)# no ip ospf authentication message-digest
+ # % Unknown command.
+ # frr(config-if)# no ip ospf authentication
+ # frr(config-if)#
+
+ while True:
+ try:
+ _ = subprocess.check_output(cmd)
+
+ except subprocess.CalledProcessError:
+
+ # - Pull the last entry from cmd (this would be
+ # 'no ip ospf authentication message-digest 1.1.1.1' in
+ # our example above
+ # - Split that last entry by whitespace and drop the last word
+ log.warning('Failed to execute %s', ' '.join(cmd))
+ last_arg = cmd[-1].split(' ')
+
+ if len(last_arg) <= 2:
+ log.error('"%s" we failed to remove this command', original_cmd)
+ break
+
+ new_last_arg = last_arg[0:-1]
+ cmd[-1] = ' '.join(new_last_arg)
+ else:
+ log.info('Executed "%s"', ' '.join(cmd))
+ break
+
+ if lines_to_add:
+ lines_to_configure = []
+
+ for (ctx_keys, line) in lines_to_add:
+
+ if line == '!':
+ continue
+
+ cmd = line_for_vtysh_file(ctx_keys, line, False)
+ lines_to_configure.append(cmd)
+
+ if lines_to_configure:
+ random_string = ''.join(random.SystemRandom().choice(
+ string.ascii_uppercase +
+ string.digits) for _ in range(6))
+
+ filename = "/var/run/frr/reload-%s.txt" % random_string
+ log.info("%s content\n%s" % (filename, pformat(lines_to_configure)))
+
+ with open(filename, 'w') as fh:
+ for line in lines_to_configure:
+ fh.write(line + '\n')
+ subprocess.call(['/usr/bin/vtysh', '-f', filename])
+ os.unlink(filename)
+
+ # Make these changes persistent
+ subprocess.call(['/usr/bin/vtysh', '-c', 'write'])
--- /dev/null
+[Unit]
+Description=Cumulus Linux FRR
+After=syslog.target networking.service
+OnFailure=heartbeat-failed@%n.service
+
+[Service]
+Nice=-5
+EnvironmentFile=/etc/default/frr
+Type=forking
+NotifyAccess=all
+StartLimitInterval=3m
+StartLimitBurst=3
+TimeoutSec=1m
+WatchdogSec=60s
+RestartSec=5
+Restart=on-abnormal
+LimitNOFILE=1024
+ExecStart=/usr/lib/frr/frr start
+ExecStop=/usr/lib/frr/frr stop
+ExecReload=/usr/lib/frr/frr-reload.py --reload /etc/frr/Frr.conf
+[Install]
+WantedBy=network-online.target
+++ /dev/null
-#!/bin/bash
-#
-### BEGIN INIT INFO
-# Provides: quagga
-# Required-Start: $local_fs $network $remote_fs $syslog
-# Required-Stop: $local_fs $network $remote_fs $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: start and stop the Quagga routing suite
-# Description: Quagga is a routing suite for IP routing protocols like
-# BGP, OSPF, RIP and others. This script contols the main
-# daemon "quagga" as well as the individual protocol daemons.
-### END INIT INFO
-#
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-D_PATH=/usr/lib/quagga
-C_PATH=/etc/quagga
-V_PATH=/var/run/quagga
-
-# Local Daemon selection may be done by using /etc/quagga/daemons.
-# See /usr/share/doc/quagga/README.Debian.gz for further information.
-# Keep zebra first and do not list watchquagga!
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd"
-MAX_INSTANCES=5
-RELOAD_SCRIPT=/usr/lib/quagga/quagga-reload.py
-
-. /lib/lsb/init-functions
-
-if [ -f /usr/lib/quagga/ssd ]; then
- SSD=/usr/lib/quagga/ssd
-else
- SSD=`which start-stop-daemon`
-fi
-
-# Print the name of the pidfile.
-pidfile()
-{
- echo "$V_PATH/$1.pid"
-}
-
-# Print the name of the vtysh.
-vtyfile()
-{
- echo "$V_PATH/$1.vty"
-}
-
-# Check if daemon is started by using the pidfile.
-started()
-{
- [ ! -e `pidfile $1` ] && return 3
- if [ -n "$2" ] && [ "$2" == "log" ]; then
- status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $?
- else
- kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
- return 0
- fi
-}
-
-# Loads the config via vtysh -b if configured to do so.
-vtysh_b ()
-{
- # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
- if [ "$vtysh_enable" = 2 -a -f $C_PATH/Quagga.conf ]; then
- /usr/bin/vtysh -b -n
- fi
-}
-
-# Check if the daemon is activated and if its executable and config files
-# are in place.
-# params: daemon name
-# returns: 0=ok, 1=error
-check_daemon()
-{
- # If the integrated config file is used the others are not checked.
- if [ -r "$C_PATH/Quagga.conf" ]; then
- return 0
- fi
-
- # vtysh_enable has no config file nor binary so skip check.
- # (Not sure why vtysh_enable is in this list but does not hurt)
- if [ $1 != "watchquagga" -a $1 != "vtysh_enable" ]; then
- # check for daemon binary
- if [ ! -x "$D_PATH/$1" ]; then return 1; fi
-
- # check for config file
- if [ -n "$2" ]; then
- if [ ! -r "$C_PATH/$1-$2.conf" ]; then
- touch "$C_PATH/$1-$2.conf"
- chown quagga:quagga "$C_PATH/$1-$2.conf"
- fi
- elif [ ! -r "$C_PATH/$1.conf" ]; then
- touch "$C_PATH/$1.conf"
- chown quagga:quagga "$C_PATH/$1.conf"
- fi
- fi
- return 0
-}
-
-# Starts the server if it's not alrady running according to the pid file.
-# The Quagga daemons creates the pidfile when starting.
-start()
-{
- ulimit -n $MAX_FDS
- if [ "$1" = "watchquagga" ]; then
-
- # We may need to restart watchquagga if new daemons are added and/or
- # removed
- if started "$1" ; then
- stop watchquagga
- else
- # Echo only once. watchquagga is printed in the stop above
- echo -n " $1"
- fi
-
- if [ -e /var/run/quagga/watchquagga.started ] ; then
- rm /var/run/quagga/watchquagga.started
- fi
- ${SSD} \
- --start \
- --pidfile=`pidfile $1` \
- --exec "$D_PATH/$1" \
- -- \
- "${watchquagga_options[@]}"
- for i in `seq 1 10`;
- do
- if [ -e /var/run/quagga/watchquagga.started ] ; then
- break
- else
- sleep 1
- fi
- done
- elif [ -n "$2" ]; then
- echo -n " $1-$2"
- if ! check_daemon $1 $2 ; then
- echo -n " (binary does not exist)"
- return;
- fi
-
- ${SSD} \
- --start \
- --pidfile=`pidfile $1-$2` \
- --exec "$D_PATH/$1" \
- -- \
- `eval echo "$""$1""_options"` -n "$2"
- else
- echo -n " $1"
- if ! check_daemon $1; then
- echo -n " (binary does not exist)"
- return;
- fi
-
- ${SSD} \
- --start \
- --pidfile=`pidfile $1` \
- --exec "$D_PATH/$1" \
- -- \
- `eval echo "$""$1""_options"`
- fi
-}
-
-# Stop the daemon given in the parameter, printing its name to the terminal.
-stop()
-{
- local inst
-
- if [ -n "$2" ]; then
- inst="$1-$2"
- else
- inst="$1"
- fi
-
- if ! started "$inst" ; then
- echo -n " ($inst)"
- return 0
- else
- PIDFILE=`pidfile $inst`
- PID=`cat $PIDFILE 2>/dev/null`
- ${SSD} --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
- #
- # Now we have to wait until $DAEMON has _really_ stopped.
- #
- if test -n "$PID" && kill -0 $PID 2>/dev/null; then
- echo -n " (waiting) ."
- cnt=0
- while kill -0 $PID 2>/dev/null; do
- cnt=`expr $cnt + 1`
- if [ $cnt -gt 60 ]; then
- # Waited 120 secs now, fail.
- echo -n "Failed.. "
- break
- fi
- sleep 2
- echo -n "."
- done
- fi
- echo -n " $inst"
- rm -f `pidfile $inst`
- rm -f `vtyfile $inst`
- fi
-}
-
-# Converts values from /etc/quagga/daemons to all-numeric values.
-convert_daemon_prios()
-{
- for name in $DAEMONS zebra vtysh_enable watchquagga_enable; do
- # First, assign the value set by the user to $value
- eval value=\${${name}:0:3}
-
- # Daemon not activated or entry missing?
- if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
-
- # These strings parsed for backwards compatibility.
- if [ "$value" = "yes" -o "$value" = "true" ]; then
- value=1;
- fi
-
- # Zebra is threatened special. It must be between 0=off and the first
- # user assigned value "1" so we increase all other enabled daemons' values.
- if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
-
- # If e.g. name is zebra then we set "zebra=yes".
- eval $name=$value
- done
-}
-
-# Starts watchquagga for all wanted daemons.
-start_watchquagga()
-{
- local daemon_name
- local daemon_prio
- local found_one
- local daemon_inst
-
- # Start the monitor daemon only if desired.
- if [ 0 -eq "$watchquagga_enable" ]; then
- return
- fi
-
- # Check variable type
- if ! declare -p watchquagga_options | grep -q '^declare \-a'; then
- echo
- echo "ERROR: The variable watchquagga_options from /etc/quagga/debian.cnf must be a BASH array!"
- echo "ERROR: Please convert config file and restart!"
- exit 1
- fi
-
- # Which daemons have been started?
- found_one=0
- for daemon_name in $DAEMONS; do
- eval daemon_prio=\$$daemon_name
- if [ "$daemon_prio" -gt 0 ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for inst in ${daemon_inst}; do
- eval "inst_disable=\${${daemon_name}_${inst}}"
- if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
- if check_daemon $daemon_name $inst; then
- watchquagga_options+=("${daemon_name}-${inst}")
- fi
- fi
- done
- else
- if check_daemon $daemon_name; then
- watchquagga_options+=($daemon_name)
- fi
- fi
- found_one=1
- fi
- done
-
- # Start if at least one daemon is activated.
- if [ $found_one -eq 1 ]; then
- echo -n "Starting Quagga monitor daemon:"
- start watchquagga
- echo "."
- fi
-}
-
-# Stopps watchquagga.
-stop_watchquagga()
-{
- echo -n "Stopping Quagga monitor daemon:"
- stop watchquagga
- echo "."
-}
-
-# Stops all daemons that have a lower level of priority than the given.
-# (technically if daemon_prio >= wanted_prio)
-stop_prio()
-{
- local wanted_prio
- local daemon_prio
- local daemon_list
- local daemon_inst
- local inst
-
- if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$2"
- fi
-
- wanted_prio=$1
- daemon_list=${daemon:-$DAEMONS}
-
- echo -n "Stopping Quagga daemons (prio:$wanted_prio):"
-
- for prio_i in `seq 10 -1 $wanted_prio`; do
- for daemon_name in $daemon_list; do
- eval daemon_prio=\${${daemon_name}:0:3}
- daemon_inst=""
- if [ $daemon_prio -eq $prio_i ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for i in ${daemon_inst}; do
- if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
- stop "$daemon_name" "$inst"
- elif [ x"$inst" == x ]; then
- stop "$daemon_name" "$i"
- fi
- done
- else
- stop "$daemon_name"
- fi
- fi
- done
- done
-
- echo "."
- if [ -z "$inst" ]; then
- # Now stop other daemons that're prowling, coz the daemons file changed
- echo -n "Stopping other quagga daemons"
- if [ -n "$daemon" ]; then
- eval "file_list_suffix="$V_PATH"/"$daemon*""
- else
- eval "file_list_suffix="$V_PATH/*""
- fi
- for pidfile in $file_list_suffix.pid; do
- PID=`cat $pidfile 2>/dev/null`
- ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
- echo -n "."
- rm -rf "$pidfile"
- done
- echo "."
-
- echo -n "Removing remaining .vty files"
- for vtyfile in $file_list_suffix.vty; do
- rm -rf "$vtyfile"
- done
- echo "."
- fi
-}
-
-# Starts all daemons that have a higher level of priority than the given.
-# (technically if daemon_prio <= wanted_prio)
-start_prio()
-{
- local wanted_prio
- local daemon_prio
- local daemon_list
- local daemon_name
- local daemon_inst
- local inst
-
- if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$2"
- fi
-
- wanted_prio=$1
- daemon_list=${daemon:-$DAEMONS}
-
- echo -n "Starting Quagga daemons (prio:$wanted_prio):"
-
- for prio_i in `seq 1 $wanted_prio`; do
- for daemon_name in $daemon_list; do
- eval daemon_prio=\$${daemon_name}
- daemon_inst=""
- if [ $daemon_prio -eq $prio_i ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
- echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
- exit 1
- fi
- # Check if we're starting again by switching from single instance
- # to MI version
- if started "$daemon_name"; then
- PIDFILE=`pidfile $daemon_name`
- ${SSD} \
- --stop --quiet --oknodo \
- --pidfile "$PIDFILE" \
- --exec "$D_PATH/$daemon_name"
-
- rm -f `pidfile $1`
- rm -f `vtyfile $1`
- fi
-
- for i in ${daemon_inst}; do
- if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
- start "$daemon_name" "$inst"
- elif [ x"$inst" == x ]; then
- start "$daemon_name" "$i"
- fi
- done
- else
- # Check if we're starting again by switching from
- # single instance to MI version
- eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
- for pidfile in $file_list_suffix.pid; do
- ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
- echo -n "."
- rm -rf "$pidfile"
- done
- for vtyfile in $file_list_suffix.vty; do
- rm -rf "$vtyfile"
- done
-
- start "$daemon_name"
- fi
- fi
- done
- done
- echo "."
-}
-
-check_status()
-{
- local daemon_name
- local daemon_prio
- local daemon_inst
- local failed_status=0
-
- if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$1"
- fi
-
- daemon_list=${daemon:-$DAEMONS}
-
- # Which daemons have been started?
- for daemon_name in $daemon_list; do
- eval daemon_prio=\$$daemon_name
- if [ "$daemon_prio" -gt 0 ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for i in ${daemon_inst}; do
- if [ -n "$inst" -a "$inst" = "$i" ]; then
- started "$1" "log" || failed_status=$?
- elif [ -z "$inst" ]; then
- started "$daemon_name-$i" "log" || failed_status=$?
- fi
- done
- else
- started "$daemon_name" "log" || failed_status=$?
- fi
- fi
- done
-
- # All daemons that need to have been started are up and running
- return $failed_status
-}
-
-#########################################################
-# Main program #
-#########################################################
-
-# Config broken but script must exit silently.
-[ ! -r "$C_PATH/daemons" ] && exit 0
-
-# Load configuration
-. "$C_PATH/daemons"
-. "$C_PATH/debian.conf"
-
-# Read configuration variable file if it is present
-[ -r /etc/default/quagga ] && . /etc/default/quagga
-
-MAX_INSTANCES=${MAX_INSTANCES:=5}
-
-# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
-convert_daemon_prios
-
-if [ ! -d $V_PATH ]; then
- echo "Creating $V_PATH"
- mkdir -p $V_PATH
- chown quagga:quagga $V_PATH
- chmod 755 /$V_PATH
-fi
-
-if [ -n "$3" ] && [ "$3" != "all" ]; then
- dmn="$2"-"$3"
-elif [ -n "$2" ] && [ "$2" != "all" ]; then
- dmn="$2"
-fi
-
-case "$1" in
- start)
- # Try to load this necessary (at least for 2.6) module.
- if [ -d /lib/modules/`uname -r` ] ; then
- echo "Loading capability module if not yet done."
- set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e
- fi
-
- # Start all daemons
- cd $C_PATH/
- if [ "$2" != "watchquagga" ]; then
- start_prio 10 $dmn
- fi
- start_watchquagga
- vtysh_b
- ;;
-
- 1|2|3|4|5|6|7|8|9|10)
- # Stop/start daemons for the appropriate priority level
- stop_prio $1
- start_prio $1
- vtysh_b
- ;;
-
- stop|0)
- # Stop all daemons at level '0' or 'stop'
- stop_watchquagga
- if [ "$dmn" != "watchquagga" ]; then
- [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
- stop_prio 0 $dmn
- fi
-
- if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
- echo "Removing all routes made by zebra."
- ip route flush proto zebra
- else
- [ -n "$dmn" ] && eval "${dmn/-/_}=0"
- start_watchquagga
- fi
- ;;
-
- reload)
- # Just apply the commands that have changed, no restart necessary
- [ ! -x "$RELOAD_SCRIPT" ] && echo "quagga-reload script not available" && exit 0
- NEW_CONFIG_FILE="${2:-$C_PATH/Quagga.conf}"
- [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
- echo "Applying only incremental changes to running configuration from Quagga.conf"
- "$RELOAD_SCRIPT" --reload /etc/quagga/Quagga.conf
- exit $?
- ;;
-
- status)
- check_status $dmn
- exit $?
- ;;
-
- restart|force-reload)
- $0 stop $dmn
- sleep 1
- $0 start $dmn
- ;;
-
- *)
- echo "Usage: /etc/init.d/quagga {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
- echo " E.g. '/etc/init.d/quagga 5' would start all daemons with a prio 1-5."
- echo " reload applies only modifications from the running config to all daemons."
- echo " reload neither restarts starts any daemon nor starts any new ones."
- echo " Read /usr/share/doc/quagga/README.Debian for details."
- exit 1
- ;;
-esac
-
-echo "Exiting from the script"
-exit 0
+++ /dev/null
-#!/usr/bin/python
-# Quagga Reloader
-# Copyright (C) 2014 Cumulus Networks, Inc.
-#
-# This file is part of Quagga.
-#
-# Quagga is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2, or (at your option) any
-# later version.
-#
-# Quagga is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Quagga; see the file COPYING. If not, write to the Free
-# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
-#
-"""
-This program
-- reads a quagga configuration text file
-- reads quagga's current running configuration via "vtysh -c 'show running'"
-- compares the two configs and determines what commands to execute to
- synchronize quagga's running configuration with the configuation in the
- text file
-"""
-
-import argparse
-import copy
-import logging
-import os
-import random
-import re
-import string
-import subprocess
-import sys
-from collections import OrderedDict
-from ipaddr import IPv6Address
-from pprint import pformat
-
-
-log = logging.getLogger(__name__)
-
-
-class VtyshMarkException(Exception):
- pass
-
-
-class Context(object):
-
- """
- A Context object represents a section of quagga configuration such as:
-!
-interface swp3
- description swp3 -> r8's swp1
- ipv6 nd suppress-ra
- link-detect
-!
-
-or a single line context object such as this:
-
-ip forwarding
-
- """
-
- def __init__(self, keys, lines):
- self.keys = keys
- self.lines = lines
-
- # Keep a dictionary of the lines, this is to make it easy to tell if a
- # line exists in this Context
- self.dlines = OrderedDict()
-
- for ligne in lines:
- self.dlines[ligne] = True
-
- def add_lines(self, lines):
- """
- Add lines to specified context
- """
-
- self.lines.extend(lines)
-
- for ligne in lines:
- self.dlines[ligne] = True
-
-
-class Config(object):
-
- """
- A quagga configuration is stored in a Config object. A Config object
- contains a dictionary of Context objects where the Context keys
- ('router ospf' for example) are our dictionary key.
- """
-
- def __init__(self):
- self.lines = []
- self.contexts = OrderedDict()
-
- def load_from_file(self, filename):
- """
- Read configuration from specified file and slurp it into internal memory
- The internal representation has been marked appropriately by passing it
- through vtysh with the -m parameter
- """
- log.info('Loading Config object from file %s', filename)
-
- try:
- file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename])
- except subprocess.CalledProcessError as e:
- raise VtyshMarkException(str(e))
-
- for line in file_output.split('\n'):
- line = line.strip()
- if ":" in line:
- qv6_line = get_normalized_ipv6_line(line)
- self.lines.append(qv6_line)
- else:
- self.lines.append(line)
-
- self.load_contexts()
-
- def load_from_show_running(self):
- """
- Read running configuration and slurp it into internal memory
- The internal representation has been marked appropriately by passing it
- through vtysh with the -m parameter
- """
- log.info('Loading Config object from vtysh show running')
-
- try:
- config_text = subprocess.check_output(
- "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -",
- shell=True)
- except subprocess.CalledProcessError as e:
- raise VtyshMarkException(str(e))
-
- for line in config_text.split('\n'):
- line = line.strip()
-
- if (line == 'Building configuration...' or
- line == 'Current configuration:' or
- not line):
- continue
-
- self.lines.append(line)
-
- self.load_contexts()
-
- def get_lines(self):
- """
- Return the lines read in from the configuration
- """
-
- return '\n'.join(self.lines)
-
- def get_contexts(self):
- """
- Return the parsed context as strings for display, log etc.
- """
-
- for (_, ctx) in sorted(self.contexts.iteritems()):
- print str(ctx) + '\n'
-
- def save_contexts(self, key, lines):
- """
- Save the provided key and lines as a context
- """
-
- if not key:
- return
-
- if lines:
- if tuple(key) not in self.contexts:
- ctx = Context(tuple(key), lines)
- self.contexts[tuple(key)] = ctx
- else:
- ctx = self.contexts[tuple(key)]
- ctx.add_lines(lines)
-
- else:
- if tuple(key) not in self.contexts:
- ctx = Context(tuple(key), [])
- self.contexts[tuple(key)] = ctx
-
- def load_contexts(self):
- """
- Parse the configuration and create contexts for each appropriate block
- """
-
- current_context_lines = []
- ctx_keys = []
-
- '''
- The end of a context is flagged via the 'end' keyword:
-
-!
-interface swp52
- ipv6 nd suppress-ra
- link-detect
-!
-end
-router bgp 10
- bgp router-id 10.0.0.1
- bgp log-neighbor-changes
- no bgp default ipv4-unicast
- neighbor EBGP peer-group
- neighbor EBGP advertisement-interval 1
- neighbor EBGP timers connect 10
- neighbor 2001:40:1:4::6 remote-as 40
- neighbor 2001:40:1:8::a remote-as 40
-!
-end
- address-family ipv6
- neighbor IBGPv6 activate
- neighbor 2001:10::2 peer-group IBGPv6
- neighbor 2001:10::3 peer-group IBGPv6
- exit-address-family
-!
-end
-router ospf
- ospf router-id 10.0.0.1
- log-adjacency-changes detail
- timers throttle spf 0 50 5000
-!
-end
- '''
-
- # The code assumes that its working on the output from the "vtysh -m"
- # command. That provides the appropriate markers to signify end of
- # a context. This routine uses that to build the contexts for the
- # config.
- #
- # There are single line contexts such as "log file /media/node/zebra.log"
- # and multi-line contexts such as "router ospf" and subcontexts
- # within a context such as "address-family" within "router bgp"
- # In each of these cases, the first line of the context becomes the
- # key of the context. So "router bgp 10" is the key for the non-address
- # family part of bgp, "router bgp 10, address-family ipv6 unicast" is
- # the key for the subcontext and so on.
- ctx_keys = []
- main_ctx_key = []
- new_ctx = True
-
- # the keywords that we know are single line contexts. bgp in this case
- # is not the main router bgp block, but enabling multi-instance
- oneline_ctx_keywords = ("access-list ",
- "bgp ",
- "debug ",
- "dump ",
- "enable ",
- "hostname ",
- "ip ",
- "ipv6 ",
- "log ",
- "password ",
- "ptm-enable",
- "router-id ",
- "service ",
- "table ",
- "username ",
- "zebra ")
-
- for line in self.lines:
-
- if not line:
- continue
-
- if line.startswith('!') or line.startswith('#'):
- continue
-
- # one line contexts
- if new_ctx is True and any(line.startswith(keyword) for keyword in oneline_ctx_keywords):
- self.save_contexts(ctx_keys, current_context_lines)
-
- # Start a new context
- main_ctx_key = []
- ctx_keys = [line, ]
- current_context_lines = []
-
- log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
- self.save_contexts(ctx_keys, current_context_lines)
- new_ctx = True
-
- elif line == "end":
- self.save_contexts(ctx_keys, current_context_lines)
- log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
-
- # Start a new context
- new_ctx = True
- main_ctx_key = []
- ctx_keys = []
- current_context_lines = []
-
- elif line == "exit-address-family" or line == "exit":
- # if this exit is for address-family ipv4 unicast, ignore the pop
- if main_ctx_key:
- self.save_contexts(ctx_keys, current_context_lines)
-
- # Start a new context
- ctx_keys = copy.deepcopy(main_ctx_key)
- current_context_lines = []
- log.debug('LINE %-50s: popping from subcontext to ctx%-50s', line, ctx_keys)
-
- elif new_ctx is True:
- if not main_ctx_key:
- ctx_keys = [line, ]
- else:
- ctx_keys = copy.deepcopy(main_ctx_key)
- main_ctx_key = []
-
- current_context_lines = []
- new_ctx = False
- log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
-
- elif "address-family " in line:
- main_ctx_key = []
-
- # Save old context first
- self.save_contexts(ctx_keys, current_context_lines)
- current_context_lines = []
- main_ctx_key = copy.deepcopy(ctx_keys)
- log.debug('LINE %-50s: entering sub-context, append to ctx_keys', line)
-
- if line == "address-family ipv6":
- ctx_keys.append("address-family ipv6 unicast")
- elif line == "address-family ipv4":
- ctx_keys.append("address-family ipv4 unicast")
- else:
- ctx_keys.append(line)
-
- else:
- # Continuing in an existing context, add non-commented lines to it
- current_context_lines.append(line)
- log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys)
-
- # Save the context of the last one
- self.save_contexts(ctx_keys, current_context_lines)
-
-
-def line_to_vtysh_conft(ctx_keys, line, delete):
- """
- Return the vtysh command for the specified context line
- """
-
- cmd = []
- cmd.append('vtysh')
- cmd.append('-c')
- cmd.append('conf t')
-
- if line:
- for ctx_key in ctx_keys:
- cmd.append('-c')
- cmd.append(ctx_key)
-
- line = line.lstrip()
-
- if delete:
- cmd.append('-c')
-
- if line.startswith('no '):
- cmd.append('%s' % line[3:])
- else:
- cmd.append('no %s' % line)
-
- else:
- cmd.append('-c')
- cmd.append(line)
-
- # If line is None then we are typically deleting an entire
- # context ('no router ospf' for example)
- else:
-
- if delete:
-
- # Only put the 'no' on the last sub-context
- for ctx_key in ctx_keys:
- cmd.append('-c')
-
- if ctx_key == ctx_keys[-1]:
- cmd.append('no %s' % ctx_key)
- else:
- cmd.append('%s' % ctx_key)
- else:
- for ctx_key in ctx_keys:
- cmd.append('-c')
- cmd.append(ctx_key)
-
- return cmd
-
-
-def line_for_vtysh_file(ctx_keys, line, delete):
- """
- Return the command as it would appear in Quagga.conf
- """
- cmd = []
-
- if line:
- for (i, ctx_key) in enumerate(ctx_keys):
- cmd.append(' ' * i + ctx_key)
-
- line = line.lstrip()
- indent = len(ctx_keys) * ' '
-
- if delete:
- if line.startswith('no '):
- cmd.append('%s%s' % (indent, line[3:]))
- else:
- cmd.append('%sno %s' % (indent, line))
-
- else:
- cmd.append(indent + line)
-
- # If line is None then we are typically deleting an entire
- # context ('no router ospf' for example)
- else:
- if delete:
-
- # Only put the 'no' on the last sub-context
- for ctx_key in ctx_keys:
-
- if ctx_key == ctx_keys[-1]:
- cmd.append('no %s' % ctx_key)
- else:
- cmd.append('%s' % ctx_key)
- else:
- for ctx_key in ctx_keys:
- cmd.append(ctx_key)
-
- return '\n' + '\n'.join(cmd)
-
-
-def get_normalized_ipv6_line(line):
- """
- Return a normalized IPv6 line as produced by quagga,
- with all letters in lower case and trailing and leading
- zeros removed
- """
- norm_line = ""
- words = line.split(' ')
- for word in words:
- if ":" in word:
- try:
- norm_word = str(IPv6Address(word)).lower()
- except:
- norm_word = word
- else:
- norm_word = word
- norm_line = norm_line + " " + norm_word
-
- return norm_line.strip()
-
-
-def line_exist(lines, target_ctx_keys, target_line):
- for (ctx_keys, line) in lines:
- if ctx_keys == target_ctx_keys and line == target_line:
- return True
- return False
-
-
-def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
-
- # Quite possibly the most confusing (while accurate) variable names in history
- lines_to_add_to_del = []
- lines_to_del_to_del = []
-
- for (ctx_keys, line) in lines_to_del:
- deleted = False
-
- if ctx_keys[0].startswith('router bgp') and line and line.startswith('neighbor '):
- """
- BGP changed how it displays swpX peers that are part of peer-group. Older
- versions of quagga would display these on separate lines:
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- but today we display via a single line
- neighbor swp1 interface peer-group FOO
-
- This change confuses quagga-reload.py so check to see if we are deleting
- neighbor swp1 interface peer-group FOO
-
- and adding
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- If so then chop the del line and the corresponding add lines
- """
-
- re_swpx_int_peergroup = re.search('neighbor (\S+) interface peer-group (\S+)', line)
- re_swpx_int_v6only_peergroup = re.search('neighbor (\S+) interface v6only peer-group (\S+)', line)
-
- if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup:
- swpx_interface = None
- swpx_peergroup = None
-
- if re_swpx_int_peergroup:
- swpx = re_swpx_int_peergroup.group(1)
- peergroup = re_swpx_int_peergroup.group(2)
- swpx_interface = "neighbor %s interface" % swpx
- elif re_swpx_int_v6only_peergroup:
- swpx = re_swpx_int_v6only_peergroup.group(1)
- peergroup = re_swpx_int_v6only_peergroup.group(2)
- swpx_interface = "neighbor %s interface v6only" % swpx
-
- swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup)
- found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
- found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup)
- tmp_ctx_keys = tuple(list(ctx_keys))
-
- if not found_add_swpx_peergroup:
- tmp_ctx_keys = list(ctx_keys)
- tmp_ctx_keys.append('address-family ipv4 unicast')
- tmp_ctx_keys = tuple(tmp_ctx_keys)
- found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
-
- if not found_add_swpx_peergroup:
- tmp_ctx_keys = list(ctx_keys)
- tmp_ctx_keys.append('address-family ipv6 unicast')
- tmp_ctx_keys = tuple(tmp_ctx_keys)
- found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
-
- if found_add_swpx_interface and found_add_swpx_peergroup:
- deleted = True
- lines_to_del_to_del.append((ctx_keys, line))
- lines_to_add_to_del.append((ctx_keys, swpx_interface))
- lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
-
- """
- In 3.0.1 we changed how we display neighbor interface command. Older
- versions of quagga would display the following:
- neighbor swp1 interface
- neighbor swp1 remote-as external
- neighbor swp1 capability extended-nexthop
-
- but today we display via a single line
- neighbor swp1 interface remote-as external
-
- and capability extended-nexthop is no longer needed because we
- automatically enable it when the neighbor is of type interface.
-
- This change confuses quagga-reload.py so check to see if we are deleting
- neighbor swp1 interface remote-as (external|internal|ASNUM)
-
- and adding
- neighbor swp1 interface
- neighbor swp1 remote-as (external|internal|ASNUM)
- neighbor swp1 capability extended-nexthop
-
- If so then chop the del line and the corresponding add lines
- """
- re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
- re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
-
- if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
- swpx_interface = None
- swpx_remoteas = None
-
- if re_swpx_int_remoteas:
- swpx = re_swpx_int_remoteas.group(1)
- remoteas = re_swpx_int_remoteas.group(2)
- swpx_interface = "neighbor %s interface" % swpx
- elif re_swpx_int_v6only_remoteas:
- swpx = re_swpx_int_v6only_remoteas.group(1)
- remoteas = re_swpx_int_v6only_remoteas.group(2)
- swpx_interface = "neighbor %s interface v6only" % swpx
-
- swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
- found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
- found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
- tmp_ctx_keys = tuple(list(ctx_keys))
-
- if found_add_swpx_interface and found_add_swpx_remoteas:
- deleted = True
- lines_to_del_to_del.append((ctx_keys, line))
- lines_to_add_to_del.append((ctx_keys, swpx_interface))
- lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
-
- if not deleted:
- found_add_line = line_exist(lines_to_add, ctx_keys, line)
-
- if found_add_line:
- lines_to_del_to_del.append((ctx_keys, line))
- lines_to_add_to_del.append((ctx_keys, line))
- else:
- '''
- We have commands that used to be displayed in the global part
- of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
-
- # old way
- router bgp 64900
- neighbor ISL advertisement-interval 0
-
- vs.
-
- # new way
- router bgp 64900
- address-family ipv4 unicast
- neighbor ISL advertisement-interval 0
-
- Look to see if we are deleting it in one format just to add it back in the other
- '''
- if ctx_keys[0].startswith('router bgp') and len(ctx_keys) > 1 and ctx_keys[1] == 'address-family ipv4 unicast':
- tmp_ctx_keys = list(ctx_keys)[:-1]
- tmp_ctx_keys = tuple(tmp_ctx_keys)
-
- found_add_line = line_exist(lines_to_add, tmp_ctx_keys, line)
-
- if found_add_line:
- lines_to_del_to_del.append((ctx_keys, line))
- lines_to_add_to_del.append((tmp_ctx_keys, line))
-
- for (ctx_keys, line) in lines_to_del_to_del:
- lines_to_del.remove((ctx_keys, line))
-
- for (ctx_keys, line) in lines_to_add_to_del:
- lines_to_add.remove((ctx_keys, line))
-
- return (lines_to_add, lines_to_del)
-
-
-def compare_context_objects(newconf, running):
- """
- Create a context diff for the two specified contexts
- """
-
- # Compare the two Config objects to find the lines that we need to add/del
- lines_to_add = []
- lines_to_del = []
- delete_bgpd = False
-
- # Find contexts that are in newconf but not in running
- # Find contexts that are in running but not in newconf
- for (running_ctx_keys, running_ctx) in running.contexts.iteritems():
-
- if running_ctx_keys not in newconf.contexts:
-
- # We check that the len is 1 here so that we only look at ('router bgp 10')
- # and not ('router bgp 10', 'address-family ipv4 unicast'). The
- # latter could cause a false delete_bgpd positive if ipv4 unicast is in
- # running but not in newconf.
- if "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) == 1:
- delete_bgpd = True
- lines_to_del.append((running_ctx_keys, None))
-
- # If this is an address-family under 'router bgp' and we are already deleting the
- # entire 'router bgp' context then ignore this sub-context
- elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd:
- continue
-
- # Non-global context
- elif running_ctx_keys and not any("address-family" in key for key in running_ctx_keys):
- lines_to_del.append((running_ctx_keys, None))
-
- # Global context
- else:
- for line in running_ctx.lines:
- lines_to_del.append((running_ctx_keys, line))
-
- # Find the lines within each context to add
- # Find the lines within each context to del
- for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems():
-
- if newconf_ctx_keys in running.contexts:
- running_ctx = running.contexts[newconf_ctx_keys]
-
- for line in newconf_ctx.lines:
- if line not in running_ctx.dlines:
- lines_to_add.append((newconf_ctx_keys, line))
-
- for line in running_ctx.lines:
- if line not in newconf_ctx.dlines:
- lines_to_del.append((newconf_ctx_keys, line))
-
- for (newconf_ctx_keys, newconf_ctx) in newconf.contexts.iteritems():
-
- if newconf_ctx_keys not in running.contexts:
- lines_to_add.append((newconf_ctx_keys, None))
-
- for line in newconf_ctx.lines:
- lines_to_add.append((newconf_ctx_keys, line))
-
- (lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del)
-
- return (lines_to_add, lines_to_del)
-
-if __name__ == '__main__':
- # Command line options
- parser = argparse.ArgumentParser(description='Dynamically apply diff in quagga configs')
- parser.add_argument('--input', help='Read running config from file instead of "show running"')
- group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('--reload', action='store_true', help='Apply the deltas', default=False)
- group.add_argument('--test', action='store_true', help='Show the deltas', default=False)
- parser.add_argument('--debug', action='store_true', help='Enable debugs', default=False)
- parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False)
- parser.add_argument('filename', help='Location of new quagga config file')
- args = parser.parse_args()
-
- # Logging
- # For --test log to stdout
- # For --reload log to /var/log/quagga/quagga-reload.log
- if args.test or args.stdout:
- logging.basicConfig(level=logging.INFO,
- format='%(asctime)s %(levelname)5s: %(message)s')
-
- # Color the errors and warnings in red
- logging.addLevelName(logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR))
- logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING))
-
- elif args.reload:
- if not os.path.isdir('/var/log/quagga/'):
- os.makedirs('/var/log/quagga/')
-
- logging.basicConfig(filename='/var/log/quagga/quagga-reload.log',
- level=logging.INFO,
- format='%(asctime)s %(levelname)5s: %(message)s')
-
- # argparse should prevent this from happening but just to be safe...
- else:
- raise Exception('Must specify --reload or --test')
- log = logging.getLogger(__name__)
-
- # Verify the new config file is valid
- if not os.path.isfile(args.filename):
- print "Filename %s does not exist" % args.filename
- sys.exit(1)
-
- if not os.path.getsize(args.filename):
- print "Filename %s is an empty file" % args.filename
- sys.exit(1)
-
- # Verify that 'service integrated-vtysh-config' is configured
- vtysh_filename = '/etc/quagga/vtysh.conf'
- service_integrated_vtysh_config = True
-
- if os.path.isfile(vtysh_filename):
- with open(vtysh_filename, 'r') as fh:
- for line in fh.readlines():
- line = line.strip()
-
- if line == 'no service integrated-vtysh-config':
- service_integrated_vtysh_config = False
- break
-
- if not service_integrated_vtysh_config:
- print "'service integrated-vtysh-config' is not configured, this is required for 'service quagga reload'"
- sys.exit(1)
-
- if args.debug:
- log.setLevel(logging.DEBUG)
-
- log.info('Called via "%s"', str(args))
-
- # Create a Config object from the config generated by newconf
- newconf = Config()
- newconf.load_from_file(args.filename)
-
- if args.test:
-
- # Create a Config object from the running config
- running = Config()
-
- if args.input:
- running.load_from_file(args.input)
- else:
- running.load_from_show_running()
-
- (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
- lines_to_configure = []
-
- if lines_to_del:
- print "\nLines To Delete"
- print "==============="
-
- for (ctx_keys, line) in lines_to_del:
-
- if line == '!':
- continue
-
- cmd = line_for_vtysh_file(ctx_keys, line, True)
- lines_to_configure.append(cmd)
- print cmd
-
- if lines_to_add:
- print "\nLines To Add"
- print "============"
-
- for (ctx_keys, line) in lines_to_add:
-
- if line == '!':
- continue
-
- cmd = line_for_vtysh_file(ctx_keys, line, False)
- lines_to_configure.append(cmd)
- print cmd
-
- elif args.reload:
-
- log.debug('New Quagga Config\n%s', newconf.get_lines())
-
- # This looks a little odd but we have to do this twice...here is why
- # If the user had this running bgp config:
- #
- # router bgp 10
- # neighbor 1.1.1.1 remote-as 50
- # neighbor 1.1.1.1 route-map FOO out
- #
- # and this config in the newconf config file
- #
- # router bgp 10
- # neighbor 1.1.1.1 remote-as 999
- # neighbor 1.1.1.1 route-map FOO out
- #
- #
- # Then the script will do
- # - no neighbor 1.1.1.1 remote-as 50
- # - neighbor 1.1.1.1 remote-as 999
- #
- # The problem is the "no neighbor 1.1.1.1 remote-as 50" will also remove
- # the "neighbor 1.1.1.1 route-map FOO out" line...so we compare the
- # configs again to put this line back.
-
- for x in range(2):
- running = Config()
- running.load_from_show_running()
- log.debug('Running Quagga Config (Pass #%d)\n%s', x, running.get_lines())
-
- (lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
-
- if lines_to_del:
- for (ctx_keys, line) in lines_to_del:
-
- if line == '!':
- continue
-
- # 'no' commands are tricky, we can't just put them in a file and
- # vtysh -f that file. See the next comment for an explanation
- # of their quirks
- cmd = line_to_vtysh_conft(ctx_keys, line, True)
- original_cmd = cmd
-
- # Some commands in quagga are picky about taking a "no" of the entire line.
- # OSPF is bad about this, you can't "no" the entire line, you have to "no"
- # only the beginning. If we hit one of these command an exception will be
- # thrown. Catch it and remove the last '-c', 'FOO' from cmd and try again.
- #
- # Example:
- # quagga(config-if)# ip ospf authentication message-digest 1.1.1.1
- # quagga(config-if)# no ip ospf authentication message-digest 1.1.1.1
- # % Unknown command.
- # quagga(config-if)# no ip ospf authentication message-digest
- # % Unknown command.
- # quagga(config-if)# no ip ospf authentication
- # quagga(config-if)#
-
- while True:
- try:
- _ = subprocess.check_output(cmd)
-
- except subprocess.CalledProcessError:
-
- # - Pull the last entry from cmd (this would be
- # 'no ip ospf authentication message-digest 1.1.1.1' in
- # our example above
- # - Split that last entry by whitespace and drop the last word
- log.warning('Failed to execute %s', ' '.join(cmd))
- last_arg = cmd[-1].split(' ')
-
- if len(last_arg) <= 2:
- log.error('"%s" we failed to remove this command', original_cmd)
- break
-
- new_last_arg = last_arg[0:-1]
- cmd[-1] = ' '.join(new_last_arg)
- else:
- log.info('Executed "%s"', ' '.join(cmd))
- break
-
- if lines_to_add:
- lines_to_configure = []
-
- for (ctx_keys, line) in lines_to_add:
-
- if line == '!':
- continue
-
- cmd = line_for_vtysh_file(ctx_keys, line, False)
- lines_to_configure.append(cmd)
-
- if lines_to_configure:
- random_string = ''.join(random.SystemRandom().choice(
- string.ascii_uppercase +
- string.digits) for _ in range(6))
-
- filename = "/var/run/quagga/reload-%s.txt" % random_string
- log.info("%s content\n%s" % (filename, pformat(lines_to_configure)))
-
- with open(filename, 'w') as fh:
- for line in lines_to_configure:
- fh.write(line + '\n')
- subprocess.call(['/usr/bin/vtysh', '-f', filename])
- os.unlink(filename)
-
- # Make these changes persistent
- subprocess.call(['/usr/bin/vtysh', '-c', 'write'])
+++ /dev/null
-[Unit]
-Description=Cumulus Linux Quagga
-After=syslog.target networking.service
-OnFailure=heartbeat-failed@%n.service
-
-[Service]
-Nice=-5
-EnvironmentFile=/etc/default/quagga
-Type=forking
-NotifyAccess=all
-StartLimitInterval=3m
-StartLimitBurst=3
-TimeoutSec=1m
-WatchdogSec=60s
-RestartSec=5
-Restart=on-abnormal
-LimitNOFILE=1024
-ExecStart=/usr/lib/quagga/quagga start
-ExecStop=/usr/lib/quagga/quagga stop
-ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
-[Install]
-WantedBy=network-online.target
$(top_srcdir)/zebra/zebra_fpm.c \
$(top_srcdir)/zebra/zebra_ptm.c \
$(top_srcdir)/zebra/zebra_mpls_vty.c \
- $(top_srcdir)/watchquagga/watchquagga_vty.c \
+ $(top_srcdir)/watchfrr/watchfrr_vty.c \
$(BGP_VNC_RFAPI_SRC) $(BGP_VNC_RFP_SRC)
vtysh_cmd.c: $(vtysh_cmd_FILES) extract.pl
$ignore{'"router ospf [(1-65535)]"'} = "ignore";
$ignore{'"address-family vpnv6 [unicast]"'} = "ignore";
$ignore{'"address-family vpnv4 [unicast]"'} = "ignore";
+$ignore{'"logical-router (1-65535) ns NAME"'} = "ignore";
my $cli_stomp = 0;
{ .fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .path = BGP_VTYSH_PATH, .next = NULL},
{ .fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .path = ISIS_VTYSH_PATH, .next = NULL},
{ .fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .path = PIM_VTYSH_PATH, .next = NULL},
- { .fd = -1, .name = "watchquagga", .flag = VTYSH_WATCHQUAGGA, .path = WATCHQUAGGA_VTYSH_PATH, .next = NULL},
+ { .fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .path = WATCHFRR_VTYSH_PATH, .next = NULL},
};
enum vtysh_write_integrated vtysh_write_integrated = WRITE_INTEGRATED_UNSPECIFIED;
err++;
}
- pwentry = getpwnam (QUAGGA_USER);
+ pwentry = getpwnam (FRR_USER);
if (pwentry)
uid = pwentry->pw_uid;
else
{
- printf ("%% Warning: could not look up user \"%s\"\n", QUAGGA_USER);
+ printf ("%% Warning: could not look up user \"%s\"\n", FRR_USER);
err++;
}
- grentry = getgrnam (QUAGGA_GROUP);
+ grentry = getgrnam (FRR_GROUP);
if (grentry)
gid = grentry->gr_gid;
else
{
- printf ("%% Warning: could not look up group \"%s\"\n", QUAGGA_GROUP);
+ printf ("%% Warning: could not look up group \"%s\"\n", FRR_GROUP);
err++;
}
{
ret = CMD_WARNING;
for (i = 0; i < array_size(vtysh_client); i++)
- if (vtysh_client[i].flag == VTYSH_WATCHQUAGGA)
+ if (vtysh_client[i].flag == VTYSH_WATCHFRR)
break;
if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1)
ret = vtysh_client_execute (&vtysh_client[i], "write integrated", stdout);
if (ret != CMD_SUCCESS)
{
printf("\nWarning: attempting direct configuration write without "
- "watchquagga.\nFile permissions and ownership may be "
+ "watchfrr.\nFile permissions and ownership may be "
"incorrect, or write may fail.\n\n");
ret = vtysh_write_config_integrated();
}
if (head_client->flag != VTYSH_OSPFD) return;
- /* ls /var/run/quagga/ and look for all files ending in .vty */
- dir = opendir("/var/run/quagga/");
+ /* ls DAEMON_VTY_DIR and look for all files ending in .vty */
+ dir = opendir(DAEMON_VTY_DIR "/");
if (dir)
{
while ((file = readdir(dir)) != NULL)
if (n == MAXIMUM_INSTANCES)
{
fprintf(stderr,
- "Parsing /var/run/quagga/, client limit(%d) reached!\n", n);
+ "Parsing %s/, client limit(%d) reached!\n",
+ DAEMON_VTY_DIR, n);
break;
}
client = (struct vtysh_client *) malloc(sizeof(struct vtysh_client));
client->name = "ospfd";
client->flag = VTYSH_OSPFD;
ptr = (char *) malloc(100);
- sprintf(ptr, "/var/run/quagga/%s", file->d_name);
+ sprintf(ptr, "%s/%s", DAEMON_VTY_DIR, file->d_name);
client->path = (const char *)ptr;
client->next = NULL;
vtysh_client_sorted_insert(head_client, client);
#define VTYSH_ISISD 0x40
#define VTYSH_PIMD 0x100
#define VTYSH_LDPD 0x200
-#define VTYSH_WATCHQUAGGA 0x400
+#define VTYSH_WATCHFRR 0x400
/* commands in REALLYALL are crucial to correct vtysh operation */
#define VTYSH_REALLYALL ~0U
-/* watchquagga is not in ALL since library CLI functions should not be
+/* watchfrr is not in ALL since library CLI functions should not be
* run on it (logging & co. should stay in a fixed/frozen config, and
* things like prefix lists are not even initialised) */
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD
"Note that multiple commands may be executed from the command\n" \
"line by passing multiple -c args, or by embedding linefeed\n" \
"characters in one or more of the commands.\n\n" \
- "Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+ "Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
exit (status);
}
pam_handle_t *pamh = NULL;
/* Start PAM. */
- ret = pam_start(QUAGGA_PROGNAME, user, &conv, &pamh);
+ ret = pam_start(FRR_PAM_NAME, user, &conv, &pamh);
/* printf ("ret %d\n", ret); */
/* Is user really user? */
--- /dev/null
+Makefile
+Makefile.in
+*.o
+watchfrr
+tags
+TAGS
+.deps
+.nfs*
+*.lo
+*.la
+*.libs
+.arch-inventory
+.arch-ids
+*~
+*.loT
+
--- /dev/null
+## Process this file with Automake to create Makefile.in
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
+DEFS = @DEFS@ -DSTATEDIR=\"$(localstatedir)/\"
+
+AM_CFLAGS = $(WERROR)
+
+sbin_PROGRAMS = watchfrr
+
+noinst_HEADERS = watchfrr.h
+
+watchfrr_SOURCES = watchfrr.c watchfrr_vty.c
+watchfrr_LDADD = ../lib/libzebra.la @LIBCAP@
--- /dev/null
+/*
+ Monitor status of frr daemons and restart if necessary.
+
+ Copyright (C) 2004 Andrew J. Schorr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <zebra.h>
+#include <thread.h>
+#include <log.h>
+#include <network.h>
+#include <sigevent.h>
+#include <lib/version.h>
+#include "command.h"
+#include "memory_vty.h"
+
+#include <getopt.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <memory.h>
+#include <systemd.h>
+
+#include "watchfrr.h"
+
+#ifndef MIN
+#define MIN(X,Y) (((X) <= (Y)) ? (X) : (Y))
+#endif
+
+/* Macros to help randomize timers. */
+#define JITTER(X) ((random() % ((X)+1))-((X)/2))
+#define FUZZY(X) ((X)+JITTER((X)/20))
+
+#define DEFAULT_PERIOD 5
+#define DEFAULT_TIMEOUT 10
+#define DEFAULT_RESTART_TIMEOUT 20
+#define DEFAULT_LOGLEVEL LOG_INFO
+#define DEFAULT_MIN_RESTART 60
+#define DEFAULT_MAX_RESTART 600
+#ifdef PATH_WATCHFRR_PID
+#define DEFAULT_PIDFILE PATH_WATCHFRR_PID
+#else
+#define DEFAULT_PIDFILE STATEDIR "/watchfrr.pid"
+#endif
+#ifdef DAEMON_VTY_DIR
+#define VTYDIR DAEMON_VTY_DIR
+#else
+#define VTYDIR STATEDIR
+#endif
+
+#define PING_TOKEN "PING"
+
+/* Needs to be global, referenced somewhere inside libzebra. */
+struct thread_master *master;
+
+typedef enum
+{
+ MODE_MONITOR = 0,
+ MODE_GLOBAL_RESTART,
+ MODE_SEPARATE_RESTART,
+ MODE_PHASED_ZEBRA_RESTART,
+ MODE_PHASED_ALL_RESTART
+} watch_mode_t;
+
+static const char *mode_str[] =
+{
+ "monitor",
+ "global restart",
+ "individual daemon restart",
+ "phased zebra restart",
+ "phased global restart for any failure",
+};
+
+typedef enum
+{
+ PHASE_NONE = 0,
+ PHASE_STOPS_PENDING,
+ PHASE_WAITING_DOWN,
+ PHASE_ZEBRA_RESTART_PENDING,
+ PHASE_WAITING_ZEBRA_UP
+} restart_phase_t;
+
+static const char *phase_str[] =
+{
+ "None",
+ "Stop jobs running",
+ "Waiting for other daemons to come down",
+ "Zebra restart job running",
+ "Waiting for zebra to come up",
+ "Start jobs running",
+};
+
+#define PHASE_TIMEOUT (3*gs.restart_timeout)
+
+struct restart_info
+{
+ const char *name;
+ const char *what;
+ pid_t pid;
+ struct timeval time;
+ long interval;
+ struct thread *t_kill;
+ int kills;
+};
+
+static struct global_state
+{
+ watch_mode_t mode;
+ restart_phase_t phase;
+ struct thread *t_phase_hanging;
+ const char *vtydir;
+ long period;
+ long timeout;
+ long restart_timeout;
+ long min_restart_interval;
+ long max_restart_interval;
+ int do_ping;
+ struct daemon *daemons;
+ const char *restart_command;
+ const char *start_command;
+ const char *stop_command;
+ struct restart_info restart;
+ int unresponsive_restart;
+ int loglevel;
+ struct daemon *special; /* points to zebra when doing phased restart */
+ int numdaemons;
+ int numpids;
+ int numdown; /* # of daemons that are not UP or UNRESPONSIVE */
+} gs = {
+ .mode = MODE_MONITOR,
+ .phase = PHASE_NONE,
+ .vtydir = VTYDIR,
+ .period = 1000*DEFAULT_PERIOD,
+ .timeout = DEFAULT_TIMEOUT,
+ .restart_timeout = DEFAULT_RESTART_TIMEOUT,
+ .loglevel = DEFAULT_LOGLEVEL,
+ .min_restart_interval = DEFAULT_MIN_RESTART,
+ .max_restart_interval = DEFAULT_MAX_RESTART,
+ .do_ping = 1,
+};
+
+typedef enum
+{
+ DAEMON_INIT,
+ DAEMON_DOWN,
+ DAEMON_CONNECTING,
+ DAEMON_UP,
+ DAEMON_UNRESPONSIVE
+} daemon_state_t;
+
+#define IS_UP(DMN) \
+ (((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE))
+
+static const char *state_str[] =
+{
+ "Init",
+ "Down",
+ "Connecting",
+ "Up",
+ "Unresponsive",
+};
+
+struct daemon {
+ const char *name;
+ daemon_state_t state;
+ int fd;
+ struct timeval echo_sent;
+ u_int connect_tries;
+ struct thread *t_wakeup;
+ struct thread *t_read;
+ struct thread *t_write;
+ struct daemon *next;
+ struct restart_info restart;
+};
+
+static const struct option longopts[] =
+{
+ { "daemon", no_argument, NULL, 'd'},
+ { "statedir", required_argument, NULL, 'S'},
+ { "no-echo", no_argument, NULL, 'e'},
+ { "loglevel", required_argument, NULL, 'l'},
+ { "interval", required_argument, NULL, 'i'},
+ { "timeout", required_argument, NULL, 't'},
+ { "restart-timeout", required_argument, NULL, 'T'},
+ { "restart", required_argument, NULL, 'r'},
+ { "start-command", required_argument, NULL, 's'},
+ { "kill-command", required_argument, NULL, 'k'},
+ { "restart-all", required_argument, NULL, 'R'},
+ { "all-restart", no_argument, NULL, 'a'},
+ { "always-all-restart", no_argument, NULL, 'A'},
+ { "unresponsive-restart", no_argument, NULL, 'z'},
+ { "min-restart-interval", required_argument, NULL, 'm'},
+ { "max-restart-interval", required_argument, NULL, 'M'},
+ { "pid-file", required_argument, NULL, 'p'},
+ { "blank-string", required_argument, NULL, 'b'},
+ { "help", no_argument, NULL, 'h'},
+ { "version", no_argument, NULL, 'v'},
+ { NULL, 0, NULL, 0 }
+};
+
+static int try_connect(struct daemon *dmn);
+static int wakeup_send_echo(struct thread *t_wakeup);
+static void try_restart(struct daemon *dmn);
+static void phase_check(void);
+
+static int
+usage(const char *progname, int status)
+{
+ if (status != 0)
+ fprintf(stderr, "Try `%s --help' for more information.\n", progname);
+ else
+ {
+ printf("Usage : %s [OPTION...] <daemon name> ...\n\n\
+Watchdog program to monitor status of frr daemons and try to restart\n\
+them if they are down or unresponsive. It determines whether a daemon is\n\
+up based on whether it can connect to the daemon's vty unix stream socket.\n\
+It then repeatedly sends echo commands over that socket to determine whether\n\
+the daemon is responsive. If the daemon crashes, we will receive an EOF\n\
+on the socket connection and know immediately that the daemon is down.\n\n\
+The daemons to be monitored should be listed on the command line.\n\n\
+This program can run in one of 5 modes:\n\n\
+0. Mode: %s.\n\
+ Just monitor and report on status changes. Example:\n\
+ %s -d zebra ospfd bgpd\n\n\
+1. Mode: %s.\n\
+ Whenever any daemon hangs or crashes, use the given command to restart\n\
+ them all. Example:\n\
+ %s -dz \\\n\
+ -R '/sbin/service zebra restart; /sbin/service ospfd restart' \\\n\
+ zebra ospfd\n\n\
+2. Mode: %s.\n\
+ When any single daemon hangs or crashes, restart only the daemon that's\n\
+ in trouble using the supplied restart command. Example:\n\
+ %s -dz -r '/sbin/service %%s restart' zebra ospfd bgpd\n\n\
+3. Mode: %s.\n\
+ The same as the previous mode, except that there is special treatment when\n\
+ the zebra daemon is in trouble. In that case, a phased restart approach\n\
+ is used: 1. stop all other daemons; 2. restart zebra; 3. start the other\n\
+ daemons. Example:\n\
+ %s -adz -r '/sbin/service %%s restart' \\\n\
+ -s '/sbin/service %%s start' \\\n\
+ -k '/sbin/service %%s stop' zebra ospfd bgpd\n\n\
+4. Mode: %s.\n\
+ This is the same as the previous mode, except that the phased restart\n\
+ procedure is used whenever any of the daemons hangs or crashes. Example:\n\
+ %s -Adz -r '/sbin/service %%s restart' \\\n\
+ -s '/sbin/service %%s start' \\\n\
+ -k '/sbin/service %%s stop' zebra ospfd bgpd\n\n\
+As of this writing, it is believed that mode 2 [%s]\n\
+is not safe, and mode 3 [%s] may not be safe with some of the\n\
+routing daemons.\n\n\
+In order to avoid attempting to restart the daemons in a fast loop,\n\
+the -m and -M options allow you to control the minimum delay between\n\
+restart commands. The minimum restart delay is recalculated each time\n\
+a restart is attempted: if the time since the last restart attempt exceeds\n\
+twice the -M value, then the restart delay is set to the -m value.\n\
+Otherwise, the interval is doubled (but capped at the -M value).\n\n",
+ progname,mode_str[0],progname,mode_str[1],progname,mode_str[2],
+ progname,mode_str[3],progname,mode_str[4],progname,mode_str[2],
+ mode_str[3]);
+
+ printf("Options:\n\
+-d, --daemon Run in daemon mode. In this mode, error messages are sent\n\
+ to syslog instead of stdout.\n\
+-S, --statedir Set the vty socket directory (default is %s)\n\
+-e, --no-echo Do not ping the daemons to test responsiveness (this\n\
+ option is necessary if the daemons do not support the\n\
+ echo command)\n\
+-l, --loglevel Set the logging level (default is %d).\n\
+ The value should range from %d (LOG_EMERG) to %d (LOG_DEBUG),\n\
+ but it can be set higher than %d if extra-verbose debugging\n\
+ messages are desired.\n\
+-m, --min-restart-interval\n\
+ Set the minimum seconds to wait between invocations of daemon\n\
+ restart commands (default is %d).\n\
+-M, --max-restart-interval\n\
+ Set the maximum seconds to wait between invocations of daemon\n\
+ restart commands (default is %d).\n\
+-i, --interval Set the status polling interval in seconds (default is %d)\n\
+-t, --timeout Set the unresponsiveness timeout in seconds (default is %d)\n\
+-T, --restart-timeout\n\
+ Set the restart (kill) timeout in seconds (default is %d).\n\
+ If any background jobs are still running after this much\n\
+ time has elapsed, they will be killed.\n\
+-r, --restart Supply a Bourne shell command to use to restart a single\n\
+ daemon. The command string should include '%%s' where the\n\
+ name of the daemon should be substituted.\n\
+ Note that -r and -R are incompatible.\n\
+-s, --start-command\n\
+ Supply a Bourne shell to command to use to start a single\n\
+ daemon. The command string should include '%%s' where the\n\
+ name of the daemon should be substituted.\n\
+-k, --kill-command\n\
+ Supply a Bourne shell to command to use to stop a single\n\
+ daemon. The command string should include '%%s' where the\n\
+ name of the daemon should be substituted.\n\
+-R, --restart-all\n\
+ When one or more daemons is down, try to restart everything\n\
+ using the Bourne shell command supplied as the argument.\n\
+ Note that -r and -R are incompatible.\n\
+-z, --unresponsive-restart\n\
+ When a daemon is unresponsive, treat it as being down for\n\
+ restart purposes.\n\
+-a, --all-restart\n\
+ When zebra hangs or crashes, restart all daemons using\n\
+ this phased approach: 1. stop all other daemons; 2. restart\n\
+ zebra; 3. start other daemons. Requires -r, -s, and -k.\n\
+-A, --always-all-restart\n\
+ When any daemon (not just zebra) hangs or crashes, use the\n\
+ same phased restart mechanism described above for -a.\n\
+ Requires -r, -s, and -k.\n\
+-p, --pid-file Set process identifier file name\n\
+ (default is %s).\n\
+-b, --blank-string\n\
+ When the supplied argument string is found in any of the\n\
+ various shell command arguments (-r, -s, -k, or -R), replace\n\
+ it with a space. This is an ugly hack to circumvent problems\n\
+ passing command-line arguments with embedded spaces.\n\
+-v, --version Print program version\n\
+-h, --help Display this help and exit\n",
+ VTYDIR,DEFAULT_LOGLEVEL,LOG_EMERG,LOG_DEBUG,LOG_DEBUG,
+ DEFAULT_MIN_RESTART,DEFAULT_MAX_RESTART,
+ DEFAULT_PERIOD,DEFAULT_TIMEOUT,DEFAULT_RESTART_TIMEOUT,
+ DEFAULT_PIDFILE);
+ }
+
+ return status;
+}
+
+static pid_t
+run_background(char *shell_cmd)
+{
+ pid_t child;
+
+ switch (child = fork())
+ {
+ case -1:
+ zlog_err("fork failed, cannot run command [%s]: %s",
+ shell_cmd,safe_strerror(errno));
+ return -1;
+ case 0:
+ /* Child process. */
+ /* Use separate process group so child processes can be killed easily. */
+ if (setpgid(0,0) < 0)
+ zlog_warn("warning: setpgid(0,0) failed: %s",safe_strerror(errno));
+ {
+ char shell[] = "sh";
+ char dashc[] = "-c";
+ char * const argv[4] = { shell, dashc, shell_cmd, NULL};
+ execv("/bin/sh", argv);
+ zlog_err("execv(/bin/sh -c '%s') failed: %s",
+ shell_cmd,safe_strerror(errno));
+ _exit(127);
+ }
+ default:
+ /* Parent process: we will reap the child later. */
+ zlog_err("Forked background command [pid %d]: %s",(int)child,shell_cmd);
+ return child;
+ }
+}
+
+static struct timeval *
+time_elapsed(struct timeval *result, const struct timeval *start_time)
+{
+ gettimeofday(result,NULL);
+ result->tv_sec -= start_time->tv_sec;
+ result->tv_usec -= start_time->tv_usec;
+ while (result->tv_usec < 0)
+ {
+ result->tv_usec += 1000000L;
+ result->tv_sec--;
+ }
+ return result;
+}
+
+static int
+restart_kill(struct thread *t_kill)
+{
+ struct restart_info *restart = THREAD_ARG(t_kill);
+ struct timeval delay;
+
+ time_elapsed(&delay,&restart->time);
+ zlog_warn("Warning: %s %s child process %d still running after "
+ "%ld seconds, sending signal %d",
+ restart->what,restart->name,(int)restart->pid, (long)delay.tv_sec,
+ (restart->kills ? SIGKILL : SIGTERM));
+ kill(-restart->pid,(restart->kills ? SIGKILL : SIGTERM));
+ restart->kills++;
+ restart->t_kill = thread_add_timer(master,restart_kill,restart,
+ gs.restart_timeout);
+ return 0;
+}
+
+static struct restart_info *
+find_child(pid_t child)
+{
+ if (gs.mode == MODE_GLOBAL_RESTART)
+ {
+ if (gs.restart.pid == child)
+ return &gs.restart;
+ }
+ else
+ {
+ struct daemon *dmn;
+ for (dmn = gs.daemons; dmn; dmn = dmn->next)
+ {
+ if (dmn->restart.pid == child)
+ return &dmn->restart;
+ }
+ }
+ return NULL;
+}
+
+static void
+sigchild(void)
+{
+ pid_t child;
+ int status;
+ const char *name;
+ const char *what;
+ struct restart_info *restart;
+
+ switch (child = waitpid(-1,&status,WNOHANG))
+ {
+ case -1:
+ zlog_err("waitpid failed: %s",safe_strerror(errno));
+ return;
+ case 0:
+ zlog_warn("SIGCHLD received, but waitpid did not reap a child");
+ return;
+ }
+
+ if (child == integrated_write_pid)
+ {
+ integrated_write_sigchld(status);
+ return;
+ }
+
+ if ((restart = find_child(child)) != NULL)
+ {
+ name = restart->name;
+ what = restart->what;
+ restart->pid = 0;
+ gs.numpids--;
+ thread_cancel(restart->t_kill);
+ restart->t_kill = NULL;
+ /* Update restart time to reflect the time the command completed. */
+ gettimeofday(&restart->time,NULL);
+ }
+ else
+ {
+ zlog_err("waitpid returned status for an unknown child process %d",
+ (int)child);
+ name = "(unknown)";
+ what = "background";
+ }
+ if (WIFSTOPPED(status))
+ zlog_warn("warning: %s %s process %d is stopped",
+ what,name,(int)child);
+ else if (WIFSIGNALED(status))
+ zlog_warn("%s %s process %d terminated due to signal %d",
+ what,name,(int)child,WTERMSIG(status));
+ else if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) != 0)
+ zlog_warn("%s %s process %d exited with non-zero status %d",
+ what,name,(int)child,WEXITSTATUS(status));
+ else
+ zlog_debug("%s %s process %d exited normally",what,name,(int)child);
+ }
+ else
+ zlog_err("cannot interpret %s %s process %d wait status 0x%x",
+ what,name,(int)child,status);
+ phase_check();
+}
+
+static int
+run_job(struct restart_info *restart, const char *cmdtype, const char *command,
+ int force, int update_interval)
+{
+ struct timeval delay;
+
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("attempting to %s %s",cmdtype,restart->name);
+
+ if (restart->pid)
+ {
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("cannot %s %s, previous pid %d still running",
+ cmdtype,restart->name,(int)restart->pid);
+ return -1;
+ }
+
+ /* Note: time_elapsed test must come before the force test, since we need
+ to make sure that delay is initialized for use below in updating the
+ restart interval. */
+ if ((time_elapsed(&delay,&restart->time)->tv_sec < restart->interval) &&
+ !force)
+ {
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("postponing %s %s: "
+ "elapsed time %ld < retry interval %ld",
+ cmdtype,restart->name,(long)delay.tv_sec,restart->interval);
+ return -1;
+ }
+
+ gettimeofday(&restart->time,NULL);
+ restart->kills = 0;
+ {
+ char cmd[strlen(command)+strlen(restart->name)+1];
+ snprintf(cmd,sizeof(cmd),command,restart->name);
+ if ((restart->pid = run_background(cmd)) > 0)
+ {
+ restart->t_kill = thread_add_timer(master,restart_kill,restart,
+ gs.restart_timeout);
+ restart->what = cmdtype;
+ gs.numpids++;
+ }
+ else
+ restart->pid = 0;
+ }
+
+ /* Calculate the new restart interval. */
+ if (update_interval)
+ {
+ if (delay.tv_sec > 2*gs.max_restart_interval)
+ restart->interval = gs.min_restart_interval;
+ else if ((restart->interval *= 2) > gs.max_restart_interval)
+ restart->interval = gs.max_restart_interval;
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("restart %s interval is now %ld",
+ restart->name,restart->interval);
+ }
+ return restart->pid;
+}
+
+#define SET_READ_HANDLER(DMN) \
+ (DMN)->t_read = thread_add_read(master,handle_read,(DMN),(DMN)->fd)
+
+#define SET_WAKEUP_DOWN(DMN) \
+ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_down,(DMN), \
+ FUZZY(gs.period))
+
+#define SET_WAKEUP_UNRESPONSIVE(DMN) \
+ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_unresponsive,(DMN), \
+ FUZZY(gs.period))
+
+#define SET_WAKEUP_ECHO(DMN) \
+ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_send_echo,(DMN), \
+ FUZZY(gs.period))
+
+static int
+wakeup_down(struct thread *t_wakeup)
+{
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+
+ dmn->t_wakeup = NULL;
+ if (try_connect(dmn) < 0)
+ SET_WAKEUP_DOWN(dmn);
+ if ((dmn->connect_tries > 1) && (dmn->state != DAEMON_UP))
+ try_restart(dmn);
+ return 0;
+}
+
+static int
+wakeup_init(struct thread *t_wakeup)
+{
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+
+ dmn->t_wakeup = NULL;
+ if (try_connect(dmn) < 0)
+ {
+ SET_WAKEUP_DOWN(dmn);
+ zlog_err("%s state -> down : initial connection attempt failed",
+ dmn->name);
+ dmn->state = DAEMON_DOWN;
+ }
+ return 0;
+}
+
+static void
+daemon_down(struct daemon *dmn, const char *why)
+{
+ if (IS_UP(dmn) || (dmn->state == DAEMON_INIT))
+ zlog_err("%s state -> down : %s",dmn->name,why);
+ else if (gs.loglevel > LOG_DEBUG)
+ zlog_debug("%s still down : %s",dmn->name,why);
+ if (IS_UP(dmn))
+ gs.numdown++;
+ dmn->state = DAEMON_DOWN;
+ if (dmn->fd >= 0)
+ {
+ close(dmn->fd);
+ dmn->fd = -1;
+ }
+ THREAD_OFF(dmn->t_read);
+ THREAD_OFF(dmn->t_write);
+ THREAD_OFF(dmn->t_wakeup);
+ if (try_connect(dmn) < 0)
+ SET_WAKEUP_DOWN(dmn);
+ phase_check();
+}
+
+static int
+handle_read(struct thread *t_read)
+{
+ struct daemon *dmn = THREAD_ARG(t_read);
+ static const char resp[sizeof(PING_TOKEN)+4] = PING_TOKEN "\n";
+ char buf[sizeof(resp)+100];
+ ssize_t rc;
+ struct timeval delay;
+
+ dmn->t_read = NULL;
+ if ((rc = read(dmn->fd,buf,sizeof(buf))) < 0)
+ {
+ char why[100];
+
+ if (ERRNO_IO_RETRY(errno))
+ {
+ /* Pretend it never happened. */
+ SET_READ_HANDLER(dmn);
+ return 0;
+ }
+ snprintf(why,sizeof(why),"unexpected read error: %s",
+ safe_strerror(errno));
+ daemon_down(dmn,why);
+ return 0;
+ }
+ if (rc == 0)
+ {
+ daemon_down(dmn,"read returned EOF");
+ return 0;
+ }
+ if (!dmn->echo_sent.tv_sec)
+ {
+ char why[sizeof(buf)+100];
+ snprintf(why,sizeof(why),"unexpected read returns %d bytes: %.*s",
+ (int)rc,(int)rc,buf);
+ daemon_down(dmn,why);
+ return 0;
+ }
+
+ /* We are expecting an echo response: is there any chance that the
+ response would not be returned entirely in the first read? That
+ seems inconceivable... */
+ if ((rc != sizeof(resp)) || memcmp(buf,resp,sizeof(resp)))
+ {
+ char why[100+sizeof(buf)];
+ snprintf(why,sizeof(why),"read returned bad echo response of %d bytes "
+ "(expecting %u): %.*s",
+ (int)rc,(u_int)sizeof(resp),(int)rc,buf);
+ daemon_down(dmn,why);
+ return 0;
+ }
+
+ time_elapsed(&delay,&dmn->echo_sent);
+ dmn->echo_sent.tv_sec = 0;
+ if (dmn->state == DAEMON_UNRESPONSIVE)
+ {
+ if (delay.tv_sec < gs.timeout)
+ {
+ dmn->state = DAEMON_UP;
+ zlog_warn("%s state -> up : echo response received after %ld.%06ld "
+ "seconds", dmn->name,
+ (long)delay.tv_sec, (long)delay.tv_usec);
+ }
+ else
+ zlog_warn("%s: slow echo response finally received after %ld.%06ld "
+ "seconds", dmn->name,
+ (long)delay.tv_sec, (long)delay.tv_usec);
+ }
+ else if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("%s: echo response received after %ld.%06ld seconds",
+ dmn->name, (long)delay.tv_sec, (long)delay.tv_usec);
+
+ SET_READ_HANDLER(dmn);
+ if (dmn->t_wakeup)
+ thread_cancel(dmn->t_wakeup);
+ SET_WAKEUP_ECHO(dmn);
+
+ return 0;
+}
+
+/*
+ * Wait till we notice that all daemons are ready before
+ * we send we are ready to systemd
+ */
+static void
+daemon_send_ready (void)
+{
+ static int sent = 0;
+ if (!sent && gs.numdown == 0)
+ {
+#if defined (HAVE_CUMULUS)
+ FILE *fp;
+
+ fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w");
+ fclose(fp);
+#endif
+ zlog_notice ("Watchfrr: Notifying Systemd we are up and running");
+ systemd_send_started(master, 0);
+ sent = 1;
+ }
+}
+
+static void
+daemon_up(struct daemon *dmn, const char *why)
+{
+ dmn->state = DAEMON_UP;
+ gs.numdown--;
+ dmn->connect_tries = 0;
+ zlog_notice("%s state -> up : %s",dmn->name,why);
+ daemon_send_ready();
+ if (gs.do_ping)
+ SET_WAKEUP_ECHO(dmn);
+ phase_check();
+}
+
+static int
+check_connect(struct thread *t_write)
+{
+ struct daemon *dmn = THREAD_ARG(t_write);
+ int sockerr;
+ socklen_t reslen = sizeof(sockerr);
+
+ dmn->t_write = NULL;
+ if (getsockopt(dmn->fd,SOL_SOCKET,SO_ERROR,(char *)&sockerr,&reslen) < 0)
+ {
+ zlog_warn("%s: check_connect: getsockopt failed: %s",
+ dmn->name,safe_strerror(errno));
+ daemon_down(dmn,"getsockopt failed checking connection success");
+ return 0;
+ }
+ if ((reslen == sizeof(sockerr)) && sockerr)
+ {
+ char why[100];
+ snprintf(why,sizeof(why),
+ "getsockopt reports that connection attempt failed: %s",
+ safe_strerror(sockerr));
+ daemon_down(dmn,why);
+ return 0;
+ }
+
+ daemon_up(dmn,"delayed connect succeeded");
+ return 0;
+}
+
+static int
+wakeup_connect_hanging(struct thread *t_wakeup)
+{
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+ char why[100];
+
+ dmn->t_wakeup = NULL;
+ snprintf(why,sizeof(why),"connection attempt timed out after %ld seconds",
+ gs.timeout);
+ daemon_down(dmn,why);
+ return 0;
+}
+
+/* Making connection to protocol daemon. */
+static int
+try_connect(struct daemon *dmn)
+{
+ int sock;
+ struct sockaddr_un addr;
+ socklen_t len;
+
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("%s: attempting to connect",dmn->name);
+ dmn->connect_tries++;
+
+ memset (&addr, 0, sizeof (struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty",
+ gs.vtydir,dmn->name);
+#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ len = addr.sun_len = SUN_LEN(&addr);
+#else
+ len = sizeof (addr.sun_family) + strlen (addr.sun_path);
+#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
+
+ /* Quick check to see if we might succeed before we go to the trouble
+ of creating a socket. */
+ if (access(addr.sun_path, W_OK) < 0)
+ {
+ if (errno != ENOENT)
+ zlog_err("%s: access to socket %s denied: %s",
+ dmn->name,addr.sun_path,safe_strerror(errno));
+ return -1;
+ }
+
+ if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ zlog_err("%s(%s): cannot make socket: %s",
+ __func__,addr.sun_path, safe_strerror(errno));
+ return -1;
+ }
+
+ if (set_nonblocking(sock) < 0 || set_cloexec(sock) < 0)
+ {
+ zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed",
+ __func__, addr.sun_path, sock);
+ close(sock);
+ return -1;
+ }
+
+ if (connect (sock, (struct sockaddr *) &addr, len) < 0)
+ {
+ if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK))
+ {
+ if (gs.loglevel > LOG_DEBUG)
+ zlog_debug("%s(%s): connect failed: %s",
+ __func__,addr.sun_path, safe_strerror(errno));
+ close (sock);
+ return -1;
+ }
+ if (gs.loglevel > LOG_DEBUG)
+ zlog_debug("%s: connection in progress",dmn->name);
+ dmn->state = DAEMON_CONNECTING;
+ dmn->fd = sock;
+ dmn->t_write = thread_add_write(master,check_connect,dmn,dmn->fd);
+ dmn->t_wakeup = thread_add_timer(master,wakeup_connect_hanging,dmn,
+ gs.timeout);
+ SET_READ_HANDLER(dmn);
+ return 0;
+ }
+
+ dmn->fd = sock;
+ SET_READ_HANDLER(dmn);
+ daemon_up(dmn,"connect succeeded");
+ return 1;
+}
+
+static int
+phase_hanging(struct thread *t_hanging)
+{
+ gs.t_phase_hanging = NULL;
+ zlog_err("Phase [%s] hanging for %ld seconds, aborting phased restart",
+ phase_str[gs.phase],PHASE_TIMEOUT);
+ gs.phase = PHASE_NONE;
+ return 0;
+}
+
+static void
+set_phase(restart_phase_t new_phase)
+{
+ gs.phase = new_phase;
+ if (gs.t_phase_hanging)
+ thread_cancel(gs.t_phase_hanging);
+ gs.t_phase_hanging = thread_add_timer(master,phase_hanging,NULL,
+ PHASE_TIMEOUT);
+}
+
+static void
+phase_check(void)
+{
+ switch (gs.phase)
+ {
+ case PHASE_NONE:
+ break;
+ case PHASE_STOPS_PENDING:
+ if (gs.numpids)
+ break;
+ zlog_info("Phased restart: all routing daemon stop jobs have completed.");
+ set_phase(PHASE_WAITING_DOWN);
+ /*FALLTHRU*/
+ case PHASE_WAITING_DOWN:
+ if (gs.numdown+IS_UP(gs.special) < gs.numdaemons)
+ break;
+ zlog_info("Phased restart: all routing daemons now down.");
+ run_job(&gs.special->restart,"restart",gs.restart_command,1,1);
+ set_phase(PHASE_ZEBRA_RESTART_PENDING);
+ /*FALLTHRU*/
+ case PHASE_ZEBRA_RESTART_PENDING:
+ if (gs.special->restart.pid)
+ break;
+ zlog_info("Phased restart: %s restart job completed.",gs.special->name);
+ set_phase(PHASE_WAITING_ZEBRA_UP);
+ /*FALLTHRU*/
+ case PHASE_WAITING_ZEBRA_UP:
+ if (!IS_UP(gs.special))
+ break;
+ zlog_info("Phased restart: %s is now up.",gs.special->name);
+ {
+ struct daemon *dmn;
+ for (dmn = gs.daemons; dmn; dmn = dmn->next)
+ {
+ if (dmn != gs.special)
+ run_job(&dmn->restart,"start",gs.start_command,1,0);
+ }
+ }
+ gs.phase = PHASE_NONE;
+ THREAD_OFF(gs.t_phase_hanging);
+ zlog_notice("Phased global restart has completed.");
+ break;
+ }
+}
+
+static void
+try_restart(struct daemon *dmn)
+{
+ switch (gs.mode)
+ {
+ case MODE_MONITOR:
+ return;
+ case MODE_GLOBAL_RESTART:
+ run_job(&gs.restart,"restart",gs.restart_command,0,1);
+ break;
+ case MODE_SEPARATE_RESTART:
+ run_job(&dmn->restart,"restart",gs.restart_command,0,1);
+ break;
+ case MODE_PHASED_ZEBRA_RESTART:
+ if (dmn != gs.special)
+ {
+ if ((gs.special->state == DAEMON_UP) && (gs.phase == PHASE_NONE))
+ run_job(&dmn->restart,"restart",gs.restart_command,0,1);
+ else
+ zlog_debug("%s: postponing restart attempt because master %s daemon "
+ "not up [%s], or phased restart in progress",
+ dmn->name,gs.special->name,state_str[gs.special->state]);
+ break;
+ }
+ /*FALLTHRU*/
+ case MODE_PHASED_ALL_RESTART:
+ if ((gs.phase != PHASE_NONE) || gs.numpids)
+ {
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("postponing phased global restart: restart already in "
+ "progress [%s], or outstanding child processes [%d]",
+ phase_str[gs.phase],gs.numpids);
+ break;
+ }
+ /* Is it too soon for a restart? */
+ {
+ struct timeval delay;
+ if (time_elapsed(&delay,&gs.special->restart.time)->tv_sec <
+ gs.special->restart.interval)
+ {
+ if (gs.loglevel > LOG_DEBUG+1)
+ zlog_debug("postponing phased global restart: "
+ "elapsed time %ld < retry interval %ld",
+ (long)delay.tv_sec,gs.special->restart.interval);
+ break;
+ }
+ }
+ run_job(&gs.restart,"restart",gs.restart_command,0,1);
+ break;
+ default:
+ zlog_err("error: unknown restart mode %d",gs.mode);
+ break;
+ }
+}
+
+static int
+wakeup_unresponsive(struct thread *t_wakeup)
+{
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+
+ dmn->t_wakeup = NULL;
+ if (dmn->state != DAEMON_UNRESPONSIVE)
+ zlog_err("%s: no longer unresponsive (now %s), "
+ "wakeup should have been cancelled!",
+ dmn->name,state_str[dmn->state]);
+ else
+ {
+ SET_WAKEUP_UNRESPONSIVE(dmn);
+ try_restart(dmn);
+ }
+ return 0;
+}
+
+static int
+wakeup_no_answer(struct thread *t_wakeup)
+{
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+
+ dmn->t_wakeup = NULL;
+ dmn->state = DAEMON_UNRESPONSIVE;
+ zlog_err("%s state -> unresponsive : no response yet to ping "
+ "sent %ld seconds ago",dmn->name,gs.timeout);
+ if (gs.unresponsive_restart)
+ {
+ SET_WAKEUP_UNRESPONSIVE(dmn);
+ try_restart(dmn);
+ }
+ return 0;
+}
+
+static int
+wakeup_send_echo(struct thread *t_wakeup)
+{
+ static const char echocmd[] = "echo " PING_TOKEN;
+ ssize_t rc;
+ struct daemon *dmn = THREAD_ARG(t_wakeup);
+
+ dmn->t_wakeup = NULL;
+ if (((rc = write(dmn->fd,echocmd,sizeof(echocmd))) < 0) ||
+ ((size_t)rc != sizeof(echocmd)))
+ {
+ char why[100+sizeof(echocmd)];
+ snprintf(why,sizeof(why),"write '%s' returned %d instead of %u",
+ echocmd,(int)rc,(u_int)sizeof(echocmd));
+ daemon_down(dmn,why);
+ }
+ else
+ {
+ gettimeofday(&dmn->echo_sent,NULL);
+ dmn->t_wakeup = thread_add_timer(master,wakeup_no_answer,dmn,gs.timeout);
+ }
+ return 0;
+}
+
+static void
+sigint(void)
+{
+ zlog_notice("Terminating on signal");
+ systemd_send_stopping ();
+ exit(0);
+}
+
+static int
+valid_command(const char *cmd)
+{
+ char *p;
+
+ return ((p = strchr(cmd,'%')) != NULL) && (*(p+1) == 's') && !strchr(p+1,'%');
+}
+
+/* This is an ugly hack to circumvent problems with passing command-line
+ arguments that contain spaces. The fix is to use a configuration file. */
+static char *
+translate_blanks(const char *cmd, const char *blankstr)
+{
+ char *res;
+ char *p;
+ size_t bslen = strlen(blankstr);
+
+ if (!(res = strdup(cmd)))
+ {
+ perror("strdup");
+ exit(1);
+ }
+ while ((p = strstr(res,blankstr)) != NULL)
+ {
+ *p = ' ';
+ if (bslen != 1)
+ memmove(p+1,p+bslen,strlen(p+bslen)+1);
+ }
+ return res;
+}
+
+struct zebra_privs_t watchfrr_privs =
+{
+#ifdef VTY_GROUP
+ .vty_group = VTY_GROUP,
+#endif
+};
+
+int
+main(int argc, char **argv)
+{
+ const char *progname;
+ int opt;
+ int daemon_mode = 0;
+ const char *pidfile = DEFAULT_PIDFILE;
+ const char *special = "zebra";
+ const char *blankstr = NULL;
+ static struct quagga_signal_t my_signals[] =
+ {
+ {
+ .signal = SIGINT,
+ .handler = sigint,
+ },
+ {
+ .signal = SIGTERM,
+ .handler = sigint,
+ },
+ {
+ .signal = SIGCHLD,
+ .handler = sigchild,
+ },
+ };
+
+ if ((progname = strrchr (argv[0], '/')) != NULL)
+ progname++;
+ else
+ progname = argv[0];
+
+ gs.restart.name = "all";
+ while ((opt = getopt_long(argc, argv, "aAb:dek:l:m:M:i:p:r:R:S:s:t:T:zvh",
+ longopts, 0)) != EOF)
+ {
+ switch (opt)
+ {
+ case 0:
+ break;
+ case 'a':
+ if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART))
+ {
+ fputs("Ambiguous operating mode selected.\n",stderr);
+ return usage(progname,1);
+ }
+ gs.mode = MODE_PHASED_ZEBRA_RESTART;
+ break;
+ case 'A':
+ if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART))
+ {
+ fputs("Ambiguous operating mode selected.\n",stderr);
+ return usage(progname,1);
+ }
+ gs.mode = MODE_PHASED_ALL_RESTART;
+ break;
+ case 'b':
+ blankstr = optarg;
+ break;
+ case 'd':
+ daemon_mode = 1;
+ break;
+ case 'e':
+ gs.do_ping = 0;
+ break;
+ case 'k':
+ if (!valid_command(optarg))
+ {
+ fprintf(stderr,"Invalid kill command, must contain '%%s': %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ gs.stop_command = optarg;
+ break;
+ case 'l':
+ {
+ char garbage[3];
+ if ((sscanf(optarg,"%d%1s",&gs.loglevel,garbage) != 1) ||
+ (gs.loglevel < LOG_EMERG))
+ {
+ fprintf(stderr,"Invalid loglevel argument: %s\n",optarg);
+ return usage(progname,1);
+ }
+ }
+ break;
+ case 'm':
+ {
+ char garbage[3];
+ if ((sscanf(optarg,"%ld%1s",
+ &gs.min_restart_interval,garbage) != 1) ||
+ (gs.min_restart_interval < 0))
+ {
+ fprintf(stderr,"Invalid min_restart_interval argument: %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ }
+ break;
+ case 'M':
+ {
+ char garbage[3];
+ if ((sscanf(optarg,"%ld%1s",
+ &gs.max_restart_interval,garbage) != 1) ||
+ (gs.max_restart_interval < 0))
+ {
+ fprintf(stderr,"Invalid max_restart_interval argument: %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ }
+ break;
+ case 'i':
+ {
+ char garbage[3];
+ int period;
+ if ((sscanf(optarg,"%d%1s",&period,garbage) != 1) ||
+ (gs.period < 1))
+ {
+ fprintf(stderr,"Invalid interval argument: %s\n",optarg);
+ return usage(progname,1);
+ }
+ gs.period = 1000*period;
+ }
+ break;
+ case 'p':
+ pidfile = optarg;
+ break;
+ case 'r':
+ if ((gs.mode == MODE_GLOBAL_RESTART) ||
+ (gs.mode == MODE_SEPARATE_RESTART))
+ {
+ fputs("Ambiguous operating mode selected.\n",stderr);
+ return usage(progname,1);
+ }
+ if (!valid_command(optarg))
+ {
+ fprintf(stderr,
+ "Invalid restart command, must contain '%%s': %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ gs.restart_command = optarg;
+ if (gs.mode == MODE_MONITOR)
+ gs.mode = MODE_SEPARATE_RESTART;
+ break;
+ case 'R':
+ if (gs.mode != MODE_MONITOR)
+ {
+ fputs("Ambiguous operating mode selected.\n",stderr);
+ return usage(progname,1);
+ }
+ if (strchr(optarg,'%'))
+ {
+ fprintf(stderr,
+ "Invalid restart-all arg, must not contain '%%s': %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ gs.restart_command = optarg;
+ gs.mode = MODE_GLOBAL_RESTART;
+ break;
+ case 's':
+ if (!valid_command(optarg))
+ {
+ fprintf(stderr,"Invalid start command, must contain '%%s': %s\n",
+ optarg);
+ return usage(progname,1);
+ }
+ gs.start_command = optarg;
+ break;
+ case 'S':
+ gs.vtydir = optarg;
+ break;
+ case 't':
+ {
+ char garbage[3];
+ if ((sscanf(optarg,"%ld%1s",&gs.timeout,garbage) != 1) ||
+ (gs.timeout < 1))
+ {
+ fprintf(stderr,"Invalid timeout argument: %s\n",optarg);
+ return usage(progname,1);
+ }
+ }
+ break;
+ case 'T':
+ {
+ char garbage[3];
+ if ((sscanf(optarg,"%ld%1s",&gs.restart_timeout,garbage) != 1) ||
+ (gs.restart_timeout < 1))
+ {
+ fprintf(stderr,"Invalid restart timeout argument: %s\n",optarg);
+ return usage(progname,1);
+ }
+ }
+ break;
+ case 'z':
+ gs.unresponsive_restart = 1;
+ break;
+ case 'v':
+ printf ("%s version %s\n", progname, FRR_VERSION);
+ puts("Copyright 2004 Andrew J. Schorr");
+ return 0;
+ case 'h':
+ return usage(progname,0);
+ default:
+ fputs("Invalid option.\n",stderr);
+ return usage(progname,1);
+ }
+ }
+
+ if (gs.unresponsive_restart && (gs.mode == MODE_MONITOR))
+ {
+ fputs("Option -z requires a -r or -R restart option.\n",stderr);
+ return usage(progname,1);
+ }
+ switch (gs.mode)
+ {
+ case MODE_MONITOR:
+ if (gs.restart_command || gs.start_command || gs.stop_command)
+ {
+ fprintf(stderr,"No kill/(re)start commands needed for %s mode.\n",
+ mode_str[gs.mode]);
+ return usage(progname,1);
+ }
+ break;
+ case MODE_GLOBAL_RESTART:
+ case MODE_SEPARATE_RESTART:
+ if (!gs.restart_command || gs.start_command || gs.stop_command)
+ {
+ fprintf(stderr,"No start/kill commands needed in [%s] mode.\n",
+ mode_str[gs.mode]);
+ return usage(progname,1);
+ }
+ break;
+ case MODE_PHASED_ZEBRA_RESTART:
+ case MODE_PHASED_ALL_RESTART:
+ if (!gs.restart_command || !gs.start_command || !gs.stop_command)
+ {
+ fprintf(stderr,
+ "Need start, kill, and restart commands in [%s] mode.\n",
+ mode_str[gs.mode]);
+ return usage(progname,1);
+ }
+ break;
+ }
+
+ if (blankstr)
+ {
+ if (gs.restart_command)
+ gs.restart_command = translate_blanks(gs.restart_command,blankstr);
+ if (gs.start_command)
+ gs.start_command = translate_blanks(gs.start_command,blankstr);
+ if (gs.stop_command)
+ gs.stop_command = translate_blanks(gs.stop_command,blankstr);
+ }
+
+ gs.restart.interval = gs.min_restart_interval;
+
+ zprivs_init (&watchfrr_privs);
+
+ master = thread_master_create();
+ cmd_init(-1);
+ memory_init();
+ vty_init(master);
+ watchfrr_vty_init();
+ vty_serv_sock(NULL, 0, WATCHFRR_VTYSH_PATH);
+
+ signal_init (master, array_size(my_signals), my_signals);
+ srandom(time(NULL));
+
+ {
+ int i;
+ struct daemon *tail = NULL;
+
+ for (i = optind; i < argc; i++)
+ {
+ struct daemon *dmn;
+
+ if (!(dmn = (struct daemon *)calloc(1,sizeof(*dmn))))
+ {
+ fprintf(stderr,"calloc(1,%u) failed: %s\n",
+ (u_int)sizeof(*dmn), safe_strerror(errno));
+ return 1;
+ }
+ dmn->name = dmn->restart.name = argv[i];
+ dmn->state = DAEMON_INIT;
+ gs.numdaemons++;
+ gs.numdown++;
+ dmn->fd = -1;
+ dmn->t_wakeup = thread_add_timer_msec(master,wakeup_init,dmn,
+ 100+(random() % 900));
+ dmn->restart.interval = gs.min_restart_interval;
+ if (tail)
+ tail->next = dmn;
+ else
+ gs.daemons = dmn;
+ tail = dmn;
+
+ if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) ||
+ (gs.mode == MODE_PHASED_ALL_RESTART)) &&
+ !strcmp(dmn->name,special))
+ gs.special = dmn;
+ }
+ }
+ if (!gs.daemons)
+ {
+ fputs("Must specify one or more daemons to monitor.\n",stderr);
+ return usage(progname,1);
+ }
+ if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) ||
+ (gs.mode == MODE_PHASED_ALL_RESTART)) && !gs.special)
+ {
+ fprintf(stderr,"In mode [%s], but cannot find master daemon %s\n",
+ mode_str[gs.mode],special);
+ return usage(progname,1);
+ }
+
+ zlog_default = openzlog(progname, ZLOG_WATCHFRR, 0,
+ LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+ zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
+ if (daemon_mode)
+ {
+ zlog_set_level(NULL, ZLOG_DEST_SYSLOG, MIN(gs.loglevel,LOG_DEBUG));
+ if (daemon (0, 0) < 0)
+ {
+ fprintf(stderr, "Watchfrr daemon failed: %s", strerror(errno));
+ exit (1);
+ }
+ }
+ else
+ zlog_set_level(NULL, ZLOG_DEST_STDOUT, MIN(gs.loglevel,LOG_DEBUG));
+
+ /* Make sure we're not already running. */
+ pid_output (pidfile);
+
+ /* Announce which daemons are being monitored. */
+ {
+ struct daemon *dmn;
+ size_t len = 0;
+
+ for (dmn = gs.daemons; dmn; dmn = dmn->next)
+ len += strlen(dmn->name)+1;
+
+ {
+ char buf[len+1];
+ char *p = buf;
+
+ for (dmn = gs.daemons; dmn; dmn = dmn->next)
+ {
+ if (p != buf)
+ *p++ = ' ';
+ strcpy(p,dmn->name);
+ p += strlen(p);
+ }
+ zlog_notice("%s %s watching [%s], mode [%s]",
+ progname, FRR_VERSION, buf, mode_str[gs.mode]);
+ }
+ }
+
+ {
+ struct thread thread;
+
+ while (thread_fetch (master, &thread))
+ thread_call (&thread);
+ }
+
+ systemd_send_stopping ();
+ /* Not reached. */
+ return 0;
+}
--- /dev/null
+/*
+ Common definitions for watchfrr API socket.
+
+ Copyright (C) 2016 David Lamparter for NetDEF, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef FRR_WATCHFRR_H
+#define FRR_WATCHFRR_H
+
+extern void watchfrr_vty_init(void);
+
+extern pid_t integrated_write_pid;
+extern void integrated_write_sigchld(int status);
+
+#endif /* FRR_WATCHFRR_H */
--- /dev/null
+/*
+ watchfrr CLI functions.
+
+ Copyright (C) 2016 David Lamparter for NetDEF, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <zebra.h>
+#include <sys/wait.h>
+
+#include "memory.h"
+#include "log.h"
+#include "vty.h"
+#include "command.h"
+
+#include "watchfrr.h"
+
+pid_t integrated_write_pid;
+static int integrated_result_fd;
+
+DEFUN (config_write_integrated,
+ config_write_integrated_cmd,
+ "write integrated",
+ "Write running configuration to memory, network, or terminal\n"
+ "Write integrated all-daemon Frr.conf file\n")
+{
+ pid_t child;
+ sigset_t oldmask, sigmask;
+
+ if (integrated_write_pid != -1) {
+ vty_out(vty, "%% configuration write already in progress.%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ fflush(stdout);
+ fflush(stderr);
+
+ /* need to temporarily block SIGCHLD because it could arrive between
+ * fork() call and setting the integrated_write_pid variable. This
+ * would mean the completion call gets lost and this hangs forever.
+ */
+ sigemptyset(&oldmask);
+ sigemptyset(&sigmask);
+ sigaddset(&sigmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sigmask, &oldmask);
+
+ child = fork();
+ if (child == -1) {
+ vty_out(vty, "%% configuration write fork() failed: %s.%s",
+ safe_strerror(errno), VTY_NEWLINE);
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ return CMD_WARNING;
+ }
+ if (child != 0) {
+ /* note: the VTY won't write a command return value to vtysh; the
+ * session temporarily enters an intentional "hang" state. This is
+ * to make sure latency in vtysh doing the config write (several
+ * seconds is not rare to see) does not interfere with watchfrr's
+ * supervisor job.
+ *
+ * The fd is duplicated here so we don't need to hold a vty pointer
+ * (which could become invalid in the meantime).
+ */
+ integrated_write_pid = child;
+ integrated_result_fd = dup(vty->wfd);
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ return CMD_SUSPEND;
+ }
+
+ /* redirect stdout/stderr to vty session. Note vty->wfd is marked
+ * CLOEXEC, but dup2 will clear that flag. */
+ dup2(vty->wfd, 1);
+ dup2(vty->wfd, 2);
+
+ /* don't allow the user to pass parameters, we're root here!
+ * should probably harden vtysh at some point too... */
+ execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL);
+
+ /* unbuffered write; we just messed with stdout... */
+ char msg[512];
+ snprintf(msg, sizeof(msg), "error executing %s: %s\n",
+ VTYSH_BIN_PATH, safe_strerror(errno));
+ write(1, msg, strlen(msg));
+ exit(1);
+}
+
+void integrated_write_sigchld(int status)
+{
+ uint8_t reply[4] = { 0, 0, 0, CMD_WARNING };
+
+ if (WIFEXITED(status)) {
+ zlog_info("configuration write completed with exit code %d",
+ WEXITSTATUS(status));
+ reply[3] = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ zlog_warn("configuration write terminated by signal %d",
+ WTERMSIG(status));
+ } else {
+ zlog_warn("configuration write terminated");
+ }
+
+ if (reply[3] != CMD_SUCCESS) {
+ /* failure might be silent in vtysh without this */
+ static const char msg[] = "% Configuration write failed.\n";
+ write(integrated_result_fd, msg, strlen(msg));
+ }
+
+ /* don't care about failures here, if the connection is broken the
+ * return value will just be lost. */
+ write(integrated_result_fd, reply, sizeof(reply));
+ close(integrated_result_fd);
+
+ integrated_write_pid = -1;
+}
+
+void watchfrr_vty_init(void)
+{
+ integrated_write_pid = -1;
+ install_element(ENABLE_NODE, &config_write_integrated_cmd);
+}
+++ /dev/null
-Makefile
-Makefile.in
-*.o
-watchquagga
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-
+++ /dev/null
-## Process this file with Automake to create Makefile.in
-
-AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
-DEFS = @DEFS@ -DSTATEDIR=\"$(localstatedir)/\"
-
-AM_CFLAGS = $(WERROR)
-
-sbin_PROGRAMS = watchquagga
-
-noinst_HEADERS = watchquagga.h
-
-watchquagga_SOURCES = watchquagga.c watchquagga_vty.c
-watchquagga_LDADD = ../lib/libzebra.la @LIBCAP@
+++ /dev/null
-/*
- Monitor status of quagga daemons and restart if necessary.
-
- Copyright (C) 2004 Andrew J. Schorr
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <zebra.h>
-#include <thread.h>
-#include <log.h>
-#include <network.h>
-#include <sigevent.h>
-#include <lib/version.h>
-#include "command.h"
-#include "memory_vty.h"
-
-#include <getopt.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <memory.h>
-#include <systemd.h>
-
-#include "watchquagga.h"
-
-#ifndef MIN
-#define MIN(X,Y) (((X) <= (Y)) ? (X) : (Y))
-#endif
-
-/* Macros to help randomize timers. */
-#define JITTER(X) ((random() % ((X)+1))-((X)/2))
-#define FUZZY(X) ((X)+JITTER((X)/20))
-
-#define DEFAULT_PERIOD 5
-#define DEFAULT_TIMEOUT 10
-#define DEFAULT_RESTART_TIMEOUT 20
-#define DEFAULT_LOGLEVEL LOG_INFO
-#define DEFAULT_MIN_RESTART 60
-#define DEFAULT_MAX_RESTART 600
-#ifdef PATH_WATCHQUAGGA_PID
-#define DEFAULT_PIDFILE PATH_WATCHQUAGGA_PID
-#else
-#define DEFAULT_PIDFILE STATEDIR "/watchquagga.pid"
-#endif
-#ifdef DAEMON_VTY_DIR
-#define VTYDIR DAEMON_VTY_DIR
-#else
-#define VTYDIR STATEDIR
-#endif
-
-#define PING_TOKEN "PING"
-
-/* Needs to be global, referenced somewhere inside libzebra. */
-struct thread_master *master;
-
-typedef enum
-{
- MODE_MONITOR = 0,
- MODE_GLOBAL_RESTART,
- MODE_SEPARATE_RESTART,
- MODE_PHASED_ZEBRA_RESTART,
- MODE_PHASED_ALL_RESTART
-} watch_mode_t;
-
-static const char *mode_str[] =
-{
- "monitor",
- "global restart",
- "individual daemon restart",
- "phased zebra restart",
- "phased global restart for any failure",
-};
-
-typedef enum
-{
- PHASE_NONE = 0,
- PHASE_STOPS_PENDING,
- PHASE_WAITING_DOWN,
- PHASE_ZEBRA_RESTART_PENDING,
- PHASE_WAITING_ZEBRA_UP
-} restart_phase_t;
-
-static const char *phase_str[] =
-{
- "None",
- "Stop jobs running",
- "Waiting for other daemons to come down",
- "Zebra restart job running",
- "Waiting for zebra to come up",
- "Start jobs running",
-};
-
-#define PHASE_TIMEOUT (3*gs.restart_timeout)
-
-struct restart_info
-{
- const char *name;
- const char *what;
- pid_t pid;
- struct timeval time;
- long interval;
- struct thread *t_kill;
- int kills;
-};
-
-static struct global_state
-{
- watch_mode_t mode;
- restart_phase_t phase;
- struct thread *t_phase_hanging;
- const char *vtydir;
- long period;
- long timeout;
- long restart_timeout;
- long min_restart_interval;
- long max_restart_interval;
- int do_ping;
- struct daemon *daemons;
- const char *restart_command;
- const char *start_command;
- const char *stop_command;
- struct restart_info restart;
- int unresponsive_restart;
- int loglevel;
- struct daemon *special; /* points to zebra when doing phased restart */
- int numdaemons;
- int numpids;
- int numdown; /* # of daemons that are not UP or UNRESPONSIVE */
-} gs = {
- .mode = MODE_MONITOR,
- .phase = PHASE_NONE,
- .vtydir = VTYDIR,
- .period = 1000*DEFAULT_PERIOD,
- .timeout = DEFAULT_TIMEOUT,
- .restart_timeout = DEFAULT_RESTART_TIMEOUT,
- .loglevel = DEFAULT_LOGLEVEL,
- .min_restart_interval = DEFAULT_MIN_RESTART,
- .max_restart_interval = DEFAULT_MAX_RESTART,
- .do_ping = 1,
-};
-
-typedef enum
-{
- DAEMON_INIT,
- DAEMON_DOWN,
- DAEMON_CONNECTING,
- DAEMON_UP,
- DAEMON_UNRESPONSIVE
-} daemon_state_t;
-
-#define IS_UP(DMN) \
- (((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE))
-
-static const char *state_str[] =
-{
- "Init",
- "Down",
- "Connecting",
- "Up",
- "Unresponsive",
-};
-
-struct daemon {
- const char *name;
- daemon_state_t state;
- int fd;
- struct timeval echo_sent;
- u_int connect_tries;
- struct thread *t_wakeup;
- struct thread *t_read;
- struct thread *t_write;
- struct daemon *next;
- struct restart_info restart;
-};
-
-static const struct option longopts[] =
-{
- { "daemon", no_argument, NULL, 'd'},
- { "statedir", required_argument, NULL, 'S'},
- { "no-echo", no_argument, NULL, 'e'},
- { "loglevel", required_argument, NULL, 'l'},
- { "interval", required_argument, NULL, 'i'},
- { "timeout", required_argument, NULL, 't'},
- { "restart-timeout", required_argument, NULL, 'T'},
- { "restart", required_argument, NULL, 'r'},
- { "start-command", required_argument, NULL, 's'},
- { "kill-command", required_argument, NULL, 'k'},
- { "restart-all", required_argument, NULL, 'R'},
- { "all-restart", no_argument, NULL, 'a'},
- { "always-all-restart", no_argument, NULL, 'A'},
- { "unresponsive-restart", no_argument, NULL, 'z'},
- { "min-restart-interval", required_argument, NULL, 'm'},
- { "max-restart-interval", required_argument, NULL, 'M'},
- { "pid-file", required_argument, NULL, 'p'},
- { "blank-string", required_argument, NULL, 'b'},
- { "help", no_argument, NULL, 'h'},
- { "version", no_argument, NULL, 'v'},
- { NULL, 0, NULL, 0 }
-};
-
-static int try_connect(struct daemon *dmn);
-static int wakeup_send_echo(struct thread *t_wakeup);
-static void try_restart(struct daemon *dmn);
-static void phase_check(void);
-
-static int
-usage(const char *progname, int status)
-{
- if (status != 0)
- fprintf(stderr, "Try `%s --help' for more information.\n", progname);
- else
- {
- printf("Usage : %s [OPTION...] <daemon name> ...\n\n\
-Watchdog program to monitor status of quagga daemons and try to restart\n\
-them if they are down or unresponsive. It determines whether a daemon is\n\
-up based on whether it can connect to the daemon's vty unix stream socket.\n\
-It then repeatedly sends echo commands over that socket to determine whether\n\
-the daemon is responsive. If the daemon crashes, we will receive an EOF\n\
-on the socket connection and know immediately that the daemon is down.\n\n\
-The daemons to be monitored should be listed on the command line.\n\n\
-This program can run in one of 5 modes:\n\n\
-0. Mode: %s.\n\
- Just monitor and report on status changes. Example:\n\
- %s -d zebra ospfd bgpd\n\n\
-1. Mode: %s.\n\
- Whenever any daemon hangs or crashes, use the given command to restart\n\
- them all. Example:\n\
- %s -dz \\\n\
- -R '/sbin/service zebra restart; /sbin/service ospfd restart' \\\n\
- zebra ospfd\n\n\
-2. Mode: %s.\n\
- When any single daemon hangs or crashes, restart only the daemon that's\n\
- in trouble using the supplied restart command. Example:\n\
- %s -dz -r '/sbin/service %%s restart' zebra ospfd bgpd\n\n\
-3. Mode: %s.\n\
- The same as the previous mode, except that there is special treatment when\n\
- the zebra daemon is in trouble. In that case, a phased restart approach\n\
- is used: 1. stop all other daemons; 2. restart zebra; 3. start the other\n\
- daemons. Example:\n\
- %s -adz -r '/sbin/service %%s restart' \\\n\
- -s '/sbin/service %%s start' \\\n\
- -k '/sbin/service %%s stop' zebra ospfd bgpd\n\n\
-4. Mode: %s.\n\
- This is the same as the previous mode, except that the phased restart\n\
- procedure is used whenever any of the daemons hangs or crashes. Example:\n\
- %s -Adz -r '/sbin/service %%s restart' \\\n\
- -s '/sbin/service %%s start' \\\n\
- -k '/sbin/service %%s stop' zebra ospfd bgpd\n\n\
-As of this writing, it is believed that mode 2 [%s]\n\
-is not safe, and mode 3 [%s] may not be safe with some of the\n\
-routing daemons.\n\n\
-In order to avoid attempting to restart the daemons in a fast loop,\n\
-the -m and -M options allow you to control the minimum delay between\n\
-restart commands. The minimum restart delay is recalculated each time\n\
-a restart is attempted: if the time since the last restart attempt exceeds\n\
-twice the -M value, then the restart delay is set to the -m value.\n\
-Otherwise, the interval is doubled (but capped at the -M value).\n\n",
- progname,mode_str[0],progname,mode_str[1],progname,mode_str[2],
- progname,mode_str[3],progname,mode_str[4],progname,mode_str[2],
- mode_str[3]);
-
- printf("Options:\n\
--d, --daemon Run in daemon mode. In this mode, error messages are sent\n\
- to syslog instead of stdout.\n\
--S, --statedir Set the vty socket directory (default is %s)\n\
--e, --no-echo Do not ping the daemons to test responsiveness (this\n\
- option is necessary if the daemons do not support the\n\
- echo command)\n\
--l, --loglevel Set the logging level (default is %d).\n\
- The value should range from %d (LOG_EMERG) to %d (LOG_DEBUG),\n\
- but it can be set higher than %d if extra-verbose debugging\n\
- messages are desired.\n\
--m, --min-restart-interval\n\
- Set the minimum seconds to wait between invocations of daemon\n\
- restart commands (default is %d).\n\
--M, --max-restart-interval\n\
- Set the maximum seconds to wait between invocations of daemon\n\
- restart commands (default is %d).\n\
--i, --interval Set the status polling interval in seconds (default is %d)\n\
--t, --timeout Set the unresponsiveness timeout in seconds (default is %d)\n\
--T, --restart-timeout\n\
- Set the restart (kill) timeout in seconds (default is %d).\n\
- If any background jobs are still running after this much\n\
- time has elapsed, they will be killed.\n\
--r, --restart Supply a Bourne shell command to use to restart a single\n\
- daemon. The command string should include '%%s' where the\n\
- name of the daemon should be substituted.\n\
- Note that -r and -R are incompatible.\n\
--s, --start-command\n\
- Supply a Bourne shell to command to use to start a single\n\
- daemon. The command string should include '%%s' where the\n\
- name of the daemon should be substituted.\n\
--k, --kill-command\n\
- Supply a Bourne shell to command to use to stop a single\n\
- daemon. The command string should include '%%s' where the\n\
- name of the daemon should be substituted.\n\
--R, --restart-all\n\
- When one or more daemons is down, try to restart everything\n\
- using the Bourne shell command supplied as the argument.\n\
- Note that -r and -R are incompatible.\n\
--z, --unresponsive-restart\n\
- When a daemon is unresponsive, treat it as being down for\n\
- restart purposes.\n\
--a, --all-restart\n\
- When zebra hangs or crashes, restart all daemons using\n\
- this phased approach: 1. stop all other daemons; 2. restart\n\
- zebra; 3. start other daemons. Requires -r, -s, and -k.\n\
--A, --always-all-restart\n\
- When any daemon (not just zebra) hangs or crashes, use the\n\
- same phased restart mechanism described above for -a.\n\
- Requires -r, -s, and -k.\n\
--p, --pid-file Set process identifier file name\n\
- (default is %s).\n\
--b, --blank-string\n\
- When the supplied argument string is found in any of the\n\
- various shell command arguments (-r, -s, -k, or -R), replace\n\
- it with a space. This is an ugly hack to circumvent problems\n\
- passing command-line arguments with embedded spaces.\n\
--v, --version Print program version\n\
--h, --help Display this help and exit\n",
- VTYDIR,DEFAULT_LOGLEVEL,LOG_EMERG,LOG_DEBUG,LOG_DEBUG,
- DEFAULT_MIN_RESTART,DEFAULT_MAX_RESTART,
- DEFAULT_PERIOD,DEFAULT_TIMEOUT,DEFAULT_RESTART_TIMEOUT,
- DEFAULT_PIDFILE);
- }
-
- return status;
-}
-
-static pid_t
-run_background(char *shell_cmd)
-{
- pid_t child;
-
- switch (child = fork())
- {
- case -1:
- zlog_err("fork failed, cannot run command [%s]: %s",
- shell_cmd,safe_strerror(errno));
- return -1;
- case 0:
- /* Child process. */
- /* Use separate process group so child processes can be killed easily. */
- if (setpgid(0,0) < 0)
- zlog_warn("warning: setpgid(0,0) failed: %s",safe_strerror(errno));
- {
- char shell[] = "sh";
- char dashc[] = "-c";
- char * const argv[4] = { shell, dashc, shell_cmd, NULL};
- execv("/bin/sh", argv);
- zlog_err("execv(/bin/sh -c '%s') failed: %s",
- shell_cmd,safe_strerror(errno));
- _exit(127);
- }
- default:
- /* Parent process: we will reap the child later. */
- zlog_err("Forked background command [pid %d]: %s",(int)child,shell_cmd);
- return child;
- }
-}
-
-static struct timeval *
-time_elapsed(struct timeval *result, const struct timeval *start_time)
-{
- gettimeofday(result,NULL);
- result->tv_sec -= start_time->tv_sec;
- result->tv_usec -= start_time->tv_usec;
- while (result->tv_usec < 0)
- {
- result->tv_usec += 1000000L;
- result->tv_sec--;
- }
- return result;
-}
-
-static int
-restart_kill(struct thread *t_kill)
-{
- struct restart_info *restart = THREAD_ARG(t_kill);
- struct timeval delay;
-
- time_elapsed(&delay,&restart->time);
- zlog_warn("Warning: %s %s child process %d still running after "
- "%ld seconds, sending signal %d",
- restart->what,restart->name,(int)restart->pid, (long)delay.tv_sec,
- (restart->kills ? SIGKILL : SIGTERM));
- kill(-restart->pid,(restart->kills ? SIGKILL : SIGTERM));
- restart->kills++;
- restart->t_kill = thread_add_timer(master,restart_kill,restart,
- gs.restart_timeout);
- return 0;
-}
-
-static struct restart_info *
-find_child(pid_t child)
-{
- if (gs.mode == MODE_GLOBAL_RESTART)
- {
- if (gs.restart.pid == child)
- return &gs.restart;
- }
- else
- {
- struct daemon *dmn;
- for (dmn = gs.daemons; dmn; dmn = dmn->next)
- {
- if (dmn->restart.pid == child)
- return &dmn->restart;
- }
- }
- return NULL;
-}
-
-static void
-sigchild(void)
-{
- pid_t child;
- int status;
- const char *name;
- const char *what;
- struct restart_info *restart;
-
- switch (child = waitpid(-1,&status,WNOHANG))
- {
- case -1:
- zlog_err("waitpid failed: %s",safe_strerror(errno));
- return;
- case 0:
- zlog_warn("SIGCHLD received, but waitpid did not reap a child");
- return;
- }
-
- if (child == integrated_write_pid)
- {
- integrated_write_sigchld(status);
- return;
- }
-
- if ((restart = find_child(child)) != NULL)
- {
- name = restart->name;
- what = restart->what;
- restart->pid = 0;
- gs.numpids--;
- thread_cancel(restart->t_kill);
- restart->t_kill = NULL;
- /* Update restart time to reflect the time the command completed. */
- gettimeofday(&restart->time,NULL);
- }
- else
- {
- zlog_err("waitpid returned status for an unknown child process %d",
- (int)child);
- name = "(unknown)";
- what = "background";
- }
- if (WIFSTOPPED(status))
- zlog_warn("warning: %s %s process %d is stopped",
- what,name,(int)child);
- else if (WIFSIGNALED(status))
- zlog_warn("%s %s process %d terminated due to signal %d",
- what,name,(int)child,WTERMSIG(status));
- else if (WIFEXITED(status))
- {
- if (WEXITSTATUS(status) != 0)
- zlog_warn("%s %s process %d exited with non-zero status %d",
- what,name,(int)child,WEXITSTATUS(status));
- else
- zlog_debug("%s %s process %d exited normally",what,name,(int)child);
- }
- else
- zlog_err("cannot interpret %s %s process %d wait status 0x%x",
- what,name,(int)child,status);
- phase_check();
-}
-
-static int
-run_job(struct restart_info *restart, const char *cmdtype, const char *command,
- int force, int update_interval)
-{
- struct timeval delay;
-
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("attempting to %s %s",cmdtype,restart->name);
-
- if (restart->pid)
- {
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("cannot %s %s, previous pid %d still running",
- cmdtype,restart->name,(int)restart->pid);
- return -1;
- }
-
- /* Note: time_elapsed test must come before the force test, since we need
- to make sure that delay is initialized for use below in updating the
- restart interval. */
- if ((time_elapsed(&delay,&restart->time)->tv_sec < restart->interval) &&
- !force)
- {
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("postponing %s %s: "
- "elapsed time %ld < retry interval %ld",
- cmdtype,restart->name,(long)delay.tv_sec,restart->interval);
- return -1;
- }
-
- gettimeofday(&restart->time,NULL);
- restart->kills = 0;
- {
- char cmd[strlen(command)+strlen(restart->name)+1];
- snprintf(cmd,sizeof(cmd),command,restart->name);
- if ((restart->pid = run_background(cmd)) > 0)
- {
- restart->t_kill = thread_add_timer(master,restart_kill,restart,
- gs.restart_timeout);
- restart->what = cmdtype;
- gs.numpids++;
- }
- else
- restart->pid = 0;
- }
-
- /* Calculate the new restart interval. */
- if (update_interval)
- {
- if (delay.tv_sec > 2*gs.max_restart_interval)
- restart->interval = gs.min_restart_interval;
- else if ((restart->interval *= 2) > gs.max_restart_interval)
- restart->interval = gs.max_restart_interval;
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("restart %s interval is now %ld",
- restart->name,restart->interval);
- }
- return restart->pid;
-}
-
-#define SET_READ_HANDLER(DMN) \
- (DMN)->t_read = thread_add_read(master,handle_read,(DMN),(DMN)->fd)
-
-#define SET_WAKEUP_DOWN(DMN) \
- (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_down,(DMN), \
- FUZZY(gs.period))
-
-#define SET_WAKEUP_UNRESPONSIVE(DMN) \
- (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_unresponsive,(DMN), \
- FUZZY(gs.period))
-
-#define SET_WAKEUP_ECHO(DMN) \
- (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_send_echo,(DMN), \
- FUZZY(gs.period))
-
-static int
-wakeup_down(struct thread *t_wakeup)
-{
- struct daemon *dmn = THREAD_ARG(t_wakeup);
-
- dmn->t_wakeup = NULL;
- if (try_connect(dmn) < 0)
- SET_WAKEUP_DOWN(dmn);
- if ((dmn->connect_tries > 1) && (dmn->state != DAEMON_UP))
- try_restart(dmn);
- return 0;
-}
-
-static int
-wakeup_init(struct thread *t_wakeup)
-{
- struct daemon *dmn = THREAD_ARG(t_wakeup);
-
- dmn->t_wakeup = NULL;
- if (try_connect(dmn) < 0)
- {
- SET_WAKEUP_DOWN(dmn);
- zlog_err("%s state -> down : initial connection attempt failed",
- dmn->name);
- dmn->state = DAEMON_DOWN;
- }
- return 0;
-}
-
-static void
-daemon_down(struct daemon *dmn, const char *why)
-{
- if (IS_UP(dmn) || (dmn->state == DAEMON_INIT))
- zlog_err("%s state -> down : %s",dmn->name,why);
- else if (gs.loglevel > LOG_DEBUG)
- zlog_debug("%s still down : %s",dmn->name,why);
- if (IS_UP(dmn))
- gs.numdown++;
- dmn->state = DAEMON_DOWN;
- if (dmn->fd >= 0)
- {
- close(dmn->fd);
- dmn->fd = -1;
- }
- THREAD_OFF(dmn->t_read);
- THREAD_OFF(dmn->t_write);
- THREAD_OFF(dmn->t_wakeup);
- if (try_connect(dmn) < 0)
- SET_WAKEUP_DOWN(dmn);
- phase_check();
-}
-
-static int
-handle_read(struct thread *t_read)
-{
- struct daemon *dmn = THREAD_ARG(t_read);
- static const char resp[sizeof(PING_TOKEN)+4] = PING_TOKEN "\n";
- char buf[sizeof(resp)+100];
- ssize_t rc;
- struct timeval delay;
-
- dmn->t_read = NULL;
- if ((rc = read(dmn->fd,buf,sizeof(buf))) < 0)
- {
- char why[100];
-
- if (ERRNO_IO_RETRY(errno))
- {
- /* Pretend it never happened. */
- SET_READ_HANDLER(dmn);
- return 0;
- }
- snprintf(why,sizeof(why),"unexpected read error: %s",
- safe_strerror(errno));
- daemon_down(dmn,why);
- return 0;
- }
- if (rc == 0)
- {
- daemon_down(dmn,"read returned EOF");
- return 0;
- }
- if (!dmn->echo_sent.tv_sec)
- {
- char why[sizeof(buf)+100];
- snprintf(why,sizeof(why),"unexpected read returns %d bytes: %.*s",
- (int)rc,(int)rc,buf);
- daemon_down(dmn,why);
- return 0;
- }
-
- /* We are expecting an echo response: is there any chance that the
- response would not be returned entirely in the first read? That
- seems inconceivable... */
- if ((rc != sizeof(resp)) || memcmp(buf,resp,sizeof(resp)))
- {
- char why[100+sizeof(buf)];
- snprintf(why,sizeof(why),"read returned bad echo response of %d bytes "
- "(expecting %u): %.*s",
- (int)rc,(u_int)sizeof(resp),(int)rc,buf);
- daemon_down(dmn,why);
- return 0;
- }
-
- time_elapsed(&delay,&dmn->echo_sent);
- dmn->echo_sent.tv_sec = 0;
- if (dmn->state == DAEMON_UNRESPONSIVE)
- {
- if (delay.tv_sec < gs.timeout)
- {
- dmn->state = DAEMON_UP;
- zlog_warn("%s state -> up : echo response received after %ld.%06ld "
- "seconds", dmn->name,
- (long)delay.tv_sec, (long)delay.tv_usec);
- }
- else
- zlog_warn("%s: slow echo response finally received after %ld.%06ld "
- "seconds", dmn->name,
- (long)delay.tv_sec, (long)delay.tv_usec);
- }
- else if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("%s: echo response received after %ld.%06ld seconds",
- dmn->name, (long)delay.tv_sec, (long)delay.tv_usec);
-
- SET_READ_HANDLER(dmn);
- if (dmn->t_wakeup)
- thread_cancel(dmn->t_wakeup);
- SET_WAKEUP_ECHO(dmn);
-
- return 0;
-}
-
-/*
- * Wait till we notice that all daemons are ready before
- * we send we are ready to systemd
- */
-static void
-daemon_send_ready (void)
-{
- static int sent = 0;
- if (!sent && gs.numdown == 0)
- {
-#if defined (HAVE_CUMULUS)
- FILE *fp;
-
- fp = fopen("/var/run/quagga/watchquagga.started", "w");
- fclose(fp);
-#endif
- zlog_notice ("Watchquagga: Notifying Systemd we are up and running");
- systemd_send_started(master, 0);
- sent = 1;
- }
-}
-
-static void
-daemon_up(struct daemon *dmn, const char *why)
-{
- dmn->state = DAEMON_UP;
- gs.numdown--;
- dmn->connect_tries = 0;
- zlog_notice("%s state -> up : %s",dmn->name,why);
- daemon_send_ready();
- if (gs.do_ping)
- SET_WAKEUP_ECHO(dmn);
- phase_check();
-}
-
-static int
-check_connect(struct thread *t_write)
-{
- struct daemon *dmn = THREAD_ARG(t_write);
- int sockerr;
- socklen_t reslen = sizeof(sockerr);
-
- dmn->t_write = NULL;
- if (getsockopt(dmn->fd,SOL_SOCKET,SO_ERROR,(char *)&sockerr,&reslen) < 0)
- {
- zlog_warn("%s: check_connect: getsockopt failed: %s",
- dmn->name,safe_strerror(errno));
- daemon_down(dmn,"getsockopt failed checking connection success");
- return 0;
- }
- if ((reslen == sizeof(sockerr)) && sockerr)
- {
- char why[100];
- snprintf(why,sizeof(why),
- "getsockopt reports that connection attempt failed: %s",
- safe_strerror(sockerr));
- daemon_down(dmn,why);
- return 0;
- }
-
- daemon_up(dmn,"delayed connect succeeded");
- return 0;
-}
-
-static int
-wakeup_connect_hanging(struct thread *t_wakeup)
-{
- struct daemon *dmn = THREAD_ARG(t_wakeup);
- char why[100];
-
- dmn->t_wakeup = NULL;
- snprintf(why,sizeof(why),"connection attempt timed out after %ld seconds",
- gs.timeout);
- daemon_down(dmn,why);
- return 0;
-}
-
-/* Making connection to protocol daemon. */
-static int
-try_connect(struct daemon *dmn)
-{
- int sock;
- struct sockaddr_un addr;
- socklen_t len;
-
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("%s: attempting to connect",dmn->name);
- dmn->connect_tries++;
-
- memset (&addr, 0, sizeof (struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty",
- gs.vtydir,dmn->name);
-#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
- len = addr.sun_len = SUN_LEN(&addr);
-#else
- len = sizeof (addr.sun_family) + strlen (addr.sun_path);
-#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
-
- /* Quick check to see if we might succeed before we go to the trouble
- of creating a socket. */
- if (access(addr.sun_path, W_OK) < 0)
- {
- if (errno != ENOENT)
- zlog_err("%s: access to socket %s denied: %s",
- dmn->name,addr.sun_path,safe_strerror(errno));
- return -1;
- }
-
- if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- zlog_err("%s(%s): cannot make socket: %s",
- __func__,addr.sun_path, safe_strerror(errno));
- return -1;
- }
-
- if (set_nonblocking(sock) < 0 || set_cloexec(sock) < 0)
- {
- zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed",
- __func__, addr.sun_path, sock);
- close(sock);
- return -1;
- }
-
- if (connect (sock, (struct sockaddr *) &addr, len) < 0)
- {
- if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK))
- {
- if (gs.loglevel > LOG_DEBUG)
- zlog_debug("%s(%s): connect failed: %s",
- __func__,addr.sun_path, safe_strerror(errno));
- close (sock);
- return -1;
- }
- if (gs.loglevel > LOG_DEBUG)
- zlog_debug("%s: connection in progress",dmn->name);
- dmn->state = DAEMON_CONNECTING;
- dmn->fd = sock;
- dmn->t_write = thread_add_write(master,check_connect,dmn,dmn->fd);
- dmn->t_wakeup = thread_add_timer(master,wakeup_connect_hanging,dmn,
- gs.timeout);
- SET_READ_HANDLER(dmn);
- return 0;
- }
-
- dmn->fd = sock;
- SET_READ_HANDLER(dmn);
- daemon_up(dmn,"connect succeeded");
- return 1;
-}
-
-static int
-phase_hanging(struct thread *t_hanging)
-{
- gs.t_phase_hanging = NULL;
- zlog_err("Phase [%s] hanging for %ld seconds, aborting phased restart",
- phase_str[gs.phase],PHASE_TIMEOUT);
- gs.phase = PHASE_NONE;
- return 0;
-}
-
-static void
-set_phase(restart_phase_t new_phase)
-{
- gs.phase = new_phase;
- if (gs.t_phase_hanging)
- thread_cancel(gs.t_phase_hanging);
- gs.t_phase_hanging = thread_add_timer(master,phase_hanging,NULL,
- PHASE_TIMEOUT);
-}
-
-static void
-phase_check(void)
-{
- switch (gs.phase)
- {
- case PHASE_NONE:
- break;
- case PHASE_STOPS_PENDING:
- if (gs.numpids)
- break;
- zlog_info("Phased restart: all routing daemon stop jobs have completed.");
- set_phase(PHASE_WAITING_DOWN);
- /*FALLTHRU*/
- case PHASE_WAITING_DOWN:
- if (gs.numdown+IS_UP(gs.special) < gs.numdaemons)
- break;
- zlog_info("Phased restart: all routing daemons now down.");
- run_job(&gs.special->restart,"restart",gs.restart_command,1,1);
- set_phase(PHASE_ZEBRA_RESTART_PENDING);
- /*FALLTHRU*/
- case PHASE_ZEBRA_RESTART_PENDING:
- if (gs.special->restart.pid)
- break;
- zlog_info("Phased restart: %s restart job completed.",gs.special->name);
- set_phase(PHASE_WAITING_ZEBRA_UP);
- /*FALLTHRU*/
- case PHASE_WAITING_ZEBRA_UP:
- if (!IS_UP(gs.special))
- break;
- zlog_info("Phased restart: %s is now up.",gs.special->name);
- {
- struct daemon *dmn;
- for (dmn = gs.daemons; dmn; dmn = dmn->next)
- {
- if (dmn != gs.special)
- run_job(&dmn->restart,"start",gs.start_command,1,0);
- }
- }
- gs.phase = PHASE_NONE;
- THREAD_OFF(gs.t_phase_hanging);
- zlog_notice("Phased global restart has completed.");
- break;
- }
-}
-
-static void
-try_restart(struct daemon *dmn)
-{
- switch (gs.mode)
- {
- case MODE_MONITOR:
- return;
- case MODE_GLOBAL_RESTART:
- run_job(&gs.restart,"restart",gs.restart_command,0,1);
- break;
- case MODE_SEPARATE_RESTART:
- run_job(&dmn->restart,"restart",gs.restart_command,0,1);
- break;
- case MODE_PHASED_ZEBRA_RESTART:
- if (dmn != gs.special)
- {
- if ((gs.special->state == DAEMON_UP) && (gs.phase == PHASE_NONE))
- run_job(&dmn->restart,"restart",gs.restart_command,0,1);
- else
- zlog_debug("%s: postponing restart attempt because master %s daemon "
- "not up [%s], or phased restart in progress",
- dmn->name,gs.special->name,state_str[gs.special->state]);
- break;
- }
- /*FALLTHRU*/
- case MODE_PHASED_ALL_RESTART:
- if ((gs.phase != PHASE_NONE) || gs.numpids)
- {
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("postponing phased global restart: restart already in "
- "progress [%s], or outstanding child processes [%d]",
- phase_str[gs.phase],gs.numpids);
- break;
- }
- /* Is it too soon for a restart? */
- {
- struct timeval delay;
- if (time_elapsed(&delay,&gs.special->restart.time)->tv_sec <
- gs.special->restart.interval)
- {
- if (gs.loglevel > LOG_DEBUG+1)
- zlog_debug("postponing phased global restart: "
- "elapsed time %ld < retry interval %ld",
- (long)delay.tv_sec,gs.special->restart.interval);
- break;
- }
- }
- run_job(&gs.restart,"restart",gs.restart_command,0,1);
- break;
- default:
- zlog_err("error: unknown restart mode %d",gs.mode);
- break;
- }
-}
-
-static int
-wakeup_unresponsive(struct thread *t_wakeup)
-{
- struct daemon *dmn = THREAD_ARG(t_wakeup);
-
- dmn->t_wakeup = NULL;
- if (dmn->state != DAEMON_UNRESPONSIVE)
- zlog_err("%s: no longer unresponsive (now %s), "
- "wakeup should have been cancelled!",
- dmn->name,state_str[dmn->state]);
- else
- {
- SET_WAKEUP_UNRESPONSIVE(dmn);
- try_restart(dmn);
- }
- return 0;
-}
-
-static int
-wakeup_no_answer(struct thread *t_wakeup)
-{
- struct daemon *dmn = THREAD_ARG(t_wakeup);
-
- dmn->t_wakeup = NULL;
- dmn->state = DAEMON_UNRESPONSIVE;
- zlog_err("%s state -> unresponsive : no response yet to ping "
- "sent %ld seconds ago",dmn->name,gs.timeout);
- if (gs.unresponsive_restart)
- {
- SET_WAKEUP_UNRESPONSIVE(dmn);
- try_restart(dmn);
- }
- return 0;
-}
-
-static int
-wakeup_send_echo(struct thread *t_wakeup)
-{
- static const char echocmd[] = "echo " PING_TOKEN;
- ssize_t rc;
- struct daemon *dmn = THREAD_ARG(t_wakeup);
-
- dmn->t_wakeup = NULL;
- if (((rc = write(dmn->fd,echocmd,sizeof(echocmd))) < 0) ||
- ((size_t)rc != sizeof(echocmd)))
- {
- char why[100+sizeof(echocmd)];
- snprintf(why,sizeof(why),"write '%s' returned %d instead of %u",
- echocmd,(int)rc,(u_int)sizeof(echocmd));
- daemon_down(dmn,why);
- }
- else
- {
- gettimeofday(&dmn->echo_sent,NULL);
- dmn->t_wakeup = thread_add_timer(master,wakeup_no_answer,dmn,gs.timeout);
- }
- return 0;
-}
-
-static void
-sigint(void)
-{
- zlog_notice("Terminating on signal");
- systemd_send_stopping ();
- exit(0);
-}
-
-static int
-valid_command(const char *cmd)
-{
- char *p;
-
- return ((p = strchr(cmd,'%')) != NULL) && (*(p+1) == 's') && !strchr(p+1,'%');
-}
-
-/* This is an ugly hack to circumvent problems with passing command-line
- arguments that contain spaces. The fix is to use a configuration file. */
-static char *
-translate_blanks(const char *cmd, const char *blankstr)
-{
- char *res;
- char *p;
- size_t bslen = strlen(blankstr);
-
- if (!(res = strdup(cmd)))
- {
- perror("strdup");
- exit(1);
- }
- while ((p = strstr(res,blankstr)) != NULL)
- {
- *p = ' ';
- if (bslen != 1)
- memmove(p+1,p+bslen,strlen(p+bslen)+1);
- }
- return res;
-}
-
-struct zebra_privs_t watchquagga_privs =
-{
-#ifdef VTY_GROUP
- .vty_group = VTY_GROUP,
-#endif
-};
-
-int
-main(int argc, char **argv)
-{
- const char *progname;
- int opt;
- int daemon_mode = 0;
- const char *pidfile = DEFAULT_PIDFILE;
- const char *special = "zebra";
- const char *blankstr = NULL;
- static struct quagga_signal_t my_signals[] =
- {
- {
- .signal = SIGINT,
- .handler = sigint,
- },
- {
- .signal = SIGTERM,
- .handler = sigint,
- },
- {
- .signal = SIGCHLD,
- .handler = sigchild,
- },
- };
-
- if ((progname = strrchr (argv[0], '/')) != NULL)
- progname++;
- else
- progname = argv[0];
-
- gs.restart.name = "all";
- while ((opt = getopt_long(argc, argv, "aAb:dek:l:m:M:i:p:r:R:S:s:t:T:zvh",
- longopts, 0)) != EOF)
- {
- switch (opt)
- {
- case 0:
- break;
- case 'a':
- if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART))
- {
- fputs("Ambiguous operating mode selected.\n",stderr);
- return usage(progname,1);
- }
- gs.mode = MODE_PHASED_ZEBRA_RESTART;
- break;
- case 'A':
- if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART))
- {
- fputs("Ambiguous operating mode selected.\n",stderr);
- return usage(progname,1);
- }
- gs.mode = MODE_PHASED_ALL_RESTART;
- break;
- case 'b':
- blankstr = optarg;
- break;
- case 'd':
- daemon_mode = 1;
- break;
- case 'e':
- gs.do_ping = 0;
- break;
- case 'k':
- if (!valid_command(optarg))
- {
- fprintf(stderr,"Invalid kill command, must contain '%%s': %s\n",
- optarg);
- return usage(progname,1);
- }
- gs.stop_command = optarg;
- break;
- case 'l':
- {
- char garbage[3];
- if ((sscanf(optarg,"%d%1s",&gs.loglevel,garbage) != 1) ||
- (gs.loglevel < LOG_EMERG))
- {
- fprintf(stderr,"Invalid loglevel argument: %s\n",optarg);
- return usage(progname,1);
- }
- }
- break;
- case 'm':
- {
- char garbage[3];
- if ((sscanf(optarg,"%ld%1s",
- &gs.min_restart_interval,garbage) != 1) ||
- (gs.min_restart_interval < 0))
- {
- fprintf(stderr,"Invalid min_restart_interval argument: %s\n",
- optarg);
- return usage(progname,1);
- }
- }
- break;
- case 'M':
- {
- char garbage[3];
- if ((sscanf(optarg,"%ld%1s",
- &gs.max_restart_interval,garbage) != 1) ||
- (gs.max_restart_interval < 0))
- {
- fprintf(stderr,"Invalid max_restart_interval argument: %s\n",
- optarg);
- return usage(progname,1);
- }
- }
- break;
- case 'i':
- {
- char garbage[3];
- int period;
- if ((sscanf(optarg,"%d%1s",&period,garbage) != 1) ||
- (gs.period < 1))
- {
- fprintf(stderr,"Invalid interval argument: %s\n",optarg);
- return usage(progname,1);
- }
- gs.period = 1000*period;
- }
- break;
- case 'p':
- pidfile = optarg;
- break;
- case 'r':
- if ((gs.mode == MODE_GLOBAL_RESTART) ||
- (gs.mode == MODE_SEPARATE_RESTART))
- {
- fputs("Ambiguous operating mode selected.\n",stderr);
- return usage(progname,1);
- }
- if (!valid_command(optarg))
- {
- fprintf(stderr,
- "Invalid restart command, must contain '%%s': %s\n",
- optarg);
- return usage(progname,1);
- }
- gs.restart_command = optarg;
- if (gs.mode == MODE_MONITOR)
- gs.mode = MODE_SEPARATE_RESTART;
- break;
- case 'R':
- if (gs.mode != MODE_MONITOR)
- {
- fputs("Ambiguous operating mode selected.\n",stderr);
- return usage(progname,1);
- }
- if (strchr(optarg,'%'))
- {
- fprintf(stderr,
- "Invalid restart-all arg, must not contain '%%s': %s\n",
- optarg);
- return usage(progname,1);
- }
- gs.restart_command = optarg;
- gs.mode = MODE_GLOBAL_RESTART;
- break;
- case 's':
- if (!valid_command(optarg))
- {
- fprintf(stderr,"Invalid start command, must contain '%%s': %s\n",
- optarg);
- return usage(progname,1);
- }
- gs.start_command = optarg;
- break;
- case 'S':
- gs.vtydir = optarg;
- break;
- case 't':
- {
- char garbage[3];
- if ((sscanf(optarg,"%ld%1s",&gs.timeout,garbage) != 1) ||
- (gs.timeout < 1))
- {
- fprintf(stderr,"Invalid timeout argument: %s\n",optarg);
- return usage(progname,1);
- }
- }
- break;
- case 'T':
- {
- char garbage[3];
- if ((sscanf(optarg,"%ld%1s",&gs.restart_timeout,garbage) != 1) ||
- (gs.restart_timeout < 1))
- {
- fprintf(stderr,"Invalid restart timeout argument: %s\n",optarg);
- return usage(progname,1);
- }
- }
- break;
- case 'z':
- gs.unresponsive_restart = 1;
- break;
- case 'v':
- printf ("%s version %s\n", progname, QUAGGA_VERSION);
- puts("Copyright 2004 Andrew J. Schorr");
- return 0;
- case 'h':
- return usage(progname,0);
- default:
- fputs("Invalid option.\n",stderr);
- return usage(progname,1);
- }
- }
-
- if (gs.unresponsive_restart && (gs.mode == MODE_MONITOR))
- {
- fputs("Option -z requires a -r or -R restart option.\n",stderr);
- return usage(progname,1);
- }
- switch (gs.mode)
- {
- case MODE_MONITOR:
- if (gs.restart_command || gs.start_command || gs.stop_command)
- {
- fprintf(stderr,"No kill/(re)start commands needed for %s mode.\n",
- mode_str[gs.mode]);
- return usage(progname,1);
- }
- break;
- case MODE_GLOBAL_RESTART:
- case MODE_SEPARATE_RESTART:
- if (!gs.restart_command || gs.start_command || gs.stop_command)
- {
- fprintf(stderr,"No start/kill commands needed in [%s] mode.\n",
- mode_str[gs.mode]);
- return usage(progname,1);
- }
- break;
- case MODE_PHASED_ZEBRA_RESTART:
- case MODE_PHASED_ALL_RESTART:
- if (!gs.restart_command || !gs.start_command || !gs.stop_command)
- {
- fprintf(stderr,
- "Need start, kill, and restart commands in [%s] mode.\n",
- mode_str[gs.mode]);
- return usage(progname,1);
- }
- break;
- }
-
- if (blankstr)
- {
- if (gs.restart_command)
- gs.restart_command = translate_blanks(gs.restart_command,blankstr);
- if (gs.start_command)
- gs.start_command = translate_blanks(gs.start_command,blankstr);
- if (gs.stop_command)
- gs.stop_command = translate_blanks(gs.stop_command,blankstr);
- }
-
- gs.restart.interval = gs.min_restart_interval;
-
- zprivs_init (&watchquagga_privs);
-
- master = thread_master_create();
- cmd_init(-1);
- memory_init();
- vty_init(master);
- watchquagga_vty_init();
- vty_serv_sock(NULL, 0, WATCHQUAGGA_VTYSH_PATH);
-
- signal_init (master, array_size(my_signals), my_signals);
- srandom(time(NULL));
-
- {
- int i;
- struct daemon *tail = NULL;
-
- for (i = optind; i < argc; i++)
- {
- struct daemon *dmn;
-
- if (!(dmn = (struct daemon *)calloc(1,sizeof(*dmn))))
- {
- fprintf(stderr,"calloc(1,%u) failed: %s\n",
- (u_int)sizeof(*dmn), safe_strerror(errno));
- return 1;
- }
- dmn->name = dmn->restart.name = argv[i];
- dmn->state = DAEMON_INIT;
- gs.numdaemons++;
- gs.numdown++;
- dmn->fd = -1;
- dmn->t_wakeup = thread_add_timer_msec(master,wakeup_init,dmn,
- 100+(random() % 900));
- dmn->restart.interval = gs.min_restart_interval;
- if (tail)
- tail->next = dmn;
- else
- gs.daemons = dmn;
- tail = dmn;
-
- if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) ||
- (gs.mode == MODE_PHASED_ALL_RESTART)) &&
- !strcmp(dmn->name,special))
- gs.special = dmn;
- }
- }
- if (!gs.daemons)
- {
- fputs("Must specify one or more daemons to monitor.\n",stderr);
- return usage(progname,1);
- }
- if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) ||
- (gs.mode == MODE_PHASED_ALL_RESTART)) && !gs.special)
- {
- fprintf(stderr,"In mode [%s], but cannot find master daemon %s\n",
- mode_str[gs.mode],special);
- return usage(progname,1);
- }
-
- zlog_default = openzlog(progname, ZLOG_WATCHQUAGGA, 0,
- LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
- zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
- if (daemon_mode)
- {
- zlog_set_level(NULL, ZLOG_DEST_SYSLOG, MIN(gs.loglevel,LOG_DEBUG));
- if (daemon (0, 0) < 0)
- {
- fprintf(stderr, "Watchquagga daemon failed: %s", strerror(errno));
- exit (1);
- }
- }
- else
- zlog_set_level(NULL, ZLOG_DEST_STDOUT, MIN(gs.loglevel,LOG_DEBUG));
-
- /* Make sure we're not already running. */
- pid_output (pidfile);
-
- /* Announce which daemons are being monitored. */
- {
- struct daemon *dmn;
- size_t len = 0;
-
- for (dmn = gs.daemons; dmn; dmn = dmn->next)
- len += strlen(dmn->name)+1;
-
- {
- char buf[len+1];
- char *p = buf;
-
- for (dmn = gs.daemons; dmn; dmn = dmn->next)
- {
- if (p != buf)
- *p++ = ' ';
- strcpy(p,dmn->name);
- p += strlen(p);
- }
- zlog_notice("%s %s watching [%s], mode [%s]",
- progname, QUAGGA_VERSION, buf, mode_str[gs.mode]);
- }
- }
-
- {
- struct thread thread;
-
- while (thread_fetch (master, &thread))
- thread_call (&thread);
- }
-
- systemd_send_stopping ();
- /* Not reached. */
- return 0;
-}
+++ /dev/null
-/*
- Common definitions for watchquagga API socket.
-
- Copyright (C) 2016 David Lamparter for NetDEF, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef QUAGGA_WATCHQUAGGA_H
-#define QUAGGA_WATCHQUAGGA_H
-
-extern void watchquagga_vty_init(void);
-
-extern pid_t integrated_write_pid;
-extern void integrated_write_sigchld(int status);
-
-#endif /* QUAGGA_WATCHQUAGGA_H */
+++ /dev/null
-/*
- watchquagga CLI functions.
-
- Copyright (C) 2016 David Lamparter for NetDEF, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <zebra.h>
-#include <sys/wait.h>
-
-#include "memory.h"
-#include "log.h"
-#include "vty.h"
-#include "command.h"
-
-#include "watchquagga.h"
-
-pid_t integrated_write_pid;
-static int integrated_result_fd;
-
-DEFUN (config_write_integrated,
- config_write_integrated_cmd,
- "write integrated",
- "Write running configuration to memory, network, or terminal\n"
- "Write integrated all-daemon Quagga.conf file\n")
-{
- pid_t child;
- sigset_t oldmask, sigmask;
-
- if (integrated_write_pid != -1) {
- vty_out(vty, "%% configuration write already in progress.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- fflush(stdout);
- fflush(stderr);
-
- /* need to temporarily block SIGCHLD because it could arrive between
- * fork() call and setting the integrated_write_pid variable. This
- * would mean the completion call gets lost and this hangs forever.
- */
- sigemptyset(&oldmask);
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &sigmask, &oldmask);
-
- child = fork();
- if (child == -1) {
- vty_out(vty, "%% configuration write fork() failed: %s.%s",
- safe_strerror(errno), VTY_NEWLINE);
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- return CMD_WARNING;
- }
- if (child != 0) {
- /* note: the VTY won't write a command return value to vtysh; the
- * session temporarily enters an intentional "hang" state. This is
- * to make sure latency in vtysh doing the config write (several
- * seconds is not rare to see) does not interfere with watchquagga's
- * supervisor job.
- *
- * The fd is duplicated here so we don't need to hold a vty pointer
- * (which could become invalid in the meantime).
- */
- integrated_write_pid = child;
- integrated_result_fd = dup(vty->wfd);
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- return CMD_SUSPEND;
- }
-
- /* redirect stdout/stderr to vty session. Note vty->wfd is marked
- * CLOEXEC, but dup2 will clear that flag. */
- dup2(vty->wfd, 1);
- dup2(vty->wfd, 2);
-
- /* don't allow the user to pass parameters, we're root here!
- * should probably harden vtysh at some point too... */
- execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL);
-
- /* unbuffered write; we just messed with stdout... */
- char msg[512];
- snprintf(msg, sizeof(msg), "error executing %s: %s\n",
- VTYSH_BIN_PATH, safe_strerror(errno));
- write(1, msg, strlen(msg));
- exit(1);
-}
-
-void integrated_write_sigchld(int status)
-{
- uint8_t reply[4] = { 0, 0, 0, CMD_WARNING };
-
- if (WIFEXITED(status)) {
- zlog_info("configuration write completed with exit code %d",
- WEXITSTATUS(status));
- reply[3] = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- zlog_warn("configuration write terminated by signal %d",
- WTERMSIG(status));
- } else {
- zlog_warn("configuration write terminated");
- }
-
- if (reply[3] != CMD_SUCCESS) {
- /* failure might be silent in vtysh without this */
- static const char msg[] = "% Configuration write failed.\n";
- write(integrated_result_fd, msg, strlen(msg));
- }
-
- /* don't care about failures here, if the connection is broken the
- * return value will just be lost. */
- write(integrated_result_fd, reply, sizeof(reply));
- close(integrated_result_fd);
-
- integrated_write_pid = -1;
-}
-
-void watchquagga_vty_init(void)
-{
- integrated_write_pid = -1;
- install_element(ENABLE_NODE, &config_write_integrated_cmd);
-}
/*
- * $Quagga: $Format:%an, %ai, %h$ $
- *
* GNU Zebra client test main routine.
* Copyright (C) 1997 Kunihiro Ishiguro
*
int i;
struct if_link_params *iflp = ifp->link_params;
vty_out(vty, " Traffic Engineering Link Parameters:%s", VTY_NEWLINE);
- if (IS_PARAM_SET(iflp, LP_TE))
+ if (IS_PARAM_SET(iflp, LP_TE_METRIC))
vty_out(vty, " TE metric %u%s",iflp->te_metric, VTY_NEWLINE);
if (IS_PARAM_SET(iflp, LP_MAX_BW))
vty_out(vty, " Maximum Bandwidth %g (Byte/s)%s", iflp->max_bw, VTY_NEWLINE);
VTY_GET_ULONG("metric", metric, argv[idx_number]->arg);
/* Update TE metric if needed */
- link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE | LP_TE_METRIC, metric);
+ link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE_METRIC, metric);
return CMD_SUCCESS;
}
VTY_DECLVAR_CONTEXT (interface, ifp);
/* Unset TE Metric */
- link_param_cmd_unset(ifp, LP_TE | LP_TE_METRIC);
+ link_param_cmd_unset(ifp, LP_TE_METRIC);
return CMD_SUCCESS;
}
vty_out (vty, " link-params%s", VTY_NEWLINE);
vty_out(vty, " enable%s", VTY_NEWLINE);
- if (IS_PARAM_SET(iflp, LP_TE) && IS_PARAM_SET(iflp, LP_TE_METRIC))
+ if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
vty_out(vty, " metric %u%s",iflp->te_metric, VTY_NEWLINE);
if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
vty_out(vty, " max-bw %g%s", iflp->max_bw, VTY_NEWLINE);
/* zebra privileges to run with */
struct zebra_privs_t zserv_privs =
{
-#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
- .user = QUAGGA_USER,
- .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
printf ("-v, --version Print program version\n"\
"-h, --help Display this help and exit\n"\
"\n"\
- "Report bugs to %s\n", ZEBRA_BUG_ADDRESS);
+ "Report bugs to %s\n", FRR_BUG_ADDRESS);
}
exit (status);
vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
/* Print banner. */
- zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ zlog_notice ("Zebra %s starting: vty@%d", FRR_VERSION, vty_port);
while (thread_fetch (zebrad.master, &thread))
thread_call (&thread);
/* Nexthop information. */
u_char nexthop_num;
u_char nexthop_active_num;
- u_char nexthop_fib_num;
};
/* meta-queue structure:
extern void rib_addnode (struct route_node *rn, struct rib *rib, int process);
extern void rib_delnode (struct route_node *rn, struct rib *rib);
-extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int update);
+extern int rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old);
extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib);
/* NOTE:
"-v, --version Print program version\n"\
"-h, --help Display this help and exit\n"\
"\n"\
- "Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+ "Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
}
exit (status);
vty_serv_sock (vty_addr, vty_port, "/tmp/test_zebra");
/* Print banner. */
- zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);
+ zlog_notice ("Zebra %s starting: vty@%d", FRR_VERSION, vty_port);
while (thread_fetch (zebrad.master, &thread))
thread_call (&thread);
#include "vrf.h"
#include "rib.h"
#include "zebra_vrf.h"
+#include "version.h"
#define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
#define ZEBRA_PTM_RECONNECT_TIME_MAX 300
ptm_cb.pid = getpid();
zebra_ptm_install_commands();
- sprintf(buf, "%s", "quagga");
+ sprintf(buf, "%s", FRR_PTM_NAME);
ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb,
zebra_ptm_handle_msg_cb);
ptm_cb.wb = buffer_new(0);
* is only used for IPv4.
*/
int
-rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
+rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old)
{
int ret = 0;
struct nexthop *nexthop, *tnexthop;
* the kernel.
*/
zfpm_trigger_update (rn, "installing in kernel");
- ret = kernel_route_rib (&rn->p, update ? rib : NULL, rib);
+ ret = kernel_route_rib (&rn->p, old, rib);
/* If install succeeds, update FIB flag for nexthops. */
if (!ret)
if (!RIB_SYSTEM_ROUTE (new))
{
- if (rib_install_kernel (rn, new, 0))
+ if (rib_install_kernel (rn, new, NULL))
{
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
zlog_warn ("%u:%s/%d: Route install failed",
/* Non-system route should be installed. */
if (!RIB_SYSTEM_ROUTE (new))
{
- if (rib_install_kernel (rn, new, 1))
+ if (rib_install_kernel (rn, new, old))
{
installed = 0;
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
break;
}
if (!in_fib)
- rib_install_kernel (rn, new, 0);
+ rib_install_kernel (rn, new, NULL);
}
}
);
zlog_debug
(
- "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
+ "%s: nexthop_num == %u, nexthop_active_num == %u",
func,
rib->nexthop_num,
- rib->nexthop_active_num,
- rib->nexthop_fib_num
+ rib->nexthop_active_num
);
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{
/* This means someone else, other than Zebra, has deleted
* a Zebra router from the kernel. We will add it back */
- rib_install_kernel(rn, fib, 0);
+ rib_install_kernel(rn, fib, NULL);
}
}
else
"ip protocol <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> route-map ROUTE-MAP",
IP_STR
"Filter routing info exchanged between zebra and protocol\n"
- QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route-map\n"
"Route map name\n")
{
NO_STR
IP_STR
"Stop filtering routing info between zebra and protocol\n"
- QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
return CMD_SUCCESS;
}
-
DEFUN (show_ip_protocol,
show_ip_protocol_cmd,
"show ip protocol",
"ipv6 protocol <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> route-map ROUTE-MAP",
IP6_STR
"Filter IPv6 routing info exchanged between zebra and protocol\n"
- QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
NO_STR
IP6_STR
"Stop filtering IPv6 routing info between zebra and protocol\n"
- QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
return CMD_SUCCESS;
}
-
DEFUN (show_ipv6_protocol,
show_ipv6_protocol_cmd,
"show ipv6 protocol",
"ip nht <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> route-map ROUTE-MAP",
IP_STR
"Filter Next Hop tracking route resolution\n"
- QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
NO_STR
IP_STR
"Filter Next Hop tracking route resolution\n"
- QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
return CMD_SUCCESS;
}
-
DEFUN (show_ip_protocol_nht,
show_ip_protocol_nht_cmd,
"show ip nht route-map",
"ipv6 nht <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> route-map ROUTE-MAP",
IP6_STR
"Filter Next Hop tracking route resolution\n"
- QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
NO_STR
IP6_STR
"Filter Next Hop tracking route resolution\n"
- QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Specify route map\n"
"Route map name\n")
{
return CMD_SUCCESS;
}
-
DEFUN (show_ipv6_protocol_nht,
show_ipv6_protocol_nht_cmd,
"show ipv6 nht route-map",
{
/* Update route in kernel if it's in fib */
if (CHECK_FLAG(rib->status, RIB_ENTRY_SELECTED_FIB))
- rib_install_kernel (rn, rib, 1);
+ rib_install_kernel (rn, rib, rib);
/* Update redistribution if it's selected */
if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED))
redistribute_update (&rn->p, rib, NULL);
IP_STR
"IP routing table\n"
VRF_CMD_HELP_STR
- QUAGGA_IP_REDIST_HELP_STR_ZEBRA)
+ FRR_IP_REDIST_HELP_STR_ZEBRA)
{
int type;
struct route_table *table;
IP_STR
"IP routing table\n"
VRF_ALL_CMD_HELP_STR
- QUAGGA_IP_REDIST_HELP_STR_ZEBRA"\n")
+ FRR_IP_REDIST_HELP_STR_ZEBRA"\n")
{
int type;
struct route_table *table;
IP_STR
"IP routing table\n"
VRF_CMD_HELP_STR
- QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)
+ FRR_IP6_REDIST_HELP_STR_ZEBRA)
{
int type;
struct route_table *table;
IP_STR
"IP routing table\n"
VRF_ALL_CMD_HELP_STR
- QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)
+ FRR_IP6_REDIST_HELP_STR_ZEBRA)
{
int idx_protocol = 5;
int type;
install_element (CONFIG_NODE, &no_ip_route_flags_cmd);
install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd);
- install_element (VIEW_NODE, &show_ip_route_vrf_cmd);
install_element (VIEW_NODE, &show_ip_route_vrf_cmd);
install_element (VIEW_NODE, &show_ip_route_vrf_all_cmd);