]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2101 from qlyoung/stream-fifo-safe
authorRafael Zalamena <rzalamena@users.noreply.github.com>
Tue, 15 May 2018 15:29:45 +0000 (12:29 -0300)
committerGitHub <noreply@github.com>
Tue, 15 May 2018 15:29:45 +0000 (12:29 -0300)
lib: add mt-safe variants for stream_fifo ops

110 files changed:
COMMUNITY.md [deleted file]
Makefile.am
README
README.NetBSD [deleted file]
REPORTING-BUGS [deleted file]
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_attr_evpn.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
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_routemap.c
bgpd/bgp_rpki.c
bgpd/bgp_snmp.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/backports/ubuntu14.04/debian/frr.postinst
debianpkg/frr-doc.docs
debianpkg/frr.postinst
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/manpages/index.rst
doc/user/.gitignore
doc/user/Makefile [deleted file]
doc/user/Makefile.in [new file with mode: 0644]
doc/user/basic.rst
doc/user/bugs.rst [new file with mode: 0644]
doc/user/conf.py
doc/user/index.rst
doc/user/installation.rst
doc/user/ospf6d.rst
doc/user/pbr.rst
doc/user/snmp.rst
doc/user/zebra.rst
isisd/isis_redist.c
lib/command.c
lib/command.h
lib/ipaddr.h
lib/prefix.c
lib/prefix.h
lib/zclient.c
lib/zclient.h
ospf6d/ospf6_abr.c
ospf6d/ospf6_area.h
ospf6d/ospf6_intra.c
ospf6d/ospf6_route.c
ospf6d/ospf6_top.c
ospfd/ospf_interface.c
pbrd/pbr_vty.c
pbrd/pbr_zebra.c
pimd/COMMANDS
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_igmp.c
pimd/pim_igmp.h
pimd/pim_igmp_mtrace.c
pimd/pim_igmp_stats.c [new file with mode: 0644]
pimd/pim_igmp_stats.h [new file with mode: 0644]
pimd/pim_igmpv2.c
pimd/pim_igmpv3.c
pimd/pim_instance.c
pimd/pim_msdp.c
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_zebra.c
pimd/subdir.am
redhat/frr.spec.in
tests/bgpd/test_mp_attr.c
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/label_manager.c
zebra/label_manager.h
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..7600ec54cca656f596639fc8c3a48df6b86ed6e1 100644 (file)
--- a/README
+++ b/README
@@ -5,11 +5,11 @@ 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.
+See the file COPYING for copying conditions.
 
 Public email discussion can be found at https://lists.frrouting.org/listinfo
 
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 b6e9ee3cb233e85730b8dde983e0b96c544982cc..276a7054e37ae4007de403875b4f9ca32d191bad 100644 (file)
@@ -2021,36 +2021,32 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
        return 0;
 }
 
-/* Prefix SID attribute
- * draft-ietf-idr-bgp-prefix-sid-05
+/*
+ * Read an individual SID value returning how much data we have read
+ * Returns 0 if there was an error that needs to be passed up the stack
  */
-static bgp_attr_parse_ret_t
-bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
-                   struct bgp_nlri *mp_update)
+static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
+                                             int32_t length,
+                                             struct bgp_attr_parser_args *args,
+                                             struct bgp_nlri *mp_update)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
-       int type;
-       int length;
        uint32_t label_index;
        struct in6_addr ipv6_sid;
        uint32_t srgb_base;
        uint32_t srgb_range;
        int srgb_count;
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
-
-       type = stream_getc(peer->curr);
-       length = stream_getw(peer->curr);
-
        if (type == BGP_PREFIX_SID_LABEL_INDEX) {
                if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
                        zlog_err(
-                               "Prefix SID label index length is %d instead of %d",
-                               length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                               args->total);
+                                "Prefix SID label index length is %d instead of %d",
+                                length,
+                                BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
                }
 
                /* Ignore flags and reserved */
@@ -2060,9 +2056,8 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
                /* Fetch the label index and see if it is valid. */
                label_index = stream_getl(peer->curr);
                if (label_index == BGP_INVALID_LABEL_INDEX)
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
-                               args->total);
+                       return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                                 args->total);
 
                /* Store label index; subsequently, we'll check on
                 * address-family */
@@ -2083,9 +2078,9 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
                if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
                        zlog_err("Prefix SID IPv6 length is %d instead of %d",
                                 length, BGP_PREFIX_SID_IPV6_LENGTH);
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                               args->total);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
                }
 
                /* Ignore reserved */
@@ -2122,6 +2117,47 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
        return BGP_ATTR_PARSE_PROCEED;
 }
 
+/* Prefix SID attribute
+ * draft-ietf-idr-bgp-prefix-sid-05
+ */
+bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+                   struct bgp_nlri *mp_update)
+{
+       struct peer *const peer = args->peer;
+       struct attr *const attr = args->attr;
+       bgp_attr_parse_ret_t ret;
+
+       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
+
+       while (tlength) {
+               int32_t type, length;
+
+               type = stream_getc(peer->curr);
+               length = stream_getw(peer->curr);
+
+               ret = bgp_attr_psid_sub(type, length, args, mp_update);
+
+               if (ret != BGP_ATTR_PARSE_PROCEED)
+                       return ret;
+               /*
+                * Subtract length + the T and the L
+                * since length is the Vector portion
+                */
+               tlength -= length + 3;
+
+               if (tlength < 0) {
+                       zlog_err("Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
+                                length);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
+               }
+       }
+
+       return BGP_ATTR_PARSE_PROCEED;
+}
+
 /* PMSI tunnel attribute (RFC 6514)
  * Basic validation checks done here.
  */
@@ -2498,7 +2534,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                                             startp);
                        break;
                case BGP_ATTR_PREFIX_SID:
-                       ret = bgp_attr_prefix_sid(&attr_args, mp_update);
+                       ret = bgp_attr_prefix_sid(length,
+                                                 &attr_args, mp_update);
                        break;
                case BGP_ATTR_PMSI_TUNNEL:
                        ret = bgp_attr_pmsi_tunnel(&attr_args);
index d59eae5f14749ad3d642edc7a1ce7c078bb8ff13..f17c2a68e4533780614a99586205adfb62667412 100644 (file)
@@ -308,6 +308,9 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                              struct bgp_nlri *);
 extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
                                struct bgp_nlri *);
+extern bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+                   struct bgp_nlri *mp_update);
 
 extern struct bgp_attr_encap_subtlv *
 encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
index d2a61b93fe2cacb5585c4bcc55c5bb0d50f628b2..14ff01ada54c09eb56466857557959c30f71d90d 100644 (file)
@@ -227,16 +227,18 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
        dst->family = AF_EVPN;
        p_evpn_p->route_type = evpn_type;
        if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
-               p_evpn_p->eth_tag = eth_tag;
-               p_evpn_p->ip_prefix_length = p2.prefixlen;
+               p_evpn_p->prefix_addr.eth_tag = eth_tag;
+               p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
                if (src->family == AF_INET) {
-                       SET_IPADDR_V4(&p_evpn_p->ip);
-                       memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
+                       SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
+                       memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
+                              &src->u.prefix4,
                               sizeof(struct in_addr));
                        dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
                } else {
-                       SET_IPADDR_V6(&p_evpn_p->ip);
-                       memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
+                       SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
+                       memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
+                              &src->u.prefix6,
                               sizeof(struct in6_addr));
                        dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
                }
index 49808e7cdd370436972a4869802a5bfd6448e02d..ee53beb191d2f553a5d17179fc53afb9c8a201e7 100644 (file)
@@ -510,15 +510,15 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
                bgp->vrf_id);
        stream_putl(s, vpn->vni);
-       stream_put(s, &p->prefix.mac.octet, ETH_ALEN); /* Mac Addr */
+       stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */
        /* IP address length and IP address, if any. */
-       if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+       if (is_evpn_prefix_ipaddr_none(p))
                stream_putl(s, 0);
        else {
-               ipa_len = IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BYTELEN
+               ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN
                                                      : IPV6_MAX_BYTELEN;
                stream_putl(s, ipa_len);
-               stream_put(s, &p->prefix.ip.ip.addr, ipa_len);
+               stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len);
        }
        stream_put_in_addr(s, &remote_vtep_ip);
 
@@ -532,8 +532,10 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                zlog_debug(
                        "Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s",
                        add ? "ADD" : "DEL", vpn->vni,
-                       prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)),
-                       ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)), flags,
+                       prefix_mac2str(&p->prefix.macip_addr.mac,
+                                      buf1, sizeof(buf1)),
+                       ipaddr2str(&p->prefix.macip_addr.ip,
+                                  buf3, sizeof(buf3)), flags,
                        inet_ntop(AF_INET, &remote_vtep_ip, buf2,
                                  sizeof(buf2)));
 
@@ -563,9 +565,9 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
                s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
                bgp->vrf_id);
        stream_putl(s, vpn->vni);
-       if (IS_EVPN_PREFIX_IPADDR_V4(p))
-               stream_put_in_addr(s, &p->prefix.ip.ipaddr_v4);
-       else if (IS_EVPN_PREFIX_IPADDR_V6(p)) {
+       if (is_evpn_prefix_ipaddr_v4(p))
+               stream_put_in_addr(s, &p->prefix.imet_addr.ip.ipaddr_v4);
+       else if (is_evpn_prefix_ipaddr_v6(p)) {
                zlog_err(
                        "Bad remote IP when trying to %s remote VTEP for VNI %u",
                        add ? "ADD" : "DEL", vpn->vni);
@@ -577,7 +579,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
        if (bgp_debug_zebra(NULL))
                zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
                           add ? "ADD" : "DEL", vpn->vni,
-                          inet_ntoa(p->prefix.ip.ipaddr_v4));
+                          inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
 
        return zclient_send_message(zclient);
 }
@@ -1293,8 +1295,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
         * these routes.
         */
        if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
-           (IS_EVPN_PREFIX_IPADDR_V4(p) ||
-            !IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) &&
+           (is_evpn_prefix_ipaddr_v4(p) ||
+            !IN6_IS_ADDR_LINKLOCAL(&p->prefix.macip_addr.ip.ipaddr_v6)) &&
            CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
                add_l3_ecomm = 1;
 
@@ -1539,8 +1541,8 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
                if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
                        continue;
 
-               if (IS_EVPN_PREFIX_IPADDR_V6(evp) &&
-                   IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6))
+               if (is_evpn_prefix_ipaddr_v6(evp) &&
+                   IN6_IS_ADDR_LINKLOCAL(&evp->prefix.macip_addr.ip.ipaddr_v6))
                        update_evpn_route_entry(bgp, vpn, afi, safi, rn,
                                                &attr_ip6_ll, 0, 1, &ri, 0);
                else {
@@ -1792,10 +1794,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        char buf1[PREFIX_STRLEN];
 
        memset(pp, 0, sizeof(struct prefix));
-       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-               ip_prefix_from_type2_prefix(evp, pp);
-       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
-               ip_prefix_from_type5_prefix(evp, pp);
+       ip_prefix_from_evpn_prefix(evp, pp);
 
        if (bgp_debug_zebra(NULL)) {
                zlog_debug(
@@ -1807,11 +1806,11 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
 
        /* Create (or fetch) route within the VRF. */
        /* NOTE: There is no RD here. */
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                afi = AFI_IP;
                safi = SAFI_UNICAST;
                rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                afi = AFI_IP6;
                safi = SAFI_UNICAST;
                rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
@@ -1820,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)
@@ -1842,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));
@@ -1914,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));
@@ -1970,10 +1972,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        char buf1[PREFIX_STRLEN];
 
        memset(pp, 0, sizeof(struct prefix));
-       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-               ip_prefix_from_type2_prefix(evp, pp);
-       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
-               ip_prefix_from_type5_prefix(evp, pp);
+       ip_prefix_from_evpn_prefix(evp, pp);
 
        if (bgp_debug_zebra(NULL)) {
                zlog_debug(
@@ -1985,7 +1984,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
 
        /* Locate route within the VRF. */
        /* NOTE: There is no RD here. */
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                afi = AFI_IP;
                safi = SAFI_UNICAST;
                rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
@@ -2232,8 +2231,8 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
                                continue;
 
                        /* if not a mac+ip route skip this route */
-                       if (!(IS_EVPN_PREFIX_IPADDR_V4(evp)
-                             || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+                       if (!(is_evpn_prefix_ipaddr_v4(evp)
+                             || is_evpn_prefix_ipaddr_v6(evp)))
                                continue;
 
                        for (ri = rn->info; ri; ri = ri->next) {
@@ -2423,8 +2422,8 @@ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi,
 
        /* if it is type-2 route and not a mac+ip route skip this route */
        if ((evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-           && !(IS_EVPN_PREFIX_IPADDR_V4(evp)
-                || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+           && !(is_evpn_prefix_ipaddr_v4(evp)
+                || is_evpn_prefix_ipaddr_v6(evp)))
                return 0;
 
        for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
@@ -2850,7 +2849,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Copy Ethernet Tag */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.macip_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Get the MAC Addr len */
@@ -2858,7 +2857,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Get the MAC Addr */
        if (macaddr_len == (ETH_ALEN * 8)) {
-               memcpy(&p.prefix.mac.octet, pfx, ETH_ALEN);
+               memcpy(&p.prefix.macip_addr.mac.octet, pfx, ETH_ALEN);
                pfx += ETH_ALEN;
        } else {
                zlog_err(
@@ -2880,10 +2879,10 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        if (ipaddr_len) {
                ipaddr_len /= 8; /* Convert to bytes. */
-               p.prefix.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
+               p.prefix.macip_addr.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
                                               ? IPADDR_V4
                                               : IPADDR_V6;
-               memcpy(&p.prefix.ip.ip.addr, pfx, ipaddr_len);
+               memcpy(&p.prefix.macip_addr.ip.ip.addr, pfx, ipaddr_len);
        }
        pfx += ipaddr_len;
 
@@ -2965,14 +2964,14 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Copy Ethernet Tag */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.imet_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Get the IP. */
        ipaddr_len = *pfx++;
        if (ipaddr_len == IPV4_MAX_BITLEN) {
-               p.prefix.ip.ipa_type = IPADDR_V4;
-               memcpy(&p.prefix.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
+               p.prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+               memcpy(&p.prefix.imet_addr.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
        } else {
                zlog_err(
                        "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
@@ -3039,7 +3038,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Fetch Ethernet Tag. */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.prefix_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Fetch IP prefix length. */
@@ -3050,21 +3049,21 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
                        peer->bgp->vrf_id, peer->host, ippfx_len);
                return -1;
        }
-       p.prefix.ip_prefix_length = ippfx_len;
+       p.prefix.prefix_addr.ip_prefix_length = ippfx_len;
 
        /* Determine IPv4 or IPv6 prefix */
        /* Since the address and GW are from the same family, this just becomes
         * a simple check on the total size.
         */
        if (psize == 34) {
-               SET_IPADDR_V4(&p.prefix.ip);
-               memcpy(&p.prefix.ip.ipaddr_v4, pfx, 4);
+               SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
+               memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
                pfx += 4;
                memcpy(&evpn.gw_ip.ipv4, pfx, 4);
                pfx += 4;
        } else {
-               SET_IPADDR_V6(&p.prefix.ip);
-               memcpy(&p.prefix.ip.ipaddr_v6, pfx, 16);
+               SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
+               memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx, 16);
                pfx += 16;
                memcpy(&evpn.gw_ip.ipv6, pfx, 16);
                pfx += 16;
@@ -3109,7 +3108,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
        /* len denites the total len of IP and GW-IP in the route
           IP and GW-IP have to be both ipv4 or ipv6
         */
-       if (IS_IPADDR_V4(&p_evpn_p->ip))
+       if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                len = 8; /* IP and GWIP are both ipv4 */
        else
                len = 32; /* IP and GWIP are both ipv6 */
@@ -3120,20 +3119,20 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
                stream_put(s, &(attr->evpn_overlay.eth_s_id), 10);
        else
                stream_put(s, &temp, 10);
-       stream_putl(s, p_evpn_p->eth_tag);
-       stream_putc(s, p_evpn_p->ip_prefix_length);
-       if (IS_IPADDR_V4(&p_evpn_p->ip))
-               stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr);
+       stream_putl(s, p_evpn_p->prefix_addr.eth_tag);
+       stream_putc(s, p_evpn_p->prefix_addr.ip_prefix_length);
+       if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
+               stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr);
        else
-               stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16);
+               stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
        if (attr) {
-               if (IS_IPADDR_V4(&p_evpn_p->ip))
+               if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                        stream_put_ipv4(s,
                                        attr->evpn_overlay.gw_ip.ipv4.s_addr);
                else
                        stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16);
        } else {
-               if (IS_IPADDR_V4(&p_evpn_p->ip))
+               if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                        stream_put_ipv4(s, 0);
                else
                        stream_put(s, &temp, 16);
@@ -3583,44 +3582,49 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
 
        if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
                json_object_int_add(json, "routeType", p->prefix.route_type);
-               json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+               json_object_int_add(json, "ethTag",
+                                   p->prefix.imet_addr.eth_tag);
                json_object_int_add(json, "ipLen",
-                                   IS_EVPN_PREFIX_IPADDR_V4(p)
+                                   is_evpn_prefix_ipaddr_v4(p)
                                            ? IPV4_MAX_BITLEN
                                            : IPV6_MAX_BITLEN);
                json_object_string_add(json, "ip",
-                                      inet_ntoa(p->prefix.ip.ipaddr_v4));
+                                      inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
        } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
-               if (IS_EVPN_PREFIX_IPADDR_NONE(p)) {
+               if (is_evpn_prefix_ipaddr_none(p)) {
                        json_object_int_add(json, "routeType",
                                            p->prefix.route_type);
-                       json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+                       json_object_int_add(json, "ethTag",
+                                           p->prefix.macip_addr.eth_tag);
                        json_object_int_add(json, "macLen", 8 * ETH_ALEN);
                        json_object_string_add(json, "mac",
-                                              prefix_mac2str(&p->prefix.mac,
+                                              prefix_mac2str(&p->prefix.macip_addr.mac,
                                                              buf1,
                                                              sizeof(buf1)));
                } else {
                        uint8_t family;
 
-                       family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
                                                             : AF_INET6;
 
                        json_object_int_add(json, "routeType",
                                            p->prefix.route_type);
-                       json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+                       json_object_int_add(json, "ethTag",
+                                           p->prefix.macip_addr.eth_tag);
                        json_object_int_add(json, "macLen", 8 * ETH_ALEN);
                        json_object_string_add(json, "mac",
-                                              prefix_mac2str(&p->prefix.mac,
+                                              prefix_mac2str(&p->prefix.macip_addr.mac,
                                                              buf1,
                                                              sizeof(buf1)));
                        json_object_int_add(json, "ipLen",
-                                           IS_EVPN_PREFIX_IPADDR_V4(p)
+                                           is_evpn_prefix_ipaddr_v4(p)
                                                    ? IPV4_MAX_BITLEN
                                                    : IPV6_MAX_BITLEN);
                        json_object_string_add(
                                json, "ip",
-                               inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+                               inet_ntop(family,
+                                         &p->prefix.macip_addr.ip.ip.addr,
+                                         buf2,
                                          PREFIX2STR_BUFFER));
                }
        } else {
@@ -3639,42 +3643,44 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
 
        if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
                snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
-                        p->prefix.eth_tag,
-                        IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BITLEN
+                        p->prefix.imet_addr.eth_tag,
+                        is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BITLEN
                                                     : IPV6_MAX_BITLEN,
-                        inet_ntoa(p->prefix.ip.ipaddr_v4));
+                        inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
        } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
-               if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+               if (is_evpn_prefix_ipaddr_none(p))
                        snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
                                 p->prefix.route_type,
-                                p->prefix.eth_tag,
+                                p->prefix.macip_addr.eth_tag,
                                 8 * ETH_ALEN,
-                                prefix_mac2str(&p->prefix.mac, buf1,
+                                prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
                                                sizeof(buf1)));
                else {
                        uint8_t family;
 
-                       family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
                                                             : AF_INET6;
                        snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
                                 p->prefix.route_type,
-                                p->prefix.eth_tag,
+                                p->prefix.macip_addr.eth_tag,
                                 8 * ETH_ALEN,
-                                prefix_mac2str(&p->prefix.mac, buf1,
+                                prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
                                                sizeof(buf1)),
                                 family == AF_INET ? IPV4_MAX_BITLEN
                                                   : IPV6_MAX_BITLEN,
-                                inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+                                inet_ntop(family,
+                                          &p->prefix.macip_addr.ip.ip.addr,
+                                          buf2,
                                           PREFIX2STR_BUFFER));
                }
        } else if (p->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
                snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
                         p->prefix.route_type,
-                        p->prefix.eth_tag,
-                        p->prefix.ip_prefix_length,
-                        IS_EVPN_PREFIX_IPADDR_V4(p)
-                                ? inet_ntoa(p->prefix.ip.ipaddr_v4)
-                                : inet6_ntoa(p->prefix.ip.ipaddr_v6));
+                        p->prefix.prefix_addr.eth_tag,
+                        p->prefix.prefix_addr.ip_prefix_length,
+                        is_evpn_prefix_ipaddr_v4(p)
+                                ? inet_ntoa(p->prefix.prefix_addr.ip.ipaddr_v4)
+                                : inet6_ntoa(p->prefix.prefix_addr.ip.ipaddr_v6));
        } else {
                /* For EVPN route types not supported yet. */
                snprintf(buf, len, "(unsupported route type %d)",
@@ -3703,9 +3709,9 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
 
        switch (evp->prefix.route_type) {
        case BGP_EVPN_MAC_IP_ROUTE:
-               if (IS_EVPN_PREFIX_IPADDR_V4(evp))
+               if (is_evpn_prefix_ipaddr_v4(evp))
                        ipa_len = IPV4_MAX_BYTELEN;
-               else if (IS_EVPN_PREFIX_IPADDR_V6(evp))
+               else if (is_evpn_prefix_ipaddr_v6(evp))
                        ipa_len = IPV6_MAX_BYTELEN;
                /* RD, ESI, EthTag, MAC+len, IP len, [IP], 1 VNI */
                len = 8 + 10 + 4 + 1 + 6 + 1 + ipa_len + 3;
@@ -3717,12 +3723,13 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
                        stream_put(s, &attr->evpn_overlay.eth_s_id, ESI_LEN);
                else
                        stream_put(s, 0, 10);
-               stream_putl(s, evp->prefix.eth_tag);        /* Ethernet Tag ID */
+               stream_putl(s, evp->prefix.macip_addr.eth_tag); /* Ethernet Tag ID */
                stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
-               stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */
-               stream_putc(s, 8 * ipa_len);             /* IP address Length */
-               if (ipa_len)                             /* IP */
-                       stream_put(s, &evp->prefix.ip.ip.addr, ipa_len);
+               stream_put(s, evp->prefix.macip_addr.mac.octet, 6); /* Mac Addr */
+               stream_putc(s, 8 * ipa_len); /* IP address Length */
+               if (ipa_len) /* IP */
+                       stream_put(s, &evp->prefix.macip_addr.ip.ip.addr,
+                                  ipa_len);
                /* 1st label is the L2 VNI */
                stream_put(s, label, BGP_LABEL_BYTES);
                /* Include 2nd label (L3 VNI) if advertising MAC+IP */
@@ -3733,10 +3740,10 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
        case BGP_EVPN_IMET_ROUTE:
                stream_putc(s, 17); // TODO: length - assumes IPv4 address
                stream_put(s, prd->val, 8);      /* RD */
-               stream_putl(s, evp->prefix.eth_tag);             /* Ethernet Tag ID */
+               stream_putl(s, evp->prefix.imet_addr.eth_tag); /* Ethernet Tag ID */
                stream_putc(s, IPV4_MAX_BITLEN); /* IP address Length - bits */
                /* Originating Router's IP Addr */
-               stream_put_in_addr(s, &evp->prefix.ip.ipaddr_v4);
+               stream_put_in_addr(s, &evp->prefix.imet_addr.ip.ipaddr_v4);
                break;
 
        case BGP_EVPN_IP_PREFIX_ROUTE:
@@ -4421,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 1eecb9ecf7e47372bc1f7efca12f5ebc24dd4a02..1efde3a71934c0c56312fd55b92dc9d7faeb9537 100644 (file)
@@ -272,15 +272,15 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
                                               struct prefix *ip)
 {
        memset(ip, 0, sizeof(struct prefix));
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                ip->family = AF_INET;
-               ip->prefixlen = evp->prefix.ip_prefix_length;
-               memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+               ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+               memcpy(&(ip->u.prefix4), &(evp->prefix.prefix_addr.ip.ip),
                       IPV4_MAX_BYTELEN);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                ip->family = AF_INET6;
-               ip->prefixlen = evp->prefix.ip_prefix_length;
-               memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+               ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+               memcpy(&(ip->u.prefix6), &(evp->prefix.prefix_addr.ip.ip),
                       IPV6_MAX_BYTELEN);
        }
 }
@@ -290,26 +290,36 @@ static inline int is_evpn_prefix_default(struct prefix *evp)
        if (evp->family != AF_EVPN)
                return 0;
 
-       return ((evp->u.prefix_evpn.ip_prefix_length  == 0) ? 1 : 0);
+       return ((evp->u.prefix_evpn.prefix_addr.ip_prefix_length  == 0) ?
+               1 : 0);
 }
 
 static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
                                               struct prefix *ip)
 {
        memset(ip, 0, sizeof(struct prefix));
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                ip->family = AF_INET;
                ip->prefixlen = IPV4_MAX_BITLEN;
-               memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+               memcpy(&(ip->u.prefix4), &(evp->prefix.macip_addr.ip.ip),
                       IPV4_MAX_BYTELEN);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                ip->family = AF_INET6;
                ip->prefixlen = IPV6_MAX_BITLEN;
-               memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+               memcpy(&(ip->u.prefix6), &(evp->prefix.macip_addr.ip.ip),
                       IPV6_MAX_BYTELEN);
        }
 }
 
+static inline void ip_prefix_from_evpn_prefix(struct prefix_evpn *evp,
+                                             struct prefix *ip)
+{
+       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
+               ip_prefix_from_type2_prefix(evp, ip);
+       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
+               ip_prefix_from_type5_prefix(evp, ip);
+}
+
 static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
                                           struct ethaddr *mac,
                                           struct ipaddr *ip)
@@ -318,10 +328,10 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
        p->family = AF_EVPN;
        p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
        p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
-       memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN);
-       p->prefix.ip.ipa_type = IPADDR_NONE;
+       memcpy(&p->prefix.macip_addr.mac.octet, mac->octet, ETH_ALEN);
+       p->prefix.macip_addr.ip.ipa_type = IPADDR_NONE;
        if (ip)
-               memcpy(&p->prefix.ip, ip, sizeof(*ip));
+               memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip));
 }
 
 static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
@@ -343,10 +353,10 @@ static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
        memset(evp, 0, sizeof(struct prefix_evpn));
        evp->family = AF_EVPN;
        evp->prefixlen = EVPN_TYPE_5_ROUTE_PREFIXLEN;
-       evp->prefix.ip_prefix_length = ip_prefix->prefixlen;
        evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
-       evp->prefix.ip.ipa_type = ip.ipa_type;
-       memcpy(&evp->prefix.ip, &ip, sizeof(struct ipaddr));
+       evp->prefix.prefix_addr.ip_prefix_length = ip_prefix->prefixlen;
+       evp->prefix.prefix_addr.ip.ipa_type = ip.ipa_type;
+       memcpy(&evp->prefix.prefix_addr.ip, &ip, sizeof(struct ipaddr));
 }
 
 static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
@@ -356,8 +366,8 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
        p->family = AF_EVPN;
        p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
        p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
-       p->prefix.ip.ipa_type = IPADDR_V4;
-       p->prefix.ip.ipaddr_v4 = originator_ip;
+       p->prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+       p->prefix.imet_addr.ip.ipaddr_v4 = originator_ip;
 }
 
 static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
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 4802a4caa54895cb89e026f7b0364ee54885d1e6..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);
        }
 
@@ -4626,7 +4657,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
                if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
                        struct bgp_encap_type_vxlan bet;
                        memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
-                       bet.vnid = p->u.prefix_evpn.eth_tag;
+                       bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
                        bgp_encap_type_vxlan_to_tlv(&bet, &attr);
                }
                if (bgp_static->router_mac) {
@@ -5101,10 +5132,10 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        if ((gw_ip.family == AF_INET
-                            && IS_EVPN_PREFIX_IPADDR_V6(
+                            && is_evpn_prefix_ipaddr_v6(
                                        (struct prefix_evpn *)&p))
                            || (gw_ip.family == AF_INET6
-                               && IS_EVPN_PREFIX_IPADDR_V4(
+                               && is_evpn_prefix_ipaddr_v4(
                                           (struct prefix_evpn *)&p))) {
                                vty_out(vty,
                                        "%% GatewayIp family differs with IP prefix\n");
@@ -7129,10 +7160,10 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
                vty_out(vty, "%s", str);
                XFREE(MTYPE_TMP, str);
 
-               if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
+               if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
-               } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
+               } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntop(AF_INET6,
                                          &(attr->evpn_overlay.gw_ip.ipv6), buf,
@@ -11398,14 +11429,15 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                        prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
                        if (p->u.prefix_evpn.route_type == 5) {
                                char local_buf[PREFIX_STRLEN];
-                               uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((
+                               uint8_t family = is_evpn_prefix_ipaddr_v4((
                                                         struct prefix_evpn *)p)
                                                         ? AF_INET
                                                         : AF_INET6;
-                               inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
+                               inet_ntop(family,
+                                         &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
                                          local_buf, PREFIX_STRLEN);
                                sprintf(buf, "%s/%u", local_buf,
-                                       p->u.prefix_evpn.ip_prefix_length);
+                                       p->u.prefix_evpn.prefix_addr.ip_prefix_length);
                        } else {
                                prefix2str(p, buf, sizeof(buf));
                        }
@@ -11417,7 +11449,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                                          sizeof(buf2));
                        vty_out(vty,
                                "  network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
-                               buf, rdbuf, p->u.prefix_evpn.eth_tag,
+                               buf, rdbuf,
+                               p->u.prefix_evpn.prefix_addr.eth_tag,
                                decode_label(&bgp_static->label), esi, buf2,
                                macrouter);
 
index 4cc889286ea031860b95f27ec1f04e1d458acafe..63400f7d313ce61acfb422128cc9e1e7aaeb0a52 100644 (file)
@@ -635,7 +635,7 @@ static route_map_result_t route_match_mac_address(void *rule,
 
                p.family = AF_ETHERNET;
                p.prefixlen = ETH_ALEN * 8;
-               p.u.prefix_eth = prefix->u.prefix_evpn.mac;
+               p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
 
                return (access_list_apply(alist, &p) == FILTER_DENY
                                ? RMAP_NOMATCH
index 75ba1609d03be0f6bbfbdfb0e0ff4e30af5d7726..a23d5d03c4a06599ea1ed08da7b70c2306340e9a 100644 (file)
@@ -25,6 +25,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/* If rtrlib compiled with ssh support, don`t fail build */
+#define LIBSSH_LEGACY_0_4
+
 #include <zebra.h>
 #include <pthread.h>
 #include <time.h>
index 2c7e4e04357b89ebc3098ef892a9c237d3414850..241b23a62db758d0320aa046ed9ca2c5e537faed 100644 (file)
@@ -356,20 +356,19 @@ static struct peer *peer_lookup_addr_ipv4(struct in_addr *src)
        struct bgp *bgp;
        struct peer *peer;
        struct listnode *node;
-       struct in_addr addr;
-       int ret;
 
        bgp = bgp_get_default();
        if (!bgp)
                return NULL;
 
        for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
-               ret = inet_pton(AF_INET, peer->host, &addr);
-               if (ret > 0) {
-                       if (IPV4_ADDR_SAME(&addr, src))
-                               return peer;
-               }
+               if (sockunion_family(&peer->su) != AF_INET)
+                       continue;
+
+               if (sockunion2ip(&peer->su) == src->s_addr)
+                       return peer;
        }
+
        return NULL;
 }
 
@@ -377,28 +376,31 @@ static struct peer *bgp_peer_lookup_next(struct in_addr *src)
 {
        struct bgp *bgp;
        struct peer *peer;
+       struct peer *next_peer = NULL;
        struct listnode *node;
-       struct in_addr *p;
-       union sockunion su;
-       int ret;
-
-       sockunion_init(&su);
 
        bgp = bgp_get_default();
        if (!bgp)
                return NULL;
 
        for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
-               ret = inet_pton(AF_INET, peer->host, &su.sin.sin_addr);
-               if (ret > 0) {
-                       p = &su.sin.sin_addr;
-
-                       if (ntohl(p->s_addr) > ntohl(src->s_addr)) {
-                               src->s_addr = p->s_addr;
-                               return peer;
-                       }
+               if (sockunion_family(&peer->su) != AF_INET)
+                       continue;
+               if (ntohl(sockunion2ip(&peer->su)) <= ntohl(src->s_addr))
+                       continue;
+
+               if (!next_peer
+                   || ntohl(sockunion2ip(&next_peer->su))
+                              > ntohl(sockunion2ip(&peer->su))) {
+                       next_peer = peer;
                }
        }
+
+       if (next_peer) {
+               src->s_addr = sockunion2ip(&next_peer->su);
+               return next_peer;
+       }
+
        return NULL;
 }
 
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 e1b050bf59cb2a563c05b18fb5b48ef9c8ca69be..b8c81232bb24147f22fa57e57455132f3370bc9f 100644 (file)
@@ -12153,7 +12153,6 @@ static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
 {
        struct bgp *bgp;
        struct peer *peer;
-       struct peer_group *group;
        struct listnode *lnbgp, *lnpeer;
 
        for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
@@ -12177,11 +12176,6 @@ static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
 
                        vector_set(comps, XSTRDUP(MTYPE_COMPLETION, name));
                }
-
-               if (token->type == VARIABLE_TKN)
-                       for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group))
-                               vector_set(comps, XSTRDUP(MTYPE_COMPLETION,
-                                                         group->name));
        }
 }
 
@@ -12191,9 +12185,27 @@ static const struct cmd_variable_handler bgp_var_neighbor[] = {
        {.varname = "peer", .completions = bgp_ac_neighbor},
        {.completions = NULL}};
 
+static void bgp_ac_peergroup(vector comps, struct cmd_token *token)
+{
+       struct bgp *bgp;
+       struct peer_group *group;
+       struct listnode *lnbgp, *lnpeer;
+
+       for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
+               for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group))
+                       vector_set(comps, XSTRDUP(MTYPE_COMPLETION,
+                                                 group->name));
+       }
+}
+
+static const struct cmd_variable_handler bgp_var_peergroup[] = {
+       {.tokenname = "PGNAME", .completions = bgp_ac_peergroup},
+       {.completions = NULL} };
+
 void bgp_vty_init(void)
 {
        cmd_variable_handler_register(bgp_var_neighbor);
+       cmd_variable_handler_register(bgp_var_peergroup);
 
        /* Install bgp top node. */
        install_node(&bgp_node, bgp_config_write);
@@ -12575,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..4a909d8cdc0247b5c0bb94fcc1b0eb4c248a5f4b 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);
@@ -2405,12 +2391,25 @@ static void bgp_zebra_process_label_chunk(
        uint8_t response_keep;
        uint32_t first;
        uint32_t last;
+       uint8_t proto;
+       unsigned short instance;
 
        s = zclient->ibuf;
+       STREAM_GETC(s, proto);
+       STREAM_GETW(s, instance);
        STREAM_GETC(s, response_keep);
        STREAM_GETL(s, first);
        STREAM_GETL(s, last);
 
+       if (zclient->redist_default != proto) {
+               zlog_err("Got LM msg with wrong proto %u", proto);
+               return;
+       }
+       if (zclient->instance != instance) {
+               zlog_err("Got LM msg with wrong instance %u", proto);
+               return;
+       }
+
        if (first > last ||
                first < MPLS_LABEL_UNRESERVED_MIN ||
                last > MPLS_LABEL_UNRESERVED_MAX) {
index a331fad5d4a242397050bf1438a2c3df959745d8..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
@@ -5947,39 +5981,63 @@ int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
        struct peer_group *group;
        struct listnode *node, *nnode;
 
+       /* apply configuration and set flags */
        SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
-       peer->pmax[afi][safi] = max;
-       peer->pmax_threshold[afi][safi] = threshold;
-       peer->pmax_restart[afi][safi] = restart;
        if (warning)
                SET_FLAG(peer->af_flags[afi][safi],
                         PEER_FLAG_MAX_PREFIX_WARNING);
        else
                UNSET_FLAG(peer->af_flags[afi][safi],
                           PEER_FLAG_MAX_PREFIX_WARNING);
+       peer->pmax[afi][safi] = max;
+       peer->pmax_threshold[afi][safi] = threshold;
+       peer->pmax_restart[afi][safi] = restart;
 
+       /* if handling a peer-group, apply to all children */
        if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
                group = peer->group;
                for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
-                       SET_FLAG(peer->af_flags[afi][safi],
-                                PEER_FLAG_MAX_PREFIX);
-                       peer->pmax[afi][safi] = max;
-                       peer->pmax_threshold[afi][safi] = threshold;
-                       peer->pmax_restart[afi][safi] = restart;
-                       if (warning)
+                       /*
+                        * If peer configuration is user-set, it overrides
+                        * peer-group config.
+                        */
+                       if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
+                                       PEER_FLAG_MAX_PREFIX)) {
                                SET_FLAG(peer->af_flags[afi][safi],
-                                        PEER_FLAG_MAX_PREFIX_WARNING);
-                       else
-                               UNSET_FLAG(peer->af_flags[afi][safi],
-                                          PEER_FLAG_MAX_PREFIX_WARNING);
+                                        PEER_FLAG_MAX_PREFIX);
+                               peer->pmax[afi][safi] = max;
+                               peer->pmax_threshold[afi][safi] = threshold;
+                               peer->pmax_restart[afi][safi] = restart;
+                       }
+                       if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
+                                       PEER_FLAG_MAX_PREFIX_WARNING)) {
+                               if (warning)
+                                       SET_FLAG(peer->af_flags[afi][safi],
+                                                PEER_FLAG_MAX_PREFIX_WARNING);
+                               else
+                                       UNSET_FLAG(
+                                               peer->af_flags[afi][safi],
+                                               PEER_FLAG_MAX_PREFIX_WARNING);
+                       }
 
                        if ((peer->status == Established)
                            && (peer->afc[afi][safi]))
                                bgp_maximum_prefix_overflow(peer, afi, safi, 1);
                }
        } else {
+               /* if not handling a peer-group, set the override flags */
                if ((peer->status == Established) && (peer->afc[afi][safi]))
                        bgp_maximum_prefix_overflow(peer, afi, safi, 1);
+
+               SET_FLAG(peer->af_flags_override[afi][safi],
+                        PEER_FLAG_MAX_PREFIX);
+
+               if (warning)
+                       SET_FLAG(peer->af_flags_override[afi][safi],
+                                PEER_FLAG_MAX_PREFIX_WARNING);
+               else
+                       UNSET_FLAG(peer->af_flags_override[afi][safi],
+                                  PEER_FLAG_MAX_PREFIX_WARNING);
        }
 
        return 0;
@@ -5990,49 +6048,49 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
        struct peer_group *group;
        struct listnode *node, *nnode;
 
-       /* apply peer-group config */
-       if (peer_group_active(peer)) {
-               if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
-                              PEER_FLAG_MAX_PREFIX))
-                       SET_FLAG(peer->af_flags[afi][safi],
-                                PEER_FLAG_MAX_PREFIX);
-               else
-                       UNSET_FLAG(peer->af_flags[afi][safi],
-                                  PEER_FLAG_MAX_PREFIX);
-
-               if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
-                              PEER_FLAG_MAX_PREFIX_WARNING))
-                       SET_FLAG(peer->af_flags[afi][safi],
-                                PEER_FLAG_MAX_PREFIX_WARNING);
-               else
-                       UNSET_FLAG(peer->af_flags[afi][safi],
-                                  PEER_FLAG_MAX_PREFIX_WARNING);
-
-               peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
-               peer->pmax_threshold[afi][safi] =
-                       peer->group->conf->pmax_threshold[afi][safi];
-               peer->pmax_restart[afi][safi] =
-                       peer->group->conf->pmax_restart[afi][safi];
-               return 0;
-       }
-
        UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
        UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
        peer->pmax[afi][safi] = 0;
        peer->pmax_threshold[afi][safi] = 0;
        peer->pmax_restart[afi][safi] = 0;
 
-       if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+       /* if not handling a peer-group, unset override flags */
+       if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+               UNSET_FLAG(peer->af_flags_override[afi][safi],
+                          PEER_FLAG_MAX_PREFIX);
+               UNSET_FLAG(peer->af_flags_override[afi][safi],
+                          PEER_FLAG_MAX_PREFIX_WARNING);
+               /* if peer is part of a peer-group, apply peer-group config */
+               if (peer_group_active(peer)) {
+                       peer->pmax[afi][safi] =
+                               peer->group->conf->pmax[afi][safi];
+                       peer->pmax_threshold[afi][safi] =
+                               peer->group->conf->pmax_threshold[afi][safi];
+                       peer->pmax_restart[afi][safi] =
+                               peer->group->conf->pmax_restart[afi][safi];
+               }
+
                return 0;
+       }
 
+       /*
+        * If this peer is a peer-group, set all peers in the group unless they
+        * have overrides for our config.
+        */
        group = peer->group;
        for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
-               UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
-               UNSET_FLAG(peer->af_flags[afi][safi],
-                          PEER_FLAG_MAX_PREFIX_WARNING);
-               peer->pmax[afi][safi] = 0;
-               peer->pmax_threshold[afi][safi] = 0;
-               peer->pmax_restart[afi][safi] = 0;
+               if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
+                               PEER_FLAG_MAX_PREFIX_WARNING))
+                       UNSET_FLAG(peer->af_flags[afi][safi],
+                                  PEER_FLAG_MAX_PREFIX_WARNING);
+               if (!CHECK_FLAG(peer->af_flags_override[afi][safi],
+                               PEER_FLAG_MAX_PREFIX)) {
+                       UNSET_FLAG(peer->af_flags[afi][safi],
+                                  PEER_FLAG_MAX_PREFIX);
+                       peer->pmax[afi][safi] = 0;
+                       peer->pmax_threshold[afi][safi] = 0;
+                       peer->pmax_restart[afi][safi] = 0;
+               }
        }
        return 0;
 }
@@ -7109,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)
@@ -7559,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 470fd108501f6ce1d79fc254b6633814439709e7..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)
@@ -836,7 +837,28 @@ struct peer {
        /* NSF mode (graceful restart) */
        uint8_t nsf[AFI_MAX][SAFI_MAX];
 
-       /* Per AF configuration flags. */
+       /* Peer Per AF flags */
+       /*
+        * Parallel array to af_flags that indicates whether each flag
+        * originates from a peer-group or if it is config that is specific to
+        * this individual peer. If a flag is set independent of the
+        * peer-group the same bit should be set here. If this peer is a
+        * peer-group, this memory region should be all zeros. The assumption
+        * is that the default state for all flags is unset.
+        *
+        * Notes:
+        * - if a flag for an individual peer is unset, the corresponding
+        *   override flag is unset and the peer is considered to be back in
+        *   sync with the peer-group.
+        * - This does *not* contain the flag values, rather it contains
+        *   whether the flag at the same position in af_flags is
+        *   *peer-specific*.
+        */
+       uint32_t af_flags_override[AFI_MAX][SAFI_MAX];
+       /*
+        * Effective flags, computed by applying peer-group flags and then
+        * overriding with individual flags
+        */
        uint32_t af_flags[AFI_MAX][SAFI_MAX];
 #define PEER_FLAG_SEND_COMMUNITY            (1 << 0) /* send-community */
 #define PEER_FLAG_SEND_EXT_COMMUNITY        (1 << 1) /* send-community ext. */
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 b1d463a33d96c5885e4ee35ca8d6b5e276967843..5a14e510cd7175d431070505125e7717ee167404 100644 (file)
@@ -18,7 +18,7 @@ chgrp ${frrvtygid} /etc/frr/vtysh*
 chmod 644 /etc/frr/*
 
 ENVIRONMENTFILE=/etc/environment
-if ! grep --quiet VTYSH_PAGER=/bin/cat ${ENVIRONMENTFILE}; then
+if ! egrep --quiet '^VTYSH_PAGER=' ${ENVIRONMENTFILE}; then
     echo "VTYSH_PAGER=/bin/cat"  >> ${ENVIRONMENTFILE}
 fi
 ##################################################
index 4720a3b92034143e83913a2ee9e525a14051f8df..d2218d00f9bd895f12436351e3d2166b5c78bd74 100644 (file)
@@ -1,6 +1,5 @@
 AUTHORS
 NEWS
 README
-REPORTING-BUGS
 doc/user/*.rst
 doc/figures/*.png
index 972f8c0500fb500fdd48004307f14e195b9e876b..32af741c989f5580cd678f1d83b6d4a315242f58 100644 (file)
@@ -19,7 +19,7 @@ chgrp ${frrvtygid} /etc/frr/vtysh*
 chmod 644 /etc/frr/*
 
 ENVIRONMENTFILE=/etc/environment
-if ! grep --quiet VTYSH_PAGER=/bin/cat ${ENVIRONMENTFILE}; then
+if ! egrep --quiet '^VTYSH_PAGER=' ${ENVIRONMENTFILE}; then
     echo "VTYSH_PAGER=/bin/cat"  >> ${ENVIRONMENTFILE}
 fi
 ##################################################
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 2f4b96bc1f4e488a9fddb23d34dcdca7b84e9b20..42192db637da57abe93d02541fef01029f1b5aac 100644 (file)
@@ -1,11 +1,12 @@
-Welcome to FRR's documentation!
-===============================
+FRRouting Developer's Guide
+===========================
 
 .. toctree::
    :maxdepth: 2
 
    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 ae622bb6995718cacebe3b24d0a5b206cd3eb8a3..6d3f3aae55aab6608025c09835c52dd3b77d7db8 100644 (file)
@@ -3,9 +3,6 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to FRR's documentation!
-===============================
-
 .. toctree::
    :maxdepth: 2
 
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
index f134133da44ff31dc83f382788ebc7d18338120b..b861444e88d964dd2871fbfe5345360eee7ac5b4 100644 (file)
@@ -55,18 +55,23 @@ Basic Config Commands
 
    Set hostname of the router.
 
-.. index:: password PASSWORD
+.. index::
+   single: no password PASSWORD
+   single: password PASSWORD
 
-.. clicmd:: password PASSWORD
+.. clicmd:: [no] password PASSWORD
 
-   Set password for vty interface. If there is no password, a vty won't
-   accept connections.
+   Set password for vty interface. The ``no`` form of the command deletes the
+   password. If there is no password, a vty won't accept connections.
 
-.. index:: enable password PASSWORD
+.. index::
+   single: no enable password PASSWORD
+   single: enable password PASSWORD
 
-.. clicmd:: enable password PASSWORD
+.. clicmd:: [no] enable password PASSWORD
 
-   Set enable password.
+   Set enable password. The ``no`` form of the command deletes the enable
+   password.
 
 .. index::
    single: no log trap [LEVEL]
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 28a85da8aac0c577635b1bb5a62fbac58fe024fa..f20ff8ec2b6ced8fe7a7fe1398047b17e705a11c 100644 (file)
@@ -1,5 +1,5 @@
-Welcome to FRR's documentation!
-===============================
+FRRouting User Guide
+====================
 
 .. toctree::
    :maxdepth: 2
@@ -27,6 +27,7 @@ Welcome to FRR's documentation!
    ripngd
    sharp
    vnc
+   bugs
    glossary
    appendix
 
index cd56cbcf500df8e50c59af2b78f9522e38f74b62..700a727d8f5ce14a95fafd81a4c5bd566eda72c6 100644 (file)
@@ -117,11 +117,6 @@ customize the build to include or exclude specific features and dependencies.
 
    Enable Traffic Engineering Extension for ISIS (RFC5305)
 
-.. option:: --enable-multipath <ARG>
-
-   Enable support for Equal Cost Multipath. `ARG` is the maximum number
-   of ECMP paths to allow, set to 0 to allow unlimited number of paths.
-
 .. option:: --enable-realms
 
    Enable the support of Linux Realms. Convert tag values from 1-255 into a
index 56f95e64b02f7c9f876d7265404b094d5c311a16..71bc04772021297ef35c843baeb4b2dca6870c60 100644 (file)
@@ -101,7 +101,7 @@ OSPF6 interface
 .. index:: ipv6 ospf6 hello-interval HELLOINTERVAL
 .. clicmd:: ipv6 ospf6 hello-interval HELLOINTERVAL
 
-   Sets interface's Hello Interval. Default 40
+   Sets interface's Hello Interval. Default 10
 
 .. index:: ipv6 ospf6 dead-interval DEADINTERVAL
 .. clicmd:: ipv6 ospf6 dead-interval DEADINTERVAL
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 1a24d56cb76ef01d22d1c801036883ab7ff907c6..38918ff250f34e967777574940016087e36141cd 100644 (file)
@@ -43,6 +43,9 @@ master SNMP agent (snmpd) and each of the FRR daemons must be configured. In
 In each of the FRR daemons, ``agentx`` command will enable AgentX support.
 
 :file:`/etc/snmp/snmpd.conf`:
+
+::
+
    #
    # example access restrictions setup
    #
@@ -113,6 +116,9 @@ using the password "frr_ospfd". For testing it is recommending to take exactly
 the below snmpd.conf as wrong access restrictions can be hard to debug.
 
 :file:`/etc/snmp/snmpd.conf`:
+
+::
+
    #
    # example access restrictions setup
    #
@@ -126,6 +132,9 @@ the below snmpd.conf as wrong access restrictions can be hard to debug.
    smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
 
 :file:`/etc/frr/ospf`:
+
+::
+
    ! ... the rest of ospfd.conf has been omitted for clarity ...
    !
    smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
index f1d194b1a395664641eef8ae456f2f4281218539..9d927359baabdadc9ee706cb6586bc28ccb0b055 100644 (file)
@@ -38,7 +38,14 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
    force zebra to limit the maximum ecmp allowed to X.  This number
    is bounded by what you compiled FRR with as the maximum number.
 
-.. program:: configure
+.. option:: -n, --vrfwnetns
+
+   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.
+
+   .. seealso:: :ref:`vrf`
 
 .. _interface-commands:
 
@@ -54,6 +61,10 @@ Standard Commands
 
 .. clicmd:: interface IFNAME
 
+.. index:: interface IFNAME vrf VRF
+
+.. clicmd:: interface IFNAME vrf VRF
+
 .. index:: shutdown
 
 .. clicmd:: shutdown
@@ -234,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
@@ -253,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
 
@@ -345,16 +356,139 @@ 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.
+
+.. _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.
+
+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.
+
+This conceptual view introduces the *Default VRF* case. If the user does not
+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
+
+   # case without VRF
+   configure terminal
+    ip route 10.0.0.0 255.255.255.0 10.0.0.2
+   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 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
+
+   # case with VRF
+   configure terminal
+   vrf r1-cust1
+    ip route 10.0.0.0 255.255.255.0 10.0.0.2
+   exit-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
+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.
+
+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:
+
+.. index:: vrf VRF
+.. 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.
+
+.. 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 NEXTHOPVRF
+.. clicmd:: ip route NETWORK NETMASK GATEWAY NEXTHOPVRF
+
+   This command is based on VRF configuration mode or in configuration mode. If
+   on configuration mode, this applies to default VRF. Otherwise, this command
+   applies to the VRF of the vrf configuration mode. This command is used to
+   configure a vrf route leak across 2 VRFs. This command is only available
+   when *Zebra* is launched without :option:`-n` option.
+
+.. 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*.
+
+.. 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``.
+
+.. 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 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
+
+   ip route 10.0.0.0 255.255.255.0 10.0.0.2 vrf r1-cust1 table 43
+   show ip table vrf r1-cust1 table 43
+
 
 .. _multicast-rib-commands:
 
@@ -526,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 9c61512df4f71c6e318387a76b06ee7dc96d2232..e903dc8c7fea87d8dfd97c676b7c57e480f7f8d9 100644 (file)
@@ -184,8 +184,7 @@ static void isis_redist_update_ext_reach(struct isis_area *area, int level,
        route_map_result_t map_ret;
 
        memcpy(&area_info, info, sizeof(area_info));
-       if (redist->metric != 0xffffffff)
-               area_info.metric = redist->metric;
+       area_info.metric = redist->metric;
 
        if (redist->map_name) {
                map_ret =
@@ -540,7 +539,7 @@ DEFUN (isis_redistribute,
        int afi;
        int type;
        int level;
-       unsigned long metric;
+       unsigned long metric = 0;
        const char *routemap = NULL;
 
        family = str2family(argv[idx_afi]->text);
@@ -567,9 +566,6 @@ DEFUN (isis_redistribute,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       metric = 0xffffffff;
-       routemap = NULL;
-
        if (argc > idx_metric_rmap + 1) {
                if (argv[idx_metric_rmap + 1]->arg[0] == '\0')
                        return CMD_WARNING_CONFIG_FAILED;
@@ -651,7 +647,7 @@ DEFUN (isis_default_originate,
        int family;
        int originate_type = DEFAULT_ORIGINATE;
        int level;
-       unsigned long metric = 0xffffffff;
+       unsigned long metric = 0;
        const char *routemap = NULL;
 
        family = str2family(argv[idx_afi]->text);
@@ -748,7 +744,7 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
                                continue;
                        vty_out(vty, " redistribute %s %s level-%d", family_str,
                                zebra_route_string(type), level);
-                       if (redist->metric != 0xffffffff)
+                       if (redist->metric)
                                vty_out(vty, " metric %u", redist->metric);
                        if (redist->map_name)
                                vty_out(vty, " route-map %s", redist->map_name);
@@ -766,7 +762,7 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
                        family_str, level);
                if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
                        vty_out(vty, " always");
-               if (redist->metric != 0xffffffff)
+               if (redist->metric)
                        vty_out(vty, " metric %u", redist->metric);
                if (redist->map_name)
                        vty_out(vty, " route-map %s", redist->map_name);
index 2744061b5a1ed3b4a52fa67040cade0047d1dd58..0fa6bde3345262ecff39774896ae304c6775a793 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");
@@ -1895,7 +1911,7 @@ DEFUN (config_no_hostname,
 DEFUN (config_password,
        password_cmd,
        "password [(8-8)] WORD",
-       "Assign the terminal connection password\n"
+       "Modify the terminal connection password\n"
        "Specifies a HIDDEN password will follow\n"
        "The password string\n")
 {
@@ -1934,6 +1950,34 @@ DEFUN (config_password,
        return CMD_SUCCESS;
 }
 
+/* VTY interface password delete. */
+DEFUN (no_config_password,
+       no_password_cmd,
+       "no password",
+       NO_STR
+       "Modify the terminal connection password\n")
+{
+       bool warned = false;
+
+       if (host.password) {
+               if (!vty_shell_serv(vty)) {
+                       vty_out(vty, NO_PASSWD_CMD_WARNING);
+                       warned = true;
+               }
+               XFREE(MTYPE_HOST, host.password);
+       }
+       host.password = NULL;
+
+       if (host.password_encrypt) {
+               if (!warned && !vty_shell_serv(vty))
+                       vty_out(vty, NO_PASSWD_CMD_WARNING);
+               XFREE(MTYPE_HOST, host.password_encrypt);
+       }
+       host.password_encrypt = NULL;
+
+       return CMD_SUCCESS;
+}
+
 /* VTY enable password set. */
 DEFUN (config_enable_password,
        enable_password_cmd,
@@ -1995,12 +2039,22 @@ DEFUN (no_config_enable_password,
        "Modify enable password parameters\n"
        "Assign the privileged level password\n")
 {
-       if (host.enable)
+       bool warned = false;
+
+       if (host.enable) {
+               if (!vty_shell_serv(vty)) {
+                       vty_out(vty, NO_PASSWD_CMD_WARNING);
+                       warned = true;
+               }
                XFREE(MTYPE_HOST, host.enable);
+       }
        host.enable = NULL;
 
-       if (host.enable_encrypt)
+       if (host.enable_encrypt) {
+               if (!warned && !vty_shell_serv(vty))
+                       vty_out(vty, NO_PASSWD_CMD_WARNING);
                XFREE(MTYPE_HOST, host.enable_encrypt);
+       }
        host.enable_encrypt = NULL;
 
        return CMD_SUCCESS;
@@ -2304,7 +2358,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;
 }
@@ -2330,6 +2384,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]]",
@@ -2339,13 +2403,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;
 }
 
@@ -2357,6 +2415,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))
@@ -2710,6 +2771,7 @@ void cmd_init(int terminal)
 
        if (terminal > 0) {
                install_element(CONFIG_NODE, &password_cmd);
+               install_element(CONFIG_NODE, &no_password_cmd);
                install_element(CONFIG_NODE, &enable_password_cmd);
                install_element(CONFIG_NODE, &no_enable_password_cmd);
 
index f18de3417cae810bbe0df47f87d7614cf025bd42..8d9c39b0ea05ec9805d656e69b7e0b1b7c86c624 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. */
@@ -376,6 +376,10 @@ struct cmd_node {
 
 #define CONF_BACKUP_EXT ".sav"
 
+/* Command warnings. */
+#define NO_PASSWD_CMD_WARNING                                                  \
+       "Please be aware that removing the password is a security risk and you should think twice about this command.\n"
+
 /* IPv4 only machine should not accept IPv6 address for peer's IP
    address.  So we replace VTY command string like below. */
 #define NEIGHBOR_ADDR_STR  "Neighbor address\nIPv6 address\n"
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 b38dd94589bd988ee6767431e2941a930bfaea4a..05af190e9daa5b59db64d3015142a4933dd3685b 100644 (file)
@@ -1206,54 +1206,104 @@ int str2prefix(const char *str, struct prefix *p)
        return 0;
 }
 
-static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
+static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
+                                     int size)
+{
+       snprintf(str, size, "Unsupported EVPN prefix");
+       return str;
+}
+
+static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
+                                       int size)
 {
        uint8_t family;
        char buf[PREFIX2STR_BUFFER];
        char buf2[ETHER_ADDR_STRLEN];
 
-       if (p->u.prefix_evpn.route_type == 2) {
-               if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p))
-                       snprintf(str, size, "[%d]:[%s]/%d",
-                                p->u.prefix_evpn.route_type,
-                                prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
-                                               sizeof(buf2)),
-                                p->prefixlen);
-               else {
-                       family = IS_EVPN_PREFIX_IPADDR_V4(
-                                        (struct prefix_evpn *)p)
-                                        ? AF_INET
-                                        : AF_INET6;
-                       snprintf(str, size, "[%d]:[%s]:[%s]/%d",
-                                p->u.prefix_evpn.route_type,
-                                prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
-                                               sizeof(buf2)),
-                                inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
-                                          buf, PREFIX2STR_BUFFER),
-                                p->prefixlen);
-               }
-       } else if (p->u.prefix_evpn.route_type == 3) {
-               family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
-                                ? AF_INET
-                                : AF_INET6;
-               snprintf(str, size, "[%d]:[%s]/%d", p->u.prefix_evpn.route_type,
-                        inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
-                                  PREFIX2STR_BUFFER),
+       if (is_evpn_prefix_ipaddr_none(p))
+               snprintf(str, size, "[%d]:[%s]/%d",
+                        p->prefix.route_type,
+                        prefix_mac2str(&p->prefix.macip_addr.mac,
+                                       buf2, sizeof(buf2)),
                         p->prefixlen);
-       } else if (p->u.prefix_evpn.route_type == 5) {
-               family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
+       else {
+               family = is_evpn_prefix_ipaddr_v4(p)
                                 ? AF_INET
                                 : AF_INET6;
-               snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
-                        p->u.prefix_evpn.route_type, p->u.prefix_evpn.eth_tag,
-                        inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
-                                  PREFIX2STR_BUFFER),
-                        p->u.prefix_evpn.ip_prefix_length, p->prefixlen);
-       } else {
-               sprintf(str, "Unsupported EVPN route type %d",
-                       p->u.prefix_evpn.route_type);
+               snprintf(str, size, "[%d]:[%s]:[%s]/%d",
+                        p->prefix.route_type,
+                        prefix_mac2str(&p->prefix.macip_addr.mac,
+                                       buf2, sizeof(buf2)),
+                        inet_ntop(family,
+                                  &p->prefix.macip_addr.ip.ip.addr,
+                                  buf, PREFIX2STR_BUFFER),
+                        p->prefixlen);
        }
+       return str;
+}
+
+static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
+                                      int size)
+{
+       uint8_t family;
+       char buf[PREFIX2STR_BUFFER];
+
+       family = is_evpn_prefix_ipaddr_v4(p)
+                        ? AF_INET
+                        : AF_INET6;
+       snprintf(str, size, "[%d]:[%s]/%d", p->prefix.route_type,
+                inet_ntop(family,
+                          &p->prefix.imet_addr.ip.ip.addr, buf,
+                          PREFIX2STR_BUFFER),
+                p->prefixlen);
+       return str;
+}
 
+static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
+                                    int size)
+{
+       snprintf(str, size, "Unsupported EVPN prefix");
+       return str;
+}
+
+static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
+                                        int size)
+{
+       uint8_t family;
+       char buf[PREFIX2STR_BUFFER];
+
+       family = is_evpn_prefix_ipaddr_v4(p)
+                        ? AF_INET
+                        : AF_INET6;
+       snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
+                p->prefix.route_type,
+                p->prefix.prefix_addr.eth_tag,
+                inet_ntop(family,
+                          &p->prefix.prefix_addr.ip.ip.addr, buf,
+                          PREFIX2STR_BUFFER),
+                p->prefix.prefix_addr.ip_prefix_length,
+                p->prefixlen);
+       return str;
+}
+
+static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
+                                 int size)
+{
+       switch (p->prefix.route_type) {
+       case 1:
+               return prefixevpn_ead2str(p, str, size);
+       case 2:
+               return prefixevpn_macip2str(p, str, size);
+       case 3:
+               return prefixevpn_imet2str(p, str, size);
+       case 4:
+               return prefixevpn_es2str(p, str, size);
+       case 5:
+               return prefixevpn_prefix2str(p, str, size);
+       default:
+               snprintf(str, size, "Unsupported EVPN prefix");
+               break;
+       }
        return str;
 }
 
@@ -1277,7 +1327,7 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
                break;
 
        case AF_EVPN:
-               prefixevpn2str(p, str, size);
+               prefixevpn2str((const struct prefix_evpn *)p, str, size);
                break;
 
        case AF_FLOWSPEC:
index f01c85b811918079ce603ff8492166d39930d2f6..ab3c05ae744a740ee19ed9fc3c0d54466f519a47 100644 (file)
@@ -56,26 +56,56 @@ struct ethaddr {
 #define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8)
 #define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8)
 
-/* EVPN address (RFC 7432) */
-struct evpn_addr {
-       uint8_t route_type;
+typedef struct esi_t_ {
+       uint8_t val[10];
+} esi_t;
+
+struct evpn_ead_addr {
+       esi_t esi;
+       uint32_t eth_tag;
+};
+
+struct evpn_macip_addr {
+       uint32_t eth_tag;
        uint8_t ip_prefix_length;
        struct ethaddr mac;
+       struct ipaddr ip;
+};
+
+struct evpn_imet_addr {
        uint32_t eth_tag;
+       uint8_t ip_prefix_length;
        struct ipaddr ip;
-#if 0
-  union
-  {
-    uint8_t addr;
-    struct in_addr v4_addr;
-    struct in6_addr v6_addr;
-  } ip;
-#endif
 };
 
-#define IS_EVPN_PREFIX_IPADDR_NONE(evp)  IS_IPADDR_NONE(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V4(evp)    IS_IPADDR_V4(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V6(evp)    IS_IPADDR_V6(&(evp)->prefix.ip)
+struct evpn_es_addr {
+       esi_t esi;
+       uint8_t ip_prefix_length;
+       struct ipaddr ip;
+};
+
+struct evpn_prefix_addr {
+       uint32_t eth_tag;
+       uint8_t ip_prefix_length;
+       struct ipaddr ip;
+};
+
+/* EVPN address (RFC 7432) */
+struct evpn_addr {
+       uint8_t route_type;
+       union {
+               struct evpn_ead_addr _ead_addr;
+               struct evpn_macip_addr _macip_addr;
+               struct evpn_imet_addr _imet_addr;
+               struct evpn_es_addr _es_addr;
+               struct evpn_prefix_addr _prefix_addr;
+       } u;
+#define ead_addr u._ead_addr
+#define macip_addr u._macip_addr
+#define imet_addr u._imet_addr
+#define es_addr u._es_addr
+#define prefix_addr u._prefix_addr
+};
 
 /*
  * A struct prefix contains an address family, a prefix length, and an
@@ -177,6 +207,39 @@ struct prefix_evpn {
        struct evpn_addr prefix __attribute__((aligned(8)));
 };
 
+static inline int is_evpn_prefix_ipaddr_none(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_NONE(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_NONE(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_NONE(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v4(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_V4(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_V4(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_V4(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_V6(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_V6(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_V6(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
 /* Prefix for a generic pointer */
 struct prefix_ptr {
        uint8_t family;
index cb39099fc21871971e82d2328f3c67627960b6d1..0f7cf350dbad7e1a5a3c4b3a659a8c6c10825664 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));
                }
        }
 
@@ -1231,9 +1237,8 @@ stream_failure:
        return 0;
 }
 
-static void zapi_encode_prefix(struct stream *s,
-                             struct prefix *p,
-                             uint8_t family)
+static void zapi_encode_prefix(struct stream *s, struct prefix *p,
+                              uint8_t family)
 {
        struct prefix any;
 
@@ -1248,8 +1253,7 @@ static void zapi_encode_prefix(struct stream *s,
        stream_put(s, &p->u.prefix, prefix_blen(p));
 }
 
-int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
-                        struct pbr_rule *zrule)
+int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
 {
        stream_reset(s);
        zclient_create_header(s, cmd, zrule->vrf_id);
@@ -1265,11 +1269,11 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
 
        zapi_encode_prefix(s, &(zrule->filter.src_ip),
                           zrule->filter.src_ip.family);
-       stream_putw(s, zrule->filter.src_port);  /* src port */
+       stream_putw(s, zrule->filter.src_port); /* src port */
        zapi_encode_prefix(s, &(zrule->filter.dst_ip),
                           zrule->filter.src_ip.family);
-       stream_putw(s, zrule->filter.dst_port);  /* dst port */
-       stream_putw(s, zrule->filter.fwmark);    /* fwmark */
+       stream_putw(s, zrule->filter.dst_port); /* dst port */
+       stream_putw(s, zrule->filter.fwmark);   /* fwmark */
 
        stream_putl(s, zrule->action.table);
        stream_putl(s, zrule->ifindex);
@@ -1317,8 +1321,8 @@ bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
        STREAM_GETL(s, ifi);
 
        if (zclient_debug)
-               zlog_debug("%s: %u %u %u %u", __PRETTY_FUNCTION__,
-                          seq, prio, uni, ifi);
+               zlog_debug("%s: %u %u %u %u", __PRETTY_FUNCTION__, seq, prio,
+                          uni, ifi);
        *seqno = seq;
        *priority = prio;
        *unique = uni;
@@ -1330,9 +1334,8 @@ stream_failure:
        return false;
 }
 
-bool zapi_ipset_notify_decode(struct stream *s,
-                             uint32_t *unique,
-                            enum zapi_ipset_notify_owner *note)
+bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
+                             enum zapi_ipset_notify_owner *note)
 {
        uint32_t uni;
 
@@ -1350,10 +1353,9 @@ stream_failure:
        return false;
 }
 
-bool zapi_ipset_entry_notify_decode(struct stream *s,
-               uint32_t *unique,
-               char *ipset_name,
-               enum zapi_ipset_entry_notify_owner *note)
+bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
+                                   char *ipset_name,
+                                   enum zapi_ipset_entry_notify_owner *note)
 {
        uint32_t uni;
 
@@ -1361,8 +1363,7 @@ bool zapi_ipset_entry_notify_decode(struct stream *s,
 
        STREAM_GETL(s, uni);
 
-       STREAM_GET(ipset_name, s,
-                  ZEBRA_IPSET_NAME_SIZE);
+       STREAM_GET(ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
 
        if (zclient_debug)
                zlog_debug("%s: %u", __PRETTY_FUNCTION__, uni);
@@ -1408,7 +1409,7 @@ struct nexthop *nexthop_from_zapi_nexthop(struct zapi_nexthop *znh)
         */
        if (znh->label_num) {
                nexthop_add_labels(n, ZEBRA_LSP_NONE, znh->label_num,
-                       znh->labels);
+                                  znh->labels);
        }
 
        return n;
@@ -1469,7 +1470,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
                if (nhr->nexthops[i].label_num)
                        STREAM_GET(&nhr->nexthops[i].labels[0], s,
                                   nhr->nexthops[i].label_num
-                                  * sizeof(mpls_label_t));
+                                          * sizeof(mpls_label_t));
        }
 
        return true;
@@ -1892,8 +1893,9 @@ struct connected *zebra_interface_address_read(int type, struct stream *s,
                                zlog_warn(
                                        "warning: interface %s address %s "
                                        "with peer flag set, but no peer address!",
-                                       ifp->name, prefix2str(ifc->address, buf,
-                                                             sizeof buf));
+                                       ifp->name,
+                                       prefix2str(ifc->address, buf,
+                                                  sizeof buf));
                                UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                        }
                }
@@ -2059,7 +2061,7 @@ int lm_label_manager_connect(struct zclient *zclient)
        uint8_t result;
 
        if (zclient_debug)
-               zlog_debug("Connecting to Label Manager");
+               zlog_debug("Connecting to Label Manager (LM)");
 
        if (zclient->sock < 0)
                return -1;
@@ -2079,33 +2081,45 @@ int lm_label_manager_connect(struct zclient *zclient)
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               zlog_err("Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               zlog_err("Zclient sock closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (zclient_debug)
-               zlog_debug("%s: Label manager connect request (%d bytes) sent",
-                          __func__, ret);
+               zlog_debug("LM connect request sent (%d bytes)", ret);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_LABEL_MANAGER_CONNECT)
            != 0)
                return -1;
 
-       /* result */
        s = zclient->ibuf;
+
+       /* read instance and proto */
+       uint8_t proto = stream_getc(s);
+       uint16_t instance = stream_getw(s);
+
+       /* sanity */
+       if (proto != zclient->redist_default)
+               zlog_err(
+                       "Wrong proto (%u) in LM connect response. Should be %u",
+                       proto, zclient->redist_default);
+       if (instance != zclient->instance)
+               zlog_err(
+                       "Wrong instId (%u) in LM connect response. Should be %u",
+                       instance, zclient->instance);
+
+       /* result code */
        result = stream_getc(s);
        if (zclient_debug)
-               zlog_debug(
-                       "%s: Label Manager connect response received, result %u",
-                       __func__, result);
+               zlog_debug("LM connect-response received, result %u", result);
 
        return (int)result;
 }
@@ -2118,10 +2132,8 @@ int lm_label_manager_connect(struct zclient *zclient)
  * @param chunk_size Amount of labels requested
  * @result 0 on success, -1 otherwise
  */
-int zclient_send_get_label_chunk(
-       struct zclient  *zclient,
-       uint8_t         keep,
-       uint32_t        chunk_size)
+int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
+                                uint32_t chunk_size)
 {
        struct stream *s;
 
@@ -2135,6 +2147,10 @@ int zclient_send_get_label_chunk(
        stream_reset(s);
 
        zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        stream_putc(s, keep);
        stream_putl(s, chunk_size);
 
@@ -2174,6 +2190,10 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
        s = zclient->obuf;
        stream_reset(s);
        zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        /* keep */
        stream_putc(s, keep);
        /* chunk size */
@@ -2183,26 +2203,39 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               zlog_err("Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               zlog_err("Zclient sock closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (zclient_debug)
-               zlog_debug("%s: Label chunk request (%d bytes) sent", __func__,
-                          ret);
+               zlog_debug("Label chunk request (%d bytes) sent", ret);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0)
                return -1;
 
+       /* parse response */
        s = zclient->ibuf;
+
+       /* read proto and instance */
+       uint8_t proto = stream_getc(s);
+       uint16_t instance = stream_getw(s);
+
+       /* sanities */
+       if (proto != zclient->redist_default)
+               zlog_err("Wrong proto (%u) in get chunk response. Should be %u",
+                        proto, zclient->redist_default);
+       if (instance != zclient->instance)
+               zlog_err("Wrong instId (%u) in get chunk response Should be %u",
+                        instance, zclient->instance);
+
        /* keep */
        response_keep = stream_getc(s);
        /* start and end labels */
@@ -2212,19 +2245,18 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
        /* not owning this response */
        if (keep != response_keep) {
                zlog_err(
-                       "%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
-                       __func__, *start, *end, keep, response_keep);
+                       "Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
+                       *start, *end, keep, response_keep);
        }
        /* sanity */
        if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
            || *end > MPLS_LABEL_UNRESERVED_MAX) {
-               zlog_err("%s: Invalid Label chunk: %u - %u", __func__, *start,
-                        *end);
+               zlog_err("Invalid Label chunk: %u - %u", *start, *end);
                return -1;
        }
 
        if (zclient_debug)
-               zlog_debug("Label Chunk assign: %u - %u (%u) ", *start, *end,
+               zlog_debug("Label Chunk assign: %u - %u (%u)", *start, *end,
                           response_keep);
 
        return 0;
@@ -2245,7 +2277,7 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
        struct stream *s;
 
        if (zclient_debug)
-               zlog_debug("Releasing Label Chunk");
+               zlog_debug("Releasing Label Chunk %u - %u", start, end);
 
        if (zclient->sock < 0)
                return -1;
@@ -2255,6 +2287,10 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
        stream_reset(s);
        zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT);
 
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        /* start */
        stream_putl(s, start);
        /* end */
@@ -2265,13 +2301,13 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               zlog_err("Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               zlog_err("Zclient sock connection closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
@@ -2319,8 +2355,7 @@ int tm_table_manager_connect(struct zclient *zclient)
                return -1;
 
        if (zclient_debug)
-               zlog_debug("%s: Table manager connect request sent",
-                          __func__);
+               zlog_debug("%s: Table manager connect request sent", __func__);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_TABLE_MANAGER_CONNECT)
@@ -2783,7 +2818,7 @@ static int zclient_read(struct thread *thread)
        case ZEBRA_GET_LABEL_CHUNK:
                if (zclient->label_chunk)
                        (*zclient->label_chunk)(command, zclient, length,
-                                                     vrf_id);
+                                               vrf_id);
                break;
        case ZEBRA_IPSET_NOTIFY_OWNER:
                if (zclient->ipset_notify_owner)
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 b895b5ad8b5ff034f0a45dd10e8504a503894792..bc1ce621ae60f29f6ff1925e36f78eba809cc809 100644 (file)
@@ -684,7 +684,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
 {
        struct prefix prefix, abr_prefix;
        struct ospf6_route_table *table = NULL;
-       struct ospf6_route *range, *route, *old = NULL;
+       struct ospf6_route *range, *route, *old = NULL, *old_route;
        struct ospf6_route *abr_entry;
        uint8_t type = 0;
        char options[3] = {0, 0, 0};
@@ -695,14 +695,15 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        int is_debug = 0;
        struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
        struct ospf6_inter_router_lsa *router_lsa = NULL;
-       struct ospf6_path *path;
+       bool old_entry_updated = false;
 
        memset(&prefix, 0, sizeof(prefix));
 
        if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
                if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
                        is_debug++;
-                       zlog_debug("Examin %s in area %s", lsa->name, oa->name);
+                       zlog_debug("%s: Examin %s in area %s",
+                                  __PRETTY_FUNCTION__, lsa->name, oa->name);
                }
 
                prefix_lsa =
@@ -720,7 +721,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
                if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
                        is_debug++;
-                       zlog_debug("Examin %s in area %s", lsa->name, oa->name);
+                       zlog_debug("%s: Examin %s in area %s",
+                                  __PRETTY_FUNCTION__, lsa->name, oa->name);
                }
 
                router_lsa =
@@ -768,7 +770,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        }
        if (OSPF6_LSA_IS_MAXAGE(lsa)) {
                if (is_debug)
-                       zlog_debug("LSA is MaxAge, ignore");
+                       zlog_debug("%s: LSA %s is MaxAge, ignore",
+                                  __PRETTY_FUNCTION__, lsa->name);
                if (old)
                        ospf6_route_remove(old, table);
                return;
@@ -845,9 +848,24 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
            || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
            || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
                if (is_debug)
-                       zlog_debug("ABR router entry does not exist, ignore");
-               if (old)
-                       ospf6_route_remove(old, table);
+                       zlog_debug("%s: ABR router entry does not exist, ignore",
+                                  __PRETTY_FUNCTION__);
+               if (old) {
+                       if (old->type == OSPF6_DEST_TYPE_ROUTER &&
+                           oa->intra_brouter_calc) {
+                               if (is_debug)
+                                       zlog_debug(
+                                                  "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
+                                                  __PRETTY_FUNCTION__, buf,
+                                                  (void *)old);
+                       } else {
+                               if (is_debug)
+                                       zlog_debug("%s: remove old entry: %s %p ",
+                                                  __PRETTY_FUNCTION__, buf,
+                                                  (void *)old);
+                               ospf6_route_remove(old, table);
+                       }
+               }
                return;
        }
 
@@ -902,11 +920,11 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        route->path.type = OSPF6_PATH_TYPE_INTER;
        route->path.cost = abr_entry->path.cost + cost;
 
-       ospf6_route_copy_nexthops(route, abr_entry);
-
-       path = ospf6_path_dup(&route->path);
-       ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
-       listnode_add_sort(route->paths, path);
+       /* Inter abr_entry is same as brouter.
+        * Avoid duplicate nexthops to brouter and its
+        * learnt route. i.e. use merge nexthops.
+        */
+       ospf6_route_merge_nexthops(route, abr_entry);
 
        /* (7) If the routes are identical, copy the next hops over to existing
           route. ospf6's route table implementation will otherwise string both
@@ -915,11 +933,28 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        */
        old = ospf6_route_lookup(&prefix, table);
 
-       if (old && (ospf6_route_cmp(route, old) == 0)) {
-               ospf6_route_merge_nexthops(old, route);
+       for (old_route = old; old_route; old_route = old_route->next) {
+               if (!ospf6_route_is_same(old_route, route) ||
+                       (old_route->type != route->type) ||
+                       (old_route->path.type != route->path.type))
+                       continue;
+
+               if ((ospf6_route_cmp(route, old_route) != 0)) {
+                       if (is_debug) {
+                               prefix2str(&prefix, buf, sizeof(buf));
+                               zlog_debug("%s: old %p %s cost %u new route cost %u are not same",
+                                          __PRETTY_FUNCTION__,
+                                          (void *)old_route, buf,
+                                          old_route->path.cost,
+                                          route->path.cost);
+                       }
+                       continue;
+               }
 
+               old_entry_updated = true;
+               ospf6_route_merge_nexthops(old, route);
                if (is_debug)
-                       zlog_debug("%s: Update route: %s old cost %u new cost %u nh count %u",
+                       zlog_debug("%s: Update route: %s old cost %u new cost %u nh %u",
                                   __PRETTY_FUNCTION__,
                                   buf, old->path.cost, route->path.cost,
                                   listcount(route->nh_list));
@@ -930,9 +965,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
 
                /* Delete new route */
                ospf6_route_delete(route);
-       } else {
+               break;
+       }
+
+       if (old_entry_updated == false) {
                if (is_debug)
-                       zlog_debug("%s: Install route: %s cost %u nh count %u",
+                       zlog_debug("%s: Install route: %s cost %u nh %u",
                                   __PRETTY_FUNCTION__, buf, route->path.cost,
                                   listcount(route->nh_list));
                /* ospf6_ia_add_nw_route (table, &prefix, route); */
index eaf3e5c6de73659f1384002b8e178c06fbc02757..ba497a168e987b9ed3d60a897e0cc6b67e30482b 100644 (file)
@@ -50,6 +50,9 @@ struct ospf6_area {
        /* Area type */
        int no_summary;
 
+       /* Brouter traversal protection */
+       int intra_brouter_calc;
+
        /* OSPF interface list */
        struct list *if_list;
 
index b234b10d511a8fb6f21166c46ef6805e1a775e8c..26e6deadae89636490f744d00f41cebc79f054cc 100644 (file)
@@ -2047,8 +2047,10 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
        uint32_t brouter_id;
        char brouter_name[16];
 
-       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id))
-               zlog_info("border-router calculation for area %s", oa->name);
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+           IS_OSPF6_DEBUG_ROUTE(MEMORY))
+               zlog_info("%s: border-router calculation for area %s",
+                         __PRETTY_FUNCTION__, oa->name);
 
        hook_add = oa->ospf6->brouter_table->hook_add;
        hook_remove = oa->ospf6->brouter_table->hook_remove;
@@ -2114,6 +2116,7 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
 
        for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
             brouter = nbrouter) {
+
                /*
                 * brouter may have been "deleted" in the last loop iteration.
                 * If this is the case there is still 1 final refcount lock
@@ -2122,6 +2125,8 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
                 * skip processing the deleted route.
                 */
                if (brouter->lock == 1) {
+                       if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
+                               ospf6_brouter_debug_print(brouter);
                        nbrouter = ospf6_route_next(brouter);
                        continue;
                } else {
@@ -2173,8 +2178,14 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
                                       brouter_id)
                            || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
                                       oa->area_id))
-                               zlog_info("brouter %s disappears via area %s",
-                                         brouter_name, oa->name);
+                               zlog_info("%s: brouter %s disappears via area %s",
+                                         __PRETTY_FUNCTION__, brouter_name,
+                                         oa->name);
+                       /* This is used to protect nbrouter from removed from
+                        * the table. For an example, ospf6_abr_examin_summary,
+                        * removes brouters which are marked for remove.
+                        */
+                       oa->intra_brouter_calc = 1;
                        ospf6_route_remove(brouter, oa->ospf6->brouter_table);
                        brouter = NULL;
                } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
@@ -2184,8 +2195,9 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
                                       brouter_id)
                            || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
                                       oa->area_id))
-                               zlog_info("brouter %s appears via area %s",
-                                         brouter_name, oa->name);
+                               zlog_info("%s: brouter %s appears via area %s",
+                                         __PRETTY_FUNCTION__, brouter_name,
+                                         oa->name);
 
                        /* newly added */
                        if (hook_add)
@@ -2205,11 +2217,14 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
                        UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
                        UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
                }
+               /* Reset for nbrouter */
+               oa->intra_brouter_calc = 0;
        }
 
-       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id))
-               zlog_info("border-router calculation for area %s: done",
-                         oa->name);
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+           IS_OSPF6_DEBUG_ROUTE(MEMORY))
+               zlog_info("%s: border-router calculation for area %s: done",
+                         __PRETTY_FUNCTION__, oa->name);
 }
 
 struct ospf6_lsa_handler router_handler = {.lh_type = OSPF6_LSTYPE_ROUTER,
index 39272b370153b899f87c290480e0caf4c9fe0387..15d8eb6cf2584362867eb9f26be6bcbd7e40e9d8 100644 (file)
@@ -925,10 +925,11 @@ struct ospf6_route *ospf6_route_next(struct ospf6_route *route)
        struct ospf6_route *next = route->next;
 
        if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
-               zlog_info("%s %p: route next: %p<-[%p]->%p",
+               zlog_info("%s %p: route next: %p<-[%p]->%p , route ref count %u",
                          ospf6_route_table_name(route->table),
                          (void *)route->table, (void *)route->prev,
-                         (void *)route, (void *)route->next);
+                         (void *)route, (void *)route->next,
+                         route->lock);
 
        ospf6_route_unlock(route);
        if (next)
index e4a48915264c7d5286cc91a4501b32d0c7859c8d..7bf099fbbfb2dd33bc0c008e41ca7a6812e12e88 100644 (file)
@@ -97,7 +97,8 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route)
 
 static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
 {
-       if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+       if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
+           IS_OSPF6_DEBUG_BROUTER) {
                uint32_t brouter_id;
                char brouter_name[16];
 
@@ -116,15 +117,17 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
 
 static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
 {
-       if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+       if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
+           IS_OSPF6_DEBUG_BROUTER) {
                uint32_t brouter_id;
                char brouter_name[16];
 
                brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
                inet_ntop(AF_INET, &brouter_id, brouter_name,
                          sizeof(brouter_name));
-               zlog_debug("%s: brouter %s del with nh count %u",
-                          __PRETTY_FUNCTION__, brouter_name,
+               zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
+                          __PRETTY_FUNCTION__, (void *)route, brouter_name,
+                          route->path.origin.adv_router,
                           listcount(route->nh_list));
        }
        route->flag |= OSPF6_ROUTE_REMOVE;
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 bc7dd2083213916b08d483741e65bec8795d5357..cdacfad4b4db1a96339bda5d183e384dd99de4a8 100644 (file)
@@ -479,6 +479,7 @@ static void pbr_encode_pbr_map_sequence(struct stream *s,
        stream_putw(s, 0);  /* src port */
        pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family);
        stream_putw(s, 0);  /* dst port */
+       stream_putl(s, 0);  /* fwmark */
        if (pbrms->nhgrp_name)
                stream_putl(s, pbr_nht_get_table(pbrms->nhgrp_name));
        else if (pbrms->nhg)
index 6f2e020bd87f5c146d5c5574fa55790f7671cbcd..141ec62aeb0ab979b40fb38e0176c0976369d912 100644 (file)
@@ -24,6 +24,7 @@ verification commands:
        show ip igmp groups retransmissions     IGMP group retransmission
        show ip igmp sources                    IGMP sources information
        show ip igmp sources retransmissions    IGMP source retransmission
+       show ip igmp statistics                 IGMP statistics information
        show ip pim address                     PIM interface address
        show ip pim assert                      PIM interface assert
        show ip pim assert-internal             PIM interface internal assert state
index 35514a85dac0b79149c735bb21e98b67824d5da2..81191eb96c6371064fbf3b2d9b7b1a202cac8df1 100644 (file)
@@ -1294,6 +1294,76 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
        }
 }
 
+static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
+                                const char *ifname, uint8_t uj)
+{
+       struct interface *ifp;
+       struct igmp_stats rx_stats;
+
+       igmp_stats_init(&rx_stats);
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp;
+               struct listnode *sock_node;
+               struct igmp_sock *igmp;
+
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (ifname && strcmp(ifname, ifp->name))
+                       continue;
+
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
+                                         igmp)) {
+                       igmp_stats_add(&rx_stats, &igmp->rx_stats);
+               }
+       }
+       if (uj) {
+               json_object *json = NULL;
+               json_object *json_row = NULL;
+
+               json = json_object_new_object();
+               json_row = json_object_new_object();
+
+               json_object_string_add(json_row, "name", ifname ? ifname :
+                                      "global");
+               json_object_int_add(json_row, "queryV1", rx_stats.query_v1);
+               json_object_int_add(json_row, "queryV2", rx_stats.query_v2);
+               json_object_int_add(json_row, "queryV3", rx_stats.query_v3);
+               json_object_int_add(json_row, "leaveV3", rx_stats.leave_v2);
+               json_object_int_add(json_row, "reportV1", rx_stats.report_v1);
+               json_object_int_add(json_row, "reportV2", rx_stats.report_v2);
+               json_object_int_add(json_row, "reportV3", rx_stats.report_v3);
+               json_object_int_add(json_row, "mtraceResponse",
+                                   rx_stats.mtrace_rsp);
+               json_object_int_add(json_row, "mtraceRequest",
+                                   rx_stats.mtrace_req);
+               json_object_int_add(json_row, "unsupported",
+                                   rx_stats.unsupported);
+               json_object_object_add(json, ifname ? ifname : "global",
+                                      json_row);
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       } else {
+               vty_out(vty, "IGMP RX statistics\n");
+               vty_out(vty, "Interface       : %s\n",
+                       ifname ? ifname : "global");
+               vty_out(vty, "V1 query        : %u\n", rx_stats.query_v1);
+               vty_out(vty, "V2 query        : %u\n", rx_stats.query_v2);
+               vty_out(vty, "V3 query        : %u\n", rx_stats.query_v3);
+               vty_out(vty, "V2 leave        : %u\n", rx_stats.leave_v2);
+               vty_out(vty, "V1 report       : %u\n", rx_stats.report_v1);
+               vty_out(vty, "V2 report       : %u\n", rx_stats.report_v2);
+               vty_out(vty, "V3 report       : %u\n", rx_stats.report_v3);
+               vty_out(vty, "mtrace response : %u\n", rx_stats.mtrace_rsp);
+               vty_out(vty, "mtrace request  : %u\n", rx_stats.mtrace_req);
+               vty_out(vty, "unsupported     : %u\n", rx_stats.unsupported);
+       }
+}
+
 static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                uint8_t uj)
 {
@@ -3527,6 +3597,33 @@ DEFUN (show_ip_igmp_sources_retransmissions,
        return CMD_SUCCESS;
 }
 
+DEFUN (show_ip_igmp_statistics,
+       show_ip_igmp_statistics_cmd,
+       "show ip igmp [vrf NAME] statistics [interface WORD] [json]",
+       SHOW_STR
+       IP_STR
+       IGMP_STR
+       VRF_CMD_HELP_STR
+       "IGMP statistics\n"
+       "interface\n"
+       "IGMP interface\n"
+       JSON_STR)
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       uint8_t uj = use_json(argc, argv);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       if (argv_find(argv, argc, "WORD", &idx))
+               igmp_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
+       else
+               igmp_show_statistics(vrf->info, vty, NULL, uj);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (show_ip_pim_assert,
        show_ip_pim_assert_cmd,
        "show ip pim [vrf NAME] assert",
@@ -8644,6 +8741,7 @@ void pim_cmd_init(void)
        install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
        install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
        install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
+       install_element(VIEW_NODE, &show_ip_igmp_statistics_cmd);
        install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
        install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
        install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
index 5996a3ac96b9f1f75745f85afa66f20f8be5882e..5c4d99ad4d0099e032d4eeb1f2556a0849dbcdcd 100644 (file)
@@ -62,7 +62,16 @@ void pim_if_init(struct pim_instance *pim)
 
 void pim_if_terminate(struct pim_instance *pim)
 {
-       // Nothing to do at this moment
+       struct interface *ifp;
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               pim_if_delete(ifp);
+       }
        return;
 }
 
index bb56379c14a2ec0585f8ffcc08470b7e6cf3dd04..5e6b0f10cf5e47a048bbca58aca0c09cabe47820 100644 (file)
@@ -124,11 +124,6 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
        }
 }
 
-void pim_ifchannel_free(struct pim_ifchannel *ch)
-{
-       XFREE(MTYPE_PIM_IFCHANNEL, ch);
-}
-
 void pim_ifchannel_delete(struct pim_ifchannel *ch)
 {
        struct pim_interface *pim_ifp;
@@ -198,7 +193,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                zlog_debug("%s: ifchannel entry %s is deleted ",
                           __PRETTY_FUNCTION__, ch->sg_str);
 
-       pim_ifchannel_free(ch);
+       XFREE(MTYPE_PIM_IFCHANNEL, ch);
 }
 
 void pim_ifchannel_delete_all(struct interface *ifp)
index 0af9ebf0beb925ca2b37563d020cca9f1327b02e..b9d4d291d854d910aeb96bd58048878b1786050d 100644 (file)
@@ -114,7 +114,6 @@ RB_HEAD(pim_ifchannel_rb, pim_ifchannel);
 RB_PROTOTYPE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb,
             pim_ifchannel_compare);
 
-void pim_ifchannel_free(struct pim_ifchannel *ch);
 void pim_ifchannel_delete(struct pim_ifchannel *ch);
 void pim_ifchannel_delete_all(struct interface *ifp);
 void pim_ifchannel_membership_clear(struct interface *ifp);
index 5e1aecc3a389cec533e495815141c8bd545ad022..c980f5fcbaa718187ca1682201b8b4314423c9ba 100644 (file)
@@ -303,6 +303,21 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       switch (query_version) {
+       case 1:
+               igmp->rx_stats.query_v1++;
+               break;
+       case 2:
+               igmp->rx_stats.query_v2++;
+               break;
+       case 3:
+               igmp->rx_stats.query_v3++;
+               break;
+       default:
+               igmp->rx_stats.unsupported++;
+       }
+
        /*
         * RFC 3376 defines some guidelines on operating in backwards
         * compatibility with older versions of IGMP but there are some gaps in
@@ -400,6 +415,9 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.report_v1++;
+
        if (PIM_DEBUG_IGMP_TRACE) {
                zlog_warn("%s %s: FIXME WRITEME", __FILE__,
                          __PRETTY_FUNCTION__);
@@ -524,6 +542,9 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
 
        zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type);
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.unsupported++;
+
        return -1;
 }
 
@@ -867,6 +888,8 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
                pim_ifp->igmp_default_robustness_variable;
        igmp->sock_creation = pim_time_monotonic_sec();
 
+       igmp_stats_init(&igmp->rx_stats);
+
        if (mtrace_only) {
                igmp->mtrace_only = mtrace_only;
                return igmp;
index 561a127d0f1dcc963d3082675c4c96c08aac432f..c8b880ddd7e08aab73bfdabe6249ea6e042a1f49 100644 (file)
@@ -25,6 +25,7 @@
 #include <zebra.h>
 #include "vty.h"
 #include "linklist.h"
+#include "pim_igmp_stats.h"
 
 /*
   The following sizes are likely to support
@@ -94,6 +95,8 @@ struct igmp_sock {
 
        struct list *igmp_group_list; /* list of struct igmp_group */
        struct hash *igmp_group_hash;
+
+       struct igmp_stats rx_stats;
 };
 
 struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
index d3ae185709079d6a8eb0b54cfd8e030f147fb505..673e2ca5b8f2e66566128a7ce92da6ec89440646 100644 (file)
@@ -671,6 +671,9 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.mtrace_req++;
+
        if (PIM_DEBUG_MTRACE)
                mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
 
@@ -881,6 +884,9 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr,
 
        mtracep->checksum = checksum;
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.mtrace_rsp++;
+
        if (PIM_DEBUG_MTRACE)
                mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
 
diff --git a/pimd/pim_igmp_stats.c b/pimd/pim_igmp_stats.c
new file mode 100644 (file)
index 0000000..428816e
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * PIM for FRRouting
+ * Copyright (C) 2018  Mladen Sablic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "pim_igmp_stats.h"
+
+void igmp_stats_init(struct igmp_stats *stats)
+{
+       memset(stats, 0, sizeof(struct igmp_stats));
+}
+
+void igmp_stats_add(struct igmp_stats *a, struct igmp_stats *b)
+{
+       if (!a || !b)
+               return;
+
+       a->query_v1 += b->query_v1;
+       a->query_v2 += b->query_v2;
+       a->query_v3 += b->query_v3;
+       a->report_v1 += b->report_v1;
+       a->report_v2 += b->report_v2;
+       a->report_v3 += b->report_v3;
+       a->leave_v2 += b->leave_v2;
+       a->mtrace_rsp += b->mtrace_rsp;
+       a->mtrace_req += b->mtrace_req;
+       a->unsupported += b->unsupported;
+}
diff --git a/pimd/pim_igmp_stats.h b/pimd/pim_igmp_stats.h
new file mode 100644 (file)
index 0000000..57b5cc6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * PIM for FRRouting
+ * Copyright (C) 2018  Mladen Sablic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PIM_IGMP_STATS_H
+#define PIM_IGMP_STATS_H
+
+#include <zebra.h>
+
+struct igmp_stats {
+       uint32_t        query_v1;
+       uint32_t        query_v2;
+       uint32_t        query_v3;
+       uint32_t        report_v1;
+       uint32_t        report_v2;
+       uint32_t        report_v3;
+       uint32_t        leave_v2;
+       uint32_t        mtrace_rsp;
+       uint32_t        mtrace_req;
+       uint32_t        unsupported;
+};
+
+void igmp_stats_init(struct igmp_stats *stats);
+void igmp_stats_add(struct igmp_stats *a, struct igmp_stats *b);
+
+#endif /* PIM_IGMP_STATS_H */
index dbbe83a9658842a3679cc71824969723423b1bd0..19c37688130c523f4468dc7c488d5712668cfdf2 100644 (file)
@@ -121,6 +121,9 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.report_v2++;
+
        memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
 
        if (PIM_DEBUG_IGMP_PACKETS) {
@@ -167,6 +170,9 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.leave_v2++;
+
        memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
 
        if (PIM_DEBUG_IGMP_PACKETS) {
index 3360e36b4aaff8816f35c304701c569d320706ba..5ccad39b3356e32cbc60841881139f933702a9d0 100644 (file)
@@ -1900,6 +1900,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from,
                return -1;
        }
 
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.report_v3++;
+
        num_groups = ntohs(
                *(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET));
        if (num_groups < 1) {
index ab4ffc26ae4906816e2eecfdc6f54c85d9ea1df8..7e5bb34e31ee391f97cec7139f8a6c93e09eb509 100644 (file)
 
 static void pim_instance_terminate(struct pim_instance *pim)
 {
-       /* Traverse and cleanup rpf_hash */
-       if (pim->rpf_hash) {
-               hash_clean(pim->rpf_hash, (void *)pim_rp_list_hash_clean);
-               hash_free(pim->rpf_hash);
-               pim->rpf_hash = NULL;
-       }
-
        if (pim->ssm_info) {
                pim_ssm_terminate(pim->ssm_info);
                pim->ssm_info = NULL;
@@ -54,6 +47,13 @@ static void pim_instance_terminate(struct pim_instance *pim)
 
        pim_upstream_terminate(pim);
 
+       /* Traverse and cleanup rpf_hash */
+       if (pim->rpf_hash) {
+               hash_clean(pim->rpf_hash, (void *)pim_rp_list_hash_clean);
+               hash_free(pim->rpf_hash);
+               pim->rpf_hash = NULL;
+       }
+
        pim_oil_terminate(pim);
 
        pim_if_terminate(pim);
index 829c917b0f36483fdca475cedd7e2149293316b8..7afc37a28e74a763592edd97e1060d83b6b9da59 100644 (file)
@@ -1176,8 +1176,7 @@ static void pim_msdp_peer_free(struct pim_msdp_peer *mp)
         * Let's make sure we are not running when we delete
         * the underlying data structure
         */
-       pim_msdp_peer_cr_timer_setup(mp, false);
-       pim_msdp_peer_ka_timer_setup(mp, false);
+       pim_msdp_peer_stop_tcp_conn(mp, false);
 
        if (mp->ibuf) {
                stream_free(mp->ibuf);
@@ -1190,6 +1189,8 @@ static void pim_msdp_peer_free(struct pim_msdp_peer *mp)
        if (mp->mesh_group_name) {
                XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name);
        }
+
+       mp->pim = NULL;
        XFREE(MTYPE_PIM_MSDP_PEER, mp);
 }
 
index b5f5f646d42aba7aebe4a61d71d9b848403bbb42..9329d72ce05536b16f04956efc80efe79aa0299b 100644 (file)
@@ -140,12 +140,6 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,
        return NULL;
 }
 
-void pim_upstream_free(struct pim_upstream *up)
-{
-       XFREE(MTYPE_PIM_UPSTREAM, up);
-       up = NULL;
-}
-
 static void upstream_channel_oil_detach(struct pim_upstream *up)
 {
        if (up->channel_oil) {
@@ -161,6 +155,8 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
 struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                                      struct pim_upstream *up, const char *name)
 {
+       struct listnode *node, *nnode;
+       struct pim_ifchannel *ch;
        bool notify_msdp = false;
        struct prefix nht_p;
 
@@ -200,20 +196,17 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                notify_msdp = true;
        }
 
-       pim_upstream_remove_children(pim, up);
-       if (up->sources)
-               list_delete_and_null(&up->sources);
-
        pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
        upstream_channel_oil_detach(up);
 
+       for (ALL_LIST_ELEMENTS(up->ifchannels, node, nnode, ch))
+               pim_ifchannel_delete(ch);
        list_delete_and_null(&up->ifchannels);
 
-       /*
-         notice that listnode_delete() can't be moved
-         into pim_upstream_free() because the later is
-         called by list_delete_all_node()
-       */
+       pim_upstream_remove_children(pim, up);
+       if (up->sources)
+               list_delete_and_null(&up->sources);
+
        if (up->parent && up->parent->sources)
                listnode_delete(up->parent->sources, up);
        up->parent = NULL;
@@ -237,7 +230,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
        }
        pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
 
-       pim_upstream_free(up);
+       XFREE(MTYPE_PIM_UPSTREAM, up);
 
        return NULL;
 }
@@ -1545,8 +1538,15 @@ unsigned int pim_upstream_hash_key(void *arg)
 
 void pim_upstream_terminate(struct pim_instance *pim)
 {
-       if (pim->upstream_list)
+       struct listnode *node, *nnode;
+       struct pim_upstream *up;
+
+       if (pim->upstream_list) {
+               for (ALL_LIST_ELEMENTS(pim->upstream_list, node, nnode, up))
+                       pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+
                list_delete_and_null(&pim->upstream_list);
+       }
 
        if (pim->upstream_hash)
                hash_free(pim->upstream_hash);
@@ -1773,6 +1773,5 @@ void pim_upstream_init(struct pim_instance *pim)
                                              pim_upstream_equal, hash_name);
 
        pim->upstream_list = list_new();
-       pim->upstream_list->del = (void (*)(void *))pim_upstream_free;
        pim->upstream_list->cmp = pim_upstream_compare;
 }
index b75a5b9df376e74cfaab7c02096f08008ea3864e..ba133b39dd444a3a3508d501049389b9b11fdc4d 100644 (file)
@@ -137,7 +137,6 @@ struct pim_upstream {
        int64_t state_transition; /* Record current state uptime */
 };
 
-void pim_upstream_free(struct pim_upstream *up);
 struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
                                       struct prefix_sg *sg);
 struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
index 6cce69720285271dfa5a97df5bcc0db70f5138ad..ae7f61c8eb1c2d9787ffa539946e3a47d2224b0a 100644 (file)
@@ -69,6 +69,7 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
                            zebra_size_t length, vrf_id_t vrf_id)
 {
        struct interface *ifp;
+       struct pim_instance *pim;
 
        /*
          zebra api adds/dels interfaces using the same call
@@ -78,6 +79,7 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
        if (!ifp)
                return 0;
 
+       pim = pim_get_pim_instance(vrf_id);
        if (PIM_DEBUG_ZEBRA) {
                zlog_debug(
                        "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
@@ -86,8 +88,19 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
                        if_is_operative(ifp));
        }
 
-       if (if_is_operative(ifp))
+       if (if_is_operative(ifp)) {
+               struct pim_interface *pim_ifp;
+
+               pim_ifp = ifp->info;
+               /*
+                * If we have a pim_ifp already and this is an if_add
+                * that means that we probably have a vrf move event
+                * If that is the case, set the proper vrfness.
+                */
+               if (pim_ifp)
+                       pim_ifp->pim = pim;
                pim_if_addr_add_all(ifp);
+       }
 
        /*
         * If we are a vrf device that is up, open up the pim_socket for
@@ -145,6 +158,7 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
 static int pim_zebra_if_state_up(int command, struct zclient *zclient,
                                 zebra_size_t length, vrf_id_t vrf_id)
 {
+       struct pim_instance *pim;
        struct interface *ifp;
        uint32_t table_id;
 
@@ -164,7 +178,19 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
                        if_is_operative(ifp));
        }
 
+       pim = pim_get_pim_instance(vrf_id);
        if (if_is_operative(ifp)) {
+               struct pim_interface *pim_ifp;
+
+               pim_ifp = ifp->info;
+               /*
+                * If we have a pim_ifp already and this is an if_add
+                * that means that we probably have a vrf move event
+                * If that is the case, set the proper vrfness.
+                */
+               if (pim_ifp)
+                       pim_ifp->pim = pim;
+
                /*
                  pim_if_addr_add_all() suffices for bringing up both IGMP and
                  PIM
@@ -274,6 +300,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
        struct connected *c;
        struct prefix *p;
        struct pim_interface *pim_ifp;
+       struct pim_instance *pim;
 
        /*
          zebra api notifies address adds/dels events by using the same call
@@ -327,8 +354,12 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
        }
 
        pim_if_addr_add(c);
-       if (pim_ifp)
+       if (pim_ifp) {
+               pim = pim_get_pim_instance(vrf_id);
+               pim_ifp->pim = pim;
+
                pim_rp_check_on_if_add(pim_ifp);
+       }
 
        if (if_is_loopback(c->ifp)) {
                struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
index 2254362221bfa9bd98a1d7499f3775d28f5ba1fa..0696d9b1e81762fdeca60442fad45b5595224b39 100644 (file)
@@ -20,6 +20,7 @@ pimd_libpim_a_SOURCES = \
        pimd/pim_ifchannel.c \
        pimd/pim_igmp.c \
        pimd/pim_igmp_mtrace.c \
+       pimd/pim_igmp_stats.c \
        pimd/pim_igmpv2.c \
        pimd/pim_igmpv3.c \
        pimd/pim_instance.c \
@@ -69,6 +70,7 @@ noinst_HEADERS += \
        pimd/pim_igmp.h \
        pimd/pim_igmp_join.h \
        pimd/pim_igmp_mtrace.h \
+       pimd/pim_igmp_stats.h \
        pimd/pim_igmpv2.h \
        pimd/pim_igmpv3.h \
        pimd/pim_instance.h \
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 9e0cb1f5ca61cf3e7bb5af2e5bd621690f24324f..8db1cb2ca1d385edea51cae5fdaf26d4f1693114 100644 (file)
@@ -945,6 +945,24 @@ static struct test_segment mp_unreach_segments[] = {
        },
        {NULL, NULL, {0}, 0, 0}};
 
+static struct test_segment mp_prefix_sid[] = {
+       {
+               "PREFIX-SID",
+               "PREFIX-SID Test 1",
+               {
+                       0x01, 0x00, 0x07,
+                       0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x02,
+                       0x03, 0x00, 0x08, 0x00,
+                       0x00, 0x0a, 0x1b, 0xfe,
+                       0x00, 0x00, 0x0a
+               },
+               .len = 21,
+               .parses = SHOULD_PARSE,
+       },
+       {NULL, NULL, { 0 }, 0, 0},
+};
+
 /* nlri_parse indicates 0 on successful parse, and -1 otherwise.
  * attr_parse indicates BGP_ATTR_PARSE_PROCEED/0 on success,
  * and BGP_ATTR_PARSE_ERROR/-1 or lower negative ret on err.
@@ -1000,10 +1018,20 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
 
        printf("%s: %s\n", t->name, t->desc);
 
-       if (type == BGP_ATTR_MP_REACH_NLRI)
+       switch (type) {
+       case BGP_ATTR_MP_REACH_NLRI:
                parse_ret = bgp_mp_reach_parse(&attr_args, &nlri);
-       else
+               break;
+       case BGP_ATTR_MP_UNREACH_NLRI:
                parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
+               break;
+       case BGP_ATTR_PREFIX_SID:
+               parse_ret = bgp_attr_prefix_sid(t->len, &attr_args, &nlri);
+               break;
+       default:
+               printf("unknown type");
+               return;
+       }
        if (!parse_ret) {
                iana_afi_t pkt_afi;
                iana_safi_t pkt_safi;
@@ -1022,7 +1050,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
        if (!parse_ret) {
                if (type == BGP_ATTR_MP_REACH_NLRI)
                        nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0);
-               else
+               else if (type == BGP_ATTR_MP_UNREACH_NLRI)
                        nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1);
        }
        handle_result(peer, t, parse_ret, nlri_ret);
@@ -1085,6 +1113,10 @@ int main(void)
                parse_test(peer, &mp_unreach_segments[i++],
                           BGP_ATTR_MP_UNREACH_NLRI);
 
+       i = 0;
+       while (mp_prefix_sid[i].name)
+               parse_test(peer, &mp_prefix_sid[i++],
+                          BGP_ATTR_PREFIX_SID);
        printf("failures: %d\n", failed);
        return failed;
 }
index 867dc9cd1504a9fd4afd554b9078f32340f03a5a..9fff2ee58c4ee90091030551926c6112577b33cf 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"
@@ -2361,13 +2361,22 @@ DEFUNSH(VTYSH_ALL, no_vtysh_service_password_encrypt,
 
 DEFUNSH(VTYSH_ALL, vtysh_config_password, vtysh_password_cmd,
        "password [(8-8)] LINE",
-       "Assign the terminal connection password\n"
+       "Modify the terminal connection password\n"
        "Specifies a HIDDEN password will follow\n"
        "The password string\n")
 {
        return CMD_SUCCESS;
 }
 
+DEFUNSH(VTYSH_ALL, no_vtysh_config_password, no_vtysh_password_cmd,
+       "no password", NO_STR
+       "Modify the terminal connection password\n")
+{
+       vty_out(vty, NO_PASSWD_CMD_WARNING);
+
+       return CMD_SUCCESS;
+}
+
 DEFUNSH(VTYSH_ALL, vtysh_config_enable_password, vtysh_enable_password_cmd,
        "enable password [(8-8)] LINE",
        "Modify enable password parameters\n"
@@ -2383,6 +2392,8 @@ DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password,
        "Modify enable password parameters\n"
        "Assign the privileged level password\n")
 {
+       vty_out(vty, NO_PASSWD_CMD_WARNING);
+
        return CMD_SUCCESS;
 }
 
@@ -3605,6 +3616,7 @@ void vtysh_init_vty(void)
        install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
 
        install_element(CONFIG_NODE, &vtysh_password_cmd);
+       install_element(CONFIG_NODE, &no_vtysh_password_cmd);
        install_element(CONFIG_NODE, &vtysh_enable_password_cmd);
        install_element(CONFIG_NODE, &no_vtysh_enable_password_cmd);
 }
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 190ac1e57f7ec7571f4306a7fb1fe3642bd30e16..f3fa3ba94efd618e9730c46527f8c2f64f14390f 100644 (file)
@@ -50,7 +50,6 @@ DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk");
  * it will be a proxy to relay messages to external label manager
  * This zclient thus is to connect to it
  */
-static struct stream *ibuf;
 static struct stream *obuf;
 static struct zclient *zclient;
 bool lm_is_external;
@@ -60,7 +59,7 @@ static void delete_label_chunk(void *val)
        XFREE(MTYPE_LM_CHUNK, val);
 }
 
-static int relay_response_back(struct zserv *zserv)
+static int relay_response_back(void)
 {
        int ret = 0;
        struct stream *src, *dst;
@@ -69,49 +68,72 @@ static int relay_response_back(struct zserv *zserv)
        uint8_t version;
        vrf_id_t vrf_id;
        uint16_t resp_cmd;
+       uint8_t proto;
+       const char *proto_str;
+       unsigned short instance;
+       struct zserv *zserv;
 
+       /* input buffer with msg from label manager */
        src = zclient->ibuf;
-       dst = obuf;
 
        stream_reset(src);
 
+       /* parse header */
        ret = zclient_read_header(src, zclient->sock, &size, &marker, &version,
                                  &vrf_id, &resp_cmd);
        if (ret < 0 && errno != EAGAIN) {
-               zlog_err("%s: Error reading Label Manager response: %s",
-                        __func__, strerror(errno));
+               zlog_err("Error reading Label Manager response: %s",
+                        strerror(errno));
                return -1;
        }
-       zlog_debug("%s: Label Manager response received, %d bytes", __func__,
-                  size);
+       zlog_debug("Label Manager response received, %d bytes", size);
        if (size == 0)
                return -1;
 
-       /* send response back */
+       /* Get the 'proto' field of the message */
+       proto = stream_getc(src);
+
+       /* Get the 'instance' field of the message */
+       instance = stream_getw(src);
+
+       proto_str = zebra_route_string(proto);
+
+       /* lookup the client to relay the msg to */
+       zserv = zebra_find_client(proto, instance);
+       if (!zserv) {
+               zlog_err(
+                       "Error relaying LM response: can't find client %s, instance %u",
+                       proto_str, instance);
+               return -1;
+       }
+       zlog_debug("Found client to relay LM response to client %s instance %u",
+                  proto_str, instance);
+
+       /* copy msg into output buffer */
+       dst = obuf;
        stream_copy(dst, src);
-       ret = writen(zserv->sock, src->data, stream_get_endp(src));
+
+       /* send response back */
+       ret = writen(zserv->sock, dst->data, stream_get_endp(dst));
        if (ret <= 0) {
-               zlog_err("%s: Error sending Label Manager response back: %s",
-                        __func__, strerror(errno));
+               zlog_err("Error relaying LM response to %s instance %u: %s",
+                        proto_str, instance, strerror(errno));
                return -1;
        }
-       zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__,
-                  ret);
+       zlog_debug("Relayed LM response (%d bytes) to %s instance %u", ret,
+                  proto_str, instance);
 
        return 0;
 }
 
 static int lm_zclient_read(struct thread *t)
 {
-       struct zserv *zserv;
        int ret;
 
-       /* Get socket to zebra. */
-       zserv = THREAD_ARG(t);
        zclient->t_read = NULL;
 
        /* read response and send it back */
-       ret = relay_response_back(zserv);
+       ret = relay_response_back();
 
        return ret;
 }
@@ -125,6 +147,10 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
 
        zclient_create_header(s, cmd, vrf_id);
 
+       /* proto */
+       stream_putc(s, zserv->proto);
+       /* instance */
+       stream_putw(s, zserv->instance);
        /* result */
        stream_putc(s, 1);
 
@@ -148,38 +174,73 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
  * @return 0 on success, -1 otherwise
  */
 int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
-                                     vrf_id_t vrf_id)
+                                     struct stream *msg, vrf_id_t vrf_id)
 {
-       struct stream *src, *dst;
+       struct stream *dst;
        int ret = 0;
+       uint8_t proto;
+       const char *proto_str;
+       unsigned short instance;
 
        if (zclient->sock < 0) {
-               zlog_err(
-                       "%s: Error relaying label chunk request: no zclient socket",
-                       __func__);
+               zlog_err("Unable to relay LM request: no socket");
                reply_error(cmd, zserv, vrf_id);
                return -1;
        }
 
+       /* peek msg to get proto and instance id. This zebra, which acts as
+        * a proxy needs to have such values for each client in order to
+        * relay responses back to it.
+        */
+
+       /* Get the 'proto' field of incoming msg */
+       proto = stream_getc(msg);
+
+       /* Get the 'instance' field of incoming msg */
+       instance = stream_getw(msg);
+
+       /* stringify proto */
+       proto_str = zebra_route_string(proto);
+
+       /* check & set client proto if unset */
+       if (zserv->proto && zserv->proto != proto) {
+               zlog_warn("Client proto(%u) != msg proto(%u)", zserv->proto,
+                         proto);
+               return -1;
+       }
+
+       /* check & set client instance if unset */
+       if (zserv->instance && zserv->instance != instance) {
+               zlog_err("Client instance(%u) != msg instance(%u)",
+                        zserv->instance, instance);
+               return -1;
+       }
+
+       /* recall proto and instance */
+       zserv->instance = instance;
+       zserv->proto = proto;
+
        /* in case there's any incoming message enqueued, read and forward it */
        while (ret == 0)
-               ret = relay_response_back(zserv);
+               ret = relay_response_back();
 
-       /* Send request to external label manager */
-       src = ibuf;
+       /* get the msg buffer used toward the 'master' Label Manager */
        dst = zclient->obuf;
 
-       stream_copy(dst, src);
+       /* copy the message */
+       stream_copy(dst, msg);
 
+       /* Send request to external label manager */
        ret = writen(zclient->sock, dst->data, stream_get_endp(dst));
        if (ret <= 0) {
-               zlog_err("%s: Error relaying label chunk request: %s", __func__,
-                        strerror(errno));
+               zlog_err("Error relaying LM request from %s instance %u: %s",
+                        proto_str, instance, strerror(errno));
                reply_error(cmd, zserv, vrf_id);
                return -1;
        }
-       zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__,
-                  ret);
+       zlog_debug("Relayed LM request (%d bytes) from %s instance %u", ret,
+                  proto_str, instance);
+
 
        /* Release label chunk has no response */
        if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
@@ -187,7 +248,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
 
        /* make sure we listen to the response */
        if (!zclient->t_read)
-               thread_add_read(zclient->master, lm_zclient_read, zserv,
+               thread_add_read(zclient->master, lm_zclient_read, NULL,
                                zclient->sock, &zclient->t_read);
 
        return 0;
@@ -276,7 +337,7 @@ void label_manager_init(char *lm_zserv_path)
 {
        /* this is an actual label manager */
        if (!lm_zserv_path) {
-               zlog_debug("Initializing own label manager");
+               zlog_debug("Initializing internal label manager");
                lm_is_external = false;
                lbl_mgr.lc_list = list_new();
                lbl_mgr.lc_list->del = delete_label_chunk;
@@ -287,7 +348,6 @@ void label_manager_init(char *lm_zserv_path)
                lm_zclient_init(lm_zserv_path);
        }
 
-       ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
        obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
        hook_register(zapi_client_close, release_daemon_label_chunks);
@@ -393,6 +453,5 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
 void label_manager_close()
 {
        list_delete_and_null(&lbl_mgr.lc_list);
-       stream_free(ibuf);
        stream_free(obuf);
 }
index b998372224ad02cc679cfd19c6e7aeb8e51dafab..3e3def5f98bbf47eaf7a18e11cc6da2a4786c65d 100644 (file)
@@ -64,7 +64,7 @@ struct label_manager {
 bool lm_is_external;
 
 int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
-                                     vrf_id_t vrf_id);
+                                     struct stream *msg, vrf_id_t vrf_id);
 void label_manager_init(char *lm_zserv_path);
 struct label_manager_chunk *assign_label_chunk(uint8_t proto,
                                               unsigned short instance,
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..9a18cc22f0c5500c090b7ef1c2cb56515129a187 100644 (file)
@@ -887,6 +887,10 @@ static int zsend_assign_label_chunk_response(struct zserv *client,
        zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
 
        if (lmc) {
+               /* proto */
+               stream_putc(s, lmc->proto);
+               /* instance */
+               stream_putw(s, lmc->instance);
                /* keep */
                stream_putc(s, lmc->keep);
                /* start and end labels */
@@ -912,6 +916,12 @@ static int zsend_label_manager_connect_response(struct zserv *client,
 
        zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
 
+       /* proto */
+       stream_putc(s, client->proto);
+
+       /* instance */
+       stream_putw(s, client->instance);
+
        /* result */
        stream_putc(s, result);
 
@@ -1382,7 +1392,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 +1425,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 +1532,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 +1734,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 +2158,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++;
 
@@ -2398,6 +2407,26 @@ static void zread_label_manager_connect(struct zserv *client,
 stream_failure:
        return;
 }
+static int msg_client_id_mismatch(const char *op, struct zserv *client,
+                                 uint8_t proto, unsigned int instance)
+{
+       if (proto != client->proto) {
+               zlog_err("%s: msg vs client proto mismatch, client=%u msg=%u",
+                        op, client->proto, proto);
+               /* TODO: fail when BGP sets proto and instance */
+               /* return 1; */
+       }
+
+       if (instance != client->instance) {
+               zlog_err(
+                       "%s: msg vs client instance mismatch, client=%u msg=%u",
+                       op, client->instance, instance);
+               /* TODO: fail when BGP sets proto and instance */
+               /* return 1; */
+       }
+
+       return 0;
+}
 
 static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
                                  vrf_id_t vrf_id)
@@ -2406,21 +2435,32 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
        uint8_t keep;
        uint32_t size;
        struct label_manager_chunk *lmc;
+       uint8_t proto;
+       unsigned short instance;
 
        /* Get input stream.  */
        s = msg;
 
        /* Get data. */
+       STREAM_GETC(s, proto);
+       STREAM_GETW(s, instance);
        STREAM_GETC(s, keep);
        STREAM_GETL(s, size);
 
+       /* detect client vs message (proto,instance) mismatch */
+       if (msg_client_id_mismatch("Get-label-chunk", client, proto, instance))
+               return;
+
        lmc = assign_label_chunk(client->proto, client->instance, keep, size);
        if (!lmc)
-               zlog_err("%s: Unable to assign Label Chunk of size %u",
-                        __func__, size);
+               zlog_err(
+                       "Unable to assign Label Chunk of size %u to %s instance %u",
+                       size, zebra_route_string(client->proto),
+                       client->instance);
        else
-               zlog_debug("Assigned Label Chunk %u - %u to %u", lmc->start,
-                          lmc->end, keep);
+               zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",
+                          lmc->start, lmc->end,
+                          zebra_route_string(client->proto), client->instance);
        /* send response back */
        zsend_assign_label_chunk_response(client, vrf_id, lmc);
 
@@ -2432,14 +2472,23 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
 {
        struct stream *s;
        uint32_t start, end;
+       uint8_t proto;
+       unsigned short instance;
 
        /* Get input stream.  */
        s = msg;
 
        /* Get data. */
+       STREAM_GETC(s, proto);
+       STREAM_GETW(s, instance);
        STREAM_GETL(s, start);
        STREAM_GETL(s, end);
 
+       /* detect client vs message (proto,instance) mismatch */
+       if (msg_client_id_mismatch("Release-label-chunk", client, proto,
+                                  instance))
+               return;
+
        release_label_chunk(client->proto, client->instance, start, end);
 
 stream_failure:
@@ -2453,7 +2502,7 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
 
        /* external label manager */
        if (lm_is_external)
-               zread_relay_label_manager_request(hdr->command, client,
+               zread_relay_label_manager_request(hdr->command, client, msg,
                                                  zvrf_id(zvrf));
        /* this is a label manager */
        else {
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);