Merge branch 'master' into working/master/bgp-vpn-vrf-leaking

This commit is contained in:
paulzlabn 2018-03-14 13:31:58 -07:00 committed by GitHub
commit 3f1224cd1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
287 changed files with 21542 additions and 17315 deletions

3
.gitignore vendored
View File

@ -82,3 +82,6 @@ GPATH
*.lo *.lo
compile_commands.json compile_commands.json
.dirstamp .dirstamp
# clippy generated source
*_clippy.c

36
alpine/APKBUILD.in Normal file
View File

@ -0,0 +1,36 @@
# Maintainer: Arthur Jones <arthur.jones@riverbed.com>
pkgname=frr
pkgver=@VERSION@
pkgrel=0
pkgdesc="Free Range Routing is a fork of quagga"
url="https://frrouting.org/"
arch="all"
license="GPL-2.0"
depends="iproute2 json-c c-ares ipsec-tools iproute2"
makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
acct autoconf automake bash
binutils binutils-libs bison bsd-compat-headers build-base
c-ares c-ares-dev ca-certificates cryptsetup-libs curl
device-mapper-libs expat fakeroot flex fortify-headers gdbm
git gmp isl json-c-dev kmod lddtree libacl libatomic libattr
libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc
libgomp libisoburn libisofs libltdl libressl libssh2
libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1
mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base
patch pax-utils pcre perl pkgconf python2 python2-dev readline
readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs"
subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
source="$pkgname-$pkgver.tar.gz"
builddir="$srcdir"/$pkgname-$pkgver
build() {
cd "$builddir"
./configure --prefix=/usr || return 1
make || return 1
}
package() {
cd "$builddir"
make DESTDIR="$pkgdir" install || return 1
}

1
bgpd/.gitignore vendored
View File

@ -16,4 +16,3 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
*clippy.c

View File

@ -2107,6 +2107,51 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
return BGP_ATTR_PARSE_PROCEED; return BGP_ATTR_PARSE_PROCEED;
} }
/* PMSI tunnel attribute (RFC 6514)
* Basic validation checks done here.
*/
static bgp_attr_parse_ret_t
bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
u_int8_t tnl_type;
/* Verify that the receiver is expecting "ingress replication" as we
* can only support that.
*/
if (length < 2) {
zlog_err("Bad PMSI tunnel attribute length %d", length);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
}
stream_getc(peer->curr); /* Flags */
tnl_type = stream_getc(peer->curr);
if (tnl_type > PMSI_TNLTYPE_MAX) {
zlog_err("Invalid PMSI tunnel attribute type %d", tnl_type);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
}
if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
if (length != 9) {
zlog_err("Bad PMSI tunnel attribute length %d for IR",
length);
return bgp_attr_malformed(
args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
}
}
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
attr->pmsi_tnl_type = tnl_type;
/* Forward read pointer of input stream. */
stream_forward_getp(peer->curr, length - 2);
return BGP_ATTR_PARSE_PROCEED;
}
/* BGP unknown attribute treatment. */ /* BGP unknown attribute treatment. */
static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
{ {
@ -2440,6 +2485,9 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
case BGP_ATTR_PREFIX_SID: case BGP_ATTR_PREFIX_SID:
ret = bgp_attr_prefix_sid(&attr_args, mp_update); ret = bgp_attr_prefix_sid(&attr_args, mp_update);
break; break;
case BGP_ATTR_PMSI_TUNNEL:
ret = bgp_attr_pmsi_tunnel(&attr_args);
break;
default: default:
ret = bgp_attr_unknown(&attr_args); ret = bgp_attr_unknown(&attr_args);
break; break;
@ -3263,7 +3311,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_PMSI_TUNNEL); stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
stream_putc(s, 9); // Length stream_putc(s, 9); // Length
stream_putc(s, 0); // Flags stream_putc(s, 0); // Flags
stream_putc(s, 6); // Tunnel type: Ingress Replication (6) stream_putc(s, PMSI_TNLTYPE_INGR_REPL); // IR (6)
stream_put(s, &(attr->label), stream_put(s, &(attr->label),
BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
stream_put_ipv4(s, attr->nexthop.s_addr); stream_put_ipv4(s, attr->nexthop.s_addr);

View File

@ -66,6 +66,8 @@
#define BGP_PREFIX_SID_IPV6_LENGTH 19 #define BGP_PREFIX_SID_IPV6_LENGTH 19
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6 #define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
/* PMSI tunnel types (RFC 6514) */
struct bgp_attr_encap_subtlv { struct bgp_attr_encap_subtlv {
struct bgp_attr_encap_subtlv *next; /* for chaining */ struct bgp_attr_encap_subtlv *next; /* for chaining */
/* Reference count of this attribute. */ /* Reference count of this attribute. */
@ -96,6 +98,18 @@ struct overlay_index {
union gw_addr gw_ip; union gw_addr gw_ip;
}; };
enum pta_type {
PMSI_TNLTYPE_NO_INFO = 0,
PMSI_TNLTYPE_RSVP_TE_P2MP,
PMSI_TNLTYPE_MLDP_P2MP,
PMSI_TNLTYPE_PIM_SSM,
PMSI_TNLTYPE_PIM_SM,
PMSI_TNLTYPE_PIM_BIDIR,
PMSI_TNLTYPE_INGR_REPL,
PMSI_TNLTYPE_MLDP_MP2MP,
PMSI_TNLTYPE_MAX = PMSI_TNLTYPE_MLDP_MP2MP
};
/* BGP core attribute structure. */ /* BGP core attribute structure. */
struct attr { struct attr {
/* AS Path structure */ /* AS Path structure */
@ -119,6 +133,9 @@ struct attr {
/* Path origin attribute */ /* Path origin attribute */
u_char origin; u_char origin;
/* PMSI tunnel type (RFC 6514). */
enum pta_type pmsi_tnl_type;
/* has the route-map changed any attribute? /* has the route-map changed any attribute?
Used on the peer outbound side. */ Used on the peer outbound side. */
u_int32_t rmap_change_flags; u_int32_t rmap_change_flags;

View File

@ -162,7 +162,6 @@ static const struct message bgp_notify_capability_msg[] = {
const char *bgp_origin_str[] = {"i", "e", "?"}; const char *bgp_origin_str[] = {"i", "e", "?"};
const char *bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; const char *bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"};
/* Given a string return a pointer the corresponding peer structure */ /* Given a string return a pointer the corresponding peer structure */
static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str) static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str)
{ {
@ -417,6 +416,10 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size)
inet_ntoa(attr->cluster->list[i])); inet_ntoa(attr->cluster->list[i]));
} }
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)))
snprintf(buf + strlen(buf), size - strlen(buf),
", pmsi tnltype %u", attr->pmsi_tnl_type);
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
snprintf(buf + strlen(buf), size - strlen(buf), ", path %s", snprintf(buf + strlen(buf), size - strlen(buf), ", path %s",
aspath_print(attr->aspath)); aspath_print(attr->aspath));

View File

@ -142,6 +142,7 @@ struct bgp_debug_filter {
#define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b) #define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
extern const char *bgp_type_str[]; extern const char *bgp_type_str[];
extern const char *pmsi_tnltype_str[];
extern int bgp_dump_attr(struct attr *, char *, size_t); extern int bgp_dump_attr(struct attr *, char *, size_t);
extern int bgp_debug_peer_updout_enabled(char *host); extern int bgp_debug_peer_updout_enabled(char *host);

View File

@ -474,6 +474,17 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
bgp_evpn_derive_auto_rt_export(bgp, vpn); bgp_evpn_derive_auto_rt_export(bgp, vpn);
} }
/*
* Convert nexthop (remote VTEP IP) into an IPv6 address.
*/
static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
{
if (BGP_ATTR_NEXTHOP_AFI_IP6(attr))
return;
ipv4_to_ipv4_mapped_ipv6(&attr->mp_nexthop_global, attr->nexthop);
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
}
/* /*
* Add (update) or delete MACIP from zebra. * Add (update) or delete MACIP from zebra.
*/ */
@ -622,17 +633,17 @@ static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf,
} }
/* /*
* Build extended communities for EVPN route. RT and ENCAP are * Build extended communities for EVPN route.
* applicable to all routes. * This function is applicable for type-2 and type-3 routes. The layer-2 RT
* TODO: currently kernel doesnt support ipv6 routes with ipv4 nexthops. * and ENCAP extended communities are applicable for all routes.
* This means that we can't do symmetric routing for ipv6 hosts routes * The default gateway extended community and MAC mobility (sticky) extended
* in the same way as ipv4 host routes. * community are added as needed based on passed settings - only for type-2
* We wont attach l3-vni related RTs for ipv6 routes. * routes. Likewise, the layer-3 RT and Router MAC extended communities are
* For now, We will only adevrtise ipv4 host routes * added, if present, based on passed settings - only for non-link-local
* with L3-VNI related ext-comm. * type-2 routes.
*/ */
static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
afi_t afi) int add_l3_ecomm)
{ {
struct ecommunity ecom_encap; struct ecommunity ecom_encap;
struct ecommunity ecom_sticky; struct ecommunity ecom_sticky;
@ -662,11 +673,10 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom); attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom);
/* /* Add the export RTs for L3VNI if told to - caller determines
* only attach l3-vni export rts for ipv4 address family and if we are * when this should be done.
* advertising both the labels in type-2 routes
*/ */
if (afi == AFI_IP && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) { if (add_l3_ecomm) {
vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn); vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn);
if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) { if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) {
for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode, for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode,
@ -676,6 +686,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
} }
} }
/* Add MAC mobility (sticky) if needed. */
if (attr->sticky) { if (attr->sticky) {
seqnum = 0; seqnum = 0;
memset(&ecom_sticky, 0, sizeof(ecom_sticky)); memset(&ecom_sticky, 0, sizeof(ecom_sticky));
@ -686,12 +697,8 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_sticky); ecommunity_merge(attr->ecommunity, &ecom_sticky);
} }
/* /* Add RMAC, if told to. */
* only attach l3-vni rmac for ipv4 address family and if we are if (add_l3_ecomm) {
* advertising both the labels in type-2 routes
*/
if (afi == AFI_IP && !is_zero_mac(&attr->rmac)
&& CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) {
memset(&ecom_rmac, 0, sizeof(ecom_rmac)); memset(&ecom_rmac, 0, sizeof(ecom_rmac));
encode_rmac_extcomm(&eval_rmac, &attr->rmac); encode_rmac_extcomm(&eval_rmac, &attr->rmac);
ecom_rmac.size = 1; ecom_rmac.size = 1;
@ -700,6 +707,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_rmac); ecommunity_merge(attr->ecommunity, &ecom_rmac);
} }
/* Add default gateway, if needed. */
if (attr->default_gw) { if (attr->default_gw) {
memset(&ecom_default_gw, 0, sizeof(ecom_default_gw)); memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
encode_default_gw_extcomm(&eval_default_gw); encode_default_gw_extcomm(&eval_default_gw);
@ -1260,6 +1268,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_node *rn; struct bgp_node *rn;
struct attr attr; struct attr attr;
struct attr *attr_new; struct attr *attr_new;
int add_l3_ecomm = 0;
struct bgp_info *ri; struct bgp_info *ri;
afi_t afi = AFI_L2VPN; afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN; safi_t safi = SAFI_EVPN;
@ -1279,14 +1288,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
/* router mac is only needed for type-2 and type-5 routes */ /* router mac is only needed for type-2 routes here. */
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
bgpevpn_get_rmac(vpn, &attr.rmac); bgpevpn_get_rmac(vpn, &attr.rmac);
vni2label(vpn->vni, &(attr.label)); vni2label(vpn->vni, &(attr.label));
/* Set up RT and ENCAP extended community. */ /* Include L3 VNI related RTs and RMAC for type-2 routes, if they're
build_evpn_route_extcomm( * IPv4 or IPv6 global addresses and we're advertising L3VNI with
vpn, &attr, IS_EVPN_PREFIX_IPADDR_V4(p) ? AFI_IP : AFI_IP6); * these routes.
*/
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
(IS_EVPN_PREFIX_IPADDR_V4(p) ||
!IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) &&
CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
add_l3_ecomm = 1;
/* Set up extended community. */
build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
/* First, create (or fetch) route node within the VNI. */ /* First, create (or fetch) route node within the VNI. */
/* NOTE: There is no RD here. */ /* NOTE: There is no RD here. */
@ -1466,22 +1484,20 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
struct attr attr; struct attr attr;
struct attr attr_sticky; struct attr attr_sticky;
struct attr attr_def_gw; struct attr attr_def_gw;
struct attr attr_ip6; struct attr attr_ip6_ll;
struct attr attr_sticky_ip6;
struct attr attr_def_gw_ip6;
struct attr *attr_new; struct attr *attr_new;
int add_l3_ecomm = 0;
afi = AFI_L2VPN; afi = AFI_L2VPN;
safi = SAFI_EVPN; safi = SAFI_EVPN;
memset(&attr, 0, sizeof(struct attr)); memset(&attr, 0, sizeof(struct attr));
memset(&attr_sticky, 0, sizeof(struct attr)); memset(&attr_sticky, 0, sizeof(struct attr));
memset(&attr_def_gw, 0, sizeof(struct attr)); memset(&attr_def_gw, 0, sizeof(struct attr));
memset(&attr_ip6, 0, sizeof(struct attr)); memset(&attr_ip6_ll, 0, sizeof(struct attr));
memset(&attr_sticky_ip6, 0, sizeof(struct attr));
memset(&attr_def_gw_ip6, 0, sizeof(struct attr));
/* Build path-attribute - all type-2 routes for this VNI will share the /* Build path-attribute - multiple type-2 routes for this VNI will share
* same path attribute. * the same path attribute, but we need separate structures for sticky
* MACs, default gateway and IPv6 link-local addresses (no L3 RT/RMAC).
*/ */
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP);
@ -1500,31 +1516,21 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_def_gw.default_gw = 1; attr_def_gw.default_gw = 1;
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac); bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP); attr_ip6_ll.nexthop = vpn->originator_ip;
bgp_attr_default_set(&attr_def_gw_ip6, BGP_ORIGIN_IGP); attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip;
attr_ip6.nexthop = vpn->originator_ip; attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
bgpevpn_get_rmac(vpn, &attr_ip6.rmac);
attr_sticky_ip6.nexthop = vpn->originator_ip;
attr_sticky_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_sticky_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_sticky_ip6.sticky = 1;
bgpevpn_get_rmac(vpn, &attr_sticky_ip6.rmac);
attr_def_gw_ip6.nexthop = vpn->originator_ip;
attr_def_gw_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_def_gw_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_def_gw_ip6.default_gw = 1;
bgpevpn_get_rmac(vpn, &attr_def_gw_ip6.rmac);
/* Set up RT, ENCAP and sticky MAC extended community. */ /* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if
build_evpn_route_extcomm(vpn, &attr, AFI_IP); * using L3 VNI for type-2 routes also.
build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP); */
build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP); if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6); add_l3_ecomm = 1;
build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6);
build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP); build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_sticky, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_def_gw, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_ip6_ll, 0);
/* Walk this VNI's route table and update local type-2 routes. For any /* Walk this VNI's route table and update local type-2 routes. For any
* routes updated, update corresponding entry in the global table too. * routes updated, update corresponding entry in the global table too.
@ -1538,7 +1544,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue; continue;
if (IS_EVPN_PREFIX_IPADDR_V4(evp)) { if (IS_EVPN_PREFIX_IPADDR_V6(evp) &&
IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_ip6_ll, 0, 1, &ri, 0);
else {
if (evpn_route_is_sticky(bgp, rn)) if (evpn_route_is_sticky(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri, &attr_sticky, 0, 1, &ri,
@ -1550,19 +1560,6 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
else else
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, 1, &ri, 0); &attr, 0, 1, &ri, 0);
} else {
if (evpn_route_is_sticky(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky_ip6, 0, 1,
&ri, 0);
else if (evpn_route_is_def_gw(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_def_gw_ip6, 0, 1,
&ri, 0);
else
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_ip6, 0, 1, &ri,
0);
} }
/* If a local route exists for this prefix, we need to update /* If a local route exists for this prefix, we need to update
@ -1593,11 +1590,9 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
/* Unintern temporary. */ /* Unintern temporary. */
aspath_unintern(&attr.aspath); aspath_unintern(&attr.aspath);
aspath_unintern(&attr_ip6.aspath);
aspath_unintern(&attr_sticky.aspath); aspath_unintern(&attr_sticky.aspath);
aspath_unintern(&attr_sticky_ip6.aspath);
aspath_unintern(&attr_def_gw.aspath); aspath_unintern(&attr_def_gw.aspath);
aspath_unintern(&attr_def_gw_ip6.aspath); aspath_unintern(&attr_ip6_ll.aspath);
return 0; return 0;
} }
@ -1791,6 +1786,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *ri; struct bgp_info *ri;
struct attr attr;
struct attr *attr_new; struct attr *attr_new;
int ret = 0; int ret = 0;
struct prefix p; struct prefix p;
@ -1827,6 +1823,15 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
} else } else
return 0; return 0;
/* EVPN routes currently only support a IPv4 next hop which corresponds
* to the remote VTEP. When importing into a VRF, if it is IPv6 host
* route, we have to convert the next hop to an IPv4-mapped address
* for the rest of the code to flow through.
*/
bgp_attr_dup(&attr, parent_ri->attr);
if (afi == AFI_IP6)
evpn_convert_nexthop_to_ipv6(&attr);
/* Check if route entry is already present. */ /* Check if route entry is already present. */
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
if (ri->extra if (ri->extra
@ -1835,7 +1840,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
if (!ri) { if (!ri) {
/* Add (or update) attribute to hash. */ /* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(parent_ri->attr); attr_new = bgp_attr_intern(&attr);
/* Create new route with its attribute. */ /* Create new route with its attribute. */
ri = info_make(parent_ri->type, parent_ri->sub_type, 0, ri = info_make(parent_ri->type, parent_ri->sub_type, 0,
@ -1850,21 +1855,25 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
} }
bgp_info_add(rn, ri); bgp_info_add(rn, ri);
} else { } else {
if (attrhash_cmp(ri->attr, parent_ri->attr) if (attrhash_cmp(ri->attr, &attr)
&& !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
bgp_unlock_node(rn); bgp_unlock_node(rn);
return 0; return 0;
} }
/* The attribute has changed. */ /* The attribute has changed. */
/* Add (or update) attribute to hash. */ /* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(parent_ri->attr); attr_new = bgp_attr_intern(&attr);
/* Restore route, if needed. */ /* Restore route, if needed. */
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
bgp_info_restore(rn, ri); bgp_info_restore(rn, ri);
/* Mark if nexthop has changed. */ /* Mark if nexthop has changed. */
if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) if ((afi == AFI_IP &&
!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) ||
(afi == AFI_IP6 &&
!IPV6_ADDR_SAME(&ri->attr->mp_nexthop_global,
&attr_new->mp_nexthop_global)))
SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
/* Unintern existing, set to new. */ /* Unintern existing, set to new. */
@ -2577,10 +2586,12 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
{ {
/* delete all ipv4 routes and withdraw from peers */ /* delete all ipv4 routes and withdraw from peers */
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP))
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* delete all ipv6 routes and withdraw from peers */ /* delete all ipv6 routes and withdraw from peers */
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP6))
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
} }
/* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5 /* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5
@ -2588,10 +2599,12 @@ static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
static void update_advertise_vrf_routes(struct bgp *bgp_vrf) static void update_advertise_vrf_routes(struct bgp *bgp_vrf)
{ {
/* update all ipv4 routes */ /* update all ipv4 routes */
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP))
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* update all ipv6 routes */ /* update all ipv6 routes */
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP6))
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
} }
/* /*
@ -2922,6 +2935,19 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
return -1; return -1;
} }
/* If PMSI is present, log if it is anything other than IR.
* Note: We just simply ignore the values as it is not clear if
* doing anything else is better.
*/
if (attr &&
(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL) {
zlog_warn("%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
peer->bgp->vrf_id, peer->host,
attr->pmsi_tnl_type);
}
}
/* Make prefix_rd */ /* Make prefix_rd */
prd.family = AF_UNSPEC; prd.family = AF_UNSPEC;
prd.prefixlen = 64; prd.prefixlen = 64;
@ -3214,10 +3240,6 @@ void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
struct prefix_evpn evp; struct prefix_evpn evp;
char buf[PREFIX_STRLEN]; char buf[PREFIX_STRLEN];
/* NOTE: Check needed as this is called per-route also. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
build_type5_prefix_from_ip_prefix(&evp, p); build_type5_prefix_from_ip_prefix(&evp, p);
ret = delete_evpn_type5_route(bgp_vrf, &evp); ret = delete_evpn_type5_route(bgp_vrf, &evp);
if (ret) { if (ret) {
@ -3235,10 +3257,6 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi)
struct bgp_node *rn = NULL; struct bgp_node *rn = NULL;
struct bgp_info *ri; struct bgp_info *ri;
/* Bail out early if we don't have to advertise type-5 routes. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
table = bgp_vrf->rib[afi][safi]; table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Only care about "selected" routes - non-imported. */ /* Only care about "selected" routes - non-imported. */
@ -3267,11 +3285,7 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
int ret = 0; int ret = 0;
struct prefix_evpn evp; struct prefix_evpn evp;
char buf[PREFIX_STRLEN]; char buf[PREFIX_STRLEN];
/* NOTE: Check needed as this is called per-route also. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
build_type5_prefix_from_ip_prefix(&evp, p); build_type5_prefix_from_ip_prefix(&evp, p);
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr); ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
if (ret) if (ret)
@ -3290,10 +3304,6 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
struct bgp_node *rn = NULL; struct bgp_node *rn = NULL;
struct bgp_info *ri; struct bgp_info *ri;
/* Bail out early if we don't have to advertise type-5 routes. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
table = bgp_vrf->rib[afi][safi]; table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Need to identify the "selected" route entry to use its /* Need to identify the "selected" route entry to use its

View File

@ -55,6 +55,25 @@ static inline vni_t label2vni(mpls_label_t *label)
return vni; return vni;
} }
static inline int advertise_type5_routes(struct bgp *bgp_vrf,
afi_t afi)
{
if (!bgp_vrf->l3vni)
return 0;
if (afi == AFI_IP &&
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
return 1;
if (afi == AFI_IP6 &&
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
return 1;
return 0;
}
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
struct prefix *p, struct prefix *p,
struct attr *src_attr, afi_t afi, struct attr *src_attr, afi_t afi,

View File

@ -285,6 +285,14 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
} }
} }
static inline int is_evpn_prefix_default(struct prefix *evp)
{
if (evp->family != AF_EVPN)
return 0;
return ((evp->u.prefix_evpn.ip_prefix_length == 0) ? 1 : 0);
}
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
struct prefix *ip) struct prefix *ip)
{ {
@ -352,19 +360,17 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
p->prefix.ip.ipaddr_v4 = originator_ip; p->prefix.ip.ipaddr_v4 = originator_ip;
} }
static inline int advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi) static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
safi_t safi)
{ {
if (!bgp_vrf->l3vni) if (afi == AFI_IP &&
return 0; CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
if (afi == AFI_IP
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
return 1; return 1;
else if (afi == AFI_IP6 &&
if (afi == AFI_IP6 CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
return 1; return 1;
return 0; return 0;
} }

View File

@ -2419,7 +2419,50 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp,
/* /*
* evpn - enable advertisement of default g/w * evpn - enable advertisement of default g/w
*/ */
static void evpn_set_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn) static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
afi_t afi, int add)
{
struct prefix ip_prefix;
safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
/* form the default prefix 0.0.0.0/0 */
memset(&ip_prefix, 0, sizeof(struct prefix));
ip_prefix.family = afi2family(afi);
ip_prefix.prefixlen = 0;
if (add) {
/* bail if we are already advertising default route */
if (evpn_default_originate_set(bgp_vrf, afi, safi))
return;
if (afi == AFI_IP)
SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
else if (afi == AFI_IP6)
SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
NULL, afi, safi);
} else {
/* bail out if we havent advertised the default route */
if (!evpn_default_originate_set(bgp_vrf, afi, safi))
return;
if (afi == AFI_IP)
UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
else if (afi == AFI_IP6)
UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
afi, safi);
}
}
/*
* evpn - enable advertisement of default g/w
*/
static void evpn_set_advertise_subnet(struct bgp *bgp,
struct bgpevpn *vpn)
{ {
if (vpn->advertise_subnet) if (vpn->advertise_subnet)
return; return;
@ -2612,6 +2655,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (bgp_evpn_default_originate,
bgp_evpn_default_originate_cmd,
"default-originate <ipv4 | ipv6>",
"originate a default route\n"
"ipv4 address family\n"
"ipv6 address family\n")
{
afi_t afi = 0;
int idx_afi = 0;
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
if (!bgp_vrf)
return CMD_WARNING;
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
return CMD_SUCCESS;
}
DEFUN (no_bgp_evpn_default_originate,
no_bgp_evpn_default_originate_cmd,
"no default-originate <ipv4 | ipv6>",
NO_STR
"withdraw a default route\n"
"ipv4 address family\n"
"ipv6 address family\n")
{
afi_t afi = 0;
int idx_afi = 0;
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
if (!bgp_vrf)
return CMD_WARNING;
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
return CMD_SUCCESS;
}
DEFUN (bgp_evpn_advertise_vni_subnet, DEFUN (bgp_evpn_advertise_vni_subnet,
bgp_evpn_advertise_vni_subnet_cmd, bgp_evpn_advertise_vni_subnet_cmd,
"advertise-subnet", "advertise-subnet",
@ -2631,14 +2711,6 @@ DEFUN (bgp_evpn_advertise_vni_subnet,
if (!bgp_vrf) if (!bgp_vrf)
return CMD_WARNING; return CMD_WARNING;
if (!(advertise_type5_routes(bgp_vrf, AFI_IP)
|| advertise_type5_routes(bgp_vrf, AFI_IP6))) {
vty_out(vty,
"%%Please enable ip prefix advertisement under l2vpn evpn in %s",
vrf_id_to_name(bgp_vrf->vrf_id));
return CMD_WARNING;
}
evpn_set_advertise_subnet(bgp, vpn); evpn_set_advertise_subnet(bgp, vpn);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -2711,19 +2783,23 @@ DEFUN (bgp_evpn_advertise_type5,
/* if we are already advertising ipv4 prefix as type-5 /* if we are already advertising ipv4 prefix as type-5
* nothing to do * nothing to do
*/ */
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, if (!rmap_changed &&
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
return CMD_WARNING; return CMD_WARNING;
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN); SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
} else { } else {
/* if we are already advertising ipv6 prefix as type-5 /* if we are already advertising ipv6 prefix as type-5
* nothing to do * nothing to do
*/ */
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, if (!rmap_changed &&
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
return CMD_WARNING; return CMD_WARNING;
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN); SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
} }
if (rmap_changed) { if (rmap_changed) {
@ -2766,7 +2842,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
argv_find_and_parse_safi(argv, argc, &idx_safi, &safi); argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
if (!(afi == AFI_IP) || (afi == AFI_IP6)) { if (!(afi == AFI_IP || afi == AFI_IP6)) {
vty_out(vty, vty_out(vty,
"%%only ipv4 or ipv6 address families are supported"); "%%only ipv4 or ipv6 address families are supported");
return CMD_WARNING; return CMD_WARNING;
@ -2780,25 +2856,25 @@ DEFUN (no_bgp_evpn_advertise_type5,
if (afi == AFI_IP) { if (afi == AFI_IP) {
/* if we are already advertising ipv4 prefix as type-5 /* if we are not advertising ipv4 prefix as type-5
* nothing to do * nothing to do
*/ */
if (CHECK_FLAG(bgp_vrf->vrf_flags, if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) { BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
UNSET_FLAG(bgp_vrf->vrf_flags, UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV4_IN_EVPN); BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
} }
} else { } else {
/* if we are already advertising ipv6 prefix as type-5 /* if we are not advertising ipv6 prefix as type-5
* nothing to do * nothing to do
*/ */
if (CHECK_FLAG(bgp_vrf->vrf_flags, if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) { BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
UNSET_FLAG(bgp_vrf->vrf_flags, UNSET_FLAG(bgp_vrf->vrf_flags,
BGP_VRF_ADVERTISE_IPV6_IN_EVPN); BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
} }
} }
@ -4305,12 +4381,22 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
if (bgp->advertise_gw_macip) if (bgp->advertise_gw_macip)
vty_out(vty, " advertise-default-gw\n"); vty_out(vty, " advertise-default-gw\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
vty_out(vty, " advertise ipv4 unicast\n"); vty_out(vty, " advertise ipv4 unicast\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
vty_out(vty, " advertise ipv6 unicast\n"); vty_out(vty, " advertise ipv6 unicast\n");
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
vty_out(vty, " default-originate ipv4\n");
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
vty_out(vty, " default-originate ipv6\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD)) if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
vty_out(vty, " rd %s\n", vty_out(vty, " rd %s\n",
prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1))); prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
@ -4373,6 +4459,8 @@ void bgp_ethernetvpn_init(void)
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
/* "show bgp l2vpn evpn" commands. */ /* "show bgp l2vpn evpn" commands. */
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd); install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);

View File

@ -82,6 +82,21 @@
extern const char *bgp_origin_str[]; extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[]; extern const char *bgp_origin_long_str[];
/* PMSI strings. */
#define PMSI_TNLTYPE_STR_NO_INFO "No info"
#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
static const struct message bgp_pmsi_tnltype_str[] = {
{PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
{PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
{PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
{PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
{PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
{PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
{PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
{PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
{0}
};
struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p, safi_t safi, struct prefix *p,
struct prefix_rd *prd) struct prefix_rd *prd)
@ -2285,12 +2300,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
/* advertise/withdraw type-5 routes */ /* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (new_select if (advertise_type5_routes(bgp, afi) && new_select &&
&& (!new_select->extra || !new_select->extra->parent)) (!new_select->extra || !new_select->extra->parent))
bgp_evpn_advertise_type5_route( bgp_evpn_advertise_type5_route(bgp, &rn->p,
bgp, &rn->p, new_select->attr, afi, safi); new_select->attr,
else if (old_select afi, safi);
&& (!old_select->extra || !old_select->extra->parent)) else if (advertise_type5_routes(bgp, afi) && old_select &&
(!old_select->extra || !old_select->extra->parent))
bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
} }
@ -7197,6 +7213,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
json_object *json_ext_community = NULL; json_object *json_ext_community = NULL;
json_object *json_lcommunity = NULL; json_object *json_lcommunity = NULL;
json_object *json_last_update = NULL; json_object *json_last_update = NULL;
json_object *json_pmsi = NULL;
json_object *json_nexthop_global = NULL; json_object *json_nexthop_global = NULL;
json_object *json_nexthop_ll = NULL; json_object *json_nexthop_ll = NULL;
json_object *json_nexthops = NULL; json_object *json_nexthops = NULL;
@ -7949,6 +7966,24 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
json_last_update); json_last_update);
} else } else
vty_out(vty, " Last update: %s", ctime(&tbuf)); vty_out(vty, " Last update: %s", ctime(&tbuf));
/* Line 10 display PMSI tunnel attribute, if present */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
const char *str = lookup_msg(bgp_pmsi_tnltype_str,
attr->pmsi_tnl_type,
PMSI_TNLTYPE_STR_DEFAULT);
if (json_paths) {
json_pmsi = json_object_new_object();
json_object_string_add(json_pmsi,
"tunnelType", str);
json_object_object_add(json_path, "pmsi",
json_pmsi);
} else
vty_out(vty, " PMSI Tunnel Type: %s\n",
str);
}
} }
/* We've constructed the json object for this path, add it to the json /* We've constructed the json object for this path, add it to the json

View File

@ -595,6 +595,24 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
route_match_ip_route_source_prefix_list_compile, route_match_ip_route_source_prefix_list_compile,
route_match_ip_route_source_prefix_list_free}; route_match_ip_route_source_prefix_list_free};
/* `match evpn default-route' */
/* Match function should return 1 if match is success else 0 */
static route_map_result_t route_match_evpn_default_route(void *rule,
struct prefix *p,
route_map_object_t
type, void *object)
{
if (type == RMAP_BGP && is_evpn_prefix_default(p))
return RMAP_MATCH;
return RMAP_NOMATCH;
}
/* Route map commands for default-route matching. */
struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
"evpn default-route", route_match_evpn_default_route, NULL, NULL};
/* `match mac address MAC_ACCESS_LIST' */ /* `match mac address MAC_ACCESS_LIST' */
/* Match function should return 1 if match is success else return /* Match function should return 1 if match is success else return
@ -3254,6 +3272,29 @@ DEFUN (no_match_evpn_vni,
RMAP_EVENT_MATCH_DELETED); RMAP_EVENT_MATCH_DELETED);
} }
DEFUN (match_evpn_default_route,
match_evpn_default_route_cmd,
"match evpn default-route",
MATCH_STR
EVPN_HELP_STR
"default EVPN type-5 route\n")
{
return bgp_route_match_add(vty, "evpn default-route", NULL,
RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_evpn_default_route,
no_match_evpn_default_route_cmd,
"no match evpn default-route",
NO_STR
MATCH_STR
EVPN_HELP_STR
"default EVPN type-5 route\n")
{
return bgp_route_match_delete(vty, "evpn default-route", NULL,
RMAP_EVENT_MATCH_DELETED);
}
DEFUN (match_peer, DEFUN (match_peer,
match_peer_cmd, match_peer_cmd,
"match peer <A.B.C.D|X:X::X:X|WORD>", "match peer <A.B.C.D|X:X::X:X|WORD>",
@ -4633,6 +4674,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_mac_address_cmd); route_map_install_match(&route_match_mac_address_cmd);
route_map_install_match(&route_match_evpn_vni_cmd); route_map_install_match(&route_match_evpn_vni_cmd);
route_map_install_match(&route_match_evpn_route_type_cmd); route_map_install_match(&route_match_evpn_route_type_cmd);
route_map_install_match(&route_match_evpn_default_route_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd); route_map_install_set(&route_set_ip_nexthop_cmd);
route_map_install_set(&route_set_local_pref_cmd); route_map_install_set(&route_set_local_pref_cmd);
@ -4669,6 +4711,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_match_evpn_vni_cmd); install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
install_element(RMAP_NODE, &match_evpn_route_type_cmd); install_element(RMAP_NODE, &match_evpn_route_type_cmd);
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd); install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
install_element(RMAP_NODE, &match_evpn_default_route_cmd);
install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
install_element(RMAP_NODE, &match_aspath_cmd); install_element(RMAP_NODE, &match_aspath_cmd);
install_element(RMAP_NODE, &no_match_aspath_cmd); install_element(RMAP_NODE, &no_match_aspath_cmd);

View File

@ -7534,16 +7534,14 @@ static void bgp_pthreads_init()
.id = PTHREAD_IO, .id = PTHREAD_IO,
.start = frr_pthread_attr_default.start, .start = frr_pthread_attr_default.start,
.stop = frr_pthread_attr_default.stop, .stop = frr_pthread_attr_default.stop,
.name = "BGP I/O thread",
}; };
struct frr_pthread_attr ka = { struct frr_pthread_attr ka = {
.id = PTHREAD_KEEPALIVES, .id = PTHREAD_KEEPALIVES,
.start = bgp_keepalives_start, .start = bgp_keepalives_start,
.stop = bgp_keepalives_stop, .stop = bgp_keepalives_stop,
.name = "BGP Keepalives thread",
}; };
frr_pthread_new(&io); frr_pthread_new(&io, "BGP I/O thread");
frr_pthread_new(&ka); frr_pthread_new(&ka, "BGP Keepalives thread");
} }
void bgp_pthreads_run() void bgp_pthreads_run()

View File

@ -319,6 +319,13 @@ struct bgp {
#define BGP_CONFIG_DAMPENING (1 << 0) #define BGP_CONFIG_DAMPENING (1 << 0)
#define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1) #define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1)
/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1)
#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 2)
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 3)
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 4)
/* Route table for next-hop lookup cache. */ /* Route table for next-hop lookup cache. */
struct bgp_table *nexthop_cache_table[AFI_MAX]; struct bgp_table *nexthop_cache_table[AFI_MAX];
@ -430,12 +437,11 @@ struct bgp {
/* vrf flags */ /* vrf flags */
uint32_t vrf_flags; uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0) #define BGP_VRF_AUTO (1 << 0)
#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1) #define BGP_VRF_IMPORT_RT_CFGD (1 << 1)
#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2) #define BGP_VRF_EXPORT_RT_CFGD (1 << 2)
#define BGP_VRF_IMPORT_RT_CFGD (1 << 3) #define BGP_VRF_RD_CFGD (1 << 3)
#define BGP_VRF_EXPORT_RT_CFGD (1 << 4) #define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 4)
#define BGP_VRF_RD_CFGD (1 << 5)
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6)
/* unique ID for auto derivation of RD for this vrf */ /* unique ID for auto derivation of RD for this vrf */
uint16_t vrf_rd_id; uint16_t vrf_rd_id;

View File

@ -396,6 +396,8 @@ AC_ARG_ENABLE(rpki,
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support])) AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
AC_ARG_ENABLE([clippy-only], AC_ARG_ENABLE([clippy-only],
AS_HELP_STRING([--enable-clippy-only], [Only build clippy])) AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
AC_ARG_ENABLE([numeric_version],
AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
AS_IF([test "${enable_clippy_only}" != "yes"], [ AS_IF([test "${enable_clippy_only}" != "yes"], [
AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_HEADERS(json-c/json.h)
@ -647,6 +649,14 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout
AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use]) AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
dnl ------------------------------------
dnl Alpine only accepts numeric versions
dnl ------------------------------------
if test "x${enable_numeric_version}" != "x" ; then
VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`"
PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`"
fi
dnl ----------------------------------- dnl -----------------------------------
dnl Add extra version string to package dnl Add extra version string to package
dnl name, string and version fields. dnl name, string and version fields.
@ -1872,27 +1882,10 @@ AC_CONFIG_FILES([Makefile
redhat/frr.spec redhat/frr.spec
debianpkg/Makefile debianpkg/Makefile
debianpkg/changelog debianpkg/changelog
alpine/APKBUILD
snapcraft/snapcraft.yaml snapcraft/snapcraft.yaml
lib/version.h lib/version.h
tests/lib/cli/test_cli.refout tests/lib/cli/test_cli.refout
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/eigrpd.8
doc/ripngd.8
doc/pimd.8
doc/mtracebis.8
doc/nhrpd.8
doc/vtysh.1
doc/watchfrr.8
doc/zebra.8
doc/frr.1
doc/frr-args.8
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
pkgsrc/eigrpd.sh]) pkgsrc/eigrpd.sh])

View File

@ -27,6 +27,9 @@ MULTIPATH ?= 256
WANT_FRR_USER ?= frr WANT_FRR_USER ?= frr
WANT_FRR_VTY_GROUP ?= frrvty WANT_FRR_VTY_GROUP ?= frrvty
# Don't build PDF docs by default
GENERATE_PDF ?= 0
# #
#################################### ####################################
@ -135,18 +138,11 @@ override_dh_auto_configure:
fi fi
override_dh_auto_build: override_dh_auto_build:
#dh_auto_build
$(MAKE)
dh_auto_build -- -C doc draft-zebra-00.txt
# doc/ is a bit crazy
ifeq ($(GENERATE_PDF), 1) ifeq ($(GENERATE_PDF), 1)
dh_auto_build -- -C doc frr.pdf || true # pdfetex fails with exit code 1 but still produces a good looking .pdf dh_auto_build -- -C doc pdf
endif endif
rm -vf doc/frr.info rm -vf doc/user/_build/texinfo/frr.info
dh_auto_build -- -C doc frr.info dh_auto_build -- -C doc info
rm -vf doc/frr.info.html*
override_dh_auto_test: override_dh_auto_test:

View File

@ -5,18 +5,6 @@ usr/include/frr/
usr/lib/ usr/lib/
tools/frr etc/init.d/ tools/frr etc/init.d/
usr/share/doc/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/man/man8/mtracebis.8
usr/share/snmp/mibs/ usr/share/snmp/mibs/
tools/etc/* etc/ tools/etc/* etc/
tools/*.service lib/systemd/system tools/*.service lib/systemd/system

View File

@ -27,6 +27,9 @@ MULTIPATH ?= 256
WANT_FRR_USER ?= frr WANT_FRR_USER ?= frr
WANT_FRR_VTY_GROUP ?= frrvty WANT_FRR_VTY_GROUP ?= frrvty
# Don't build PDF docs by default
GENERATE_PDF ?= 0
# #
#################################### ####################################
@ -137,16 +140,13 @@ override_dh_auto_configure:
override_dh_auto_build: override_dh_auto_build:
#dh_auto_build #dh_auto_build
$(MAKE) $(MAKE)
dh_auto_build -- -C doc draft-zebra-00.txt
# doc/ is a bit crazy # doc/ is a bit crazy
ifeq ($(GENERATE_PDF), 1) ifeq ($(GENERATE_PDF), 1)
dh_auto_build -- -C doc frr.pdf || true # pdfetex fails with exit code 1 but still produces a good looking .pdf dh_auto_build -- -C doc pdf
endif endif
rm -vf doc/frr.info rm -vf doc/_build/texinfo/frr.info
dh_auto_build -- -C doc frr.info dh_auto_build -- -C doc info
rm -vf doc/frr.info.html*
override_dh_auto_test: override_dh_auto_test:

View File

@ -4,7 +4,7 @@ Priority: optional
Maintainer: Nobody <nobody@frrouting.org> Maintainer: Nobody <nobody@frrouting.org>
Uploaders: Nobody <nobody@frrouting.org> Uploaders: Nobody <nobody@frrouting.org>
XSBC-Original-Maintainer: <maintainers@frrouting.org> XSBC-Original-Maintainer: <maintainers@frrouting.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, autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7), python-ipaddr 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), autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7), python-ipaddr, python-sphinx
Standards-Version: 3.9.6 Standards-Version: 3.9.6
Homepage: http://www.frrouting.org/ Homepage: http://www.frrouting.org/

View File

@ -2,7 +2,5 @@ AUTHORS
NEWS NEWS
README README
REPORTING-BUGS REPORTING-BUGS
doc/BGP-TypeCode doc/user/*.rst
doc/draft-zebra-00.txt doc/figures/*.png
doc/mpls/
bgpd/BGP4-MIB.txt

View File

@ -1 +1 @@
doc/frr.info* doc/user/_build/texinfo/frr.info

View File

@ -1,2 +1 @@
usr/share/info doc/user/_build/texinfo/*.png usr/share/info
doc/*.png usr/share/info

View File

@ -5,20 +5,7 @@ usr/include/frr/
usr/lib/ usr/lib/
tools/frr usr/lib/frr tools/frr usr/lib/frr
usr/share/doc/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/man/man8/frr-args.8
usr/share/man/man8/mtracebis.8
usr/share/snmp/mibs/ usr/share/snmp/mibs/
tools/etc/* etc/ tools/etc/* etc/
tools/*.service lib/systemd/system tools/*.service lib/systemd/system
debian/frr.conf usr/lib/tmpfiles.d debian/frr.conf usr/lib/tmpfiles.d

View File

@ -1,9 +1,15 @@
doc/bgpd.8 doc/manpages/_build/man/frr.1
doc/ospf6d.8 doc/manpages/_build/man/bgpd.8
doc/ospfd.8 doc/manpages/_build/man/pimd.8
doc/ripd.8 doc/manpages/_build/man/eigrpd.8
doc/ripngd.8 doc/manpages/_build/man/ldpd.8
doc/vtysh.1 doc/manpages/_build/man/nhrpd.8
doc/zebra.8 doc/manpages/_build/man/ospf6d.8
doc/isisd.8 doc/manpages/_build/man/ospfd.8
doc/watchfrr.8 doc/manpages/_build/man/ripd.8
doc/manpages/_build/man/ripngd.8
doc/manpages/_build/man/vtysh.1
doc/manpages/_build/man/zebra.8
doc/manpages/_build/man/isisd.8
doc/manpages/_build/man/watchfrr.8
doc/manpages/_build/man/mtracebis.8

View File

@ -27,6 +27,9 @@ MULTIPATH ?= 256
WANT_FRR_USER ?= frr WANT_FRR_USER ?= frr
WANT_FRR_VTY_GROUP ?= frrvty WANT_FRR_VTY_GROUP ?= frrvty
# Don't build PDF docs by default
GENERATE_PDF ?= 0
# #
#################################### ####################################
@ -136,18 +139,12 @@ override_dh_auto_configure:
fi fi
override_dh_auto_build: override_dh_auto_build:
#dh_auto_build
$(MAKE)
dh_auto_build -- -C doc draft-zebra-00.txt
# doc/ is a bit crazy # doc/ is a bit crazy
ifeq ($(GENERATE_PDF), 1) ifeq ($(GENERATE_PDF), 1)
dh_auto_build -- -C doc frr.pdf || true # pdfetex fails with exit code 1 but still produces a good looking .pdf dh_auto_build -- -C doc pdf
endif endif
rm -vf doc/frr.info rm -vf doc/user/_build/texinfo/frr.info
dh_auto_build -- -C doc frr.info dh_auto_build -- -C doc info
rm -vf doc/frr.info.html*
override_dh_auto_test: override_dh_auto_test:

9
doc/.gitignore vendored
View File

@ -2,13 +2,6 @@ Makefile
Makefile.in Makefile.in
mdate-sh mdate-sh
draft-zebra-00.txt draft-zebra-00.txt
frr.info-*
zebra.html
defines.texi
version.texi
texinfo.tex
frr.html
frr.info
*.pdf *.pdf
*.eps *.eps
frr.ps frr.ps
@ -28,8 +21,6 @@ stamp-vti
*.toc *.toc
*.tp *.tp
*.vr *.vr
*.8
*.1
.arch-inventory .arch-inventory
.arch-ids .arch-ids
*~ *~

View File

@ -1,96 +0,0 @@
Building FRR for OpenWRT/LEDE from Git Source
===============================================
- for the moment because of cross compile problems, master is not supported,
only upto 3.0
- LDP can't be built because of missing Perl-XML-LibXML in OpenWRT/LEDE tree
Prepare build environment
-------------------------
https://lede-project.org/docs/guide-developer/install-buildsystem
for
Ubuntu 12.04LTS:
sudo apt-get install build-essential subversion git-core \
libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc \
libxml-parser-perl mercurial bzr ecj cvs unzip
Ubuntu 64bit:
sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \
gawk gcc-multilib flex git-core gettext libssl-dev
Debian 8 Jessie:
sudo apt-get install build-essential libncurses5-dev gawk git subversion \
libssl-dev gettext unzip zlib1g-dev file python
Debian 9 Stretch:
sudo apt-get install build-essential libncurses5-dev gawk git subversion \
libssl-dev gettext zlib1g-dev
Centos x86-64 (some packages require EPEL):
yum install subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \
ncurses-devel zlib-devel zlib-static make patch unzip glibc glibc-devel \
perl-ExtUtils-MakeMaker glibc-static quilt ncurses-libs sed sdcc bison \
intltool sharutils wget git-core openssl-devel xz
Fedora 24 - 64Bit:
dnf install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext git-core \
unzip ncurses-devel ncurses-compat-libs zlib-devel zlib-static make \
flex patch perl-ExtUtils-MakeMaker perl-Thread-Queue glibc glibc-devel \
glibc-static quilt sed sdcc intltool sharutils bison wget openssl-devel
Get LEDE Sources (from Git)
---------------------------
LEDE and OpenWRT is planned to remerge and won't cover the similar OpenWRT build
As normal user:
git clone https://git.lede-project.org/source.git lede
cd lede
./scripts/feeds update -a
./scripts/feeds install -a
cd feeds/routing
git pull origin pull/319/head
ln -s ../../../feeds/routing/frr/ ../../package/feeds/routing/
cd ../..
make menuconfig
Select the needed target then select needed packages in
Network -> Routing and Redirection -> frr, exit and save
make or make package/frr/compile
It may be possible that on first build `make package/frr/compile` not to work
and it may be needed to run a `make` for the entire build envronment, add V=s
for debugging
Work with sources
-----------------
To update the rc1 version or add other options, the Makefile is found in
feeds/routing/frr
edit:
PKG_VERSION:=
PKG_SOURCE_VERSION:=<git-hash>
Usage
-----
Edit `/usr/sbin/frr.init` and add/remove the daemons name in section DAEMONS=
or don't install unneded packages
For example: zebra bgpd ldpd isisd nhrpd ospfd ospf6d pimd ripd ripngd
### Enable the serivce
- service frr enable
### Start the service
- service frr start

View File

@ -1,194 +1,258 @@
## Process this file with automake to produce Makefile.in. ## Process this file with automake to produce Makefile.in.
# Dia, the version i have at least, doesn't do very good EPS output # Pass down make invocation to each subdirectory.
# (some of the text is scaled strangely). So this will work, but
# it is probably better to use something like gimp to convert the
# dia exported PNG files to EPS manually.
# #
# Here we use 'convert' from the well known 'ImageMagick' package # Each of these directories contains a Sphinx-generated Makefile that has been
# to do conversion from png to eps/pdf for figures. # modified to implement all the targets required by Automake, as documented in
# PDF form is required for frr.pdf, using PDFTex at least. # the 'Third-Party Makefiles' section of the Automake docs.
# #
# TeX implementation, which we depend on already anyway. # Note the absence of the 'developer' directory here; development docs are
# # never built as part of a regular build. They are only built when explicitly
# dia -> (dia) -> png -> (convert) -> eps -> (epstopdf) -> pdf # asked for. See comment further down.
SUFFIXES = .png .eps .dia .pdf
DIATOPNG = dia -t png -e
DIATOEPS = dia -t eps -e
PNGTOEPS = convert -antialias -contrast -despeckle
PNGTOPDF = $(PNGTOEPS)
EPSTOPDF = epstopdf
VNCFIGURES_PNG = # Sphinx is not designed to be invoked multiple times against the same toctree.
VNCFIGURES_DIA = -vnc-mesh -vnc-frr-route-reflector \ .NOTPARALLEL:
-vnc-commercial-route-reflector -vnc-redundant-route-reflectors \
-vnc-gw -vnc-gw-rr
# TODO: A target that creates an empty text file for each member of SUBDIRS = manpages user
# VNCFIGURES_TXT AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir} doczdir=${abs_srcdir}
VNCFIGURES_TXT = $(VNCFIGURES:%.png=%.txt)
# The figure sources MANPAGE_BUILDDIR = manpages/_build/man
figures_names_parts = -normal-processing -rs-processing \
_topologies_full _topologies_rs \
$(VNCFIGURES_DIA)
figures_sources = $(figures_names_parts:%=fig%.dia) # This is a hack, see comment further down.
figures_png = $(figures_names_parts:%=fig%.png) $(VNCFIGURES_PNG) man_MANS = $(MANPAGE_BUILDDIR)/frr.1
figures_pdf = $(figures_names_parts:%=fig%.pdf) $(VNCFIGURES_PNG:%.png=%.pdf)
figures_eps = $(figures_names_parts:%=fig%.eps) $(VNCFIGURES_PNG:%.png=%.eps)
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, 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.
info_TEXINFOS = frr.texi
# 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...
frr.pdf: $(info_TEXINFOS) $(figures_pdf) $(frr_TEXINFOS) defines.texi
$(TEXI2PDF) -o "$@" $< || true
# don't ask me why the info file is in srcdir
$(srcdir)/frr.info: $(frr_TEXINFOS) defines.texi
frr.dvi: $(frr_TEXINFOS) defines.texi
frr.html: $(frr_TEXINFOS) defines.texi
frr_TEXINFOS = \
appendix.texi \
basic.texi \
bgpd.texi \
isisd.texi \
filter.texi \
vnc.texi \
babeld.texi \
install.texi \
ipv6.texi \
kernel.texi \
main.texi \
nhrpd.texi \
eigrpd.texi \
ospf6d.texi \
ospfd.texi \
overview.texi \
protocol.texi \
ripd.texi \
ripngd.texi \
routemap.texi \
snmp.texi \
vtysh.texi \
routeserver.texi \
$(figures_png) \
snmptrap.texi \
ospf_fundamentals.texi \
isisd.texi $(figures_txt) \
rpki.texi \
pimd.texi \
#END
.png.eps:
$(PNGTOEPS) $< "$@"
.png.pdf:
$(PNGTOPDF) $< "$@"
.dia.png:
$(DIATOPNG) "$@" $<
man_MANS = frr.1 frr-args.8
if PIMD if PIMD
man_MANS += pimd.8 man_MANS += $(MANPAGE_BUILDDIR)/pimd.8
man_MANS += mtracebis.8 man_MANS += $(MANPAGE_BUILDDIR)/mtracebis.8
endif endif
if BGPD if BGPD
man_MANS += bgpd.8 man_MANS += $(MANPAGE_BUILDDIR)/bgpd.8
endif endif
if ISISD if ISISD
man_MANS += isisd.8 man_MANS += $(MANPAGE_BUILDDIR)/isisd.8
endif endif
if OSPF6D if OSPF6D
man_MANS += ospf6d.8 man_MANS += $(MANPAGE_BUILDDIR)/ospf6d.8
endif endif
if OSPFCLIENT if OSPFCLIENT
man_MANS += ospfclient.8 man_MANS += $(MANPAGE_BUILDDIR)/ospfclient.8
endif endif
if OSPFD if OSPFD
man_MANS += ospfd.8 man_MANS += $(MANPAGE_BUILDDIR)/ospfd.8
endif endif
if LDPD if LDPD
man_MANS += ldpd.8 man_MANS += $(MANPAGE_BUILDDIR)/ldpd.8
endif endif
if RIPD if RIPD
man_MANS += ripd.8 man_MANS += $(MANPAGE_BUILDDIR)/ripd.8
endif endif
if RIPNGD if RIPNGD
man_MANS += ripngd.8 man_MANS += $(MANPAGE_BUILDDIR)/ripngd.8
endif endif
if NHRPD if NHRPD
man_MANS += nhrpd.8 man_MANS += $(MANPAGE_BUILDDIR)/nhrpd.8
endif endif
if VTYSH if VTYSH
man_MANS += vtysh.1 man_MANS += $(MANPAGE_BUILDDIR)/vtysh.1
endif endif
if WATCHFRR if WATCHFRR
man_MANS += watchfrr.8 man_MANS += $(MANPAGE_BUILDDIR)/watchfrr.8
endif endif
if ZEBRA if ZEBRA
man_MANS += zebra.8 man_MANS += $(MANPAGE_BUILDDIR)/zebra.8
endif endif
if EIGRPD if EIGRPD
man_MANS += eigrpd.8 man_MANS += $(MANPAGE_BUILDDIR)/eigrpd.8
endif endif
EXTRA_DIST = BGP-TypeCode draft-zebra-00.ms draft-zebra-00.txt \ # Automake is particular about manpages. It is aware of them and has some
\ # special facilities for handling them, but it assumes that manpages are always
bgpd.8.in \ # given in groff source and so these facilities are limited to simply
isisd.8.in \ # specifying the path to the groff sources in a special variable. There is no
ospf6d.8.in \ # target for building manpages that can be extended, as there are for pdf,
ospfclient.8.in \ # html, dvi, etc. Unfortunately this leaves us with hijacking the
ospfd.8.in \ # 'install-data' and 'all' targets in the 3rd-party Makefile in manpages/ to
ldpd.8.in \ # make sure manpages are always built, and then using the special Automake
ripd.8.in \ # variable defined above in order to take advantage of automatic installation.
ripngd.8.in \ #
pimd.8.in \ # However, it is conceivable that someone may want to build just the manpages,
mtracebis.8.in \ # so here's an explicit target for that.
nhrpd.8.in \ man:
vtysh.1.in \ $(MAKE) -C manpages man
watchfrr.8.in \
zebra.8.in \
frr.1.in \
eigrpd.8.in \
\
mpls/ChangeLog.opaque.txt mpls/cli_summary.txt \
mpls/opaque_lsa.txt mpls/ospfd.conf \
$(figures_sources) $(figures_png) $(figures_txt)
draft-zebra-00.txt: draft-zebra-00.ms # Automake automatically defines targets for various document formats. All of
groff -T ascii -ms $< > $@ # the child 3rd-party Makefiles are aware of all Automake targets and implement
# the ones we are interested in.
#
# The SUBDIRS variable at the top of this Makefile.am causes the following
# implicit Automake targets to only build user documentation, and not developer
# documentation:
# - info
# - html
# - pdf
#
# If you wish to build developer documentation, use these targets:
developer-info:
$(MAKE) -C developer info
# Ensure that all of the figures are copied into the html directory developer-pdf:
html-local: $(HTMLS) $(MAKE) -C developer latexpdf
if test -d $(HTMLS) ; then \
cp -p $(figures_png) $(HTMLS) ; \ developer-html:
else \ $(MAKE) -C developer html
echo "$(HTMLS) is not a directory. Make it so, the rerun make."; \
fi # If you want to build the developer's docs in other formats, try the
# following:
#
# $ cd developer
# $ make help
# dist tarballs want doc sources
EXTRA_DIST = frr-sphinx.mk \
manpages/defines.rst \
manpages/ldpd.rst \
manpages/index.rst \
manpages/bgpd.rst \
manpages/watchfrr.rst \
manpages/ospfclient.rst \
manpages/ripd.rst \
manpages/zebra.rst \
manpages/epilogue.rst \
manpages/eigrpd.rst \
manpages/isisd.rst \
manpages/ospf6d.rst \
manpages/common-options.rst \
manpages/ospfd.rst \
manpages/vtysh.rst \
manpages/nhrpd.rst \
manpages/pimd.rst \
manpages/mtracebis.rst \
manpages/ripngd.rst \
manpages/frr.rst \
manpages/conf.py \
manpages/Makefile \
developer/Building_FRR_on_NetBSD7.rst \
developer/ldpd-basic-test-setup.md \
developer/cli.rst \
developer/index.rst \
developer/library.rst \
developer/memtypes.rst \
developer/bgpd.rst \
developer/draft-zebra-00.ms \
developer/dev-modules.md \
developer/conf.py \
developer/next-hop-tracking.rst \
developer/Building_FRR_on_FreeBSD11.rst \
developer/building.rst \
developer/Building_FRR_on_CentOS6.rst \
developer/Building_FRR_on_Ubuntu1604.rst \
developer/ospf-api.rst \
developer/ospf-sr.rst \
developer/Building_FRR_on_OpenBSD6.rst \
developer/Building_FRR_on_Debian8.rst \
developer/Building_FRR_on_NetBSD6.rst \
developer/Building_FRR_on_Debian9.rst \
developer/Building_FRR_on_LEDE-OpenWRT.rst \
developer/modules.rst \
developer/Building_FRR_on_FreeBSD10.rst \
developer/Building_FRR_on_Ubuntu1204.rst \
developer/Building_FRR_on_Fedora24.rst \
developer/Makefile \
developer/Building_FRR_on_FreeBSD9.rst \
developer/BGP-TypeCode \
developer/Building_FRR_on_OmniOS.rst \
developer/Building_FRR_on_CentOS7.rst \
developer/hooks.rst \
developer/OSPF-API.md \
developer/workflow.rst \
developer/Building_FRR_on_Ubuntu1404.rst \
user/ospf_fundamentals.rst \
user/routemap.rst \
user/index.rst \
user/conf.py \
user/ipv6.rst \
user/ripd.rst \
user/vnc.rst \
user/zebra.rst \
user/installation.rst \
user/overview.rst \
user/protocol.rst \
user/eigrpd.rst \
user/rpki.rst \
user/kernel.rst \
user/isisd.rst \
user/ospf6d.rst \
user/Useful_Sysctl_Settings.md \
user/basic.rst \
user/ospfd.rst \
user/vtysh.rst \
user/filter.rst \
user/nhrpd.rst \
user/Makefile \
user/routeserver.rst \
user/appendix.rst \
user/bgp.rst \
user/babeld.rst \
user/snmp.rst \
user/pim.rst \
user/ripngd.rst \
user/snmptrap.rst \
user/glossary.rst \
mpls/ChangeLog.opaque.txt \
mpls/ospfd.conf \
mpls/cli_summary.txt \
mpls/opaque_lsa.txt \
figures/frr-logo.png \
figures/fig-vnc-commercial-route-reflector.dia \
figures/ospf_api_msghdr.png \
figures/fig-normal-processing.txt \
figures/fig-vnc-gw-rr.txt \
figures/fig-vnc-mesh.dia \
figures/frr-logo-medium.png \
figures/git_branches.svg \
figures/fig-vnc-commercial-route-reflector.txt \
figures/fig_topologies_rs.txt \
figures/git_branches.png \
figures/fig-vnc-mesh.txt \
figures/ospf_api_msgs1.png \
figures/fig-vnc-redundant-route-reflectors.txt \
figures/fig-vnc-commercial-route-reflector.png \
figures/fig-vnc-gw.png \
figures/fig_topologies_rs.png \
figures/fig_topologies_full.txt \
figures/fig-vnc-frr-route-reflector.txt \
figures/fig-normal-processing.dia \
figures/fig-vnc-redundant-route-reflectors.png \
figures/fig-vnc-frr-route-reflector.dia \
figures/fig_topologies_full.png \
figures/fig-vnc-redundant-route-reflectors.dia \
figures/fig-normal-processing.png \
figures/fig-rs-processing.dia \
figures/ospf_api_msgs2.png \
figures/fig-vnc-gw.dia \
figures/fig-rs-processing.txt \
figures/frr-logo-icon.png \
figures/ospf_api_architecture.png \
figures/fig-vnc-gw.txt \
figures/fig-rs-processing.png \
figures/frr-icon.svg \
figures/fig_topologies_rs.dia \
figures/fig-vnc-frr-route-reflector.png \
figures/fig-vnc-gw-rr.png \
figures/fig-vnc-gw-rr.dia \
figures/fig_topologies_full.dia \
figures/frr-logo-small.png \
figures/fig-vnc-mesh.png

View File

@ -1,257 +0,0 @@
@node Packet Binary Dump Format
@appendix Packet Binary Dump Format
FRR can dump routing protocol packet into file with a binary format
(@pxref{Dump BGP packets and table}).
It seems to be better that we share the MRT's header format for
backward compatibility with MRT's dump logs. We should also define the
binary format excluding the header, because we must support both IP
v4 and v6 addresses as socket addresses and / or routing entries.
In the last meeting, we discussed to have a version field in the
header. But Masaki told us that we can define new `type' value rather
than having a `version' field, and it seems to be better because we
don't need to change header format.
Here is the common header format. This is same as that of MRT.
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Subtype |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
If `type' is PROTOCOL_BGP4MP_ET, the common header format will
contain an additional microsecond field (RFC6396 2011).
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Subtype |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Microsecond |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE, and
Address Family == IP (version 4)
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source AS number | Destination AS number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Interface Index | Address Family |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Old State | New State |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
Where State is the value defined in RFC1771.
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE,
and Address Family == IP version 6
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source AS number | Destination AS number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Interface Index | Address Family |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Old State | New State |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_MESSAGE,
and Address Family == IP (version 4)
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source AS number | Destination AS number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Interface Index | Address Family |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BGP Message Packet |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
Where BGP Message Packet is the whole contents of the
BGP4 message including header portion.
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_MESSAGE,
and Address Family == IP version 6
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source AS number | Destination AS number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Interface Index | Address Family |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BGP Message Packet |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_ENTRY,
and Address Family == IP (version 4)
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| View # | Status |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time Last Change |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address Family | SAFI | Next-Hop-Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Hop Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Prefix Length | Address Prefix [variable] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BGP Attribute [variable length] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_ENTRY,
and Address Family == IP version 6
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| View # | Status |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time Last Change |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address Family | SAFI | Next-Hop-Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Hop Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Hop Address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Hop Address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Hop Address (Cont'd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Prefix Length | Address Prefix [variable] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address Prefix (cont'd) [variable] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BGP Attribute [variable length] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
BGP4 Attribute must not contain MP_UNREACH_NLRI.
If BGP Attribute has MP_REACH_NLRI field, it must has
zero length NLRI, e.g., MP_REACH_NLRI has only Address
Family, SAFI and next-hop values.
If `type' is PROTOCOL_BGP4MP and `subtype' is BGP4MP_SNAPSHOT,
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| View # | File Name [variable] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example
The file specified in "File Name" contains all routing entries,
which are in the format of ``subtype == BGP4MP_ENTRY''.
@example
@group
Constants:
/* type value */
#define MSG_PROTOCOL_BGP4MP 16
#define MSG_PROTOCOL_BGP4MP_ET 17
/* subtype value */
#define BGP4MP_STATE_CHANGE 0
#define BGP4MP_MESSAGE 1
#define BGP4MP_ENTRY 2
#define BGP4MP_SNAPSHOT 3
@end group
@end example

View File

@ -1,212 +0,0 @@
@c -*-texinfo-*-
@c This is part of the FRR Manual.
@c @value{COPYRIGHT_STR}
@c See file frr.texi for copying conditions.
@node Babel
@chapter Babel
Babel is an interior gateway protocol that is suitable both for wired
networks and for wireless mesh networks. Babel has been described as
``RIP on speed'' --- it is based on the same principles as RIP, but
includes a number of refinements that make it react much faster to
topology changes without ever counting to infinity, and allow it to
perform reliable link quality estimation on wireless links. Babel is
a double-stack routing protocol, meaning that a single Babel instance
is able to perform routing for both IPv4 and IPv6.
FRR implements Babel as described in RFC6126.
@menu
* Configuring babeld::
* Babel configuration::
* Babel redistribution::
* Show Babel information::
* Babel debugging commands::
@end menu
@node Configuring babeld, Babel configuration, Babel, Babel
@section Configuring babeld
The @command{babeld} daemon can be invoked with any of the common
options (@pxref{Common Invocation Options}).
The @command{zebra} daemon must be running before @command{babeld} is
invoked. Also, if @command{zebra} is restarted then @command{babeld}
must be too.
Configuration of @command{babeld} is done in its configuration file
@file{babeld.conf}.
@node Babel configuration, Babel redistribution, Configuring babeld, Babel
@section Babel configuration
@deffn Command {router babel} {}
@deffnx Command {no router babel} {}
Enable or disable Babel routing.
@end deffn
@deffn Command {babel resend-delay <20-655340>} {}
Specifies the time after which important messages are resent when
avoiding a black-hole. The default is 2000@dmn{ms}.
@end deffn
@deffn Command {babel diversity} {}
@deffnx Command {no babel diversity} {}
Enable or disable routing using radio frequency diversity. This is
highly recommended in networks with many wireless nodes.
If you enable this, you will probably want to set @code{babel
diversity-factor} and @code{babel channel} below.
@end deffn
@deffn Command {babel diversity-factor <1-256>} {}
Sets the multiplicative factor used for diversity routing, in units of
1/256; lower values cause diversity to play a more important role in
route selection. The default it 256, which means that diversity plays
no role in route selection; you will probably want to set that to 128
or less on nodes with multiple independent radios.
@end deffn
@deffn {Babel Command} {network @var{ifname}} {}
@deffnx {Babel Command} {no network @var{ifname}} {}
Enable or disable Babel on the given interface.
@end deffn
@deffn {Interface Command} {babel wired} {}
@deffnx {Interface Command} {babel wireless} {}
Specifies whether this interface is wireless, which disables a number
of optimisations that are only correct on wired interfaces.
Specifying @code{wireless} (the default) is always correct, but may
cause slower convergence and extra routing traffic.
@end deffn
@deffn {Interface Command} {babel split-horizon}
@deffnx {Interface Command} {no babel split-horizon}
Specifies whether to perform split-horizon on the interface.
Specifying @code{no babel split-horizon} is always correct, while
@code{babel split-horizon} is an optimisation that should only be used
on symmetric and transitive (wired) networks. The default is
@code{babel split-horizon} on wired interfaces, and @code{no babel
split-horizon} on wireless interfaces. This flag is reset when the
wired/wireless status of an interface is changed.
@end deffn
@deffn {Interface Command} {babel hello-interval <20-655340>}
Specifies the time in milliseconds between two scheduled hellos. On
wired links, Babel notices a link failure within two hello intervals;
on wireless links, the link quality value is reestimated at every
hello interval. The default is 4000@dmn{ms}.
@end deffn
@deffn {Interface Command} {babel update-interval <20-655340>}
Specifies the time in milliseconds between two scheduled updates.
Since Babel makes extensive use of triggered updates, this can be set
to fairly high values on links with little packet loss. The default
is 20000@dmn{ms}.
@end deffn
@deffn {Interface Command} {babel channel <1-254>}
@deffnx {Interface Command} {babel channel interfering}
@deffnx {Interface Command} {babel channel noninterfering}
Set the channel number that diversity routing uses for this interface
(see @code{babel diversity} above). Noninterfering interfaces are
assumed to only interfere with themselves, interfering interfaces are
assumed to interfere with all other channels except noninterfering
channels, and interfaces with a channel number interfere with
interfering interfaces and interfaces with the same channel number.
The default is @samp{babel channel interfering} for wireless
interfaces, and @samp{babel channel noninterfering} for wired
interfaces. This is reset when the wired/wireless status of an
interface is changed.
@end deffn
@deffn {Interface Command} {babel rxcost <1-65534>}
Specifies the base receive cost for this interface. For wireless
interfaces, it specifies the multiplier used for computing the ETX
reception cost (default 256); for wired interfaces, it specifies the
cost that will be advertised to neighbours. This value is reset when
the wired/wireless attribute of the interface is changed.
Do not use this command unless you know what you are doing; in most
networks, acting directly on the cost using route maps is a better
technique.
@end deffn
@deffn {Interface Command} {babel rtt-decay <1-256>}
This specifies the decay factor for the exponential moving average of
RTT samples, in units of 1/256. Higher values discard old samples
faster. The default is 42.
@end deffn
@deffn {Interface Command} {babel rtt-min <1-65535>}
This specifies the minimum RTT, in milliseconds, starting from which we
increase the cost to a neighbour. The additional cost is linear in (rtt
- rtt-min ). The default is 10@dmn{ms}.
@end deffn
@deffn {Interface Command} {babel rtt-max <1-65535>}
This specifies the maximum RTT, in milliseconds, above which we don't
increase the cost to a neighbour. The default is 120@dmn{ms}.
@end deffn
@deffn {Interface Command} {babel max-rtt-penalty <0-65535>}
This specifies the maximum cost added to a neighbour because of RTT,
i.e. when the RTT is higher or equal than rtt-max. The default is 0,
which effectively disables the use of a RTT-based cost.
@end deffn
@deffn {Interface Command} {babel enable-timestamps}
@deffnx {Interface Command} {no babel enable-timestamps}
Enable or disable sending timestamps with each Hello and IHU message in
order to compute RTT values. The default is @code{no babel
enable-timestamps}.
@end deffn
@deffn {Babel Command} {babel resend-delay <20-655340>}
Specifies the time in milliseconds after which an ``important''
request or update will be resent. The default is 2000@dmn{ms}. You
probably don't want to tweak this value.
@end deffn
@deffn {Babel Command} {babel smoothing-half-life <0-65534>}
Specifies the time constant, in seconds, of the smoothing algorithm
used for implementing hysteresis. Larger values reduce route
oscillation at the cost of very slightly increasing convergence time.
The value 0 disables hysteresis, and is suitable for wired networks.
The default is 4@dmn{s}.
@end deffn
@node Babel redistribution, Show Babel information, Babel configuration, Babel
@section Babel redistribution
@deffn {Babel command} {redistribute @var{<ipv4|ipv6>} @var{kind}}
@deffnx {Babel command} {no redistribute @var{<ipv4|ipv6>} @var{kind}}
Specify which kind of routes should be redistributed into Babel.
@end deffn
@node Show Babel information, Babel debugging commands, Babel redistribution, Babel
@section Show Babel information
@deffn {Command} {show babel route} {}
@deffnx {Command} {show babel route A.B.C.D}
@deffnx {Command} {show babel route X:X::X:X}
@deffnx {Command} {show babel route A.B.C.D/M}
@deffnx {Command} {show babel route X:X::X:X/M}
@deffnx {Command} {show babel interface} {}
@deffnx {Command} {show babel interface @var{ifname}} {}
@deffnx {Command} {show babel neighbor} {}
@deffnx {Command} {show babel parameters} {}
These commands dump various parts of @command{babeld}'s internal state.
@end deffn
@node Babel debugging commands, , Show Babel information, Babel
@section Babel debugging commands
@deffn {Babel Command} {debug babel @var{kind}} {}
@deffnx {Babel Command} {no debug babel @var{kind}} {}
Enable or disable debugging messages of a given kind. @var{kind} can
be one of @samp{common}, @samp{kernel}, @samp{filter}, @samp{timeout},
@samp{interface}, @samp{route} or @samp{all}. Note that if you have
compiled with the NO_DEBUG flag, then these commands aren't available.
@end deffn

View File

@ -1,642 +0,0 @@
@node Basic commands
@chapter Basic commands
There are five routing daemons in use, and there is one manager daemon.
These daemons may be located on separate machines from the manager
daemon. Each of these daemons will listen on a particular port for
incoming VTY connections. The routing daemons are:
@itemize @bullet
@item @command{ripd}, @command{ripngd}, @command{ospfd}, @command{ospf6d}, @command{bgpd}
@item @command{zebra}
@end itemize
The following sections discuss commands common to all the routing
daemons.
@menu
* Config Commands:: Commands used in config files
* Terminal Mode Commands:: Common commands used in a VTY
* Common Invocation Options:: Starting the daemons
* Loadable Module Support:: Using extension modules
* Virtual Terminal Interfaces:: Interacting with the daemons
@end menu
@node Config Commands
@section Config Commands
@cindex Configuration files for running the software
@c A -not configuration files for installing the software
@cindex Files for running configurations
@cindex Modifying the herd's behavior
@cindex Getting the herd running
@menu
* Basic Config Commands:: Some of the generic config commands
* Sample Config File:: An example config file
@end menu
In a config file, you can write the debugging options, a vty's password,
routing daemon configurations, a log file name, and so forth. This
information forms the initial command set for a routing beast as it is
starting.
Config files are generally found in:
@itemize @w{}
@item @file{@value{INSTALL_PREFIX_ETC}/*.conf}
@end itemize
Each of the daemons has its own
config file. For example, zebra's default config file name is:
@itemize @w{}
@item @file{@value{INSTALL_PREFIX_ETC}/zebra.conf}
@end itemize
The daemon name plus @file{.conf} is the default config file name. You
can specify a config file using the @kbd{-f} or @kbd{--config-file}
options when starting the daemon.
@node Basic Config Commands
@subsection Basic Config Commands
@deffn Command {hostname @var{hostname}} {}
Set hostname of the router.
@end deffn
@deffn Command {password @var{password}} {}
Set password for vty interface. If there is no password, a vty won't
accept connections.
@end deffn
@deffn Command {enable password @var{password}} {}
Set enable password.
@end deffn
@deffn Command {log trap @var{level}} {}
@deffnx Command {no log trap} {}
These commands are deprecated and are present only for historical compatibility.
The log trap command sets the current logging level for all enabled
logging destinations, and it sets the default for all future logging commands
that do not specify a level. The normal default
logging level is debugging. The @code{no} form of the command resets
the default level for future logging commands to debugging, but it does
not change the logging level of existing logging destinations.
@end deffn
@deffn Command {log stdout} {}
@deffnx Command {log stdout @var{level}} {}
@deffnx Command {no log stdout} {}
Enable logging output to stdout.
If the optional second argument specifying the
logging level is not present, the default logging level (typically debugging,
but can be changed using the deprecated @code{log trap} command) will be used.
The @code{no} form of the command disables logging to stdout.
The @code{level} argument must have one of these values:
emergencies, alerts, critical, errors, warnings, notifications, informational, or debugging. Note that the existing code logs its most important messages
with severity @code{errors}.
@end deffn
@deffn Command {log file @var{filename}} {}
@deffnx Command {log file @var{filename} @var{level}} {}
@deffnx Command {no log file} {}
If you want to log into a file, please specify @code{filename} as
in this example:
@example
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,
but can be changed using the deprecated @code{log trap} command) will be used.
The @code{no} form of the command disables logging to a file.
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/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
@deffn Command {log syslog} {}
@deffnx Command {log syslog @var{level}} {}
@deffnx Command {no log syslog} {}
Enable logging output to syslog.
If the optional second argument specifying the
logging level is not present, the default logging level (typically debugging,
but can be changed using the deprecated @code{log trap} command) will be used.
The @code{no} form of the command disables logging to syslog.
@end deffn
@deffn Command {log monitor} {}
@deffnx Command {log monitor @var{level}} {}
@deffnx Command {no log monitor} {}
Enable logging output to vty terminals that have enabled logging
using the @code{terminal monitor} command.
By default, monitor logging is enabled at the debugging level, but this
command (or the deprecated @code{log trap} command) can be used to change
the monitor logging level.
If the optional second argument specifying the
logging level is not present, the default logging level (typically debugging,
but can be changed using the deprecated @code{log trap} command) will be used.
The @code{no} form of the command disables logging to terminal monitors.
@end deffn
@deffn Command {log facility @var{facility}} {}
@deffnx Command {no log facility} {}
This command changes the facility used in syslog messages. The default
facility is @code{daemon}. The @code{no} form of the command resets
the facility to the default @code{daemon} facility.
@end deffn
@deffn Command {log record-priority} {}
@deffnx Command {no log record-priority} {}
To include the severity in all messages logged to a file, to stdout, or to
a terminal monitor (i.e. anything except syslog),
use the @code{log record-priority} global configuration command.
To disable this option, use the @code{no} form of the command. By default,
the severity level is not included in logged messages. Note: some
versions of syslogd (including Solaris) can be configured to include
the facility and level in the messages emitted.
@end deffn
@deffn Command {log timestamp precision @var{<0-6>}} {}
@deffnx Command {no log timestamp precision} {}
This command sets the precision of log message timestamps to the
given number of digits after the decimal point. Currently,
the value must be in the range 0 to 6 (i.e. the maximum precision
is microseconds).
To restore the default behavior (1-second accuracy), use the
@code{no} form of the command, or set the precision explicitly to 0.
@example
@group
log timestamp precision 3
@end group
@end example
In this example, the precision is set to provide timestamps with
millisecond accuracy.
@end deffn
@deffn Command {log commands} {}
This command enables the logging of all commands typed by a user to
all enabled log destinations. The note that logging includes full
command lines, including passwords. Once set, command logging can only
be turned off by restarting the daemon.
@end deffn
@deffn Command {service password-encryption} {}
Encrypt password.
@end deffn
@deffn Command {service advanced-vty} {}
Enable advanced mode VTY.
@end deffn
@deffn Command {service terminal-length @var{<0-512>}} {}
Set system wide line configuration. This configuration command applies
to all VTY interfaces.
@end deffn
@deffn Command {line vty} {}
Enter vty configuration mode.
@end deffn
@deffn Command {banner motd default} {}
Set default motd string.
@end deffn
@deffn Command {no banner motd} {}
No motd banner string will be printed.
@end deffn
@deffn {Line Command} {exec-timeout @var{minute}} {}
@deffnx {Line Command} {exec-timeout @var{minute} @var{second}} {}
Set VTY connection timeout value. When only one argument is specified
it is used for timeout value in minutes. Optional second argument is
used for timeout value in seconds. Default timeout value is 10 minutes.
When timeout value is zero, it means no timeout.
@end deffn
@deffn {Line Command} {no exec-timeout} {}
Do not perform timeout at all. This command is as same as
@command{exec-timeout 0 0}.
@end deffn
@deffn {Line Command} {access-class @var{access-list}} {}
Restrict vty connections with an access list.
@end deffn
@node Sample Config File
@subsection Sample Config File
Below is a sample configuration file for the zebra daemon.
@example
@group
!
! Zebra configuration file
!
hostname Router
password zebra
enable password zebra
!
log stdout
!
!
@end group
@end example
'!' and '#' are comment characters. If the first character of the word
is one of the comment characters then from the rest of the line forward
will be ignored as a comment.
@example
password zebra!password
@end example
If a comment character is not the first character of the word, it's a
normal character. So in the above example '!' will not be regarded as a
comment and the password is set to 'zebra!password'.
@node Terminal Mode Commands
@section Terminal Mode Commands
@deffn Command {write terminal} {}
Displays the current configuration to the vty interface.
@end deffn
@deffn Command {write file} {}
Write current configuration to configuration file.
@end deffn
@deffn Command {configure terminal} {}
Change to configuration mode. This command is the first step to
configuration.
@end deffn
@deffn Command {terminal length @var{<0-512>}} {}
Set terminal display length to @var{<0-512>}. If length is 0, no
display control is performed.
@end deffn
@deffn Command {who} {}
Show a list of currently connected vty sessions.
@end deffn
@deffn Command {list} {}
List all available commands.
@end deffn
@deffn Command {show version} {}
Show the current version of @value{PACKAGE_NAME} and its build host information.
@end deffn
@deffn Command {show logging} {}
Shows the current configuration of the logging system. This includes
the status of all logging destinations.
@end deffn
@deffn Command {logmsg @var{level} @var{message}} {}
Send a message to all logging destinations that are enabled for messages
of the given severity.
@end deffn
@node Common Invocation Options
@section Common Invocation Options
@c COMMON_OPTIONS
@c OPTIONS section of the man page
These options apply to all @value{PACKAGE_NAME} daemons.
@table @samp
@item -d
@itemx --daemon
Runs in daemon mode.
@item -f @var{file}
@itemx --config_file=@var{file}
Set configuration file name.
@item -h
@itemx --help
Display this help and exit.
@item -i @var{file}
@itemx --pid_file=@var{file}
Upon startup the process identifier of the daemon is written to a file,
typically in @file{/var/run}. This file can be used by the init system
to implement commands such as @command{@dots{}/init.d/zebra status},
@command{@dots{}/init.d/zebra restart} or @command{@dots{}/init.d/zebra
stop}.
The file name is an run-time option rather than a configure-time option
so that multiple routing daemons can be run simultaneously. This is
useful when using @value{PACKAGE_NAME} to implement a routing looking glass. One
machine can be used to collect differing routing views from differing
points in the network.
@item -A @var{address}
@itemx --vty_addr=@var{address}
Set the VTY local address to bind to. If set, the VTY socket will only
be bound to this address.
@item -P @var{port}
@itemx --vty_port=@var{port}
Set the VTY TCP port number. If set to 0 then the TCP VTY sockets will not
be opened.
@item -u @var{user}
@itemx --vty_addr=@var{user}
Set the user and group to run as.
@item -v
@itemx --version
Print program version.
@end table
@node Loadable Module Support
@section Loadable Module Support
FRR supports loading extension modules at startup. Loading, reloading or
unloading modules at runtime is not supported (yet). To load a module, use
the following command line option at daemon startup:
@table @samp
@item -M @var{module:options}
@itemx --module @var{module:options}
Load the specified module, optionally passing options to it. If the module
name contains a slash (/), it is assumed to be a full pathname to a file to
be loaded. If it does not contain a slash, the
@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of
the given name; first with the daemon name prepended (e.g. @code{zebra_mod}
for @code{mod}), then without the daemon name prepended.
This option is available on all daemons, though some daemons may not have
any modules available to be loaded.
@end table
@subsection The SNMP Module
If SNMP is enabled during compile-time and installed as part of the package,
the @code{snmp} module can be loaded for the @command{zebra},
@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons.
The module ignores any options passed to it. Refer to @ref{SNMP Support}
for information on its usage.
@subsection The FPM Module
If FPM is enabled during compile-time and installed as part of the package,
the @code{fpm} module can be loaded for the @command{zebra} daemon. This
provides the Forwarding Plane Manager ("FPM") API.
The module expects its argument to be either @code{netlink} or
@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the
default, and @code{protobuf} may not be available if the module was built
without protobuf support. Refer to @ref{zebra FIB push interface} for more
information.
@node Virtual Terminal Interfaces
@section Virtual Terminal Interfaces
VTY -- Virtual Terminal [aka TeletYpe] Interface is a command line
interface (CLI) for user interaction with the routing daemon.
@menu
* VTY Overview:: Basics about VTYs
* VTY Modes:: View, Enable, and Other VTY modes
* VTY CLI Commands:: Commands for movement, edition, and management
@end menu
@node VTY Overview
@subsection VTY Overview
VTY stands for Virtual TeletYpe interface. It means you can connect to
the daemon via the telnet protocol.
To enable a VTY interface, you have to setup a VTY password. If there
is no VTY password, one cannot connect to the VTY interface at all.
@example
@group
% telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello, this is @value{PACKAGE_NAME} (version @value{PACKAGE_VERSION})
@value{COPYRIGHT_STR}
User Access Verification
Password: XXXXX
Router> ?
enable Turn on privileged commands
exit Exit current mode and down to previous mode
help Description of the interactive help system
list Print command list
show Show running system information
who Display who is on a vty
Router> enable
Password: XXXXX
Router# configure terminal
Router(config)# interface eth0
Router(config-if)# ip address 10.0.0.1/8
Router(config-if)# ^Z
Router#
@end group
@end example
'?' is very useful for looking up commands.
@node VTY Modes
@subsection VTY Modes
There are three basic VTY modes:
@menu
* VTY View Mode:: Mode for read-only interaction
* VTY Enable Mode:: Mode for read-write interaction
* VTY Other Modes:: Special modes (tftp, etc)
@end menu
There are commands that may be restricted to specific VTY modes.
@node VTY View Mode
@subsubsection VTY View Mode
@c to be written (gpoul)
This mode is for read-only access to the CLI. One may exit the mode by
leaving the system, or by entering @code{enable} mode.
@node VTY Enable Mode
@subsubsection VTY Enable Mode
@c to be written (gpoul)
This mode is for read-write access to the CLI. One may exit the mode by
leaving the system, or by escaping to view mode.
@node VTY Other Modes
@subsubsection VTY Other Modes
@c to be written (gpoul)
This page is for describing other modes.
@node VTY CLI Commands
@subsection VTY CLI Commands
Commands that you may use at the command-line are described in the following
three subsubsections.
@menu
* CLI Movement Commands:: Commands for moving the cursor about
* CLI Editing Commands:: Commands for changing text
* CLI Advanced Commands:: Other commands, session management and so on
@end menu
@node CLI Movement Commands
@subsubsection CLI Movement Commands
These commands are used for moving the CLI cursor. The @key{C} character
means press the Control Key.
@table @kbd
@item C-f
@itemx @key{RIGHT}
@kindex C-f
@kindex @key{RIGHT}
Move forward one character.
@item C-b
@itemx @key{LEFT}
@kindex C-b
@kindex @key{LEFT}
Move backward one character.
@item M-f
@kindex M-f
Move forward one word.
@item M-b
@kindex M-b
Move backward one word.
@item C-a
@kindex C-a
Move to the beginning of the line.
@item C-e
@kindex C-e
Move to the end of the line.
@end table
@node CLI Editing Commands
@subsubsection CLI Editing Commands
These commands are used for editing text on a line. The @key{C}
character means press the Control Key.
@table @kbd
@item C-h
@itemx @key{DEL}
@kindex C-h
@kindex @key{DEL}
Delete the character before point.
@item C-d
@kindex C-d
Delete the character after point.
@item M-d
@kindex M-d
Forward kill word.
@item C-w
@kindex C-w
Backward kill word.
@item C-k
@kindex C-k
Kill to the end of the line.
@item C-u
@kindex C-u
Kill line from the beginning, erasing input.
@item C-t
@kindex C-t
Transpose character.
@end table
@node CLI Advanced Commands
@subsubsection CLI Advanced Commands
There are several additional CLI commands for command line completions,
insta-help, and VTY session management.
@table @kbd
@item C-c
@kindex C-c
Interrupt current input and moves to the next line.
@item C-z
@kindex C-z
End current configuration session and move to top node.
@item C-n
@itemx @key{DOWN}
@kindex C-n
@kindex @key{DOWN}
Move down to next line in the history buffer.
@item C-p
@itemx @key{UP}
@kindex C-p
@kindex @key{UP}
Move up to previous line in the history buffer.
@item TAB
@kindex @key{TAB}
Use command line completion by typing @key{TAB}.
@item ?
@kindex @key{?}
You can use command line help by typing @code{help} at the beginning of
the line. Typing @kbd{?} at any point in the line will show possible
completions.
@end table

View File

@ -1,132 +0,0 @@
.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
] [
.B \-M
.I module:options
]
.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\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBbgpd\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES
.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 nhrpd (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.

File diff suppressed because it is too large Load Diff

View File

@ -1,557 +0,0 @@
FRR Command Line Interface
==========================
Definition Grammar
------------------
This is a reference for the syntax used when defining new CLI commands. An
example definition is:
```
DEFUN (command_name,
command_name_cmd,
--> "example <command|line [interface]> DEFINITION...",
<..doc strings..>)
```
The arrowed part is the definition string.
Explicit syntax rules in Flex and Bison may be found in lib/command_lex.l and
lib/command_parse.y, respectively. If you can read BNF and regex those will be
more useful than this document.
If the parser is throwing syntax or other errors and you can't figure out why,
it's unlikely to be a bug in the parser. If the error message is not useful,
please file a bug for a better error message. If all else fails, read the token
definitions in the lexer source and the Bison BNF in the parser source.
Characters allowed in each token type:
Tokens
------
* `WORD` -- A token that begins with +, -, or a lowercase letter. It is
an unchanging part of the command and will only match itself.
Example: "show ip bgp", every token is a WORD.
* `IPV4` -- 'A.B.C.D', matches an IPv4 address.
* `IPV6` -- 'X:X::X:X', matches an IPv6 address.
* `IPV4_PREFIX` -- 'A.B.C.D/M', matches an IPv4 prefix in CIDR notation.
* `IPV6_PREFIX` -- 'X:X::X:X/M', matches an IPv6 prefix in CIDR notation.
* `MAC` -- 'M:A:C', matches a 48-bit mac address
* `MAC_PREFIX` -- 'M:A:C/M', matches a 48-bit mac address with a mask
* `VARIABLE` -- Begins with a capital letter. Matches any input.
* `RANGE` -- Numeric range delimited by parentheses, e.g. (-100 - 100) or
(10-20). Will only match numbers in the range.
Rules
-----
* `<angle|brackets>` -- Contain sequences of tokens separated by pipes and
provide mutual exclusion. Sequences may contain
`<mutual|exclusion>` but not as the first token.
Disallowed: `"example <<a|b> c|d>"`
Allowed: `"example <a c|b c|d>"`
* `[square brackets]` -- Contains sequences of tokens that are optional (can be
omitted). `[<a|b>]` can be shortened to `[a|b]`.
* `{curly|braces}` -- similar to angle brackets, but instead of mutual
exclusion, curly braces indicate that one or more of the
pipe-separated sequences may be provided in any order.
* `VARIADICS...` -- Any token which accepts input (so anything except WORD)
and that occurs as the last token of a line may be
followed by an ellipsis, which indicates that input
matching the token may be repeated an unlimited number
of times.
* `$name` -- Specify a variable name for the preceding token. See
"Variable Names" below.
Some general notes:
* Options are allowed at the beginning of the command. The developer is
entreated to use these extremely sparingly. They are most useful for
implementing the 'no' form of configuration commands. Please think carefully
before using them for anything else. There is usually a better solution, even
if it is just separating out the command definition into separate ones.
* The developer should judiciously apply separation of concerns when defining
CLI. CLI definitions for two unrelated or vaguely related commands or
configuration items should be defined in separate commands. Clarity is
preferred over LOC (within reason).
* The maximum number of space-separated tokens that can be entered is presently
limited to 256. Please keep this limit in mind when implementing new CLI.
Variable Names
--------------
The parser tries to fill the "varname" field on each token. This can happen
either manually or automatically. Manual specifications work by appending
`"$name"` after the input specifier:
```
foo bar$cmd WORD$name A.B.C.D$ip
```
Note that you can also assign variable names to fixed input tokens, this can
be useful if multiple commands share code. You can also use "$name" after a
multiple-choice option:
```
foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode
```
The variable name is in this case assigned to the last token in each of the
branches.
Automatic assignment of variable names works by applying the following rules:
- manual names always have priority
- a "[no]" at the beginning receives "no" as varname on the "no" token
- VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned lowercase
version of the token text as varname, e.g. "ROUTE-MAP" becomes "route_map".
- other variable tokens (i.e. everything except "fixed") receive the text of
the preceding fixed token as varname, if one can be found. E.g.:
"ip route A.B.C.D/M INTERFACE" assigns "route" to the "A.B.C.D/M" token.
These rules should make it possible to avoid manual varname assignment in 90%
of the cases.
DEFPY
-----
`DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by
` python/clidef.py`. The python script parses the command definition string,
extracts variable names and types, and generates a C wrapper function that
parses the variables and passes them on. This means that in the CLI function
body, you will receive additional parameters with appropriate types.
This is best explained by an example:
```
DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...")
=>
func(self, vty, argc, argv, /* standard CLI arguments */
const char *no, /* unparsed "no" */
struct in_addr bar, /* parsed IP address */
const char *bar_str, /* unparsed IP address */
long num, /* parsed num */
const char *num_str) /* unparsed num */
```
Note that as documented in the previous section, "bar" is automatically
applied as variable name for "A.B.C.D". The python code then detects this
is an IP address argument and generates code to parse it into a
`struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`.
The range/number argument works in the same way with the explicitly given
variable name.
### Type rules
| Token(s) | Type | Value if omitted by user |
|--------------------------|-------------|--------------------------|
| `A.B.C.D` | `struct in_addr` | 0.0.0.0 |
| `X:X::X:X` | `struct in6_addr` | :: |
| `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL |
| `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL |
| `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL |
| `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL |
| `(0-9)` | `long` | 0 |
| `VARIABLE` | `const char *` | NULL |
| `word` | `const char *` | NULL |
| _all other_ | `const char *` | NULL |
Note the following details:
* not all parameters are pointers, some are passed as values.
* when the type is not `const char *`, there will be an extra `_str` argument
with type `const char *`.
* you can give a variable name not only to `VARIABLE` tokens but also to
`word` tokens (e.g. constant words). This is useful if some parts of a
command are optional. The type will be `const char *`.
* `[no]` will be passed as `const char *no`.
* pointers will be NULL when the argument is optional and the user did not
use it.
* if a parameter is not a pointer, but is optional and the user didn't use it,
the default value will be passed. Check the `_str` argument if you need to
determine whether the parameter was omitted.
* if the definition contains multiple parameters with the same variable name,
they will be collapsed into a single function parameter. The python code
will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and
choose a corresponding C type.
* the standard DEFUN parameters (self, vty, argc, argv) are still present and
can be used. A DEFUN can simply be **edited into a DEFPY without further
changes and it will still work**; this allows easy forward migration.
* a file may contain both DEFUN and DEFPY statements.
### Getting a parameter dump
The clidef.py script can be called to get a list of DEFUNs/DEFPYs with
the parameter name/type list:
```
lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null
```
The generated code is printed to stdout, the info dump to stderr. The
`--all-defun` argument will make it process DEFUN blocks as well as DEFPYs,
which is useful prior to converting some DEFUNs. **The dump does not list
the `_str` arguments** to keep the output shorter.
Note that the clidef.py script cannot be run with python directly, it needs
to be run with _clippy_ since the latter makes the CLI parser available.
### Include & Makefile requirements
A source file that uses DEFPY needs to include the `_clippy.c` file **before
all DEFPY statements**:
```
/* GPL header */
#include ...
...
#include "daemon/filename_clippy.c"
DEFPY(...)
DEFPY(...)
install_element(...)
```
This dependency needs to be marked in Makefile.am: (there is no ordering
requirement)
```
include ../common.am
# ...
# if linked into a LTLIBRARY (.la/.so):
filename.lo: filename_clippy.c
# if linked into an executable or static library (.a):
filename.o: filename_clippy.c
```
Doc Strings
-----------
Each token in a command definition should be documented with a brief doc
string that informs a user of the meaning and/or purpose of the subsequent
command tree. These strings are provided as the last parameter to DEFUN macros,
concatenated together and separated by an escaped newline ('\n'). These are
best explained by example.
```
DEFUN (config_terminal,
config_terminal_cmd,
"configure terminal",
"Configuration from vty interface\n"
"Configuration terminal\n")
```
The last parameter is split into two lines for readability. Two newline
delimited doc strings are present, one for each token in the command. The
second string documents the functionality of the 'terminal' command in the
'configure' tree.
Note that the first string, for 'configure' does not contain documentation for
'terminal'. This is because the CLI is best envisioned as a tree, with tokens
defining branches. An imaginary 'start' token is the root of every command in a
CLI node. Each subsequent written token descends into a subtree, so the
documentation for that token ideally summarizes all the functionality contained
in the subtree.
A consequence of this structure is that the developer must be careful to use
the same doc strings when defining multiple commands that are part of the same
tree. Commands which share prefixes must share the same doc strings for those
prefixes. On startup the parser will generate warnings if it notices
inconsistent doc strings. Behavior is undefined; the same token may show up
twice in completions, with different doc strings, or it may show up once with a
random doc string. Parser warnings should be heeded and fixed to avoid
confusing users.
The number of doc strings provided must be equal to the amount of tokens
present in the command definition, read left to right, ignoring any special
constructs.
In the examples below, each arrowed token needs a doc string.
```
"show ip bgp"
^ ^ ^
"command <foo|bar> [example]"
^ ^ ^ ^
```
Data Structures
---------------
On startup, the CLI parser sequentially parses each command string definition
and constructs a directed graph with each token forming a node. This graph is
the basis of the entire CLI system. It is used to match user input in order to
generate command completions and match commands to functions.
There is one graph per CLI node (not the same as a graph node in the CLI
graph). The CLI node struct keeps a reference to its graph (see lib/command.h).
While most of the graph maintains the form of a tree, special constructs
outlined in the Rules section introduce some quirks. <>, [] and {} form
self-contained 'subgraphs'. Each subgraph is a tree except that all of the
'leaves' actually share a child node. This helps with minimizing graph size and
debugging.
As an example, the subgraph generated by <foo|bar> looks like this:
.
.
|
+----+---+
+--- -+ FORK +----+
| +--------+ |
+--v---+ +--v---+
| foo | | bar |
+--+---+ +--+---+
| +------+ |
+------> JOIN <-----+
+---+--+
|
.
.
FORK and JOIN nodes are plumbing nodes that don't correspond to user input.
They're necessary in order to deduplicate these constructs where applicable.
Options follow the same form, except that there is an edge from the FORK node
to the JOIN node.
Keywords follow the same form, except that there is an edge from JOIN to FORK.
Because of this the CLI graph cannot be called acyclic. There is special logic
in the input matching code that keeps a stack of paths already taken through
the node in order to disallow following the same path more than once.
Variadics are a bit special; they have an edge back to themselves, which allows
repeating the same input indefinitely.
The leaves of the graph are nodes that have no out edges. These nodes are
special; their data section does not contain a token, as most nodes do, or
NULL, as in FORK/JOIN nodes, but instead has a pointer to a cmd_element. All
paths through the graph that terminate on a leaf are guaranteed to be defined
by that command. When a user enters a complete command, the command matcher
tokenizes the input and executes a DFS on the CLI graph. If it is
simultaneously able to exhaust all input (one input token per graph node), and
then find exactly one leaf connected to the last node it reaches, then the
input has matched the corresponding command and the command is executed. If it
finds more than one node, then the command is ambiguous (more on this in
deduplication). If it cannot exhaust all input, the command is unknown. If it
exhausts all input but does not find an edge node, the command is incomplete.
The parser uses an incremental strategy to build the CLI graph for a node. Each
command is parsed into its own graph, and then this graph is merged into the
overall graph. During this merge step, the parser makes a best-effort attempt
to remove duplicate nodes. If it finds a node in the overall graph that is
equal to a node in the corresponding position in the command graph, it will
intelligently merge the properties from the node in the command graph into the
already-existing node. Subgraphs are also checked for isomorphism and merged
where possible. The definition of whether two nodes are 'equal' is based on the
equality of some set of token properties; read the parser source for the most
up-to-date definition of equality.
When the parser is unable to deduplicate some complicated constructs, this
can result in two identical paths through separate parts of the graph. If
this occurs and the user enters input that matches these paths, they will
receive an 'ambiguous command' error and will be unable to execute the command.
Most of the time the parser can detect and warn about duplicate commands, but
it will not always be able to do this. Hence care should be taken before
defining a new command to ensure it is not defined elsewhere.
Command handlers
----------------
The block that follows a CLI definition is executed when a user enters input
that matches the definition. Its function signature looks like this:
int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]);
The first argument is the command definition struct. The last argument is an
ordered array of tokens that correspond to the path taken through the graph,
and the argument just prior to that is the length of the array.
The arrangement of the token array has changed from the prior incarnation of
the CLI system. In the old system, missing arguments were padded with NULLs so
that the same parts of a command would show up at the same indices regardless
of what was entered. The new system does not perform such padding and therefore
it is generally _incorrect_ to assume consistent indices in this array. As a
simple example:
Command definition:
```
command [foo] <bar|baz>
```
User enters:
```
command foo bar
```
Array:
```
[0] -> command
[1] -> foo
[2] -> bar
```
User enters:
```
command baz
```
Array:
```
[0] -> command
[1] -> baz
```
Command abbreviation & matching priority
----------------------------------------
As in the prior implementation, it is possible for users to elide parts of
tokens when the CLI matcher does not need them to make an unambiguous match.
This is best explained by example.
Command definitions:
```
command dog cow
command dog crow
```
User input:
```
c d c -> ambiguous command
c d co -> match "command dog cow"
```
In the new implementation, this functionality has improved. Where previously
the parser would stop at the first ambiguous token, it will now look ahead and
attempt to disambiguate based on tokens later on in the input string.
Command definitions:
```
show ip bgp A.B.C.D
show ipv6 bgp X:X::X:X
```
User enters:
```
s i b 4.3.2.1 -> match "show ip bgp A.B.C.D"
s i b ::e0 -> match "show ipv6 bgp X:X::X:X"
```
Previously both of these commands would be ambiguous since 'i' does not
explicitly select either 'ip' or 'ipv6'. However, since the user later provides
a token that matches only one of the commands (an IPv4 or IPv6 address) the
parser is able to look ahead and select the appropriate command. This has some
implications for parsing the argv*[] that is passed to the command handler.
Now consider a command definition such as:
```
command <foo|VAR>
```
'foo' only matches the string 'foo', but 'VAR' matches any input, including
'foo'. Who wins? In situations like this the matcher will always choose the
'better' match, so 'foo' will win.
Consider also:
```
show <ip|ipv6> foo
```
User input:
```
show ip foo
```
'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will win.
struct cmd_token
----------------
```
/* Command token struct. */
struct cmd_token
{
enum cmd_token_type type; // token type
u_char attr; // token attributes
bool allowrepeat; // matcher allowed to match token repetitively?
char *text; // token text
char *desc; // token description
long long min, max; // for ranges
char *arg; // user input that matches this token
char *varname; // variable name
};
```
This struct is used in the CLI graph to match input against. It is also used to
pass user input to command handler functions, as it is frequently useful for
handlers to have access to that information. When a command is matched, the
sequence of cmd_tokens that form the matching path are duplicated and placed in
order into argv*[]. Before this happens the ->arg field is set to point at the
snippet of user input that matched it.
For most nontrivial commands the handler function will need to determine which
of the possible matching inputs was entered. Previously this was done by
looking at the first few characters of input. This is now considered an
anti-pattern and should be avoided. Instead, the ->type or ->text fields for
this logic. The ->type field can be used when the possible inputs differ in
type. When the possible types are the same, use the ->text field. This field
has the full text of the corresponding token in the definition string and using
it makes for much more readable code. An example is helpful.
Command definition:
```
command <(1-10)|foo|BAR>
```
In this example, the user may enter any one of:
* an integer between 1 and 10
* "foo"
* anything at all
If the user enters "command f", then:
```
argv[1]->type == WORD_TKN
argv[1]->arg == "f"
argv[1]->text == "foo"
```
Range tokens have some special treatment; a token with ->type == RANGE_TKN will
have the ->min and ->max fields set to the bounding values of the range.
Permutations
------------
Finally, it is sometimes useful to check all the possible combinations of input
that would match an arbitrary definition string. There is a tool in tools/
called 'permutations' that reads CLI definition strings on stdin and prints out
all matching input permutations. It also dumps a text representation of the
graph, which is more useful for debugging than anything else. It looks like
this:
```
$ ./permutations "show [ip] bgp [<view|vrf> WORD]"
show ip bgp view WORD
show ip bgp vrf WORD
show ip bgp
show bgp view WORD
show bgp vrf WORD
show bgp
```
This functionality is also built into VTY/VTYSH; the 'list permutations'
command will list all possible matching input permutations in the current CLI
node.

View File

@ -1,21 +0,0 @@
@c -*- texinfo -*-
@c @configure_input@
@c Set variables
@set PACKAGE_NAME @PACKAGE_NAME@
@set PACKAGE_TARNAME @PACKAGE_TARNAME@
@set PACKAGE_STRING @PACKAGE_STRING@
@set PACKAGE_URL @PACKAGE_URL@
@set PACKAGE_VERSION @PACKAGE_VERSION@
@set AUTHORS Kunihiro Ishiguro, et al.
@set COPYRIGHT_YEAR 1999-2005
@set COPYRIGHT_STR Copyright @copyright{} @value{COPYRIGHT_YEAR} @value{AUTHORS}
@c These may vary with installation environment.
@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
@set INSTALL_PREFIX_SBIN @CFG_SBIN@
@set INSTALL_PREFIX_STATE @CFG_STATE@
@set INSTALL_PREFIX_MODULES @CFG_MODULE@
@set INSTALL_USER @enable_user@
@set INSTALL_GROUP @enable_group@
@set INSTALL_VTY_GROUP @enable_vty_group@

View File

@ -1,46 +1,67 @@
Building FRR on CentOS 6 from Git Source CentOS 6
======================================== ========================================
(As an alternative to this installation, you may prefer to create a FRR (As an alternative to this installation, you may prefer to create a FRR
rpm package yourself and install that package instead. See instructions rpm package yourself and install that package instead. See instructions
in redhat/README.rpm_build.md on how to build a rpm package) in redhat/README.rpm\_build.md on how to build a rpm package)
Instructions are tested with `CentOS 6.8` on `x86_64` platform Instructions are tested with ``CentOS 6.8`` on ``x86_64`` platform
Warning:
--------
``CentOS 6`` is very old and not fully supported by the FRR community
anymore. Building FRR takes multiple manual steps to update the build
system with newer packages than what's available from the archives.
However, the built packages can still be installed afterwards on
a standard ``CentOS 6`` without any special packages.
Support for CentOS 6 is now on a best-effort base by the community.
CentOS 6 restrictions: CentOS 6 restrictions:
---------------------- ----------------------
- PIMd is not supported on `CentOS 6`. Upgrade to `CentOS 7` if PIMd is - PIMd is not supported on ``CentOS 6``. Upgrade to ``CentOS 7`` if
needed PIMd is needed
- MPLS is not supported on `CentOS 6`. MPLS requires Linux Kernel 4.5 or - MPLS is not supported on ``CentOS 6``. MPLS requires Linux Kernel 4.5
higher (LDP can be built, but may have limited use without MPLS) or higher (LDP can be built, but may have limited use without MPLS)
- Zebra is unable to detect what bridge/vrf an interface is associcated - Zebra is unable to detect what bridge/vrf an interface is associcated
with (IFLA_INFO_SLAVE_KIND does not exist in the kernel headers, you with (IFLA\_INFO\_SLAVE\_KIND does not exist in the kernel headers,
can use a newer kernel + headers to get this functionality) you can use a newer kernel + headers to get this functionality)
- frr_reload.py will not work, as this requires Python 2.7, and CentOS 6 - frr\_reload.py will not work, as this requires Python 2.7, and CentOS
only has 2.6. You can install Python 2.7 via IUS, but it won't work 6 only has 2.6. You can install Python 2.7 via IUS, but it won't work
properly unless you compile and install the ipaddr package for it. properly unless you compile and install the ipaddr package for it.
- Building the package requires Sphinx >= 1.1. Only a non-standard
package provides a newer sphinx and requires manual installation
(see below)
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
sudo yum install git autoconf automake libtool make gawk \ sudo yum install git autoconf automake libtool make gawk \
readline-devel texinfo net-snmp-devel groff pkgconfig \ readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel flex epel-release perl-XML-LibXML \ json-c-devel pam-devel flex epel-release perl-XML-LibXML \
c-ares-devel c-ares-devel
Install newer version of bison (CentOS 6 package source is too old) from Install newer version of bison (CentOS 6 package source is too old) from
CentOS 7 CentOS 7
::
sudo yum install rpm-build sudo yum install rpm-build
curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm
rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm
sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm
rm -rf rpmbuild rm -rf rpmbuild
Install newer version of autoconf and automake (Package versions are too old) Install newer version of autoconf and automake (Package versions are too
old)
::
curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
tar xvf autoconf-2.69.tar.gz tar xvf autoconf-2.69.tar.gz
@ -49,7 +70,7 @@ Install newer version of autoconf and automake (Package versions are too old)
make make
sudo make install sudo make install
cd .. cd ..
curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
tar xvf automake-1.15.tar.gz tar xvf automake-1.15.tar.gz
cd automake-1.15 cd automake-1.15
@ -58,35 +79,69 @@ Install newer version of autoconf and automake (Package versions are too old)
sudo make install sudo make install
cd .. cd ..
Install `Python 2.7` in parallel to default 2.6. Install ``Python 2.7`` in parallel to default 2.6. Make sure you've
Make sure you've install EPEL (`epel-release` as above). Then install current install EPEL (``epel-release`` as above). Then install current
`python27`, `python27-devel` and `pytest` ``python27``, ``python27-devel`` and ``pytest``
::
sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm
sudo yum install python27 python27-pip python27-devel sudo yum install python27 python27-pip python27-devel
sudo pip2.7 install pytest sudo pip2.7 install pytest
Please note that `CentOS 6` needs to keep python pointing to version 2.6 Please note that ``CentOS 6`` needs to keep python pointing to version
for `yum` to keep working, so don't create a symlink for python2.7 to python 2.6 for ``yum`` to keep working, so don't create a symlink for python2.7
to python
Install newer ``Sphinx-Build`` based on ``Python 2.7``
Create a new repo ``/etc/yum.repos.d/puias6.repo`` with the following contents:
::
### Name: RPM Repository for RHEL 6 - PUIAS (used for Sphinx-Build)
### URL: http://springdale.math.ias.edu/data/puias/computational
[puias-computational]
name = RPM Repository for RHEL 6 - Sphinx-Build
baseurl = http://springdale.math.ias.edu/data/puias/computational/$releasever/$basearch
#mirrorlist =
enabled = 1
protect = 0
gpgkey =
gpgcheck = 0
Update rpm database & Install newer sphinx
::
sudo yum update
sudo yum install python27-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FRRouting suite" -d /var/run/frr frr -c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -116,11 +171,15 @@ an example.)
--enable-babeld \ --enable-babeld \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make SPHINXBUILD=sphinx-build2.7
make check PYTHON=/usr/bin/python2.7 make check PYTHON=/usr/bin/python2.7 SPHINXBUILD=sphinx-build2.7
sudo make install sudo make SPHINXBUILD=sphinx-build2.7 install
Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
### Create empty FRR configuration files
sudo mkdir /var/log/frr sudo mkdir /var/log/frr
sudo mkdir /etc/frr sudo mkdir /etc/frr
sudo touch /etc/frr/zebra.conf sudo touch /etc/frr/zebra.conf
@ -138,20 +197,28 @@ an example.)
sudo chown frr:frrvt /etc/frr/vtysh.conf sudo chown frr:frrvt /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf sudo chmod 640 /etc/frr/*.conf
### Install daemon config file Install daemon config file
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 644 redhat/daemons /etc/frr/ sudo install -p -m 644 redhat/daemons /etc/frr/
sudo chown frr:frr /etc/frr/daemons sudo chown frr:frr /etc/frr/daemons
### Edit /etc/frr/daemons as needed to select the required daemons Edit /etc/frr/daemons as needed to select the required daemons
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Look for the section with `watchfrr_enable=...` and `zebra=...` etc. Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
Enable the daemons as required by changing the value to `yes` Enable the daemons as required by changing the value to ``yes``
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and set the following values (ignore the other Edit ``/etc/sysctl.conf`` and set the following values (ignore the other
settings) settings)
::
# Controls IP packet forwarding # Controls IP packet forwarding
net.ipv4.ip_forward = 1 net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
@ -161,14 +228,28 @@ settings)
Load the modifed sysctl's on the system: Load the modifed sysctl's on the system:
::
sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
### Add init.d startup files Add init.d startup files
~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 755 redhat/frr.init /etc/init.d/frr sudo install -p -m 755 redhat/frr.init /etc/init.d/frr
sudo chkconfig --add frr sudo chkconfig --add frr
### Enable frr daemon at startup Enable frr daemon at startup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo chkconfig frr on sudo chkconfig frr on
### Start FRR manually (or reboot) Start FRR manually (or reboot)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo /etc/init.d/frr start sudo /etc/init.d/frr start

View File

@ -1,44 +1,53 @@
Building FRR on CentOS 7 from Git Source CentOS 7
======================================== ========================================
(As an alternative to this installation, you may prefer to create a FRR (As an alternative to this installation, you may prefer to create a FRR
rpm package yourself and install that package instead. See instructions rpm package yourself and install that package instead. See instructions
in redhat/README.rpm_build.md on how to build a rpm package) in redhat/README.rpm\_build.md on how to build a rpm package)
CentOS 7 restrictions: CentOS 7 restrictions:
---------------------- ----------------------
- MPLS is not supported on `CentOS 7` with default kernel. MPLS requires - MPLS is not supported on ``CentOS 7`` with default kernel. MPLS
Linux Kernel 4.5 or higher (LDP can be built, but may have limited use requires Linux Kernel 4.5 or higher (LDP can be built, but may have
without MPLS) limited use without MPLS)
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
sudo yum install git autoconf automake libtool make gawk \ sudo yum install git autoconf automake libtool make gawk \
readline-devel texinfo net-snmp-devel groff pkgconfig \ readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \ json-c-devel pam-devel bison flex pytest c-ares-devel \
perl-XML-LibXML python-devel systemd-devel perl-XML-LibXML python-devel systemd-devel python-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FRRouting suite" -d /var/run/frr frr -c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -73,7 +82,11 @@ an example.)
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /var/log/frr sudo mkdir /var/log/frr
sudo mkdir /etc/frr sudo mkdir /etc/frr
sudo touch /etc/frr/zebra.conf sudo touch /etc/frr/zebra.conf
@ -92,20 +105,28 @@ an example.)
sudo chown frr:frrvt /etc/frr/vtysh.conf sudo chown frr:frrvt /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf sudo chmod 640 /etc/frr/*.conf
### Install daemon config file Install daemon config file
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 644 redhat/daemons /etc/frr/ sudo install -p -m 644 redhat/daemons /etc/frr/
sudo chown frr:frr /etc/frr/daemons sudo chown frr:frr /etc/frr/daemons
### Edit /etc/frr/daemons as needed to select the required daemons Edit /etc/frr/daemons as needed to select the required daemons
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Look for the section with `watchfrr_enable=...` and `zebra=...` etc. Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
Enable the daemons as required by changing the value to `yes` Enable the daemons as required by changing the value to ``yes``
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a new file `/etc/sysctl.d/90-routing-sysctl.conf` with the Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the
following content: following content:
::
# Sysctl for routing # Sysctl for routing
# #
# Routing: We need to forward packets # Routing: We need to forward packets
@ -114,17 +135,35 @@ following content:
Load the modifed sysctl's on the system: Load the modifed sysctl's on the system:
::
sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
### Install frr Service and redhat init files Install frr Service and redhat init files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
### Register the systemd files Register the systemd files
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo systemctl preset frr.service sudo systemctl preset frr.service
### Enable required frr at startup Enable required frr at startup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo systemctl enable frr sudo systemctl enable frr
### Reboot or start FRR manually Reboot or start FRR manually
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo systemctl start frr sudo systemctl start frr

View File

@ -1,33 +1,40 @@
Building FRR on Debian 8 from Git Source Debian 8
======================================== ========================================
Debian 8 restrictions: Debian 8 restrictions:
---------------------- ----------------------
- MPLS is not supported on `Debian 8` with default kernel. MPLS requires - MPLS is not supported on ``Debian 8`` with default kernel. MPLS
Linux Kernel 4.5 or higher (LDP can be built, but may have limited use requires Linux Kernel 4.5 or higher (LDP can be built, but may have
without MPLS) limited use without MPLS)
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
sudo apt-get install git autoconf automake libtool make gawk \ sudo apt-get install git autoconf automake libtool make gawk \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex \ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
python-pip libc-ares-dev python3-dev python-pip libc-ares-dev python3-dev python3-sphinx
Install newer pytest (>3.0) from pip Install newer pytest (>3.0) from pip
sudo pip install pytest ::
sudo pip install pytest
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 92 frr
sudo addgroup --system --gid 85 frrvty sudo addgroup --system --gid 85 frrvty
@ -35,10 +42,14 @@ any packages**
--gecos "FRR suite" --shell /bin/false frr --gecos "FRR suite" --shell /bin/false frr
sudo usermod -a -G frrvty frr sudo usermod -a -G frrvty frr
### Download Source, configure and compile it Download Source, configure and compile it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -63,12 +74,15 @@ an example.)
--enable-fpm \ --enable-fpm \
--enable-ldpd \ --enable-ldpd \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 775 -o frr -g frrvty -d /etc/frr sudo install -m 775 -o frr -g frrvty -d /etc/frr
@ -84,11 +98,14 @@ an example.)
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and uncomment the following values (ignore the Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
other settings) other settings)
::
# Uncomment the next line to enable packet forwarding for IPv4 # Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 net.ipv4.ip_forward=1
@ -97,35 +114,43 @@ other settings)
# based on Router Advertisements for this host # based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
**Reboot** or use `sysctl -p` to apply the same config to the running system **Reboot** or use ``sysctl -p`` to apply the same config to the running
system
### Troubleshooting Troubleshooting
~~~~~~~~~~~~~~~
**Local state directory** **Local state directory**
The local state directory must exist and have the correct permissions applied The local state directory must exist and have the correct permissions
for the frrouting daemons to start. In the above ./configure example the applied for the frrouting daemons to start. In the above ./configure
local state directory is set to /var/run/frr (--localstatedir=/var/run/frr) example the local state directory is set to /var/run/frr
Debian considers /var/run/frr to be temporary and this is removed after a (--localstatedir=/var/run/frr) Debian considers /var/run/frr to be
reboot. temporary and this is removed after a reboot.
When using a different local state directory you need to create the new When using a different local state directory you need to create the new
directory and change the ownership to the frr user, for example: directory and change the ownership to the frr user, for example:
::
mkdir /var/opt/frr mkdir /var/opt/frr
chown frr /var/opt/frr chown frr /var/opt/frr
**Shared library error** **Shared library error**
If you try and start any of the frrouting daemons you may see the below error If you try and start any of the frrouting daemons you may see the below
due to the frrouting shared library directory not being found: error due to the frrouting shared library directory not being found:
::
./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory ./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
The fix is to add the following line to /etc/ld.so.conf which will continue to The fix is to add the following line to /etc/ld.so.conf which will
reference the library directory after the system reboots. To load the library continue to reference the library directory after the system reboots. To
directory path immediately run the ldconfig command after adding the line to load the library directory path immediately run the ldconfig command
the file eg: after adding the line to the file eg:
::
echo include /usr/local/lib >> /etc/ld.so.conf echo include /usr/local/lib >> /etc/ld.so.conf
ldconfig ldconfig

View File

@ -1,4 +1,4 @@
Building FRR on Debian 9 from Git Source Debian 9
======================================== ========================================
Install required packages Install required packages
@ -6,17 +6,22 @@ Install required packages
Add packages: Add packages:
::
sudo apt-get install git autoconf automake libtool make \ sudo apt-get install git autoconf automake libtool make \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex \ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
python-pip libc-ares-dev python3-dev python-pytest python-pip libc-ares-dev python3-dev python-pytest python3-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 92 frr
sudo addgroup --system --gid 85 frrvty sudo addgroup --system --gid 85 frrvty
@ -24,10 +29,14 @@ any packages**
--gecos "FRR suite" --shell /bin/false frr --gecos "FRR suite" --shell /bin/false frr
sudo usermod -a -G frrvty frr sudo usermod -a -G frrvty frr
### Download Source, configure and compile it Download Source, configure and compile it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
git checkout stable/3.0 git checkout stable/3.0
@ -53,12 +62,15 @@ an example.)
--enable-fpm \ --enable-fpm \
--enable-ldpd \ --enable-ldpd \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 755 -o frr -g frr -d /var/opt/frr sudo install -m 755 -o frr -g frr -d /var/opt/frr
@ -75,11 +87,14 @@ an example.)
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and uncomment the following values (ignore the Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
other settings) other settings)
::
# Uncomment the next line to enable packet forwarding for IPv4 # Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 net.ipv4.ip_forward=1
@ -88,21 +103,29 @@ other settings)
# based on Router Advertisements for this host # based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
**Reboot** or use `sysctl -p` to apply the same config to the running system **Reboot** or use ``sysctl -p`` to apply the same config to the running
system
### Troubleshooting Troubleshooting
---------------
**Shared library error** Shared library error
~~~~~~~~~~~~~~~~~~~~
If you try and start any of the frrouting daemons you may see the below error If you try and start any of the frrouting daemons you may see the below
due to the frrouting shared library directory not being found: error due to the frrouting shared library directory not being found:
./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory ::
The fix is to add the following line to /etc/ld.so.conf which will continue to ./zebra: error while loading shared libraries: libfrr.so.0: cannot open
reference the library directory after the system reboots. To load the library shared object file: No such file or directory
directory path immediately run the ldconfig command after adding the line to
the file eg:
echo include /usr/local/lib >> /etc/ld.so.conf The fix is to add the following line to /etc/ld.so.conf which will
ldconfig continue to reference the library directory after the system reboots. To
load the library directory path immediately run the ldconfig command
after adding the line to the file eg:
::
echo include /usr/local/lib >> /etc/ld.so.conf
ldconfig

View File

@ -1,37 +1,46 @@
Building FRR on Fedora 24 from Git Source Fedora 24
========================================= =========================================
(As an alternative to this installation, you may prefer to create a FRR (As an alternative to this installation, you may prefer to create a FRR
rpm package yourself and install that package instead. See instructions rpm package yourself and install that package instead. See instructions
in redhat/README.rpm_build.md on how to build a rpm package) in redhat/README.rpm\_build.md on how to build a rpm package)
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
sudo dnf install git autoconf automake libtool make gawk \ sudo dnf install git autoconf automake libtool make gawk \
readline-devel texinfo net-snmp-devel groff pkgconfig \ readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel perl-XML-LibXML pytest bison flex \ json-c-devel pam-devel perl-XML-LibXML pytest bison flex \
c-ares-devel python3-devel c-ares-devel python3-devel python3-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not **This assumes you want to build and install FRR from source and not
using any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FRRouting suite" -d /var/run/frr frr -c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -60,12 +69,16 @@ an example.)
--enable-eigrpd \ --enable-eigrpd \
--enable-babeld \ --enable-babeld \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /var/log/frr sudo mkdir /var/log/frr
sudo mkdir /etc/frr sudo mkdir /etc/frr
sudo touch /etc/frr/zebra.conf sudo touch /etc/frr/zebra.conf
@ -85,21 +98,28 @@ an example.)
sudo chown frr:frrvt /etc/frr/vtysh.conf sudo chown frr:frrvt /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf sudo chmod 640 /etc/frr/*.conf
### Install daemon config file Install daemon config file
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 644 redhat/daemons /etc/frr/ sudo install -p -m 644 redhat/daemons /etc/frr/
sudo chown frr:frr /etc/frr/daemons sudo chown frr:frr /etc/frr/daemons
### Edit /etc/frr/daemons as needed to select the required daemons Edit /etc/frr/daemons as needed to select the required daemons
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Look for the section with `watchfrr_enable=...` and `zebra=...` etc. Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
Enable the daemons as required by changing the value to `yes` Enable the daemons as required by changing the value to ``yes``
### Enable IP & IPv6 forwarding (and MPLS) Enable IP & IPv6 forwarding (and MPLS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a new file `/etc/sysctl.d/90-routing-sysctl.conf` with the Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the
following content: following content: (Please make sure to list all interfaces with
(Please make sure to list all interfaces with required MPLS similar required MPLS similar to ``net.mpls.conf.eth0.input=1``)
to `net.mpls.conf.eth0.input=1`)
::
# Sysctl for routing # Sysctl for routing
# #
@ -115,9 +135,14 @@ to `net.mpls.conf.eth0.input=1`)
Load the modifed sysctl's on the system: Load the modifed sysctl's on the system:
::
sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
Create a new file `/etc/modules-load.d/mpls.conf` with the following content: Create a new file ``/etc/modules-load.d/mpls.conf`` with the following
content:
::
# Load MPLS Kernel Modules # Load MPLS Kernel Modules
mpls-router mpls-router
@ -125,14 +150,28 @@ Create a new file `/etc/modules-load.d/mpls.conf` with the following content:
And load the kernel modules on the running system: And load the kernel modules on the running system:
::
sudo modprobe mpls-router mpls-iptunnel sudo modprobe mpls-router mpls-iptunnel
### Install frr Service and redhat init files Install frr Service and redhat init files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
### Enable required frr at startup Enable required frr at startup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo systemctl enable frr sudo systemctl enable frr
### Reboot or start FRR manually Reboot or start FRR manually
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo systemctl start frr sudo systemctl start frr

View File

@ -1,46 +1,53 @@
Building FRR on FreeBSD 10 from Git Source FreeBSD 10
========================================== ==========================================
FreeBSD 10 restrictions: FreeBSD 10 restrictions:
------------------------ ------------------------
- MPLS is not supported on `FreeBSD`. MPLS requires a Linux Kernel - MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel
(4.5 or higher). LDP can be built, but may have limited use (4.5 or higher). LDP can be built, but may have limited use without
without MPLS MPLS
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages: (Allow the install of the package managment tool if this
(Allow the install of the package managment tool if this is first package is first package install and asked)
install and asked)
::
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
bison flex py27-pytest c-ares python3 bison flex py27-pytest c-ares python3 py-sphinx
Make sure there is no /usr/bin/flex preinstalled (and use the newly Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): installed in /usr/local/bin): (FreeBSD frequently provides a older flex
(FreeBSD frequently provides a older flex as part of the base OS which as part of the base OS which takes preference in path)
takes preference in path)
::
rm -f /usr/bin/flex rm -f /usr/bin/flex
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not **This assumes you want to build and install FRR from source and not
using any packages** using any packages**
### Add frr group and user Add frr group and user
~~~~~~~~~~~~~~~~~~~~~~
::
pw groupadd frr -g 101 pw groupadd frr -g 101
pw groupadd frrvty -g 102 pw groupadd frrvty -g 102
pw adduser frr -g 101 -u 101 -G 102 -c "FRR suite" \ pw adduser frr -g 101 -u 101 -G 102 -c "FRR suite" \
-d /usr/local/etc/frr -s /usr/sbin/nologin -d /usr/local/etc/frr -s /usr/sbin/nologin
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -63,12 +70,16 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /usr/local/etc/frr sudo mkdir /usr/local/etc/frr
sudo touch /usr/local/etc/frr/zebra.conf sudo touch /usr/local/etc/frr/zebra.conf
sudo touch /usr/local/etc/frr/bgpd.conf sudo touch /usr/local/etc/frr/bgpd.conf
@ -83,12 +94,16 @@ an example)
sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf
sudo chmod 640 /usr/local/etc/frr/*.conf sudo chmod 640 /usr/local/etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/sysctl.conf`: Add the following lines to the end of ``/etc/sysctl.conf``:
::
# Routing: We need to forward packets # Routing: We need to forward packets
net.inet.ip.forwarding=1 net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1 net.inet6.ip6.forwarding=1
**Reboot** or use `sysctl` to apply the same config to the running system **Reboot** or use ``sysctl`` to apply the same config to the running
system

View File

@ -1,37 +1,42 @@
Building FRR on FreeBSD 11 from Git Source FreeBSD 11
========================================== ==========================================
FreeBSD 11 restrictions: FreeBSD 11 restrictions:
------------------------ ------------------------
- MPLS is not supported on `FreeBSD`. MPLS requires a Linux Kernel - MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel
(4.5 or higher). LDP can be built, but may have limited use (4.5 or higher). LDP can be built, but may have limited use without
without MPLS MPLS
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages: (Allow the install of the package managment tool if this
(Allow the install of the package managment tool if this is first package is first package install and asked)
install and asked)
::
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
bison flex py27-pytest c-ares python3 bison flex py27-pytest c-ares python3 py-sphinx
Make sure there is no /usr/bin/flex preinstalled (and use the newly Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): installed in /usr/local/bin): (FreeBSD frequently provides a older flex
(FreeBSD frequently provides a older flex as part of the base OS which as part of the base OS which takes preference in path)
takes preference in path)
::
rm -f /usr/bin/flex rm -f /usr/bin/flex
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not **This assumes you want to build and install FRR from source and not
using any packages** using any packages**
### Add frr group and user Add frr group and user
~~~~~~~~~~~~~~~~~~~~~~
::
pw groupadd frr -g 101 pw groupadd frr -g 101
pw groupadd frrvty -g 102 pw groupadd frrvty -g 102
@ -41,6 +46,8 @@ using any packages**
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -63,12 +70,16 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /usr/local/etc/frr sudo mkdir /usr/local/etc/frr
sudo touch /usr/local/etc/frr/zebra.conf sudo touch /usr/local/etc/frr/zebra.conf
sudo touch /usr/local/etc/frr/bgpd.conf sudo touch /usr/local/etc/frr/bgpd.conf
@ -83,12 +94,16 @@ an example)
sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf
sudo chmod 640 /usr/local/etc/frr/*.conf sudo chmod 640 /usr/local/etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/sysctl.conf`: Add the following lines to the end of ``/etc/sysctl.conf``:
::
# Routing: We need to forward packets # Routing: We need to forward packets
net.inet.ip.forwarding=1 net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1 net.inet6.ip6.forwarding=1
**Reboot** or use `sysctl` to apply the same config to the running system **Reboot** or use ``sysctl`` to apply the same config to the running
system

View File

@ -1,32 +1,39 @@
Building FRR on FreeBSD 9 from Git Source FreeBSD 9
========================================= =========================================
FreeBSD 9 restrictions: FreeBSD 9 restrictions:
----------------------- -----------------------
- MPLS is not supported on `FreeBSD`. MPLS requires a Linux Kernel - MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel
(4.5 or higher). LDP can be built, but may have limited use (4.5 or higher). LDP can be built, but may have limited use without
without MPLS MPLS
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages: (Allow the install of the package managment tool if this
(Allow the install of the package managment tool if this is first package is first package install and asked)
install and asked)
::
pkg install -y git autoconf automake libtool gmake gawk \ pkg install -y git autoconf automake libtool gmake gawk \
pkgconf texinfo json-c bison flex py27-pytest c-ares \ pkgconf texinfo json-c bison flex py27-pytest c-ares \
python3 python3 py-sphinx
Make sure there is no /usr/bin/flex preinstalled (and use the newly Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): installed in /usr/local/bin): (FreeBSD frequently provides a older flex
(FreeBSD frequently provides a older flex as part of the base OS which as part of the base OS which takes preference in path)
takes preference in path)
::
rm -f /usr/bin/flex rm -f /usr/bin/flex
For building with clang (instead of gcc), upgrade clang from 3.4 default to 3.6 *This is needed to build FreeBSD packages as well - for packages clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during compile) For building with clang (instead of gcc), upgrade clang from 3.4 default
to 3.6 *This is needed to build FreeBSD packages as well - for packages
clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during
compile)
::
pkg install clang36 pkg install clang36
pkg delete clang34 pkg delete clang34
@ -39,7 +46,10 @@ Get FRR, compile it and install it (from Git)
**This assumes you want to build and install FRR from source and not **This assumes you want to build and install FRR from source and not
using any packages** using any packages**
### Add frr group and user Add frr group and user
~~~~~~~~~~~~~~~~~~~~~~
::
pw groupadd frr -g 101 pw groupadd frr -g 101
pw groupadd frrvty -g 102 pw groupadd frrvty -g 102
@ -49,6 +59,8 @@ using any packages**
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -71,12 +83,16 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /usr/local/etc/frr sudo mkdir /usr/local/etc/frr
sudo touch /usr/local/etc/frr/zebra.conf sudo touch /usr/local/etc/frr/zebra.conf
sudo touch /usr/local/etc/frr/bgpd.conf sudo touch /usr/local/etc/frr/bgpd.conf
@ -91,12 +107,16 @@ an example)
sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf
sudo chmod 640 /usr/local/etc/frr/*.conf sudo chmod 640 /usr/local/etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/sysctl.conf`: Add the following lines to the end of ``/etc/sysctl.conf``:
::
# Routing: We need to forward packets # Routing: We need to forward packets
net.inet.ip.forwarding=1 net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1 net.inet6.ip6.forwarding=1
**Reboot** or use `sysctl` to apply the same config to the running system **Reboot** or use ``sysctl`` to apply the same config to the running
system

View File

@ -0,0 +1,108 @@
OpenWRT/LEDE
=============================================
- for the moment because of cross compile problems, master is not
supported, only up to 3.0
- LDP can't be built because of missing Perl-XML-LibXML in OpenWRT/LEDE
tree
Prepare build environment
-------------------------
https://lede-project.org/docs/guide-developer/install-buildsystem
for
Ubuntu 12.04LTS:
::
sudo apt-get install build-essential subversion git-core \
libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc \
libxml-parser-perl mercurial bzr ecj cvs unzip python3-sphinx
Ubuntu 64bit:
::
sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \
gawk gcc-multilib flex git-core gettext libssl-dev python3-sphinx
Debian 8 Jessie:
::
sudo apt-get install build-essential libncurses5-dev gawk git subversion \
libssl-dev gettext unzip zlib1g-dev file python python3-sphinx
Debian 9 Stretch:
::
sudo apt-get install build-essential libncurses5-dev gawk git subversion \
libssl-dev gettext zlib1g-dev python3-sphinx
Centos x86-64 (some packages require EPEL):
::
yum install subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \
ncurses-devel zlib-devel zlib-static make patch unzip glibc glibc-devel \
perl-ExtUtils-MakeMaker glibc-static quilt ncurses-libs sed sdcc bison \
intltool sharutils wget git-core openssl-devel xz python-sphinx
Fedora 24 - 64Bit:
::
dnf install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext git-core \
unzip ncurses-devel ncurses-compat-libs zlib-devel zlib-static make \
flex patch perl-ExtUtils-MakeMaker perl-Thread-Queue glibc glibc-devel \
glibc-static quilt sed sdcc intltool sharutils bison wget openssl-devel \
python3-sphinx
Get LEDE Sources (from Git)
---------------------------
LEDE and OpenWRT is planned to remerge and won't cover the similar
OpenWRT build As normal user: git clone
https://git.lede-project.org/source.git lede cd lede ./scripts/feeds
update -a ./scripts/feeds install -a cd feeds/routing git pull origin
pull/319/head ln -s ../../../feeds/routing/frr/
../../package/feeds/routing/ cd ../.. make menuconfig
Select the needed target then select needed packages in Network ->
Routing and Redirection -> frr, exit and save
::
make or make package/frr/compile
It may be possible that on first build ``make package/frr/compile`` not
to work and it may be needed to run a ``make`` for the entire build
envronment, add V=s for debugging
Work with sources
-----------------
To update the rc1 version or add other options, the Makefile is found in
feeds/routing/frr
edit: PKG\_VERSION:= PKG\_SOURCE\_VERSION:=
Usage
-----
Edit ``/usr/sbin/frr.init`` and add/remove the daemons name in section
DAEMONS= or don't install unneded packages For example: zebra bgpd ldpd
isisd nhrpd ospfd ospf6d pimd ripd ripngd
Enable the serivce
~~~~~~~~~~~~~~~~~~
- service frr enable
Start the service
~~~~~~~~~~~~~~~~~
- service frr start

View File

@ -1,50 +1,66 @@
Building FRR on NetBSD 6 from Git Source NetBSD 6
======================================== ========================================
NetBSD 6 restrictions: NetBSD 6 restrictions:
---------------------- ----------------------
- MPLS is not supported on `NetBSD`. MPLS requires a Linux Kernel - MPLS is not supported on ``NetBSD``. MPLS requires a Linux Kernel
(4.5 or higher). LDP can be built, but may have limited use (4.5 or higher). LDP can be built, but may have limited use without
without MPLS MPLS
Install required packages Install required packages
------------------------- -------------------------
Configure Package location: Configure Package location:
::
PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All" PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
export PKG_PATH export PKG_PATH
Add packages: Add packages:
::
sudo pkg_add git autoconf automake libtool gmake gawk openssl \ sudo pkg_add git autoconf automake libtool gmake gawk openssl \
pkg-config json-c python27 py27-test python35 pkg-config json-c python27 py27-test python35 py-sphinx
Install SSL Root Certificates (for git https access): Install SSL Root Certificates (for git https access):
::
sudo pkg_add mozilla-rootcerts sudo pkg_add mozilla-rootcerts
sudo touch /etc/openssl/openssl.cnf sudo touch /etc/openssl/openssl.cnf
sudo mozilla-rootcerts install sudo mozilla-rootcerts install
Select default Python and py.test Select default Python and py.test
::
sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
------------------------------------------------ ---------------------------------------------
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -g 93 frrvty sudo groupadd -g 93 frrvty
sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \ sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
-d /nonexistent -s /sbin/nologin frr -d /nonexistent -s /sbin/nologin frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -67,12 +83,16 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /var/log/frr sudo mkdir /var/log/frr
sudo mkdir /usr/pkg/etc/frr sudo mkdir /usr/pkg/etc/frr
sudo touch /usr/pkg/etc/frr/zebra.conf sudo touch /usr/pkg/etc/frr/zebra.conf
@ -88,23 +108,35 @@ an example)
sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
sudo chmod 640 /usr/pkg/etc/frr/*.conf sudo chmod 640 /usr/pkg/etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/sysctl.conf`: Add the following lines to the end of ``/etc/sysctl.conf``:
::
# Routing: We need to forward packets # Routing: We need to forward packets
net.inet.ip.forwarding=1 net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1 net.inet6.ip6.forwarding=1
**Reboot** or use `sysctl` to apply the same config to the running system **Reboot** or use ``sysctl`` to apply the same config to the running
system
Install rc.d init files
~~~~~~~~~~~~~~~~~~~~~~~
::
### Install rc.d init files
cp pkgsrc/*.sh /etc/rc.d/ cp pkgsrc/*.sh /etc/rc.d/
chmod 555 /etc/rc.d/*.sh chmod 555 /etc/rc.d/*.sh
### Enable FRR processes Enable FRR processes
~~~~~~~~~~~~~~~~~~~~
(Enable the required processes only) (Enable the required processes only)
::
echo "zebra=YES" >> /etc/rc.conf echo "zebra=YES" >> /etc/rc.conf
echo "bgpd=YES" >> /etc/rc.conf echo "bgpd=YES" >> /etc/rc.conf
echo "ospfd=YES" >> /etc/rc.conf echo "ospfd=YES" >> /etc/rc.conf

View File

@ -1,44 +1,57 @@
Building FRR on NetBSD 7 from Git Source NetBSD 7
======================================== ========================================
NetBSD 7 restrictions: NetBSD 7 restrictions:
---------------------- ----------------------
- MPLS is not supported on `NetBSD`. MPLS requires a Linux Kernel - MPLS is not supported on ``NetBSD``. MPLS requires a Linux Kernel
(4.5 or higher). LDP can be built, but may have limited use (4.5 or higher). LDP can be built, but may have limited use without
without MPLS MPLS
Install required packages Install required packages
------------------------- -------------------------
::
sudo pkgin install git autoconf automake libtool gmake gawk openssl \ sudo pkgin install git autoconf automake libtool gmake gawk openssl \
pkg-config json-c python27 py27-test python35 pkg-config json-c python27 py27-test python35 py-sphinx
Install SSL Root Certificates (for git https access): Install SSL Root Certificates (for git https access):
::
sudo pkgin install mozilla-rootcerts sudo pkgin install mozilla-rootcerts
sudo touch /etc/openssl/openssl.cnf sudo touch /etc/openssl/openssl.cnf
sudo mozilla-rootcerts install sudo mozilla-rootcerts install
Select default Python and py.test Select default Python and py.test
::
sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
------------------------------------------------ ---------------------------------------------
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -g 93 frrvty sudo groupadd -g 93 frrvty
sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \ sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
-d /nonexistent -s /sbin/nologin frr -d /nonexistent -s /sbin/nologin frr
### Download Source, configure and compile it Download Source, configure and compile it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -61,12 +74,16 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo mkdir /usr/pkg/etc/frr sudo mkdir /usr/pkg/etc/frr
sudo touch /usr/pkg/etc/frr/zebra.conf sudo touch /usr/pkg/etc/frr/zebra.conf
sudo touch /usr/pkg/etc/frr/bgpd.conf sudo touch /usr/pkg/etc/frr/bgpd.conf
@ -81,23 +98,35 @@ an example)
sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
sudo chmod 640 /usr/pkg/etc/frr/*.conf sudo chmod 640 /usr/pkg/etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/sysctl.conf`: Add the following lines to the end of ``/etc/sysctl.conf``:
::
# Routing: We need to forward packets # Routing: We need to forward packets
net.inet.ip.forwarding=1 net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1 net.inet6.ip6.forwarding=1
**Reboot** or use `sysctl` to apply the same config to the running system **Reboot** or use ``sysctl`` to apply the same config to the running
system
Install rc.d init files
~~~~~~~~~~~~~~~~~~~~~~~
::
### Install rc.d init files
cp pkgsrc/*.sh /etc/rc.d/ cp pkgsrc/*.sh /etc/rc.d/
chmod 555 /etc/rc.d/*.sh chmod 555 /etc/rc.d/*.sh
### Enable FRR processes Enable FRR processes
~~~~~~~~~~~~~~~~~~~~
(Enable the required processes only) (Enable the required processes only)
::
echo "zebra=YES" >> /etc/rc.conf echo "zebra=YES" >> /etc/rc.conf
echo "bgpd=YES" >> /etc/rc.conf echo "bgpd=YES" >> /etc/rc.conf
echo "ospfd=YES" >> /etc/rc.conf echo "ospfd=YES" >> /etc/rc.conf

View File

@ -1,23 +1,28 @@
Building FRR on OmniOS (OpenSolaris) from Git Source OmniOS (OpenSolaris)
==================================================== ====================================================
OmniOS restrictions: OmniOS restrictions:
-------------------- --------------------
- MPLS is not supported on `OmniOS` or `Solaris`. MPLS requires a Linux - MPLS is not supported on ``OmniOS`` or ``Solaris``. MPLS requires a
Kernel (4.5 or higher). LDP can be built, but may have limited use Linux Kernel (4.5 or higher). LDP can be built, but may have limited
without MPLS use without MPLS
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
routeadm -e ipv4-forwarding routeadm -e ipv4-forwarding
routeadm -e ipv6-forwarding routeadm -e ipv6-forwarding
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
pkg install \ pkg install \
developer/build/autoconf \ developer/build/autoconf \
developer/build/automake \ developer/build/automake \
@ -32,10 +37,12 @@ Add packages:
library/idnkit/header-idnkit \ library/idnkit/header-idnkit \
system/header \ system/header \
system/library/math/header-math \ system/library/math/header-math \
git libtool gawk pkg-config git libtool gawk pkg-config
Add additional Solaris packages: Add additional Solaris packages:
::
pkgadd -d http://get.opencsw.org/now pkgadd -d http://get.opencsw.org/now
/opt/csw/bin/pkgutil -U /opt/csw/bin/pkgutil -U
/opt/csw/bin/pkgutil -y -i texinfo /opt/csw/bin/pkgutil -y -i texinfo
@ -45,33 +52,50 @@ Add additional Solaris packages:
Add libjson to Solaris equivalent of ld.so.conf Add libjson to Solaris equivalent of ld.so.conf
::
crle -l /opt/csw/lib -u crle -l /opt/csw/lib -u
Add pytest: Add pytest:
::
pip install pytest pip install pytest
Install Sphinx:::
pip install sphinx
Select Python 2.7 as default (required for pytest) Select Python 2.7 as default (required for pytest)
::
rm -f /usr/bin/python rm -f /usr/bin/python
ln -s /opt/csw/bin/python2.7 /usr/bin/python ln -s /opt/csw/bin/python2.7 /usr/bin/python
Fix PATH for all users and non-interactive sessions. Edit `/etc/default/login` Fix PATH for all users and non-interactive sessions. Edit
and add the following default PATH: ``/etc/default/login`` and add the following default PATH:
::
PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
Edit `~/.profile` and add the following default PATH: Edit ``~/.profile`` and add the following default PATH:
::
PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr group and user Add frr group and user
~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 93 frr sudo groupadd -g 93 frr
sudo groupadd -g 94 frrvty sudo groupadd -g 94 frrvty
@ -81,6 +105,8 @@ any packages**
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -106,12 +132,15 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
sudo gmake install sudo gmake install
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
routeadm -e ipv4-forwarding routeadm -e ipv4-forwarding
routeadm -e ipv6-forwarding routeadm -e ipv6-forwarding

View File

@ -1,39 +1,52 @@
Building FRR on OpenBSD 6 from Git Source OpenBSD 6
========================================= =========================================
Install required packages Install required packages
------------------------- -------------------------
Configure PKG_PATH Configure PKG\_PATH
::
export PKG_PATH=http://ftp5.usa.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(machine -a)/ export PKG_PATH=http://ftp5.usa.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(machine -a)/
Add packages: Add packages:
::
pkg_add git autoconf-2.69p2 automake-1.15p0 libtool bison pkg_add git autoconf-2.69p2 automake-1.15p0 libtool bison
pkg_add gmake gawk dejagnu openssl json-c py-test pkg_add gmake gawk dejagnu openssl json-c py-test py-sphinx
Select Python2.7 as default (required for pytest) Select Python2.7 as default (required for pytest)
::
ln -s /usr/local/bin/python2.7 /usr/local/bin/python ln -s /usr/local/bin/python2.7 /usr/local/bin/python
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr group and user Add frr group and user
~~~~~~~~~~~~~~~~~~~~~~
::
groupadd -g 525 _frr groupadd -g 525 _frr
groupadd -g 526 _frrvty groupadd -g 526 _frrvty
useradd -g 525 -u 525 -c "FRR suite" -G _frrvty \ useradd -g 525 -u 525 -c "FRR suite" -G _frrvty \
-d /nonexistent -s /sbin/nologin _frr -d /nonexistent -s /sbin/nologin _frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example) an example)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
export AUTOCONF_VERSION="2.69" export AUTOCONF_VERSION="2.69"
@ -56,12 +69,15 @@ an example)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
gmake gmake
gmake check gmake check
doas gmake install doas gmake install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
doas mkdir /var/frr doas mkdir /var/frr
doas chown _frr:_frr /var/frr doas chown _frr:_frr /var/frr
@ -83,47 +99,65 @@ an example)
doas chmod 750 /etc/frr doas chmod 750 /etc/frr
doas chmod 640 /etc/frr/*.conf doas chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to the end of `/etc/rc.conf`: Add the following lines to the end of ``/etc/rc.conf``:
net.inet6.ip6.forwarding=1 # 1=Permit forwarding of IPv6 packets ::
net.inet6.ip6.forwarding=1 # 1=Permit forwarding of IPv6 packets
net.inet6.ip6.mforwarding=1 # 1=Permit forwarding of IPv6 multicast packets net.inet6.ip6.mforwarding=1 # 1=Permit forwarding of IPv6 multicast packets
net.inet6.ip6.multipath=1 # 1=Enable IPv6 multipath routing net.inet6.ip6.multipath=1 # 1=Enable IPv6 multipath routing
**Reboot** to apply the config to the system **Reboot** to apply the config to the system
### Enable MPLS Forwarding Enable MPLS Forwarding
~~~~~~~~~~~~~~~~~~~~~~
To enable MPLS forwarding on a given interface, use the following command: To enable MPLS forwarding on a given interface, use the following
command:
::
doas ifconfig em0 mpls doas ifconfig em0 mpls
Alternatively, to make MPLS forwarding persistent across reboots, add the "mpls" Alternatively, to make MPLS forwarding persistent across reboots, add
keyword in the hostname.* files of the desired interfaces. Example: the "mpls" keyword in the hostname.\* files of the desired interfaces.
Example:
::
cat /etc/hostname.em0 cat /etc/hostname.em0
inet 10.0.1.1 255.255.255.0 mpls inet 10.0.1.1 255.255.255.0 mpls
### Install rc.d init files Install rc.d init files
(create them in /etc/rc.d - no example are included at this time with ~~~~~~~~~~~~~~~~~~~~~~~
(create them in /etc/rc.d - no example are included at this time with
FRR source) FRR source)
Example (for zebra - store as `/etc/rc.d/frr_zebra.sh`) Example (for zebra - store as ``/etc/rc.d/frr_zebra.sh``)
::
#!/bin/sh #!/bin/sh
# #
# $OpenBSD: frr_zebra.rc,v 1.1 2013/04/18 20:29:08 sthen Exp $ # $OpenBSD: frr_zebra.rc,v 1.1 2013/04/18 20:29:08 sthen Exp $
daemon="/usr/local/sbin/zebra -d" daemon="/usr/local/sbin/zebra -d"
. /etc/rc.d/rc.subr . /etc/rc.d/rc.subr
rc_cmd $1 rc_cmd $1
### Enable FRR processes Enable FRR processes
~~~~~~~~~~~~~~~~~~~~
(Enable the required processes only) (Enable the required processes only)
::
echo "frr_zebra=YES" >> /etc/rc.conf echo "frr_zebra=YES" >> /etc/rc.conf
echo "frr_bgpd=YES" >> /etc/rc.conf echo "frr_bgpd=YES" >> /etc/rc.conf
echo "frr_ospfd=YES" >> /etc/rc.conf echo "frr_ospfd=YES" >> /etc/rc.conf

View File

@ -1,40 +1,46 @@
Building FRR on Ubuntu 12.04LTS from Git Source Ubuntu 12.04LTS
=============================================== ===============================================
- MPLS is not supported on `Ubuntu 12.04` with default kernel. MPLS requires - MPLS is not supported on ``Ubuntu 12.04`` with default kernel. MPLS
Linux Kernel 4.5 or higher (LDP can be built, but may have limited use requires Linux Kernel 4.5 or higher (LDP can be built, but may have
without MPLS) limited use without MPLS) For an updated Ubuntu Kernel, see
For an updated Ubuntu Kernel, see http://kernel.ubuntu.com/~kernel-ppa/mainline/ http://kernel.ubuntu.com/~kernel-ppa/mainline/
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
apt-get install git autoconf automake libtool make gawk libreadline-dev \ apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \ texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \
libjson0-dev flex python-pip libc-ares-dev python3-dev libjson0-dev flex python-pip libc-ares-dev python3-dev python3-sphinx
Install newer bison from 14.04 package source (Ubuntu 12.04 package source Install newer bison from 14.04 package source (Ubuntu 12.04 package
is too old) source is too old)
::
mkdir builddir mkdir builddir
cd builddir cd builddir
wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.dsc wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.dsc
wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg.orig.tar.bz2 wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg.orig.tar.bz2
wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.debian.tar.gz wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.debian.tar.gz
tar -jxvf bison_3.0.2.dfsg.orig.tar.bz2 tar -jxvf bison_3.0.2.dfsg.orig.tar.bz2
cd bison-3.0.2.dfsg/ cd bison-3.0.2.dfsg/
tar xzf ../bison_3.0.2.dfsg-2.debian.tar.gz tar xzf ../bison_3.0.2.dfsg-2.debian.tar.gz
sudo apt-get build-dep bison sudo apt-get build-dep bison
debuild -b -uc -us debuild -b -uc -us
cd .. cd ..
sudo dpkg -i ./libbison-dev_3.0.2.dfsg-2_amd64.deb ./bison_3.0.2.dfsg-2_amd64.deb sudo dpkg -i ./libbison-dev_3.0.2.dfsg-2_amd64.deb ./bison_3.0.2.dfsg-2_amd64.deb
cd .. cd ..
rm -rf builddir rm -rf builddir
Install newer version of autoconf and automake: Install newer version of autoconf and automake:
::
wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
tar xvf autoconf-2.69.tar.gz tar xvf autoconf-2.69.tar.gz
cd autoconf-2.69 cd autoconf-2.69
@ -42,7 +48,7 @@ Install newer version of autoconf and automake:
make make
sudo make install sudo make install
cd .. cd ..
wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
tar xvf automake-1.15.tar.gz tar xvf automake-1.15.tar.gz
cd automake-1.15 cd automake-1.15
@ -53,15 +59,20 @@ Install newer version of autoconf and automake:
Install pytest: Install pytest:
::
pip install pytest pip install pytest
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvty sudo groupadd -r -g 85 frrvty
@ -69,10 +80,14 @@ any packages**
--gecos "FRR suite" --shell /sbin/nologin frr --gecos "FRR suite" --shell /sbin/nologin frr
sudo usermod -a -G frrvty frr sudo usermod -a -G frrvty frr
### Download Source, configure and compile it Download Source, configure and compile it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just (You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -95,12 +110,15 @@ an example.)
--enable-rtadv \ --enable-rtadv \
--enable-fpm \ --enable-fpm \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 775 -o frr -g frrvty -d /etc/frr sudo install -m 775 -o frr -g frrvty -d /etc/frr
@ -116,11 +134,14 @@ an example.)
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and uncomment the following values (ignore the Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
other settings) other settings)
::
# Uncomment the next line to enable packet forwarding for IPv4 # Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 net.ipv4.ip_forward=1
@ -129,27 +150,38 @@ other settings)
# based on Router Advertisements for this host # based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
**Reboot** or use `sysctl -p` to apply the same config to the running system **Reboot** or use ``sysctl -p`` to apply the same config to the running
system
### Install the init.d service Install the init.d service
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 755 tools/frr /etc/init.d/frr
sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
### Enable daemons
Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd.
For example.
zebra=yes Enable daemons
bgpd=yes ~~~~~~~~~~~~~~
ospfd=yes
ospf6d=yes | Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
ripd=yes those daemons you want to start by systemd.
ripngd=yes | For example.
isisd=yes
::
### Start the init.d service
- /etc/init.d/frr start zebra=yes
- use `/etc/init.d/frr status` to check its status. bgpd=yes
ospfd=yes
ospf6d=yes
ripd=yes
ripngd=yes
isisd=yes
Start the init.d service
~~~~~~~~~~~~~~~~~~~~~~~~
- /etc/init.d/frr start
- use ``/etc/init.d/frr status`` to check its status.

View File

@ -1,27 +1,32 @@
Building FRR on Ubuntu 14.04LTS from Git Source Ubuntu 14.04LTS
=============================================== ===============================================
- MPLS is not supported on `Ubuntu 14.04` with default kernel. MPLS requires - MPLS is not supported on ``Ubuntu 14.04`` with default kernel. MPLS
Linux Kernel 4.5 or higher (LDP can be built, but may have limited use requires Linux Kernel 4.5 or higher (LDP can be built, but may have
without MPLS) limited use without MPLS) For an updated Ubuntu Kernel, see
For an updated Ubuntu Kernel, see http://kernel.ubuntu.com/~kernel-ppa/mainline/ http://kernel.ubuntu.com/~kernel-ppa/mainline/
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
apt-get install git autoconf automake libtool make gawk libreadline-dev \ apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
python-pytest libc-ares-dev python3-dev python-pytest libc-ares-dev python3-dev python3-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvty sudo groupadd -r -g 85 frrvty
@ -29,10 +34,14 @@ any packages**
--gecos "FRR suite" --shell /sbin/nologin frr --gecos "FRR suite" --shell /sbin/nologin frr
sudo usermod -a -G frrvty frr sudo usermod -a -G frrvty frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -56,12 +65,15 @@ an example.)
--enable-fpm \ --enable-fpm \
--enable-ldpd \ --enable-ldpd \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 775 -o frr -g frrvty -d /etc/frr sudo install -m 775 -o frr -g frrvty -d /etc/frr
@ -74,14 +86,17 @@ an example.)
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
### Enable IP & IPv6 forwarding Enable IP & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and uncomment the following values (ignore the Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
other settings) other settings)
::
# Uncomment the next line to enable packet forwarding for IPv4 # Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 net.ipv4.ip_forward=1
@ -90,30 +105,35 @@ other settings)
# based on Router Advertisements for this host # based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
**Reboot** or use `sysctl -p` to apply the same config to the running system **Reboot** or use ``sysctl -p`` to apply the same config to the running
### Install the init.d service system ### Install the init.d service
::
sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 755 tools/frr /etc/init.d/frr
sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
### Enable daemons
Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd. Enable daemons
For example. ~~~~~~~~~~~~~~
zebra=yes | Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
bgpd=yes those daemons you want to start by systemd.
ospfd=yes | For example.
ospf6d=yes
ripd=yes ::
ripngd=yes
isisd=yes zebra=yes
bgpd=yes
### Start the init.d service ospfd=yes
- /etc/init.d/frr start ospf6d=yes
- use `/etc/init.d/frr status` to check its status. ripd=yes
ripngd=yes
isisd=yes
Start the init.d service
~~~~~~~~~~~~~~~~~~~~~~~~
- /etc/init.d/frr start
- use ``/etc/init.d/frr status`` to check its status.

View File

@ -1,28 +1,33 @@
Building FRR on Ubuntu 16.04LTS from Git Source Ubuntu 16.04LTS
=============================================== ===============================================
- MPLS is not supported on `Ubuntu 16.04` with default kernel. MPLS requires - MPLS is not supported on ``Ubuntu 16.04`` with default kernel. MPLS
Linux Kernel 4.5 or higher (LDP can be built, but may have limited use requires Linux Kernel 4.5 or higher (LDP can be built, but may have
without MPLS) limited use without MPLS) For an updated Ubuntu Kernel, see
For an updated Ubuntu Kernel, see http://kernel.ubuntu.com/~kernel-ppa/mainline/
http://kernel.ubuntu.com/~kernel-ppa/mainline/
Install required packages Install required packages
------------------------- -------------------------
Add packages: Add packages:
::
apt-get install git autoconf automake libtool make gawk libreadline-dev \ apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
python-pytest libc-ares-dev python3-dev libsystemd-dev python-ipaddr python-pytest libc-ares-dev python3-dev libsystemd-dev python-ipaddr \
python3-sphinx
Get FRR, compile it and install it (from Git) Get FRR, compile it and install it (from Git)
--------------------------------------------- ---------------------------------------------
**This assumes you want to build and install FRR from source and not using **This assumes you want to build and install FRR from source and not
any packages** using any packages**
### Add frr groups and user Add frr groups and user
~~~~~~~~~~~~~~~~~~~~~~~
::
sudo groupadd -g 92 frr sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvty sudo groupadd -r -g 85 frrvty
@ -30,10 +35,14 @@ any packages**
--gecos "FRR suite" --shell /sbin/nologin frr --gecos "FRR suite" --shell /sbin/nologin frr
sudo usermod -a -G frrvty frr sudo usermod -a -G frrvty frr
### Download Source, configure and compile it Download Source, configure and compile it
(You may prefer different options on configure statement. These are just ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(You may prefer different options on configure statement. These are just
an example.) an example.)
::
git clone https://github.com/frrouting/frr.git frr git clone https://github.com/frrouting/frr.git frr
cd frr cd frr
./bootstrap.sh ./bootstrap.sh
@ -57,12 +66,15 @@ an example.)
--enable-fpm \ --enable-fpm \
--enable-systemd=yes \ --enable-systemd=yes \
--with-pkg-git-version \ --with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion --with-pkg-extra-version=-MyOwnFRRVersion
make make
make check make check
sudo make install sudo make install
### Create empty FRR configuration files Create empty FRR configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 775 -o frr -g frrvty -d /etc/frr sudo install -m 775 -o frr -g frrvty -d /etc/frr
@ -75,14 +87,17 @@ an example.)
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
### Enable IPv4 & IPv6 forwarding Enable IPv4 & IPv6 forwarding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and uncomment the following values (ignore the Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
other settings) other settings)
::
# Uncomment the next line to enable packet forwarding for IPv4 # Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 net.ipv4.ip_forward=1
@ -91,10 +106,14 @@ other settings)
# based on Router Advertisements for this host # based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1
### Enable MPLS Forwarding (with Linux Kernel >= 4.5) Enable MPLS Forwarding (with Linux Kernel >= 4.5)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit `/etc/sysctl.conf` and the following lines. Make sure to add a line Edit ``/etc/sysctl.conf`` and the following lines. Make sure to add a
equal to `net.mpls.conf.eth0.input` or each interface used with MPLS line equal to ``net.mpls.conf.eth0.input`` or each interface used with
MPLS
::
# Enable MPLS Label processing on all interfaces # Enable MPLS Label processing on all interfaces
net.mpls.conf.eth0.input=1 net.mpls.conf.eth0.input=1
@ -102,18 +121,24 @@ equal to `net.mpls.conf.eth0.input` or each interface used with MPLS
net.mpls.conf.eth2.input=1 net.mpls.conf.eth2.input=1
net.mpls.platform_labels=100000 net.mpls.platform_labels=100000
### Add MPLS kernel modules Add MPLS kernel modules
~~~~~~~~~~~~~~~~~~~~~~~
Add the following lines to `/etc/modules-load.d/modules.conf`: Add the following lines to ``/etc/modules-load.d/modules.conf``:
::
# Load MPLS Kernel Modules # Load MPLS Kernel Modules
mpls-router mpls-router
mpls-iptunnel mpls-iptunnel
**Reboot** or use `sysctl -p` to apply the same config to the running system **Reboot** or use ``sysctl -p`` to apply the same config to the running
system
Install the systemd service (if rebooted from last step, change directory back to frr directory)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Install the systemd service (if rebooted from last step, change directory back to frr directory) ::
sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
sudo install -m 644 tools/etc/default/frr /etc/default/frr sudo install -m 644 tools/etc/default/frr /etc/default/frr
@ -122,10 +147,14 @@ Add the following lines to `/etc/modules-load.d/modules.conf`:
sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf
sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
### Enable daemons Enable daemons
~~~~~~~~~~~~~~
Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd. | Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
For example. those daemons you want to start by systemd.
| For example.
::
zebra=yes zebra=yes
bgpd=yes bgpd=yes
@ -135,9 +164,13 @@ For example.
ripngd=yes ripngd=yes
isisd=yes isisd=yes
### Enable the systemd service Enable the systemd service
- systemctl enable frr ~~~~~~~~~~~~~~~~~~~~~~~~~~
### Start the systemd service - systemctl enable frr
- systemctl start frr
- use `systemctl status frr` to check its status. Start the systemd service
~~~~~~~~~~~~~~~~~~~~~~~~~
- systemctl start frr
- use ``systemctl status frr`` to check its status.

1
doc/developer/Makefile Normal file
View File

@ -0,0 +1 @@
include ../frr-sphinx.mk

8
doc/developer/bgpd.rst Normal file
View File

@ -0,0 +1,8 @@
BGPD
=========================
.. toctree::
:maxdepth: 2
next-hop-tracking

View File

@ -0,0 +1,22 @@
Building FRR
=========================
.. toctree::
:maxdepth: 2
Building_FRR_on_LEDE-OpenWRT
Building_FRR_on_CentOS6
Building_FRR_on_CentOS7
Building_FRR_on_Debian8
Building_FRR_on_Debian9
Building_FRR_on_Fedora24
Building_FRR_on_FreeBSD10
Building_FRR_on_FreeBSD11
Building_FRR_on_FreeBSD9
Building_FRR_on_NetBSD6
Building_FRR_on_NetBSD7
Building_FRR_on_OmniOS
Building_FRR_on_OpenBSD6
Building_FRR_on_Ubuntu1204
Building_FRR_on_Ubuntu1404
Building_FRR_on_Ubuntu1604

723
doc/developer/cli.rst Normal file
View File

@ -0,0 +1,723 @@
Command Line Interface
======================
FRR features a flexible modal command line interface. Often when adding new
features or modifying existing code it is necessary to create or modify CLI
commands. FRR has a powerful internal CLI system that does most of the heavy
lifting for you.
All definitions for the CLI system are exposed in ``lib/command.h``. In this
header there are a set of macros used to define commands. These macros are
collectively referred to as "DEFUNs", because of their syntax:
::
DEFUN(command_name,
command_name_cmd,
"example command FOO...",
"Examples\n"
"CLI command\n"
"Argument\n")
{
// ...command handler...
}
DEFUNs generally take four arguments which are expanded into the appropriate
constructs for hooking into the CLI. In order these are:
- **Function name** - the name of the handler function for the command
- **Command name** - the identifier of the ``struct cmd_element`` for the
command. By convention this should be the function name with ``_cmd``
appended.
- **Command definition** - an expression in FRR's CLI grammar that defines the
form of the command and its arguments, if any
- **Doc string** - a newline-delimited string that documents each element in
the command definition
In the above example, ``command_name`` is the function name,
``command_name_cmd`` is the command name, ``"example..."`` is the definition
and the last argument is the doc string. The block following the macro is the
body of the handler function, details on which are presented later in this
section.
In order to make the command show up to the user it must be installed into the
CLI graph. To do this, call:
``install_element(NODE, &command_name_cmd);``
This will install the command into the specified CLI node. Usually these calls
are grouped together in a CLI initialization function for a set of commands,
and the DEFUNs themselves are grouped into the same source file to avoid
cluttering the codebase. The names of these files follow the form
``*_vty.[ch]`` by convention. Please do not scatter individual CLI commands in
the middle of source files; instead expose the necessary functions in a header
and place the command definition in a ``*_vty.[ch]`` file.
Definition Grammar
------------------
FRR uses its own grammar for defining CLI commands. The grammar draws from
syntax commonly seen in \*nix manpages and should be fairly intuitive. The
parser is implemented in Bison and the lexer in Flex. These may be found in
``lib/command_lex.l`` and ``lib/command_parse.y``, respectively.
**ProTip**: if you define a new command and find that the parser is
throwing syntax or other errors, the parser is the last place you want
to look. Bison is very stable and if it detects a syntax error, 99% of
the time it will be a syntax error in your definition.
The formal grammar in BNF is given below. This is the grammar implemented in
the Bison parser. At runtime, the Bison parser reads all of the CLI strings and
builds a combined directed graph that is used to match and interpret user
input.
Human-friendly explanations of how to use this grammar are given a bit later in
this section alongside information on the :ref:`cli-data-structures` constructed
by the parser.
.. productionlist::
command: `cmd_token_seq`
: `cmd_token_seq` `placeholder_token` "..."
cmd_token_seq: *empty*
: `cmd_token_seq` `cmd_token`
cmd_token: `simple_token`
: `selector`
simple_token: `literal_token`
: `placeholder_token`
literal_token: WORD `varname_token`
varname_token: "$" WORD
placeholder_token: `placeholder_token_real` `varname_token`
placeholder_token_real: IPV4
: IPV4_PREFIX
: IPV6
: IPV6_PREFIX
: VARIABLE
: RANGE
: MAC
: MAC_PREFIX
selector: "<" `selector_seq_seq` ">" `varname_token`
: "{" `selector_seq_seq` "}" `varname_token`
: "[" `selector_seq_seq` "]" `varname_token`
selector_seq_seq: `selector_seq_seq` "|" `selector_token_seq`
: `selector_token_seq`
selector_token_seq: `selector_token_seq` `selector_token`
: `selector_token`
selector_token: `selector`
: `simple_token`
Tokens
~~~~~~
The various capitalized tokens in the BNF above are in fact themselves
placeholders, but not defined as such in the formal grammar; the grammar
provides the structure, and the tokens are actually more like a type system for
the strings you write in your CLI definitions. A CLI definition string is
broken apart and each piece is assigned a type by the lexer based on a set of
regular expressions. The parser uses the type information to verify the string
and determine the structure of the CLI graph; additional metadata (such as the
raw text of each token) is encoded into the graph as it is constructed by the
parser, but this is merely a dumb copy job.
Here is a brief summary of the various token types along with examples.
+-----------------+-----------------+-------------------------------------------------------------+
| Token type | Syntax | Description |
+=================+=================+=============================================================+
| ``WORD`` | ``show ip bgp`` | Matches itself. In the given example every token is a WORD. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``MAC`` | ``M:A:C`` | Matches a 48-bit mac address. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``MAC_PREFIX`` | ``M:A:C/M`` | Matches a 48-bit mac address with a mask. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``VARIABLE`` | ``FOOBAR`` | Matches anything. |
+-----------------+-----------------+-------------------------------------------------------------+
| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. |
+-----------------+-----------------+-------------------------------------------------------------+
When presented with user input, the parser will search over all defined
commands in the current context to find a match. It is aware of the various
types of user input and has a ranking system to help disambiguate commands. For
instance, suppose the following commands are defined in the user's current
context:
::
example command FOO
example command (22-49)
example command A.B.C.D/X
The following table demonstrates the matcher's choice for a selection of
possible user input.
+-----------------------------+---------------------------+--------------------------------------------------------------------------------------------------------------+
| Input | Matched command | Reason |
+=============================+===========================+==============================================================================================================+
| example command eLi7eH4xx0r | example command FOO | ``eLi7eH4xx0r`` is not an integer or IPv4 prefix, |
| | | but FOO is a variable and matches all input. |
+-----------------------------+---------------------------+--------------------------------------------------------------------------------------------------------------+
| example command 42 | example command (22-49) | ``42`` is not an IPv4 prefix. It does match both |
| | | ``(22-49)`` and ``FOO``, but RANGE tokens are more specific and have a higher priority than VARIABLE tokens. |
+-----------------------------+---------------------------+--------------------------------------------------------------------------------------------------------------+
| example command 10.3.3.0/24 | example command A.B.C.D/X | The user entered an IPv4 prefix, which is best matched by the last command. |
+-----------------------------+---------------------------+--------------------------------------------------------------------------------------------------------------+
Rules
~~~~~
There are also constructs which allow optional tokens, mutual exclusion, one-or-more selection and repetition.
- ``<angle|brackets>`` -- Contain sequences of tokens separated by pipes and
provide mutual exclusion. User input matches at most one option.
- ``[square brackets]`` -- Contains sequences of tokens that can be omitted.
``[<a|b>]`` can be shortened to ``[a|b]``.
- ``{curly|braces}`` -- similar to angle brackets, but instead of mutual
exclusion, curly braces indicate that one or more of the pipe-separated
sequences may be provided in any order.
- ``VARIADICS...`` -- Any token which accepts input (anything except WORD)
which occurs as the last token of a line may be followed by an ellipsis,
which indicates that input matching the token may be repeated an unlimited
number of times.
- ``$name`` -- Specify a variable name for the preceding token. See
"Variable Names" below.
Some general notes:
- Options are allowed at the beginning of the command. The developer is
entreated to use these extremely sparingly. They are most useful for
implementing the 'no' form of configuration commands. Please think carefully
before using them for anything else. There is usually a better solution, even
if it is just separating out the command definition into separate ones.
- The developer should judiciously apply separation of concerns when defining
commands. CLI definitions for two unrelated or vaguely related commands or
configuration items should be defined in separate commands. Clarity is
preferred over LOC (within reason).
- The maximum number of space-separated tokens that can be entered is
presently limited to 256. Please keep this limit in mind when
implementing new CLI.
Variable Names
--------------
The parser tries to fill the "varname" field on each token. This can
happen either manually or automatically. Manual specifications work by
appending ``"$name"`` after the input specifier:
::
foo bar$cmd WORD$name A.B.C.D$ip
Note that you can also assign variable names to fixed input tokens, this
can be useful if multiple commands share code. You can also use "$name"
after a multiple-choice option:
::
foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode
The variable name is in this case assigned to the last token in each of
the branches.
Automatic assignment of variable names works by applying the following
rules:
- manual names always have priority
- a "[no]" at the beginning receives "no" as varname on the "no" token
- VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned
lowercase version of the token text as varname, e.g. "ROUTE-MAP"
becomes "route\_map".
- other variable tokens (i.e. everything except "fixed") receive the
text of the preceding fixed token as varname, if one can be found.
E.g.: "ip route A.B.C.D/M INTERFACE" assigns "route" to the
"A.B.C.D/M" token.
These rules should make it possible to avoid manual varname assignment
in 90% of the cases.
DEFPY
-----
``DEFPY(...)`` is an enhanced version of ``DEFUN()`` which is
preprocessed by ``python/clidef.py``. The python script parses the
command definition string, extracts variable names and types, and
generates a C wrapper function that parses the variables and passes them
on. This means that in the CLI function body, you will receive
additional parameters with appropriate types.
This is best explained by an example:
::
DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...")
=>
func(self, vty, argc, argv, /* standard CLI arguments */
const char *no, /* unparsed "no" */
struct in_addr bar, /* parsed IP address */
const char *bar_str, /* unparsed IP address */
long num, /* parsed num */
const char *num_str) /* unparsed num */
Note that as documented in the previous section, "bar" is automatically
applied as variable name for "A.B.C.D". The python code then detects
this is an IP address argument and generates code to parse it into a
``struct in_addr``, passing it in ``bar``. The raw value is passed in
``bar_str``. The range/number argument works in the same way with the
explicitly given variable name.
Type rules
~~~~~~~~~~
+-----------------------------+--------------------------------+--------------------------+
| Token(s) | Type | Value if omitted by user |
+=============================+================================+==========================+
| ``A.B.C.D`` | ``struct in_addr`` | 0.0.0.0 |
+-----------------------------+--------------------------------+--------------------------+
| ``X:X::X:X`` | ``struct in6_addr`` | \:: |
+-----------------------------+--------------------------------+--------------------------+
| ``A.B.C.D + X:X::X:X`` | ``const union sockunion *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| ``A.B.C.D/M`` | ``const struct prefix_ipv4 *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| ``X:X::X:X/M`` | ``const struct prefix_ipv6 *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| ``A.B.C.D/M + X:X::X:X/M`` | ``const struct prefix *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| ``(0-9)`` | ``long`` | 0 |
+-----------------------------+--------------------------------+--------------------------+
| ``VARIABLE`` | ``const char *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| ``word`` | ``const char *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
| *all other* | ``const char *`` | NULL |
+-----------------------------+--------------------------------+--------------------------+
Note the following details:
- Not all parameters are pointers, some are passed as values.
- When the type is not ``const char *``, there will be an extra
``_str`` argument with type ``const char *``.
- You can give a variable name not only to ``VARIABLE`` tokens but also
to ``word`` tokens (e.g. constant words). This is useful if some
parts of a command are optional. The type will be ``const char *``.
- ``[no]`` will be passed as ``const char *no``.
- Pointers will be NULL when the argument is optional and the user did
not use it.
- If a parameter is not a pointer, but is optional and the user didn't
use it, the default value will be passed. Check the ``_str`` argument
if you need to determine whether the parameter was omitted.
- If the definition contains multiple parameters with the same variable
name, they will be collapsed into a single function parameter. The
python code will detect if the types are compatible (i.e. IPv4 + IPv6
variantes) and choose a corresponding C type.
- The standard DEFUN parameters (self, vty, argc, argv) are still
present and can be used. A DEFUN can simply be **edited into a DEFPY
without further changes and it will still work**; this allows easy
forward migration.
- A file may contain both DEFUN and DEFPY statements.
Getting a parameter dump
~~~~~~~~~~~~~~~~~~~~~~~~
The clidef.py script can be called to get a list of DEFUNs/DEFPYs with
the parameter name/type list:
::
lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null
The generated code is printed to stdout, the info dump to stderr. The
``--all-defun`` argument will make it process DEFUN blocks as well as
DEFPYs, which is useful prior to converting some DEFUNs. **The dump does
not list the ``_str`` arguments** to keep the output shorter.
Note that the clidef.py script cannot be run with python directly, it
needs to be run with *clippy* since the latter makes the CLI parser
available.
Include & Makefile requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A source file that uses DEFPY needs to include the ``_clippy.c`` file
**before all DEFPY statements**:
::
/* GPL header */
#include ...
...
#include "daemon/filename_clippy.c"
DEFPY(...)
DEFPY(...)
install_element(...)
This dependency needs to be marked in Makefile.am: (there is no ordering
requirement)
::
include ../common.am
# ...
# if linked into a LTLIBRARY (.la/.so):
filename.lo: filename_clippy.c
# if linked into an executable or static library (.a):
filename.o: filename_clippy.c
Doc Strings
-----------
Each token in a command definition should be documented with a brief doc string
that informs a user of the meaning and/or purpose of the subsequent command
tree. These strings are provided as the last parameter to DEFUN macros,
concatenated together and separated by an escaped newline (\n). These are best
explained by example.
::
DEFUN (config_terminal,
config_terminal_cmd,
"configure terminal",
"Configuration from vty interface\n"
"Configuration terminal\n")
The last parameter is split into two lines for readability. Two newline
delimited doc strings are present, one for each token in the command.
The second string documents the functionality of the 'terminal' command
in the 'configure' tree.
Note that the first string, for 'configure' does not contain
documentation for 'terminal'. This is because the CLI is best envisioned
as a tree, with tokens defining branches. An imaginary 'start' token is
the root of every command in a CLI node. Each subsequent written token
descends into a subtree, so the documentation for that token ideally
summarizes all the functionality contained in the subtree.
A consequence of this structure is that the developer must be careful to
use the same doc strings when defining multiple commands that are part
of the same tree. Commands which share prefixes must share the same doc
strings for those prefixes. On startup the parser will generate warnings
if it notices inconsistent doc strings. Behavior is undefined; the same
token may show up twice in completions, with different doc strings, or
it may show up once with a random doc string. Parser warnings should be
heeded and fixed to avoid confusing users.
The number of doc strings provided must be equal to the amount of tokens
present in the command definition, read left to right, ignoring any
special constructs.
In the examples below, each arrowed token needs a doc string.
::
"show ip bgp"
^ ^ ^
"command <foo|bar> [example]"
^ ^ ^ ^
.. _cli-data-structures:
Data Structures
---------------
On startup, the CLI parser sequentially parses each command string
definition and constructs a directed graph with each token forming a
node. This graph is the basis of the entire CLI system. It is used to
match user input in order to generate command completions and match
commands to functions.
There is one graph per CLI node (not the same as a graph node in the CLI
graph). The CLI node struct keeps a reference to its graph (see
lib/command.h).
While most of the graph maintains the form of a tree, special constructs
outlined in the Rules section introduce some quirks. <>, [] and {} form
self-contained 'subgraphs'. Each subgraph is a tree except that all of
the 'leaves' actually share a child node. This helps with minimizing
graph size and debugging.
As a working example, here is the graph of the following command: ::
show [ip] bgp neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]
.. figure:: ../figures/cligraph.svg
:align: center
Graph of example CLI command
``FORK`` and ``JOIN`` nodes are plumbing nodes that don't correspond to user
input. They're necessary in order to deduplicate these constructs where
applicable.
Options follow the same form, except that there is an edge from the ``FORK``
node to the ``JOIN`` node. Since all of the subgraphs in the example command
are optional, all of them have this edge.
Keywords follow the same form, except that there is an edge from ``JOIN`` to
``FORK``. Because of this the CLI graph cannot be called acyclic. There is
special logic in the input matching code that keeps a stack of paths already
taken through the node in order to disallow following the same path more than
once.
Variadics are a bit special; they have an edge back to themselves, which allows
repeating the same input indefinitely.
The leaves of the graph are nodes that have no out edges. These nodes are
special; their data section does not contain a token, as most nodes do, or
NULL, as in ``FORK``/``JOIN`` nodes, but instead has a pointer to a
cmd\_element. All paths through the graph that terminate on a leaf are
guaranteed to be defined by that command. When a user enters a complete
command, the command matcher tokenizes the input and executes a DFS on the CLI
graph. If it is simultaneously able to exhaust all input (one input token per
graph node), and then find exactly one leaf connected to the last node it
reaches, then the input has matched the corresponding command and the command
is executed. If it finds more than one node, then the command is ambiguous
(more on this in deduplication). If it cannot exhaust all input, the command is
unknown. If it exhausts all input but does not find an edge node, the command
is incomplete.
The parser uses an incremental strategy to build the CLI graph for a node. Each
command is parsed into its own graph, and then this graph is merged into the
overall graph. During this merge step, the parser makes a best-effort attempt
to remove duplicate nodes. If it finds a node in the overall graph that is
equal to a node in the corresponding position in the command graph, it will
intelligently merge the properties from the node in the command graph into the
already-existing node. Subgraphs are also checked for isomorphism and merged
where possible. The definition of whether two nodes are 'equal' is based on the
equality of some set of token properties; read the parser source for the most
up-to-date definition of equality.
When the parser is unable to deduplicate some complicated constructs, this can
result in two identical paths through separate parts of the graph. If this
occurs and the user enters input that matches these paths, they will receive an
'ambiguous command' error and will be unable to execute the command. Most of
the time the parser can detect and warn about duplicate commands, but it will
not always be able to do this. Hence care should be taken before defining a
new command to ensure it is not defined elsewhere.
Command handlers
----------------
The block that follows a CLI definition is executed when a user enters
input that matches the definition. Its function signature looks like
this:
::
int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]);
The first argument is the command definition struct. The last argument
is an ordered array of tokens that correspond to the path taken through
the graph, and the argument just prior to that is the length of the
array.
The arrangement of the token array has changed from the prior
incarnation of the CLI system. In the old system, missing arguments were
padded with NULLs so that the same parts of a command would show up at
the same indices regardless of what was entered. The new system does not
perform such padding and therefore it is generally *incorrect* to assume
consistent indices in this array. As a simple example:
Command definition:
::
command [foo] <bar|baz>
User enters:
::
command foo bar
Array:
::
[0] -> command
[1] -> foo
[2] -> bar
User enters:
::
command baz
Array:
::
[0] -> command
[1] -> baz
Command abbreviation & matching priority
----------------------------------------
As in the prior implementation, it is possible for users to elide parts
of tokens when the CLI matcher does not need them to make an unambiguous
match. This is best explained by example.
Command definitions:
::
command dog cow
command dog crow
User input:
::
c d c -> ambiguous command
c d co -> match "command dog cow"
In the new implementation, this functionality has improved. Where
previously the parser would stop at the first ambiguous token, it will
now look ahead and attempt to disambiguate based on tokens later on in
the input string.
Command definitions:
::
show ip bgp A.B.C.D
show ipv6 bgp X:X::X:X
User enters:
::
s i b 4.3.2.1 -> match "show ip bgp A.B.C.D"
s i b ::e0 -> match "show ipv6 bgp X:X::X:X"
Previously both of these commands would be ambiguous since 'i' does not
explicitly select either 'ip' or 'ipv6'. However, since the user later
provides a token that matches only one of the commands (an IPv4 or IPv6
address) the parser is able to look ahead and select the appropriate
command. This has some implications for parsing the argv\*[] that is
passed to the command handler.
Now consider a command definition such as:
::
command <foo|VAR>
'foo' only matches the string 'foo', but 'VAR' matches any input,
including 'foo'. Who wins? In situations like this the matcher will
always choose the 'better' match, so 'foo' will win.
Consider also:
::
show <ip|ipv6> foo
User input:
::
show ip foo
'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will
win.
struct cmd\_token
-----------------
::
/* Command token struct. */
struct cmd_token
{
enum cmd_token_type type; // token type
u_char attr; // token attributes
bool allowrepeat; // matcher allowed to match token repetitively?
char *text; // token text
char *desc; // token description
long long min, max; // for ranges
char *arg; // user input that matches this token
char *varname; // variable name
};
This struct is used in the CLI graph to match input against. It is also
used to pass user input to command handler functions, as it is
frequently useful for handlers to have access to that information. When
a command is matched, the sequence of cmd\_tokens that form the matching
path are duplicated and placed in order into argv\*[]. Before this
happens the ->arg field is set to point at the snippet of user input
that matched it.
For most nontrivial commands the handler function will need to determine
which of the possible matching inputs was entered. Previously this was
done by looking at the first few characters of input. This is now
considered an anti-pattern and should be avoided. Instead, the ->type or
->text fields for this logic. The ->type field can be used when the
possible inputs differ in type. When the possible types are the same,
use the ->text field. This field has the full text of the corresponding
token in the definition string and using it makes for much more readable
code. An example is helpful.
Command definition:
::
command <(1-10)|foo|BAR>
In this example, the user may enter any one of: \* an integer between 1
and 10 \* "foo" \* anything at all
If the user enters "command f", then:
::
argv[1]->type == WORD_TKN
argv[1]->arg == "f"
argv[1]->text == "foo"
Range tokens have some special treatment; a token with ->type ==
RANGE\_TKN will have the ->min and ->max fields set to the bounding
values of the range.
Permutations
------------
Finally, it is sometimes useful to check all the possible combinations
of input that would match an arbitrary definition string. There is a
tool in tools/ called 'permutations' that reads CLI definition strings
on stdin and prints out all matching input permutations. It also dumps a
text representation of the graph, which is more useful for debugging
than anything else. It looks like this:
::
$ ./permutations "show [ip] bgp [<view|vrf> WORD]"
show ip bgp view WORD
show ip bgp vrf WORD
show ip bgp
show bgp view WORD
show bgp vrf WORD
show bgp
This functionality is also built into VTY/VTYSH; the 'list permutations'
command will list all possible matching input permutations in the
current CLI node.

View File

@ -24,7 +24,10 @@ import re
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here. # If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0' needs_sphinx = '1.0'
# prolog for various variable substitutions
rst_prolog = ''
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@ -36,7 +39,7 @@ templates_path = ['_templates']
# The suffix(es) of source filenames. # The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string: # You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md'] # source_suffix = ['.rst']
source_suffix = '.rst' source_suffix = '.rst'
# The encoding of source files. # The encoding of source files.
@ -59,14 +62,51 @@ version = u'?.?'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = u'?.?-?' release = u'?.?-?'
# -----------------------------------------------------------------------------
# Extract values from codebase for substitution into docs.
# -----------------------------------------------------------------------------
# Various installation prefixes. Reasonable defaults are set where possible.
# Values are overridden by logic below.
replace_vars = {
'AUTHORS': 'Kunihiro Ishiguro, et al.',
'COPYRIGHT_YEAR': '1999-2005',
'COPYRIGHT_STR': None,
'PACKAGE_NAME': project.lower(),
'PACKAGE_TARNAME': project.lower(),
'PACKAGE_STRING': None,
'PACKAGE_URL': 'https://frrouting.org/',
'PACKAGE_VERSION': None,
'INSTALL_PREFIX_ETC': None,
'INSTALL_PREFIX_SBIN': None,
'INSTALL_PREFIX_STATE': None,
'INSTALL_PREFIX_MODULES': None,
'INSTALL_USER': None,
'INSTALL_GROUP': None,
'INSTALL_VTY_GROUP': None,
}
# extract version information, installation location, other stuff we need to
# use when building final documents
val = re.compile('^S\["([^"]+)"\]="(.*)"$') val = re.compile('^S\["([^"]+)"\]="(.*)"$')
with open('../../config.status', 'r') as cfgstatus: with open('../../config.status', 'r') as cfgstatus:
for ln in cfgstatus.readlines(): for ln in cfgstatus.readlines():
m = val.match(ln) m = val.match(ln)
if m is None: continue if not m or m.group(1) not in replace_vars.keys(): continue
if m.group(1) == 'PACKAGE_VERSION': replace_vars[m.group(1)] = m.group(2)
release = m.group(2)
version = release.split('-')[0] # manually fill out some of these we can't get from config.status
replace_vars['COPYRIGHT_STR'] = "Copyright (c)"
replace_vars['COPYRIGHT_STR'] += ' {0}'.format(replace_vars['COPYRIGHT_YEAR'])
replace_vars['COPYRIGHT_STR'] += ' {0}'.format(replace_vars['AUTHORS'])
release = replace_vars['PACKAGE_VERSION']
version = release.split('-')[0]
# add substitutions to prolog
for key, value in replace_vars.items():
rst_prolog += '.. |{0}| replace:: {1}\n'.format(key, value)
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -117,12 +157,14 @@ todo_include_todos = True
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'sphinx_rtd_theme' html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
# documentation. # documentation.
#html_theme_options = {} html_theme_options = {
'sidebarbgcolor': '#374249'
}
# Add any paths that contain custom themes here, relative to this directory. # Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = [] #html_theme_path = []
@ -136,17 +178,17 @@ html_theme = 'sphinx_rtd_theme'
# The name of an image file (relative to this directory) to place at the top # The name of an image file (relative to this directory) to place at the top
# of the sidebar. # of the sidebar.
#html_logo = None html_logo = '../figures/frr-icon.svg'
# The name of an image file (within the static path) to use as favicon of the # The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
#html_favicon = None html_favicon = '../figures/frr-logo-icon.png'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] #html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or # Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied # .htaccess) here, relative to this directory. These files are copied
@ -231,13 +273,13 @@ latex_elements = {
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'FRR.tex', u'FRR Documentation', (master_doc, 'FRR.tex', u"FRR Developer's Manual",
u'FRR', 'manual'), u'FRR', 'manual'),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
# the title page. # the title page.
#latex_logo = None latex_logo = '../figures/frr-logo-medium.png'
# For "manual" documents, if this is true, then toplevel headings are parts, # For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters. # not chapters.
@ -261,7 +303,7 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'frr', u'FRR Documentation', (master_doc, 'frr', u"FRR Developer's Manual",
[author], 1) [author], 1)
] ]
@ -275,7 +317,7 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'FRR', u'FRR Documentation', (master_doc, 'frr', u"FRR Developer's Manual",
author, 'FRR', 'One line description of project.', author, 'FRR', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]
@ -291,3 +333,9 @@ texinfo_documents = [
# If true, do not generate a @detailmenu in the "Top" node's menu. # If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False #texinfo_no_detailmenu = False
# custom extensions here
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
# node later on
app.add_object_type('clicmd', 'clicmd')

View File

@ -1,18 +1,13 @@
Welcome to FRR's documentation! Welcome to FRR's documentation!
=============================== ===============================
Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
workflow
library library
bgpd
building
Indices and tables ospf-api
================== ospf-sr
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -6,5 +6,7 @@ libfrr library facilities
memtypes memtypes
hooks hooks
cli
modules

View File

@ -81,7 +81,7 @@ Definition
>80% of cases. >80% of cases.
.. todo:: .. todo::
Daemons currently have ``daemon_memory.[ch]`` files listing all of Daemons currently have ``daemon_memory.[ch]`` files listing all of
their MTYPEs. This is not how it should be, most of these types their MTYPEs. This is not how it should be, most of these types
should be moved into the appropriate files where they are used. should be moved into the appropriate files where they are used.

123
doc/developer/modules.rst Normal file
View File

@ -0,0 +1,123 @@
Modules
=======
FRR has facilities to load DSOs at startup via ``dlopen()``. These are used to
implement modules, such as SNMP and FPM.
Limitations
-----------
- can't load, unload, or reload during runtime. This just needs some
work and can probably be done in the future.
- doesn't fix any of the "things need to be changed in the code in the
library" issues. Most prominently, you can't add a CLI node because
CLI nodes are listed in the library...
- if your module crashes, the daemon crashes. Should be obvious.
- **does not provide a stable API or ABI**. Your module must match a
version of FRR and you may have to update it frequently to match
changes.
- **does not create a license boundary**. Your module will need to link
libzebra and include header files from the daemons, meaning it will
be GPL-encumbered.
Installation
------------
Look for ``moduledir`` in ``configure.ac``, default is normally
``/usr/lib64/frr/modules`` but depends on ``--libdir`` / ``--prefix``.
The daemon's name is prepended when looking for a module, e.g. "snmp"
tries to find "zebra\_snmp" first when used in zebra. This is just to
make it nicer for the user, with the snmp module having the same name
everywhere.
Modules can be packaged separately from FRR. The SNMP and FPM modules
are good candidates for this because they have dependencies (net-snmp /
protobuf) that are not FRR dependencies. However, any distro packages
should have an "exact-match" dependency onto the FRR package. Using a
module from a different FRR version will probably blow up nicely.
For snapcraft (and during development), modules can be loaded with full
path (e.g. -M ``$SNAP/lib/frr/modules/zebra_snmp.so``). Note that
libtool puts output files in the .libs directory, so during development
you have to use ``./zebra -M .libs/zebra_snmp.so``.
Creating a module
-----------------
... best to look at the existing SNMP or FPM modules.
Basic boilerplate:
::
#include "hook.h"
#include "module.h"
static int
module_init (void)
{
hook_register(frr_late_init, module_late_init);
return 0;
}
FRR_MODULE_SETUP(
.name = "my module",
.version = "0.0",
.description = "my module",
.init = module_init,
)
The ``frr_late_init`` hook will be called after the daemon has finished
its other startup and is about to enter the main event loop; this is the
best place for most initialisation.
Compiler & Linker magic
-----------------------
There's a ``THIS_MODULE`` (like in the Linux kernel), which uses
``visibility`` attributes to restrict it to the current module. If you
get a linker error with ``_frrmod_this_module``, there is some linker
SNAFU. This shouldn't be possible, though one way to get it would be to
not include libzebra (which provides a fallback definition for the
symbol).
libzebra and the daemons each have their own ``THIS_MODULE``, as do all
loadable modules. In any other libraries (e.g. ``libfrrsnmp``),
``THIS_MODULE`` will use the definition in libzebra; same applies if the
main executable doesn't use ``FRR_DAEMON_INFO`` (e.g. all testcases).
The deciding factor here is "what dynamic linker unit are you using the
symbol from." If you're in a library function and want to know who
called you, you can't use ``THIS_MODULE`` (because that'll just tell you
you're in the library). Put a macro around your function that adds
``THIS_MODULE`` in the *caller's code calling your function*.
The idea is to use this in the future for module unloading. Hooks
already remember which module they were installed by, as groundwork for
a function that removes all of a module's installed hooks.
There's also the ``frr_module`` symbol in modules, pretty much a
standard entry point for loadable modules.
Hooks
-----
Hooks are just points in the code where you can register your callback
to be called. The parameter list is specific to the hook point. Since
there is no stable API, the hook code has some extra type safety checks
making sure you get a compiler warning when the hook parameter list
doesn't match your callback. Don't ignore these warnings.
Relation to MTYPE macros
------------------------
The MTYPE macros, while primarily designed to decouple MTYPEs from the
library and beautify the code, also work very nicely with loadable
modules -- both constructors and destructors are executed when
loading/unloading modules.
This means there is absolutely no change required to MTYPEs, you can
just use them in a module and they will even clean up themselves when we
implement module unloading and an unload happens. In fact, it's
impossible to create a bug where unloading fails to de-register a MTYPE.

View File

@ -0,0 +1,352 @@
Next Hop Tracking
==================
Next hop tracking is an optimization feature that reduces the processing time
involved in the BGP bestpath algorithm by monitoring changes to the routing
table.
Background
-----------
Recursive routes are of the form:
::
p/m --> n
[Ex: 1.1.0.0/16 --> 2.2.2.2]
where 'n' itself is resolved through another route as follows:
::
p2/m --> h, interface
[Ex: 2.2.2.0/24 --> 3.3.3.3, eth0]
Usually, BGP routes are recursive in nature and BGP nexthops get resolved
through an IGP route. IGP usually adds its routes pointing to an interface
(these are called non-recursive routes).
When BGP receives a recursive route from a peer, it needs to validate the
nexthop. The path is marked valid or invalid based on the reachability status
of the nexthop. Nexthop validation is also important for BGP decision process
as the metric to reach the nexthop is a parameter to best path selection
process.
As it goes with routing, this is a dynamic process. Route to the nexthop can
change. The nexthop can become unreachable or reachable. In the current BGP
implementation, the nexthop validation is done periodically in the scanner run.
The default scanner run interval is one minute. Every minute, the scanner task
walks the entire BGP table. It checks the validity of each nexthop with Zebra
(the routing table manager) through a request and response message exchange
between BGP and Zebra process. BGP process is blocked for that duration. The
mechanism has two major drawbacks:
- The scanner task runs to completion. That can potentially starve the other
tasks for long periods of time, based on the BGP table size and number of
nexthops.
- Convergence around routing changes that affect the nexthops can be long
(around a minute with the default intervals). The interval can be shortened
to achieve faster reaction time, but it makes the first problem worse, with
the scanner task consuming most of the CPU resources.
The next-hop tracking feature makes this process event-driven. It eliminates
periodic nexthop validation and introduces an asynchronous communication path
between BGP and Zebra for route change notifications that can then be acted
upon.
Goal
----
Stating the obvious, the main goal is to remove the two limitations we
discussed in the previous section. The goals, in a constructive tone,
are the following:
- **Fairness**: the scanner run should not consume an unjustly high amount of
CPU time. This should give an overall good performance and response time to
other events (route changes, session events, IO/user interface).
- **Convergence**: BGP must react to nexthop changes instantly and provide
sub-second convergence. This may involve diverting the routes from one
nexthop to another.
Overview of changes
------------------------
The changes are in both BGP and Zebra modules. The short summary is
the following:
- Zebra implements a registration mechanism by which clients can
register for next hop notification. Consequently, it maintains a
separate table, per (VRF, AF) pair, of next hops and interested
client-list per next hop.
- When the main routing table changes in Zebra, it evaluates the next
hop table: for each next hop, it checks if the route table
modifications have changed its state. If so, it notifies the
interested clients.
- BGP is one such client. It registers the next hops corresponding to
all of its received routes/paths. It also threads the paths against
each nexthop structure.
- When BGP receives a next hop notification from Zebra, it walks the
corresponding path list. It makes them valid or invalid depending
on the next hop notification. It then re-computes best path for the
corresponding destination. This may result in re-announcing those
destinations to peers.
Design
------
Modules
~~~~~~~
The core design introduces an "nht" (next hop tracking) module in BGP
and "rnh" (recursive nexthop) module in Zebra. The "nht" module
provides the following APIs:
+----------------------------+--------------------------------------------------+
| Function | Action |
+============================+==================================================+
| bgp_find_or_add_nexthop() | find or add a nexthop in BGP nexthop table |
+----------------------------+--------------------------------------------------+
| bgp_find_nexthop() | find a nexthop in BGP nexthop table |
+----------------------------+--------------------------------------------------+
| bgp_parse_nexthop_update() | parse a nexthop update message coming from zebra |
+----------------------------+--------------------------------------------------+
The "rnh" module provides the following APIs:
+----------------------------+----------------------------------------------------------------------------------------------------------+
| Function | Action |
+============================+==========================================================================================================+
| zebra_add_rnh() | add a recursive nexthop |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_delete_rnh() | delete a recursive nexthop |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_lookup_rnh() | lookup a recursive nexthop |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_add_rnh_client() | register a client for nexthop notifications against a recursive nexthop |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_remove_rnh_client() | remove the client registration for a recursive nexthop |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_evaluate_rnh_table() | (re)evaluate the recursive nexthop table (most probably because the main routing table has changed). |
+----------------------------+----------------------------------------------------------------------------------------------------------+
| zebra_cleanup_rnh_client() | Cleanup a client from the "rnh" module data structures (most probably because the client is going away). |
+----------------------------+----------------------------------------------------------------------------------------------------------+
4.2. Control flow
The next hop registration control flow is the following:
::
<==== BGP Process ====>|<==== Zebra Process ====>
|
receive module nht module | zserv module rnh module
----------------------------------------------------------------------
| | |
bgp_update_ | | |
main() | bgp_find_or_add_ | |
| nexthop() | |
| | |
| | zserv_nexthop_ |
| | register() |
| | | zebra_add_rnh()
| | |
The next hop notification control flow is the following:
::
<==== Zebra Process ====>|<==== BGP Process ====>
|
rib module rnh module | zebra module nht module
----------------------------------------------------------------------
| | |
meta_queue_ | | |
process() | zebra_evaluate_ | |
| rnh_table() | |
| | |
| | bgp_read_nexthop_ |
| | update() |
| | | bgp_parse_
| | | nexthop_update()
| | |
zclient message format
~~~~~~~~~~~~~~~~~~~~~~
ZEBRA_NEXTHOP_REGISTER and ZEBRA_NEXTHOP_UNREGISTER messages are
encoded in the following way:
::
. 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AF | prefix len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. Nexthop prefix .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AF | prefix len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. Nexthop prefix .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
``ZEBRA_NEXTHOP_UPDATE`` message is encoded as follows:
::
. 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AF | prefix len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. Nexthop prefix getting resolved .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| metric |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| #nexthops |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| nexthop type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. resolving Nexthop details .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| nexthop type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. resolving Nexthop details .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
BGP data structure
~~~~~~~~~~~~~~~~~~
Legend:
::
/\ struct bgp_node: a BGP destination/route/prefix
\/
[ ] struct bgp_info: a BGP path (e.g. route received from a peer)
_
(_) struct bgp_nexthop_cache: a BGP nexthop
/\ NULL
\/--+ ^
| :
+--[ ]--[ ]--[ ]--> NULL
/\ :
\/--+ :
| :
+--[ ]--[ ]--> NULL
:
_ :
(_)...........
Zebra data structure
~~~~~~~~~~~~~~~~~~~~
RNH table::
O
/ \
O O
/ \
O O
struct rnh
{
u_char flags;
struct route_entry *state;
struct list *client_list;
struct route_node *node;
};
User interface changes
~~~~~~~~~~~~~~~~~~~~~~
::
frr# show ip nht
3.3.3.3
resolved via kernel
via 11.0.0.6, swp1
Client list: bgp(fd 12)
11.0.0.10
resolved via connected
is directly connected, swp2
Client list: bgp(fd 12)
11.0.0.18
resolved via connected
is directly connected, swp4
Client list: bgp(fd 12)
11.11.11.11
resolved via kernel
via 10.0.1.2, eth0
Client list: bgp(fd 12)
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.0.0.10 valid [IGP metric 1], #paths 1
Last update: Wed Oct 16 04:43:51 2013
11.0.0.18 valid [IGP metric 1], #paths 2
Last update: Wed Oct 16 04:43:47 2013
11.11.11.11 valid [IGP metric 0], #paths 1
Last update: Wed Oct 16 04:43:47 2013
frr# show ipv6 nht
frr# show ip bgp nexthop detail
frr# debug bgp nht
frr# debug zebra nht
6. Sample test cases
r2----r3
/ \ /
r1----r4
- Verify that a change in IGP cost triggers NHT
+ shutdown the r1-r4 and r2-r4 links
+ no shut the r1-r4 and r2-r4 links and wait for OSPF to come back
up
+ We should be back to the original nexthop via r4 now
- Verify that a NH becoming unreachable triggers NHT
+ Shutdown all links to r4
- Verify that a NH becoming reachable triggers NHT
+ no shut all links to r4
Future work
~~~~~~~~~~~
- route-policy for next hop validation (e.g. ignore default route)
- damping for rapid next hop changes
- prioritized handling of nexthop changes ((un)reachability vs. metric
changes)
- handling recursion loop, e.g::
11.11.11.11/32 -> 12.12.12.12
12.12.12.12/32 -> 11.11.11.11
11.0.0.0/8 -> <interface>
- better statistics

388
doc/developer/ospf-api.rst Normal file
View File

@ -0,0 +1,388 @@
OSPF API Documentation
======================
Disclaimer
----------
The OSPF daemon contains an API for application access to the LSA
database. This API was created by Ralph Keller, originally as patch for
Zebra. Unfortunately, the page containing documentation of the API is no
longer online. This page is an attempt to recreate documentation for the
API (with lots of help of the WayBackMachine)
Introduction
------------
This page describes an API that allows external applications to access
the link-state database (LSDB) of the OSPF daemon. The implementation is
based on the OSPF code from FRRouting (forked from Quagga and formerly
Zebra) routing protocol suite and is subject to the GNU General Public
License. The OSPF API provides you with the following functionality:
- Retrieval of the full or partial link-state database of the OSPF
daemon. This allows applications to obtain an exact copy of the LSDB
including router LSAs, network LSAs and so on. Whenever a new LSA
arrives at the OSPF daemon, the API module immediately informs the
application by sending a message. This way, the application is always
synchronized with the LSDB of the OSPF daemon.
- Origination of own opaque LSAs (of type 9, 10, or 11) which are then
distributed transparently to other routers within the flooding scope
and received by other applications through the OSPF API.
Opaque LSAs, which are described in RFC 2370 , allow you to distribute
application-specific information within a network using the OSPF
protocol. The information contained in opaque LSAs is transparent for
the routing process but it can be processed by other modules such as
traffic engineering (e.g., MPLS-TE).
Architecture
------------
The following picture depicts the architecture of the Quagga/Zebra
protocol suite. The OSPF daemon is extended with opaque LSA capabilities
and an API for external applications. The OSPF core module executes the
OSPF protocol by discovering neighbors and exchanging neighbor state.
The opaque module, implemented by Masahiko Endo, provides functions to
exchange opaque LSAs between routers. Opaque LSAs can be generated by
several modules such as the MPLS-TE module or the API server module.
These modules then invoke the opaque module to flood their data to
neighbors within the flooding scope.
The client, which is an application potentially running on a different
node than the OSPF daemon, links against the OSPF API client library.
This client library establishes a socket connection with the API server
module of the OSPF daemon and uses this connection to retrieve LSAs and
originate opaque LSAs.
.. figure:: ../figures/ospf_api_architecture.png
:alt: image
image
The OSPF API server module works like any other internal opaque module
(such as the MPLS-TE module), but listens to connections from external
applications that want to communicate with the OSPF daemon. The API
server module can handle multiple clients concurrently.
One of the main objectives of the implementation is to make as little
changes to the existing Zebra code as possible.
Installation & Configuration
----------------------------
Download FRRouting and unpack
Configure your frr version (note that --enable-opaque-lsa also enables
the ospfapi server and ospfclient).
::
% update-autotools
% sh ./configure --enable-opaque-lsa
% make
This should also compile the client library and sample application in
ospfclient.
Make sure that you have enabled opaque LSAs in your configuration. Add
the ospf opaque-lsa statement to your ospfd.conf:
::
! -*- ospf -*-
!
! OSPFd sample configuration file
!
!
hostname xxxxx
password xxxxx
router ospf
router-id 10.0.0.1
network 10.0.0.1/24 area 1
neighbor 10.0.0.2
network 10.0.1.2/24 area 1
neighbor 10.0.1.1
ospf opaque-lsa <============ add this statement!
Usage
-----
In the following we describe how you can use the sample application to
originate opaque LSAs. The sample application first registers with the
OSPF daemon the opaque type it wants to inject and then waits until the
OSPF daemon is ready to accept opaque LSAs of that type. Then the client
application originates an opaque LSA, waits 10 seconds and then updates
the opaque LSA with new opaque data. After another 20 seconds, the
client application deletes the opaque LSA from the LSDB. If the clients
terminates unexpectedly, the OSPF API module will remove all the opaque
LSAs that the application registered. Since the opaque LSAs are flooded
to other routers, we will see the opaque LSAs in all routers according
to the flooding scope of the opaque LSA.
We have a very simple demo setup, just two routers connected with an ATM
point-to-point link. Start the modified OSPF daemons on two adjacent
routers. First run on msr2:
::
> msr2:/home/keller/ospfapi/zebra/ospfd# ./ospfd -f /usr/local/etc/ospfd.conf
And on the neighboring router msr3:
::
> msr3:/home/keller/ospfapi/zebra/ospfd# ./ospfd -f /usr/local/etc/ospfd.conf
Now the two routers form adjacency and start exchanging their databases.
Looking at the OSPF daemon of msr2 (or msr3), you see this:
::
ospfd> show ip ospf database
OSPF Router with ID (10.0.0.1)
Router Link States (Area 0.0.0.1)
Link ID ADV Router Age Seq# CkSum Link count
10.0.0.1 10.0.0.1 55 0x80000003 0xc62f 2
10.0.0.2 10.0.0.2 55 0x80000003 0xe3e4 3
Net Link States (Area 0.0.0.1)
Link ID ADV Router Age Seq# CkSum
10.0.0.2 10.0.0.2 60 0x80000001 0x5fcb
Now we start the sample main application that originates an opaque LSA.
::
> cd ospfapi/apiclient
> ./main msr2 10 250 20 0.0.0.0 0.0.0.1
This originates an opaque LSA of type 10 (area local), with opaque type
250 (experimental), opaque id of 20 (chosen arbitrarily), interface
address 0.0.0.0 (which is used only for opaque LSAs type 9), and area
0.0.0.1
Again looking at the OSPF database you see:
::
ospfd> show ip ospf database
OSPF Router with ID (10.0.0.1)
Router Link States (Area 0.0.0.1)
Link ID ADV Router Age Seq# CkSum Link count
10.0.0.1 10.0.0.1 437 0x80000003 0xc62f 2
10.0.0.2 10.0.0.2 437 0x80000003 0xe3e4 3
Net Link States (Area 0.0.0.1)
Link ID ADV Router Age Seq# CkSum
10.0.0.2 10.0.0.2 442 0x80000001 0x5fcb
Area-Local Opaque-LSA (Area 0.0.0.1)
Opaque-Type/Id ADV Router Age Seq# CkSum
250.0.0.20 10.0.0.1 0 0x80000001 0x58a6 <=== opaque LSA
You can take a closer look at this opaque LSA:
::
ospfd> show ip ospf database opaque-area
OSPF Router with ID (10.0.0.1)
Area-Local Opaque-LSA (Area 0.0.0.1)
LS age: 4
Options: 66
LS Type: Area-Local Opaque-LSA
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
Advertising Router: 10.0.0.1
LS Seq Number: 80000001
Checksum: 0x58a6
Length: 24
Opaque-Type 250 (Private/Experimental)
Opaque-ID 0x14
Opaque-Info: 4 octets of data
Added using OSPF API: 4 octets of opaque data
Opaque data: 1 0 0 0 <==== counter is 1
Note that the main application updates the opaque LSA after 10 seconds,
then it looks as follows:
::
ospfd> show ip ospf database opaque-area
OSPF Router with ID (10.0.0.1)
Area-Local Opaque-LSA (Area 0.0.0.1)
LS age: 1
Options: 66
LS Type: Area-Local Opaque-LSA
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
Advertising Router: 10.0.0.1
LS Seq Number: 80000002
Checksum: 0x59a3
Length: 24
Opaque-Type 250 (Private/Experimental)
Opaque-ID 0x14
Opaque-Info: 4 octets of data
Added using OSPF API: 4 octets of opaque data
Opaque data: 2 0 0 0 <==== counter is now 2
Note that the payload of the opaque LSA has changed as you can see
above.
Then, again after another 20 seconds, the opaque LSA is flushed from the
LSDB.
Important note:
^^^^^^^^^^^^^^^
In order to originate an opaque LSA, there must be at least one active
opaque-capable neighbor. Thus, you cannot originate opaque LSAs of no
neighbors are present. If you try to originate even so no neighbor is
ready, you will receive a not ready error message. The reason for this
restriction is that it might be possible that some routers have an
identical opaque LSA from a previous origination in their LSDB that
unfortunately could not be flushed due to a crash, and now if the router
comes up again and starts originating a new opaque LSA, the new opaque
LSA is considered older since it has a lower sequence number and is
ignored by other routers (that consider the stalled opaque LSA as more
recent). However, if the originating router first synchronizes the
database before originating opaque LSAs, it will detect the older opaque
LSA and can flush it first.
Protocol and Message Formats
----------------------------
If you are developing your own client application and you don't want to
make use of the client library (due to the GNU license restriction or
whatever reason), you can implement your own client-side message
handling. The OSPF API uses two connections between the client and the
OSPF API server: One connection is used for a synchronous request /reply
protocol and another connection is used for asynchronous notifications
(e.g., LSA update, neighbor status change).
Each message begins with the following header:
.. figure:: ../figures/ospf_api_msghdr.png
:alt: image
image
The message type field can take one of the following values:
+-------------------------------+---------+
| Messages to OSPF deamon | Value |
+===============================+=========+
| MSG\_REGISTER\_OPAQUETYPE | 1 |
+-------------------------------+---------+
| MSG\_UNREGISTER\_OPAQUETYPE | 2 |
+-------------------------------+---------+
| MSG\_REGISTER\_EVENT | 3 |
+-------------------------------+---------+
| MSG\_SYNC\_LSDB | 4 |
+-------------------------------+---------+
| MSG\_ORIGINATE\_REQUEST | 5 |
+-------------------------------+---------+
| MSG\_DELETE\_REQUEST | 6 |
+-------------------------------+---------+
+-----------------------------+---------+
| Messages from OSPF deamon | Value |
+=============================+=========+
| MSG\_REPLY | 10 |
+-----------------------------+---------+
| MSG\_READY\_NOTIFY | 11 |
+-----------------------------+---------+
| MSG\_LSA\_UPDATE\_NOTIFY | 12 |
+-----------------------------+---------+
| MSG\_LSA\_DELETE\_NOTIFY | 13 |
+-----------------------------+---------+
| MSG\_NEW\_IF | 14 |
+-----------------------------+---------+
| MSG\_DEL\_IF | 15 |
+-----------------------------+---------+
| MSG\_ISM\_CHANGE | 16 |
+-----------------------------+---------+
| MSG\_NSM\_CHANGE | 17 |
+-----------------------------+---------+
The synchronous requests and replies have the following message formats:
.. figure:: ../figures/ospf_api_msgs1.png
:alt: image
image
The origin field allows to select according to the following types of
origins:
+-------------------------+---------+
| Origin | Value |
+=========================+=========+
| NON\_SELF\_ORIGINATED | 0 |
+-------------------------+---------+
| SELF\_ORIGINATED | 1 |
+-------------------------+---------+
| ANY\_ORIGIN | 2 |
+-------------------------+---------+
The reply message has on of the following error codes:
+--------------------------+---------+
| Error code | Value |
+==========================+=========+
| API\_OK | 0 |
+--------------------------+---------+
| API\_NOSUCHINTERFACE | -1 |
+--------------------------+---------+
| API\_NOSUCHAREA | -2 |
+--------------------------+---------+
| API\_NOSUCHLSA | -3 |
+--------------------------+---------+
| API\_ILLEGALSATYPE | -4 |
+--------------------------+---------+
| API\_ILLEGALOPAQUETYPE | -5 |
+--------------------------+---------+
| API\_OPAQUETYPEINUSE | -6 |
+--------------------------+---------+
| API\_NOMEMORY | -7 |
+--------------------------+---------+
| API\_ERROR | -99 |
+--------------------------+---------+
| API\_UNDEF | -100 |
+--------------------------+---------+
The asynchronous notifications have the following message formats:
.. figure:: ../figures/ospf_api_msgs2.png
:alt: image
image
Original Acknowledgments from Ralph Keller
------------------------------------------
I would like to thank Masahiko Endo, the author of the opaque LSA
extension module, for his great support. His wonderful ASCII graphs
explaining the internal workings of this code, and his invaluable input
proved to be crucial in designing a useful API for accessing the link
state database of the OSPF daemon. Once, he even decided to take the
plane from Tokyo to Zurich so that we could actually meet and have
face-to-face discussions, which was a lot of fun. Clearly, without
Masahiko no API would ever be completed. I also would like to thank
Daniel Bauer who wrote an opaque LSA implementation too and was willing
to test the OSPF API code in one of his projects.

View File

@ -21,9 +21,9 @@ Supported Features
Interoperability Interoperability
---------------- ----------------
* tested on various topology including point-to-point and LAN interfaces * Tested on various topology including point-to-point and LAN interfaces
in a mix of Free Range Routing instance and Cisco IOS-XR 6.0.x in a mix of Free Range Routing instance and Cisco IOS-XR 6.0.x
* check OSPF LSA conformity with latest wireshark release 2.5.0-rc * Check OSPF LSA conformity with latest wireshark release 2.5.0-rc
Implementation details Implementation details
---------------------- ----------------------
@ -196,17 +196,17 @@ yourself:
:: ::
modprobe mpls_router modprobe mpls_router
modprobe mpls_gso modprobe mpls_gso
modprobe mpls_iptunnel modprobe mpls_iptunnel
Then, you must activate MPLS on the interface you would used: Then, you must activate MPLS on the interface you would used:
:: ::
sysctl -w net.mpls.conf.enp0s9.input=1 sysctl -w net.mpls.conf.enp0s9.input=1
sysctl -w net.mpls.conf.lo.input=1 sysctl -w net.mpls.conf.lo.input=1
sysctl -w net.mpls.platform_labels=1048575 sysctl -w net.mpls.platform_labels=1048575
The last line fix the maximum MPLS label value. The last line fix the maximum MPLS label value.
@ -215,8 +215,8 @@ enable with:
:: ::
ip -M route ip -M route
ip route ip route
The first command show the MPLS LFIB table while the second show the FIB The first command show the MPLS LFIB table while the second show the FIB
table which contains route with MPLS label encapsulation. table which contains route with MPLS label encapsulation.
@ -227,8 +227,8 @@ especially the `lo` one. For that purpose, disable RP filtering with:
:: ::
systcl -w net.ipv4.conf.all.rp_filter=0 systcl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.lo.rp_filter=0 sysctl -w net.ipv4.conf.lo.rp_filter=0
OSPFd OSPFd
~~~~~ ~~~~~
@ -240,16 +240,16 @@ Routing.
:: ::
router ospf router ospf
ospf router-id 192.168.1.11 ospf router-id 192.168.1.11
capability opaque capability opaque
mpls-te on mpls-te on
mpls-te router-address 192.168.1.11 mpls-te router-address 192.168.1.11
router-info area 0.0.0.0 router-info area 0.0.0.0
segment-routing on segment-routing on
segment-routing global-block 10000 19999 segment-routing global-block 10000 19999
segment-routing node-msd 8 segment-routing node-msd 8
segment-routing prefix 192.168.1.11/32 index 1100 segment-routing prefix 192.168.1.11/32 index 1100
The first segment-routing statement enable it. The Second one set the SRGB, The first segment-routing statement enable it. The Second one set the SRGB,
third line the MSD and finally, set the Prefix SID index for a given prefix. third line the MSD and finally, set the Prefix SID index for a given prefix.
@ -283,4 +283,3 @@ This work has been performed in the framework of the H2020-ICT-2014
project 5GEx (Grant Agreement no. 671636), which is partially funded project 5GEx (Grant Agreement no. 671636), which is partially funded
by the European Commission. by the European Commission.

657
doc/developer/workflow.rst Normal file
View File

@ -0,0 +1,657 @@
.. _process-and-workflow:
*******************
Process & Workflow
*******************
FRR is a large project developed by many different groups. This section
documents standards for code style & quality, commit messages, pull requests
and best practices that all contributors are asked to follow.
This chapter is "descriptive/post-factual" in that it documents pratices that
are in use; it is not "definitive/pre-factual" in prescribing practices. This
means that when a procedure changes, it is agreed upon, then put into practice,
and then documented here. If this document doesn't match reality, it's the
document that needs to be updated, not reality.
Mailing Lists
=============
The FRR development group maintains multiple mailing lists for use by the
community. Italicized lists are private.
+----------------------------------+--------------------------------+
| Topic | List |
+==================================+================================+
| Development | dev@lists.frrouting.org |
+----------------------------------+--------------------------------+
| Users & Operators | frog@lists.frrouting.org |
+----------------------------------+--------------------------------+
| Announcements | announce@lists.frrouting.org |
+----------------------------------+--------------------------------+
| *Security* | security@lists.frrouting.org |
+----------------------------------+--------------------------------+
| *Technical Steering Committee* | tsc@lists.frrouting.org |
+----------------------------------+--------------------------------+
The Development list is used to discuss and document general issues related to
project development and governance. The public Slack instance,
frrouting.slack.com, and weekly technical meetings provide a higher bandwidth
channel for discussions. The results of such discussions must be reflected in
updates, as appropriate, to code (i.e., merges), `Github issues`_, and for
governance or process changes, updates to the Development list and either this
file or information posted at https://frrouting.org/.
Changelog
=========
The changelog will be the base for the release notes. A changelog entry for
your changes is usually not required and will be added based on your commit
messages by the maintainers. However, you are free to include an update to the
changelog with some better description.
Submitting Patches and Enhancements
===================================
FRR accepts patches from two sources:
- Email (git format-patch)
- Github pull request
Contributors are highly encouraged to use Github's fork-and-pr workflow. It is
easier for us to review it, test it, try it and discuss it on Github than it is
via email, thus your patch will get more attention more quickly on Github.
The base branch for new contributions and non-critical bug fixes should be
``master``. Please ensure your pull request is based on this branch when you
submit it.
Pre-submission Checklist
------------------------
- Format code (see `Code Formatting <#developers-guidelines>`__)
- Verify and acknowledge license (see `License for
contributions <#license-for-contributions>`__)
- Ensure you have properly signed off (see `Signing
Off <#signing-off>`__)
- Test building with various configurations:
- ``buildtest.sh``
- Verify building source distribution:
- ``make dist`` (and try rebuilding from the resulting tar file)
- Run unit tests:
- ``make test``
- Document Regression Runs and plans for continued maintenance of the
feature
License for contributions
-------------------------
FRR is under a “GPLv2 or later” license. Any code submitted must
be released under the same license (preferred) or any license which
allows redistribution under this GPLv2 license (eg MIT License).
Signing Off
-----------
Code submitted to FRR must be signed off. We have the same
requirements for using the signed-off-by process as the Linux kernel. In
short, you must include a signed-off-by tag in every patch.
``Signed-off-by:`` this is a developer's certification that he or she
has the right to submit the patch for inclusion into the project. It is
an agreement to the Developer's Certificate of Origin (below). Code
without a proper signoff can not and will not be merged.
If you are unfamiliar with this process, you should read the `official
policy at
kernel.org <https://www.kernel.org/doc/html/latest/process/submitting-patches.html>`__
and you might find this article about `participating in the Linux
community on the Linux Foundation
website <http://www.linuxfoundation.org/content/how-participate-linux-community-0>`__
to be a helpful resource.
In short, when you sign off on a commit, you assert your agreement to
all of the following:
::
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part by
me, under the same open source license (unless I am permitted to
submit under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
What do I submit my changes against?
------------------------------------
We've documented where we would like to have the different fixes applied
at
https://github.com/FRR/frr/wiki/Where-Do-I-create-a-Pull-Request-against%3F
If you are unsure where your submission goes, look at that document or
ask a project maintainer.
Github pull requests
--------------------
The preferred method of submitting changes is a Github pull request.
Code submitted by pull request will be automatically tested by one or
more CI systems. Once the automated tests succeed, other developers will
review your code for quality and correctness. After any concerns are
resolved, your code will be merged into the branch it was submitted
against.
Patch submission via mailing list
---------------------------------
As an alternative submission method, a patch can be mailed to the
development mailing list. Patches received on the mailing list will be
picked up by Patchwork and tested against the latest development branch.
The recommended way to send the patch (or series of NN patches) to the
list is by using ``git send-email`` as follows (assuming they are the N
most recent commit(s) in your git history:
::
git send-email -NN --annotate --to=dev@lists.frrouting.org
If your commits do not already contain a ``Signed-off-by`` line, then
use the following command to add it (after making sure you agree to the
Developer Certificate of Origin as outlined above):
::
git send-email -NN --annotate --signoff --to=dev@lists.frrouting.org
Submitting multi-commit patches as a Github pull request is **strongly
encouraged** and increases the probability of your patch getting
reviewed and merged in a timely manner.
After submitting your changes
-----------------------------
- Watch for Continuous Integration (CI) Test results
- You should automatically receive an email with the test results
within less than 2 hrs of the submission. If you dont get the
email, then check status on the Github pull request.
- Please notify the development mailing list if you think something
doesn't work.
- If the tests failed:
- In general, expect the community to ignore the submission until
the tests pass.
- It is up to you to fix and resubmit.
- This includes fixing existing unit (“make test”) tests if your
changes broke or changed them.
- It also includes fixing distribution packages for the failing
platforms (ie if new libraries are required).
- Feel free to ask for help on the development list.
- Go back to the submission process and repeat until the tests pass.
- If the tests pass:
- Wait for reviewers. Someone will review your code or be assigned
to review your code.
- Respond to any comments or concerns the reviewer has.
- After all comments and concerns are addressed, expect your patch
to be merged.
- Watch out for questions on the mailing list. At this time there will
be a manual code review and further (longer) tests by various
community members.
- Your submission is done once it is merged to the master branch.
Git Structure
=============
.. figure:: ../figures/git_branches.png
:align: center
:scale: 55%
:alt: Merging Git branches into a central trunk
Rough outline of FRR development workflow
The master Git for FRR resides on `GitHub`_.
There is one main branch for development, ``master``. For each major release
(2.0, 3.0 etc) a new release branch is created based on the master. Subsequent
point releases based on a major branch are marked by tagging.
Programming Languages, Tools and Libraries
==========================================
The core of FRR is written in C (gcc or clang supported) and makes
use of GNU compiler extensions. A few non-essential scripts are
implemented in Perl and Python. FRR requires the following tools
to build distribution packages: automake, autoconf, texinfo, libtool and
gawk and various libraries (i.e. libpam and libjson-c).
If your contribution requires a new library or other tool, then please
highlight this in your description of the change. Also make sure its
supported by all FRR platform OSes or provide a way to build
without the library (potentially without the new feature) on the other
platforms.
Documentation should be written in reStructuredText. Sphinx extensions may be
utilized but pure ReST is preferred where possible. See
:ref:`documentation`.
Coding Practices & Style
========================
Commit messages
---------------
Commit messages should be formatted in the same way as Linux kernel
commit messages. The format is roughly
::
dir: short summary
extended summary
``dir`` should be the top level source directory under which the change
was made. For example, a change in bgpd/rfapi would be formatted as:::
bgpd: short summary
The first line should be no longer than 50 characters. Subsequent lines
should be wrapped to 72 characters.
Source file header
------------------
New files need to have a Copyright header (see `License for
contributions <#license-for-contributions>`__ above) added to the file.
Preferred form of the header is as follows:
::
/*
* Title/Function of file
* Copyright (C) YEAR Authors Name
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
Adding copyright claims to existing files
-----------------------------------------
When adding copyright claims for modifications to an existing file,
please preface the claim with "Portions: " on a line before it and
indent the "Copyright ..." string. If such a case already exists, add
your indented claim immediately after. E.g.:
::
Portions:
Copyright (C) 2010 Entity A ....
Copyright (C) 2016 Your name [optional brief change description]
Code formatting
---------------
FRR uses Linux kernel style except where noted below. Code which does
not comply with these style guidelines will not be accepted.
To assist with compliance, in the project root there is a .clang-format
configuration file which can be used with the ``clang-format`` tool from
the LLVM project. In the ``tools/`` directory there is a Python script
named ``indent.py`` that wraps clang-format and handles some edge cases
specific to FRR. If you are submitting a new file, it is recommended to
run that script over the new file after ensuring that the latest stable
release of ``clang-format`` is in your PATH.
**Whitespace changes in untouched parts of the code are not acceptable
in patches that change actual code.** To change/fix formatting issues,
please create a separate patch that only does formatting changes and
nothing else.
Kernel and BSD styles are documented externally:
- https://www.kernel.org/doc/html/latest/process/coding-style.html
- http://man.openbsd.org/style
For GNU coding style, use ``indent`` with the following invocation:
::
indent -nut -nfc1 file_for_submission.c
Exceptions
^^^^^^^^^^
FRR project code comes from a variety of sources, so there are some
stylistic exceptions in place. They are organized here by branch.
For ``master``
""""""""""""""
BSD coding style applies to:
- ``ldpd/``
``babeld`` uses, approximately, the following style:
- K&R style braces
- Indents are 4 spaces
- Function return types are on their own line
For ``stable/3.0`` and ``stable/2.0``
"""""""""""""""""""""""""""""""""""""
GNU coding style apply to the following parts:
- ``lib/``
- ``zebra/``
- ``bgpd/``
- ``ospfd/``
- ``ospf6d/``
- ``isisd/``
- ``ripd/``
- ``ripngd/``
- ``vtysh/``
BSD coding style applies to:
- ``ldpd/``
Compile-time conditional code
-----------------------------
Many users access FRR via binary packages from 3rd party sources;
compile-time code puts inclusion/exclusion in the hands of the package
maintainer. Please think very carefully before making code conditional
at compile time, as it increases regression testing, maintenance
burdens, and user confusion. In particular, please avoid gratuitous
``--enable-…`` switches to the configure script - in general, code
should be of high quality and in working condition, or it shouldnt be
in FRR at all.
When code must be compile-time conditional, try have the compiler make
it conditional rather than the C pre-processor so that it will still be
checked by the compiler, even if disabled. For example,
::
if (SOME_SYMBOL)
frobnicate();
is preferred to
::
#ifdef SOME_SYMBOL
frobnicate ();
#endif /* SOME_SYMBOL */
Note that the former approach requires ensuring that ``SOME_SYMBOL``
will be defined (watch your ``AC_DEFINE``\ s).
Debug-guards in code
--------------------
Debugging statements are an important methodology to allow developers to
fix issues found in the code after it has been released. The caveat here
is that the developer must remember that people will be using the code
at scale and in ways that can be unexpected for the original
implementor. As such debugs **MUST** be guarded in such a way that they
can be turned off. FRR 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.
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.
Backwards Compatibility
-----------------------
As a general principle, changes to CLI and code in the lib/ directory
should be made in a backwards compatible fashion. This means that
changes that are purely stylistic in nature should be avoided, e.g.,
renaming an existing macro or library function name without any
functional change. When adding new parameters to common functions, it is
also good to consider if this too should be done in a backward
compatible fashion, e.g., by preserving the old form in addition to
adding the new form.
This is not to say that minor or even major functional changes to CLI
and common code should be avoided, but rather that the benefit gained
from a change should be weighed against the added cost/complexity to
existing code. Also, that when making such changes, it is good to
preserve compatibility when possible to do so without introducing
maintenance overhead/cost. It is also important to keep in mind,
existing code includes code that may reside in private repositories (and
is yet to be submitted) or code that has yet to be migrated from Quagga
to FRR.
That said, compatibility measures can (and should) be removed when
either:
- they become a significant burden, e.g. when data structures change
and the compatibility measure would need a complex adaptation layer
or becomes flat-out impossible
- some measure of time (dependent on the specific case) has passed, so
that the compatibility grace period is considered expired.
In all cases, compatibility pieces should be marked with
compiler/preprocessor annotations to print warnings at compile time,
pointing to the appropriate update path. A ``-Werror`` build should fail
if compatibility bits are used.
Miscellaneous
-------------
When in doubt, follow the guidelines in the Linux kernel style guide, or
ask on the development mailing list / public Slack instance.
.. _documentation:
Documentation
=============
FRR uses Sphinx+RST as its documentation system. The document you are currently
reading was generated by Sphinx from RST source in
:file:`doc/developer/workflow.rst`. The documentation is structured as follows:
+-----------------------+--------------------------------------------------------------+
| Directory | Contents |
+=======================+==============================================================+
| :file:`doc/user` | User documentation; configuration guides; protocol overviews |
+-----------------------+--------------------------------------------------------------+
| :file:`doc/developer` | Developer's documentation; API specs; datastructures; |
| | architecture overviews; project management procedure |
+-----------------------+--------------------------------------------------------------+
| :file:`doc/manpages` | Source for manpages |
+-----------------------+--------------------------------------------------------------+
| :file:`doc/figures` | Images and diagrams |
+-----------------------+--------------------------------------------------------------+
Each of these directories, with the exception of :file:`doc/figures`, contains
a Sphinx-generated Makefile and configuration script :file:`conf.py` used to
set various document parameters. The makefile can be used for a variety of
targets; invoke `make help` in any of these directories for a listing of
available output formats. For convenience, there is a top-level
:file:`Makefile.am` that has targets for PDF and HTML documentation for both
developer and user documentation, respectively. That makefile is also
responsible for building manual pages packed with distribution builds.
Indent and styling should follow existing conventions:
- 3 spaces for indents under directives
- Cross references may contain only lowercase alphanumeric characters and
hyphens ('-')
- Lines wrapped to 80 characters where possible
Characters for header levels should follow Python documentation guide:
- ``#`` with overline, for parts
- ``*`` with overline, for chapters
- ``=``, for sections
- ``-``, for subsections
- ``^``, for subsubsections
- ``"``, for paragraphs
After you have made your changes, please make sure that you can invoke
``make latexpdf`` and ``make html`` with no warnings.
The documentation is currently incomplete and needs love. If you find a broken
cross-reference, figure, dead hyperlink, style issue or any other nastiness we
gladly accept documentation patches.
To build the docs, please ensure you have installed a recent version of
`Sphinx <http://www.sphinx-doc.org/en/stable/install.html>`_. If you want to
build LaTeX or PDF docs, you will also need a full LaTeX distribution
installed.
Code
----
FRR is a large and complex software project developed by many different people
over a long period of time. Without adequate documentation, it can be
exceedingly difficult to understand code segments, APIs and other interfaces.
In the interest of keeping the project healthy and maintainable, you should
make every effort to document your code so that other people can understand
what it does without needing to closely read the code itself.
Some specific guidelines that contributors should follow are:
- Functions exposed in header files should have descriptive comments above
their signatures in the header file. At a minimum, a function comment should
contain information about the return value, parameters, and a general summary
of the function's purpose. Documentation on parameter values can be omitted
if it is (very) obvious what they are used for.
Function comments must follow the style for multiline comments laid out in
the kernel style guide.
Example:
.. code-block:: c
/*
* Determines whether or not a string is cool.
*
* @param text - the string to check for coolness
* @param is_clccfc - whether capslock is cruise control for cool
* @return 7 if the text is cool, 0 otherwise
*/
int check_coolness(const char *text, bool is_clccfc);
The Javadoc-style annotations are not required, but you should still strive
to make it equally clear what parameters and return values are used for.
- Static functions should have descriptive comments in the same form as above
if what they do is not immediately obvious. Use good engineering judgement
when deciding whether a comment is necessary. If you are unsure, document
your code.
- Global variables, static or not, should have a comment describing their use.
- **For new code in lib/, these guidelines are hard requirements.**
If you make significant changes to portions of the codebase covered in the
Developer's Manual, add a major subsystem or feature, or gain arcane mastery of
some undocumented or poorly documented part of the codebase, please document
your work so others can benefit. If you add a major feature or introduce a new
API, please document the architecture and API to the best of your abilities in
the Developer's Manual, using good judgement when choosing where to place it.
Finally, if you come across some code that is undocumented and feel like
going above and beyond, document it! We absolutely appreciate and accept
patches that document previously undocumented code.
User
----
If you are contributing code that adds significant user-visible functionality
please document how to use it in :file:`doc/user`. Use good judgement when
choosing where to place documentation. For example, instructions on how to use
your implementation of a new BGP draft should go in the BGP chapter instead of
being its own chapter. If you are adding a new protocol daemon, please create a
new chapter.
When documenting CLI please use a combination of the ``.. index::`` and
``.. clicmd::`` directives. For example, the command :clicmd:`show pony` would
be documented as follows:
.. code-block:: rest
.. index:: show pony
.. clicmd:: show pony
Prints an ASCII pony. Example output:::
>>\.
/_ )`.
/ _)`^)`. _.---. _
(_,' \ `^-)"" `.\
| | \
\ / |
/ \ /.___.'\ (\ (_
< ,"|| \ |`. \`-'
\\ () )| )/
hjw |_>|> /_] //
/_] /_]
When documented this way, CLI commands can be cross referenced with the
``:clicmd:`` inline markup like so:
.. code-block:: rest
:clicmd:`show pony`
This is very helpful for users who want to quickly remind themselves what a
particular command does.
.. _GitHub: https://github.com/frrouting/frr
.. _GitHub issues: https://github.com/frrouting/frr/issues

View File

@ -1,122 +0,0 @@
.TH EIGRPD 8 "6 May 2017" "@PACKAGE_FULLNAME@ EIGRP daemon" "Version @PACKAGE_VERSION@"
.SH NAME
eigrpd \- a EIGRP routing engine for use with @PACKAGE_FULLNAME@.
.SH SYNOPSIS
.B eigrpd
[
.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
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B eigrpd
is a routing component that works with the
.B @PACKAGE_FULLNAME@
routing engine.
.SH OPTIONS
Options available for the
.B eigrpd
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@/eigrpd.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 eigrpd starts its process identifier is written to
\fB\fIpid-file\fR. The init system uses the recorded PID to stop or
restart eigrpd. The default is \fB\fI@CFG_STATE@/eigrpd.pid\fR.
.TP
\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR
Specify the port that the eigrpd 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 eigrpd 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 \fBeigrpd\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBeigrpd\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES
.TP
.BI @CFG_SBIN@/eigrpd
The default location of the
.B eigrpd
binary.
.TP
.BI @CFG_SYSCONF@/eigrpd.conf
The default location of the
.B eigrpd
config file.
.TP
.BI $(PWD)/eigrpd.log
If the
.B eigrpd
process is config'd to output logs to a file, then you will find this
file in the directory where you started \fBeigrpd\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 eigrpd process may log to standard output, to a VTY, to a log
file, or through syslog to the system logs. \fBeigrpd\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 eigrpd
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.

View File

@ -1,216 +0,0 @@
@c -*-texinfo-*-
@c This is part of the Frr Manual.
@c @value{COPYRIGHT_STR}
@c See file frr.texi for copying conditions.
@node EIGRP
@chapter EIGRP
EIGRP -- Routing Information Protocol is widely deployed interior gateway
routing protocol. EIGRP was developed in the 1990's. EIGRP is a
@dfn{distance-vector} protocol and is based on the @dfn{dual} algorithms.
As a distance-vector protocol, the EIGRP router send updates to its
neighbors as networks change, thus allowing the convergence to a
known topology.
@command{eigrpd} supports EIGRP as described in RFC7868
@menu
* Starting and Stopping eigrpd::
* EIGRP Configuration::
* How to Announce EIGRP routes::
* Show EIGRP Information::
* EIGRP Debug Commands::
@end menu
@node Starting and Stopping eigrpd
@section Starting and Stopping eigrpd
The default configuration file name of @command{eigrpd}'s is
@file{eigrpd.conf}. When invocation @command{eigrpd} searches directory
@value{INSTALL_PREFIX_ETC}. If @file{eigrpd.conf} is not there next
search current directory. If an integrated config is specified
configuration is written into frr.conf
The EIGRP protocol requires interface information
maintained by @command{zebra} daemon. So running @command{zebra}
is mandatory to run @command{eigrpd}. Thus minimum sequence for running
EIGRP is like below:
@example
@group
# zebra -d
# eigrpd -d
@end group
@end example
Please note that @command{zebra} must be invoked before @command{eigrpd}.
To stop @command{eigrpd}. Please use @command{kill `cat
/var/run/eigrpd.pid`}. Certain signals have special meanings to @command{eigrpd}.
@table @samp
@item SIGHUP
@item SIGUSR1
Rotate @command{eigrpd} Rotate the logfile.
@item SIGINT
@itemx SIGTERM
@command{eigrpd} sweeps all installed EIGRP routes then terminates properly.
@end table
@command{eigrpd} invocation options. Common options that can be specified
(@pxref{Common Invocation Options}).
@table @samp
@item -r
@itemx --retain
When the program terminates, retain routes added by @command{eigrpd}.
@end table
@node EIGRP Configuration
@section EIGRP Configuration
@deffn Command {router eigrp (1-65535)} {}
The @code{router eigrp} command is necessary to enable EIGRP. To disable
EIGRP, use the @code{no router eigrp (1-65535)} command. EIGRP must be enabled before carrying out any of the EIGRP commands.
@end deffn
@deffn Command {no router eigrp (1-65535)} {}
Disable EIGRP.
@end deffn
@deffn {EIGRP Command} {network @var{network}} {}
@deffnx {EIGRP Command} {no network @var{network}} {}
Set the EIGRP enable interface by @var{network}. The interfaces which
have addresses matching with @var{network} are enabled.
This group of commands either enables or disables EIGRP interfaces between
certain numbers of a specified network address. For example, if the
network for 10.0.0.0/24 is EIGRP enabled, this would result in all the
addresses from 10.0.0.0 to 10.0.0.255 being enabled for EIGRP. The @code{no
network} command will disable EIGRP for the specified network.
@end deffn
Below is very simple EIGRP configuration. Interface @code{eth0} and
interface which address match to @code{10.0.0.0/8} are EIGRP enabled.
@example
@group
!
router eigrp 1
network 10.0.0.0/8
!
@end group
@end example
Passive interface
@deffn {EIGRP command} {passive-interface (@var{IFNAME}|default)} {}
@deffnx {EIGRP command} {no passive-interface @var{IFNAME}} {}
This command sets the specified interface to passive mode. On passive mode
interface, all receiving packets are ignored and eigrpd does
not send either multicast or unicast EIGRP packets except to EIGRP neighbors
specified with @code{neighbor} command. The interface may be specified
as @var{default} to make eigrpd default to passive on all interfaces.
The default is to be passive on all interfaces.
@end deffn
@node How to Announce EIGRP route
@section How to Announce EIGRP route
@deffn {EIGRP command} {redistribute kernel} {}
@deffnx {EIGRP command} {redistribute kernel metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)} {}
@deffnx {EIGRP command} {no redistribute kernel} {}
@code{redistribute kernel} redistributes routing information from
kernel route entries into the EIGRP tables. @code{no redistribute kernel}
disables the routes.
@end deffn
@deffn {EIGRP command} {redistribute static} {}
@deffnx {EIGRP command} {redistribute static metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)} {}
@deffnx {EIGRP command} {no redistribute static} {}
@code{redistribute static} redistributes routing information from
static route entries into the EIGRP tables. @code{no redistribute static}
disables the routes.
@end deffn
@deffn {EIGRP command} {redistribute connected} {}
@deffnx {EIGRP command} {redistribute connected metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)} {}
@deffnx {EIGRP command} {no redistribute connected} {}
Redistribute connected routes into the EIGRP tables. @code{no
redistribute connected} disables the connected routes in the EIGRP tables.
This command redistribute connected of the interface which EIGRP disabled.
The connected route on EIGRP enabled interface is announced by default.
@end deffn
@deffn {EIGRP command} {redistribute ospf} {}
@deffnx {EIGRP command} {redistribute ospf metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)} {}
@deffnx {EIGRP command} {no redistribute ospf} {}
@code{redistribute ospf} redistributes routing information from
ospf route entries into the EIGRP tables. @code{no redistribute ospf}
disables the routes.
@end deffn
@deffn {EIGRP command} {redistribute bgp} {}
@deffnx {EIGRP command} {redistribute bgp metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)} {}
@deffnx {EIGRP command} {no redistribute bgp} {}
@code{redistribute bgp} redistributes routing information from
bgp route entries into the EIGRP tables. @code{no redistribute bgp}
disables the routes.
@end deffn
@node Show EIGRP Information
@section Show EIGRP Information
To display EIGRP routes.
@deffn Command {show ip eigrp topology} {}
Show EIGRP routes.
@end deffn
The command displays all EIGRP routes.
@c Exmaple here.
@deffn Command {show ip eigrp topology} {}
The command displays current EIGRP status
@end deffn
@example
@group
eigrpd> @b{show ip eigrp topology}
# show ip eigrp topo
EIGRP Topology Table for AS(4)/ID(0.0.0.0)
Codes: P - Passive, A - Active, U - Update, Q - Query, R - Reply
r - reply Status, s - sia Status
P 10.0.2.0/24, 1 successors, FD is 256256, serno: 0
via Connected, enp0s3
@end group
@end example
@node EIGRP Debug Commands
@section EIGRP Debug Commands
Debug for EIGRP protocol.
@deffn Command {debug eigrp packets} {}
Debug eigrp packets
@end deffn
@code{debug eigrp} will show EIGRP packets that are sent and recevied.
@deffn Command {debug eigrp transmit} {}
Debug eigrp transmit events
@end deffn
@code{debug eigrp transmit} will display detailed information about the EIGRP transmit events.
@deffn Command {show debugging eigrp} {}
Display @command{eigrpd}'s debugging option.
@end deffn
@code{show debugging eigrp} will show all information currently set for eigrpd
debug.

211
doc/figures/cligraph.svg Normal file
View File

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="300pt" height="980pt"
viewBox="0.00 0.00 299.50 980.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 976)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-976 295.5,-976 295.5,4 -4,4"/>
<!-- n0xd46960 -->
<g id="node1" class="node"><title>n0xd46960</title>
<polygon fill="#ccffcc" stroke="black" points="158,-972 86,-972 86,-936 158,-936 158,-972"/>
<text text-anchor="start" x="94" y="-952.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">START_TKN</text>
</g>
<!-- n0xd46be0 -->
<g id="node2" class="node"><title>n0xd46be0</title>
<polygon fill="#ffffff" stroke="black" points="159,-900 85,-900 85,-864 159,-864 159,-900"/>
<text text-anchor="start" x="93" y="-885.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">WORD_TKN</text>
<text text-anchor="start" x="101.5" y="-875.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
<text text-anchor="start" x="105.5" y="-875.2" font-family="Fira Mono" font-weight="bold" font-size="11.00" fill="#0055ff">show</text>
<text text-anchor="start" x="138.5" y="-875.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
</g>
<!-- n0xd46960&#45;&gt;n0xd46be0 -->
<g id="edge1" class="edge"><title>n0xd46960&#45;&gt;n0xd46be0</title>
<path fill="none" stroke="black" d="M122,-935.697C122,-927.983 122,-918.712 122,-910.112"/>
<polygon fill="black" stroke="black" points="125.5,-910.104 122,-900.104 118.5,-910.104 125.5,-910.104"/>
</g>
<!-- n0xd47f80 -->
<g id="node3" class="node"><title>n0xd47f80</title>
<polygon fill="#aaddff" stroke="black" points="156.5,-828 87.5,-828 87.5,-792 156.5,-792 156.5,-828"/>
<text text-anchor="start" x="95.5" y="-808.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">FORK_TKN</text>
</g>
<!-- n0xd46be0&#45;&gt;n0xd47f80 -->
<g id="edge2" class="edge"><title>n0xd46be0&#45;&gt;n0xd47f80</title>
<path fill="none" stroke="black" d="M122,-863.697C122,-855.983 122,-846.712 122,-838.112"/>
<polygon fill="black" stroke="black" points="125.5,-838.104 122,-828.104 118.5,-838.104 125.5,-838.104"/>
</g>
<!-- n0xd47c70 -->
<g id="node4" class="node"><title>n0xd47c70</title>
<polygon fill="#ffffff" stroke="black" points="127,-756 53,-756 53,-720 127,-720 127,-756"/>
<text text-anchor="start" x="61" y="-741.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">WORD_TKN</text>
<text text-anchor="start" x="80.5" y="-731.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
<text text-anchor="start" x="84.5" y="-731.2" font-family="Fira Mono" font-weight="bold" font-size="11.00" fill="#0055ff">ip</text>
<text text-anchor="start" x="95.5" y="-731.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
</g>
<!-- n0xd47f80&#45;&gt;n0xd47c70 -->
<g id="edge3" class="edge"><title>n0xd47f80&#45;&gt;n0xd47c70</title>
<path fill="none" stroke="black" d="M114.09,-791.697C110.447,-783.728 106.046,-774.1 102.006,-765.264"/>
<polygon fill="black" stroke="black" points="105.16,-763.744 97.8191,-756.104 98.7936,-766.654 105.16,-763.744"/>
</g>
<!-- n0xd484c0 -->
<g id="node5" class="node"><title>n0xd484c0</title>
<polygon fill="#ddaaff" stroke="black" points="153.5,-684 90.5,-684 90.5,-648 153.5,-648 153.5,-684"/>
<text text-anchor="start" x="98.5" y="-664.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">JOIN_TKN</text>
</g>
<!-- n0xd47f80&#45;&gt;n0xd484c0 -->
<g id="edge20" class="edge"><title>n0xd47f80&#45;&gt;n0xd484c0</title>
<path fill="none" stroke="black" d="M127.824,-791.56C130.931,-781.33 134.431,-768.08 136,-756 138.06,-740.133 138.06,-735.867 136,-720 134.897,-711.506 132.839,-702.434 130.634,-694.24"/>
<polygon fill="black" stroke="black" points="133.945,-693.087 127.824,-684.44 127.216,-695.017 133.945,-693.087"/>
</g>
<!-- n0xd47c70&#45;&gt;n0xd484c0 -->
<g id="edge4" class="edge"><title>n0xd47c70&#45;&gt;n0xd484c0</title>
<path fill="none" stroke="black" d="M97.9101,-719.697C101.553,-711.728 105.954,-702.1 109.994,-693.264"/>
<polygon fill="black" stroke="black" points="113.206,-694.654 114.181,-684.104 106.84,-691.744 113.206,-694.654"/>
</g>
<!-- n0xd47ca0 -->
<g id="node6" class="node"><title>n0xd47ca0</title>
<polygon fill="#ffffff" stroke="black" points="159,-612 85,-612 85,-576 159,-576 159,-612"/>
<text text-anchor="start" x="93" y="-597.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">WORD_TKN</text>
<text text-anchor="start" x="106.5" y="-587.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
<text text-anchor="start" x="110.5" y="-587.2" font-family="Fira Mono" font-weight="bold" font-size="11.00" fill="#0055ff">bgp</text>
<text text-anchor="start" x="133.5" y="-587.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
</g>
<!-- n0xd484c0&#45;&gt;n0xd47ca0 -->
<g id="edge5" class="edge"><title>n0xd484c0&#45;&gt;n0xd47ca0</title>
<path fill="none" stroke="black" d="M122,-647.697C122,-639.983 122,-630.712 122,-622.112"/>
<polygon fill="black" stroke="black" points="125.5,-622.104 122,-612.104 118.5,-622.104 125.5,-622.104"/>
</g>
<!-- n0xd48540 -->
<g id="node7" class="node"><title>n0xd48540</title>
<polygon fill="#ffffff" stroke="black" points="164.5,-540 79.5,-540 79.5,-504 164.5,-504 164.5,-540"/>
<text text-anchor="start" x="93" y="-525.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">WORD_TKN</text>
<text text-anchor="start" x="87.5" y="-515.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
<text text-anchor="start" x="91.5" y="-515.2" font-family="Fira Mono" font-weight="bold" font-size="11.00" fill="#0055ff">neighbors</text>
<text text-anchor="start" x="152.5" y="-515.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
</g>
<!-- n0xd47ca0&#45;&gt;n0xd48540 -->
<g id="edge6" class="edge"><title>n0xd47ca0&#45;&gt;n0xd48540</title>
<path fill="none" stroke="black" d="M122,-575.697C122,-567.983 122,-558.712 122,-550.112"/>
<polygon fill="black" stroke="black" points="125.5,-550.104 122,-540.104 118.5,-550.104 125.5,-550.104"/>
</g>
<!-- n0xd490c0 -->
<g id="node8" class="node"><title>n0xd490c0</title>
<polygon fill="#aaddff" stroke="black" points="156.5,-468 87.5,-468 87.5,-432 156.5,-432 156.5,-468"/>
<text text-anchor="start" x="95.5" y="-448.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">FORK_TKN</text>
</g>
<!-- n0xd48540&#45;&gt;n0xd490c0 -->
<g id="edge7" class="edge"><title>n0xd48540&#45;&gt;n0xd490c0</title>
<path fill="none" stroke="black" d="M122,-503.697C122,-495.983 122,-486.712 122,-478.112"/>
<polygon fill="black" stroke="black" points="125.5,-478.104 122,-468.104 118.5,-478.104 125.5,-478.104"/>
</g>
<!-- n0xd48fc0 -->
<g id="node9" class="node"><title>n0xd48fc0</title>
<polygon fill="#ffffff" stroke="black" points="64,-396 0,-396 0,-360 64,-360 64,-396"/>
<text text-anchor="start" x="8" y="-380.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">IPV4_TKN</text>
<text text-anchor="start" x="15" y="-371.8" font-family="Fira Mono" font-size="9.00">A.B.C.D</text>
</g>
<!-- n0xd490c0&#45;&gt;n0xd48fc0 -->
<g id="edge8" class="edge"><title>n0xd490c0&#45;&gt;n0xd48fc0</title>
<path fill="none" stroke="black" d="M99.7528,-431.697C88.4181,-422.881 74.4698,-412.032 62.1811,-402.474"/>
<polygon fill="black" stroke="black" points="64.0336,-399.481 53.9913,-396.104 59.736,-405.007 64.0336,-399.481"/>
</g>
<!-- n0xd491e0 -->
<g id="node10" class="node"><title>n0xd491e0</title>
<polygon fill="#ddaaff" stroke="black" points="153.5,-324 90.5,-324 90.5,-288 153.5,-288 153.5,-324"/>
<text text-anchor="start" x="98.5" y="-304.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">JOIN_TKN</text>
</g>
<!-- n0xd490c0&#45;&gt;n0xd491e0 -->
<g id="edge19" class="edge"><title>n0xd490c0&#45;&gt;n0xd491e0</title>
<path fill="none" stroke="black" d="M117.536,-431.953C115.065,-421.63 112.248,-408.153 111,-396 109.366,-380.084 109.366,-375.916 111,-360 111.877,-351.455 113.531,-342.255 115.294,-333.958"/>
<polygon fill="black" stroke="black" points="118.743,-334.573 117.536,-324.047 111.915,-333.028 118.743,-334.573"/>
</g>
<!-- n0xd49340 -->
<g id="node15" class="node"><title>n0xd49340</title>
<polygon fill="#ffffff" stroke="black" points="184,-396 120,-396 120,-360 184,-360 184,-396"/>
<text text-anchor="start" x="128" y="-380.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">IPV6_TKN</text>
<text text-anchor="start" x="135" y="-371.8" font-family="Fira Mono" font-size="9.00">X:X::X:X</text>
</g>
<!-- n0xd490c0&#45;&gt;n0xd49340 -->
<g id="edge15" class="edge"><title>n0xd490c0&#45;&gt;n0xd49340</title>
<path fill="none" stroke="black" d="M129.416,-431.697C132.794,-423.813 136.87,-414.304 140.623,-405.546"/>
<polygon fill="black" stroke="black" points="143.947,-406.675 144.67,-396.104 137.513,-403.917 143.947,-406.675"/>
</g>
<!-- n0xd49480 -->
<g id="node16" class="node"><title>n0xd49480</title>
<polygon fill="#ffffff" stroke="black" points="291.5,-396 202.5,-396 202.5,-360 291.5,-360 291.5,-396"/>
<text text-anchor="start" x="210.5" y="-380.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">VARIABLE_TKN</text>
<text text-anchor="start" x="233" y="-371.8" font-family="Fira Mono" font-size="9.00">WORD</text>
</g>
<!-- n0xd490c0&#45;&gt;n0xd49480 -->
<g id="edge17" class="edge"><title>n0xd490c0&#45;&gt;n0xd49480</title>
<path fill="none" stroke="black" d="M152.578,-431.876C169.074,-422.639 189.624,-411.131 207.336,-401.212"/>
<polygon fill="black" stroke="black" points="209.289,-404.13 216.304,-396.19 205.869,-398.022 209.289,-404.13"/>
</g>
<!-- n0xd48fc0&#45;&gt;n0xd491e0 -->
<g id="edge9" class="edge"><title>n0xd48fc0&#45;&gt;n0xd491e0</title>
<path fill="none" stroke="black" d="M54.2472,-359.697C65.5819,-350.881 79.5302,-340.032 91.8189,-330.474"/>
<polygon fill="black" stroke="black" points="94.264,-333.007 100.009,-324.104 89.9664,-327.481 94.264,-333.007"/>
</g>
<!-- n0xd496e0 -->
<g id="node11" class="node"><title>n0xd496e0</title>
<polygon fill="#aaddff" stroke="black" points="156.5,-252 87.5,-252 87.5,-216 156.5,-216 156.5,-252"/>
<text text-anchor="start" x="95.5" y="-232.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">FORK_TKN</text>
</g>
<!-- n0xd491e0&#45;&gt;n0xd496e0 -->
<g id="edge10" class="edge"><title>n0xd491e0&#45;&gt;n0xd496e0</title>
<path fill="none" stroke="black" d="M122,-287.697C122,-279.983 122,-270.712 122,-262.112"/>
<polygon fill="black" stroke="black" points="125.5,-262.104 122,-252.104 118.5,-262.104 125.5,-262.104"/>
</g>
<!-- n0xd495e0 -->
<g id="node12" class="node"><title>n0xd495e0</title>
<polygon fill="#ffffff" stroke="black" points="127,-180 53,-180 53,-144 127,-144 127,-180"/>
<text text-anchor="start" x="61" y="-165.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">WORD_TKN</text>
<text text-anchor="start" x="73.5" y="-155.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
<text text-anchor="start" x="77.5" y="-155.2" font-family="Fira Mono" font-weight="bold" font-size="11.00" fill="#0055ff">json</text>
<text text-anchor="start" x="102.5" y="-155.2" font-family="Fira Mono" font-size="9.00">&quot;</text>
</g>
<!-- n0xd496e0&#45;&gt;n0xd495e0 -->
<g id="edge11" class="edge"><title>n0xd496e0&#45;&gt;n0xd495e0</title>
<path fill="none" stroke="black" d="M114.09,-215.697C110.447,-207.728 106.046,-198.1 102.006,-189.264"/>
<polygon fill="black" stroke="black" points="105.16,-187.744 97.8191,-180.104 98.7936,-190.654 105.16,-187.744"/>
</g>
<!-- n0xd497c0 -->
<g id="node13" class="node"><title>n0xd497c0</title>
<polygon fill="#ddaaff" stroke="black" points="153.5,-108 90.5,-108 90.5,-72 153.5,-72 153.5,-108"/>
<text text-anchor="start" x="98.5" y="-88.8" font-family="Fira Mono" font-weight="bold" font-size="9.00">JOIN_TKN</text>
</g>
<!-- n0xd496e0&#45;&gt;n0xd497c0 -->
<g id="edge14" class="edge"><title>n0xd496e0&#45;&gt;n0xd497c0</title>
<path fill="none" stroke="black" d="M127.824,-215.56C130.931,-205.33 134.431,-192.08 136,-180 138.06,-164.133 138.06,-159.867 136,-144 134.897,-135.506 132.839,-126.434 130.634,-118.24"/>
<polygon fill="black" stroke="black" points="133.945,-117.087 127.824,-108.44 127.216,-119.017 133.945,-117.087"/>
</g>
<!-- n0xd495e0&#45;&gt;n0xd497c0 -->
<g id="edge12" class="edge"><title>n0xd495e0&#45;&gt;n0xd497c0</title>
<path fill="none" stroke="black" d="M97.9101,-143.697C101.553,-135.728 105.954,-126.1 109.994,-117.264"/>
<polygon fill="black" stroke="black" points="113.206,-118.654 114.181,-108.104 106.84,-115.744 113.206,-118.654"/>
</g>
<!-- end0xd49900 -->
<g id="node14" class="node"><title>end0xd49900</title>
<polygon fill="#ffddaa" stroke="black" points="149,-36 95,-36 95,-0 149,-0 149,-36"/>
<text text-anchor="start" x="112.5" y="-15.8" font-family="Fira Mono" font-size="9.00">end</text>
</g>
<!-- n0xd497c0&#45;&gt;end0xd49900 -->
<g id="edge13" class="edge"><title>n0xd497c0&#45;&gt;end0xd49900</title>
<path fill="none" stroke="black" d="M122,-71.6966C122,-63.9827 122,-54.7125 122,-46.1124"/>
<polygon fill="black" stroke="black" points="125.5,-46.1043 122,-36.1043 118.5,-46.1044 125.5,-46.1043"/>
</g>
<!-- n0xd49340&#45;&gt;n0xd491e0 -->
<g id="edge16" class="edge"><title>n0xd49340&#45;&gt;n0xd491e0</title>
<path fill="none" stroke="black" d="M144.584,-359.697C141.206,-351.813 137.13,-342.304 133.377,-333.546"/>
<polygon fill="black" stroke="black" points="136.487,-331.917 129.33,-324.104 130.053,-334.675 136.487,-331.917"/>
</g>
<!-- n0xd49480&#45;&gt;n0xd491e0 -->
<g id="edge18" class="edge"><title>n0xd49480&#45;&gt;n0xd491e0</title>
<path fill="none" stroke="black" d="M216.422,-359.876C199.926,-350.639 179.376,-339.131 161.664,-329.212"/>
<polygon fill="black" stroke="black" points="163.131,-326.022 152.696,-324.19 159.711,-332.13 163.131,-326.022"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Some files were not shown because too many files have changed in this diff Show More