]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #1931 from msablic/pim_mtrace_router
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Mar 2018 22:41:20 +0000 (18:41 -0400)
committerGitHub <noreply@github.com>
Thu, 22 Mar 2018 22:41:20 +0000 (18:41 -0400)
pimd: mtrace router code improvments and fixes

63 files changed:
COMMUNITY.md
alpine/.gitignore [new file with mode: 0644]
alpine/APKBUILD.in
bgpd/bgp_bfd.c
bgpd/bgp_evpn.c
bgpd/bgp_fsm.c
bgpd/bgp_label.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_network.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/bgpd.h
doc/Makefile.am
doc/developer/Building_FRR_on_Alpine.rst [new file with mode: 0644]
doc/developer/building.rst
doc/developer/cli.rst
doc/developer/workflow.rst
doc/user/bgp.rst
docker/.gitignore [new file with mode: 0644]
docker/alpine/Dockerfile [new file with mode: 0644]
docker/alpine/alpine-build.sh [new file with mode: 0755]
docker/alpine/build.sh [new file with mode: 0755]
docker/alpine/builder [new file with mode: 0644]
isisd/isis_bpf.c
isisd/isis_pdu.c
isisd/isis_pdu.h
lib/command.c
lib/command.h
lib/log.c
lib/route_types.txt
lib/zclient.c
ospf6d/ospf6_area.h
ospf6d/ospf6_asbr.c
ospf6d/ospf6_flood.c
ospf6d/ospf6_flood.h
ospf6d/ospf6_intra.c
ospf6d/ospf6_neighbor.c
pimd/pim_igmp_mtrace.c
redhat/frr.spec.in
ripd/ripd.c
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
sharpd/sharp_zebra.h
vtysh/vtysh.c
zebra/main.c
zebra/redistribute.c
zebra/rib.h
zebra/zebra_mpls.c
zebra/zebra_netns_id.c
zebra/zebra_ns.c
zebra/zebra_ns.h
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_vty.c
zebra/zserv.c

index 081f7ab3b832461f9c9a49d2642c15d657d86f53..fa003108513d6a3f9dcc3a223d6d1e6fa4453938 100644 (file)
@@ -1,528 +1 @@
-Developing for FRRouting
-=========================
-
-## Table of Contents
-
-[TOC]
-
-## General note on this document
-
-This document is "descriptive/post-factual" in that it documents pratices that
-are in use; it is not "definitive/pre-factual" in prescribing practices.
-
-This means that when a procedure changes, it is agreed upon, then put into
-practice, and then documented here.  If this document doesn't match reality,
-it's the document that needs to be updated, not reality.
-
-
-## Git Structure
-
-The master Git for FRRouting resides on Github at
-[https://github.com/frrouting/frr](https://github.com/FRRouting/frr)
-
-![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg
-"git branch mechanics")
-
-There is one main branch for development and a release branch for each major
-release.
-
-New contributions are done against the head of the master branch. The CI
-systems will pick up the Github Pull Requests or the new patch from Patchwork,
-run some basic build and functional tests.
-
-For each major release (1.0, 1.1 etc) a new release branch is created based on
-the master.
-
-There was an attempt to use a "develop" branch automatically maintained by the
-CI system.  This is not currently in active use, though the system is
-operational.  If the "develop" branch is in active use and this paragraph is
-still here, this document obviously wasn't updated.
-
-
-## Programming language, Tools and Libraries
-
-The core of FRRouting is written in C (gcc or clang supported) and makes use of
-GNU compiler extensions. A few non-essential scripts are implemented in Perl
-and Python. FRRouting requires the following tools to build distribution
-packages: automake, autoconf, texinfo, libtool and gawk and various libraries
-(i.e. libpam and libjson-c).
-
-If your contribution requires a new library or other tool, then please
-highlight this in your description of the change. Also make sure it’s supported
-by all FRRouting platform OSes or provide a way to build without the library
-(potentially without the new feature) on the other platforms.
-
-Documentation should be written in Tex (.texi) or Markdown (.md) format with a
-preference for Markdown.
-
-
-## Mailing lists
-
-Italicized lists are private.
-
-| Topic                          | List                         |
-|--------------------------------|------------------------------|
-| Development                    | dev@lists.frrouting.org      |
-| Users & Operators              | frog@lists.frrouting.org     |
-| Announcements                  | announce@lists.frrouting.org |
-| _Security_                     | security@lists.frrouting.org |
-| _Technical Steering Committee_ | tsc@lists.frrouting.org      |
-
-The Development list is used to discuss and document general issues
-related to project development and governance. The public Slack
-instance, frrouting.slack.com, and weekly technical meetings provide a
-higher bandwidth channel for discussions.  The results of such
-discussions must be reflected in updates, as appropriate, to code (i.e.,
-merges), [github](https://github.com/FRRouting/frr/issues) tracked
-issues, and for governance or process changes, updates to the
-Development list and either this file or information posted at
-[https://frrouting.org/](https://frrouting.org/).
-
-
-### Changelog
-
-The changelog will be the base for the release notes. A changelog entry for
-your changes is usually not required and will be added based on your commit
-messages by the maintainers. However, you are free to include an update to
-the changelog with some better description. The changelog will be the base
-for the release notes.
-
-
-## Submitting Patches and Enhancements
-
-### Pre-submission Checklist
-
-* Format code (see [Developer's Guidelines](#developers-guidelines))
-* Verify and acknowledge license (see [License for contributions](#license-for-contributions))
-* Ensure you have properly signed off (see [Signing Off](#signing-off))
-* Test building with various configurations:
-    * `buildtest.sh`
-* Verify building source distribution:
-    * `make dist` (and try rebuilding from the resulting tar file)
-* Run unit tests:
-    * `make test`
-* Document Regression Runs and plans for continued maintenance of the feature
-
-### License for contributions
-
-FRRouting is under a “GPLv2 or later” license. Any code submitted must be
-released under the same license (preferred) or any license which allows
-redistribution under this GPLv2 license (eg MIT License).
-
-### Signing Off
-
-Code submitted to FRRouting must be signed off. We have the same requirements
-for using the signed-off-by process as the Linux kernel. In short, you must
-include a signed-off-by tag in every patch.
-
-`Signed-off-by:` this is a developer's certification that he or she has the
-right to submit the patch for inclusion into the project. It is an agreement to
-the Developer's Certificate of Origin (below). Code without a proper signoff
-can not and will not be merged.
-
-If you are unfamiliar with this process, you should read the [official policy
-at kernel.org](https://www.kernel.org/doc/html/latest/process/submitting-patches.html) and
-you might find this article about [participating in the Linux community on the
-Linux Foundation
-website](http://www.linuxfoundation.org/content/how-participate-linux-community-0)
-to be a helpful resource.
-
-In short, when you sign off on a commit, you assert your agreement to all of
-the following:
-
-> Developer's Certificate of Origin 1.1
->
-> By making a contribution to this project, I certify that:
->
-> (a) The contribution was created in whole or in part by me and I
->     have the right to submit it under the open source license
->     indicated in the file; or
->
-> (b) The contribution is based upon previous work that, to the best
->     of my knowledge, is covered under an appropriate open source
->     license and I have the right under that license to submit that
->     work with modifications, whether created in whole or in part
->     by me, under the same open source license (unless I am
->     permitted to submit under a different license), as indicated
->     in the file; or
->
-> (c) The contribution was provided directly to me by some other
->     person who certified (a), (b) or (c) and I have not modified
->     it.
->
-> (d) I understand and agree that this project and the contribution
->     are public and that a record of the contribution (including all
->     personal information I submit with it, including my sign-off) is
->     maintained indefinitely and may be redistributed consistent with
->     this project or the open source license(s) involved.
-
-### What do I submit my changes against?
-
-We've documented where we would like to have the different fixes applied at
-https://github.com/FRRouting/frr/wiki/Where-Do-I-create-a-Pull-Request-against%3F
-If you are unsure where your submission goes, look at that document or ask a
-project maintainer.
-
-### Github pull requests
-
-The preferred method of submitting changes is a Github pull request. Code
-submitted by pull request will be automatically tested by one or more CI
-systems. Once the automated tests succeed, other developers will review your
-code for quality and correctness. After any concerns are resolved, your code
-will be merged into the branch it was submitted against.
-
-### Patch submission via mailing list
-
-As an alternative submission method, a patch can be mailed to the development
-mailing list. Patches received on the mailing list will be picked up by
-Patchwork and tested against the latest development branch.
-
-The recommended way to send the patch (or series of NN patches) to the list is
-by using `git send-email` as follows (assuming they are the N most recent
-commit(s) in your git history:
-
-```
-git send-email -NN --annotate --to=dev@lists.frrouting.org
-```
-
-If your commits do not already contain a `Signed-off-by` line, then use the
-following command to add it (after making sure you agree to the Developer
-Certificate of Origin as outlined above):
-
-```
-git send-email -NN --annotate --signoff --to=dev@lists.frrouting.org
-```
-
-Submitting multi-commit patches as a Github pull request is **strongly
-encouraged** and increases the probability of your patch getting reviewed and
-merged in a timely manner.
-
-
-## After submitting your changes
-
-* Watch for Continuous Integration (CI) Test results
-    * You should automatically receive an email with the test results within
-      less than 2 hrs of the submission. If you don’t get the email, then check
-      status on the github pull request (if submitted by pull request) or on
-      Patchwork at
-      [https://patchwork.frrouting.org](https://patchwork.frrouting.org) (if
-      submitted as patch to mailing list).
-    * Please notify the development mailing list if you think something doesn’t
-      work.
-* If the tests failed:
-    * In general, expect the community to ignore the submission until the tests
-      pass.
-    * It is up to you to fix and resubmit.
-        * This includes fixing existing unit (“make test”) tests if your
-          changes broke or changed them.
-        * It also includes fixing distribution packages for the failing
-          platforms (ie if new libraries are required).
-        * Feel free to ask for help on the development list.
-    * Go back to the submission process and repeat until the tests pass.
-* If the tests pass:
-    * Wait for reviewers. Someone will review your code or be assigned to
-      review your code.
-    * Respond to any comments or concerns the reviewer has.
-    * After all comments and concerns are addressed, expect your patch to be
-      merged.
-* Watch out for questions on the mailing list. At this time there will be a
-  manual code review and further (longer) tests by various community members.
-* Your submission is done once it is merged to the master branch.
-
-
-## Developer's Guidelines
-
-### Commit messages
-
-Commit messages should be formatted in the same way as Linux kernel commit
-messages. The format is roughly
-
-```
-dir: short summary
-
-extended summary
-```
-
-`dir` should be the top level source directory under which the change was made.
-For example, a change in bgpd/rfapi would be formatted as:
-
-`bgpd: short summary`
-
-The first line should be no longer than 50 characters. Subsequent lines should
-be wrapped to 72 characters.
-
-### Source file header
-
-New files need to have a Copyright header (see [License for
-contributions](#license-for-contributions) above) added to the file. Preferred
-form of the header is as follows:
-
-```
-/*
- * Title/Function of file
- * Copyright (C) YEAR  Author’s Name
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-```
-
-### Adding copyright claims to existing files
-
-When adding copyright claims for modifications to an existing file, please
-preface the claim with "Portions: " on a line before it and indent the
-"Copyright ..." string. If such a case already exists, add your indented claim
-immediately after. E.g.:
-
-```
-Portions:
-  Copyright (C) 2010 Entity A ....
-  Copyright (C) 2016 Your name [optional brief change description]
-```
-
-### Code formatting
-
-FRR uses Linux kernel style except where noted below. Code which does not
-comply with these style guidelines will not be accepted.
-
-To assist with compliance, in the project root there is a .clang-format
-configuration file which can be used with the `clang-format` tool from the LLVM
-project. In the `tools/` directory there is a Python script named `indent.py`
-that wraps clang-format and handles some edge cases specific to FRR. If you are
-submitting a new file, it is recommended to run that script over the new file
-after ensuring that the latest stable release of `clang-format` is in your
-PATH.
-
-**Whitespace changes in untouched parts of the code are not acceptable in
-patches that change actual code.**  To change/fix formatting issues, please
-create a separate patch that only does formatting changes and nothing else.
-
-#### Style documentation
-Kernel and BSD styles are documented externally:
-
-* [https://www.kernel.org/doc/html/latest/process/coding-style.html](https://www.kernel.org/doc/html/latest/process/coding-style.html)
-* [http://man.openbsd.org/style](http://man.openbsd.org/style)
-
-For GNU coding style, use `indent` with the following invocation:
-
-```
-indent -nut -nfc1 file_for_submission.c
-```
-
-#### Exceptions
-
-FRR project code comes from a variety of sources, so there are some stylistic
-exceptions in place. They are organized here by branch.
-
-**For `master`:**
-
-BSD coding style applies to:
-
-* `ldpd/`
-
-`babeld` uses, approximately, the following style:
-
-* K&R style braces
-* Indents are 4 spaces
-* Function return types are on their own line
-
-
-**For `stable/3.0` and `stable/2.0`:**
-
-GNU coding style apply to the following parts:
-
-* `lib/`
-* `zebra/`
-* `bgpd/`
-* `ospfd/`
-* `ospf6d/`
-* `isisd/`
-* `ripd/`
-* `ripngd/`
-* `vtysh/`
-
-BSD coding style applies to:
-
-* `ldpd/`
-
-
-### Documentation
-
-FRRouting is a large and complex software project developed by many different
-people over a long period of time. Without adequate documentation, it can be
-exceedingly difficult to understand code segments, APIs and other interfaces.
-In the interest of keeping the project healthy and maintainable, you should
-make every effort to document your code so that other people can understand
-what it does without needing to closely read the code itself.
-
-Some specific guidelines that contributors should follow are:
-
-* Functions exposed in header files should have descriptive comments above
-  their signatures in the header file. At a minimum, a function comment should
-  contain information about the return value, parameters, and a general summary
-  of the function's purpose. Documentation on parameter values can be omitted
-  if it is (very) obvious what they are used for.
-
-  Function comments must follow the style for multiline comments laid out in
-  the kernel style guide.
-
-Example:
-
-```
-/*
- * Determines whether or not a string is cool.
- *
- * @param text - the string to check for coolness
- * @param is_clccfc - whether capslock is cruise control for cool
- * @return 7 if the text is cool, 0 otherwise
- */
-int check_coolness(const char *text, bool is_clccfc);
-```
-
-The Javadoc-style annotations are not required, but you should still strive to
-make it equally clear what parameters and return values are used for.
-
-* Static functions should have descriptive comments in the same form as above
-  if what they do is not immediately obvious. Use good engineering judgement
-  when deciding whether a comment is necessary. If you are unsure, document
-  your code.
-
-* Global variables, static or not, should have a comment describing their use.
-
-* **For new code in `lib/`, these guidelines are hard requirements.**
-
-
-If you are contributing code that adds significant user-visible functionality
-or introduces a new API, please document it in `doc/`.  Markdown and LaTeX are
-acceptable formats, although Markdown is currently preferred for new
-documentation. This may change in the near future.
-
-Finally, if you come across some code that is undocumented and feel like going
-above and beyond, document it! We absolutely appreciate and accept patches that
-document previously undocumented code.
-
-### Compile-time conditional code
-
-Many users access FRR via binary packages from 3rd party sources; compile-time
-code puts inclusion/exclusion in the hands of the package maintainer.  Please
-think very carefully before making code conditional at compile time, as it
-increases regression testing, maintenance burdens, and user confusion. In
-particular, please avoid gratuitous `--enable-…` switches to the configure
-script - in general, code should be of high quality and in working condition,
-or it shouldn’t be in FRR at all.
-
-When code must be compile-time conditional, try have the compiler make it
-conditional rather than the C pre-processor so that it will still be checked by
-the compiler, even if disabled. For example,
-
-```
-if (SOME_SYMBOL)
-      frobnicate();
-```
-
-is preferred to
-
-```
-#ifdef SOME_SYMBOL
-frobnicate ();
-#endif /* SOME_SYMBOL */
-```
-
-Note that the former approach requires ensuring that `SOME_SYMBOL` will be
-defined (watch your `AC_DEFINE`s).
-
-### Debug-guards in code
-
-Debugging statements are an important methodology to allow developers to fix
-issues found in the code after it has been released.  The caveat here is that
-the developer must remember that people will be using the code at scale and in
-ways that can be unexpected for the original implementor.  As such debugs
-**MUST** be guarded in such a way that they can be turned off.  FRR has the
-ability to turn on/off debugs from the CLI and it is expected that the
-developer will use this convention to allow control of their debugs.
-
-### CLI changes
-
-CLI's are a complicated ugly beast.  Additions or changes to the CLI should use
-a DEFUN to encapsulate one setting as much as is possible.  Additionally as new
-DEFUN's are added to the system, documentation should be provided for the new
-commands.
-
-### Backwards Compatibility
-
-As a general principle, changes to CLI and code in the lib/ directory should be
-made in a backwards compatible fashion. This means that changes that are purely
-stylistic in nature should be avoided, e.g., renaming an existing macro or
-library function name without any functional change. When adding new parameters
-to common functions, it is also good to consider if this too should be done in
-a backward compatible fashion, e.g., by preserving the old form in addition to
-adding the new form.
-
-This is not to say that minor or even major functional changes to CLI and
-common code should be avoided, but rather that the benefit gained from a change
-should be weighed against the added cost/complexity to existing code.  Also,
-that when making such changes, it is good to preserve compatibility when
-possible to do so without introducing maintenance overhead/cost.  It is also
-important to keep in mind, existing code includes code that may reside in
-private repositories (and is yet to be submitted) or code that has yet to be
-migrated from Quagga to FRR.
-
-That said, compatibility measures can (and should) be removed when either:
-
-* they become a significant burden, e.g. when data structures change and the
-  compatibility measure would need a complex adaptation layer or becomes
-  flat-out impossible
-* some measure of time (dependent on the specific case) has passed, so that the
-  compatibility grace period is considered expired.
-
-In all cases, compatibility pieces should be marked with compiler/preprocessor
-annotations to print warnings at compile time, pointing to the appropriate
-update path.  A `-Werror` build should fail if compatibility bits are used.
-
-### Release Process/Schedule
-
-FRR employs a <MAJOR>.<MINOR>.<BUGFIX> versioning scheme.
-
-* MAJOR - Significant new features or multiple minor features
-  A example of a MAJOR feature is a New Routing Protocol
-* MINOR - Smaller Features
-  A example of a MINOR feature is the addition of the BGP Shutdown feature.
-* BUGFIX - Fixes for actual bugs and/or security issues.
-
-We will pull a new development branch for the next release every 4 months.
-The current schedule is Feb/June/October 1.  The decision for a MAJOR/MINOR
-release is made at the time of branch pull based on what has been received
-the previous 4 months.  The branch name will be dev/MAJOR.MINOR.  At
-this point in time the master branch configure.ac and packaging systems
-will be updated to reflect the next possible release name to allow
-for easy distinguishing.  Additionally the new dev branch will have
-these files updated too.
-
-After one month the development branch will be renamed to
-stable/MAJOR.MINOR.  This process is not held up unless a crash or
-security issue has been found and needs to be addressed.  Issues
-being fixed will not cause a delay.
-
-Bug fix releases are at 1 month intervals until next MAJOR.MINOR is
-pulled.  Then at that time as needed for issues filed.
-
-Security issues are fixed for 1 year minimum on old releases and
-normal bug fixes for the current and previous release
-
-### Miscellaneous
-
-When in doubt, follow the guidelines in the Linux kernel style guide, or ask on
-the development mailing list / public Slack instance.
+Moved to doc/developer/workflow.rst
diff --git a/alpine/.gitignore b/alpine/.gitignore
new file mode 100644 (file)
index 0000000..1b6593c
--- /dev/null
@@ -0,0 +1 @@
+/APKBUILD
index 33c2859245693247061fd5675d1328ebf24d508c..2b211ccafdb53e9367a5ff47cfe969f4ae562fc6 100644 (file)
@@ -18,7 +18,8 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
     libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1
     mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base
     patch pax-utils pcre perl pkgconf python2 python2-dev readline
-    readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs"
+    readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs
+    py-sphinx"
 subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
 source="$pkgname-$pkgver.tar.gz"
 
index ce46b21f03d1be51d1de1224ff43c6184c4bae56..91b6929ff9998e74cdb0077e433295c607d11c23 100644 (file)
@@ -101,7 +101,7 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
 
        bfd_info = (struct bfd_info *)peer->bfd_info;
 
-       if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF))
+       if (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
                vrf_id = peer->bgp->vrf_id;
 
        if (command == ZEBRA_BFD_DEST_DEREGISTER) {
index 94d9cb465be9c5c3c9fa0ef11bd10e36c19b92f6..448cc91cc7d81c8ee5cc318fa334eef2093f6718 100644 (file)
@@ -367,15 +367,12 @@ static void map_vrf_to_rt(struct bgp *bgp_vrf, struct ecommunity_val *eval)
                mask_ecom_global_admin(&eval_tmp, eval);
 
        irt = lookup_vrf_import_rt(&eval_tmp);
-       if (irt && irt->vrfs)
-               if (is_vrf_present_in_irt_vrfs(irt->vrfs, bgp_vrf))
-                       /* Already mapped. */
-                       return;
+       if (irt && is_vrf_present_in_irt_vrfs(irt->vrfs, bgp_vrf))
+               /* Already mapped. */
+               return;
 
-       if (!irt) {
+       if (!irt)
                irt = vrf_import_rt_new(&eval_tmp);
-               assert(irt);
-       }
 
        /* Add VRF to the list for this RT. */
        listnode_add(irt->vrfs, bgp_vrf);
@@ -3754,13 +3751,6 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
        u_char rlen;
        struct prefix p;
 
-       /* Check peer status. */
-       if (peer->status != Established) {
-               zlog_err("%u:%s - EVPN update received in state %d",
-                        peer->bgp->vrf_id, peer->host, peer->status);
-               return -1;
-       }
-
        /* Start processing the NLRI - there may be multiple in the MP_REACH */
        pnt = packet->nlri;
        lim = pnt + packet->length;
@@ -3990,7 +3980,7 @@ void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp)
        bgp->vrf_prd.family = AF_UNSPEC;
        bgp->vrf_prd.prefixlen = 64;
        sprintf(buf, "%s:%hu", inet_ntoa(bgp->router_id), bgp->vrf_rd_id);
-       str2prefix_rd(buf, &bgp->vrf_prd);
+       (void)str2prefix_rd(buf, &bgp->vrf_prd);
 }
 
 /*
index 3255aff2a8e080a41404139d5d9b66f2bc4bb995..e4a0a1d404ea50345fdcb4c497f277c9c90b6a38 100644 (file)
@@ -1377,7 +1377,7 @@ int bgp_start(struct peer *peer)
                return 0;
        }
 
-       if (peer->bgp && peer->bgp->vrf_id == VRF_UNKNOWN) {
+       if (peer->bgp->vrf_id == VRF_UNKNOWN) {
                if (bgp_debug_neighbor_events(peer))
                        zlog_err(
                                "%s [FSM] In a VRF that is not initialised yet",
index 38b39075be376b51aecdc46d1f61050b0274175e..546ed0ed6829818b5f3f55e6f8cadc1ac14b7b99 100644 (file)
@@ -212,10 +212,6 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
        mpls_label_t label = MPLS_INVALID_LABEL;
        u_char llen;
 
-       /* Check peer status. */
-       if (peer->status != Established)
-               return 0;
-
        pnt = packet->nlri;
        lim = pnt + packet->length;
        afi = packet->afi;
index d87f78a7830dae257675914d0a04229031de40ab..9f740db325c3b2e0753d1ae40089e90b711e11bd 100644 (file)
@@ -28,8 +28,8 @@
 #include "queue.h"
 #include "filter.h"
 #include "mpls.h"
-#include "lib/json.h"
-#include "lib/zclient.h"
+#include "json.h"
+#include "zclient.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_debug.h"
@@ -109,10 +109,6 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
        int addpath_encoded;
        u_int32_t addpath_id;
 
-       /* Check peer status. */
-       if (peer->status != Established)
-               return 0;
-
        /* Make prefix_rd */
        prd.family = AF_UNSPEC;
        prd.prefixlen = 64;
@@ -461,16 +457,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn,       /* to */
        struct bgp_node *bn;
        const char *debugmsg;
 
-       if (debug) {
-               const char *s = "";
-
-               if (info_vrf->attr && info_vrf->attr->ecommunity) {
-                       s = ecommunity_ecom2str(info_vrf->attr->ecommunity,
-                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               }
+       if (debug && info_vrf->attr->ecommunity) {
+               char *s = ecommunity_ecom2str(info_vrf->attr->ecommunity,
+                                             ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
                zlog_debug("%s: info_vrf->type=%d, EC{%s}", __func__,
                           info_vrf->type, s);
+               XFREE(MTYPE_ECOMMUNITY_STR, s);
        }
 
        if (!bgp_vpn)
@@ -521,15 +514,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn,       /* to */
                }
        }
 
-       if (debug) {
-               const char *s = "";
+       if (debug && static_attr.ecommunity) {
+               char *s = ecommunity_ecom2str(static_attr.ecommunity,
+                                             ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (static_attr.ecommunity) {
-                       s = ecommunity_ecom2str(static_attr.ecommunity,
-                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               }
                zlog_debug("%s: post route map static_attr.ecommunity{%s}",
                           __func__, s);
+               XFREE(MTYPE_ECOMMUNITY_STR, s);
        }
 
        /*
@@ -554,15 +545,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn,       /* to */
        static_attr.ecommunity = new_ecom;
        SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
 
-       if (debug) {
-               const char *s = "";
+       if (debug && static_attr.ecommunity) {
+               char *s = ecommunity_ecom2str(static_attr.ecommunity,
+                                             ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (static_attr.ecommunity) {
-                       s = ecommunity_ecom2str(static_attr.ecommunity,
-                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               }
                zlog_debug("%s: post merge static_attr.ecommunity{%s}",
                           __func__, s);
+               XFREE(MTYPE_ECOMMUNITY_STR, s);
        }
 
        /* Nexthop */
@@ -627,14 +616,12 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn,       /* to */
                &static_attr);  /* hashed refcounted everything */
        bgp_attr_flush(&static_attr); /* free locally-allocated parts */
 
-       if (debug) {
-               const char *s = "";
+       if (debug && new_attr->ecommunity) {
+               char *s = ecommunity_ecom2str(new_attr->ecommunity,
+                                             ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (new_attr->ecommunity) {
-                       s = ecommunity_ecom2str(new_attr->ecommunity,
-                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               }
                zlog_debug("%s: new_attr->ecommunity{%s}", __func__, s);
+               XFREE(MTYPE_ECOMMUNITY_STR, s);
        }
 
        /* Now new_attr is an allocated interned attr */
@@ -738,7 +725,6 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
        safi_t safi = SAFI_MPLS_VPN;
 
        /*
-        * Walk vpn table, delete bi with parent == bgp_vrf
         * Walk vpn table, delete bi with bgp_orig == bgp_vrf
         */
        for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn;
@@ -824,7 +810,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
        struct prefix *p = &info_vpn->net->p;
        afi_t afi = family2afi(p->family);
 
-       struct bgp_redist *red;
        struct attr static_attr = {0};
        struct attr *new_attr = NULL;
        struct bgp_node *bn;
@@ -836,7 +821,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
 
        int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
 
-       if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg, &red)) {
+       if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg)) {
                if (debug)
                        zlog_debug("%s: skipping: %s", __func__, debugmsg);
                return;
@@ -893,28 +878,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
 
        /*
         * route map handling
-        * For now, we apply two route maps: the "redist" route map and the
-        * vpn-policy route map. Once we finalize CLI syntax, one of these
-        * route maps will probably go away.
         */
-       if (red->rmap.map) {
-               struct bgp_info info;
-               route_map_result_t ret;
-
-               memset(&info, 0, sizeof(info));
-               info.peer = bgp_vrf->peer_self;
-               info.attr = &static_attr;
-               ret = route_map_apply(red->rmap.map, p, RMAP_BGP, &info);
-               if (RMAP_DENYMATCH == ret) {
-                       bgp_attr_flush(&static_attr); /* free any added parts */
-                       if (debug)
-                               zlog_debug(
-                                       "%s: vrf %s redist route map \"%s\" says DENY, skipping",
-                                       __func__, bgp_vrf->name,
-                                       red->rmap.name);
-                       return;
-               }
-       }
        if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
                struct bgp_info info;
                route_map_result_t ret;
@@ -989,12 +953,11 @@ void vpn_leak_to_vrf_update(struct bgp *bgp_vpn,       /* from */
 void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,       /* from */
                              struct bgp_info *info_vpn) /* route */
 {
-       struct prefix *p = &info_vpn->net->p;
-       afi_t afi = family2afi(p->family);
+       struct prefix *p;
+       afi_t afi;
        safi_t safi = SAFI_UNICAST;
        struct bgp *bgp;
        struct listnode *mnode, *mnnode;
-       struct bgp_redist *red;
        struct bgp_node *bn;
        struct bgp_info *bi;
        const char *debugmsg;
@@ -1004,10 +967,27 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,       /* from */
        if (debug)
                zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn);
 
+       if (!info_vpn->net) {
+#if ENABLE_BGP_VNC
+               /* BGP_ROUTE_RFP routes do not have info_vpn->net set (yet) */
+               if (info_vpn->type == ZEBRA_ROUTE_BGP &&
+                       info_vpn->sub_type == BGP_ROUTE_RFP) {
+
+                       return;
+               }
+#endif
+               if (debug)
+                       zlog_debug("%s: info_vpn->net unexpectedly NULL, no prefix, bailing",
+                               __func__);
+               return;
+       }
+
+       p = &info_vpn->net->p;
+       afi = family2afi(p->family);
 
        /* Loop over VRFs */
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
-               if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg, &red)) {
+               if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) {
                        if (debug)
                                zlog_debug("%s: skipping: %s", __func__,
                                           debugmsg);
@@ -1164,36 +1144,27 @@ static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
                                           __func__);
                }
 
-               /*
-                * vpn -> vrf leaking currently can have two route-maps:
-                * 1. the vpn-policy tovpn route-map
-                * 2. the (per-afi) redistribute vpn route-map
-                */
-               char *mapname_vpn_policy =
-                       bgp->vpn_policy[afi]
-                               .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN];
-               struct bgp_redist *red = NULL;
-
-               if (vpn_leak_from_vpn_active(bgp, afi, NULL, &red)
-                   && ((mapname_vpn_policy
-                        && !strcmp(rmap_name, mapname_vpn_policy))
-                       || (red && red->rmap.name
-                           && !strcmp(red->rmap.name, rmap_name)))) {
+               char *mapname = bgp->vpn_policy[afi]
+                       .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN];
 
-                       if (debug)
-                               zlog_debug(
-                                       "%s: rmap \"%s\" matches vrf-policy fromvpn"
-                                       " for as %d afi %s",
+               if (vpn_leak_from_vpn_active(bgp, afi, NULL) &&
+                       mapname &&
+                       !strcmp(rmap_name, mapname))  {
+
+                       if (debug) {
+                               zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
                                        __func__, rmap_name, bgp->as,
                                        afi2str(afi));
+                       }
 
                        vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
                                           bgp_get_default(), bgp);
 
-                       if (!rmap)
+                       if (!rmap) {
                                bgp->vpn_policy[afi]
                                        .rmap[BGP_VPN_POLICY_DIR_FROMVPN] =
                                        NULL;
+                       }
 
                        vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
                                            bgp_get_default(), bgp);
index d0ad8ac8462b7fb20573c1fb62c9590682fae18e..d35568b8385729179bc79c179ada30deea2d4935 100644 (file)
@@ -81,6 +81,14 @@ extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
 static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
                                         const char **pmsg)
 {
+       if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
+               && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+
+               if (pmsg)
+                       *pmsg = "source bgp instance neither vrf nor default";
+               return 0;
+       }
+
        /* Is vrf configured to export to vpn? */
        if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
                        BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
@@ -107,27 +115,21 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
 }
 
 static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
-                                          const char **pmsg,
-                                          struct bgp_redist **pred)
+                                          const char **pmsg)
 {
-       struct bgp_redist *red;
-
        if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
-           && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+               && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
 
                if (pmsg)
                        *pmsg = "destination bgp instance neither vrf nor default";
                return 0;
        }
 
-       /* Hijack zebra redist bits for this route type */
-       red = bgp_redist_lookup(bgp_vrf, afi, ZEBRA_ROUTE_BGP_VPN, 0);
-       if (red) {
-               if (pred)
-                       *pred = red;
-       } else {
+       /* Is vrf configured to import from vpn? */
+       if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+                       BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
                if (pmsg)
-                       *pmsg = "redist not set";
+                       *pmsg = "import not set";
                return 0;
        }
        if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
@@ -142,10 +144,16 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
                                      afi_t afi, struct bgp *bgp_vpn,
                                      struct bgp *bgp_vrf)
 {
-       if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
+       if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
+               vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
+
                vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
-       if (direction == BGP_VPN_POLICY_DIR_TOVPN)
+       }
+       if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
+               vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
+
                vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
+       }
 }
 
 static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
@@ -156,16 +164,14 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
                vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
        if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
 
-               if (bgp_vrf->vpn_policy[afi].tovpn_label
-                   != bgp_vrf->vpn_policy[afi]
+               if (bgp_vrf->vpn_policy[afi].tovpn_label !=
+                       bgp_vrf->vpn_policy[afi]
                               .tovpn_zebra_vrf_label_last_sent) {
                        vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
                }
 
                vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
        }
-       if (direction == BGP_VPN_POLICY_DIR_TOVPN)
-               vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
 }
 
 extern void vpn_policy_routemap_event(const char *rmap_name);
index 71454dfe03c15ef72fda0e58e3afb7e98c98a429..37d06c1e53ad9373a07a692ca7b7b715cfedbed1 100644 (file)
@@ -447,6 +447,9 @@ static char *bgp_get_bound_name(struct peer *peer)
 {
        char *name = NULL;
 
+       if (!peer)
+               return NULL;
+
        if ((peer->bgp->vrf_id == VRF_DEFAULT) && !peer->ifname
            && !peer->conf_if)
                return NULL;
@@ -455,8 +458,6 @@ static char *bgp_get_bound_name(struct peer *peer)
            && peer->su.sa.sa_family != AF_INET6)
                return NULL; // unexpected
 
-       if (!peer)
-               return name;
        /* For IPv6 peering, interface (unnumbered or link-local with interface)
         * takes precedence over VRF. For IPv4 peering, explicit interface or
         * VRF are the situations to bind.
index cb702d80d1f1fd7f8afe97db90ece96fb56098ce..d17c33441982be008536d1a6238cf2cd770b5695 100644 (file)
@@ -389,7 +389,7 @@ int bgp_generate_updgrp_packets(struct thread *thread)
        if (peer->status != Established)
                return 0;
 
-       if (peer->bgp && peer->bgp->main_peers_update_hold)
+       if (peer->bgp->main_peers_update_hold)
                return 0;
 
        do {
index 032b33229cdec58b92a89b08990c064925f4a9b3..41dff0a7e2ce45b40a4a2ce0093a5af8c6553add 100644 (file)
@@ -2095,6 +2095,25 @@ struct bgp_process_queue {
        unsigned int queued;
 };
 
+/*
+ * old_select = The old best path
+ * new_select = the new best path
+ *
+ * if (!old_select && new_select)
+ *     We are sending new information on.
+ *
+ * if (old_select && new_select) {
+ *         if (new_select != old_select)
+ *                 We have a new best path send a change
+ *         else
+ *                 We've received a update with new attributes that needs
+ *                 to be passed on.
+ * }
+ *
+ * if (old_select && !new_select)
+ *     We have no eligible route that we can announce or the rn
+ *     is being removed.
+ */
 static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                                 afi_t afi, safi_t safi)
 {
@@ -2294,7 +2313,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                                || old_select->sub_type == BGP_ROUTE_AGGREGATE
                                || old_select->sub_type == BGP_ROUTE_IMPORTED))
 
-                               bgp_zebra_withdraw(p, old_select, safi);
+                               bgp_zebra_withdraw(p, old_select, bgp, safi);
                }
        }
 
@@ -3664,10 +3683,12 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
        struct bgp_node *rn = cnq->rn;
        struct peer *peer = wq->spec.data;
        struct bgp_info *ri;
+       struct bgp *bgp;
        afi_t afi = bgp_node_table(rn)->afi;
        safi_t safi = bgp_node_table(rn)->safi;
 
        assert(rn && peer);
+       bgp = peer->bgp;
 
        /* It is possible that we have multiple paths for a prefix from a peer
         * if that peer is using AddPath.
@@ -3686,8 +3707,18 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
                        /* If this is an EVPN route, process for
                         * un-import. */
                        if (safi == SAFI_EVPN)
-                               bgp_evpn_unimport_route(peer->bgp, afi, safi,
+                               bgp_evpn_unimport_route(bgp, afi, safi,
                                                        &rn->p, ri);
+                       /* Handle withdraw for VRF route-leaking and L3VPN */
+                       if (SAFI_UNICAST == safi
+                           && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
+                               bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT))
+                               vpn_leak_from_vrf_withdraw(bgp_get_default(),
+                                                          bgp, ri);
+                       if (SAFI_MPLS_VPN == safi &&
+                           bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+                               vpn_leak_to_vrf_withdraw(bgp, ri);
+
                        bgp_rib_remove(rn, ri, peer, afi, safi);
                }
        }
@@ -3953,7 +3984,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
        }
 }
 
-static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
+static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
+                             safi_t safi)
 {
        struct bgp_node *rn;
        struct bgp_info *ri;
@@ -3969,7 +4001,8 @@ static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
                                || ri->sub_type == BGP_ROUTE_IMPORTED)) {
 
                                if (bgp_fibupd_safi(safi))
-                                       bgp_zebra_withdraw(&rn->p, ri, safi);
+                                       bgp_zebra_withdraw(&rn->p, ri,
+                                                          bgp, safi);
                                bgp_info_reap(rn, ri);
                        }
                }
@@ -3984,7 +4017,8 @@ void bgp_cleanup_routes(struct bgp *bgp)
        for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
                if (afi == AFI_L2VPN)
                        continue;
-               bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
+               bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
+                                 SAFI_UNICAST);
                /*
                 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
                 */
@@ -3994,7 +4028,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
                        for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
                             rn = bgp_route_next(rn)) {
                                if (rn->info) {
-                                       bgp_cleanup_table(
+                                       bgp_cleanup_table(bgp,
                                                (struct bgp_table *)(rn->info),
                                                safi);
                                        bgp_table_finish((struct bgp_table **)&(
@@ -4007,7 +4041,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
                        for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
                             rn = bgp_route_next(rn)) {
                                if (rn->info) {
-                                       bgp_cleanup_table(
+                                       bgp_cleanup_table(bgp,
                                                (struct bgp_table *)(rn->info),
                                                safi);
                                        bgp_table_finish((struct bgp_table **)&(
@@ -4021,7 +4055,8 @@ void bgp_cleanup_routes(struct bgp *bgp)
        for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
             rn = bgp_route_next(rn)) {
                if (rn->info) {
-                       bgp_cleanup_table((struct bgp_table *)(rn->info),
+                       bgp_cleanup_table(bgp,
+                                         (struct bgp_table *)(rn->info),
                                          SAFI_EVPN);
                        bgp_table_finish((struct bgp_table **)&(rn->info));
                        rn->info = NULL;
@@ -4060,10 +4095,6 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
        int addpath_encoded;
        u_int32_t addpath_id;
 
-       /* Check peer status. */
-       if (peer->status != Established)
-               return 0;
-
        pnt = packet->nlri;
        lim = pnt + packet->length;
        afi = packet->afi;
index 4a5633c94d07f706c0dcee53fef08d324690614c..ad6f1a558873f4d02f03409715261915a4a04608 100644 (file)
@@ -6112,74 +6112,63 @@ ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as,
             NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
             "Use addpath to advertise the bestpath per each neighboring AS\n")
 
-
-DEFUN_NOSH (vpn_policy_afi,
-       vpn_policy_afi_cmd,
-       "vpn-policy <ipv4|ipv6>",
-       "Enter vpn-policy command mode\n"
-       BGP_AFI_HELP_STR)
+static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
+                        struct ecommunity **list)
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF
-           && bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+       struct ecommunity *ecom = NULL;
+       struct ecommunity *ecomadd;
 
-               vty_out(vty,
-                       "vpn-policy supported only in core or vrf instances.\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
+       for (; argc; --argc, ++argv) {
 
-       afi_t afi;
-       int idx = 0;
+               ecomadd = ecommunity_str2com(argv[0]->arg,
+                                            ECOMMUNITY_ROUTE_TARGET, 0);
+               if (!ecomadd) {
+                       vty_out(vty, "Malformed community-list value\n");
+                       if (ecom)
+                               ecommunity_free(&ecom);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
 
-       if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
-               if (afi == AFI_IP)
-                       vty->node = BGP_VPNPOLICY_IPV4_NODE;
-               else
-                       vty->node = BGP_VPNPOLICY_IPV6_NODE;
-               return CMD_SUCCESS;
+               if (ecom) {
+                       ecommunity_merge(ecom, ecomadd);
+                       ecommunity_free(&ecomadd);
+               } else {
+                       ecom = ecomadd;
+               }
+       }
+
+       if (*list) {
+               ecommunity_free(&*list);
        }
-       return CMD_WARNING_CONFIG_FAILED;
+       *list = ecom;
+
+       return CMD_SUCCESS;
 }
 
-static int vpn_policy_afis(struct vty *vty, int *doafi)
+static int vpn_policy_getafi(struct vty *vty, int *doafi)
 {
        switch (vty->node) {
-       case BGP_VPNPOLICY_IPV4_NODE:
+       case BGP_IPV4_NODE:
                doafi[AFI_IP] = 1;
                break;
-       case BGP_VPNPOLICY_IPV6_NODE:
+       case BGP_IPV6_NODE:
                doafi[AFI_IP6] = 1;
                break;
        default:
                vty_out(vty,
-                       "%% context error: valid only in vpn-policy block\n");
+                       "%% context error: valid only in address-family <ipv4|ipv6> unicast block\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
        return CMD_SUCCESS;
 }
 
-static int argv_find_and_parse_vpn_policy_dirs(struct vty *vty,
-                                              struct cmd_token **argv,
-                                              int argc, int *idx, int *dodir)
-{
-       if (argv_find(argv, argc, "fromvpn", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
-       } else if (argv_find(argv, argc, "tovpn", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
-       } else if (argv_find(argv, argc, "both", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
-               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
-       } else {
-               vty_out(vty, "%% direction parse error\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       return CMD_SUCCESS;
-}
-
-DEFUN (vpn_policy_rd,
-       vpn_policy_rd_cmd,
-       "rd ASN:NN_OR_IP-ADDRESS:NN",
+DEFPY (af_rd_vpn_export,
+       af_rd_vpn_export_cmd,
+       "[no] rd vpn export ASN:NN_OR_IP-ADDRESS:NN$rd_str",
+       NO_STR
        "Specify route distinguisher\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "Route Distinguisher (<as-number>:<number> | <ip-address>:<number>)\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6187,14 +6176,21 @@ DEFUN (vpn_policy_rd,
        int ret;
        int doafi[AFI_MAX] = {0};
        afi_t afi;
+       int idx = 0;
+       int yes = 1;
 
-       ret = str2prefix_rd(argv[1]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed rd\n");
-               return CMD_WARNING_CONFIG_FAILED;
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
+
+       if (yes) {
+               ret = str2prefix_rd(rd_str, &prd);
+               if (!ret) {
+                       vty_out(vty, "%% Malformed rd\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
        }
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6208,9 +6204,14 @@ DEFUN (vpn_policy_rd,
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
 
-               bgp->vpn_policy[afi].tovpn_rd = prd;
-               SET_FLAG(bgp->vpn_policy[afi].flags,
-                        BGP_VPN_POLICY_TOVPN_RD_SET);
+               if (yes) {
+                       bgp->vpn_policy[afi].tovpn_rd = prd;
+                       SET_FLAG(bgp->vpn_policy[afi].flags,
+                                BGP_VPN_POLICY_TOVPN_RD_SET);
+               } else {
+                       UNSET_FLAG(bgp->vpn_policy[afi].flags,
+                                  BGP_VPN_POLICY_TOVPN_RD_SET);
+               }
 
                /* post-change: re-export vpn routes */
                vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
@@ -6220,57 +6221,38 @@ DEFUN (vpn_policy_rd,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_rd,
-       vpn_policy_no_rd_cmd,
-       "no rd",
+ALIAS (af_rd_vpn_export,
+       af_no_rd_vpn_export_cmd,
+       "no rd vpn export",
        NO_STR
-       "Specify route distinguisher\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               UNSET_FLAG(bgp->vpn_policy[afi].flags,
-                          BGP_VPN_POLICY_TOVPN_RD_SET);
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+       "Specify route distinguisher\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-DEFUN (vpn_policy_label,
-       vpn_policy_label_cmd,
-       "label (0-1048575)",
+DEFPY (af_label_vpn_export,
+       af_label_vpn_export_cmd,
+       "[no] label vpn export (0-1048575)$label_val",
+       NO_STR
        "label value for VRF\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "Label Value <0-1048575>\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
-       mpls_label_t label;
+       mpls_label_t label = MPLS_LABEL_NONE;
        int doafi[AFI_MAX] = {0};
        afi_t afi;
        int ret;
+       int idx = 0;
+       int yes = 1;
 
-       label = strtoul(argv[1]->arg, NULL, 10);
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
 
-       ret = vpn_policy_afis(vty, doafi);
+       if (yes)
+               label = label_val; /* rely on parser to force unsigned */
+
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6278,7 +6260,8 @@ DEFUN (vpn_policy_label,
                if (!doafi[afi])
                        continue;
 
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+               /*
+                * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
                 */
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
@@ -6293,44 +6276,21 @@ DEFUN (vpn_policy_label,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_label,
-       vpn_policy_no_label_cmd,
-       "no label",
-       "Negate a command or set its defaults\n"
-       "label value for VRF\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-       int ret;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+ALIAS (af_label_vpn_export,
+       af_no_label_vpn_export_cmd,
+       "no label vpn export",
+       NO_STR
+       "label value for VRF\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-DEFPY (vpn_policy_nexthop,
-       vpn_policy_nexthop_cmd,
-       "nexthop <A.B.C.D|X:X::X:X>$nexthop",
+DEFPY (af_nexthop_vpn_export,
+       af_nexthop_vpn_export_cmd,
+       "[no] nexthop vpn export <A.B.C.D|X:X::X:X>$nexthop_str",
+       NO_STR
        "Specify next hop to use for VRF advertised prefixes\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "IPv4 prefix\n"
        "IPv6 prefix\n")
 {
@@ -6339,11 +6299,18 @@ DEFPY (vpn_policy_nexthop,
        afi_t afi;
        int ret;
        struct prefix p;
+       int idx = 0;
+       int yes = 1;
 
-       if (!sockunion2hostprefix(nexthop, &p))
-               return CMD_WARNING_CONFIG_FAILED;
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
+
+       if (yes) {
+               if (!sockunion2hostprefix(nexthop_str, &p))
+                       return CMD_WARNING_CONFIG_FAILED;
+       }
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6357,9 +6324,14 @@ DEFPY (vpn_policy_nexthop,
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
 
-               bgp->vpn_policy[afi].tovpn_nexthop = p;
-               SET_FLAG(bgp->vpn_policy[afi].flags,
-                        BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               if (yes) {
+                       bgp->vpn_policy[afi].tovpn_nexthop = p;
+                       SET_FLAG(bgp->vpn_policy[afi].flags,
+                                BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               } else {
+                       UNSET_FLAG(bgp->vpn_policy[afi].flags,
+                                  BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               }
 
                /* post-change: re-export vpn routes */
                vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
@@ -6369,81 +6341,40 @@ DEFPY (vpn_policy_nexthop,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_nexthop,
-       vpn_policy_no_nexthop_cmd,
-       "no nexthop",
+ALIAS (af_nexthop_vpn_export,
+       af_no_nexthop_vpn_export_cmd,
+       "no nexthop vpn export",
        NO_STR
-       "Specify next hop to use for VRF advertised prefixes\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-       int ret;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               UNSET_FLAG(bgp->vpn_policy[afi].flags,
-                          BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+       "Specify next hop to use for VRF advertised prefixes\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
-                        struct ecommunity **list)
+static int vpn_policy_getdirs(struct vty *vty, const char *dstr, int *dodir)
 {
-       struct ecommunity *ecom = NULL;
-       struct ecommunity *ecomadd;
-
-       for (; argc; --argc, ++argv) {
-
-               ecomadd = ecommunity_str2com(argv[0]->arg,
-                                            ECOMMUNITY_ROUTE_TARGET, 0);
-               if (!ecomadd) {
-                       vty_out(vty, "Malformed community-list value\n");
-                       if (ecom)
-                               ecommunity_free(&ecom);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               if (ecom) {
-                       ecommunity_merge(ecom, ecomadd);
-                       ecommunity_free(&ecomadd);
-               } else {
-                       ecom = ecomadd;
-               }
-       }
-
-       if (*list) {
-               ecommunity_free(&*list);
+       if (!strcmp(dstr, "import")) {
+               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+       } else if (!strcmp(dstr, "export")) {
+               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+       } else if (!strcmp(dstr, "both")) {
+               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+       } else {
+               vty_out(vty, "%% direction parse error\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
-       *list = ecom;
-
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_rt,
-       vpn_policy_rt_cmd,
-       "rt <fromvpn|tovpn|both> RTLIST...",
+DEFPY (af_rt_vpn_imexport,
+       af_rt_vpn_imexport_cmd,
+       "[no] <rt|route-target> vpn <import|export|both>$direction_str RTLIST...",
+       NO_STR
        "Specify route target list\n"
-       "fromvpn: match any\n"
-       "tovpn: set\n"
-       "both fromvpn: match any and tovpn: set\n"
+       "Specify route target list\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family: match any\n"
+       "For routes leaked from current address-family to vpn: set\n"
+       "both import: match any and export: set\n"
        "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6454,18 +6385,28 @@ DEFUN (vpn_policy_rt,
        vpn_policy_direction_t dir;
        afi_t afi;
        int idx = 0;
+       int yes = 1;
+
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
+       ret = vpn_policy_getdirs(vty, direction_str, dodir);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = set_ecom_list(vty, argc - 2, argv + 2, &ecom);
-       if (ret != CMD_SUCCESS) {
-               return ret;
+       if (yes) {
+               if (!argv_find(argv, argc, "RTLIST", &idx)) {
+                       vty_out(vty, "%% Missing RTLIST\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+               ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom);
+               if (ret != CMD_SUCCESS) {
+                       return ret;
+               }
        }
 
        for (afi = 0; afi < AFI_MAX; ++afi) {
@@ -6477,71 +6418,48 @@ DEFUN (vpn_policy_rt,
 
                        vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
 
-                       if (bgp->vpn_policy[afi].rtlist[dir])
-                               ecommunity_free(
-                                       &bgp->vpn_policy[afi].rtlist[dir]);
-                       bgp->vpn_policy[afi].rtlist[dir] = ecommunity_dup(ecom);
+                       if (yes) {
+                               if (bgp->vpn_policy[afi].rtlist[dir])
+                                       ecommunity_free(
+                                           &bgp->vpn_policy[afi].rtlist[dir]);
+                               bgp->vpn_policy[afi].rtlist[dir] =
+                                       ecommunity_dup(ecom);
+                       } else {
+                               if (bgp->vpn_policy[afi].rtlist[dir])
+                                       ecommunity_free(
+                                           &bgp->vpn_policy[afi].rtlist[dir]);
+                               bgp->vpn_policy[afi].rtlist[dir] = NULL;
+                       }
 
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
        }
-       ecommunity_free(&ecom);
+       if (ecom)
+               ecommunity_free(&ecom);
 
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_rt,
-       vpn_policy_no_rt_cmd,
-       "no rt <fromvpn|tovpn|both>",
+ALIAS (af_rt_vpn_imexport,
+       af_no_rt_vpn_imexport_cmd,
+       "no <rt|route-target> vpn <import|export|both>$direction_str",
        NO_STR
        "Specify route target list\n"
-       "fromvpn: match any\n"
-       "tovpn: set\n"
-       "both fromvpn: match any and tovpn: set\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
-       int doafi[AFI_MAX] = {0};
-       vpn_policy_direction_t dir;
-       afi_t afi;
-       int idx = 0;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-               for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
-                       if (!dodir[dir])
-                               continue;
-
-                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
-
-                       if (bgp->vpn_policy[afi].rtlist[dir])
-                               ecommunity_free(
-                                       &bgp->vpn_policy[afi].rtlist[dir]);
-                       bgp->vpn_policy[afi].rtlist[dir] = NULL;
-
-                       vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
-               }
-       }
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (vpn_policy_route_map,
-       vpn_policy_route_map_cmd,
-       "route-map <fromvpn|tovpn> WORD",
+       "Specify route target list\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n"
+       "both import and export\n")
+
+DEFPY (af_route_map_vpn_imexport,
+       af_route_map_vpn_imexport_cmd,
+/* future: "route-map <vpn|evpn|vrf NAME> <import|export> RMAP" */
+       "[no] route-map vpn <import|export>$direction_str RMAP$rmap_str",
+       NO_STR
        "Specify route map\n"
-       "fromvpn: core vpn -> this vrf\n"
-       "tovpn: this vrf -> core vpn\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n"
        "name of route-map\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6550,14 +6468,17 @@ DEFUN (vpn_policy_route_map,
        int doafi[AFI_MAX] = {0};
        vpn_policy_direction_t dir;
        afi_t afi;
-       int map_name_arg = 2;
        int idx = 0;
+       int yes = 1;
+
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
+       ret = vpn_policy_getdirs(vty, direction_str, dodir);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6570,14 +6491,21 @@ DEFUN (vpn_policy_route_map,
 
                        vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
 
-                       if (bgp->vpn_policy[afi].rmap_name[dir])
-                               XFREE(MTYPE_ROUTE_MAP_NAME,
-                                     bgp->vpn_policy[afi].rmap_name[dir]);
-                       bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
-                               MTYPE_ROUTE_MAP_NAME, argv[map_name_arg]->arg);
-                       bgp->vpn_policy[afi].rmap[dir] =
-                               route_map_lookup_by_name(
-                                       argv[map_name_arg]->arg);
+                       if (yes) {
+                               if (bgp->vpn_policy[afi].rmap_name[dir])
+                                       XFREE(MTYPE_ROUTE_MAP_NAME,
+                                       bgp->vpn_policy[afi].rmap_name[dir]);
+                               bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
+                                       MTYPE_ROUTE_MAP_NAME, rmap_str);
+                               bgp->vpn_policy[afi].rmap[dir] =
+                                       route_map_lookup_by_name(rmap_str);
+                       } else {
+                               if (bgp->vpn_policy[afi].rmap_name[dir])
+                                       XFREE(MTYPE_ROUTE_MAP_NAME,
+                                       bgp->vpn_policy[afi].rmap_name[dir]);
+                               bgp->vpn_policy[afi].rmap_name[dir] = NULL;
+                               bgp->vpn_policy[afi].rmap[dir] = NULL;
+                       }
 
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
@@ -6586,47 +6514,75 @@ DEFUN (vpn_policy_route_map,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_route_map,
-       vpn_policy_no_route_map_cmd,
-       "no route-map <fromvpn|tovpn>",
+ALIAS (af_route_map_vpn_imexport,
+       af_no_route_map_vpn_imexport_cmd,
+       "no route-map vpn <import|export>$direction_str",
        NO_STR
        "Specify route map\n"
-       "fromvpn: core vpn -> this vrf\n"
-       "tovpn: this vrf -> core vpn\n")
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n")
+
+/* This command is valid only in a bgp vrf instance or the default instance */
+DEFPY (bgp_imexport_vpn,
+       bgp_imexport_vpn_cmd,
+       "[no] <import|export>$direction_str vpn",
+       NO_STR
+       "Import routes to this address-family\n"
+       "Export routes from this address-family\n"
+       "to/from default instance VPN RIB\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
-       int doafi[AFI_MAX] = {0};
-       vpn_policy_direction_t dir;
+       int previous_state;
        afi_t afi;
+       safi_t safi;
        int idx = 0;
+       int yes = 1;
+       int flag;
+       vpn_policy_direction_t dir;
 
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
-       if (ret != CMD_SUCCESS)
-               return ret;
+       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type &&
+               BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
 
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-               for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
-                       if (!dodir[dir])
-                               continue;
+               vty_out(vty, "%% import|export vpn valid only for bgp vrf or default instance\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
+       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
+               vty_out(vty, "%% import|export vpn valid only for unicast ipv4|ipv6\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (!strcmp(direction_str, "import")) {
+               flag = BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT;
+               dir = BGP_VPN_POLICY_DIR_FROMVPN;
+       } else if (!strcmp(direction_str, "export")) {
+               flag = BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT;
+               dir = BGP_VPN_POLICY_DIR_TOVPN;
+       } else {
+               vty_out(vty, "%% unknown direction %s\n", direction_str);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-                       if (bgp->vpn_policy[afi].rmap_name[dir])
-                               XFREE(MTYPE_ROUTE_MAP_NAME,
-                                     bgp->vpn_policy[afi].rmap_name[dir]);
-                       bgp->vpn_policy[afi].rmap_name[dir] = NULL;
-                       bgp->vpn_policy[afi].rmap[dir] = NULL;
+       previous_state = CHECK_FLAG(bgp->af_flags[afi][safi], flag);
 
+       if (yes) {
+               SET_FLAG(bgp->af_flags[afi][safi], flag);
+               if (!previous_state) {
+                       /* trigger export current vrf */
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
+       } else {
+               if (previous_state) {
+                       /* trigger un-export current vrf */
+                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+               }
+               UNSET_FLAG(bgp->af_flags[afi][safi], flag);
        }
 
        return CMD_SUCCESS;
@@ -11659,99 +11615,20 @@ void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
        }
 }
 
-/* This command is valid only in a bgp vrf instance or the default instance */
-DEFUN (bgp_export_vpn,
-       bgp_export_vpn_cmd,
-       "export vpn",
-       "Export routes to another routing protocol\n"
-       "to VPN RIB per vpn-policy")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int was_off = 0;
-       afi_t afi;
-       safi_t safi;
-
-       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
-           && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
-               vty_out(vty,
-                       "%% export vpn valid only for bgp vrf or default instance\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
-               vty_out(vty,
-                       "%% export vpn valid only for unicast ipv4|ipv6\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (!CHECK_FLAG(bgp->af_flags[afi][safi],
-                       BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
-               was_off = 1;
-       }
-       SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
-       if (was_off) {
-               /* trigger export current vrf */
-               zlog_debug("%s: calling postchange", __func__);
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-       return CMD_SUCCESS;
-}
-
-DEFUN (bgp_no_export_vpn,
-       bgp_no_export_vpn_cmd,
-       "no export vpn",
-       NO_STR
-       "Export routes to another routing protocol\n"
-       "to VPN RIB per vpn-policy")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int was_on = 0;
-       afi_t afi;
-       safi_t safi;
-
-       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
-           && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
-               vty_out(vty,
-                       "%% export vpn valid only for bgp vrf or default instance\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
-               vty_out(vty,
-                       "%% export vpn valid only for unicast ipv4|ipv6\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                      BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
-               was_on = 1;
-       }
-       if (was_on) {
-               /* trigger un-export current vrf */
-               zlog_debug("%s: calling postchange", __func__);
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-       }
-       UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
-       return CMD_SUCCESS;
-}
-
-static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
+/* This is part of the address-family block (unicast only) */
+void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                            afi_t afi)
 {
-       vty_frame(vty, " vpn-policy ipv%d\n", ((afi == AFI_IP) ? 4 : 6));
+       int indent = 2;
 
        if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
-               vty_out(vty, "    label %u\n",
+               vty_out(vty, "%*slabel vpn export %u\n", indent, "",
                        bgp->vpn_policy[afi].tovpn_label);
        }
        if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
                       BGP_VPN_POLICY_TOVPN_RD_SET)) {
                char buf[RD_ADDRSTRLEN];
-               vty_out(vty, "    rd %s\n",
+               vty_out(vty, "%*srd vpn export %s\n", indent, "",
                        prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
                                      sizeof(buf)));
        }
@@ -11763,7 +11640,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                              &bgp->vpn_policy[afi].tovpn_nexthop.u.prefix, buf,
                              sizeof(buf))) {
 
-                       vty_out(vty, "    nexthop %s\n", buf);
+                       vty_out(vty, "%*snexthop vpn export %s\n",
+                               indent, "", buf);
                }
        }
        if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]
@@ -11775,7 +11653,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                char *b = ecommunity_ecom2str(
                        bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN],
                        ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
-               vty_out(vty, "    rt both %s\n", b);
+               vty_out(vty, "%*srt vpn both %s\n", indent, "", b);
                XFREE(MTYPE_ECOMMUNITY_STR, b);
        } else {
                if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
@@ -11784,7 +11662,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                        .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
                                ECOMMUNITY_FORMAT_ROUTE_MAP,
                                ECOMMUNITY_ROUTE_TARGET);
-                       vty_out(vty, "    rt fromvpn %s\n", b);
+                       vty_out(vty, "%*srt vpn import %s\n", indent, "", b);
                        XFREE(MTYPE_ECOMMUNITY_STR, b);
                }
                if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
@@ -11793,28 +11671,21 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                        .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
                                ECOMMUNITY_FORMAT_ROUTE_MAP,
                                ECOMMUNITY_ROUTE_TARGET);
-                       vty_out(vty, "    rt tovpn %s\n", b);
+                       vty_out(vty, "%*srt vpn export %s\n", indent, "", b);
                        XFREE(MTYPE_ECOMMUNITY_STR, b);
                }
        }
        if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) {
-               vty_out(vty, "    route-map fromvpn %s\n",
+               vty_out(vty, "%*sroute-map vpn import %s\n", indent, "",
                        bgp->vpn_policy[afi]
                                .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]);
        }
        if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]) {
-               vty_out(vty, "    route-map tovpn %s\n",
+               vty_out(vty, "%*sroute-map vpn export %s\n", indent, "",
                        bgp->vpn_policy[afi]
                                .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]);
        }
 
-       vty_endframe(vty, " exit\n");
-}
-
-void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp)
-{
-       bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP);
-       bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP6);
 }
 
 
@@ -11859,12 +11730,6 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
 static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
                                            "%s(config-router-af-vni)# ", 1};
 
-static struct cmd_node bgp_vpn_policy_ipv4_node = {
-       BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1};
-
-static struct cmd_node bgp_vpn_policy_ipv6_node = {
-       BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1};
-
 static void community_list_vty(void);
 
 static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
@@ -11925,8 +11790,6 @@ void bgp_vty_init(void)
        install_node(&bgp_vpnv6_node, NULL);
        install_node(&bgp_evpn_node, NULL);
        install_node(&bgp_evpn_vni_node, NULL);
-       install_node(&bgp_vpn_policy_ipv4_node, NULL);
-       install_node(&bgp_vpn_policy_ipv6_node, NULL);
 
        /* Install default VTY commands to new nodes.  */
        install_default(BGP_NODE);
@@ -11940,8 +11803,6 @@ void bgp_vty_init(void)
        install_default(BGP_VPNV6_NODE);
        install_default(BGP_EVPN_NODE);
        install_default(BGP_EVPN_VNI_NODE);
-       install_default(BGP_VPNPOLICY_IPV4_NODE);
-       install_default(BGP_VPNPOLICY_IPV6_NODE);
 
        /* "bgp multiple-instance" commands. */
        install_element(CONFIG_NODE, &bgp_multiple_instance_cmd);
@@ -13001,11 +12862,9 @@ void bgp_vty_init(void)
        install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
        install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
 
-       /* export vpn [route-map WORD] */
-       install_element(BGP_IPV4_NODE, &bgp_export_vpn_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_export_vpn_cmd);
-       install_element(BGP_IPV4_NODE, &bgp_no_export_vpn_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_no_export_vpn_cmd);
+       /* import|export vpn [route-map WORD] */
+       install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
+       install_element(BGP_IPV6_NODE, &bgp_imexport_vpn_cmd);
 
        /* ttl_security commands */
        install_element(BGP_NODE, &neighbor_ttl_security_cmd);
@@ -13027,28 +12886,27 @@ void bgp_vty_init(void)
        community_list_vty();
 
        /* vpn-policy commands */
-       install_element(BGP_NODE, &vpn_policy_afi_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_route_map_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_route_map_cmd);
-
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_route_map_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_route_map_cmd);
+       install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_label_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_label_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV4_NODE, &af_route_map_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_route_map_vpn_imexport_cmd);
+
+       install_element(BGP_IPV4_NODE, &af_no_rd_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_rd_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_label_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_label_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_route_map_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd);
 }
 
 #include "memory.h"
index 459c4ffcc3a293d26102eb85062fc5baa5b0f310..f77ebb610e3fec0f35d8a54ee593792e2d1d7ebe 100644 (file)
@@ -71,5 +71,6 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
                                               safi_t *safi, struct bgp **bgp);
 extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
                                safi_t safi, u_char use_json);
-extern void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp);
+extern void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
+                                           afi_t afi);
 #endif /* _QUAGGA_BGP_VTY_H */
index cba3811e11fc1508ecf9c3971b0da4f7ca994454..bc6ee73da8d5d7e4539b7b6eb7bb41b2bfd72a83 100644 (file)
@@ -1303,7 +1303,8 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
                                                   safi);
 }
 
-void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
+void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
+                       struct bgp *bgp, safi_t safi)
 {
        struct zapi_route api;
        struct peer *peer;
@@ -1329,12 +1330,12 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
        /* Don't try to install if we're not connected to Zebra or Zebra doesn't
         * know of this instance.
         */
-       if (!bgp_install_info_to_zebra(peer->bgp))
+       if (!bgp_install_info_to_zebra(bgp))
                return;
 
        memset(&api, 0, sizeof(api));
        memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
-       api.vrf_id = peer->bgp->vrf_id;
+       api.vrf_id = bgp->vrf_id;
        api.type = ZEBRA_ROUTE_BGP;
        api.safi = safi;
        api.prefix = *p;
@@ -1353,14 +1354,14 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
 
        if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
            || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
-           || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+           || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
                SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
 
        if (bgp_debug_zebra(p)) {
                char buf[PREFIX_STRLEN];
 
                prefix2str(&api.prefix, buf, sizeof(buf));
-               zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf);
+               zlog_debug("Tx route delete VRF %u %s", bgp->vrf_id, buf);
        }
 
        zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
@@ -1445,27 +1446,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance)
                }
 #endif
 
-               /* vpn -> vrf (happens within bgp but we hijack redist bits */
-               if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-                    || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-                   && type == ZEBRA_ROUTE_BGP_VPN) {
-
-                       /* leak update all */
-                       vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                          bgp_get_default(), bgp);
-               }
-
                vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
-
-               /* vpn -> vrf (happens within bgp but we hijack redist bits */
-               if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-                    || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-                   && type == ZEBRA_ROUTE_BGP_VPN) {
-
-                       /* leak update all */
-                       vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                           bgp_get_default(), bgp);
-               }
        }
 
        /*
@@ -1619,15 +1600,6 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
                vnc_export_bgp_disable(bgp, afi);
        }
 #endif
-       /* vpn -> vrf (happend within bgp but we hijack redist bits */
-       if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-            || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-           && type == ZEBRA_ROUTE_BGP_VPN) {
-
-               /* leak withdraw all */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                  bgp_get_default(), bgp);
-       }
 
        red = bgp_redist_lookup(bgp, afi, type, instance);
        if (!red)
index da5160bc16d6c0ce96e8950eb58dff71ebe5a257..c30f63039b902d05d184ea15d52ac2425f131d1b 100644 (file)
@@ -33,7 +33,8 @@ extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
 extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
                               struct bgp_info *, struct bgp *, afi_t, safi_t);
 extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
-extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t);
+extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *,
+                              struct bgp *, safi_t);
 
 extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
 extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
index 2eae2e5e9e333cde76e5e95c828b0a9a2a3d88a7..c178727b548270be0fa20f84730717c23b5ab489 100644 (file)
@@ -7132,10 +7132,18 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
        if (safi == SAFI_EVPN)
                bgp_config_write_evpn_info(vty, bgp, afi, safi);
 
-       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                      BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
+       if (safi == SAFI_UNICAST) {
+               bgp_vpn_policy_config_write_afi(vty, bgp, afi);
+               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                              BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
 
-               vty_out(vty, "  export vpn\n");
+                       vty_out(vty, "  export vpn\n");
+               }
+               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                              BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
+
+                       vty_out(vty, "  import vpn\n");
+               }
        }
 
        vty_endframe(vty, " exit-address-family\n");
@@ -7404,8 +7412,6 @@ int bgp_config_write(struct vty *vty)
                if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
                        vty_out(vty, " no auto-summary\n");
 
-               bgp_vpn_policy_config_write(vty, bgp);
-
                /* IPv4 unicast configuration.  */
                bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
 
index 664f8c9da4a82c812ee7eb52429956274c666cb7..79fe8c8c3bab69da98f9f17d43917a4f0ab1af98 100644 (file)
@@ -318,6 +318,7 @@ struct bgp {
        u_int16_t af_flags[AFI_MAX][SAFI_MAX];
 #define BGP_CONFIG_DAMPENING              (1 << 0)
 #define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT  (1 << 1)
+#define BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT  (1 << 2)
 
 /* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
 #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST      (1 << 1)
@@ -471,7 +472,7 @@ struct bgp {
                uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */
                uint32_t tovpn_zebra_vrf_label_last_sent;
                struct prefix_rd tovpn_rd;
-               struct prefix tovpn_nexthop; /* unset => set to router id */
+               struct prefix tovpn_nexthop; /* unset => set to 0 */
                uint32_t flags;
 #define BGP_VPN_POLICY_TOVPN_RD_SET            0x00000004
 #define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET       0x00000008
index aeabc0981dbb1ed09a03ab3f0cbc48c48b30bb0c..8d35d4540ba797aaa8337dd5a5290ef6e063659c 100644 (file)
@@ -179,6 +179,7 @@ EXTRA_DIST = frr-sphinx.mk \
        developer/OSPF-API.md \
        developer/workflow.rst \
        developer/Building_FRR_on_Ubuntu1404.rst \
+       developer/Building_FRR_on_Alpine.rst \
        user/ospf_fundamentals.rst \
        user/routemap.rst \
        user/index.rst \
diff --git a/doc/developer/Building_FRR_on_Alpine.rst b/doc/developer/Building_FRR_on_Alpine.rst
new file mode 100644 (file)
index 0000000..27718bd
--- /dev/null
@@ -0,0 +1,47 @@
+Building FRR dev packages on Alpine Linux from Git Source
+=========================================================
+
+For building Alpine Linux dev packages, we use docker.
+
+Install docker 17.05 or later
+-----------------------------
+
+Depending on your host, there are different ways of installing
+docker.  Refer to the documentation here for instructions on how
+to install a free version of docker: https://www.docker.com/community-edition
+
+Work with sources
+-----------------
+
+    git clone https://github.com/frrouting/frr.git frr
+    cd frr
+
+Build apk packages
+------------------
+
+    ./docker/alpine/build.sh
+
+This will put the apk packages in:
+
+    ./docker/pkgs/apk/x86_64/
+
+Usage
+-----
+
+To add the packages to a docker image, create a Dockerfile in ./docker/pkgs:
+
+    FROM alpine:3.7
+    RUN mkdir -p /pkgs
+    ADD apk/ /pkgs/
+    RUN apk add --no-cache --allow-untrusted /pkgs/x86_64/*.apk
+
+And build a docker image:
+
+    docker build --rm --force-rm -t alpine-dev-pkgs:latest docker/pkgs
+
+And run the image:
+
+    docker run -it --rm alpine-dev-pkgs:latest /bin/sh
+
+Currently, we only package the raw daemons and example files, so, you'll
+need to run the daemons by hand (or, better, orchestrate in the Dockerfile).
index 4715bca53248eac912c95756fcbd41542b902f55..e56744ad87644a5d8cc9e712d75f6e435883760d 100644 (file)
@@ -5,6 +5,7 @@ Building FRR
    :maxdepth: 2
 
    Building_FRR_on_LEDE-OpenWRT
+   Building_FRR_on_Alpine
    Building_FRR_on_CentOS6
    Building_FRR_on_CentOS7
    Building_FRR_on_Debian8
index cff3d21ef7f64885914d34bee8c26173869ca8a9..ee47f61c4baae756b4990016a1c9b3bdc30fec43 100644 (file)
@@ -1,3 +1,5 @@
+.. _command-line-interface:
+
 Command Line Interface
 ======================
 
index e1101fd76af3a9af38e3e0c80fb9577d1a70d1aa..dfd4784f324d9022a1535ea9581676390148dcf7 100644 (file)
@@ -42,6 +42,41 @@ updates, as appropriate, to code (i.e., merges), `Github issues`_, and for
 governance or process changes, updates to the Development list and either this
 file or information posted at https://frrouting.org/.
 
+Release Process & Schedule
+==========================
+
+FRR employs a <MAJOR>.<MINOR>.<BUGFIX> versioning scheme.
+
+MAJOR
+   Significant new features or multiple minor features. The addition of a new
+   routing protocol or daemon would fall under this class.
+
+MINOR
+   Small features, e.g. options for automatic BGP shutdown.
+
+BUGFIX
+   Fixes for actual bugs and/or security issues.
+
+We will pull a new development branch for the next release every 4 months.  The
+current schedule is Feb/June/October 1. The decision for a MAJOR/MINOR release
+is made at the time of branch pull based on what has been received the previous
+4 months. The branch name will be dev/MAJOR.MINOR. At this point in time the
+master branch, :file:`configure.ac`, documentation and packaging systems will
+be updated to reflect the next possible release name to allow for easy
+distinguishing. Additionally the new dev branch will have these files updated
+too.
+
+After one month the development branch will be renamed to stable/MAJOR.MINOR.
+This process is not held up unless a crash or security issue has been found and
+needs to be addressed. Issues being fixed will not cause a delay.
+
+Bugfix releases are made as needed at 1 month intervals until the next
+MAJOR.MINOR relese branch is pulled. Depending on the severity of the bugs,
+bugfix releases may occur sooner.
+
+Bugfixes are applied to the two most recent releases. Security fixes are
+backported to all releases less than or equal to one year old. Security fixes
+may also be backported to older releases depending on severity.
 
 Changelog
 =========
@@ -339,13 +374,111 @@ Code formatting
 FRR uses Linux kernel style except where noted below. Code which does
 not comply with these style guidelines will not be accepted.
 
-To assist with compliance, in the project root there is a .clang-format
-configuration file which can be used with the ``clang-format`` tool from
-the LLVM project. In the ``tools/`` directory there is a Python script
-named ``indent.py`` that wraps clang-format and handles some edge cases
-specific to FRR. If you are submitting a new file, it is recommended to
-run that script over the new file after ensuring that the latest stable
-release of ``clang-format`` is in your PATH.
+The project provides multiple tools to allow you to correctly style your code
+as painlessly as possible, primarily built around ``clang-format``.
+
+clang-format
+   In the project root there is a :file:`.clang-format` configuration file
+   which can be used with the ``clang-format`` source formatter tool from the
+   LLVM project. Most of the time, this is the easiest and smartest tool to
+   use. It can be run in a variety of ways. If you point it at a C source file
+   or directory of source files, it will format all of them. In the LLVM source
+   tree there are scripts that allow you to integrate it with ``git``, ``vim``
+   and ``emacs``, and there are third-party plugins for other editors. The
+   ``git`` integration is particularly useful; suppose you have some changes in
+   your git index. Then, with the integration installed, you can do the
+   following:
+
+   ::
+
+      git clang-format
+
+   This will format *only* the changes present in your index. If you have just
+   made a few commits and would like to correctly style only the changes made
+   in those commits, you can use the following syntax:
+
+   ::
+
+      git clang-format HEAD~X
+
+   Where X is one more than the number of commits back from the tip of your
+   branch you would like ``clang-format`` to look at (similar to specifying the
+   target for a rebase).
+
+   The ``vim`` plugin is particularly useful. It allows you to select lines in
+   visual line mode and press a key binding to invoke ``clang-format`` on only
+   those lines.
+
+   When using ``clang-format``, it is recommended to use the latest version.
+   Each consecutive version generally has better handling of various edge
+   cases. You may notice on occasion that two consecutive runs of
+   ``clang-format`` over the same code may result in changes being made on the
+   second run. This is an unfortunate artifact of the tool. Please check with
+   the kernel style guide if in doubt.
+
+   One stylistic problem with the FRR codebase is the use of ``DEFUN`` macros
+   for defining CLI commands. ``clang-format`` will happily format these macro
+   invocations, but the result is often unsightly and difficult to read.
+   Consequently, FRR takes a more relaxed position with how these are
+   formatted. In general you should lean towards using the style exemplified in
+   the section on :ref:`command-line-interface`. Because ``clang-format``
+   mangles this style, there is a Python script named ``tools/indent.py`` that
+   wraps ``clang-format`` and handles ``DEFUN`` macros as well as some other
+   edge cases specific to FRR. If you are submitting a new file, it is
+   recommended to run that script over the new file, preferably after ensuring
+   that the latest stable release of ``clang-format`` is in your ``PATH``.
+
+   Documentation on ``clang-format`` and its various integrations is maintained
+   on the LLVM website.
+
+   https://clang.llvm.org/docs/ClangFormat.html
+
+checkpatch.sh
+   In the Linux kernel source tree there is a Perl script used to check
+   incoming patches for style errors. FRR uses an adapted version of this
+   script for the same purpose. It can be found at
+   :file:`tools/checkpatch.sh`. This script takes a git-formatted diff or
+   patch file, applies it to a clean FRR tree, and inspects the result to catch
+   potential style errors. Running this script on your patches before
+   submission is highly recommended. The CI system runs this script as well and
+   will comment on the PR with the results if style errors are found.
+
+   It is run like this:
+
+   ::
+
+      checkpatch.sh <patch> <tree>
+
+   Reports are generated on ``stderr`` and the exit code indicates whether
+   issues were found (2, 1) or not (0).
+
+   Where ``<patch>`` is the path to the diff or patch file and ``<tree>`` is
+   the path to your FRR source tree. The tree should be on the branch that you
+   intend to submit the patch against. The script will make a best-effort
+   attempt to save the state of your working tree and index before applying the
+   patch, and to restore it when it is done, but it is still recommended that
+   you have a clean working tree as the script does perform a hard reset on
+   your tree during its run.
+
+   The script reports two classes of issues, namely WARNINGs and ERRORs. Please
+   pay attention to both of them. The script will generally report WARNINGs
+   where it cannot be 100% sure that a particular issue is real. In most cases
+   WARNINGs indicate an issue that needs to be fixed. Sometimes the script will
+   report false positives; these will be handled in code review on a
+   case-by-case basis. Since the script only looks at changed lines,
+   occasionally changing one part of a line can cause the script to report a
+   style issue already present on that line that is unrelated to the change.
+   When convenient it is preferred that these be cleaned up inline, but this is
+   not required.
+
+   If the script finds one or more WARNINGs it will exit with 1. If it finds
+   one or more ERRORs it will exit with 2.
+
+
+Please remember that while FRR provides these tools for your convenience,
+responsibility for properly formatting your code ultimately lies on the
+shoulders of the submitter. As such, it is recommended to double-check the
+results of these tools to avoid delays in merging your submission.
 
 **Whitespace changes in untouched parts of the code are not acceptable
 in patches that change actual code.** To change/fix formatting issues,
index 0cc2c511c352fe43eeaf0a6757a37f8c8fc100d3..b5ee632271f5439f579066d3d8277c340b391c19 100644 (file)
@@ -1529,6 +1529,140 @@ BGP Large Communities in Route Map
    large-community list. The third will add a large-community value without
    overwriting other values. Multiple large-community values can be specified.
 
+
+.. _bgp-vrfs:
+
+BGP VRFs
+========
+
+Bgpd supports multiple VRF instances via the  *router bgp* command:
+
+.. index:: router bgp ASN vrf VRFNAME
+.. clicmd:: router bgp ASN vrf VRFNAME
+
+VRFNAME is matched against VRFs configured in the kernel. When no
+*vrf VRFNAME* is specified, the BGP protocol process belongs to
+the default VRF.
+
+BGP routes may be leaked (i.e., copied) between a unicast VRF RIB
+and the VPN safi RIB of the default VRF (leaking is also permitted
+between the unicast RIB of the default VRF and VPN).  A common
+application of this feature is to connect a customer's private
+routing domain to a provider's VPN service. Leaking is configured
+from the point of view of an individual VRF: ``import`` refers to
+routes leaked from VPN to a unicast VRF, whereas ``export`` refers
+to routes leaked from a unicast VRF to VPN.
+
+Required Parameters
+-------------------
+
+Routes exported from a unicast VRF to the VPN RIB must be augmented
+by two parameters:
+a route-distinguisher (RD) and a route-target list (RTLIST).
+Configuration for these exported routes must, at a minimum, specify
+these two parameters.
+
+Routes imported from the VPN RIB to a unicast VRF are selected
+according to their RTLISTs.
+Routes whose RTLIST contains at least one route-target in common with
+the configured import RTLIST are leaked.
+Configuration for these imported routes must specify an RTLIST to be matched.
+
+The RD, which carries no semantic value, is intended to make the
+route unique in the VPN RIB among all routes of its prefix that
+originate from all the customers and sites that are attached
+to the provider's VPN service. Accordingly, each site of each customer
+is typically assigned an RD that is unique across the entire provider
+network.
+
+The RTLIST is a set of route-target extended community values whose
+purpose is to specify route-leaking policy. Typically, a customer
+is assigned a single route-target value for import and export to be
+used at all customer sites. This configuration specifies a simple
+topology wherein a customer has a single routing domain which is
+shared across all its sites. More complex routing topologies are possible
+through use of additional route-targets to augment the leaking of
+sets of routes in various ways.
+
+Configuration
+-------------
+
+Configuration of route leaking between a unicast VRF RIB and the
+VPN safi RIB of the default VRF is accomplished via commands in the
+context of a VRF address-family:
+
+.. index:: rd vpn export AS:NN|IP:nn
+.. clicmd:: rd vpn export AS:NN|IP:nn
+
+   Specifies the route distinguisher to be added to a route exported
+   from the current unicast VRF to VPN.
+
+.. index:: no rd vpn export [AS:NN|IP:nn]
+.. clicmd:: no rd vpn export [AS:NN|IP:nn]
+
+   Deletes any previously-configured export route distinguisher.
+
+.. index:: rt vpn import|export|both RTLIST...
+.. clicmd:: rt vpn import|export|both RTLIST...
+
+   Specifies the route-target list to be attached to a route (export)
+   or the route-target list to match against (import) when
+   exporting/importing between the current unicast VRF and VPN.
+
+   The RTLIST is a space-separated list of route-targets, which are
+   BGP extended community values as described in
+   :ref:`bgp-extended-communities-attribute`.
+
+.. index:: no rt vpn import|export|both [RTLIST...]
+.. clicmd:: no rt vpn import|export|both [RTLIST...]
+
+   Deletes any previously-configured import or export route-target list.
+
+.. index:: label vpn export (0..1048575)
+.. clicmd:: label vpn export (0..1048575)
+
+   Specifies an optional MPLS label to be attached to a route exported
+   from the current unicast VRF to VPN.
+
+.. index:: no label vpn export [(0..1048575)]
+.. clicmd:: no label vpn export [(0..1048575)]
+
+   Deletes any previously-configured export label.
+
+.. index:: nexthop vpn export A.B.C.D|X:X::X:X
+.. clicmd:: nexthop vpn export A.B.C.D|X:X::X:X
+
+   Specifies an optional nexthop value to be assigned to a route exported
+   from the current unicast VRF to VPN. If left unspecified, the nexthop
+   will be set to 0.0.0.0 or 0:0::0:0 (self).
+
+.. index:: no nexthop vpn export [A.B.C.D|X:X::X:X]
+.. clicmd:: no nexthop vpn export [A.B.C.D|X:X::X:X]
+
+   Deletes any previously-configured export nexthop.
+
+.. index:: route-map vpn import|export MAP
+.. clicmd:: route-map vpn import|export MAP
+
+   Specifies an optional route-map to be applied to routes imported
+   or exported betwen the current unicast VRF and VPN.
+
+.. index:: no route-map vpn import|export [MAP]
+.. clicmd:: no route-map vpn import|export [MAP]
+
+   Deletes any previously-configured import or export route-map.
+
+.. index:: import|export vpn
+.. clicmd:: import|export vpn
+
+   Enables import or export of routes betwen the current unicast VRF and VPN.
+
+.. index:: no import|export vpn
+.. clicmd:: no import|export vpn
+
+   Disables import or export of routes betwen the current unicast VRF and VPN.
+
+
 .. _displaying-bgp-information:
 
 Displaying BGP information
diff --git a/docker/.gitignore b/docker/.gitignore
new file mode 100644 (file)
index 0000000..e9beab5
--- /dev/null
@@ -0,0 +1,2 @@
+src.tar
+pkgs/
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
new file mode 100644 (file)
index 0000000..e186fdc
--- /dev/null
@@ -0,0 +1,30 @@
+FROM alpine:3.7 as source-builder
+ARG commit
+RUN apk add --no-cache abuild acct alpine-sdk attr autoconf automake bash \
+    binutils binutils-libs bison bsd-compat-headers build-base \
+    c-ares c-ares-dev ca-certificates cryptsetup-libs curl \
+    device-mapper-libs expat fakeroot flex fortify-headers g++ gcc gdbm \
+    git gmp isl json-c json-c-dev kmod lddtree libacl libatomic libattr \
+    libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc \
+    libgomp libisoburn libisofs libltdl libressl libssh2 \
+    libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1 \
+    mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base \
+    patch pax-utils pcre perl pkgconf python2 python2-dev readline \
+    readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs \
+    groff gzip bc py-sphinx
+RUN mkdir -p /src
+ADD src.tar /src
+RUN (cd /src && \
+       ./bootstrap.sh && \
+       ./configure \
+               --enable-numeric-version \
+               --with-pkg-extra-version=_git$commit && \
+       make dist)
+FROM alpine:3.7 as alpine-builder
+RUN apk add --no-cache abuild alpine-sdk && mkdir -p /pkgs/apk
+ADD alpine-build.sh /usr/bin/
+ADD builder /etc/sudoers.d
+COPY --from=source-builder /src/*.tar.gz /src/alpine/APKBUILD /dist/
+RUN adduser -D -G abuild builder && chown -R builder /dist /pkgs
+USER builder
+RUN /usr/bin/alpine-build.sh
diff --git a/docker/alpine/alpine-build.sh b/docker/alpine/alpine-build.sh
new file mode 100755 (executable)
index 0000000..d4c0311
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -e
+
+cd /dist
+
+sudo apk --update add alpine-conf
+sudo setup-apkcache /var/cache/apk
+abuild-keygen -a -n
+abuild checksum
+abuild -r -P /pkgs/apk
diff --git a/docker/alpine/build.sh b/docker/alpine/build.sh
new file mode 100755 (executable)
index 0000000..357ea12
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+set -e
+set -v
+set -x
+
+##
+# commit must be converted to decimal
+##
+c=`git rev-parse --short=10 HEAD`
+commit=`printf '%u\n' 0x$c`
+git archive --format=tar $c > docker/alpine/src.tar
+(cd docker/alpine && \
+       docker build --build-arg commit=$commit --rm --force-rm -t \
+               frr:alpine-$c . && \
+       rm -f src.tar)
+
+id=`docker create frr:alpine-$c`
+docker cp ${id}:/pkgs/ docker
+docker rm $id
+docker rmi frr:alpine-$c
diff --git a/docker/alpine/builder b/docker/alpine/builder
new file mode 100644 (file)
index 0000000..a950b8a
--- /dev/null
@@ -0,0 +1 @@
+builder ALL=(ALL) NOPASSWD:ALL
index 0493c125bdd32670343b74959d3cbd5cf1c7224a..872bc5bc72f2395e9e7a42800e9fe6e4d281788f 100644 (file)
@@ -216,7 +216,8 @@ end:
 
 int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
 {
-       int bytesread = 0, bytestoread, offset, one = 1;
+       int bytesread = 0, bytestoread, offset, one = 1, err = ISIS_OK;
+       u_char *buff_ptr;
        struct bpf_hdr *bpf_hdr;
 
        assert(circuit->fd > 0);
@@ -230,25 +231,33 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
        }
        if (bytesread < 0) {
                zlog_warn("isis_recv_pdu_bcast(): read() failed: %s",
-                         safe_strerror(errno));
+                               safe_strerror(errno));
                return ISIS_WARNING;
        }
 
        if (bytesread == 0)
                return ISIS_WARNING;
 
-       bpf_hdr = (struct bpf_hdr *)readbuff;
+       buff_ptr = readbuff;
+       while (buff_ptr < readbuff + bytesread) {
+               bpf_hdr = (struct bpf_hdr *) buff_ptr;
+               assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
+               offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
 
-       assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
+               /* then we lose the BPF, LLC and ethernet headers */
+               stream_write(circuit->rcv_stream, buff_ptr + offset,
+                            bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
+               stream_set_getp(circuit->rcv_stream, 0);
 
-       offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
+               memcpy(ssnpa, buff_ptr + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN,
+               ETHER_ADDR_LEN);
 
-       /* then we lose the BPF, LLC and ethernet headers */
-       stream_write(circuit->rcv_stream, readbuff + offset,
-                    bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
-       stream_set_getp(circuit->rcv_stream, 0);
+               err = isis_handle_pdu(circuit, ssnpa);
+               stream_reset(circuit->rcv_stream);
+               buff_ptr += BPF_WORDALIGN(bpf_hdr->bh_hdrlen +
+                                               bpf_hdr->bh_datalen);
+       }
 
-       memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
 
        if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
                zlog_warn("Flushing failed: %s", safe_strerror(errno));
index bcbda330887bdbd133e83e5dfb8228e24f21dfde..ebcf197a3730f240af737b205c1ef38b53191e47 100644 (file)
@@ -1337,7 +1337,7 @@ static int pdu_size(uint8_t pdu_type, uint8_t *size)
  * PDU Dispatcher
  */
 
-static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
+int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
 {
        int retval = ISIS_OK;
 
@@ -1460,8 +1460,10 @@ int isis_receive(struct thread *thread)
 
        retval = circuit->rx(circuit, ssnpa);
 
+#if ISIS_METHOD != ISIS_METHOD_BPF
        if (retval == ISIS_OK)
                retval = isis_handle_pdu(circuit, ssnpa);
+#endif //ISIS_METHOD != ISIS_METHOD_BPF
 
        /*
         * prepare for next packet.
index 7096761879394591f830f7554d30f6d6707ed5ca..2d9100c10b118b80276bd107ebe35e5abdc90ca2 100644 (file)
@@ -215,5 +215,5 @@ int send_l2_psnp(struct thread *thread);
 int send_lsp(struct thread *thread);
 void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
 int send_hello(struct isis_circuit *circuit, int level);
-
+int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa);
 #endif /* _ZEBRA_ISIS_PDU_H */
index b289cdd7a3cba562760fb138728833ec00153f0b..5697c1d812b01d6baff6b181c8cafab7c9d4489a 100644 (file)
@@ -87,8 +87,6 @@ const char *node_names[] = {
        "bgp vnc l2",               // BGP_VNC_L2_GROUP_NODE,
        "rfp defaults",             // RFP_DEFAULTS_NODE,
        "bgp evpn",                 // BGP_EVPN_NODE,
-       "bgp vpn policy ipv4",      // BGP_VPNPOLICY_IPV4_NODE
-       "bgp vpn policy ipv6",      // BGP_VPNPOLICY_IPV6_NODE
        "ospf",                     // OSPF_NODE,
        "ospf6",                    // OSPF6_NODE,
        "ldp",                      // LDP_NODE,
@@ -951,8 +949,6 @@ enum node_type node_parent(enum node_type node)
        case BGP_VPNV4_NODE:
        case BGP_VPNV6_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
@@ -1323,8 +1319,6 @@ void cmd_exit(struct vty *vty)
        case BGP_VPNV4_NODE:
        case BGP_VPNV6_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
@@ -1395,8 +1389,6 @@ DEFUN (config_end,
        case BABEL_NODE:
        case BGP_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
index 1e700aaa8f8c7bea013c9819d30863a2a07d65a4..95d8ee99dfa1cc1e9a7b7c4f6b561352fe60eee6 100644 (file)
@@ -110,8 +110,6 @@ enum node_type {
        BGP_VNC_L2_GROUP_NODE,   /* BGP VNC L2 group */
        RFP_DEFAULTS_NODE,       /* RFP defaults node */
        BGP_EVPN_NODE,           /* BGP EVPN node. */
-       BGP_VPNPOLICY_IPV4_NODE, /* BGP VPN IPv6 policy */
-       BGP_VPNPOLICY_IPV6_NODE, /* BGP VPN IPv6 policy */
        OSPF_NODE,               /* OSPF protocol mode */
        OSPF6_NODE,              /* OSPF protocol for IPv6 mode */
        LDP_NODE,                /* LDP protocol mode */
index a8e7462baac123992a49a50dfaa3ee621ce62096..74e7be7c7d76821705d9e923261f0a8bef707a9b 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -1055,8 +1055,6 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
-               else if (strmatch(s, "vpn"))
-                       return ZEBRA_ROUTE_BGP_VPN;
        }
        if (afi == AFI_IP6) {
                if (strmatch(s, "kernel"))
@@ -1085,8 +1083,6 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
-               else if (strmatch(s, "vpn"))
-                       return ZEBRA_ROUTE_BGP_VPN;
        }
        return -1;
 }
index 98cada8f89887ecdf7fa035de51434a8761e9b86..310a993c38654e551871b981ad07543dd84b58ce 100644 (file)
@@ -76,7 +76,6 @@ ZEBRA_ROUTE_VNC_DIRECT_RH, vnc-rn, NULL,   'V', 0, 0, "VNC-RN"
 ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL,  'b', 0, 0, "BGP-Direct"
 #  bgp unicast -> vnc 
 ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, "BGP2VNC"
-ZEBRA_ROUTE_BGP_VPN,    vpn,       NULL,   'c', 1, 1, "VPN", bgpd
 ZEBRA_ROUTE_BABEL,      babel,     babeld, 'A', 1, 1, "Babel"
 ZEBRA_ROUTE_SHARP,    sharp,     sharpd, 'D', 1, 1, "SHARP"
 ZEBRA_ROUTE_ALL,        wildcard,  none,   '-', 0, 0, "-"
@@ -102,6 +101,5 @@ ZEBRA_ROUTE_OLSR,   "Optimised Link State Routing (OLSR)"
 ZEBRA_ROUTE_TABLE,  "Non-main Kernel Routing Table"
 ZEBRA_ROUTE_LDP,    "Label Distribution Protocol (LDP)"
 ZEBRA_ROUTE_VNC_DIRECT,    "VNC direct (not via zebra) routes"
-ZEBRA_ROUTE_BGP_VPN, "BGP VPN routes"
 ZEBRA_ROUTE_BABEL,  "Babel routing protocol (Babel)"
 ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)"
index 777f6fcf9bf32fac3f57f27d62ffed8b4b7562f1..2cac71ac45a37e1d78b0499cdf067854ac030f81 100644 (file)
@@ -1340,6 +1340,16 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
                case NEXTHOP_TYPE_BLACKHOLE:
                        break;
                }
+               STREAM_GETC(s, nhr->nexthops[i].label_num);
+               if (nhr->nexthops[i].label_num > MPLS_MAX_LABELS) {
+                       zlog_warn("%s: invalid number of MPLS labels (%u)",
+                                 __func__, nhr->nexthops[i].label_num);
+                       return false;
+               }
+               if (nhr->nexthops[i].label_num)
+                       STREAM_GET(&nhr->nexthops[i].labels[0], s,
+                                  nhr->nexthops[i].label_num
+                                  * sizeof(mpls_label_t));
        }
 
        return true;
index e162d21cd25f27fbb2b9145f80ed2cce1c4e686e..a44a432a0a96d5599fa101d015b274b0a3573f5f 100644 (file)
@@ -101,6 +101,7 @@ struct ospf6_area {
        struct timeval ts_spf; /* SPF calculation time stamp. */
 
        uint32_t full_nbrs; /* Fully adjacent neighbors. */
+       uint8_t intra_prefix_originate; /* Force intra_prefix lsa originate */
 };
 
 #define OSPF6_AREA_ENABLE     0x01
index c23fe99bc8bd5cb6eb09256b21234964bb8b5847..cd930f6c0983fef4af54759266865568fb07352b 100644 (file)
@@ -616,6 +616,8 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
                        prefix2str(&prefix, buf, sizeof(buf));
                        zlog_debug("AS-External route %s not found", buf);
                }
+
+               ospf6_route_delete(route_to_del);
                return;
        }
 
index dae10dce0d7e1cd5ba3c52daf74978395ccad393..6040c53dce191a9c03e5fd134afe640db738eaab 100644 (file)
@@ -156,6 +156,28 @@ void ospf6_lsa_purge(struct ospf6_lsa *lsa)
        ospf6_lsa_premature_aging(lsa);
 }
 
+/* Puring Multi Link-State IDs LSAs:
+ * Same Advertising Router with Multiple Link-State IDs
+ * LSAs, purging require to traverse all Link-State IDs
+ */
+void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, struct ospf6_lsa *lsa)
+{
+       int ls_id = 0;
+       struct ospf6_lsa *lsa_next;
+       uint16_t type;
+
+       type = lsa->header->type;
+
+       ospf6_lsa_purge(lsa);
+
+       lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
+                                    oa->ospf6->router_id, oa->lsdb);
+       while (lsa_next) {
+               ospf6_lsa_purge(lsa_next);
+               lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
+                                            oa->ospf6->router_id, oa->lsdb);
+       }
+}
 
 void ospf6_increment_retrans_count(struct ospf6_lsa *lsa)
 {
index f5d33e2843aa3269a24e56c0fd6f20aab0ccb15b..6931024fff43d0a74202a39a84113fe28dbd1cfc 100644 (file)
@@ -41,6 +41,9 @@ extern void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
                                          struct ospf6_interface *oi);
 extern void ospf6_lsa_purge(struct ospf6_lsa *lsa);
 
+extern void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa,
+                                       struct ospf6_lsa *lsa);
+
 /* access method to retrans_count */
 extern void ospf6_increment_retrans_count(struct ospf6_lsa *lsa);
 extern void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa);
index 14f12d6b6a5faa6355d29ba1fddf1a84c8e68a6c..c9e2ff9eb5cc0e5242aceb9fc7ea1fb6bf924d8f 100644 (file)
@@ -1015,6 +1015,20 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
                return 0;
        }
 
+       /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
+        * has not change, Flush old LSA and Re-Originate INP,
+        * as ospf6_flood() checks if LSA is same as DB,
+        * it won't be updated to neighbor's DB.
+        */
+       if (oa->intra_prefix_originate) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("%s: Re-originate intra prefix LSA, Current full nbrs %u",
+                                  __PRETTY_FUNCTION__, oa->full_nbrs);
+               if (old)
+                       ospf6_lsa_purge_multi_ls_id(oa, old);
+               oa->intra_prefix_originate = 0;
+       }
+
        /* put prefixes to advertise */
        prefix_num = 0;
        op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
index 542a24bfc94b411316696dda2e894d54bfd52ad8..16bf2fd8e7bbb87ee6913f80566e2e954e4daccf 100644 (file)
@@ -188,6 +188,9 @@ static void ospf6_neighbor_state_change(u_char next_state,
                        OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if);
                        OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if);
                }
+               if (next_state == OSPF6_NEIGHBOR_FULL)
+                       on->ospf6_if->area->intra_prefix_originate = 1;
+
                OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area);
 
                if (prev_state == OSPF6_NEIGHBOR_LOADING
index c60436f391909de62bd122cb327ff2ed2941792d..5167aa0495bf419e2f44cf218f6240e30c305388 100644 (file)
@@ -285,9 +285,11 @@ static int mtrace_un_forward_packet(struct pim_instance *pim, struct ip *ip_hdr,
        pim_socket_ip_hdr(fd);
 
        if (interface == NULL) {
+               memset(&nexthop, 0, sizeof(nexthop));
                ret = pim_nexthop_lookup(pim, &nexthop, ip_hdr->ip_dst, 0);
 
                if (ret != 0) {
+                       close(fd);
                        if (PIM_DEBUG_MTRACE)
                                zlog_warn(
                                        "Dropping mtrace packet, "
@@ -463,6 +465,7 @@ static int mtrace_send_response(struct pim_instance *pim,
                if (PIM_DEBUG_MTRACE)
                        zlog_debug("mtrace response to RP");
        } else {
+               memset(&nexthop, 0, sizeof(nexthop));
                /* TODO: should use unicast rib lookup */
                ret = pim_nexthop_lookup(pim, &nexthop, mtracep->rsp_addr, 1);
 
@@ -641,6 +644,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
 
        nh_addr.s_addr = 0;
 
+       memset(&nexthop, 0, sizeof(nexthop));
        ret = pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1);
 
        if (ret == 0) {
index 8e0cc86a9ccfc4b13f04bdf6d91684391f3d0340..14fb910219122cd1ff25d20dfe231b35a26a7bfa 100644 (file)
@@ -146,6 +146,7 @@ Requires(post): /sbin/install-info
 BuildRequires:  gcc patch libcap-devel
 BuildRequires:  readline readline-devel ncurses ncurses-devel
 BuildRequires:  json-c-devel bison >= 2.7 flex make
+BuildRequires:  c-ares-devel texinfo
 %if 0%{?rhel} && 0%{?rhel} < 7
 #python27-devel is available from ius community repo for RedHat/CentOS 6
 BuildRequires:  python27-devel python27-sphinx
index 7575c8e1fffdfb04acacf63ff9e32fe8b7c69adf..86c0348b946e7c6fc1d481bee561fa7f017e4b7d 100644 (file)
@@ -2186,6 +2186,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
                                 */
                                int suppress = 0;
                                struct rip_info *tmp_rinfo = NULL;
+                               struct connected *tmp_ifc = NULL;
 
                                for (ALL_LIST_ELEMENTS_RO(list, listnode,
                                                          tmp_rinfo))
@@ -2197,10 +2198,17 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
                                        }
 
                                if (!suppress
-                                   && rinfo->type == ZEBRA_ROUTE_CONNECT
-                                   && prefix_match((struct prefix *)p,
-                                                   ifc->address))
-                                       suppress = 1;
+                                   && rinfo->type == ZEBRA_ROUTE_CONNECT) {
+                                       for (ALL_LIST_ELEMENTS_RO(
+                                                    ifc->ifp->connected,
+                                                    listnode, tmp_ifc))
+                                               if (prefix_match(
+                                                           (struct prefix *)p,
+                                                           tmp_ifc->address)) {
+                                                       suppress = 1;
+                                                       break;
+                                               }
+                               }
 
                                if (suppress)
                                        continue;
@@ -2311,19 +2319,29 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
                                 * configured on the same interface).
                                 */
                                struct rip_info *tmp_rinfo = NULL;
+                               struct connected *tmp_ifc = NULL;
 
                                for (ALL_LIST_ELEMENTS_RO(list, listnode,
                                                          tmp_rinfo))
                                        if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
                                            && tmp_rinfo->nh.ifindex
                                                       == ifc->ifp->ifindex)
-                                               tmp_rinfo->metric_out =
+                                               rinfo->metric_out =
                                                        RIP_METRIC_INFINITY;
 
-                               if (rinfo->type == ZEBRA_ROUTE_CONNECT
-                                   && prefix_match((struct prefix *)p,
-                                                   ifc->address))
-                                       rinfo->metric_out = RIP_METRIC_INFINITY;
+                               if (rinfo->metric_out != RIP_METRIC_INFINITY
+                                   && rinfo->type == ZEBRA_ROUTE_CONNECT) {
+                                       for (ALL_LIST_ELEMENTS_RO(
+                                                    ifc->ifp->connected,
+                                                    listnode, tmp_ifc))
+                                               if (prefix_match(
+                                                           (struct prefix *)p,
+                                                           tmp_ifc->address)) {
+                                                       rinfo->metric_out =
+                                                               RIP_METRIC_INFINITY;
+                                                       break;
+                                               }
+                               }
                        }
 
                        /* Prepare preamble, auth headers, if needs be */
index 3065ad19c3b50d7ce6860d04810246dec489b164..4d19484a64172191d24818ff277677c114011459 100644 (file)
@@ -39,6 +39,46 @@ extern uint32_t total_routes;
 extern uint32_t installed_routes;
 extern uint32_t removed_routes;
 
+DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
+      "sharp watch nexthop X:X::X:X$nhop",
+      "Sharp routing Protocol\n"
+      "Watch for changes\n"
+      "Watch for nexthop changes\n"
+      "The v6 nexthop to signal for watching\n")
+{
+       struct prefix p;
+
+       memset(&p, 0, sizeof(p));
+
+       p.prefixlen = 128;
+       memcpy(&p.u.prefix6, &nhop, 16);
+       p.family = AF_INET6;
+
+       sharp_zebra_nexthop_watch(&p, true);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
+      "sharp watch nexthop A.B.C.D$nhop",
+      "Sharp routing Protocol\n"
+      "Watch for changes\n"
+      "Watch for nexthop changes\n"
+      "The v4 nexthop to signal for watching\n")
+{
+       struct prefix p;
+
+       memset(&p, 0, sizeof(p));
+
+       p.prefixlen = 32;
+       p.u.prefix4 = nhop;
+       p.family = AF_INET;
+
+       sharp_zebra_nexthop_watch(&p, true);
+
+       return CMD_SUCCESS;
+}
+
 DEFPY (install_routes,
        install_routes_cmd,
        "sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
@@ -147,5 +187,7 @@ void sharp_vty_init(void)
        install_element(ENABLE_NODE, &install_routes_cmd);
        install_element(ENABLE_NODE, &remove_routes_cmd);
        install_element(ENABLE_NODE, &vrf_label_cmd);
+       install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
+       install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
        return;
 }
index 8915397c7e7455cf01e3e248cc8d8084bea5bf8c..999255e9254e08f812ab649da3f03326b9ec2093 100644 (file)
@@ -214,6 +214,65 @@ void route_delete(struct prefix *p)
        return;
 }
 
+void sharp_zebra_nexthop_watch(struct prefix *p, bool watch)
+{
+       int command = ZEBRA_NEXTHOP_REGISTER;
+
+       if (!watch)
+               command = ZEBRA_NEXTHOP_UNREGISTER;
+
+       zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT);
+}
+
+static int sharp_nexthop_update(int command, struct zclient *zclient,
+                               zebra_size_t length, vrf_id_t vrf_id)
+{
+       struct zapi_route nhr;
+       char buf[PREFIX_STRLEN];
+       int i;
+
+       if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
+               zlog_warn("%s: Decode of update failed", __PRETTY_FUNCTION__);
+
+               return 0;
+       }
+
+       zlog_debug("Received update for %s",
+                  prefix2str(&nhr.prefix, buf, sizeof(buf)));
+       for (i = 0; i < nhr.nexthop_num; i++) {
+               struct zapi_nexthop *znh = &nhr.nexthops[i];
+
+               switch (znh->type) {
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+               case NEXTHOP_TYPE_IPV4:
+                       zlog_debug(
+                               "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
+                               inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
+                                         sizeof(buf)),
+                               znh->type, znh->ifindex, znh->vrf_id,
+                               znh->label_num);
+                       break;
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+               case NEXTHOP_TYPE_IPV6:
+                       zlog_debug(
+                               "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
+                               inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
+                                         sizeof(buf)),
+                               znh->type, znh->ifindex, znh->vrf_id,
+                               znh->label_num);
+                       break;
+               case NEXTHOP_TYPE_IFINDEX:
+                       zlog_debug("\tNexthop IFINDEX: %d, ifindex: %d",
+                                  znh->type, znh->ifindex);
+                       break;
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       zlog_debug("\tNexthop blackhole");
+                       break;
+               }
+       }
+       return 0;
+}
+
 extern struct zebra_privs_t sharp_privs;
 
 void sharp_zebra_init(void)
@@ -231,4 +290,5 @@ void sharp_zebra_init(void)
        zclient->interface_address_add = interface_address_add;
        zclient->interface_address_delete = interface_address_delete;
        zclient->route_notify_owner = route_notify_owner;
+       zclient->nexthop_update = sharp_nexthop_update;
 }
index 0bba443bd48c43c6ee6c6f12069bd576f10f4b5e..0c906fc4ffd10fc97ed7ae2121fefb46527b50c1 100644 (file)
@@ -27,4 +27,5 @@ extern void sharp_zebra_init(void);
 extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
 extern void route_add(struct prefix *p, struct nexthop *nh);
 extern void route_delete(struct prefix *p);
+extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch);
 #endif
index 556ce272291887e952d083c62752dc70b9075ff1..efef106d978ac0e87f9bcc4ad185b8b001256e80 100644 (file)
@@ -360,9 +360,7 @@ static int vtysh_execute_func(const char *line, int pager)
                } else if ((saved_node == KEYCHAIN_KEY_NODE
                            || saved_node == LDP_PSEUDOWIRE_NODE
                            || saved_node == LDP_IPV4_IFACE_NODE
-                           || saved_node == LDP_IPV6_IFACE_NODE
-                           || saved_node == BGP_VPNPOLICY_IPV4_NODE
-                           || saved_node == BGP_VPNPOLICY_IPV6_NODE)
+                           || saved_node == LDP_IPV6_IFACE_NODE)
                           && (tried == 1)) {
                        vtysh_execute("exit");
                } else if (tried) {
@@ -634,9 +632,7 @@ int vtysh_mark_file(const char *filename)
                        } else if ((prev_node == BGP_EVPN_VNI_NODE)
                                   && (tried == 1)) {
                                fprintf(outputfile, "exit-vni\n");
-                       } else if ((prev_node == KEYCHAIN_KEY_NODE
-                                   || prev_node == BGP_VPNPOLICY_IPV4_NODE
-                                   || prev_node == BGP_VPNPOLICY_IPV6_NODE)
+                       } else if ((prev_node == KEYCHAIN_KEY_NODE)
                                   && (tried == 1)) {
                                fprintf(outputfile, "exit\n");
                        } else if (tried) {
@@ -1017,12 +1013,6 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
 static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
                                            "%s(config-router-af-vni)# "};
 
-static struct cmd_node bgp_vpn_policy_ipv4_node = {
-       BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1};
-
-static struct cmd_node bgp_vpn_policy_ipv6_node = {
-       BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1};
-
 static struct cmd_node bgp_ipv6l_node = {BGP_IPV6L_NODE,
                                         "%s(config-router-af)# "};
 
@@ -1274,20 +1264,6 @@ DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)",
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_BGPD, vpn_policy_afi, vpn_policy_afi_cmd, "vpn-policy <ipv4|ipv6>",
-       "Configure a VPN policy\n"
-       BGP_AFI_HELP_STR)
-{
-       int idx = 1;
-
-       if (argv_find(argv, argc, "ipv4", &idx))
-               vty->node = BGP_VPNPOLICY_IPV4_NODE;
-       else
-               vty->node = BGP_VPNPOLICY_IPV6_NODE;
-       return CMD_SUCCESS;
-}
-
-
 #if defined(ENABLE_BGP_VNC)
 DEFUNSH(VTYSH_BGPD, vnc_defaults, vnc_defaults_cmd, "vnc defaults",
        "VNC/RFP related configuration\n"
@@ -1562,8 +1538,6 @@ static int vtysh_exit(struct vty *vty)
        case BGP_IPV6M_NODE:
        case BGP_IPV6L_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_EVPN_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
@@ -3112,8 +3086,6 @@ void vtysh_init_vty(void)
        install_node(&bgp_vrf_policy_node, NULL);
        install_node(&bgp_evpn_node, NULL);
        install_node(&bgp_evpn_vni_node, NULL);
-       install_node(&bgp_vpn_policy_ipv4_node, NULL);
-       install_node(&bgp_vpn_policy_ipv6_node, NULL);
        install_node(&bgp_vnc_defaults_node, NULL);
        install_node(&bgp_vnc_nve_group_node, NULL);
        install_node(&bgp_vnc_l2_group_node, NULL);
@@ -3206,10 +3178,6 @@ void vtysh_init_vty(void)
        install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd);
        install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd);
        install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_exit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_quit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_exit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_quit_bgpd_cmd);
 #if defined(ENABLE_BGP_VNC)
        install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd);
        install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd);
@@ -3262,8 +3230,6 @@ void vtysh_init_vty(void)
        install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_end_all_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_end_all_cmd);
        install_element(ISIS_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
@@ -3313,7 +3279,6 @@ void vtysh_init_vty(void)
        install_element(CONFIG_NODE, &router_bgp_cmd);
        install_element(BGP_NODE, &address_family_vpnv4_cmd);
        install_element(BGP_NODE, &address_family_vpnv6_cmd);
-       install_element(BGP_NODE, &vpn_policy_afi_cmd);
 #if defined(ENABLE_BGP_VNC)
        install_element(BGP_NODE, &vnc_vrf_policy_cmd);
        install_element(BGP_NODE, &vnc_defaults_cmd);
index 00d853ea26d755e17e54652b9d5d3ee107cfede0..b0a19c5aa559791e5004e39201e83af56c52d33c 100644 (file)
@@ -351,9 +351,6 @@ int main(int argc, char **argv)
        */
        frr_config_fork();
 
-       /* Clean up rib -- before fork (?) */
-       /* rib_weed_tables (); */
-
        /* After we have successfully acquired the pidfile, we can be sure
        *  about being the only copy of zebra process, which is submitting
        *  changes to the FIB.
index 3a66aea45f897ef6d9f7d1b61987d0c50c129669..89c17b069aab07617a721ecab5c128d95fe288af 100644 (file)
@@ -58,7 +58,8 @@ int is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id)
        if (afi == AFI_MAX)
                return 0;
 
-       if (is_zebra_valid_kernel_table(table_id))
+       if (is_zebra_valid_kernel_table(table_id) &&
+           table_id < ZEBRA_KERNEL_TABLE_MAX)
                return zebra_import_table_used[afi][table_id];
        return 0;
 }
index 0ee89e015a13a5596f2d79833f53873458c2d135..0562d544e64267c87c44488fbfd86cebc915e5f9 100644 (file)
@@ -230,23 +230,24 @@ typedef enum {
        RIB_UPDATE_OTHER
 } rib_update_event_t;
 
-extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
-                                                      ifindex_t,
+extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re,
+                                                      ifindex_t ifindex,
                                                       vrf_id_t nh_vrf_id);
-extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *,
-                                                        enum blackhole_type);
-extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *,
-                                                   struct in_addr *,
-                                                   struct in_addr *,
+extern struct nexthop *
+route_entry_nexthop_blackhole_add(struct route_entry *re,
+                                 enum blackhole_type bh_type);
+extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re,
+                                                   struct in_addr *ipv4,
+                                                   struct in_addr *src,
                                                    vrf_id_t nh_vrf_id);
 extern struct nexthop *
-route_entry_nexthop_ipv4_ifindex_add(struct route_entry *, struct in_addr *,
-                                    struct in_addr *, ifindex_t,
-                                    vrf_id_t nh_vrf_id);
+route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
+                                    struct in_addr *ipv4, struct in_addr *src,
+                                    ifindex_t ifindex, vrf_id_t nh_vrf_id);
 extern void route_entry_nexthop_delete(struct route_entry *re,
                                       struct nexthop *nexthop);
-extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *,
-                                                   struct in6_addr *,
+extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re,
+                                                   struct in6_addr *ipv6,
                                                    vrf_id_t nh_vrf_id);
 extern struct nexthop *
 route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
@@ -258,8 +259,9 @@ extern void route_entry_copy_nexthops(struct route_entry *re,
                                      struct nexthop *nh);
 
 #define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re)
-extern void _route_entry_dump(const char *, union prefixconstptr,
-                             union prefixconstptr, const struct route_entry *);
+extern void _route_entry_dump(const char *func, union prefixconstptr pp,
+                             union prefixconstptr src_pp,
+                             const struct route_entry *re);
 /* RPF lookup behaviour */
 enum multicast_mode {
        MCAST_NO_CONFIG = 0,  /* MIX_MRIB_FIRST, but no show in config write */
@@ -274,11 +276,11 @@ enum multicast_mode {
 extern void multicast_mode_ipv4_set(enum multicast_mode mode);
 extern enum multicast_mode multicast_mode_ipv4_get(void);
 
-extern void rib_lookup_and_dump(struct prefix_ipv4 *, vrf_id_t);
-extern void rib_lookup_and_pushup(struct prefix_ipv4 *, vrf_id_t);
+extern void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id);
+extern void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id);
 
-extern int rib_lookup_ipv4_route(struct prefix_ipv4 *, union sockunion *,
-                                vrf_id_t);
+extern int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
+                                vrf_id_t vrf_id);
 #define ZEBRA_RIB_LOOKUP_ERROR -1
 #define ZEBRA_RIB_FOUND_EXACT 0
 #define ZEBRA_RIB_FOUND_NOGATE 1
@@ -305,8 +307,8 @@ extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                   u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
                   uint8_t distance, route_tag_t tag);
 
-extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *,
-                            struct prefix_ipv6 *src_p, struct route_entry *);
+extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
+                            struct prefix_ipv6 *src_p, struct route_entry *re);
 
 extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                       u_short instance, int flags, struct prefix *p,
@@ -314,27 +316,30 @@ extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                       u_int32_t table_id, u_int32_t metric, bool fromkernel,
                       struct ethaddr *rmac);
 
-extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t,
-                                    union g_addr *,
+extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
+                                    union g_addr *addr,
                                     struct route_node **rn_out);
 extern struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
                                                    struct in_addr addr,
                                                    struct route_node **rn_out);
 
-extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *, vrf_id_t);
+extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
+                                          vrf_id_t vrf_id);
 
-extern void rib_update(vrf_id_t, rib_update_event_t);
-extern void rib_weed_tables(void);
+extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
 extern void rib_sweep_route(void);
-extern void rib_close_table(struct route_table *);
+extern void rib_sweep_table(struct route_table *table);
+extern void rib_close_table(struct route_table *table);
 extern void rib_init(void);
 extern unsigned long rib_score_proto(u_char proto, u_short instance);
+extern unsigned long rib_score_proto_table(u_char proto, u_short instance,
+                                          struct route_table *table);
 extern void rib_queue_add(struct route_node *rn);
 extern void meta_queue_free(struct meta_queue *mq);
 extern int zebra_rib_labeled_unicast(struct route_entry *re);
 extern struct route_table *rib_table_ipv6;
 
-extern void rib_unlink(struct route_node *, struct route_entry *);
+extern void rib_unlink(struct route_node *rn, struct route_entry *re);
 extern int rib_gc_dest(struct route_node *rn);
 extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter);
 
index 1868b4676d191cb97b4ad421379109c70322c290..8375d45d2f61619bb0ed0e498bd83d67042fb23b 100644 (file)
@@ -2254,6 +2254,19 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
        fec_print(rn->info, vty);
 }
 
+static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
+                                   enum lsp_types_t type, mpls_label_t label)
+{
+       if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
+               nexthop_add_labels(nexthop, type, 1, &label);
+       else if (!add && nexthop->nh_label_type == type)
+               nexthop_del_labels(nexthop);
+       else
+               return false;
+
+       return true;
+}
+
 /*
  * Install/uninstall a FEC-To-NHLFE (FTN) binding.
  */
@@ -2266,6 +2279,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
        struct route_node *rn;
        struct route_entry *re;
        struct nexthop *nexthop;
+       bool found;
 
        /* Lookup table.  */
        table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST,
@@ -2285,6 +2299,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
        if (re == NULL)
                return -1;
 
+       found = false;
        for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
                switch (nexthop->type) {
                case NEXTHOP_TYPE_IPV4:
@@ -2297,7 +2312,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
                        if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
                            && nexthop->ifindex != ifindex)
                                continue;
-                       goto found;
+                       if (!mpls_ftn_update_nexthop(add, nexthop, type,
+                                                    out_label))
+                               return 0;
+                       found = true;
+                       break;
                case NEXTHOP_TYPE_IPV6:
                case NEXTHOP_TYPE_IPV6_IFINDEX:
                        if (gtype != NEXTHOP_TYPE_IPV6
@@ -2308,21 +2327,18 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
                        if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
                            && nexthop->ifindex != ifindex)
                                continue;
-                       goto found;
+                       if (!mpls_ftn_update_nexthop(add, nexthop, type,
+                                                    out_label))
+                               return 0;
+                       found = true;
+                       break;
                default:
                        break;
                }
        }
-       /* nexthop not found */
-       return -1;
 
-found:
-       if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
-               nexthop_add_labels(nexthop, type, 1, &out_label);
-       else if (!add && nexthop->nh_label_type == type)
-               nexthop_del_labels(nexthop);
-       else
-               return 0;
+       if (!found)
+               return -1;
 
        SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
        SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
index a81413f5a9db78fe9b9511d5998d23c8c26695db..57f311aac552c032f75af6ede8bb34d70ba99c78 100644 (file)
@@ -172,6 +172,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
        if (sock < 0) {
                zlog_err("netlink( %u) socket() error: %s", sock,
                         safe_strerror(errno));
+               close(fd);
                return NS_UNKNOWN;
        }
        memset(&snl, 0, sizeof(snl));
@@ -348,8 +349,10 @@ ns_id_t zebra_ns_id_get_default(void)
 
        if (fd == -1)
                return NS_DEFAULT_INTERNAL;
-       if (!vrf_is_backend_netns())
+       if (!vrf_is_backend_netns()) {
+               close(fd);
                return NS_DEFAULT_INTERNAL;
+       }
        close(fd);
        return zebra_ns_id_get((char *)NS_DEFAULT_NAME);
 #else  /* HAVE_NETNS */
index 192e8ad4137e39ed505b20930dfd3b54cd0d6ba7..29c179245bf9398a1275fee0d1b0b0dc0cde32cd 100644 (file)
@@ -37,6 +37,7 @@
 #include "zebra_netns_notify.h"
 #include "zebra_netns_id.h"
 #include "zebra_pbr.h"
+#include "rib.h"
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -162,6 +163,31 @@ struct route_table *zebra_ns_find_table(struct zebra_ns *zns, uint32_t tableid,
                return NULL;
 }
 
+unsigned long zebra_ns_score_proto(u_char proto, u_short instance)
+{
+       struct zebra_ns *zns;
+       struct zebra_ns_table *znst;
+       unsigned long cnt = 0;
+
+       zns = zebra_ns_lookup(NS_DEFAULT);
+
+       RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables)
+               cnt += rib_score_proto_table(proto, instance, znst->table);
+
+       return cnt;
+}
+
+void zebra_ns_sweep_route(void)
+{
+       struct zebra_ns_table *znst;
+       struct zebra_ns *zns;
+
+       zns = zebra_ns_lookup(NS_DEFAULT);
+
+       RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables)
+               rib_sweep_table(znst->table);
+}
+
 struct route_table *zebra_ns_get_table(struct zebra_ns *zns,
                                       struct zebra_vrf *zvrf, uint32_t tableid,
                                       afi_t afi)
index 19ecba1f0e764cab1a8c937a6aa8b8eef35aa66b..6655e5c019043d9119138e21770055b141b8f799 100644 (file)
@@ -90,4 +90,7 @@ extern struct route_table *zebra_ns_get_table(struct zebra_ns *zns,
                                              struct zebra_vrf *zvrf,
                                              uint32_t tableid, afi_t afi);
 int zebra_ns_config_write(struct vty *vty, struct ns *ns);
+
+unsigned long zebra_ns_score_proto(u_char proto, u_short instance);
+void zebra_ns_sweep_route(void);
 #endif
index 4da09dc538d72798dfc0e17ca5cf6fc5d59209ff..090ec2c502d5b38f09c0c05602384fd75cecf49b 100644 (file)
@@ -133,6 +133,25 @@ void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
                          __PRETTY_FUNCTION__);
 }
 
+static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
+{
+       struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+       struct zebra_pbr_rule *rule = b->data;
+       int *sock = data;
+
+       if (rule->sock == *sock) {
+               kernel_del_pbr_rule(rule);
+               hash_release(zns->rules_hash, rule);
+       }
+}
+
+void zebra_pbr_client_close_cleanup(int sock)
+{
+       struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+
+       hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
+}
+
 /*
  * Handle success or failure of rule (un)install in the kernel.
  */
index 4b28b6ec35f0cb5e507c15f11e3681df2ec20897..f910d8e742b8555eae08dd359daa4c3aa26b8099 100644 (file)
@@ -132,7 +132,10 @@ extern void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
  */
 extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule);
 
+extern void zebra_pbr_client_close_cleanup(int sock);
+
 extern void zebra_pbr_rules_free(void *arg);
 extern uint32_t zebra_pbr_rules_hash_key(void *arg);
 extern int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2);
+
 #endif /* _ZEBRA_PBR_H */
index 26dd48733e6d3180ea13974a228e6ee9c249db54..69cd6697d2d96b7c9739d98b85f0b0e174500a83 100644 (file)
@@ -139,9 +139,6 @@ uint8_t route_distance(int type)
 
 int is_zebra_valid_kernel_table(u_int32_t table_id)
 {
-       if ((table_id > ZEBRA_KERNEL_TABLE_MAX))
-               return 0;
-
 #ifdef linux
        if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL)
            || (table_id == RT_TABLE_COMPAT))
@@ -1865,7 +1862,6 @@ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
                [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3,
                [ZEBRA_ROUTE_BGP_DIRECT] = 3,
                [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3,
-               [ZEBRA_ROUTE_BGP_VPN] = 3,
                [ZEBRA_ROUTE_BABEL] = 2,
                [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety
 };
@@ -2706,40 +2702,8 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)
                rib_update_table(table, event);
 }
 
-/* Remove all routes which comes from non main table.  */
-static void rib_weed_table(struct route_table *table)
-{
-       struct route_node *rn;
-       struct route_entry *re;
-       struct route_entry *next;
-
-       if (table)
-               for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
-                       RNODE_FOREACH_RE_SAFE (rn, re, next) {
-                               if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
-                                       continue;
-
-                               if (re->table != zebrad.rtm_table_default
-                                   && re->table != RT_TABLE_MAIN)
-                                       rib_delnode(rn, re);
-                       }
-}
-
-/* Delete all routes from non main table. */
-void rib_weed_tables(void)
-{
-       struct vrf *vrf;
-       struct zebra_vrf *zvrf;
-
-       RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
-               if ((zvrf = vrf->info) != NULL) {
-                       rib_weed_table(zvrf->table[AFI_IP][SAFI_UNICAST]);
-                       rib_weed_table(zvrf->table[AFI_IP6][SAFI_UNICAST]);
-               }
-}
-
 /* Delete self installed routes after zebra is relaunched.  */
-static void rib_sweep_table(struct route_table *table)
+void rib_sweep_table(struct route_table *table)
 {
        struct route_node *rn;
        struct route_entry *re;
@@ -2800,11 +2764,13 @@ void rib_sweep_route(void)
                rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]);
                rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]);
        }
+
+       zebra_ns_sweep_route();
 }
 
 /* Remove specific by protocol routes from 'table'. */
-static unsigned long rib_score_proto_table(u_char proto, u_short instance,
-                                          struct route_table *table)
+unsigned long rib_score_proto_table(u_char proto, u_short instance,
+                                   struct route_table *table)
 {
        struct route_node *rn;
        struct route_entry *re;
@@ -2841,6 +2807,8 @@ unsigned long rib_score_proto(u_char proto, u_short instance)
                                         proto, instance,
                                         zvrf->table[AFI_IP6][SAFI_UNICAST]);
 
+       cnt += zebra_ns_score_proto(proto, instance);
+
        return cnt;
 }
 
index c9fb782ba615076f2092ea656dca5814c756d206..48f9f4f366b2be6badf1a27f08436d4d1bb13d21 100644 (file)
@@ -986,7 +986,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
        struct route_entry *re;
        unsigned long nump;
        u_char num;
-       struct nexthop *nexthop;
+       struct nexthop *nh;
        struct route_node *rn;
        int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE
                                                  : ZEBRA_NEXTHOP_UPDATE;
@@ -1022,32 +1022,40 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
                num = 0;
                nump = stream_get_endp(s);
                stream_putc(s, 0);
-               for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
-                       if ((CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
-                            || CHECK_FLAG(nexthop->flags,
-                                          NEXTHOP_FLAG_RECURSIVE))
-                           && CHECK_FLAG(nexthop->flags,
-                                         NEXTHOP_FLAG_ACTIVE)) {
-                               stream_putc(s, nexthop->type);
-                               switch (nexthop->type) {
+               for (nh = re->ng.nexthop; nh; nh = nh->next)
+                       if ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB)
+                            || CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
+                           && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)) {
+                               stream_putc(s, nh->type);
+                               switch (nh->type) {
                                case NEXTHOP_TYPE_IPV4:
                                case NEXTHOP_TYPE_IPV4_IFINDEX:
-                                       stream_put_in_addr(s,
-                                                          &nexthop->gate.ipv4);
-                                       stream_putl(s, nexthop->ifindex);
+                                       stream_put_in_addr(s, &nh->gate.ipv4);
+                                       stream_putl(s, nh->ifindex);
                                        break;
                                case NEXTHOP_TYPE_IFINDEX:
-                                       stream_putl(s, nexthop->ifindex);
+                                       stream_putl(s, nh->ifindex);
                                        break;
                                case NEXTHOP_TYPE_IPV6:
                                case NEXTHOP_TYPE_IPV6_IFINDEX:
-                                       stream_put(s, &nexthop->gate.ipv6, 16);
-                                       stream_putl(s, nexthop->ifindex);
+                                       stream_put(s, &nh->gate.ipv6, 16);
+                                       stream_putl(s, nh->ifindex);
                                        break;
                                default:
                                        /* do nothing */
                                        break;
                                }
+                               if (nh->nh_label) {
+                                       stream_putc(s,
+                                                   nh->nh_label->num_labels);
+                                       if (nh->nh_label->num_labels)
+                                               stream_put(
+                                                       s,
+                                                       &nh->nh_label->label[0],
+                                                       nh->nh_label->num_labels
+                                                               * sizeof(mpls_label_t));
+                               } else
+                                       stream_putc(s, 0);
                                num++;
                        }
                stream_putc_at(s, nump, num);
index 9ae60e011c664c7c6b1ce86ffa6afb7807ce516d..b65f4b8eb50087bb6719586f2de96aca6aea8484 100644 (file)
@@ -148,7 +148,7 @@ static int static_list_compare(void *arg1, void *arg2)
        if (ret)
                return ret;
 
-       ret = strcmp(shr2->nhvrf_name, shr2->nhvrf_name);
+       ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name);
        if (ret)
                return ret;
 
@@ -249,6 +249,9 @@ static int zebra_static_route_holdem(struct zebra_vrf *zvrf,
                        return CMD_SUCCESS;
                }
 
+               XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
+               XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
+               XFREE(MTYPE_STATIC_ROUTE, shr);
                /*
                 * If a person enters the same line again
                 * we need to silently accept it
@@ -2230,7 +2233,7 @@ int static_config(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi,
                if (shr->flag_str)
                        vty_out(vty, "%s ", shr->flag_str);
                if (shr->tag_str)
-                       vty_out(vty, "tag %s", shr->tag_str);
+                       vty_out(vty, "tag %s ", shr->tag_str);
                if (shr->distance_str)
                        vty_out(vty, "%s ", shr->distance_str);
                if (shr->label_str)
index 57b1be4b8b2bc8cb74187ac31a78cfa01e4f9fc1..2d68fcde8702003c5345914bc78b2c0a8faa4d84 100644 (file)
@@ -222,11 +222,15 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
        struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
        /* Check this client need interface information. */
-       if (!client->ifinfo)
+       if (!client->ifinfo) {
+               stream_free(s);
                return 0;
+       }
 
-       if (!ifp->link_params)
+       if (!ifp->link_params) {
+               stream_free(s);
                return 0;
+       }
 
        zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
 
@@ -234,8 +238,10 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
        stream_putl(s, ifp->ifindex);
 
        /* Then TE Link Parameters */
-       if (zebra_interface_link_params_write(s, ifp) == 0)
+       if (zebra_interface_link_params_write(s, ifp) == 0) {
+               stream_free(s);
                return 0;
+       }
 
        /* Write packet size. */
        stream_putw_at(s, 0, stream_get_endp(s));
@@ -595,8 +601,10 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
        struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
        /* Encode route and send. */
-       if (zapi_route_encode(cmd, s, &api) < 0)
+       if (zapi_route_encode(cmd, s, &api) < 0) {
+               stream_free(s);
                return -1;
+       }
 
        if (IS_ZEBRA_DEBUG_SEND) {
                char buf_prefix[PREFIX_STRLEN];
@@ -1160,7 +1168,12 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
        struct ipaddr vtep_ip;
 
        s = msg;
-       zapi_route_decode(s, &api);
+       if (zapi_route_decode(s, &api) < 0) {
+               if (IS_ZEBRA_DEBUG_RECV)
+                       zlog_debug("%s: Unable to decode zapi_route sent",
+                                  __PRETTY_FUNCTION__);
+               return;
+       }
 
        if (IS_ZEBRA_DEBUG_RECV) {
                char buf_prefix[PREFIX_STRLEN];
@@ -2614,7 +2627,7 @@ static inline void zserv_handle_commands(struct zserv *client,
                                         struct stream *msg,
                                         struct zebra_vrf *zvrf)
 {
-       if (hdr->command > sizeof(zserv_handlers)
+       if (hdr->command > array_size(zserv_handlers)
            || zserv_handlers[hdr->command] == NULL)
                zlog_info("Zebra received unknown command %d", hdr->command);
        else
@@ -2631,6 +2644,9 @@ static void zebra_client_free(struct zserv *client)
        /* Send client de-registration to BFD */
        zebra_ptm_bfd_client_deregister(client->proto);
 
+       /* Cleanup any rules installed from this client */
+       zebra_pbr_client_close_cleanup(client->sock);
+
        /* Cleanup any registered nexthops - across all VRFs. */
        zebra_client_close_cleanup_rnh(client);