+++ /dev/null
-Moved to doc/developer/workflow.rst
endif
EXTRA_DIST += \
- REPORTING-BUGS \
SERVICES \
aclocal.m4 \
update-autotools \
IS-IS, PIM-SM/MSDP, LDP and Babel as well as very early support for EIGRP and
NHRP.
-See the file REPORTING-BUGS to report bugs.
+See doc/user/bugs.rst for information on how to report bugs.
-See COMMUNITY.md for information on contributing.
+See doc/developer/workflow.rst for information on contributing.
Free RRRouting is free software. See the file COPYING for copying conditions.
+++ /dev/null
-#!/bin/sh
-
-# This file is helpful for building FRR from cvs on NetBSD, and
-# probably on any system using pkgsrc.
-# One should have readline installed already (pkgsrc/devel/readline).
-
-MAKE=make
-# FRR is currently documented not to require GNU make, but sometimes
-# BSD make fails. Enable this if statement as a workaround.
-if false; then
- MAKE=gmake
- echo "WARNING: using gmake to work around nonportable makefiles"
-fi
-
-# Use /usr/frr to be independent, and /usr/pkg to overwrite pkgsrc.
-PREFIX=/usr/pkg
-
-case $1 in
-
- build)
- # Omitted because it is now default:
- # --enable-opaque-lsa
- ./bootstrap.sh
- LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" CPPFLAGS="-I/usr/pkg/include" \
- ./configure --prefix=${PREFIX} \
- --sysconfdir=/etc/zebra --localstatedir=/var/run/zebra \
- --enable-exampledir=${PREFIX}/share/examples/zebra \
- --enable-pkgsrcrcdir=${PREFIX}/etc/rc.d \
- --enable-vtysh
- ${MAKE}
- ;;
-
- install)
- ${MAKE} install
- ;;
-
- clean)
- ${MAKE} clean
- ;;
-
- *)
- echo "Usage: README.NetBSD (build|install|clean)"
- exit 1
- ;;
-
-esac
+++ /dev/null
-This file describes the procedure for reporting FRRouting bugs. You are not
-obliged to follow this format, but it would be great help for FRRouting developers
-if you report a bug as described below.
-
-Bugs submitted with woefully incomplete information may be summarily
-closed. Submitters of bugs against old versions may be asked to
-retest against the latest release. Submitters may be asked for
-additional information. Bugs may be closed after 30 days of
-non-response to requests to reconfirm or supply additional
-information.
-
-Report bugs on Github Issue Tracker at
- https://github.com/frrouting/frr/issues
-
-Please supply the following information:
-1. Your FRRouting version or if it is from git then the commit reference.
- Please try to report bugs against git master or the latest release.
-2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any
- specific options you compiled FRR with.
-3. Problem description. Copy and paste relative commands and their output to
- describe your network setup e.g. "zebra>show ip route".
- Please, also give your simple network layout and output of relative OS
- commands (e.g., ifconfig (BSD) or ip (Linux)).
-4. All FRR configuration files you use. If you don't want to publish your
- network numbers change 2 middle bytes in IPv4 address to be XXX (e.g.
- 192.XXX.XXX.32/24). Similar could be done with IPv6.
-5. If any FRR daemon core dumped, please, supply stack trace using the
- following commands: host> gdb exec_file core_file , (gdb) bt .
-6. Run all FRR daemons with full debugging on (see documentation on
- debugging) and send _only_ part of logs which are relative to your problem.
-7. If the problem is difficult to reproduce please send a shell script to
- reproduce it.
-8. Patches, workarounds, fixes are always welcome.
-
-Thank You.
/* 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.
+ * or prefix route, we have to convert the next hop to an IPv4-mapped
+ * address for the rest of the code to flow through. In the case of IPv4,
+ * make sure to set the flag for next hop attribute.
*/
bgp_attr_dup(&attr, parent_ri->attr);
if (afi == AFI_IP6)
evpn_convert_nexthop_to_ipv6(&attr);
+ else
+ attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
/* Check if route entry is already present. */
for (ri = rn->info; ri; ri = ri->next)
parent_ri->peer, attr_new, rn);
SET_FLAG(ri->flags, BGP_INFO_VALID);
bgp_info_extra_get(ri);
- ri->extra->parent = parent_ri;
+ ri->extra->parent = bgp_info_lock(parent_ri);
if (parent_ri->extra) {
memcpy(&ri->extra->label, &parent_ri->extra->label,
sizeof(ri->extra->label));
parent_ri->peer, attr_new, rn);
SET_FLAG(ri->flags, BGP_INFO_VALID);
bgp_info_extra_get(ri);
- ri->extra->parent = parent_ri;
+ ri->extra->parent = bgp_info_lock(parent_ri);
if (parent_ri->extra) {
memcpy(&ri->extra->label, &parent_ri->extra->label,
sizeof(ri->extra->label));
/* Locate VNI hash */
vpn = bgp_evpn_lookup_vni(bgp, vni);
if (!vpn) {
- zlog_warn("%u: VNI hash entry for VNI %u not found at DEL",
- bgp->vrf_id, vni);
+ if (bgp_debug_zebra(NULL))
+ zlog_warn(
+ "%u: VNI hash entry for VNI %u not found at DEL",
+ bgp->vrf_id, vni);
return 0;
}
}
static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
- json_object *json)
+ uint64_t tbl_ver, json_object *json)
{
char ri_header[] =
" Network Next Hop Metric LocPrf Weight Path\n";
if (json)
return;
-
- vty_out(vty, "BGP table version is 0, local router ID is %s\n",
- inet_ntoa(bgp->router_id));
+ vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n",
+ tbl_ver, inet_ntoa(bgp->router_id));
vty_out(vty,
"Status codes: s suppressed, d damped, h history, "
"* valid, > best, i - internal\n");
{
struct bgp_node *rn;
struct bgp_info *ri;
+ struct bgp_table *table;
int header = 1;
+ uint64_t tbl_ver;
uint32_t prefix_cnt, path_cnt;
prefix_cnt = path_cnt = 0;
- for (rn = bgp_table_top(vpn->route_table); rn;
+ table = vpn->route_table;
+ tbl_ver = table->version;
+ for (rn = bgp_table_top(table); rn;
rn = bgp_route_next(rn)) {
struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
int add_prefix_to_json = 0;
if (rn->info) {
/* Overall header/legend displayed once. */
if (header) {
- bgp_evpn_show_route_header(vty, bgp, json);
+ bgp_evpn_show_route_header(vty, bgp,
+ tbl_ver, json);
header = 0;
}
static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object *json)
{
- json_object *json_vni;
- json_object *json_import_rtl;
- json_object *json_export_rtl;
+ json_object *json_vni = NULL;
+ json_object *json_import_rtl = NULL;
+ json_object *json_export_rtl = NULL;
char buf1[10];
char buf2[INET6_ADDRSTRLEN];
char rt_buf[25];
for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
rn = bgp_route_next(rn)) {
+ uint64_t tbl_ver;
+
if (use_json)
continue; /* XXX json TODO */
continue;
rd_header = 1;
+ tbl_ver = table->version;
for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
for (ri = rm->info; ri; ri = ri->next) {
json_object_int_add(
json,
"bgpTableVersion",
- 0);
+ tbl_ver);
json_object_string_add(
json,
"bgpLocalRouterId",
V4_HEADER_OVERLAY);
else {
vty_out(vty,
- "BGP table version is 0, local router ID is %s\n",
+ "BGP table version is %" PRIu64 ", local router ID is %s\n",
+ tbl_ver,
inet_ntoa(
bgp->router_id));
vty_out(vty,
char rd_str[RD_ADDRSTRLEN];
json_object *json_rd = NULL; /* contains routes for an RD */
int add_rd_to_json = 0;
+ uint64_t tbl_ver;
table = (struct bgp_table *)rd_rn->info;
if (table == NULL)
continue;
+ tbl_ver = table->version;
prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
sizeof(rd_str));
/* Overall header/legend displayed once. */
if (header) {
bgp_evpn_show_route_header(vty, bgp,
+ tbl_ver,
json);
header = 0;
}
if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
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_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
}
}
vty_out(vty, " advertise-default-gw\n");
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
- vty_out(vty, " advertise ipv4 unicast\n");
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
+ if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
+ vty_out(vty, " advertise ipv4 unicast route-map %s\n",
+ bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
+ else
+ vty_out(vty, " advertise ipv4 unicast\n");
+ }
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
- vty_out(vty, " advertise ipv6 unicast\n");
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
+ if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
+ vty_out(vty, " advertise ipv6 unicast route-map %s\n",
+ bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
+ else
+ vty_out(vty, " advertise ipv6 unicast\n");
+ }
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
#include "bgpd/bgp_memory.h"
#include "bgpd/bgp_keepalives.h"
#include "bgpd/bgp_io.h"
+#include "bgpd/bgp_zebra.h"
DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer))
DEFINE_HOOK(peer_established, (struct peer * peer), (peer))
/* If getsockopt is fail, this is fatal error. */
if (ret < 0) {
- zlog_info("can't get sockopt for nonblocking connect");
+ zlog_info("can't get sockopt for nonblocking connect: %d(%s)",
+ errno, safe_strerror(errno));
BGP_EVENT_ADD(peer, TCP_fatal_error);
return -1;
}
return 1;
} else {
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [Event] Connect failed (%s)", peer->host,
- safe_strerror(errno));
+ zlog_debug("%s [Event] Connect failed %d(%s)",
+ peer->host, status, safe_strerror(status));
BGP_EVENT_ADD(peer, TCP_connection_open_failed);
return 0;
}
if (!bgp_find_or_add_nexthop(peer->bgp, peer->bgp,
family2afi(peer->su.sa.sa_family), NULL,
peer, connected)) {
-#if defined(HAVE_CUMULUS)
- if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [FSM] Waiting for NHT", peer->host);
+ if (bgp_zebra_num_connects()) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Waiting for NHT",
+ peer->host);
- BGP_EVENT_ADD(peer, TCP_connection_open_failed);
- return 0;
-#endif
+ BGP_EVENT_ADD(peer, TCP_connection_open_failed);
+ return 0;
+ }
}
assert(!peer->t_write);
peer = THREAD_ARG(thread);
- if (peer->fd < 0)
+ if (peer->fd < 0 || bm->terminating)
return -1;
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
__attribute__((__noreturn__)) void sigint(void)
{
zlog_notice("Terminating on signal");
+ assert(bm->terminating == false);
+ bm->terminating = true; /* global flag that shutting down */
if (!retain_mode)
bgp_terminate();
setlabels(new, label, num_labels);
bgp_info_extra_get(new);
- new->extra->parent = parent;
+ new->extra->parent = bgp_info_lock(parent);
if (bgp_orig)
new->extra->bgp_orig = bgp_orig;
struct bgp_info *bgp_info_unlock(struct bgp_info *binfo)
{
+ /* unlink reference to parent, if any. */
+ if (binfo->extra && binfo->extra->parent) {
+ bgp_info_unlock((struct bgp_info *)binfo->extra->parent);
+ binfo->extra->parent = NULL;
+ }
assert(binfo && binfo->lock > 0);
binfo->lock--;
}
if (family == AF_INET6)
memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
+ if (family == AF_EVPN)
+ memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
}
int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type == BGP_ROUTE_AGGREGATE
- || new_select->sub_type == BGP_ROUTE_IMPORTED))
+ || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
+
+ /* if this is an evpn imported type-5 prefix,
+ * we need to withdraw the route first to clear
+ * the nh neigh and the RMAC entry.
+ */
+ if (old_select &&
+ is_route_parent_evpn(old_select))
+ bgp_zebra_withdraw(p, old_select, bgp, safi);
bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
- else {
+ } else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
&& (old_select->sub_type == BGP_ROUTE_NORMAL
/* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (advertise_type5_routes(bgp, afi) && new_select &&
- (!new_select->extra || !new_select->extra->parent))
- bgp_evpn_advertise_type5_route(bgp, &rn->p,
- new_select->attr,
- afi, safi);
- else if (advertise_type5_routes(bgp, afi) && old_select &&
- (!old_select->extra || !old_select->extra->parent))
+ (!new_select->extra || !new_select->extra->parent)) {
+
+ /* apply the route-map */
+ if (bgp->adv_cmd_rmap[afi][safi].map) {
+ int ret = 0;
+
+ ret = route_map_apply(
+ bgp->adv_cmd_rmap[afi][safi].map,
+ &rn->p, RMAP_BGP, new_select);
+ if (ret == RMAP_MATCH)
+ bgp_evpn_advertise_type5_route(
+ bgp, &rn->p, new_select->attr,
+ afi, safi);
+ } else {
+ bgp_evpn_advertise_type5_route(bgp,
+ &rn->p,
+ new_select->attr,
+ afi, safi);
+
+ }
+ } 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);
}
nh_modified = 1;
} else if (
peer->sort == BGP_PEER_EBGP
- && paf->safi != SAFI_EVPN
&& (bgp_multiaccess_check_v4(v4nh, peer) == 0)
&& !CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED)
&& !peer_af_flag_check(
- peer, nhafi, paf->safi,
+ peer, paf->afi, paf->safi,
PEER_FLAG_NEXTHOP_UNCHANGED)) {
/* NOTE: not handling case where NH has new AFI
*/
install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd);
install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_nexthop_self_cmd);
/* "neighbor next-hop-self force" commands. */
install_element(BGP_NODE, &neighbor_nexthop_self_force_hidden_cmd);
/* Make Zebra API structure. */
memset(&api, 0, sizeof(api));
- memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
}
}
- if (bgp->table_map[afi][safi].name || nh_othervrf) {
+ if (bgp->table_map[afi][safi].name) {
/* Copy info and attributes, so the route-map
apply doesn't modify the BGP route info. */
local_attr = *mpinfo->attr;
mpinfo_cp->attr = &local_attr;
- if (nh_othervrf) {
- /* allow route-map to modify */
- local_attr.nexthop =
- info->extra->nexthop_orig.u
- .prefix4;
- }
}
if (bgp->table_map[afi][safi].name) {
ifindex_t ifindex;
struct in6_addr *nexthop;
- if (bgp->table_map[afi][safi].name || nh_othervrf) {
+ if (bgp->table_map[afi][safi].name) {
/* Copy info and attributes, so the route-map
apply doesn't modify the BGP route info. */
local_attr = *mpinfo->attr;
mpinfo_cp->attr = &local_attr;
- if (nh_othervrf) {
- /* allow route-map to modify */
- local_attr.mp_nexthop_global =
- info->extra->nexthop_orig.u
- .prefix6;
- local_attr.mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL;
- }
}
if (bgp->table_map[afi][safi].name) {
api_nh->label_num = 1;
api_nh->labels[0] = label;
}
+ memcpy(&api_nh->rmac, &(mpinfo->attr->rmac),
+ sizeof(struct ethaddr));
valid_nh_count++;
}
}
memset(&api, 0, sizeof(api));
- memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
zclient_create_header(s, ZEBRA_ADVERTISE_DEFAULT_GW, bgp->vrf_id);
stream_putc(s, advertise);
- stream_put3(s, vni);
+ stream_putl(s, vni);
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
peer->orf_plist[afi][safi] = NULL;
}
+
+ /* set nexthop-unchanged for l2vpn evpn by default */
+ SET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
/* Create buffers. */
return 0;
}
+ /*
+ * For EVPN we implicitly set the NEXTHOP_UNCHANGED flag,
+ * if we are setting/unsetting flags which conflict with this flag
+ * handle accordingly
+ */
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+ if (set) {
+
+ /*
+ * if we are setting NEXTHOP_SELF, we need to unset the
+ * NEXTHOP_UNCHANGED flag
+ */
+ if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
+ CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
+ UNSET_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+ } else {
+
+ /*
+ * if we are unsetting NEXTHOP_SELF, we need to set the
+ * NEXTHOP_UNCHANGED flag to reset the defaults for EVPN
+ */
+ if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
+ CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
+ SET_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+ }
+ }
+
if (set)
SET_FLAG(peer->af_flags[afi][safi], flag);
else
/* atribute-unchanged. */
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
- || peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
+ || (safi != SAFI_EVPN
+ && peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED))
|| peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
if (!peer_group_active(peer)
bm->start_time = bgp_clock();
bm->t_rmap_update = NULL;
bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
+ bm->terminating = false;
bgp_process_queue_init();
/* dynamic mpls label allocation pool */
struct labelpool labelpool;
+ bool terminating; /* global flag that sigint terminate seen */
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(bgp_master)
AC_CONFIG_FILES([Makefile
bgpd/Makefile
vtysh/Makefile
- doc/Makefile tests/Makefile
- bgpd/rfp-example/rfptest/Makefile bgpd/rfp-example/librfp/Makefile
+ doc/Makefile
+ doc/user/Makefile
+ doc/manpages/Makefile
+ doc/developer/Makefile
+ tests/Makefile
+ bgpd/rfp-example/rfptest/Makefile
+ bgpd/rfp-example/librfp/Makefile
redhat/frr.spec
debianpkg/Makefile
debianpkg/changelog
+++ /dev/null
-Building your own FRRouting Debian Package
-==========================================
-(Tested on Ubuntu 12.04, 14.04, 16.04, 17.10, 18.04, Debian 8 and 9)
-
-**Note:** If you try to build for a different distro, then it will most likely
-fail because of the missing backport. See debianpkg/backports/README about
-adding a new backport.
-
-1. Follow the package installation as outlined in doc/Building_on_XXXX.md
- (XXXX refers your OS Distribution) to install the required build packages
-
-2. Install the following additional packages:
-
- on Ubuntu 12.04, 14.04, 16.04, 17.10, Debian 8 and 9:
-
- apt-get install realpath equivs groff fakeroot debhelper devscripts
-
- on Ubuntu 18.04: (realpath is now part of preinstalled by coreutils)
-
- apt-get install equivs groff fakeroot debhelper devscripts
-
-3. Checkout FRR under a **unpriviledged** user account
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- # git checkout <branch> - if different branch than master
-
-4. Run Bootstrap and make distribution tar.gz
-
- ./bootstrap.sh
- ./configure --with-pkg-extra-version=-MyDebPkgVersion
- make dist
-
- Note: configure parameters are not important for the Debian Package
- building - except the `with-pkg-extra-version` if you want to give the
- Debian Package a specific name to mark your own unoffical build
-
-5. Edit `debianpkg/rules` and set the configuration as needed
-
- Look for section `dh_auto_configure` to modify the configure
- options as needed. Options might be different between main `rules` and
- `backports/XXXX/debian/rules`. Please adjust as needed on all files
-
-6. Create backports debian sources
-
- Move the `debianpkg` to `debian` and create the backports
- (Debian requires to not ship a `debian` directory inside the source
- directory to avoid build conflicts with the reserved `debian` subdirectory
- name during the build)
-
- mv debianpkg debian
- make -f debian/rules backports
-
- This will create a `frr_*.orig.tar.gz` with the source (same as dist tar),
- and multiple `frr_*.debian.tar.xz` and `frr_*.dsc` for the debian package
- source on each backport supported distribution
-
-7. Create a new directory to build the package and populate with package src
-
- mkdir frrpkg
- cd frrpkg
- tar xf ~/frr/frr_*.orig.tar.gz
- cd frr*
- . /etc/os-release
- tar xf ~/frr/frr_*${ID}${VERSION_ID}*.debian.tar.xz
-
-8. Build Debian Package Dependencies and install them as needed
-
- sudo mk-build-deps --install debian/control
-
-9. Build Debian Package
-
- Building with standard options:
-
- debuild -b -uc -us
-
- Or change some options:
- (see `rules` file for available options)
-
- debuild --set-envvar=WANT_BGP_VNC=1 --set-envvar=WANT_CUMULUS_MODE=1 -b -uc -us
-
- To build with RPKI, download the librtr packages from
- https://ci1.netdef.org/browse/RPKI-RTRLIB/latestSuccessful/artifact
- install librtr-dev on the build server and build the packages as
- debuild --set-envvar=WANT_RPKI=1 -b -uc -us
- RPKI packages have an additonal dependency of librtr0 which can be
- found at the same URL
-
-DONE.
-
-If all works correctly, then you should end up with the Debian packages under
-`frrpkg`. If distributed, please make sure you distribute it together with
-the sources (`frr_*.orig.tar.gz`, `frr_*.debian.tar.xz` and `frr_*.dsc`)
-
-
-Enabling daemons after installation of the package:
----------------------------------------------------
-
-1. Edit `/etc/frr/daemons` and enable required routing daemons (Zebra is
-probably needed for most deployments, so make sure to enable it.)
-
-2. Check your firewall / IPtables to make sure the routing protocols are
-allowed.
-
-3. Enable FRR at startup
-
- - On `init.d` based systems (Ubuntu 12.04)
-
- sudo update-rc.d frr defaults
-
- - On `systemd` based systems (Debian 8 and later, Ubuntu 14.04 and later)
-
- sudo systemctl enable frr
-
-4. Start/Restart the daemons (or reboot)
-
- - On `init.d` based systems (Ubuntu 12.04)
-
- sudo invoke-rc.d frr start
-
- - on `systemd` based systems (Debian 8 and later, Ubuntu 14.04 and later)
-
- sudo systemctl start frr
-
-
-Configuration is stored in `/etc/frr/*.conf` files and daemon selection
-is stored in `/etc/frr/daemons`.
AUTHORS
NEWS
README
-REPORTING-BUGS
doc/user/*.rst
doc/figures/*.png
.NOTPARALLEL:
SUBDIRS = manpages user
-AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir} doczdir=${abs_srcdir}
+AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir}
MANPAGE_BUILDDIR = manpages/_build/man
/_templates
/_build
-!/Makefile
+!/Makefile.in
+++ /dev/null
-include ../frr-sphinx.mk
--- /dev/null
+# This is necessary to support VPATH builds.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# This variable is used as the documentation source location in frr-sphinx.mk
+SOURCESDIR = @srcdir@
+
+include @srcdir@/../frr-sphinx.mk
::
- pkg_add git autoconf-2.69p2 automake-1.15p0 libtool bison
+ pkg_add git autoconf-2.69p2 automake-1.15.1 libtool bison
pkg_add gmake gawk dejagnu openssl json-c py-test py-sphinx
Select Python2.7 as default (required for pytest)
+.. _building:
+
************
Building FRR
************
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
+# contents of ../extra/frrlexer.py.
+# This is read here to support VPATH build. Since this section is execfile()'d
+# with the file location, we can safely use a relative path here to save the
+# contents of the lexer file for later use even if our relative path changes
+# due to VPATH.
+with open('../extra/frrlexer.py', 'rb') as lex:
+ frrlexerpy = lex.read()
+
# custom extensions here
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
#
# frrlexer = pygments.lexers.load_lexer_from_file('../extra/frrlexer.py', lexername="FRRLexer")
custom_namespace = {}
- exec(open('../extra/frrlexer.py', 'rb').read(), custom_namespace)
+ exec(frrlexerpy, custom_namespace)
lexers['frr'] = custom_namespace['FRRLexer']()
workflow
building
+ packaging
process-architecture
library
bgpd
--- /dev/null
+Debian
+======
+
+(Tested on Ubuntu 12.04, 14.04, 16.04, 17.10, 18.04, Debian 8 and 9)
+
+.. note::
+
+ If you try to build for a different distro, then it will most likely fail
+ because of the missing backport. See :ref:`deb-backports` about adding a new
+ backport.
+
+1. Install build dependencies for your platform as outlined in :ref:`building`.
+
+2. Install the following additional packages:
+
+ - on Ubuntu 12.04, 14.04, 16.04, 17.10, Debian 8 and 9:
+
+ .. code-block:: shell
+
+ apt-get install realpath equivs groff fakeroot debhelper devscripts
+
+ - on Ubuntu 18.04: (realpath is now part of preinstalled by coreutils)
+
+ .. code-block:: shell
+
+ apt-get install equivs groff fakeroot debhelper devscripts
+
+3. Checkout FRR under a **unprivileged** user account:
+
+ .. code-block:: shell
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+
+ If you wish to build a package for a branch other than master:
+
+ .. code-block:: shell
+
+ git checkout <branch>
+
+4. Run ``bootstrap.sh`` and make a dist tarball:
+
+ .. code-block:: shell
+
+ ./bootstrap.sh
+ ./configure --with-pkg-extra-version=-MyDebPkgVersion
+ make dist
+
+ .. note::
+
+ Configure parameters are not important for the Debian Package building -
+ except the `with-pkg-extra-version` if you want to give the Debian
+ package a specific name to mark your own unoffical build.
+
+5. Edit :file:`debianpkg/rules` and set the configuration as needed.
+
+ Look for section ``dh_auto_configure`` to modify the configure options as
+ needed. Options might be different between the top-level ``rules``` and
+ :file:`backports/XXXX/debian/rules`. Please adjust as needed on all files.
+
+6. Create backports debian sources
+
+ Rename the :file:`debianpkg` directory to :file:`debian` and create the
+ backports (Debian requires to not ship a :file:`debian` directory inside the
+ source directory to avoid build conflicts with the reserved ``debian``
+ subdirectory name during the build):
+
+ .. code-block:: shell
+
+ mv debianpkg debian
+ make -f debian/rules backports
+
+ This will create a :file:`frr_*.orig.tar.gz` with the source (same as the
+ dist tarball), as well as multiple :file:`frr_*.debian.tar.xz` and
+ :file:`frr_*.dsc` corresponding to each distribution for which a backport is
+ available.
+
+7. Create a new directory to build the package and populate with package
+ source.
+
+ .. code-block:: shell
+
+ mkdir frrpkg
+ cd frrpkg
+ tar xf ~/frr/frr_*.orig.tar.gz
+ cd frr*
+ . /etc/os-release
+ tar xf ~/frr/frr_*${ID}${VERSION_ID}*.debian.tar.xz
+
+8. Build Debian package dependencies and install them as needed.
+
+ .. code-block:: shell
+
+ sudo mk-build-deps --install debian/control
+
+9. Build Debian Package
+
+ Building with standard options:
+
+ .. code-block:: shell
+
+ debuild -b -uc -us
+
+ Or change some options (see `rules` file for available options):
+
+ .. code-block:: shell
+
+ debuild --set-envvar=WANT_BGP_VNC=1 --set-envvar=WANT_CUMULUS_MODE=1 -b -uc -us
+
+ To build with RPKI:
+
+ - Download the librtr packages from
+ https://ci1.netdef.org/browse/RPKI-RTRLIB/latestSuccessful/artifact
+
+ - install librtr-dev on the build server
+
+ Then build with:
+
+ .. code-block:: shell
+
+ debuild --set-envvar=WANT_RPKI=1 -b -uc -us
+
+ RPKI packages have an additonal dependency of ``librtr0`` which can be found
+ at the same URL.
+
+10. Done!
+
+If all worked correctly, then you should end up with the Debian packages under
+:file:`frrpkg`. If distributed, please make sure you distribute it together
+with the sources (``frr_*.orig.tar.gz``, ``frr_*.debian.tar.xz`` and
+``frr_*.dsc``)
+
+.. _deb-backports:
+
+Debian Backports
+----------------
+
+The :file:`debianpkg/backports` directory contains the Debian directories for
+backports to other Debian platforms. These are built via the ``3.0 (custom)``
+source format, which allows one to build a source package directly out of
+tarballs (e.g. an orig.tar.gz tarball and a debian.tar.gz file), at which point
+the format can be changed to a real format (e.g. ``3.0 (quilt)``).
+
+Source packages are assembled via targets of the same name as the system to
+which the backport is done (e.g. ``precise``), included in :file:`debian/rules`.
+
+To create a new Debian backport:
+
+- Add its name to ``KNOWN_BACKPORTS``, defined in :file:`debian/rules`.
+- Create a directory of the same name in :file:`debian/backports`.
+- Add the files ``exclude``, ``versionext``, and ``debian/source/format`` under
+ this directory.
+
+For the last point, these files should contain the following:
+
+``exclude``
+ Contains whitespace-separated paths (relative to the root of the source dir)
+ that should be excluded from the source package (e.g.
+ :file:`debian/patches`).
+
+``versionext``
+ Contains the suffix added to the version number for this backport's build.
+ Distributions often have guidelines for what this should be. If left empty,
+ no new :file:`debian/changelog` entry is created.
+
+``debian/source/format``
+ Contains the source format of the resulting source package. As of of the
+ writing of this document the only supported format is ``3.0 (quilt)``.
+
+- Add appropriate files under the :file:`debian/` subdirectory. These will be
+ included in the source package, overriding any top-level :file:`debian/`
+ files with equivalent paths.
+
--- /dev/null
+*********
+Packaging
+*********
+
+.. toctree::
+ :maxdepth: 2
+
+ packaging-debian
PAPER ?=
BUILDDIR = _build
+# This is a custom FRR variable just for this docs subdirectory used to support
+# VPATH builds. Makefiles which include this file should override it to point
+# to the correct sources path.
+SOURCESDIR ?= .
+
# User-friendly check for sphinx-build
ifneq ($(MAKECMDGOALS), clean)
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCESDIR)
# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCESDIR)
.PHONY: help
help:
/_templates
/_build
-!/Makefile
+!/Makefile.in
+++ /dev/null
-include ../frr-sphinx.mk
-
-# -----------------------------------------------------------------------------
-# Automake requires that 3rd-party Makefiles recognize these targets.
-# -----------------------------------------------------------------------------
-# install
-# install-data
-# install-exec
-# uninstall
-# install-dvi
-# install-html
-# install-info
-# install-ps
-# install-pdf
-# installdirs
-# check
-# installcheck
-# mostlyclean
-# clean
-# distclean
-# maintainer-clean
-# dvi
-# pdf
-# ps
-# info
-# html
-# tags
-# ctags
-
-# ignore these targets
-EMPTY_AUTOMAKE_TARGETS = dvi pdf ps tags ctags distdir installdirs check installcheck install-dvi install-ps install-html install-pdf install-info install-exec
-.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
-$(EMPTY_AUTOMAKE_TARGETS):
-
-# These targets are automatically generated by Sphinx but conflict with
-# implicitly defined Automake rules, so we manually override them to nothing.
-# The other option is deleting the Sphinx-generated rules, which suppresses the
-# warning but kinda screws up the symmetry between Makefiles.
-info: ;
-html: ;
-
-all: man
-
-install-data: man
-
-install: install-data
-
-mostlyclean distclean maintainer-clean: clean
--- /dev/null
+# This is necessary to support VPATH builds.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# This variable is used as the documentation source location in frr-sphinx.mk
+SOURCESDIR = @srcdir@
+
+include @srcdir@/../frr-sphinx.mk
+
+# -----------------------------------------------------------------------------
+# Automake requires that 3rd-party Makefiles recognize these targets.
+# -----------------------------------------------------------------------------
+# install
+# install-data
+# install-exec
+# uninstall
+# install-dvi
+# install-html
+# install-info
+# install-ps
+# install-pdf
+# installdirs
+# check
+# installcheck
+# mostlyclean
+# clean
+# distclean
+# maintainer-clean
+# dvi
+# pdf
+# ps
+# info
+# html
+# tags
+# ctags
+
+# ignore these targets
+EMPTY_AUTOMAKE_TARGETS = dvi pdf ps tags ctags distdir installdirs check installcheck install-dvi install-ps install-html install-pdf install-info install-exec
+.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
+$(EMPTY_AUTOMAKE_TARGETS):
+
+# These targets are automatically generated by Sphinx but conflict with
+# implicitly defined Automake rules, so we manually override them to nothing.
+# The other option is deleting the Sphinx-generated rules, which suppresses the
+# warning but kinda screws up the symmetry between Makefiles.
+info: ;
+html: ;
+
+all: man
+
+install-data: man
+
+install: install-data
+
+mostlyclean distclean maintainer-clean: clean
/_templates
/_build
-!/Makefile
+!/Makefile.in
+++ /dev/null
-include ../frr-sphinx.mk
-
-# -----------------------------------------------------------------------------
-# Automake requires that 3rd-party Makefiles recognize these targets.
-# -----------------------------------------------------------------------------
-# install
-# install-data
-# install-exec
-# uninstall
-# install-dvi
-# install-html
-# install-info
-# install-ps
-# install-pdf
-# installdirs
-# check
-# installcheck
-# mostlyclean
-# clean
-# distclean
-# maintainer-clean
-# dvi
-# pdf
-# ps
-# info
-# html
-# tags
-# ctags
-
-# ignore these targets
-EMPTY_AUTOMAKE_TARGETS = dvi ps tags ctags distdir install-exec install-dvi install-ps installdirs check installcheck install-html install-pdf install-data install
-.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
-$(EMPTY_AUTOMAKE_TARGETS):
-
-# When building 'all', the logic is that we want to make docs that are easily
-# readable by the person that just built them. Technically the reST source is
-# readable in its own right, but we'll also build info and html because those
-# offer sequentially better reading experiences. PDF is not built by default
-# because it takes quite a while.
-all: info
-
-# info and html already have built-in sphinx rules; pdf goes to latexpdf
-pdf: latexpdf
-
-# install user manual as info file
-install-info: info
- install -d ${DESTDIR}${infodir}
- gzip < _build/texinfo/frr.info > ${DESTDIR}${infodir}/frr.info.gz
- install-info _build/texinfo/frr.info ${DESTDIR}${infodir}/dir
-
-install-data: install-info
-
-install: install-data
-
-mostlyclean distclean maintainer-clean: clean
--- /dev/null
+# This is necessary to support VPATH builds.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# This variable is used as the documentation source location in frr-sphinx.mk
+SOURCESDIR = @srcdir@
+
+include @srcdir@/../frr-sphinx.mk
+
+# -----------------------------------------------------------------------------
+# Automake requires that 3rd-party Makefiles recognize these targets.
+# -----------------------------------------------------------------------------
+# install
+# install-data
+# install-exec
+# uninstall
+# install-dvi
+# install-html
+# install-info
+# install-ps
+# install-pdf
+# installdirs
+# check
+# installcheck
+# mostlyclean
+# clean
+# distclean
+# maintainer-clean
+# dvi
+# pdf
+# ps
+# info
+# html
+# tags
+# ctags
+
+# ignore these targets
+EMPTY_AUTOMAKE_TARGETS = dvi ps tags ctags distdir install-exec install-dvi install-ps installdirs check installcheck install-html install-pdf install-data install
+.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
+$(EMPTY_AUTOMAKE_TARGETS):
+
+# When building 'all', the logic is that we want to make docs that are easily
+# readable by the person that just built them. Technically the reST source is
+# readable in its own right, but we'll also build info and html because those
+# offer sequentially better reading experiences. PDF is not built by default
+# because it takes quite a while.
+all: info
+
+# info and html already have built-in sphinx rules; pdf goes to latexpdf
+pdf: latexpdf
+
+# install user manual as info file
+install-info: info
+ install -d ${DESTDIR}${infodir}
+ gzip < _build/texinfo/frr.info > ${DESTDIR}${infodir}/frr.info.gz
+ install-info _build/texinfo/frr.info ${DESTDIR}${infodir}/dir
+
+install-data: install-info
+
+install: install-data
+
+mostlyclean distclean maintainer-clean: clean
--- /dev/null
+.. _bugs:
+
+**************
+Reporting Bugs
+**************
+
+This file describes the procedure for reporting FRRouting bugs. You are asked
+to follow this format when submitting bug reports.
+
+Bugs submitted with woefully incomplete information will receive little
+attention and are likely to be closed. If you hit a suspected bug in an older
+version, you may be asked to test with a later version in your environment.
+
+Often you may be asked for additional information to help solve the bug. Bugs
+may be closed after 30 days of non-response to requests to reconfirm or supply
+additional information.
+
+Please report bugs on the project GitHub issue tracker at
+https://github.com/frrouting/frr/issues
+
+Report Format & Requested Information
+=====================================
+
+When reporting a bug, please provide the following information.
+
+#. Your FRR version if it is a release build, or the commit hash if you built
+ from source.
+
+#. If you compiled from source, please provide your ``./configure`` line,
+ including all option flags.
+
+#. A full list of the FRR daemons you run.
+
+#. Your platform name and version, e.g. ``Ubuntu 18.04``.
+
+#. Problem description.
+
+ - Provide as much information as possible.
+ - Copy and paste relevant commands and their output to describe your network
+ setup.
+ - Topology diagrams are helpful when reporting bugs involving more than one
+ box.
+ - Platform routing tables and interface configurations are useful if you are
+ reporting a routing issue.
+
+ *Please be sure to review the provided information and censor any sensitive
+ material.*
+
+#. All FRR configuration files you use. Again, please be sure to censor any
+ sensitive information. For sensitive v4 / v6 addresses, we ask that you
+ censor the inner octets; e.g., ``192.XXX.XXX.32/24``.
+
+#. If you are reporting a crash and have a core file, please supply a stack
+ trace using GDB:
+
+ ::
+
+ $ gdb exec_file core_file
+ (gdb) bt .
+
+#. Run all FRR daemons with full debugging on and send *only* the portion of
+ logs which are relevant to your problem.
+
+#. Patches, workarounds, and fixes are always welcome.
+
+.. seealso:: :ref:`basic-config-commands`
+
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
+# contents of ../extra/frrlexer.py.
+# This is read here to support VPATH build. Since this section is execfile()'d
+# with the file location, we can safely use a relative path here to save the
+# contents of the lexer file for later use even if our relative path changes
+# due to VPATH.
+with open('../extra/frrlexer.py', 'rb') as lex:
+ frrlexerpy = lex.read()
+
# custom extensions here
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
#
# frrlexer = pygments.lexers.load_lexer_from_file('../extra/frrlexer.py', lexername="FRRLexer")
custom_namespace = {}
- exec(open('../extra/frrlexer.py', 'rb').read(), custom_namespace)
+ exec(frrlexerpy, custom_namespace)
lexers['frr'] = custom_namespace['FRRLexer']()
ripngd
sharp
vnc
+ bugs
glossary
appendix
is used to forward the packets to the end destination
.. index:: pbr-map
-.. clicmd:: pbr-map NAME seq (1-1000)
+.. clicmd:: pbr-map NAME seq (1-700)
Create a pbr-map with NAME and sequence number specified. This command puts
you into a new submode for pbr-map specification. To exit this mode type
When *Zebra* starts with this option, the VRF backend is based on Linux
network namespaces. That implies that all network namespaces discovered by
ZEBRA will create an associated VRF. The other daemons will operate on the VRF
- VRF defined by *Zebra*, as usual. More information in the :ref:`VRF Commands`
- chapter.
+ VRF defined by *Zebra*, as usual.
-.. program:: configure
+ .. seealso:: :ref:`vrf`
.. _interface-commands:
Static Route Commands
=====================
-Static routing is a very fundamental feature of routing technology. It
-defines static prefix and gateway.
+Static routing is a very fundamental feature of routing technology. It defines
+static prefix and gateway.
.. index:: ip route NETWORK GATEWAY
.. clicmd:: ip route NETWORK GATEWAY
ip route 10.0.0.0/8 ppp0
ip route 10.0.0.0/8 null0
- First example defines 10.0.0.0/8 static route with gateway 10.0.0.2.
- Second one defines the same prefix but with gateway to interface ppp0. The
- third install a blackhole route.
+ First example defines 10.0.0.0/8 static route with gateway 10.0.0.2. Second
+ one defines the same prefix but with gateway to interface ppp0. The third
+ install a blackhole route.
.. index:: ip route NETWORK NETMASK GATEWAY
.. clicmd:: ip route NETWORK NETMASK GATEWAY
- This is alternate version of above command. When NETWORK is
- A.B.C.D format, user must define NETMASK value with A.B.C.D
- format. GATEWAY is same option as above command.
+ This is alternate version of above command. When NETWORK is A.B.C.D format,
+ user must define NETMASK value with A.B.C.D format. GATEWAY is same option
+ as above command.
.. code-block:: frr
on Linux operating systems only, and perform AND matching on packet's
destination and source addresses in the kernel's forwarding path. Note that
destination longest-prefix match is "more important" than source LPM, e.g.
- *"2001:db8:1::/64 from 2001:db8::/48"* will win over
- *"2001:db8::/48 from 2001:db8:1::/64"* if both match.
+ ``2001:db8:1::/64 from 2001:db8::/48`` will win over
+ ``2001:db8::/48 from 2001:db8:1::/64`` if both match.
.. index:: table TABLENO
.. clicmd:: table TABLENO
- Select the primary kernel routing table to be used. This only works
- for kernels supporting multiple routing tables (like GNU/Linux 2.2.x
- and later). After setting TABLENO with this command,
- static routes defined after this are added to the specified table.
+ Select the primary kernel routing table to be used. This only works for
+ kernels supporting multiple routing tables (like GNU/Linux 2.2.x and later).
+ After setting TABLENO with this command, static routes defined after this
+ are added to the specified table.
-.. _multicast-rib-commands:
+.. _vrf:
+
+Virtual Routing and Forwarding
+==============================
-VRF (Virtual Routing and Forwarding)
-====================================
+FRR supports :abbr:`VRF (Virtual Routing and Forwarding)`. VRF is a way to
+separate networking contexts on the same machine. Those networking contexts are
+associated with separate interfaces, thus making it possible to associate one
+interface with a specific VRF.
-Currently, the user has the possibility to configure VRFs. VRF is a way to
-separate networking contexts on the same machine. Those networking contexts
-are associated with separate interfaces, thus making it possible to associate
-one interface with a specific VRF.
VRF can be used, for example, when instantiating per enterprise networking
-services, without having to instantiate the physical host machine or the routing
-management daemons for each enterprise. As a result, interfaces are separate for
-each set of VRF, and routing daemons can have their own context for each VRF.
+services, without having to instantiate the physical host machine or the
+routing management daemons for each enterprise. As a result, interfaces are
+separate for each set of VRF, and routing daemons can have their own context
+for each VRF.
This conceptual view introduces the *Default VRF* case. If the user does not
-configure any specific VRF, then by default, the user will however configure the
-*Default VRF*.
-On the *Zebra* context, this can be done when being in configuration mode, when
-configuring a static route clicmd:`ip route NETWORK GATEWAY`.
+configure any specific VRF, then by default, FRR uses the *Default VRF*.
+
+In the context of *Zebra*, this is done automatically when configuring a static
+route with, for example, :clicmd:`ip route NETWORK GATEWAY`:
.. code-block:: frr
exit
Configuring VRF networking contexts can be done in various ways on FRR. The VRF
-interfaces can be configured by entering in interface configuration mode :
-:clicmd:`interface IFNAME vrf VRF`. Also, if the user wants to configure a static
-route for a specific VRF, then a specific VRF configuration mode is available. After
-entering into that mode by following command: :clicmd:`vrf VRF`. the user can enter
-the same route command as before, but this time, the route command will apply to vrf
-VRF.
+interfaces can be configured by entering in interface configuration mode
+:clicmd:`interface IFNAME vrf VRF`. Also, if the user wants to configure a
+static route for a specific VRF, then a specific VRF configuration mode is
+available. After entering into that mode with :clicmd:`vrf VRF` the user can
+enter the same route command as before, but this time, the route command will
+apply to the VRF.
.. code-block:: frr
A VRF backend mode is chosen when running *Zebra*.
If no option is chosen, then the *Linux VRF* implementation as references in
-`https://www.kernel.org/doc/Documentation/networking/vrf.txt` will be mapped over
+https://www.kernel.org/doc/Documentation/networking/vrf.txt will be mapped over
the *Zebra* VRF. The routing table associated to that VRF is a Linux table
identifier located in the same *Linux network namespace* where *Zebra* started.
-If the :option:`-n` option is chosen, then the *Linux network namespace* will be
-mapped over the *Zebra* VRF. That implies that *Zebra* is able to configure several
-*Linux network namespaces*. The routing table associated to that VRF is the whole
-routing tables located in that namespace. For instance, this mode matches OpenStack
-Network Namespaces. It matches also OpenFastPath. The default behavior remains Linux
-VRF which is supported by the Linux kernel community, see
-`https://www.kernel.org/doc/Documentation/networking/vrf.txt`.
+If the :option:`-n` option is chosen, then the *Linux network namespace* will
+be mapped over the *Zebra* VRF. That implies that *Zebra* is able to configure
+several *Linux network namespaces*. The routing table associated to that VRF
+is the whole routing tables located in that namespace. For instance, this mode
+matches OpenStack Network Namespaces. It matches also OpenFastPath. The default
+behavior remains Linux VRF which is supported by the Linux kernel community,
+see https://www.kernel.org/doc/Documentation/networking/vrf.txt.
Because of that difference, there are some subtle differences when running some
commands in relationship to VRF. Here is an extract of some of those commands:
.. clicmd:: vrf VRF
This command is available on configuration mode. By default, above command
- permits accessing the vrf configuration mode. This mode is available for both
- VRFs. It is to be noted that *Zebra* does not create *Linux VRF*. Provisioning
- this command is used to keep the configuration intact.
+ permits accessing the vrf configuration mode. This mode is available for
+ both VRFs. It is to be noted that *Zebra* does not create *Linux VRF*.
+ Provisioning this command is used to keep the configuration intact.
.. index:: netns NAMESPACE
.. clicmd:: netns NAMESPACE
- This command is based on VRF configuration mode. This command is available when
- *Zebra* is run in :option:`-n` mode. This command reflects which *Linux network
- namespace* is to be mapped with *Zebra* VRF. It is to be noted that *Zebra*
- creates and detects added/suppressed VRFs from the Linux environment (in fact,
- those managed with iproute2). Provisioning this command is used to keep the
- configuration intact.
-
-.. index:: ip route NETWORK NETMASK GATEWAY
-.. clicmd:: ip route NETWORK NETMASK GATEWAY
-
- This command is based on VRF configuration mode or in configuration mode. If
- applied on configuration mode, this applies to default VRF. Otherwise, this
- command applies to the VRF of the vrf configuration mode. By default, above
- command permits configuring a network in the table identifier of the mentioned
- VRF. If :option:`-n` option is given, the network will be configured in the
- default routing table of the *Linux network namespace*.
+ This command is based on VRF configuration mode. This command is available
+ when *Zebra* is run in :option:`-n` mode. This command reflects which *Linux
+ network namespace* is to be mapped with *Zebra* VRF. It is to be noted that
+ *Zebra* creates and detects added/suppressed VRFs from the Linux environment
+ (in fact, those managed with iproute2). Provisioning this command is used to
+ keep the configuration intact.
.. index:: ip route NETWORK NETMASK GATEWAY NEXTHOPVRF
.. clicmd:: ip route NETWORK NETMASK GATEWAY NEXTHOPVRF
This command is based on VRF configuration mode or in configuration mode. If
on configuration mode, this applies to default VRF. Otherwise, this command
applies to the VRF of the vrf configuration mode. This command is used to
- configure a vrf route leak across 2 VRFs. This command is only available when
- *Zebra* is launched without :option:`-n` option.
+ configure a vrf route leak across 2 VRFs. This command is only available
+ when *Zebra* is launched without :option:`-n` option.
.. index:: ip route NETWORK NETMASK GATEWAY table TABLENO
.. clicmd:: ip route NETWORK NETMASK GATEWAY table TABLENO
- This command is based on VRF configuration mode. There, this command is only
- available with :option:`-n` command. This commands permits configuring a network
- route in the given ``TABLENO`` of the *Linux network namespace*.
-
-.. index:: ip route NETWORK NETMASK GATEWAY table TABLENO
-.. clicmd:: ip route NETWORK NETMASK GATEWAY table TABLENO
-
- This command is based on configuration mode. There, for default VRF, this command
- is available for all modes. The ``TABLENO`` configured is one of the tables from
- Default *Linux network namespace*.
+ This command is based on configuration mode. There, for default VRF, this
+ command is available for all modes. The ``TABLENO`` configured is one of the
+ tables from Default *Linux network namespace*.
.. index:: show ip route vrf VRF
.. clicmd:: show ip route vrf VRF
The show command permits dumping the routing table associated to the VRF. If
- *Zebra* is launched with default settings, this will be the ``TABLENO`` of the
- VRF configured on the kernel, thanks to information provided in
- `https://www.kernel.org/doc/Documentation/networking/vrf.txt`.
- If *Zebra* is launched with :option:`-n` option, this will be the default routing
- table of the *Linux network namespace* ``VRF``.
+ *Zebra* is launched with default settings, this will be the ``TABLENO`` of
+ the VRF configured on the kernel, thanks to information provided in
+ https://www.kernel.org/doc/Documentation/networking/vrf.txt. If *Zebra* is
+ launched with :option:`-n` option, this will be the default routing table of
+ the *Linux network namespace* ``VRF``.
.. index:: show ip route vrf VRF table TABLENO
.. clicmd:: show ip route vrf VRF table TABLENO
- The show command is only available with :option:`-n` option.
- This command will dump the routing table ``TABLENO`` of the *Linux network
- namespace* ``VRF``.
+ The show command is only available with :option:`-n` option. This command
+ will dump the routing table ``TABLENO`` of the *Linux network namespace*
+ ``VRF``.
+
+The usual static route commands are also available in the VRF context. When
+entered within the VRF context the static routes are created in the VRF.
.. code-block:: frr
show ip table vrf r1-cust1 table 43
+.. _multicast-rib-commands:
+
Multicast RIB Commands
======================
the FPM. The connection is initiated by zebra -- that is, the FPM acts
as the TCP server.
+.. program:: configure
+
The relevant zebra code kicks in when zebra is configured with the
:option:`--enable-fpm` flag. Zebra periodically attempts to connect to
the well-known FPM port. Once the connection is up, zebra starts
"keychain", // KEYCHAIN_NODE,
"keychain key", // KEYCHAIN_KEY_NODE,
"logical-router", // LOGICALROUTER_NODE,
+ "static ip", // IP_NODE,
"vrf", // VRF_NODE,
"interface", // INTERFACE_NODE,
"nexthop-group", // NH_GROUP_NODE,
"ldp l2vpn", // LDP_L2VPN_NODE,
"ldp", // LDP_PSEUDOWIRE_NODE,
"isis", // ISIS_NODE,
- "static ip", // IP_NODE,
"ipv4 access list", // ACCESS_NODE,
"ipv4 prefix list", // PREFIX_NODE,
"ipv6 access list", // ACCESS_IPV6_NODE,
if (cmd_domainname_get())
vty_out(vty, "domainname %s\n", cmd_domainname_get());
- if (host.encrypt) {
- if (host.password_encrypt)
- vty_out(vty, "password 8 %s\n", host.password_encrypt);
- if (host.enable_encrypt)
- vty_out(vty, "enable password 8 %s\n",
- host.enable_encrypt);
- } else {
- if (host.password)
- vty_out(vty, "password %s\n", host.password);
- if (host.enable)
- vty_out(vty, "enable password %s\n", host.enable);
- }
+ /* The following are all configuration commands that are not sent to
+ * watchfrr. For instance watchfrr is hardcoded to log to syslog so
+ * we would always display 'log syslog informational' in the config
+ * which would cause other daemons to then switch to syslog when they
+ * parse frr.conf.
+ */
+ if (strcmp(zlog_default->protoname, "WATCHFRR")) {
+ if (host.encrypt) {
+ if (host.password_encrypt)
+ vty_out(vty, "password 8 %s\n",
+ host.password_encrypt);
+ if (host.enable_encrypt)
+ vty_out(vty, "enable password 8 %s\n",
+ host.enable_encrypt);
+ } else {
+ if (host.password)
+ vty_out(vty, "password %s\n", host.password);
+ if (host.enable)
+ vty_out(vty, "enable password %s\n",
+ host.enable);
+ }
- if (zlog_default->default_lvl != LOG_DEBUG) {
- vty_out(vty, "! N.B. The 'log trap' command is deprecated.\n");
- vty_out(vty, "log trap %s\n",
- zlog_priority[zlog_default->default_lvl]);
- }
+ if (zlog_default->default_lvl != LOG_DEBUG) {
+ vty_out(vty,
+ "! N.B. The 'log trap' command is deprecated.\n");
+ vty_out(vty, "log trap %s\n",
+ zlog_priority[zlog_default->default_lvl]);
+ }
- if (host.logfile
- && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) {
- vty_out(vty, "log file %s", host.logfile);
- if (zlog_default->maxlvl[ZLOG_DEST_FILE]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority
- [zlog_default->maxlvl[ZLOG_DEST_FILE]]);
- vty_out(vty, "\n");
- }
+ if (host.logfile
+ && (zlog_default->maxlvl[ZLOG_DEST_FILE]
+ != ZLOG_DISABLED)) {
+ vty_out(vty, "log file %s", host.logfile);
+ if (zlog_default->maxlvl[ZLOG_DEST_FILE]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority
+ [zlog_default->maxlvl
+ [ZLOG_DEST_FILE]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
- vty_out(vty, "log stdout");
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority[zlog_default->maxlvl
- [ZLOG_DEST_STDOUT]]);
- vty_out(vty, "\n");
- }
+ if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
+ vty_out(vty, "log stdout");
+ if (zlog_default->maxlvl[ZLOG_DEST_STDOUT]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority
+ [zlog_default->maxlvl
+ [ZLOG_DEST_STDOUT]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
- vty_out(vty, "no log monitor\n");
- else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR]
- != zlog_default->default_lvl)
- vty_out(vty, "log monitor %s\n",
- zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]]);
-
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
- vty_out(vty, "log syslog");
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
+ if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
+ vty_out(vty, "no log monitor\n");
+ else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR]
+ != zlog_default->default_lvl)
+ vty_out(vty, "log monitor %s\n",
zlog_priority[zlog_default->maxlvl
- [ZLOG_DEST_SYSLOG]]);
- vty_out(vty, "\n");
- }
+ [ZLOG_DEST_MONITOR]]);
+
+ if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
+ vty_out(vty, "log syslog");
+ if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority[zlog_default->maxlvl
+ [ZLOG_DEST_SYSLOG]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->facility != LOG_DAEMON)
- vty_out(vty, "log facility %s\n",
- facility_name(zlog_default->facility));
+ if (zlog_default->facility != LOG_DAEMON)
+ vty_out(vty, "log facility %s\n",
+ facility_name(zlog_default->facility));
- if (zlog_default->record_priority == 1)
- vty_out(vty, "log record-priority\n");
+ if (zlog_default->record_priority == 1)
+ vty_out(vty, "log record-priority\n");
- if (zlog_default->timestamp_precision > 0)
- vty_out(vty, "log timestamp precision %d\n",
- zlog_default->timestamp_precision);
+ if (zlog_default->timestamp_precision > 0)
+ vty_out(vty, "log timestamp precision %d\n",
+ zlog_default->timestamp_precision);
- if (host.advanced)
- vty_out(vty, "service advanced-vty\n");
+ if (host.advanced)
+ vty_out(vty, "service advanced-vty\n");
- if (host.encrypt)
- vty_out(vty, "service password-encryption\n");
+ if (host.encrypt)
+ vty_out(vty, "service password-encryption\n");
- if (host.lines >= 0)
- vty_out(vty, "service terminal-length %d\n", host.lines);
+ if (host.lines >= 0)
+ vty_out(vty, "service terminal-length %d\n",
+ host.lines);
- if (host.motdfile)
- vty_out(vty, "banner motd file %s\n", host.motdfile);
- else if (!host.motd)
- vty_out(vty, "no banner motd\n");
+ if (host.motdfile)
+ vty_out(vty, "banner motd file %s\n", host.motdfile);
+ else if (!host.motd)
+ vty_out(vty, "no banner motd\n");
+ }
if (debug_memstats_at_exit)
vty_out(vty, "!\ndebug memstats-at-exit\n");
#if defined(HAVE_CUMULUS)
if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
- zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED;
+ zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
#endif
return CMD_SUCCESS;
}
zlog_default->default_lvl);
}
+static void disable_log_file(void)
+{
+ zlog_reset_file();
+
+ if (host.logfile)
+ XFREE(MTYPE_HOST, host.logfile);
+
+ host.logfile = NULL;
+}
+
DEFUN (no_config_log_file,
no_config_log_file_cmd,
"no log file [FILENAME [LEVEL]]",
"Logging file name\n"
"Logging level\n")
{
- zlog_reset_file();
-
- if (host.logfile)
- XFREE(MTYPE_HOST, host.logfile);
-
- host.logfile = NULL;
-
+ disable_log_file();
return CMD_SUCCESS;
}
LOG_LEVEL_DESC)
{
int idx_log_levels = 2;
+
+ disable_log_file();
+
if (argc == 3) {
int level;
if ((level = level_match(argv[idx_log_levels]->arg))
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
LOGICALROUTER_NODE, /* Logical-Router node. */
+ IP_NODE, /* Static ip route node. */
VRF_NODE, /* VRF mode node. */
INTERFACE_NODE, /* Interface mode node. */
NH_GROUP_NODE, /* Nexthop-Group mode node. */
LDP_L2VPN_NODE, /* LDP L2VPN node */
LDP_PSEUDOWIRE_NODE, /* LDP Pseudowire node */
ISIS_NODE, /* ISIS protocol mode */
- IP_NODE, /* Static ip route node. */
ACCESS_NODE, /* Access list node. */
PREFIX_NODE, /* Prefix list node. */
ACCESS_IPV6_NODE, /* Access list node. */
memcpy((char *)in6 + 12, &in, sizeof(struct in_addr));
}
+/*
+ * convert an ipv4 mapped ipv6 address back to ipv4 address
+ */
+static inline void ipv4_mapped_ipv6_to_ipv4(struct in6_addr *in6,
+ struct in_addr *in)
+{
+ memset(in, 0, sizeof(struct in_addr));
+ memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
+}
+
#endif /* __IPADDR_H__ */
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putc(s, api->safi);
- if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
- stream_put(s, &(api->rmac), sizeof(struct ethaddr));
/* Put prefix information. */
stream_putc(s, api->prefix.family);
api_nh->label_num
* sizeof(mpls_label_t));
}
+
+ /* Router MAC for EVPN routes. */
+ if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+ stream_put(s, &(api_nh->rmac),
+ sizeof(struct ethaddr));
}
}
STREAM_GETL(s, api->flags);
STREAM_GETC(s, api->message);
STREAM_GETC(s, api->safi);
- if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
- STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
/* Prefix. */
STREAM_GETC(s, api->prefix.family);
api_nh->label_num
* sizeof(mpls_label_t));
}
+
+ /* Router MAC for EVPN routes. */
+ if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+ stream_get(&(api_nh->rmac), s,
+ sizeof(struct ethaddr));
}
}
/* MPLS labels for BGP-LU or Segment Routing */
uint8_t label_num;
mpls_label_t labels[MPLS_MAX_LABELS];
+
+ struct ethaddr rmac;
};
/*
vrf_id_t vrf_id;
uint32_t tableid;
-
- struct ethaddr rmac;
};
/* Zebra IPv4 route message API. */
ospf_opaque_type9_lsa_init(oi);
oi->ospf = ospf;
+
+ ospf_if_stream_set(oi);
+
QOBJ_REG(oi, ospf_interface);
if (IS_DEBUG_OSPF_EVENT)
{
ospf_if_down(oi);
+ if (oi->obuf)
+ ospf_fifo_free(oi->obuf);
+
assert(oi->state == ISM_Down);
ospf_opaque_type9_lsa_term(oi);
struct ospf *ospf = oi->ospf;
if (oi->obuf) {
- ospf_fifo_free(oi->obuf);
- oi->obuf = NULL;
-
+ /* flush the interface packet queue */
+ ospf_fifo_flush(oi->obuf);
/*reset protocol stats */
ospf_if_reset_stats(oi);
if (oi->type == OSPF_IFTYPE_LOOPBACK)
OSPF_ISM_EVENT_SCHEDULE(oi, ISM_LoopInd);
else {
- ospf_if_stream_set(oi);
OSPF_ISM_EVENT_SCHEDULE(oi, ISM_InterfaceUp);
}
#include "pbrd/pbr_vty_clippy.c"
#endif
-DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-1000)",
+DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-700)",
"Create pbr-map or enter pbr-map command mode\n"
"The name of the PBR MAP\n"
"Sequence to insert in existing pbr-map entry\n"
return CMD_SUCCESS;
}
-DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-65535)]",
+DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
NO_STR
"Delete pbr-map\n"
"The name of the PBR MAP\n"
%defattr(-,root,root)
%doc */*.sample* AUTHORS COPYING
%doc doc/mpls
-%doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES
+%doc ChangeLog NEWS README SERVICES
%if 0%{?frr_user:1}
%dir %attr(751,%frr_user,%frr_user) %{_sysconfdir}
%dir %attr(750,%frr_user,%frr_user) /var/log/frr
}
DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
- "pbr-map NAME seq (1-1000)",
+ "pbr-map NAME seq (1-700)",
"Create pbr-map or enter pbr-map command mode\n"
"The name of the PBR MAP\n"
"Sequence to insert to/delete from existing pbr-map entry\n"
return CMD_SUCCESS;
}
-DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map WORD [seq (1-65535)]",
+DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
NO_STR
"Delete pbr-map\n"
"The name of the PBR MAP\n"
* head.
*/
rib_delete(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, &nh, 0, 0, false, NULL);
+ &p, NULL, &nh, 0, 0, false);
rib_delete(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, &nh, 0, 0, false, NULL);
+ &p, NULL, &nh, 0, 0, false);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
char buf[PREFIX_STRLEN];
struct interface *ifp,
ns_id_t ns_id)
{
- struct interface *old_ifp;
+ struct interface *other_ifp;
/*
* look if interface name is also found on other netns
if (!vrf_is_backend_netns() ||
!strcmp(ifp->name, "lo"))
return;
- old_ifp = if_lookup_by_name_not_ns(ns_id, ifp->name);
- if (!old_ifp)
+ other_ifp = if_lookup_by_name_not_ns(ns_id, ifp->name);
+ if (!other_ifp)
+ return;
+ /* because previous interface may be inactive,
+ * interface is moved back to default vrf
+ * then one may find the same pointer; ignore
+ */
+ if (other_ifp == ifp)
return;
if ((cmd == RTM_NEWLINK)
- && (CHECK_FLAG(old_ifp->status, ZEBRA_INTERFACE_ACTIVE)))
+ && (CHECK_FLAG(other_ifp->status, ZEBRA_INTERFACE_ACTIVE)))
return;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s %s(%u) %s VRF %u",
- cmd == RTM_DELLINK ?
- "RTM_DELLINK replaced by" :
- "RTM_NEWLINK replaces",
+ if (IS_ZEBRA_DEBUG_KERNEL && cmd == RTM_NEWLINK) {
+ zlog_debug("RTM_NEWLINK %s(%u, VRF %u) replaces %s(%u, VRF %u)\n",
ifp->name,
- old_ifp->ifindex,
- cmd == RTM_DELLINK ?
- "in" : "from",
- old_ifp->vrf_id);
+ ifp->ifindex,
+ ifp->vrf_id,
+ other_ifp->name,
+ other_ifp->ifindex,
+ other_ifp->vrf_id);
+ } else if (IS_ZEBRA_DEBUG_KERNEL && cmd == RTM_DELLINK) {
+ zlog_debug("RTM_DELLINK %s(%u, VRF %u) is replaced by %s(%u, VRF %u)\n",
+ ifp->name,
+ ifp->ifindex,
+ ifp->vrf_id,
+ other_ifp->name,
+ other_ifp->ifindex,
+ other_ifp->vrf_id);
+ }
/* the found interface replaces the current one
* remove it
*/
if (cmd == RTM_DELLINK)
if_delete(ifp);
else
- if_delete(old_ifp);
+ if_delete(other_ifp);
/* the found interface is replaced by the current one
* suppress it
*/
if (rn->info) {
ifp = (struct interface *)rn->info;
route_unlock_node(rn); /* get */
+ ifp->node = rn;
return ifp;
}
return;
}
+ if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
+ return;
+
/* Mark interface as inactive */
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
br_slave->bridge_ifindex);
}
- if (zebra_if->link_ifindex != IFINDEX_INTERNAL)
- vty_out(vty, " Link ifindex %u\n", zebra_if->link_ifindex);
+ if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
+ vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex);
+ if (zebra_if->link)
+ vty_out(vty, "(%s)\n", zebra_if->link->name);
+ else
+ vty_out(vty, "(Unknown)\n");
+ }
if (HAS_LINK_PARAMS(ifp)) {
int i;
int read_in = 0;
while (1) {
- char buf[NL_PKT_BUF_SIZE];
+ char buf[NL_RCV_PKT_BUF_SIZE];
struct iovec iov = {.iov_base = buf, .iov_len = sizeof buf};
struct sockaddr_nl snl;
struct msghdr msg = {.msg_name = (void *)&snl,
#ifdef HAVE_NETLINK
+#define NL_RCV_PKT_BUF_SIZE 32768
#define NL_PKT_BUF_SIZE 8192
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
if (rtm->rtm_type == RTM_CHANGE)
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, true, NULL);
+ NULL, 0, 0, true);
if (!nh.type) {
nh.type = NEXTHOP_TYPE_IPV4;
else
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, true, NULL);
+ &nh, 0, 0, true);
}
if (dest.sa.sa_family == AF_INET6) {
/* One day we might have a debug section here like one in the
if (rtm->rtm_type == RTM_CHANGE)
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, true, NULL);
+ NULL, 0, 0, true);
if (!nh.type) {
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
else
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, true, NULL);
+ &nh, 0, 0, true);
}
}
rib_delete(afi, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, re->table,
re->flags, &p, NULL, re->ng.nexthop,
- zebrad.rtm_table_default, re->metric, false, NULL);
+ zebrad.rtm_table_default, re->metric, false);
return 0;
}
extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
unsigned short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
- uint32_t table_id, uint32_t metric, bool fromkernel,
- struct ethaddr *rmac);
+ uint32_t table_id, uint32_t metric, bool fromkernel);
extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
union g_addr *addr,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, &nh, table, metric, true, NULL);
+ &p, NULL, &nh, table, metric, true);
} else {
/* XXX: need to compare the entire list of nexthops
* here for NLM_F_APPEND stupidity */
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, NULL, table, metric, true, NULL);
+ &p, NULL, NULL, table, metric, true);
}
}
"netlink_route_multipath() (%s): "
"nexthop via if %u",
routedesc, nexthop->ifindex);
- } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via if %u",
- routedesc, nexthop->ifindex);
- } else {
- rtnh->rtnh_ifindex = 0;
}
}
&(api_nh->gate.ipv4),
sizeof(struct in_addr));
zebra_vxlan_evpn_vrf_route_add(
- vrf_id, &api.rmac, &vtep_ip,
+ vrf_id, &api_nh->rmac, &vtep_ip,
&api.prefix);
}
break;
&(api_nh->gate.ipv6),
sizeof(struct in6_addr));
zebra_vxlan_evpn_vrf_route_add(
- vrf_id, &api.rmac, &vtep_ip,
+ vrf_id, &api_nh->rmac, &vtep_ip,
&api.prefix);
}
break;
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &api.prefix, src_p, NULL, table_id, api.metric,
- false, &api.rmac);
+ false);
/* Stats */
switch (api.prefix.family) {
table_id = zvrf->table_id;
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
- api.flags, &p, NULL, NULL, table_id, 0, false, NULL);
+ api.flags, &p, NULL, NULL, table_id, 0, false);
client->v4_route_del_cnt++;
stream_failure:
src_pp = NULL;
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
- api.flags, &p, src_pp, NULL, client->rtm_table, 0, false,
- NULL);
+ api.flags, &p, src_pp, NULL, client->rtm_table, 0, false);
client->v6_route_del_cnt++;
int old_ptm_enable;
int send_linkdown = 0;
+ if_data = ifp->info;
+ if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
+
if (ifp->ifindex == IFINDEX_INTERNAL) {
return CMD_SUCCESS;
}
}
}
- if_data = ifp->info;
- if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
-
return CMD_SUCCESS;
}
void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
unsigned short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
- uint32_t table_id, uint32_t metric, bool fromkernel,
- struct ethaddr *rmac)
+ uint32_t table_id, uint32_t metric, bool fromkernel)
{
struct route_table *table;
struct route_node *rn;
&(tmp_nh->gate.ipv6),
sizeof(struct in6_addr));
}
- zebra_vxlan_evpn_vrf_route_del(re->vrf_id, rmac,
+ zebra_vxlan_evpn_vrf_route_del(re->vrf_id,
&vtep_ip, p);
}
}
DEFUN (no_vrf_vni_mapping,
no_vrf_vni_mapping_cmd,
- "no vni " CMD_VNI_RANGE,
+ "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
NO_STR
"VNI corresponding to tenant VRF\n"
- "VNI-ID")
+ "VNI-ID\n"
+ "prefix-routes-only\n")
{
int ret = 0;
+ int filter = 0;
char err[ERR_STR_SZ];
vni_t vni = strtoul(argv[2]->arg, NULL, 10);
assert(vrf);
assert(zvrf);
- ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
+ if (argc == 4)
+ filter = 1;
+
+ ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err,
+ ERR_STR_SZ, filter, 0);
if (ret != 0) {
vty_out(vty, "%s\n", err);
return CMD_WARNING;
/* handle rmac delete */
-static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
+static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
struct prefix *host_prefix)
{
- zebra_mac_t *zrmac = NULL;
-
- zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
- if (!zrmac)
- return -1;
-
host_list_delete_host(zrmac->host_list, host_prefix);
if (list_isempty(zrmac->host_list)) {
/* del the rmac entry */
zl3vni_rmac_del(zl3vni, zrmac);
}
- return 0;
}
/*
}
/* handle nh neigh delete */
-static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
- struct prefix *host_prefix)
+static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh,
+ struct prefix *host_prefix)
{
- zebra_neigh_t *nh = NULL;
-
- nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
- if (!nh)
- return -1;
-
host_list_delete_host(nh->host_list, host_prefix);
if (list_isempty(nh->host_list)) {
/* delete the nh entry */
zl3vni_nh_del(zl3vni, nh);
}
-
- return 0;
}
/* handle neigh update from kernel - the only thing of interest is to
struct prefix *host_prefix)
{
zebra_l3vni_t *zl3vni = NULL;
+ struct ipaddr ipv4_vtep;
zl3vni = zl3vni_from_vrf(vrf_id);
if (!zl3vni || !is_l3vni_oper_up(zl3vni))
return;
- /* add the next hop neighbor */
+ /*
+ * add the next hop neighbor -
+ * neigh to be installed is the ipv6 nexthop neigh
+ */
zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
- /* add the rmac */
- zl3vni_remote_rmac_add(zl3vni, rmac, vtep_ip, host_prefix);
+ /*
+ * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
+ * address. Rmac is programmed against the ipv4 vtep because we only
+ * support ipv4 tunnels in the h/w right now
+ */
+ memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
+ ipv4_vtep.ipa_type = IPADDR_V4;
+ if (vtep_ip->ipa_type == IPADDR_V6)
+ ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
+ &(ipv4_vtep.ipaddr_v4));
+ else
+ memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
+ sizeof(struct in_addr));
+
+ /*
+ * add the rmac - remote rmac to be installed is against the ipv4
+ * nexthop address
+ */
+ zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
}
/* handle evpn vrf route delete */
-void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, struct ethaddr *rmac,
+void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
struct ipaddr *vtep_ip,
struct prefix *host_prefix)
{
zebra_l3vni_t *zl3vni = NULL;
+ zebra_neigh_t *nh = NULL;
+ zebra_mac_t *zrmac = NULL;
zl3vni = zl3vni_from_vrf(vrf_id);
if (!zl3vni)
return;
+ /* find the next hop entry and rmac entry */
+ nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
+ if (!nh)
+ return;
+ zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
+
/* delete the next hop entry */
- zl3vni_remote_nh_del(zl3vni, vtep_ip, host_prefix);
+ zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
/* delete the rmac entry */
- zl3vni_remote_rmac_del(zl3vni, rmac, host_prefix);
+ if (zrmac)
+ zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
+
}
void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
l += IPV4_MAX_BYTELEN;
/* Get flags - sticky mac and/or gateway mac */
- flags = stream_getc(s);
+ STREAM_GETC(s, flags);
sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
l++;
return -1;
}
+ if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
+ snprintf(err, ERR_STR_SZ,
+ "prefix-routes-only is not set for the vni");
+ return -1;
+ }
+
zebra_vxlan_process_l3vni_oper_down(zl3vni);
/* delete and uninstall all rmacs */
}
s = msg;
- advertise = stream_getc(s);
+ STREAM_GETC(s, advertise);
vni = stream_get3(s);
zvni = zvni_lookup(vni);
zvni_advertise_subnet(zvni, vlan_if, 1);
else
zvni_advertise_subnet(zvni, vlan_if, 0);
+
+stream_failure:
+ return;
}
/*
s = msg;
STREAM_GETC(s, advertise);
- STREAM_GET(&vni, s, 3);
+ STREAM_GETL(s, vni);
if (!vni) {
if (IS_ZEBRA_DEBUG_VXLAN)
struct ipaddr *ip,
struct prefix *host_prefix);
extern void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
- struct ethaddr *rmac,
struct ipaddr *vtep_ip,
struct prefix *host_prefix);