]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2217 from donaldsharp/pim_threads
authorRuss White <russ@riw.us>
Sat, 12 May 2018 10:41:27 +0000 (06:41 -0400)
committerGitHub <noreply@github.com>
Sat, 12 May 2018 10:41:27 +0000 (06:41 -0400)
Pim cleanup when networking restarts under itself

66 files changed:
COMMUNITY.md [deleted file]
Makefile.am
README
README.NetBSD [deleted file]
REPORTING-BUGS [deleted file]
bgpd/bgp_evpn.c
bgpd/bgp_evpn_vty.c
bgpd/bgp_fsm.c
bgpd/bgp_io.c
bgpd/bgp_main.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_route.c
bgpd/bgp_updgrp_packet.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
configure.ac
debianpkg/README.deb_build.md [deleted file]
debianpkg/frr-doc.docs
doc/Makefile.am
doc/developer/.gitignore
doc/developer/Makefile [deleted file]
doc/developer/Makefile.in [new file with mode: 0644]
doc/developer/building-frr-on-openbsd6.rst
doc/developer/building.rst
doc/developer/conf.py
doc/developer/index.rst
doc/developer/packaging-debian.rst [new file with mode: 0644]
doc/developer/packaging.rst [new file with mode: 0644]
doc/frr-sphinx.mk
doc/manpages/.gitignore
doc/manpages/Makefile [deleted file]
doc/manpages/Makefile.in [new file with mode: 0644]
doc/user/.gitignore
doc/user/Makefile [deleted file]
doc/user/Makefile.in [new file with mode: 0644]
doc/user/bugs.rst [new file with mode: 0644]
doc/user/conf.py
doc/user/index.rst
doc/user/pbr.rst
doc/user/zebra.rst
lib/command.c
lib/command.h
lib/ipaddr.h
lib/zclient.c
lib/zclient.h
ospfd/ospf_interface.c
pbrd/pbr_vty.c
redhat/frr.spec.in
vtysh/vtysh.c
zebra/connected.c
zebra/if_netlink.c
zebra/interface.c
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/kernel_socket.c
zebra/redistribute.c
zebra/rib.h
zebra/rt_netlink.c
zebra/zapi_msg.c
zebra/zebra_ptm.c
zebra/zebra_rib.c
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h

diff --git a/COMMUNITY.md b/COMMUNITY.md
deleted file mode 100644 (file)
index fa00310..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Moved to doc/developer/workflow.rst
index 6cac1a7ba344111cda068d796d08c4cb73133249..3b8deb5884e364228a780f36b5afbf034127dff5 100644 (file)
@@ -83,7 +83,6 @@ rc_SCRIPTS = \
 endif
 
 EXTRA_DIST += \
-       REPORTING-BUGS \
        SERVICES \
        aclocal.m4 \
        update-autotools \
diff --git a/README b/README
index af14795a6a4465c7bab8a915441d5612f74861b2..95ed0d3fc299bbd3b97c81b77ca8149ed57b0cfd 100644 (file)
--- a/README
+++ b/README
@@ -5,9 +5,9 @@ Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng,
 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.
 
diff --git a/README.NetBSD b/README.NetBSD
deleted file mode 100755 (executable)
index c97e3bc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/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
diff --git a/REPORTING-BUGS b/REPORTING-BUGS
deleted file mode 100644 (file)
index 339ebc2..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-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.
index ad45da84eb207d36faa26c6b5994649b6584df7c..ee53beb191d2f553a5d17179fc53afb9c8a201e7 100644 (file)
@@ -1819,12 +1819,15 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
 
        /* 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)
@@ -1841,7 +1844,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
                               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));
@@ -1913,7 +1916,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
                               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));
@@ -4425,8 +4428,10 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
        /* 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;
        }
 
index c74a1bfb7cf8bcd4398de2b4305eaa73d75dc101..fd3c2294724a76f548494b1baf5e0542158de128 100644 (file)
@@ -311,7 +311,7 @@ static void bgp_evpn_show_route_rd_header(struct vty *vty,
 }
 
 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";
@@ -319,9 +319,8 @@ static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
        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");
@@ -494,12 +493,16 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
 {
        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;
@@ -519,7 +522,8 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
                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;
                        }
 
@@ -603,9 +607,9 @@ static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
 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];
@@ -862,6 +866,8 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
 
        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 */
 
@@ -872,6 +878,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                        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) {
@@ -891,7 +898,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                        json_object_int_add(
                                                                json,
                                                                "bgpTableVersion",
-                                                               0);
+                                                               tbl_ver);
                                                        json_object_string_add(
                                                                json,
                                                                "bgpLocalRouterId",
@@ -917,7 +924,8 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                                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,
@@ -2201,11 +2209,13 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                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));
 
@@ -2236,6 +2246,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                                /* Overall header/legend displayed once. */
                                if (header) {
                                        bgp_evpn_show_route_header(vty, bgp,
+                                                                  tbl_ver,
                                                                   json);
                                        header = 0;
                                }
@@ -2873,7 +2884,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
                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);
                }
        }
@@ -4382,12 +4393,22 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
                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))
index a11a4f78f772732dc77b9a916539a57a7c3e961a..3f5ff12cbc0306c19f86d983f8cda55d55401a24 100644 (file)
@@ -52,6 +52,7 @@
 #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))
@@ -1256,7 +1257,8 @@ static int bgp_connect_check(struct thread *thread)
 
        /* 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;
        }
@@ -1267,8 +1269,8 @@ static int bgp_connect_check(struct thread *thread)
                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;
        }
@@ -1397,13 +1399,14 @@ int bgp_start(struct peer *peer)
        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);
index 3882ff8b5677e1caa91b091e828f5ad041354dbd..69c92e829c59ce6174a792ee08df89470cd6e6b6 100644 (file)
@@ -179,7 +179,7 @@ static int bgp_process_reads(struct thread *thread)
 
        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);
index 5158717b5d97ec2d6bec927b81175248fc25c7e3..004bdd90a24fa8f6355d02b9311a107bec7937e7 100644 (file)
@@ -143,6 +143,8 @@ void sighup(void)
 __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();
index 64d12cf6078540c26bbc42938d60a5bde3a10d6b..55365df2995ffa8580d4e23ab3aae15b831842ff 100644 (file)
@@ -569,7 +569,7 @@ leak_update(
                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;
index cfaa04a8c971d01df863feac01c11d0ad105f90b..997d708baf5d11eaebc15dbf7192ebd2fc33cce6 100644 (file)
@@ -225,6 +225,11 @@ struct bgp_info *bgp_info_lock(struct bgp_info *binfo)
 
 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--;
 
@@ -1336,6 +1341,8 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
        }
        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,
@@ -2336,10 +2343,18 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                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
@@ -2353,12 +2368,28 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
        /* 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);
        }
 
index 8ba7902a5f688557c7bae5572a3ffaeb84587370..cabd5b5cbd795027ae9a4797a2b2e17abce90d4f 100644 (file)
@@ -467,13 +467,12 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
                                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
                                 */
index fccda446faffc6664c6d2a1d4a166587e3a66477..b8c81232bb24147f22fa57e57455132f3370bc9f 100644 (file)
@@ -12587,6 +12587,8 @@ void bgp_vty_init(void)
        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);
index 93a509c219c30477f694311a0bd397429bc3639c..52a246387ee2d945dbf1406c5c797005a06b5db8 100644 (file)
@@ -1207,7 +1207,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
 
        /* 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;
@@ -1288,17 +1287,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                                }
                        }
 
-                       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) {
@@ -1323,19 +1316,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                        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) {
@@ -1376,6 +1361,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                        api_nh->label_num = 1;
                        api_nh->labels[0] = label;
                }
+               memcpy(&api_nh->rmac, &(mpinfo->attr->rmac),
+                      sizeof(struct ethaddr));
                valid_nh_count++;
        }
 
@@ -1500,7 +1487,6 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
        }
 
        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;
@@ -1913,7 +1899,7 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
 
        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);
index 32a1ea5a5fe7ef7c8cb64717862a3650ef1cf670..71707b6afa8ebae15eddf9651686d73451e496d5 100644 (file)
@@ -1174,6 +1174,11 @@ struct peer *peer_new(struct bgp *bgp)
                }
                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.  */
@@ -4072,6 +4077,35 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
                        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
@@ -7133,7 +7167,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
 
        /* 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)
@@ -7583,6 +7619,7 @@ void bgp_master_init(struct thread_master *master)
        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();
 
index d9ce77a55accbaa90ad48bb3b09156c9782a07bd..1ad6a5c9c8dd0b01dc58b79c5322a0f8a8d7f9ca 100644 (file)
@@ -144,6 +144,7 @@ struct bgp_master {
        /* dynamic mpls label allocation pool */
        struct labelpool labelpool;
 
+       bool terminating;       /* global flag that sigint terminate seen */
        QOBJ_FIELDS
 };
 DECLARE_QOBJ_TYPE(bgp_master)
index 7662f2a4e555c0b1385d4f5232b812f11e9cf3de..8b49295444aa6a30815a900d69cb3f4a28f3a54d 100755 (executable)
@@ -1913,8 +1913,13 @@ AC_MSG_RESULT($ac_cv_htonl_works)
 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
diff --git a/debianpkg/README.deb_build.md b/debianpkg/README.deb_build.md
deleted file mode 100644 (file)
index c90ca13..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-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`.
index 4720a3b92034143e83913a2ee9e525a14051f8df..d2218d00f9bd895f12436351e3d2166b5c78bd74 100644 (file)
@@ -1,6 +1,5 @@
 AUTHORS
 NEWS
 README
-REPORTING-BUGS
 doc/user/*.rst
 doc/figures/*.png
index 053842283e0ab778c2f13972d55543b387c509be..8fa057424a0e02e35e76d07ab382a5097e5fc9db 100644 (file)
@@ -14,7 +14,7 @@
 .NOTPARALLEL:
 
 SUBDIRS = manpages user
-AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir} doczdir=${abs_srcdir}
+AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir}
 
 MANPAGE_BUILDDIR = manpages/_build/man
 
index 0505537159fc49747ac0a2e52cb02e42403d152a..2e7d8573f180f02d77aa6f713fa9af14fb7ec305 100644 (file)
@@ -1,3 +1,3 @@
 /_templates
 /_build
-!/Makefile
+!/Makefile.in
diff --git a/doc/developer/Makefile b/doc/developer/Makefile
deleted file mode 100644 (file)
index 9807a75..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include ../frr-sphinx.mk
diff --git a/doc/developer/Makefile.in b/doc/developer/Makefile.in
new file mode 100644 (file)
index 0000000..76758f9
--- /dev/null
@@ -0,0 +1,8 @@
+# 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
index 1f3aec8d92064f61496244c7d93548e217d10e87..46db25a025e7d285fd94705eb2fdeeb89fbb9ba3 100644 (file)
@@ -14,7 +14,7 @@ Add packages:
 
 ::
 
-    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)
index 92fd1bb63a755ef97aeb72e8f5dc0f6614145f36..051611a65dfc212090c61a7da128a8405f539339 100644 (file)
@@ -1,3 +1,5 @@
+.. _building:
+
 ************
 Building FRR
 ************
index a3968b60ffd781f29a35aecd1f237ccd57a9642f..61253c4b2f4ef48c3b267d2ec196dcaeda5a6e05 100644 (file)
@@ -342,6 +342,14 @@ texinfo_documents = [
 # 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
@@ -357,5 +365,5 @@ def setup(app):
     #
     # 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']()
index 2c855ee880c62d0c8d6ecef85579af6ada3714ab..42192db637da57abe93d02541fef01029f1b5aac 100644 (file)
@@ -6,6 +6,7 @@ FRRouting Developer's Guide
 
    workflow
    building
+   packaging
    process-architecture
    library
    bgpd
diff --git a/doc/developer/packaging-debian.rst b/doc/developer/packaging-debian.rst
new file mode 100644 (file)
index 0000000..66339b6
--- /dev/null
@@ -0,0 +1,173 @@
+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.
+
diff --git a/doc/developer/packaging.rst b/doc/developer/packaging.rst
new file mode 100644 (file)
index 0000000..e9bb3a5
--- /dev/null
@@ -0,0 +1,8 @@
+*********
+Packaging
+*********
+
+.. toctree::
+   :maxdepth: 2
+
+   packaging-debian
index df4056760d4dbbc87cea06a0abc6079870d4521d..3e4c67d3740729f28b307dda80c36448162fb9d8 100644 (file)
@@ -10,6 +10,11 @@ SPHINXBUILD   ?= sphinx-build
 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)
@@ -23,9 +28,9 @@ endif
 # 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:
index 0505537159fc49747ac0a2e52cb02e42403d152a..2e7d8573f180f02d77aa6f713fa9af14fb7ec305 100644 (file)
@@ -1,3 +1,3 @@
 /_templates
 /_build
-!/Makefile
+!/Makefile.in
diff --git a/doc/manpages/Makefile b/doc/manpages/Makefile
deleted file mode 100644 (file)
index ebbbc31..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-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
diff --git a/doc/manpages/Makefile.in b/doc/manpages/Makefile.in
new file mode 100644 (file)
index 0000000..f28746c
--- /dev/null
@@ -0,0 +1,55 @@
+# 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
index 0505537159fc49747ac0a2e52cb02e42403d152a..2e7d8573f180f02d77aa6f713fa9af14fb7ec305 100644 (file)
@@ -1,3 +1,3 @@
 /_templates
 /_build
-!/Makefile
+!/Makefile.in
diff --git a/doc/user/Makefile b/doc/user/Makefile
deleted file mode 100644 (file)
index 223f8a6..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-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
diff --git a/doc/user/Makefile.in b/doc/user/Makefile.in
new file mode 100644 (file)
index 0000000..77c6abf
--- /dev/null
@@ -0,0 +1,62 @@
+# 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
diff --git a/doc/user/bugs.rst b/doc/user/bugs.rst
new file mode 100644 (file)
index 0000000..60ddf61
--- /dev/null
@@ -0,0 +1,67 @@
+.. _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`
+
index 886403b69d4d4d20e15843232164ea0a67535b6c..3fced110240aa379a5ba0780fa285c72ed555120 100644 (file)
@@ -342,6 +342,14 @@ texinfo_documents = [
 # 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
@@ -357,5 +365,5 @@ def setup(app):
     #
     # 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']()
index 9b9189dc30e945e1067e7ccb0e7504792202d2b6..f20ff8ec2b6ced8fe7a7fe1398047b17e705a11c 100644 (file)
@@ -27,6 +27,7 @@ FRRouting User Guide
    ripngd
    sharp
    vnc
+   bugs
    glossary
    appendix
 
index eec575cf3fd363d499631c081669ca7e60867951..aa48a3cd4f72ff5621e799a5c2f0e078bf1fc4ef 100644 (file)
@@ -57,7 +57,7 @@ against incoming packets.  If matched the nexthop-group or nexthop
 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
index 78e1959d363b4289dcbf5e6610a2feeba1a5273e..9d927359baabdadc9ee706cb6586bc28ccb0b055 100644 (file)
@@ -43,10 +43,9 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
    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:
 
@@ -246,8 +245,8 @@ Link Parameters 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
@@ -265,16 +264,16 @@ defines static prefix and 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
 
@@ -357,36 +356,38 @@ default) should the specified gateways not be reachable. E.g.:
    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
 
@@ -396,12 +397,12 @@ configuring a static route clicmd:`ip route NETWORK GATEWAY`.
    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
 
@@ -414,17 +415,17 @@ VRF.
 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:
@@ -433,29 +434,19 @@ 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
@@ -463,39 +454,35 @@ commands in relationship to VRF. Here is an extract of some of those commands:
    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
 
@@ -503,6 +490,8 @@ commands in relationship to VRF. Here is an extract of some of those commands:
    show ip table vrf r1-cust1 table 43
 
 
+.. _multicast-rib-commands:
+
 Multicast RIB Commands
 ======================
 
@@ -671,6 +660,8 @@ The FIB push interface comprises of a TCP connection between zebra and
 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
index 6250c7b6eb3414fae4e4659f87b51daa87d46054..69e301fcfabc511205799ede1f835b1174633968 100644 (file)
@@ -85,6 +85,7 @@ const char *node_names[] = {
        "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,
@@ -119,7 +120,6 @@ const char *node_names[] = {
        "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,
@@ -529,87 +529,103 @@ static int config_write_host(struct vty *vty)
        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");
@@ -2346,7 +2362,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
 
 #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;
 }
@@ -2372,6 +2388,16 @@ DEFUN (config_log_file,
                                    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]]",
@@ -2381,13 +2407,7 @@ DEFUN (no_config_log_file,
        "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;
 }
 
@@ -2399,6 +2419,9 @@ DEFUN (config_log_syslog,
        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))
index f18de3417cae810bbe0df47f87d7614cf025bd42..9ba53e0907441176c639024b7c73ccc06c51fda2 100644 (file)
@@ -85,6 +85,7 @@ enum node_type {
        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. */
@@ -119,7 +120,6 @@ enum node_type {
        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. */
index 33591cb4e7be23b9d335b431553913ac20a3bf09..7f2d06548bdf9bce095ffeef114007b24d6a9259 100644 (file)
@@ -102,4 +102,14 @@ static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6,
        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__ */
index cb39099fc21871971e82d2328f3c67627960b6d1..05bd907589ce4940273098b9c56c6750a2d7e57b 100644 (file)
@@ -975,8 +975,6 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
        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);
@@ -1061,6 +1059,11 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
                                           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));
                }
        }
 
@@ -1101,8 +1104,6 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
        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);
@@ -1212,6 +1213,11 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
                                           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));
                }
        }
 
index 8d26b7fe598b7919f1313f3dabca44047461c583..c5eaf9c0fde99ac7bcd87b692e0e92c0008a811b 100644 (file)
@@ -302,6 +302,8 @@ struct zapi_nexthop {
        /* MPLS labels for BGP-LU or Segment Routing */
        uint8_t label_num;
        mpls_label_t labels[MPLS_MAX_LABELS];
+
+       struct ethaddr rmac;
 };
 
 /*
@@ -342,8 +344,6 @@ struct zapi_route {
        vrf_id_t vrf_id;
 
        uint32_t tableid;
-
-       struct ethaddr rmac;
 };
 
 /* Zebra IPv4 route message API. */
index 52b954d6a1dfa07a08a5aaffe323441d2a836820..ea31d8c2ca2bbb8f50d6801d0a8750489a9b6c1b 100644 (file)
@@ -263,6 +263,9 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
        ospf_opaque_type9_lsa_init(oi);
 
        oi->ospf = ospf;
+
+       ospf_if_stream_set(oi);
+
        QOBJ_REG(oi, ospf_interface);
 
        if (IS_DEBUG_OSPF_EVENT)
@@ -322,6 +325,9 @@ void ospf_if_free(struct ospf_interface *oi)
 {
        ospf_if_down(oi);
 
+       if (oi->obuf)
+               ospf_fifo_free(oi->obuf);
+
        assert(oi->state == ISM_Down);
 
        ospf_opaque_type9_lsa_term(oi);
@@ -496,9 +502,8 @@ void ospf_if_stream_unset(struct ospf_interface *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);
 
@@ -781,7 +786,6 @@ int ospf_if_up(struct ospf_interface *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);
        }
 
index ba5c49ad5c7c1ec5ce5bda577fdb089769751099..b7d2b1a92890d253ccfc38c7d958fca7c918152f 100644 (file)
@@ -38,7 +38,7 @@
 #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"
@@ -54,7 +54,7 @@ DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-1000)",
        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"
index f83c08e611c1e58f647f414553a07e90af81df6b..8632a4fb2f0f7fa6c3bd2a54a8095a5ac09579e3 100644 (file)
@@ -534,7 +534,7 @@ rm -rf %{buildroot}
 %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 
index 7397089a7946c7a6b7168b612fd2950573711e27..01ba00776781efeb93c14a57ffd3c2018a7f521c 100644 (file)
@@ -1537,7 +1537,7 @@ DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
 }
 
 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"
@@ -1547,7 +1547,7 @@ DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
        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"
index 23f2f666a0593c3b0665714b44098e3d8dc0b857..a9a4dfe08f469f786a45af04438c95aa67c8c38f 100644 (file)
@@ -403,10 +403,10 @@ void connected_down(struct interface *ifp, struct connected *ifc)
         * 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];
index e28c189f8643647be215f4884c6e34675c80545c..7423e9237fe0cb56a24aea18d6ef07d7fa869fab 100644 (file)
@@ -1025,7 +1025,7 @@ static void if_netlink_check_ifp_instance_consistency(uint16_t cmd,
                                                     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
@@ -1037,29 +1037,42 @@ static void if_netlink_check_ifp_instance_consistency(uint16_t cmd,
        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
         */
index 6f59a2d399632d551a8c9f4fda8935877c80cc0e..7de18d683c1b2d4574f045bb989ec15094fb1a4f 100644 (file)
@@ -202,6 +202,7 @@ struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
        if (rn->info) {
                ifp = (struct interface *)rn->info;
                route_unlock_node(rn); /* get */
+               ifp->node = rn;
                return ifp;
        }
 
@@ -725,6 +726,9 @@ void if_delete_update(struct interface *ifp)
                return;
        }
 
+       if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
+               return;
+
        /* Mark interface as inactive */
        UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
 
@@ -1224,8 +1228,13 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
                                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;
index db4f19460a7f49dfcea82ccd18b4f1c1696e9eec..6b587dab3863fc9fb923033fcbbf2457d76d10a1 100644 (file)
@@ -463,7 +463,7 @@ int netlink_parse_info(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *,
        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,
index 8441eeac766e52436ae83a9207a1275bcd4b213b..dc075b9aff8890535ba73796d01717bf2af93ee6 100644 (file)
@@ -23,6 +23,7 @@
 
 #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,
index e60e05bcdf3c5eddf53ca2b259d595542d0d1f85..b85c4748c4c138046b5f7fa9443f04689f273951 100644 (file)
@@ -1043,7 +1043,7 @@ void rtm_read(struct rt_msghdr *rtm)
                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;
@@ -1058,7 +1058,7 @@ void rtm_read(struct rt_msghdr *rtm)
                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
@@ -1089,7 +1089,7 @@ void rtm_read(struct rt_msghdr *rtm)
                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
@@ -1106,7 +1106,7 @@ void rtm_read(struct rt_msghdr *rtm)
                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);
        }
 }
 
index 810ee33839a71bfe4af5631e3f6932aaae0fe0af..5a6565aec9cf145c0c6a1f814047a0dd920dcd55 100644 (file)
@@ -592,7 +592,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re)
 
        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;
 }
index d68bf787c0c387fb00f569e8d5d1f4d8ed2beb57..7b9e6d56a78f7e92e87b6039dd6a8105cfaef4f9 100644 (file)
@@ -313,8 +313,7 @@ extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
 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,
index a35dc9a177914850bc534a6e8dc7e9d97c82c39f..9510a0e12c2b452c02fa25b010d4647c65578b70 100644 (file)
@@ -613,12 +613,12 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                        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);
                }
        }
 
@@ -1233,14 +1233,6 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
                                "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;
        }
 }
 
index 2ff660b3f92b138d26639fa0587ec95cbff33302..6bd12391dbf223148baedb5735db572bfdf1cc60 100644 (file)
@@ -1382,7 +1382,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
                                               &(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;
@@ -1415,7 +1415,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
                                               &(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;
@@ -1522,7 +1522,7 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
 
        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) {
@@ -1724,7 +1724,7 @@ static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
        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:
@@ -2148,8 +2148,7 @@ static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
                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++;
 
index 07e81aa02008a112a36bbfeafa1aabd7309f62b4..d20f93f521a8bdf65513b6058aa64c013dea8dbc 100644 (file)
@@ -298,6 +298,9 @@ DEFUN (zebra_ptm_enable_if,
        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;
        }
@@ -317,9 +320,6 @@ DEFUN (zebra_ptm_enable_if,
                }
        }
 
-       if_data = ifp->info;
-       if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
-
        return CMD_SUCCESS;
 }
 
index 67832f2d3fe54ba157f6c205ccb6d8dcf00f29cc..7ec640164afcc57081cd5ba519379e93bd31d0d3 100644 (file)
@@ -2394,8 +2394,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
 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;
@@ -2569,7 +2568,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                                               &(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);
                        }
                }
index 2ae9ac5082969bb370ac7686ea69bdbb847db993..e6f80f92a7ddb08a9f17958ccb4b19e6b9029fef 100644 (file)
@@ -2798,12 +2798,14 @@ DEFUN (vrf_vni_mapping,
 
 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);
 
@@ -2812,7 +2814,11 @@ DEFUN (no_vrf_vni_mapping,
        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;
index 6e901a0457c6750487deb1a90da518fe4d35de4c..3278c86b992790b2d3fa47de18ef71cdf621cade 100644 (file)
@@ -3238,15 +3238,9 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
 
 
 /* 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)) {
 
@@ -3256,7 +3250,6 @@ static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
                /* del the rmac entry */
                zl3vni_rmac_del(zl3vni, zrmac);
        }
-       return 0;
 }
 
 /*
@@ -3394,15 +3387,9 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
 }
 
 /* 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)) {
 
@@ -3412,8 +3399,6 @@ static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
                /* delete the nh entry */
                zl3vni_nh_del(zl3vni, nh);
        }
-
-       return 0;
 }
 
 /* handle neigh update from kernel - the only thing of interest is to
@@ -3958,34 +3943,65 @@ void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
                                    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,
@@ -5143,7 +5159,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
                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++;
 
@@ -6516,6 +6532,12 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
                        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 */
@@ -6602,7 +6624,7 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
        }
 
        s = msg;
-       advertise = stream_getc(s);
+       STREAM_GETC(s, advertise);
        vni = stream_get3(s);
 
        zvni = zvni_lookup(vni);
@@ -6641,6 +6663,9 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
                zvni_advertise_subnet(zvni, vlan_if, 1);
        else
                zvni_advertise_subnet(zvni, vlan_if, 0);
+
+stream_failure:
+       return;
 }
 
 /*
@@ -6663,7 +6688,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
 
        s = msg;
        STREAM_GETC(s, advertise);
-       STREAM_GET(&vni, s, 3);
+       STREAM_GETL(s, vni);
 
        if (!vni) {
                if (IS_ZEBRA_DEBUG_VXLAN)
index 6153c7d7e32f31f45a2501250957405697d27e7f..34d115275102ddab077e868e43cbcbd4661e69b7 100644 (file)
@@ -160,7 +160,6 @@ extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
                                           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);