mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 06:59:21 +00:00
Merge branch 'master' into PIM_VRF
This commit is contained in:
commit
0ecfe5bf38
450
COMMUNITY.md
450
COMMUNITY.md
@ -1,4 +1,7 @@
|
||||
# Developing for PROJECT (DRAFT)
|
||||
Developing for FRRouting
|
||||
=========================
|
||||
|
||||
## Table of Contents
|
||||
|
||||
[TOC]
|
||||
|
||||
@ -14,55 +17,57 @@ it's the document that needs to be updated, not reality.
|
||||
|
||||
## Git Structure
|
||||
|
||||
The master Git for PROJECT resides on Github at
|
||||
[https://github.com/PROJECT/XXX](https://github.com/PROJECT/XXX)
|
||||
The master Git for FRRouting resides on Github at
|
||||
[https://github.com/frrouting/frr](https://github.com/FRRouting/frr)
|
||||
|
||||

|
||||
|
||||
There is one main branch for development and a release branch for each
|
||||
major release.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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 PROJECT is written in C (gcc or clang supported). A few
|
||||
non-essential scripts are implemented in Perl and Python. PROJECT requires
|
||||
the following tools to build distribution packages: automake, autoconf,
|
||||
texinfo, libtool and gawk and various libraries (i.e. libpam and libjson-c).
|
||||
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 PROJECT platform OSes or provide a way to build without the
|
||||
library (potentially without the new feature) on the other platforms.
|
||||
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
|
||||
preference on Markdown.
|
||||
Documentation should be written in Tex (.texi) or Markdown (.md) format with a
|
||||
preference for Markdown.
|
||||
|
||||
|
||||
## Before Submitting your changes
|
||||
## 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 |
|
||||
|
||||
* Format code (see [Code Styling requirements](#code-styling-requirements))
|
||||
* Verify and acknowledge license (see [License for contributions](#license-for-contributions))
|
||||
* Test building with various configurations:
|
||||
* `buildtest.sh`
|
||||
* Verify building source distribution:
|
||||
* `make dist` (and try rebuilding from the resulting tar file)
|
||||
* Run DejaGNU unit tests:
|
||||
* `make test`
|
||||
* Document Regression Runs and plans for continued maintenance of the feature
|
||||
|
||||
### Changelog
|
||||
|
||||
@ -75,16 +80,45 @@ for the release notes.
|
||||
|
||||
## Submitting Patches and Enhancements
|
||||
|
||||
### Pre-submission Checklist
|
||||
|
||||
* Format code (see [Coding style requirements](#coding-style-requirements))
|
||||
* 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
|
||||
|
||||
PROJECT is under a “GPLv2 or later” license. Any code submitted must be
|
||||
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).
|
||||
|
||||
### Signed-off required
|
||||
### Signing Off
|
||||
|
||||
Submissions to PROJECT require a “Signed-off” in the patch or git commit.
|
||||
We follow the same standard as the Linux Kernel Development.
|
||||
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](http://www.kernel.org/doc/Documentation/SubmittingPatches) 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
|
||||
>
|
||||
@ -112,79 +146,46 @@ We follow the same standard as the Linux Kernel Development.
|
||||
> maintained indefinitely and may be redistributed consistent with
|
||||
> this project or the open source license(s) involved.
|
||||
|
||||
#### Using this Process
|
||||
|
||||
We have the same requirements for using the signed-off-by process as the Linux
|
||||
kernel. In short, you need to 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 (above). Code without a proper signoff
|
||||
cannot be merged into the mainline.
|
||||
|
||||
Please make sure to have a `Signed-off-by:` in each commit/patch or the patches
|
||||
will be rejected until this is added.
|
||||
|
||||
If you are unfamiliar with this process, you should read the [official policy
|
||||
at kernel.org](http://www.kernel.org/doc/Documentation/SubmittingPatches) 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.
|
||||
|
||||
### Code submission - What do I submit my changes against?
|
||||
### 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
|
||||
the question of a maintainer.
|
||||
If you are unsure where your submission goes, look at that document or ask a
|
||||
project maintainer.
|
||||
|
||||
### Code submission - Github Pull Request (Strongly Preferred)
|
||||
### Github pull requests
|
||||
|
||||
Preferred submission of code is by using a Github Pull Request against the
|
||||
Develop branch. Code submitted by Pull Request will have an email generated to
|
||||
the PROJECT-devel mailing list for review and the submission will be
|
||||
automatically tested by one or more CI systems. Only after this test succeeds
|
||||
(and the submission is based on the head of the develop branch), then it will
|
||||
be automatically merged into the develop branch. In case of failed tests, it is
|
||||
up to the submitter to either amend the request with further commits or close,
|
||||
fix and create a new pull request.
|
||||
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.
|
||||
|
||||
Further (manual) code review and discussion happens after the merge into the
|
||||
develop branch.
|
||||
### Patch submission via mailing list
|
||||
|
||||
|
||||
### Code submission - Mailing Patch to PROJECT-Devel list
|
||||
|
||||
As an alternative submission, a patch can be mailed to the PROJECT-Devel
|
||||
mailing list. Preferred way to send the patch is using git send-mail. Patches
|
||||
received on the mailing list will be picked up by Patchwork and tested against
|
||||
the latest develop branch. After a further ACK by someone on the mailing list,
|
||||
the patch is then merged into the develop branch.
|
||||
|
||||
Further (manual) code review and discussion happens after the merge into the
|
||||
develop branch.
|
||||
|
||||
#### Sending patch to 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 most recent NN
|
||||
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=XXX-Devel@XXX.org
|
||||
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 version to add it (after making sure to be able to agree to the
|
||||
Developer Certificate of Origin as outlined above):
|
||||
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=XXX-Devel@XXX.org
|
||||
git send-email -NN --annotate --signoff --to=dev@lists.frrouting.org
|
||||
```
|
||||
|
||||
Submitting multi-commit patches as a Github Pull Request is strongly encouraged
|
||||
and will allow your changes to merge faster
|
||||
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
|
||||
@ -194,35 +195,34 @@ and will allow your changes to merge faster
|
||||
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.PROJECT.org](https://patchwork.PROJECT.org) (if
|
||||
[https://patchwork.frrouting.org](https://patchwork.frrouting.org) (if
|
||||
submitted as patch to mailing list).
|
||||
* Please notify PROJECT-Devel mailing list if you think something doesn’t
|
||||
work
|
||||
* 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 dejagnu (“make test”) tests if your
|
||||
* 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 PROJECT-Devel list
|
||||
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:
|
||||
* If the changes are done as a pull request, then they should be
|
||||
automatically merged to the develop branch.
|
||||
* Changes sent to mailing list require a manual ACK to be merged and should
|
||||
be merged within 2 weeks. If you don’t see the merge or any
|
||||
reason/discussion on PROJECT-Devel, then please ask.
|
||||
* 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. (which should
|
||||
happen every few weeks from the develop branch)
|
||||
* Your submission is done once it is merged to the master branch.
|
||||
|
||||
|
||||
## Code Styling requirements
|
||||
## Developer's Guidelines
|
||||
|
||||
### File header required for new files added
|
||||
### Source file header
|
||||
|
||||
New files need to have a Copyright header (see [License for
|
||||
contributions](#license-for-contributions) above) added to the file. Preferred
|
||||
@ -251,7 +251,7 @@ form of the header is as follows:
|
||||
#include <zebra.h>
|
||||
```
|
||||
|
||||
### Adding Copyright claims to already existing file
|
||||
### 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
|
||||
@ -264,95 +264,147 @@ Portions:
|
||||
Copyright (C) 2016 Your name [optional brief change description]
|
||||
```
|
||||
|
||||
### Code styling / format
|
||||
### Code formatting
|
||||
|
||||
Coding style standards in FRR vary depending on location. Pre-existing
|
||||
code uses GNU coding standards. New code may use Linux kernel coding style.
|
||||
FRR uses Linux kernel style except where noted below. Code which does not
|
||||
comply with these style guidelines will not be accepted.
|
||||
|
||||
GNU coding style apply to the following parts:
|
||||
|
||||
* lib/
|
||||
* zebra/
|
||||
* bgpd/
|
||||
* ospfd/
|
||||
* ospf6d/
|
||||
* isisd/
|
||||
* ripd/
|
||||
* ripngd/
|
||||
* vtysh/
|
||||
|
||||
Linux kernel coding style applies to:
|
||||
|
||||
* nhrpd/
|
||||
* watchfrr/
|
||||
* pimd/
|
||||
* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch]
|
||||
|
||||
BSD coding style applies to:
|
||||
|
||||
* ldpd/
|
||||
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.
|
||||
|
||||
It is acceptable to rewrap entire files to Linux kernel style, but this
|
||||
**MUST** come as a separate patch that does nothing other than this
|
||||
reformatting.
|
||||
#### 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)
|
||||
|
||||
#### GNU style
|
||||
|
||||
For GNU coding style, Indentation follows the result of invoking GNU indent:
|
||||
For GNU coding style, use `indent` with the following invocation:
|
||||
|
||||
```
|
||||
indent -nut -nfc1 file_for_submission.c
|
||||
```
|
||||
|
||||
Originally, tabs were used instead of spaces, with tabs are every 8 columns.
|
||||
However, tab interoperability issues mean space characters are now preferred for
|
||||
new changes. We generally only clean up whitespace when code is unmaintainable
|
||||
due to whitespace issues, to minimise merging conflicts.
|
||||
#### 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
|
||||
|
||||
|
||||
#### Linux kernel & BSD style
|
||||
**For `stable/3.0` and `stable/2.0`:**
|
||||
|
||||
These styles are documented externally:
|
||||
GNU coding style apply to the following parts:
|
||||
|
||||
* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle).
|
||||
* [http://man.openbsd.org/style](http://man.openbsd.org/style)
|
||||
* `lib/`
|
||||
* `zebra/`
|
||||
* `bgpd/`
|
||||
* `ospfd/`
|
||||
* `ospf6d/`
|
||||
* `isisd/`
|
||||
* `ripd/`
|
||||
* `ripngd/`
|
||||
* `vtysh/`
|
||||
|
||||
They are relatively similar but differ in details.
|
||||
BSD coding style applies to:
|
||||
|
||||
pimd deviates from Linux kernel style in using 2 spaces for indentation, with
|
||||
Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`.
|
||||
It is acceptable to convert indentation in pimd/ to Linux kernel style, but
|
||||
please convert an entire file at a time. (Rationale: apart from 2-space
|
||||
indentation, the styles are sufficiently close to not upset when mixed.)
|
||||
|
||||
Unlike GNU style, these styles use tabs, not spaces.
|
||||
* `ldpd/`
|
||||
|
||||
|
||||
### Compile-Time conditional code
|
||||
### Documentation
|
||||
|
||||
Many users access PROJECT 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 - typically code should be good enough to be in PROJECT, or it
|
||||
shouldn’t be there at all.
|
||||
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. I.e. this:
|
||||
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();
|
||||
```
|
||||
|
||||
rather than
|
||||
is preferred to
|
||||
|
||||
```
|
||||
#ifdef SOME_SYMBOL
|
||||
@ -363,53 +415,55 @@ frobnicate ();
|
||||
Note that the former approach requires ensuring that `SOME_SYMBOL` will be
|
||||
defined (watch your `AC_DEFINE`s).
|
||||
|
||||
### Debug-Guards in code
|
||||
### Debug-guards in code
|
||||
|
||||
Debugs 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.
|
||||
This PROJECT 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.
|
||||
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 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.
|
||||
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
|
||||
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.
|
||||
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
|
||||
* 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.
|
||||
* some measure of time (dependent on the specific case) has passed, so that the
|
||||
compatibility grace period is considered expired.
|
||||
|
||||
In all cases, compatibility pieces should be marked with compiler/preprocessor
|
||||
annotations to print warnings at compile time, pointing to the appropriate
|
||||
update path. A `-Werror` build should fail if compatibility bits are used.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
When in doubt, follow the guidelines in the Linux kernel style guide, or ask on
|
||||
the development mailing list / public Slack instance.
|
||||
|
94
Makefile.am
94
Makefile.am
@ -1,23 +1,95 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \
|
||||
AUTOMAKE_OPTIONS = subdir-objects 1.12
|
||||
include common.am
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
|
||||
AM_CFLAGS = $(WERROR)
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
LIBCAP = @LIBCAP@
|
||||
|
||||
EXTRA_DIST =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
|
||||
bin_PROGRAMS =
|
||||
sbin_PROGRAMS =
|
||||
noinst_PROGRAMS =
|
||||
noinst_HEADERS =
|
||||
noinst_LIBRARIES =
|
||||
lib_LTLIBRARIES =
|
||||
module_LTLIBRARIES =
|
||||
pkginclude_HEADERS =
|
||||
dist_examples_DATA =
|
||||
|
||||
include lib/subdir.am
|
||||
include zebra/subdir.am
|
||||
include qpb/subdir.am
|
||||
include fpm/subdir.am
|
||||
|
||||
SUBDIRS = . @LIBRFP@ @RFPTEST@ \
|
||||
@BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
|
||||
@ISISD@ @PIMD@ @NHRPD@ @EIGRPD@ @BABELD@ \
|
||||
@WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
|
||||
redhat @SOLARIS@ tests tools snapcraft
|
||||
@WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ \
|
||||
@SOLARIS@ tests tools
|
||||
|
||||
DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
|
||||
isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
|
||||
DIST_SUBDIRS = . bgpd ripd ripngd ospfd ospf6d ldpd \
|
||||
isisd watchfrr vtysh ospfclient doc tests \
|
||||
solaris pimd nhrpd eigrpd bgpd/rfp-example/librfp \
|
||||
bgpd/rfp-example/rfptest tools snapcraft babeld python \
|
||||
bgpd/rfp-example/rfptest tools babeld \
|
||||
# end
|
||||
|
||||
EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \
|
||||
if PKGSRC
|
||||
rcdir=@pkgsrcrcdir@
|
||||
rc_SCRIPTS = \
|
||||
pkgsrc/bgpd.sh \
|
||||
pkgsrc/ospf6d.sh \
|
||||
pkgsrc/ospfd.sh \
|
||||
pkgsrc/ripd.sh \
|
||||
pkgsrc/ripngd.sh \
|
||||
pkgsrc/zebra.sh \
|
||||
# end
|
||||
endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
REPORTING-BUGS \
|
||||
SERVICES \
|
||||
aclocal.m4 \
|
||||
update-autotools \
|
||||
vtysh/Makefile.in vtysh/Makefile.am \
|
||||
tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
|
||||
tools/zebra.el tools/multiple-bgpd.sh
|
||||
m4/README.txt \
|
||||
\
|
||||
python/clidef.py \
|
||||
python/clippy/__init__.py \
|
||||
\
|
||||
redhat/frr.init \
|
||||
redhat/frr.service \
|
||||
redhat/daemons \
|
||||
redhat/frr.logrotate \
|
||||
redhat/frr.pam \
|
||||
redhat/frr.spec \
|
||||
redhat/README.rpm_build.md \
|
||||
\
|
||||
snapcraft/snapcraft.yaml \
|
||||
snapcraft/README.snap_build.md \
|
||||
snapcraft/README.usage.md \
|
||||
snapcraft/extra_version_info.txt \
|
||||
snapcraft/scripts \
|
||||
snapcraft/defaults \
|
||||
snapcraft/helpers \
|
||||
snapcraft/snap \
|
||||
\
|
||||
tools/multiple-bgpd.sh \
|
||||
tools/rrcheck.pl \
|
||||
tools/rrlookup.pl \
|
||||
tools/zc.pl \
|
||||
tools/zebra.el \
|
||||
\
|
||||
vtysh/Makefile.am \
|
||||
vtysh/Makefile.in \
|
||||
# end
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
noinst_HEADERS = defaults.h
|
||||
noinst_HEADERS += defaults.h
|
||||
|
@ -207,8 +207,6 @@ main(int argc, char **argv)
|
||||
|
||||
schedule_neighbours_check(5000, 1);
|
||||
|
||||
zlog_notice ("BABELd %s starting: vty@%d", BABEL_VERSION, babel_vty_port);
|
||||
|
||||
frr_config_fork();
|
||||
frr_run(master);
|
||||
|
||||
|
@ -55,25 +55,6 @@ static struct {
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
static struct {
|
||||
int str_min_len;
|
||||
const char *str;
|
||||
} proto_redistnum_type[ZEBRA_ROUTE_MAX] = {
|
||||
[ZEBRA_ROUTE_BABEL] = {2, "babel"},
|
||||
[ZEBRA_ROUTE_BGP] = {2, "bgp"},
|
||||
[ZEBRA_ROUTE_CONNECT] = {1, "connected"},
|
||||
[ZEBRA_ROUTE_HSLS] = {1, "hsls"},
|
||||
[ZEBRA_ROUTE_ISIS] = {1, "isis"},
|
||||
[ZEBRA_ROUTE_KERNEL] = {1, "kernel"},
|
||||
[ZEBRA_ROUTE_OLSR] = {2, "olsr"},
|
||||
[ZEBRA_ROUTE_OSPF] = {2, "ospf"},
|
||||
[ZEBRA_ROUTE_OSPF6] = {5, "ospf6"},
|
||||
[ZEBRA_ROUTE_RIP] = {1, "rip"},
|
||||
[ZEBRA_ROUTE_RIPNG] = {4, "ripng"},
|
||||
[ZEBRA_ROUTE_STATIC] = {2, "static"},
|
||||
[ZEBRA_ROUTE_SYSTEM] = {2, "system"},
|
||||
};
|
||||
|
||||
/* Zebra node structure. */
|
||||
struct cmd_node zebra_node =
|
||||
{
|
||||
@ -191,66 +172,46 @@ babel_zebra_read_ipv4 (int command, struct zclient *zclient,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
babel_proto_redistnum(const char *s)
|
||||
{
|
||||
int i;
|
||||
if (! s)
|
||||
return -1;
|
||||
int len = strlen(s);
|
||||
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (len <= (int)strlen(proto_redistnum_type[i].str) &&
|
||||
strncmp(proto_redistnum_type[i].str, s,
|
||||
proto_redistnum_type[i].str_min_len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* [Babel Command] */
|
||||
DEFUN (babel_redistribute_type,
|
||||
babel_redistribute_type_cmd,
|
||||
"redistribute " FRR_REDIST_STR_BABELD,
|
||||
"Redistribute\n"
|
||||
FRR_REDIST_HELP_STR_BABELD)
|
||||
{
|
||||
int type;
|
||||
|
||||
type = babel_proto_redistnum(argv[1]->arg);
|
||||
|
||||
if (type < 0) {
|
||||
vty_out (vty, "Invalid type %s\n", argv[1]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, VRF_DEFAULT);
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* [Babel Command] */
|
||||
DEFUN (no_babel_redistribute_type,
|
||||
no_babel_redistribute_type_cmd,
|
||||
"no redistribute " FRR_REDIST_STR_BABELD,
|
||||
"[no] redistribute <ipv4 " FRR_IP_REDIST_STR_BABELD "|ipv6 " FRR_IP6_REDIST_STR_BABELD ">",
|
||||
NO_STR
|
||||
"Redistribute\n"
|
||||
FRR_REDIST_HELP_STR_BABELD)
|
||||
"Redistribute IPv4 routes\n"
|
||||
FRR_IP_REDIST_HELP_STR_BABELD
|
||||
"Redistribute IPv6 routes\n"
|
||||
FRR_IP6_REDIST_HELP_STR_BABELD)
|
||||
{
|
||||
int negate = 0;
|
||||
int family;
|
||||
int afi;
|
||||
int type;
|
||||
int idx = 0;
|
||||
|
||||
type = babel_proto_redistnum(argv[2]->arg);
|
||||
if (argv_find(argv, argc, "no", &idx))
|
||||
negate = 1;
|
||||
argv_find(argv, argc, "redistribute", &idx);
|
||||
family = str2family(argv[idx + 1]->text);
|
||||
if (family < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
afi = family2afi(family);
|
||||
if (!afi)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
type = proto_redistnum(afi, argv[idx + 2]->text);
|
||||
if (type < 0) {
|
||||
vty_out (vty, "Invalid type %s\n", argv[2]->arg);
|
||||
vty_out (vty, "Invalid type %s\n", argv[idx + 2]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT);
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
|
||||
/* perhaps should we remove xroutes having the same type... */
|
||||
if (!negate)
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, 0, VRF_DEFAULT);
|
||||
else {
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, 0, VRF_DEFAULT);
|
||||
/* perhaps should we remove xroutes having the same type... */
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -374,7 +335,6 @@ void babelz_zebra_init(void)
|
||||
|
||||
install_node (&zebra_node, zebra_config_write);
|
||||
install_element(BABEL_NODE, &babel_redistribute_type_cmd);
|
||||
install_element(BABEL_NODE, &no_babel_redistribute_type_cmd);
|
||||
install_element(ENABLE_NODE, &debug_babel_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_babel_cmd);
|
||||
install_element(CONFIG_NODE, &debug_babel_cmd);
|
||||
|
@ -76,6 +76,7 @@ static int
|
||||
babel_config_write (struct vty *vty)
|
||||
{
|
||||
int lines = 0;
|
||||
int afi;
|
||||
int i;
|
||||
|
||||
/* list enabled debug modes */
|
||||
@ -108,13 +109,17 @@ babel_config_write (struct vty *vty)
|
||||
/* list enabled interfaces */
|
||||
lines = 1 + babel_enable_if_config_write (vty);
|
||||
/* list redistributed protocols */
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
||||
if (i != zclient->redist_default &&
|
||||
vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT))
|
||||
{
|
||||
vty_out (vty, " redistribute %s\n", zebra_route_string(i));
|
||||
lines++;
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i != zclient->redist_default &&
|
||||
vrf_bitmap_check (zclient->redist[afi][i], VRF_DEFAULT)) {
|
||||
vty_out (vty, " redistribute %s %s\n",
|
||||
(afi == AFI_IP) ? "ipv4" : "ipv6",
|
||||
zebra_route_string(i));
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lines += config_write_distribute (vty);
|
||||
|
||||
|
@ -9,8 +9,8 @@ debug babel common
|
||||
router babel
|
||||
! network wlan0
|
||||
! network eth0
|
||||
! redistribute kernel
|
||||
! no redistribute static
|
||||
! redistribute ipv4 kernel
|
||||
! no redistribute ipv6 static
|
||||
|
||||
! The defaults are fine for a wireless interface
|
||||
|
||||
|
@ -90,7 +90,6 @@ THE SOFTWARE.
|
||||
|
||||
#define BABEL_VTY_PORT 2609
|
||||
#define BABEL_DEFAULT_CONFIG "babeld.conf"
|
||||
#define BABEL_VERSION "0.1 for quagga"
|
||||
|
||||
/* Values in milliseconds */
|
||||
#define BABEL_DEFAULT_HELLO_INTERVAL 4000
|
||||
|
@ -1677,7 +1677,8 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
||||
{
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t pkt_safi, safi;
|
||||
iana_safi_t pkt_safi;
|
||||
safi_t safi;
|
||||
bgp_size_t nlri_len;
|
||||
size_t start;
|
||||
struct stream *s;
|
||||
@ -1826,7 +1827,8 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
|
||||
struct stream *s;
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t pkt_safi, safi;
|
||||
iana_safi_t pkt_safi;
|
||||
safi_t safi;
|
||||
u_int16_t withdraw_len;
|
||||
struct peer *const peer = args->peer;
|
||||
struct attr *const attr = args->attr;
|
||||
@ -2039,7 +2041,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
stlv_last->next = tlv;
|
||||
stlv_last = tlv;
|
||||
}
|
||||
|
||||
if (BGP_ATTR_ENCAP == type) {
|
||||
@ -2593,7 +2595,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
|
||||
{
|
||||
size_t sizep;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
afi_t nh_afi;
|
||||
|
||||
/* Set extended bit always to encode the attribute length as 2 bytes */
|
||||
@ -3280,7 +3282,7 @@ size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
|
||||
{
|
||||
unsigned long attrlen_pnt;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
/* Set extended bit always to encode the attribute length as 2 bytes */
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
|
||||
|
@ -347,6 +347,8 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
||||
if (bgp == NULL) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
else
|
||||
vty_out(vty, "{}\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@ static int bgp_graceful_restart_timer_expire(struct thread *thread)
|
||||
|
||||
/* NSF delete stale route */
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
|
||||
if (peer->nsf[afi][safi])
|
||||
bgp_clear_stale_route(peer, afi, safi);
|
||||
|
||||
@ -521,7 +521,7 @@ static int bgp_graceful_stale_timer_expire(struct thread *thread)
|
||||
|
||||
/* NSF delete stale route */
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
|
||||
if (peer->nsf[afi][safi])
|
||||
bgp_clear_stale_route(peer, afi, safi);
|
||||
|
||||
@ -1022,7 +1022,7 @@ int bgp_stop(struct peer *peer)
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST;
|
||||
safi < SAFI_RESERVED_4; safi++)
|
||||
safi <= SAFI_MPLS_VPN; safi++)
|
||||
peer->nsf[afi][safi] = 0;
|
||||
}
|
||||
|
||||
@ -1425,7 +1425,7 @@ static int bgp_establish(struct peer *peer)
|
||||
/* graceful restart */
|
||||
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
|
||||
if (peer->afc_nego[afi][safi]
|
||||
&& CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
|
||||
&& CHECK_FLAG(peer->af_cap[afi][safi],
|
||||
|
@ -102,6 +102,7 @@ int bgp_maximum_paths_unset(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
{
|
||||
int compare;
|
||||
struct in6_addr addr1, addr2;
|
||||
|
||||
compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop);
|
||||
if (!compare) {
|
||||
@ -120,13 +121,18 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
&bi2->attr->mp_nexthop_global);
|
||||
break;
|
||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
||||
compare = IPV6_ADDR_CMP(
|
||||
&bi1->attr->mp_nexthop_global,
|
||||
&bi2->attr->mp_nexthop_global);
|
||||
addr1 = (bi1->attr->mp_nexthop_prefer_global) ?
|
||||
bi1->attr->mp_nexthop_global
|
||||
: bi1->attr->mp_nexthop_local;
|
||||
addr2 = (bi2->attr->mp_nexthop_prefer_global) ?
|
||||
bi2->attr->mp_nexthop_global
|
||||
: bi2->attr->mp_nexthop_local;
|
||||
|
||||
if (!bi1->attr->mp_nexthop_prefer_global &&
|
||||
!bi2->attr->mp_nexthop_prefer_global)
|
||||
compare = !(bi1->peer->ifindex == bi2->peer->ifindex);
|
||||
if (!compare)
|
||||
compare = IPV6_ADDR_CMP(
|
||||
&bi1->attr->mp_nexthop_local,
|
||||
&bi2->attr->mp_nexthop_local);
|
||||
compare = IPV6_ADDR_CMP(&addr1, &addr2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -374,6 +374,8 @@ int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||
if (bgp == NULL) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
else
|
||||
vty_out(vty, "{}\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,8 @@ static int bgp_capability_orf_entry(struct peer *peer,
|
||||
u_char num;
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t pkt_safi, safi;
|
||||
iana_safi_t pkt_safi;
|
||||
safi_t safi;
|
||||
u_char type;
|
||||
u_char mode;
|
||||
u_int16_t sm_cap = 0; /* capability send-mode receive */
|
||||
@ -466,7 +467,7 @@ static int bgp_capability_restart(struct peer *peer,
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
iana_afi_t pkt_afi = stream_getw(s);
|
||||
safi_t pkt_safi = stream_getc(s);
|
||||
iana_safi_t pkt_safi = stream_getc(s);
|
||||
u_char flag = stream_getc(s);
|
||||
|
||||
/* Convert AFI, SAFI to internal values, check. */
|
||||
@ -543,7 +544,7 @@ static int bgp_capability_addpath(struct peer *peer,
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
iana_afi_t pkt_afi = stream_getw(s);
|
||||
safi_t pkt_safi = stream_getc(s);
|
||||
iana_safi_t pkt_safi = stream_getc(s);
|
||||
u_char send_receive = stream_getc(s);
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
@ -600,7 +601,8 @@ static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
|
||||
while (stream_get_getp(s) + 6 <= end) {
|
||||
iana_afi_t pkt_afi = stream_getw(s);
|
||||
afi_t afi;
|
||||
safi_t safi, pkt_safi = stream_getw(s);
|
||||
iana_safi_t pkt_safi = stream_getw(s);
|
||||
safi_t safi;
|
||||
iana_afi_t pkt_nh_afi = stream_getw(s);
|
||||
afi_t nh_afi;
|
||||
|
||||
@ -1199,7 +1201,7 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
|
||||
unsigned long numberp;
|
||||
int number_of_orfs = 0;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
|
||||
@ -1264,7 +1266,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
|
||||
unsigned long cp, capp, rcapp;
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t safi, pkt_safi;
|
||||
safi_t safi;
|
||||
iana_safi_t pkt_safi;
|
||||
as_t local_as;
|
||||
u_int32_t restart_time;
|
||||
u_char afi_safi_count = 0;
|
||||
|
@ -29,9 +29,9 @@ struct capability_header {
|
||||
|
||||
/* Generic MP capability data */
|
||||
struct capability_mp_data {
|
||||
iana_afi_t afi;
|
||||
uint16_t afi; /* iana_afi_t */
|
||||
u_char reserved;
|
||||
safi_t safi;
|
||||
uint8_t safi; /* iana_safi_t */
|
||||
};
|
||||
|
||||
struct capability_as4 {
|
||||
|
@ -142,7 +142,7 @@ static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi,
|
||||
{
|
||||
struct stream *s;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
if (DISABLE_BGP_ANNOUNCE)
|
||||
return NULL;
|
||||
@ -671,7 +671,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
|
||||
struct bgp_filter *filter;
|
||||
int orf_refresh = 0;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
if (DISABLE_BGP_ANNOUNCE)
|
||||
return;
|
||||
@ -761,7 +761,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
||||
{
|
||||
struct stream *s;
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
|
||||
@ -1338,8 +1338,9 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
|
||||
packet);
|
||||
case SAFI_EVPN:
|
||||
return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse BGP Update packet and make attribute object. */
|
||||
@ -1697,7 +1698,8 @@ static void bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
|
||||
{
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t pkt_safi, safi;
|
||||
iana_safi_t pkt_safi;
|
||||
safi_t safi;
|
||||
struct stream *s;
|
||||
struct peer_af *paf;
|
||||
struct update_group *updgrp;
|
||||
@ -1965,7 +1967,8 @@ static int bgp_capability_msg_parse(struct peer *peer, u_char *pnt,
|
||||
u_char action;
|
||||
iana_afi_t pkt_afi;
|
||||
afi_t afi;
|
||||
safi_t pkt_safi, safi;
|
||||
iana_safi_t pkt_safi;
|
||||
safi_t safi;
|
||||
|
||||
end = pnt + length;
|
||||
|
||||
|
@ -2078,7 +2078,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
|
||||
vnc_import_bgp_add_route(bgp, p, old_select);
|
||||
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
|
||||
#endif
|
||||
if (bgp_fibupd_safi(safi) && !bgp->name
|
||||
if (bgp_fibupd_safi(safi)
|
||||
&& !bgp_option_check(BGP_OPT_NO_FIB)
|
||||
&& new_select->type == ZEBRA_ROUTE_BGP
|
||||
&& new_select->sub_type == BGP_ROUTE_NORMAL)
|
||||
@ -2288,7 +2288,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
|
||||
int always)
|
||||
{
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
|
||||
return 0;
|
||||
@ -8257,6 +8257,8 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
if (bgp == NULL) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
else
|
||||
vty_out(vty, "{}\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@ -8617,8 +8619,16 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
|
||||
int prefix_check, enum bgp_path_type pathtype,
|
||||
u_char use_json)
|
||||
{
|
||||
if (!bgp)
|
||||
if (!bgp) {
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
else
|
||||
vty_out(vty, "{}\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
/* labeled-unicast routes live in the unicast table */
|
||||
if (safi == SAFI_LABELED_UNICAST)
|
||||
|
@ -700,6 +700,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
int send_attr_printed = 0;
|
||||
int num_pfx = 0;
|
||||
int addpath_encode = 0;
|
||||
int addpath_overhead = 0;
|
||||
u_int32_t addpath_tx_id = 0;
|
||||
struct prefix_rd *prd = NULL;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
@ -721,6 +722,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
bpacket_attr_vec_arr_reset(&vecarr);
|
||||
|
||||
addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
|
||||
addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0;
|
||||
|
||||
adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update);
|
||||
while (adv) {
|
||||
@ -732,8 +734,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
|
||||
space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
|
||||
- BGP_MAX_PACKET_SIZE_OVERFLOW;
|
||||
space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(
|
||||
afi, safi, &rn->p);
|
||||
space_needed = BGP_NLRI_LENGTH + addpath_overhead +
|
||||
bgp_packet_mpattr_prefix_size(afi, safi, &rn->p);
|
||||
|
||||
/* When remaining space can't include NLRI and it's length. */
|
||||
if (space_remaining < space_needed)
|
||||
@ -777,9 +779,9 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
space_remaining =
|
||||
STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
|
||||
- BGP_MAX_PACKET_SIZE_OVERFLOW;
|
||||
space_needed =
|
||||
BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(
|
||||
afi, safi, &rn->p);
|
||||
space_needed = BGP_NLRI_LENGTH + addpath_overhead +
|
||||
bgp_packet_mpattr_prefix_size(afi, safi,
|
||||
&rn->p);
|
||||
|
||||
/* If the attributes alone do not leave any room for
|
||||
* NLRI then
|
||||
@ -843,7 +845,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
send_attr_str);
|
||||
if (!stream_empty(snlri)) {
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
pkt_afi = afi_int2iana(afi);
|
||||
pkt_safi = safi_int2iana(safi);
|
||||
@ -936,6 +938,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
int space_needed = 0;
|
||||
int num_pfx = 0;
|
||||
int addpath_encode = 0;
|
||||
int addpath_overhead = 0;
|
||||
u_int32_t addpath_tx_id = 0;
|
||||
struct prefix_rd *prd = NULL;
|
||||
|
||||
@ -952,6 +955,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
s = subgrp->work;
|
||||
stream_reset(s);
|
||||
addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
|
||||
addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0;
|
||||
|
||||
while ((adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw)) != NULL) {
|
||||
assert(adv->rn);
|
||||
@ -962,7 +966,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
space_remaining =
|
||||
STREAM_REMAIN(s) - BGP_MAX_PACKET_SIZE_OVERFLOW;
|
||||
space_needed =
|
||||
BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN
|
||||
BGP_NLRI_LENGTH + addpath_overhead + BGP_TOTAL_ATTR_LEN
|
||||
+ bgp_packet_mpattr_prefix_size(afi, safi, &rn->p);
|
||||
|
||||
if (space_remaining < space_needed)
|
||||
@ -985,7 +989,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
/* If first time, format the MP_UNREACH header */
|
||||
if (first_time) {
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
pkt_afi = afi_int2iana(afi);
|
||||
pkt_safi = safi_int2iana(safi);
|
||||
|
@ -51,6 +51,8 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
|
||||
if (bgp == NULL) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
else
|
||||
vty_out(vty, "{}\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,10 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
|
||||
case SAFI_MPLS_VPN:
|
||||
return BGP_VPNV4_NODE;
|
||||
break;
|
||||
default:
|
||||
/* not expected */
|
||||
return BGP_IPV4_NODE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AFI_IP6:
|
||||
@ -94,6 +98,10 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
|
||||
case SAFI_MPLS_VPN:
|
||||
return BGP_VPNV6_NODE;
|
||||
break;
|
||||
default:
|
||||
/* not expected */
|
||||
return BGP_IPV4_NODE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AFI_L2VPN:
|
||||
@ -4201,8 +4209,15 @@ DEFUN (neighbor_attr_unchanged,
|
||||
"Med attribute\n")
|
||||
{
|
||||
int idx = 0;
|
||||
char *peer = argv[1]->arg;
|
||||
char *peer_str = argv[1]->arg;
|
||||
struct peer *peer;
|
||||
u_int16_t flags = 0;
|
||||
afi_t afi = bgp_node_afi(vty);
|
||||
safi_t safi = bgp_node_safi(vty);
|
||||
|
||||
peer = peer_and_group_lookup_vty(vty, peer_str);
|
||||
if (!peer)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (argv_find(argv, argc, "as-path", &idx))
|
||||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||||
@ -4213,15 +4228,35 @@ DEFUN (neighbor_attr_unchanged,
|
||||
if (argv_find(argv, argc, "med", &idx))
|
||||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||||
|
||||
if (!flags) // no flags means all of them!
|
||||
{
|
||||
/* no flags means all of them! */
|
||||
if (!flags) {
|
||||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||||
} else {
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_MED_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
return peer_af_flag_set_vty(vty, peer, bgp_node_afi(vty),
|
||||
bgp_node_safi(vty), flags);
|
||||
return peer_af_flag_set_vty(vty, peer_str, afi, safi, flags);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -7052,12 +7087,6 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
|
||||
json);
|
||||
}
|
||||
safi++;
|
||||
if (safi == SAFI_RESERVED_4
|
||||
|| safi
|
||||
== SAFI_RESERVED_5) /* handle special
|
||||
cases to match
|
||||
zebra.h */
|
||||
safi++;
|
||||
if (!safi_wildcard)
|
||||
safi = SAFI_MAX;
|
||||
}
|
||||
|
@ -269,8 +269,6 @@ static int bgp_interface_delete(int command, struct zclient *zclient,
|
||||
if (!ifp) /* This may happen if we've just unregistered for a VRF. */
|
||||
return 0;
|
||||
|
||||
ifp->ifindex = IFINDEX_DELETED;
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name);
|
||||
|
||||
@ -279,6 +277,8 @@ static int bgp_interface_delete(int command, struct zclient *zclient,
|
||||
return 0;
|
||||
|
||||
bgp_update_interface_nbrs(bgp, ifp, NULL);
|
||||
|
||||
ifp->ifindex = IFINDEX_DELETED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
47
bgpd/bgpd.c
47
bgpd/bgpd.c
@ -611,8 +611,8 @@ int bgp_listen_limit_unset(struct bgp *bgp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi,
|
||||
safi_t *safi)
|
||||
int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
|
||||
afi_t *afi, safi_t *safi)
|
||||
{
|
||||
/* Map from IANA values to internal values, return error if
|
||||
* values are unrecognized.
|
||||
@ -626,7 +626,7 @@ int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi,
|
||||
}
|
||||
|
||||
int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi,
|
||||
safi_t *pkt_safi)
|
||||
iana_safi_t *pkt_safi)
|
||||
{
|
||||
/* Map from internal values to IANA values, return error if
|
||||
* internal values are bad (unexpected).
|
||||
@ -746,7 +746,7 @@ static unsigned int peer_hash_key_make(void *p)
|
||||
return sockunion_hash(&peer->su);
|
||||
}
|
||||
|
||||
static int peer_hash_cmp(const void *p1, const void *p2)
|
||||
static int peer_hash_same(const void *p1, const void *p2)
|
||||
{
|
||||
const struct peer *peer1 = p1;
|
||||
const struct peer *peer2 = p2;
|
||||
@ -1842,7 +1842,7 @@ static void peer_nsf_stop(struct peer *peer)
|
||||
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
|
||||
peer->nsf[afi][safi] = 0;
|
||||
|
||||
if (peer->t_gr_restart) {
|
||||
@ -2757,7 +2757,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
||||
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
|
||||
bgp->peer = list_new();
|
||||
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
|
||||
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_cmp, NULL);
|
||||
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
|
||||
bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
|
||||
|
||||
bgp->group = list_new();
|
||||
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
|
||||
@ -6926,36 +6927,34 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
bgp_config_write_filter(vty, peer, afi, safi, write);
|
||||
|
||||
/* atribute-unchanged. */
|
||||
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
|| CHECK_FLAG(peer->af_flags[afi][safi],
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
|| CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) {
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
&& peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
&& peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s attribute-unchanged\n", addr);
|
||||
} else {
|
||||
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
|
||||
peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ||
|
||||
peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
|
||||
|
||||
if (!peer_group_active(peer) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s attribute-unchanged%s%s%s\n",
|
||||
addr,
|
||||
peergroup_af_flag_check(
|
||||
peer_af_flag_check(
|
||||
peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
? " as-path"
|
||||
: "",
|
||||
peergroup_af_flag_check(
|
||||
peer_af_flag_check(
|
||||
peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
? " next-hop"
|
||||
: "",
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)
|
||||
? " med"
|
||||
: "");
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "bitfield.h"
|
||||
|
||||
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
|
||||
#define BGP_PEER_MAX_HASH_SIZE 16384
|
||||
|
||||
/* Default interval for IPv6 RAs when triggered by BGP unnumbered neighbor. */
|
||||
#define BGP_UNNUM_DEFAULT_RA_INTERVAL 10
|
||||
@ -922,10 +923,10 @@ DECLARE_QOBJ_TYPE(peer)
|
||||
stream. */
|
||||
struct bgp_nlri {
|
||||
/* AFI. */
|
||||
afi_t afi;
|
||||
uint16_t afi; /* iana_afi_t */
|
||||
|
||||
/* SAFI. */
|
||||
safi_t safi;
|
||||
uint8_t safi; /* iana_safi_t */
|
||||
|
||||
/* Pointer to NLRI byte stream. */
|
||||
u_char *nlri;
|
||||
@ -1381,10 +1382,10 @@ extern void bgp_route_map_terminate(void);
|
||||
|
||||
extern int peer_cmp(struct peer *p1, struct peer *p2);
|
||||
|
||||
extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi,
|
||||
extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
|
||||
afi_t *afi, safi_t *safi);
|
||||
extern int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi,
|
||||
iana_afi_t *pkt_afi, safi_t *pkt_safi);
|
||||
iana_afi_t *pkt_afi, iana_safi_t *pkt_safi);
|
||||
|
||||
extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t);
|
||||
extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t);
|
||||
|
@ -135,10 +135,10 @@ struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc,
|
||||
|
||||
switch (vn->family) {
|
||||
case AF_INET:
|
||||
rt_vn = &(hc->nve_groups_vn[AFI_IP]);
|
||||
rt_vn = hc->nve_groups_vn[AFI_IP];
|
||||
break;
|
||||
case AF_INET6:
|
||||
rt_vn = &(hc->nve_groups_vn[AFI_IP6]);
|
||||
rt_vn = hc->nve_groups_vn[AFI_IP6];
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@ -146,10 +146,10 @@ struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc,
|
||||
|
||||
switch (un->family) {
|
||||
case AF_INET:
|
||||
rt_un = &(hc->nve_groups_un[AFI_IP]);
|
||||
rt_un = hc->nve_groups_un[AFI_IP];
|
||||
break;
|
||||
case AF_INET6:
|
||||
rt_un = &(hc->nve_groups_un[AFI_IP6]);
|
||||
rt_un = hc->nve_groups_un[AFI_IP6];
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@ -2503,7 +2503,7 @@ DEFUN (vnc_nve_group_prefix,
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg);
|
||||
struct prefix p;
|
||||
int afi;
|
||||
afi_t afi;
|
||||
struct route_table *rt;
|
||||
struct route_node *rn;
|
||||
int is_un_prefix = 0;
|
||||
@ -2527,10 +2527,10 @@ DEFUN (vnc_nve_group_prefix,
|
||||
}
|
||||
|
||||
if (argv[1]->arg[0] == 'u') {
|
||||
rt = &(bgp->rfapi_cfg->nve_groups_un[afi]);
|
||||
rt = bgp->rfapi_cfg->nve_groups_un[afi];
|
||||
is_un_prefix = 1;
|
||||
} else {
|
||||
rt = &(bgp->rfapi_cfg->nve_groups_vn[afi]);
|
||||
rt = bgp->rfapi_cfg->nve_groups_vn[afi];
|
||||
}
|
||||
|
||||
rn = route_node_get(rt, &p); /* NB locks node */
|
||||
@ -3830,7 +3830,7 @@ void bgp_rfapi_cfg_init(void)
|
||||
struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
|
||||
{
|
||||
struct rfapi_cfg *h;
|
||||
int afi;
|
||||
afi_t afi;
|
||||
|
||||
h = (struct rfapi_cfg *)XCALLOC(MTYPE_RFAPI_CFG,
|
||||
sizeof(struct rfapi_cfg));
|
||||
@ -3838,14 +3838,9 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
|
||||
|
||||
h->nve_groups_sequential = list_new();
|
||||
assert(h->nve_groups_sequential);
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
/* ugly, to deal with addition of delegates, part of 0.99.24.1
|
||||
* merge */
|
||||
h->nve_groups_vn[afi].delegate =
|
||||
route_table_get_default_delegate();
|
||||
h->nve_groups_un[afi].delegate =
|
||||
route_table_get_default_delegate();
|
||||
h->nve_groups_vn[afi] = route_table_init();
|
||||
h->nve_groups_un[afi] = route_table_init();
|
||||
}
|
||||
h->default_response_lifetime =
|
||||
BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT;
|
||||
@ -3885,6 +3880,7 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
|
||||
|
||||
void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h)
|
||||
{
|
||||
afi_t afi;
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
||||
@ -3901,6 +3897,10 @@ void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h)
|
||||
ecommunity_free(&h->default_rt_import_list);
|
||||
if (h->default_rfp_cfg)
|
||||
XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg);
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
route_table_finish(h->nve_groups_vn[afi]);
|
||||
route_table_finish(h->nve_groups_un[afi]);
|
||||
}
|
||||
XFREE(MTYPE_RFAPI_CFG, h);
|
||||
}
|
||||
|
||||
@ -4571,7 +4571,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty)
|
||||
{
|
||||
struct rfapi_cfg *hc = bgp->rfapi_cfg;
|
||||
int afi, type, redist = 0;
|
||||
afi_t afi;
|
||||
int type, redist = 0;
|
||||
char tmp[40];
|
||||
if (hc == NULL)
|
||||
return;
|
||||
|
@ -135,8 +135,8 @@ struct rfapi_cfg {
|
||||
struct list *l2_groups; /* rfapi_l2_group_cfg list */
|
||||
/* three views into the same collection of rfapi_nve_group_cfg */
|
||||
struct list *nve_groups_sequential;
|
||||
struct route_table nve_groups_vn[AFI_MAX];
|
||||
struct route_table nve_groups_un[AFI_MAX];
|
||||
struct route_table *nve_groups_vn[AFI_MAX];
|
||||
struct route_table *nve_groups_un[AFI_MAX];
|
||||
|
||||
/*
|
||||
* For Single VRF export to ordinary routing protocols. This is
|
||||
|
@ -205,7 +205,7 @@ static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
|
||||
struct prefix p;
|
||||
struct route_node *rn;
|
||||
int rc;
|
||||
int afi;
|
||||
afi_t afi;
|
||||
|
||||
if (!bgp) {
|
||||
return ENXIO;
|
||||
@ -224,7 +224,7 @@ static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
|
||||
if ((rc = rfapiRaddr2Qprefix(un_addr, &p)))
|
||||
return rc;
|
||||
|
||||
rn = route_node_lookup(&h->un[afi], &p);
|
||||
rn = route_node_lookup(h->un[afi], &p);
|
||||
|
||||
if (!rn)
|
||||
return ENOENT;
|
||||
@ -1415,7 +1415,7 @@ int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
assert(afi_vn && afi_un);
|
||||
assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un));
|
||||
|
||||
rn = route_node_get(&(h->un[afi_un]), &pfx_un);
|
||||
rn = route_node_get(h->un[afi_un], &pfx_un);
|
||||
assert(rn);
|
||||
rfd->next = rn->info;
|
||||
rn->info = rfd;
|
||||
@ -2367,7 +2367,7 @@ int rfapi_register(void *handle, struct rfapi_ip_prefix *prefix,
|
||||
struct prefix p;
|
||||
struct prefix *pfx_ip = NULL;
|
||||
struct prefix_rd prd;
|
||||
int afi;
|
||||
afi_t afi;
|
||||
struct prefix pfx_mac_buf;
|
||||
struct prefix *pfx_mac = NULL;
|
||||
struct prefix pfx_vn_buf;
|
||||
|
@ -3872,6 +3872,10 @@ rfapiBgpInfoFilteredImportFunction(safi_t safi)
|
||||
|
||||
case SAFI_ENCAP:
|
||||
return rfapiBgpInfoFilteredImportEncap;
|
||||
|
||||
default:
|
||||
/* not expected */
|
||||
return NULL;
|
||||
}
|
||||
zlog_err("%s: bad safi %d", __func__, safi);
|
||||
return NULL;
|
||||
@ -4248,7 +4252,7 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp,
|
||||
struct rfapi *bgp_rfapi_new(struct bgp *bgp)
|
||||
{
|
||||
struct rfapi *h;
|
||||
int afi;
|
||||
afi_t afi;
|
||||
struct rfapi_rfp_cfg *cfg = NULL;
|
||||
struct rfapi_rfp_cb_methods *cbm = NULL;
|
||||
|
||||
@ -4257,9 +4261,7 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp)
|
||||
h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
/* ugly, to deal with addition of delegates, part of 0.99.24.1
|
||||
* merge */
|
||||
h->un[afi].delegate = route_table_get_default_delegate();
|
||||
h->un[afi] = route_table_init();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4292,6 +4294,8 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp)
|
||||
|
||||
void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
|
||||
{
|
||||
afi_t afi;
|
||||
|
||||
if (bgp == NULL || h == NULL)
|
||||
return;
|
||||
|
||||
@ -4327,6 +4331,11 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
|
||||
|
||||
if (h->rfp != NULL)
|
||||
rfp_stop(h->rfp);
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
route_table_finish(h->un[afi]);
|
||||
}
|
||||
|
||||
XFREE(MTYPE_RFAPI_IMPORTTABLE, h->it_ce);
|
||||
XFREE(MTYPE_RFAPI, h);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ struct rfapi_global_stats {
|
||||
* check vn address to get exact match.
|
||||
*/
|
||||
struct rfapi {
|
||||
struct route_table un[AFI_MAX];
|
||||
struct route_table *un[AFI_MAX];
|
||||
struct rfapi_import_table *imports; /* IPv4, IPv6 */
|
||||
struct list descriptors; /* debug & resolve-nve imports */
|
||||
|
||||
|
@ -2236,9 +2236,12 @@ void rfapiRibShowResponsesSummary(void *stream)
|
||||
struct rfapi_descriptor *rfd;
|
||||
struct listnode *node;
|
||||
|
||||
|
||||
if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
|
||||
return;
|
||||
if (!bgp) {
|
||||
fp(out, "Unable to find default BGP instance\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fp(out, "%-24s ", "Responses: (Prefixes)");
|
||||
fp(out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total);
|
||||
@ -2388,6 +2391,11 @@ void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
|
||||
|
||||
if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
|
||||
return;
|
||||
if (!bgp) {
|
||||
fp(out, "Unable to find default BGP instance\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* loop over NVEs
|
||||
*/
|
||||
|
38
common.am
38
common.am
@ -8,12 +8,21 @@ am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CLIPPY_0 = @echo " CLIPPY " $@;
|
||||
am__v_CLIPPY_1 =
|
||||
|
||||
SUFFIXES = _clippy.c
|
||||
CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
|
||||
|
||||
SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
|
||||
.c_clippy.c:
|
||||
$(AM_V_at)$(MAKE) -C $(top_builddir)/$(CLIPPYDIR) clippy
|
||||
$(AM_V_CLIPPY)$(top_builddir)/$(CLIPPYDIR)/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp
|
||||
@{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
|
||||
$(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp
|
||||
@{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@
|
||||
|
||||
## automake's "ylwrap" is a great piece of GNU software... not.
|
||||
.l.c:
|
||||
$(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $<
|
||||
.y.c:
|
||||
$(AM_V_YACC)$(am__skipyacc) $(YACCCOMPILE) $<
|
||||
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
|
||||
# Uncomment to use an non-system version of libprotobuf-c.
|
||||
@ -27,16 +36,19 @@ Q_PROTOBUF_C_CLIENT_LDOPTS=-lprotobuf-c
|
||||
Q_PROTOC=protoc
|
||||
Q_PROTOC_C=protoc-c
|
||||
|
||||
Q_PROTOBUF_CFILES = $(filter %.pb-c.c,$(SOURCES))
|
||||
|
||||
Q_PROTOBUF_SRCS = $(Q_PROTOBUF_CFILES) $(Q_PROTOBUF_HFILES)
|
||||
|
||||
# Rules
|
||||
%.pb.h: %.proto
|
||||
$(Q_PROTOC) $(PROTOBUF_INCLUDES) --cpp_out=$(top_srcdir) $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
|
||||
.proto.pb.h:
|
||||
$(Q_PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
|
||||
|
||||
%.pb-c.c %.pb-c.h: %.proto
|
||||
$(Q_PROTOC_C) $(PROTOBUF_INCLUDES) --c_out=$(top_srcdir) $(top_srcdir)/$(PROTOBUF_PACKAGE)/$^
|
||||
AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V))
|
||||
am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_PROTOC_C_0 = @echo " PROTOC_C" $@;
|
||||
am__v_PROTOC_C_1 =
|
||||
|
||||
.proto.pb-c.c:
|
||||
$(AM_V_PROTOC_C)$(Q_PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
|
||||
.pb-c.c.pb-c.h:
|
||||
@/bin/true
|
||||
|
||||
#
|
||||
# Information about how to link to various libraries.
|
||||
@ -46,7 +58,3 @@ Q_FRR_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libfrr_pb.la $(Q_PROTOBUF_C_CLIENT_LD
|
||||
Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfrrfpm_pb.la $(Q_FRR_PB_CLIENT_LDOPTS)
|
||||
|
||||
endif # HAVE_PROTOBUF
|
||||
|
||||
Q_CLEANFILES = $(Q_PROTOBUF_SRCS)
|
||||
|
||||
Q_BUILT_SRCS = $(Q_PROTOBUF_SRCS)
|
||||
|
337
configure.ac
337
configure.ac
@ -46,12 +46,12 @@ AS_IF([test "$host" != "$build"], [
|
||||
AC_MSG_NOTICE([...])
|
||||
|
||||
build_clippy="false"
|
||||
CLIPPYDIR="hosttools/lib"
|
||||
HOSTTOOLS="hosttools/"
|
||||
], [
|
||||
build_clippy="true"
|
||||
CLIPPYDIR="lib"
|
||||
HOSTTOOLS=""
|
||||
])
|
||||
AC_SUBST(CLIPPYDIR)
|
||||
AC_SUBST(HOSTTOOLS)
|
||||
AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy])
|
||||
|
||||
# Disable portability warnings -- our automake code (in particular
|
||||
@ -75,14 +75,13 @@ AC_SUBST(exampledir)
|
||||
|
||||
dnl default is to match previous behavior
|
||||
pkgsrcrcdir=""
|
||||
pkgsrcdir=""
|
||||
AC_ARG_ENABLE([pkgsrcrcdir],
|
||||
AS_HELP_STRING([--enable-pkgsrcrcdir],
|
||||
[specify directory for rc.d scripts]),
|
||||
pkgsrcrcdir="$enableval"; pkgsrcdir="pkgsrc",)
|
||||
pkgsrcrcdir="$enableval",)
|
||||
dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
|
||||
AC_SUBST(pkgsrcdir)
|
||||
AC_SUBST(pkgsrcrcdir)
|
||||
AM_CONDITIONAL([PKGSRC], [test "x$pkgsrcrcdir" != "x"])
|
||||
|
||||
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
|
||||
moduledir="$withval"
|
||||
@ -415,26 +414,6 @@ if test "${enable_rr_semantics}" != "no" ; then
|
||||
AC_DEFINE(HAVE_V6_RR_SEMANTICS,, Compile in v6 Route Replacement Semantics)
|
||||
fi
|
||||
|
||||
dnl ----------
|
||||
dnl MPLS check
|
||||
dnl ----------
|
||||
AC_MSG_CHECKING(whether this OS has MPLS stack)
|
||||
case "$host" in
|
||||
*-linux*)
|
||||
MPLS_METHOD="zebra_mpls_netlink.o"
|
||||
AC_MSG_RESULT(Linux MPLS)
|
||||
;;
|
||||
*-openbsd*)
|
||||
MPLS_METHOD="zebra_mpls_openbsd.o"
|
||||
AC_MSG_RESULT(OpenBSD MPLS)
|
||||
;;
|
||||
*)
|
||||
MPLS_METHOD="zebra_mpls_null.o"
|
||||
AC_MSG_RESULT(Unsupported kernel)
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(MPLS_METHOD)
|
||||
|
||||
if test "${enable_datacenter}" = "yes" ; then
|
||||
AC_DEFINE(HAVE_DATACENTER,,Compile extensions for a DataCenter)
|
||||
DFLT_NAME="datacenter"
|
||||
@ -850,50 +829,52 @@ FRR_INCLUDES
|
||||
|
||||
dnl V6 headers are checked below, after we check for v6
|
||||
|
||||
dnl Some systems (Solaris 2.x) require libnsl (Network Services Library)
|
||||
case "$host" in
|
||||
[*-sunos5.[6-7]*] | [*-solaris2.[6-7]*])
|
||||
opsys=sol2-6
|
||||
AC_DEFINE(SUNOS_56, 1, SunOS 5.6 to 5.7)
|
||||
AC_DEFINE(SUNOS_5, 1, SunOS 5)
|
||||
AC_CHECK_LIB(xnet, main)
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
[*-sunos5.[8-9]] \
|
||||
| [*-sunos5.1[0-9]] \
|
||||
| [*-sunos5.1[0-9].[0-9]] \
|
||||
| [*-solaris2.[8-9]] \
|
||||
| [*-solaris2.1[0-9]] \
|
||||
| [*-solaris2.1[0-9].[0-9]])
|
||||
opsys=sol8
|
||||
AC_DEFINE(SUNOS_59, 1, [SunOS 5.8 up])
|
||||
AC_DEFINE(SUNOS_5, 1, [SunOS 5])
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
AC_CHECK_LIB(umem, main)
|
||||
AC_CHECK_FUNCS([printstack],
|
||||
[AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
|
||||
AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
|
||||
])
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
*-sunos5* | *-solaris2*)
|
||||
AC_DEFINE(SUNOS_5,,SunOS 5, Unknown SunOS)
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
*-linux*)
|
||||
opsys=gnu-linux
|
||||
AC_DEFINE(GNU_LINUX,,GNU Linux)
|
||||
;;
|
||||
*-openbsd*)
|
||||
opsys=openbsd
|
||||
AC_DEFINE(OPEN_BSD,,OpenBSD)
|
||||
;;
|
||||
AC_MSG_CHECKING([which operating system interface to use])
|
||||
case "$host_os" in
|
||||
sunos* | solaris2*)
|
||||
AC_MSG_RESULT([Solaris])
|
||||
|
||||
AC_DEFINE(SUNOS_5, 1, [SunOS 5])
|
||||
AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
|
||||
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
AC_CHECK_LIB(umem, main)
|
||||
AC_CHECK_FUNCS([printstack], [
|
||||
AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
|
||||
AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
|
||||
])
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
linux*)
|
||||
AC_MSG_RESULT([Linux])
|
||||
|
||||
AC_DEFINE(GNU_LINUX,,GNU Linux)
|
||||
AC_DEFINE(HAVE_NETLINK,,netlink)
|
||||
AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack)
|
||||
|
||||
dnl Linux has a compilation problem with mixing
|
||||
dnl netinet/in.h and linux/in6.h they are not
|
||||
dnl compatible. There has been discussion on
|
||||
dnl how to fix it but no real progress on implementation
|
||||
dnl when they fix it, remove this
|
||||
AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count)
|
||||
|
||||
AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include <linux/if_link.h>])
|
||||
;;
|
||||
openbsd*)
|
||||
AC_MSG_RESULT([OpenBSD])
|
||||
|
||||
AC_DEFINE(OPEN_BSD,,OpenBSD)
|
||||
AC_DEFINE(KAME,1,KAME IPv6)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([BSD])
|
||||
|
||||
AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
|
||||
AC_DEFINE(KAME,1,KAME IPv6)
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
@ -1049,26 +1030,6 @@ AC_CHECK_HEADER([asm-generic/unistd.h],
|
||||
AC_CHECK_FUNCS(setns)]
|
||||
)
|
||||
|
||||
dnl ------------------------------------
|
||||
dnl Determine routing get and set method
|
||||
dnl ------------------------------------
|
||||
AC_MSG_CHECKING(zebra between kernel interface method)
|
||||
if test x"$opsys" = x"gnu-linux"; then
|
||||
AC_MSG_RESULT(netlink)
|
||||
RT_METHOD=rt_netlink.o
|
||||
KERNEL_METHOD=kernel_netlink.o
|
||||
AC_DEFINE(HAVE_NETLINK,,netlink)
|
||||
netlink=yes
|
||||
AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include <linux/if_link.h>])
|
||||
else
|
||||
AC_MSG_RESULT(Route socket)
|
||||
KERNEL_METHOD="kernel_socket.o"
|
||||
RT_METHOD="rt_socket.o"
|
||||
fi
|
||||
AC_SUBST(RT_METHOD)
|
||||
AC_SUBST(KERNEL_METHOD)
|
||||
AM_CONDITIONAL([HAVE_NETLINK], [test "x$netlink" = "xyes"])
|
||||
|
||||
dnl --------------------------
|
||||
dnl Determine IS-IS I/O method
|
||||
dnl --------------------------
|
||||
@ -1078,27 +1039,32 @@ AC_DEFINE(ISIS_METHOD_BPF, 3, [ constant value for isis method bpf ])
|
||||
AC_CHECK_HEADER(net/bpf.h)
|
||||
AC_CHECK_HEADER(sys/dlpi.h)
|
||||
AC_MSG_CHECKING(zebra IS-IS I/O method)
|
||||
if test x"$opsys" = x"gnu-linux"; then
|
||||
AC_MSG_RESULT(pfpacket)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET"
|
||||
elif test x"$opsys" = x"sol2-6" -o x"$opsys" = x"sol8"; then
|
||||
AC_MSG_RESULT(DLPI)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
|
||||
else
|
||||
if test $ac_cv_header_net_bpf_h = no; then
|
||||
if test $ac_cv_header_sys_dlpi_h = no; then
|
||||
AC_MSG_RESULT(none)
|
||||
AC_MSG_WARN([*** IS-IS support will not be built ***])
|
||||
ISISD=""
|
||||
else
|
||||
AC_MSG_RESULT(DLPI)
|
||||
fi
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_MSG_RESULT(pfpacket)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET"
|
||||
;;
|
||||
solaris* | sunos*)
|
||||
AC_MSG_RESULT(DLPI)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
|
||||
else
|
||||
AC_MSG_RESULT(BPF)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_BPF"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test $ac_cv_header_net_bpf_h = no; then
|
||||
if test $ac_cv_header_sys_dlpi_h = no; then
|
||||
AC_MSG_RESULT(none)
|
||||
AC_MSG_WARN([*** IS-IS support will not be built ***])
|
||||
ISISD=""
|
||||
else
|
||||
AC_MSG_RESULT(DLPI)
|
||||
fi
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
|
||||
else
|
||||
AC_MSG_RESULT(BPF)
|
||||
ISIS_METHOD_MACRO="ISIS_METHOD_BPF"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(ISIS_METHOD, $ISIS_METHOD_MACRO, [ selected method for isis, == one of the constants ])
|
||||
|
||||
dnl ------------------------------------
|
||||
@ -1128,59 +1094,6 @@ main()
|
||||
}]])],[AC_MSG_RESULT(yes - using workaround) AC_DEFINE(HAVE_BROKEN_CMSG_FIRSTHDR,,Broken CMSG_FIRSTHDR)],
|
||||
[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)])
|
||||
|
||||
dnl ------------------------------
|
||||
dnl check kernel route read method
|
||||
dnl ------------------------------
|
||||
AC_CACHE_CHECK([route read method], [frr_cv_rtread_method],
|
||||
[if test "x$netlink" = xyes; then
|
||||
frr_cv_rtread_method="netlink"
|
||||
else
|
||||
for frr_cv_rtread_method in /dev/ip /dev/null;
|
||||
do
|
||||
test x`ls $frr_cv_rtread_method 2>/dev/null` = x"$frr_cv_rtread_method" && break
|
||||
done
|
||||
case $frr_cv_rtread_method in
|
||||
"/dev/ip")
|
||||
case "$host" in
|
||||
*-freebsd*) frr_cv_rtread_method="sysctl";;
|
||||
*) frr_cv_rtread_method="getmsg";;
|
||||
esac;;
|
||||
*)
|
||||
frr_cv_rtread_method="sysctl";;
|
||||
esac
|
||||
fi])
|
||||
RTREAD_METHOD=rtread_${frr_cv_rtread_method}.o
|
||||
AC_SUBST(RTREAD_METHOD)
|
||||
|
||||
dnl -----------------------------
|
||||
dnl check interface lookup method
|
||||
dnl -----------------------------
|
||||
IOCTL_METHOD=ioctl.o
|
||||
AC_MSG_CHECKING(interface looking up method)
|
||||
if test "$netlink" = yes; then
|
||||
AC_MSG_RESULT(netlink)
|
||||
IF_METHOD=if_netlink.o
|
||||
elif test "$opsys" = "sol2-6";then
|
||||
AC_MSG_RESULT(Solaris GIF)
|
||||
IF_METHOD=if_ioctl.o
|
||||
elif test "$opsys" = "sol8";then
|
||||
AC_MSG_RESULT(Solaris GLIF)
|
||||
IF_METHOD=if_ioctl_solaris.o
|
||||
IOCTL_METHOD=ioctl_solaris.o
|
||||
elif test "$opsys" = "openbsd";then
|
||||
AC_MSG_RESULT(openbsd)
|
||||
IF_METHOD=if_ioctl.o
|
||||
elif grep NET_RT_IFLIST /usr/include/sys/socket.h >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT(sysctl)
|
||||
IF_METHOD=if_sysctl.o
|
||||
AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
|
||||
else
|
||||
AC_MSG_RESULT(ioctl)
|
||||
IF_METHOD=if_ioctl.o
|
||||
fi
|
||||
AC_SUBST(IF_METHOD)
|
||||
AC_SUBST(IOCTL_METHOD)
|
||||
|
||||
dnl ---------------------------------------------------------------
|
||||
dnl figure out how to specify an interface in multicast sockets API
|
||||
dnl ---------------------------------------------------------------
|
||||
@ -1276,71 +1189,11 @@ if test $ac_cv_have_decl_TCP_MD5SIG = no; then
|
||||
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)])
|
||||
fi
|
||||
|
||||
dnl -----------------------------
|
||||
dnl check ipforward detect method
|
||||
dnl -----------------------------
|
||||
AC_CACHE_CHECK([ipforward method], [frr_cv_ipforward_method],
|
||||
[if test x$cross_compiling = xyes; then
|
||||
if test x"$opsys" = x"gnu-linux"; then
|
||||
frr_cv_ipforward_method=/proc/net/snmp
|
||||
else
|
||||
frr_cv_ipforward_method=/dev/ip
|
||||
fi
|
||||
else
|
||||
for frr_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
|
||||
do
|
||||
test x`ls $frr_cv_ipforward_method 2>/dev/null` = x"$frr_cv_ipforward_method" && break
|
||||
done
|
||||
fi
|
||||
case $frr_cv_ipforward_method in
|
||||
"/proc/net/snmp") frr_cv_ipforward_method="proc";;
|
||||
"/dev/ip")
|
||||
case "$host" in
|
||||
*-freebsd*) frr_cv_ipforward_method="sysctl";;
|
||||
*) frr_cv_ipforward_method="solaris";;
|
||||
esac;;
|
||||
*) frr_cv_ipforward_method="sysctl";;
|
||||
esac])
|
||||
IPFORWARD=ipforward_${frr_cv_ipforward_method}.o
|
||||
AC_SUBST(IPFORWARD)
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl figure out if domainname is available in the utsname struct (GNU extension).
|
||||
dnl ----------------------------------------------------------------------------
|
||||
AC_CHECK_MEMBERS([struct utsname.domainname], [], [], [#include <sys/utsname.h>])
|
||||
|
||||
dnl ----------
|
||||
dnl IPv6 check
|
||||
dnl ----------
|
||||
AC_MSG_CHECKING(whether does this OS have IPv6 stack)
|
||||
dnl ---------
|
||||
dnl KAME IPv6
|
||||
dnl ---------
|
||||
if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
|
||||
AC_DEFINE(KAME,1,KAME IPv6)
|
||||
AC_MSG_RESULT(KAME)
|
||||
dnl ------------------------------------
|
||||
dnl Solaris 9, 10 and potentially higher
|
||||
dnl ------------------------------------
|
||||
elif test x"$opsys" = x"sol8"; then
|
||||
AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
|
||||
AC_MSG_RESULT(Solaris IPv6)
|
||||
dnl ----------
|
||||
dnl Linux IPv6
|
||||
dnl ----------
|
||||
elif test x"$opsys" = x"gnu-linux"; then
|
||||
AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack)
|
||||
dnl Linux has a compilation problem with mixing
|
||||
dnl netinet/in.h and linux/in6.h they are not
|
||||
dnl compatible. There has been discussion on
|
||||
dnl how to fix it but no real progress on implementation
|
||||
dnl when they fix it, remove this
|
||||
AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count)
|
||||
AC_MSG_RESULT(Linux IPv6)
|
||||
else
|
||||
AC_MSG_ERROR([Failed to detect IPv6 stack])
|
||||
fi
|
||||
|
||||
dnl ------------------
|
||||
dnl IPv6 header checks
|
||||
dnl ------------------
|
||||
@ -1375,12 +1228,7 @@ fi
|
||||
dnl --------------------
|
||||
dnl Daemon disable check
|
||||
dnl --------------------
|
||||
if test "${enable_zebra}" = "no";then
|
||||
ZEBRA=""
|
||||
else
|
||||
ZEBRA="zebra"
|
||||
fi
|
||||
AM_CONDITIONAL(ZEBRA, test "x$ZEBRA" = "xzebra")
|
||||
AM_CONDITIONAL(ZEBRA, test "${enable_zebra}" != "no")
|
||||
|
||||
if test "${enable_bgpd}" = "no";then
|
||||
BGPD=""
|
||||
@ -1412,15 +1260,18 @@ fi
|
||||
AM_CONDITIONAL(LDPD, test "x$LDPD" = "xldpd")
|
||||
|
||||
NHRPD=""
|
||||
if test "$opsys" = "gnu-linux"; then
|
||||
if test "${enable_nhrpd}" != "no"; then
|
||||
NHRPD="nhrpd"
|
||||
fi
|
||||
else
|
||||
if test "${enable_nhrpd}" = "yes"; then
|
||||
AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.])
|
||||
fi
|
||||
fi
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
if test "${enable_nhrpd}" != "no"; then
|
||||
NHRPD="nhrpd"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test "${enable_nhrpd}" = "yes"; then
|
||||
AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
|
||||
|
||||
if test "${enable_eigrpd}" = "no";then
|
||||
@ -1506,7 +1357,6 @@ fi
|
||||
AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
|
||||
|
||||
AC_SUBST(DOC)
|
||||
AC_SUBST(ZEBRA)
|
||||
AC_SUBST(RFPTEST)
|
||||
AC_SUBST(LIBRFP)
|
||||
AC_SUBST(RFPINC)
|
||||
@ -1969,22 +1819,17 @@ AC_CACHE_VAL(ac_cv_htonl_works,
|
||||
)
|
||||
AC_MSG_RESULT($ac_cv_htonl_works)
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
|
||||
AC_CONFIG_FILES([Makefile ripd/Makefile
|
||||
ripngd/Makefile bgpd/Makefile ospfd/Makefile watchfrr/Makefile
|
||||
ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
|
||||
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
|
||||
doc/Makefile ospfclient/Makefile tests/Makefile
|
||||
bgpd/rfp-example/rfptest/Makefile bgpd/rfp-example/librfp/Makefile
|
||||
babeld/Makefile
|
||||
pimd/Makefile
|
||||
eigrpd/Makefile
|
||||
nhrpd/Makefile
|
||||
redhat/Makefile
|
||||
tools/Makefile
|
||||
pkgsrc/Makefile
|
||||
python/Makefile
|
||||
fpm/Makefile
|
||||
redhat/frr.spec
|
||||
snapcraft/Makefile
|
||||
snapcraft/snapcraft.yaml
|
||||
lib/version.h
|
||||
tests/lib/cli/test_cli.refout
|
||||
|
@ -17,6 +17,9 @@ CentOS 6 restrictions:
|
||||
- Zebra is unable to detect what bridge/vrf an interface is associcated
|
||||
with (IFLA_INFO_SLAVE_KIND does not exist in the kernel headers, you
|
||||
can use a newer kernel + headers to get this functionality)
|
||||
- frr_reload.py will not work, as this requires Python 2.7, and CentOS 6
|
||||
only has 2.6. You can install Python 2.7 via IUS, but it won't work
|
||||
properly unless you compile and install the ipaddr package for it.
|
||||
|
||||
Install required packages
|
||||
-------------------------
|
||||
|
@ -179,8 +179,8 @@ The default is 4@dmn{s}.
|
||||
@node Babel redistribution, Show Babel information, Babel configuration, Babel
|
||||
@section Babel redistribution
|
||||
|
||||
@deffn {Babel command} {redistribute @var{kind}}
|
||||
@deffnx {Babel command} {no redistribute @var{kind}}
|
||||
@deffn {Babel command} {redistribute @var{<ipv4|ipv6>} @var{kind}}
|
||||
@deffnx {Babel command} {no redistribute @var{<ipv4|ipv6>} @var{kind}}
|
||||
Specify which kind of routes should be redistributed into Babel.
|
||||
@end deffn
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "keychain.h"
|
||||
#include "distribute.h"
|
||||
#include "libfrr.h"
|
||||
//#include "routemap.h"
|
||||
#include "routemap.h"
|
||||
//#include "if_rmap.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
@ -192,6 +192,11 @@ int main(int argc, char **argv, char **envp)
|
||||
prefix_list_add_hook(eigrp_distribute_update_all);
|
||||
prefix_list_delete_hook(eigrp_distribute_update_all);
|
||||
|
||||
/*
|
||||
* XXX: This is just to get the CLI installed to suppress VTYSH errors.
|
||||
* Routemaps in EIGRP are not yet functional.
|
||||
*/
|
||||
route_map_init();
|
||||
/*eigrp_route_map_init();
|
||||
route_map_add_hook (eigrp_rmap_update);
|
||||
route_map_delete_hook (eigrp_rmap_update);*/
|
||||
|
@ -237,6 +237,11 @@ DEFUN (no_router_eigrp,
|
||||
struct eigrp *eigrp;
|
||||
|
||||
eigrp = eigrp_lookup();
|
||||
if (eigrp == NULL) {
|
||||
vty_out(vty, " EIGRP Routing Process not enabled\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (eigrp->AS != atoi(argv[3]->arg)) {
|
||||
vty_out(vty, "%% Attempting to deconfigure non-existent AS\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1000,9 +1005,11 @@ DEFUN (eigrp_redistribute_source_metric,
|
||||
|
||||
/* Get distribute source. */
|
||||
argv_find(argv, argc, "redistribute", &idx);
|
||||
source = proto_redistnum(AFI_IP, argv[idx + 1]->arg);
|
||||
if (source < 0)
|
||||
source = proto_redistnum(AFI_IP, argv[idx + 1]->text);
|
||||
if (source < 0) {
|
||||
vty_out(vty, "%% Invalid route type\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Get metrics values */
|
||||
|
||||
@ -1029,9 +1036,11 @@ DEFUN (no_eigrp_redistribute_source_metric,
|
||||
|
||||
/* Get distribute source. */
|
||||
argv_find(argv, argc, "redistribute", &idx);
|
||||
source = proto_redistnum(AFI_IP, argv[idx + 1]->arg);
|
||||
if (source < 0)
|
||||
source = proto_redistnum(AFI_IP, argv[idx + 1]->text);
|
||||
if (source < 0) {
|
||||
vty_out(vty, "%% Invalid route type\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Get metrics values */
|
||||
|
||||
|
2
fpm/.gitignore
vendored
2
fpm/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
Makefile
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
tags
|
||||
|
10
fpm/Makefile
Normal file
10
fpm/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C .. fpm/libfrrfpm_pb.la
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C .. fpm/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
@ -1,29 +0,0 @@
|
||||
include ../common.am
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
|
||||
|
||||
PROTOBUF_INCLUDES=-I$(top_srcdir)
|
||||
PROTOBUF_PACKAGE = fpm
|
||||
|
||||
lib_LTLIBRARIES = libfrrfpm_pb.la
|
||||
libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
protobuf_srcs =
|
||||
|
||||
protobuf_srcs_nodist = \
|
||||
fpm.pb-c.c
|
||||
endif
|
||||
|
||||
libfrrfpm_pb_la_SOURCES = \
|
||||
fpm.h \
|
||||
fpm_pb.h \
|
||||
fpm_pb.c \
|
||||
$(protobuf_srcs)
|
||||
|
||||
nodist_libfrrfpm_pb_la_SOURCES = $(protobuf_srcs_nodist)
|
||||
|
||||
CLEANFILES = $(Q_CLEANFILES)
|
||||
|
||||
BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
|
||||
EXTRA_DIST = fpm.proto
|
@ -20,6 +20,8 @@
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
//
|
||||
// Protobuf definitions pertaining to the Forwarding Plane Manager component.
|
||||
//
|
||||
|
23
fpm/subdir.am
Normal file
23
fpm/subdir.am
Normal file
@ -0,0 +1,23 @@
|
||||
if FPM
|
||||
lib_LTLIBRARIES += fpm/libfrrfpm_pb.la
|
||||
endif
|
||||
|
||||
fpm_libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
|
||||
fpm_libfrrfpm_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
|
||||
$(Q_PROTOBUF_C_CLIENT_INCLUDES)
|
||||
fpm_libfrrfpm_pb_la_SOURCES = \
|
||||
fpm/fpm.h \
|
||||
fpm/fpm_pb.h \
|
||||
fpm/fpm_pb.c \
|
||||
# end
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
nodist_fpm_libfrrfpm_pb_la_SOURCES = fpm/fpm.pb-c.c
|
||||
BUILT_SOURCES += fpm/fpm.pb-c.c
|
||||
CLEANFILES += \
|
||||
fpm/fpm.pb-c.c \
|
||||
fpm/fpm.pb-c.h \
|
||||
# end
|
||||
endif
|
||||
|
||||
EXTRA_DIST += fpm/fpm.proto
|
1
ldpd/.gitignore
vendored
1
ldpd/.gitignore
vendored
@ -15,3 +15,4 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
ldp_vty_cmds_clippy.c
|
||||
|
@ -1,5 +1,7 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
include ../common.am
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
@ -16,6 +18,8 @@ libldp_a_SOURCES = \
|
||||
socket.c util.c ldp_vty_cmds.c ldp_vty_conf.c ldp_vty_exec.c \
|
||||
ldp_debug.c ldp_zebra.c
|
||||
|
||||
ldp_vty_cmds.o: ldp_vty_cmds_clippy.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h
|
||||
|
||||
|
@ -1328,7 +1328,6 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
|
||||
struct lde_map *me;
|
||||
|
||||
RB_FOREACH(fec, fec_tree, &ln->recv_map) {
|
||||
fn = (struct fec_node *)fec_find(&ft, fec);
|
||||
switch (fec->type) {
|
||||
case FEC_TYPE_IPV4:
|
||||
if (lde_addr->af != AF_INET)
|
||||
@ -1342,6 +1341,11 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
|
||||
continue;
|
||||
}
|
||||
|
||||
fn = (struct fec_node *)fec_find(&ft, fec);
|
||||
if (fn == NULL)
|
||||
/* shouldn't happen */
|
||||
continue;
|
||||
|
||||
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||
if (ldp_addrcmp(fnh->af, &fnh->nexthop,
|
||||
&lde_addr->addr))
|
||||
|
@ -38,31 +38,31 @@ struct cmd_node ldp_debug_node =
|
||||
};
|
||||
|
||||
int
|
||||
ldp_vty_debug(struct vty *vty, int disable, const char *type_str,
|
||||
const char *dir_str, int all)
|
||||
ldp_vty_debug(struct vty *vty, const char *negate, const char *type_str,
|
||||
const char *dir_str, const char *all)
|
||||
{
|
||||
if (strcmp(type_str, "discovery") == 0) {
|
||||
if (dir_str == NULL)
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
|
||||
if (dir_str[0] == 'r') {
|
||||
if (disable)
|
||||
if (negate)
|
||||
DEBUG_OFF(hello, HELLO_RECV);
|
||||
else
|
||||
DEBUG_ON(hello, HELLO_RECV);
|
||||
} else {
|
||||
if (disable)
|
||||
if (negate)
|
||||
DEBUG_OFF(hello, HELLO_SEND);
|
||||
else
|
||||
DEBUG_ON(hello, HELLO_SEND);
|
||||
}
|
||||
} else if (strcmp(type_str, "errors") == 0) {
|
||||
if (disable)
|
||||
if (negate)
|
||||
DEBUG_OFF(errors, ERRORS);
|
||||
else
|
||||
DEBUG_ON(errors, ERRORS);
|
||||
} else if (strcmp(type_str, "event") == 0) {
|
||||
if (disable)
|
||||
if (negate)
|
||||
DEBUG_OFF(event, EVENT);
|
||||
else
|
||||
DEBUG_ON(event, EVENT);
|
||||
@ -71,7 +71,7 @@ ldp_vty_debug(struct vty *vty, int disable, const char *type_str,
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
|
||||
if (dir_str[0] == 'r') {
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
DEBUG_OFF(msg, MSG_RECV);
|
||||
DEBUG_OFF(msg, MSG_RECV_ALL);
|
||||
} else {
|
||||
@ -80,7 +80,7 @@ ldp_vty_debug(struct vty *vty, int disable, const char *type_str,
|
||||
DEBUG_ON(msg, MSG_RECV_ALL);
|
||||
}
|
||||
} else {
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
DEBUG_OFF(msg, MSG_SEND);
|
||||
DEBUG_OFF(msg, MSG_SEND_ALL);
|
||||
} else {
|
||||
@ -90,7 +90,7 @@ ldp_vty_debug(struct vty *vty, int disable, const char *type_str,
|
||||
}
|
||||
}
|
||||
} else if (strcmp(type_str, "zebra") == 0) {
|
||||
if (disable)
|
||||
if (negate)
|
||||
DEBUG_OFF(zebra, ZEBRA);
|
||||
else
|
||||
DEBUG_ON(zebra, ZEBRA);
|
||||
|
@ -36,46 +36,46 @@ int ldp_get_address(const char *, int *, union ldpd_addr *);
|
||||
int ldp_config_write(struct vty *);
|
||||
int ldp_l2vpn_config_write(struct vty *);
|
||||
int ldp_debug_config_write(struct vty *);
|
||||
int ldp_vty_mpls_ldp (struct vty *, int);
|
||||
int ldp_vty_address_family (struct vty *, int, const char *);
|
||||
int ldp_vty_disc_holdtime(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_disc_interval(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_targeted_hello_accept(struct vty *, int, const char *);
|
||||
int ldp_vty_nbr_session_holdtime(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_af_session_holdtime(struct vty *, int, const char *);
|
||||
int ldp_vty_interface(struct vty *, int, const char *);
|
||||
int ldp_vty_trans_addr(struct vty *, int, const char *);
|
||||
int ldp_vty_neighbor_targeted(struct vty *, int, const char *);
|
||||
int ldp_vty_label_advertise(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_label_allocate(struct vty *, int, int, const char *);
|
||||
int ldp_vty_label_expnull(struct vty *, int, const char *);
|
||||
int ldp_vty_label_accept(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_ttl_security(struct vty *, int);
|
||||
int ldp_vty_router_id(struct vty *, int, const char *);
|
||||
int ldp_vty_ds_cisco_interop(struct vty *, int);
|
||||
int ldp_vty_trans_pref_ipv4(struct vty *, int);
|
||||
int ldp_vty_neighbor_password(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_neighbor_ttl_security(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_l2vpn(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_bridge(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_mtu(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pwtype(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_interface(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pseudowire(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pw_cword(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pw_nbr_addr(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pw_nbr_id(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pw_pwid(struct vty *, int, const char *);
|
||||
int ldp_vty_l2vpn_pw_pwstatus(struct vty *, int);
|
||||
int ldp_vty_mpls_ldp (struct vty *, const char *);
|
||||
int ldp_vty_address_family (struct vty *, const char *, const char *);
|
||||
int ldp_vty_disc_holdtime(struct vty *, const char *, const char *, long);
|
||||
int ldp_vty_disc_interval(struct vty *, const char *, const char *, long);
|
||||
int ldp_vty_targeted_hello_accept(struct vty *, const char *, const char *);
|
||||
int ldp_vty_nbr_session_holdtime(struct vty *, const char *, struct in_addr, long);
|
||||
int ldp_vty_af_session_holdtime(struct vty *, const char *, long);
|
||||
int ldp_vty_interface(struct vty *, const char *, const char *);
|
||||
int ldp_vty_trans_addr(struct vty *, const char *, const char *);
|
||||
int ldp_vty_neighbor_targeted(struct vty *, const char *, const char *);
|
||||
int ldp_vty_label_advertise(struct vty *, const char *, const char *, const char *);
|
||||
int ldp_vty_label_allocate(struct vty *, const char *, const char *, const char *);
|
||||
int ldp_vty_label_expnull(struct vty *, const char *, const char *);
|
||||
int ldp_vty_label_accept(struct vty *, const char *, const char *, const char *);
|
||||
int ldp_vty_ttl_security(struct vty *, const char *);
|
||||
int ldp_vty_router_id(struct vty *, const char *, struct in_addr);
|
||||
int ldp_vty_ds_cisco_interop(struct vty *, const char *);
|
||||
int ldp_vty_trans_pref_ipv4(struct vty *, const char *);
|
||||
int ldp_vty_neighbor_password(struct vty *, const char *, struct in_addr, const char *);
|
||||
int ldp_vty_neighbor_ttl_security(struct vty *, const char *, struct in_addr, const char *);
|
||||
int ldp_vty_l2vpn(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_bridge(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_mtu(struct vty *, const char *, long);
|
||||
int ldp_vty_l2vpn_pwtype(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_interface(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_pseudowire(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_pw_cword(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_pw_nbr_addr(struct vty *, const char *, const char *);
|
||||
int ldp_vty_l2vpn_pw_nbr_id(struct vty *, const char *, struct in_addr);
|
||||
int ldp_vty_l2vpn_pw_pwid(struct vty *, const char *, long);
|
||||
int ldp_vty_l2vpn_pw_pwstatus(struct vty *, const char *);
|
||||
int ldp_vty_clear_nbr(struct vty *, const char *);
|
||||
int ldp_vty_debug(struct vty *, int, const char *, const char *, int);
|
||||
int ldp_vty_show_binding(struct vty *, const char *, int, int);
|
||||
int ldp_vty_show_discovery(struct vty *, const char *, int, int);
|
||||
int ldp_vty_show_interface(struct vty *, const char *, int);
|
||||
int ldp_vty_show_capabilities(struct vty *, int);
|
||||
int ldp_vty_show_neighbor(struct vty *, int, int, int);
|
||||
int ldp_vty_show_atom_binding(struct vty *, int);
|
||||
int ldp_vty_show_atom_vc(struct vty *, int);
|
||||
int ldp_vty_debug(struct vty *, const char *, const char *, const char *, const char *);
|
||||
int ldp_vty_show_binding(struct vty *, const char *, const char *, const char *);
|
||||
int ldp_vty_show_discovery(struct vty *, const char *, const char *, const char *);
|
||||
int ldp_vty_show_interface(struct vty *, const char *, const char *);
|
||||
int ldp_vty_show_capabilities(struct vty *, const char *);
|
||||
int ldp_vty_show_neighbor(struct vty *, int, const char *, const char *);
|
||||
int ldp_vty_show_atom_binding(struct vty *, const char *);
|
||||
int ldp_vty_show_atom_vc(struct vty *, const char *);
|
||||
int ldp_vty_show_debugging(struct vty *);
|
||||
|
||||
void ldp_vty_init(void);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -233,7 +233,7 @@ ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf,
|
||||
|
||||
ldp_af_iface_config_write(vty, af);
|
||||
|
||||
vty_out (vty, " !\n");
|
||||
vty_out(vty, " exit-address-family\n");
|
||||
}
|
||||
|
||||
int
|
||||
@ -407,9 +407,9 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_mpls_ldp(struct vty *vty, int disable)
|
||||
ldp_vty_mpls_ldp(struct vty *vty, const char *negate)
|
||||
{
|
||||
if (disable)
|
||||
if (negate)
|
||||
vty_conf->flags &= ~F_LDPD_ENABLED;
|
||||
else {
|
||||
vty->node = LDP_NODE;
|
||||
@ -422,7 +422,7 @@ ldp_vty_mpls_ldp(struct vty *vty, int disable)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_address_family(struct vty *vty, int disable, const char *af_str)
|
||||
ldp_vty_address_family(struct vty *vty, const char *negate, const char *af_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
int af;
|
||||
@ -436,7 +436,7 @@ ldp_vty_address_family(struct vty *vty, int disable, const char *af_str)
|
||||
} else
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
af_conf->flags &= ~F_LDPD_AF_ENABLED;
|
||||
ldp_config_apply(vty, vty_conf);
|
||||
return (CMD_SUCCESS);
|
||||
@ -460,23 +460,15 @@ ldp_vty_address_family(struct vty *vty, int disable, const char *af_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_disc_holdtime(struct vty *vty, int disable, const char *hello_type_str,
|
||||
const char *seconds_str)
|
||||
ldp_vty_disc_holdtime(struct vty *vty, const char *negate,
|
||||
const char *hello_type_str, long secs)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
struct iface *iface;
|
||||
struct iface_af *ia;
|
||||
int af;
|
||||
char *ep;
|
||||
long int secs;
|
||||
enum hello_type hello_type;
|
||||
|
||||
secs = strtol(seconds_str, &ep, 10);
|
||||
if (*ep != '\0' || secs < MIN_HOLDTIME || secs > MAX_HOLDTIME) {
|
||||
vty_out (vty, "%% Invalid holdtime\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (hello_type_str[0] == 'h')
|
||||
hello_type = HELLO_LINK;
|
||||
else
|
||||
@ -484,7 +476,7 @@ ldp_vty_disc_holdtime(struct vty *vty, int disable, const char *hello_type_str,
|
||||
|
||||
switch (vty->node) {
|
||||
case LDP_NODE:
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
switch (hello_type) {
|
||||
case HELLO_LINK:
|
||||
vty_conf->lhello_holdtime = LINK_DFLT_HOLDTIME;
|
||||
@ -511,7 +503,7 @@ ldp_vty_disc_holdtime(struct vty *vty, int disable, const char *hello_type_str,
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
switch (hello_type) {
|
||||
case HELLO_LINK:
|
||||
af_conf->lhello_holdtime = 0;
|
||||
@ -539,7 +531,7 @@ ldp_vty_disc_holdtime(struct vty *vty, int disable, const char *hello_type_str,
|
||||
VTY_CHECK_CONTEXT(iface);
|
||||
|
||||
ia = iface_af_get(iface, af);
|
||||
if (disable)
|
||||
if (negate)
|
||||
ia->hello_holdtime = 0;
|
||||
else
|
||||
ia->hello_holdtime = secs;
|
||||
@ -554,24 +546,15 @@ ldp_vty_disc_holdtime(struct vty *vty, int disable, const char *hello_type_str,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_disc_interval(struct vty *vty, int disable, const char *hello_type_str,
|
||||
const char *seconds_str)
|
||||
ldp_vty_disc_interval(struct vty *vty, const char *negate,
|
||||
const char *hello_type_str, long secs)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
struct iface *iface;
|
||||
struct iface_af *ia;
|
||||
int af;
|
||||
char *ep;
|
||||
long int secs;
|
||||
enum hello_type hello_type;
|
||||
|
||||
secs = strtol(seconds_str, &ep, 10);
|
||||
if (*ep != '\0' || secs < MIN_HELLO_INTERVAL ||
|
||||
secs > MAX_HELLO_INTERVAL) {
|
||||
vty_out (vty, "%% Invalid interval\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (hello_type_str[0] == 'h')
|
||||
hello_type = HELLO_LINK;
|
||||
else
|
||||
@ -579,14 +562,15 @@ ldp_vty_disc_interval(struct vty *vty, int disable, const char *hello_type_str,
|
||||
|
||||
switch (vty->node) {
|
||||
case LDP_NODE:
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
switch (hello_type) {
|
||||
case HELLO_LINK:
|
||||
vty_conf->lhello_interval = LINK_DFLT_HOLDTIME;
|
||||
vty_conf->lhello_interval =
|
||||
DEFAULT_HELLO_INTERVAL;
|
||||
break;
|
||||
case HELLO_TARGETED:
|
||||
vty_conf->thello_interval =
|
||||
TARGETED_DFLT_HOLDTIME;
|
||||
DEFAULT_HELLO_INTERVAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -606,7 +590,7 @@ ldp_vty_disc_interval(struct vty *vty, int disable, const char *hello_type_str,
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
switch (hello_type) {
|
||||
case HELLO_LINK:
|
||||
af_conf->lhello_interval = 0;
|
||||
@ -634,7 +618,7 @@ ldp_vty_disc_interval(struct vty *vty, int disable, const char *hello_type_str,
|
||||
VTY_CHECK_CONTEXT(iface);
|
||||
|
||||
ia = iface_af_get(iface, af);
|
||||
if (disable)
|
||||
if (negate)
|
||||
ia->hello_interval = 0;
|
||||
else
|
||||
ia->hello_interval = secs;
|
||||
@ -649,7 +633,7 @@ ldp_vty_disc_interval(struct vty *vty, int disable, const char *hello_type_str,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_targeted_hello_accept(struct vty *vty, int disable,
|
||||
ldp_vty_targeted_hello_accept(struct vty *vty, const char *negate,
|
||||
const char *acl_from_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
@ -658,7 +642,7 @@ ldp_vty_targeted_hello_accept(struct vty *vty, int disable,
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
af_conf->flags &= ~F_LDPD_AF_THELLO_ACCEPT;
|
||||
af_conf->acl_thello_accept_from[0] = '\0';
|
||||
} else {
|
||||
@ -676,29 +660,19 @@ ldp_vty_targeted_hello_accept(struct vty *vty, int disable,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_nbr_session_holdtime(struct vty *vty, int disable,
|
||||
const char *lsr_id_str, const char *seconds_str)
|
||||
ldp_vty_nbr_session_holdtime(struct vty *vty, const char *negate,
|
||||
struct in_addr lsr_id, long secs)
|
||||
{
|
||||
char *ep;
|
||||
long int secs;
|
||||
struct in_addr lsr_id;
|
||||
struct nbr_params *nbrp;
|
||||
|
||||
if (inet_pton(AF_INET, lsr_id_str, &lsr_id) != 1 ||
|
||||
bad_addr_v4(lsr_id)) {
|
||||
if (bad_addr_v4(lsr_id)) {
|
||||
vty_out (vty, "%% Malformed address\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
secs = strtol(seconds_str, &ep, 10);
|
||||
if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) {
|
||||
vty_out (vty, "%% Invalid holdtime\n");
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
|
||||
nbrp = nbr_params_find(vty_conf, lsr_id);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (nbrp == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -722,24 +696,15 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, int disable,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_af_session_holdtime(struct vty *vty, int disable,
|
||||
const char *seconds_str)
|
||||
ldp_vty_af_session_holdtime(struct vty *vty, const char *negate, long secs)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
int af;
|
||||
char *ep;
|
||||
long int secs;
|
||||
|
||||
secs = strtol(seconds_str, &ep, 10);
|
||||
if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) {
|
||||
vty_out (vty, "%% Invalid holdtime\n");
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
af_conf->keepalive = DEFAULT_KEEPALIVE;
|
||||
else
|
||||
af_conf->keepalive = secs;
|
||||
@ -750,7 +715,7 @@ ldp_vty_af_session_holdtime(struct vty *vty, int disable,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_interface(struct vty *vty, int disable, const char *ifname)
|
||||
ldp_vty_interface(struct vty *vty, const char *negate, const char *ifname)
|
||||
{
|
||||
int af;
|
||||
struct iface *iface;
|
||||
@ -759,7 +724,7 @@ ldp_vty_interface(struct vty *vty, int disable, const char *ifname)
|
||||
af = ldp_vty_get_af(vty);
|
||||
iface = if_lookup_name(vty_conf, ifname);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (iface == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -812,7 +777,7 @@ ldp_vty_interface(struct vty *vty, int disable, const char *ifname)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_trans_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
ldp_vty_trans_addr(struct vty *vty, const char *negate, const char *addr_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
int af;
|
||||
@ -820,7 +785,7 @@ ldp_vty_trans_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
memset(&af_conf->trans_addr, 0, sizeof(af_conf->trans_addr));
|
||||
else {
|
||||
if (inet_pton(af, addr_str, &af_conf->trans_addr) != 1 ||
|
||||
@ -836,7 +801,7 @@ ldp_vty_trans_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_neighbor_targeted(struct vty *vty, int disable, const char *addr_str)
|
||||
ldp_vty_neighbor_targeted(struct vty *vty, const char *negate, const char *addr_str)
|
||||
{
|
||||
int af;
|
||||
union ldpd_addr addr;
|
||||
@ -856,7 +821,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, int disable, const char *addr_str)
|
||||
|
||||
tnbr = tnbr_find(vty_conf, af, &addr);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (tnbr == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -883,7 +848,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, int disable, const char *addr_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_label_advertise(struct vty *vty, int disable, const char *acl_to_str,
|
||||
ldp_vty_label_advertise(struct vty *vty, const char *negate, const char *acl_to_str,
|
||||
const char *acl_for_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
@ -892,7 +857,7 @@ ldp_vty_label_advertise(struct vty *vty, int disable, const char *acl_to_str,
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
af_conf->acl_label_advertise_to[0] = '\0';
|
||||
af_conf->acl_label_advertise_for[0] = '\0';
|
||||
} else {
|
||||
@ -914,7 +879,7 @@ ldp_vty_label_advertise(struct vty *vty, int disable, const char *acl_to_str,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_label_allocate(struct vty *vty, int disable, int host_routes,
|
||||
ldp_vty_label_allocate(struct vty *vty, const char *negate, const char *host_routes,
|
||||
const char *acl_for_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
@ -925,7 +890,7 @@ ldp_vty_label_allocate(struct vty *vty, int disable, int host_routes,
|
||||
|
||||
af_conf->flags &= ~F_LDPD_AF_ALLOCHOSTONLY;
|
||||
af_conf->acl_label_allocate_for[0] = '\0';
|
||||
if (!disable) {
|
||||
if (!negate) {
|
||||
if (host_routes)
|
||||
af_conf->flags |= F_LDPD_AF_ALLOCHOSTONLY;
|
||||
else
|
||||
@ -939,7 +904,7 @@ ldp_vty_label_allocate(struct vty *vty, int disable, int host_routes,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_label_expnull(struct vty *vty, int disable, const char *acl_for_str)
|
||||
ldp_vty_label_expnull(struct vty *vty, const char *negate, const char *acl_for_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
int af;
|
||||
@ -947,7 +912,7 @@ ldp_vty_label_expnull(struct vty *vty, int disable, const char *acl_for_str)
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
af_conf->flags &= ~F_LDPD_AF_EXPNULL;
|
||||
af_conf->acl_label_expnull_for[0] = '\0';
|
||||
} else {
|
||||
@ -965,7 +930,7 @@ ldp_vty_label_expnull(struct vty *vty, int disable, const char *acl_for_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_label_accept(struct vty *vty, int disable, const char *acl_from_str,
|
||||
ldp_vty_label_accept(struct vty *vty, const char *negate, const char *acl_from_str,
|
||||
const char *acl_for_str)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
@ -974,7 +939,7 @@ ldp_vty_label_accept(struct vty *vty, int disable, const char *acl_from_str,
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
af_conf->acl_label_accept_from[0] = '\0';
|
||||
af_conf->acl_label_accept_for[0] = '\0';
|
||||
} else {
|
||||
@ -996,7 +961,7 @@ ldp_vty_label_accept(struct vty *vty, int disable, const char *acl_from_str,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_ttl_security(struct vty *vty, int disable)
|
||||
ldp_vty_ttl_security(struct vty *vty, const char *negate)
|
||||
{
|
||||
struct ldpd_af_conf *af_conf;
|
||||
int af;
|
||||
@ -1004,7 +969,7 @@ ldp_vty_ttl_security(struct vty *vty, int disable)
|
||||
af = ldp_vty_get_af(vty);
|
||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
af_conf->flags &= ~F_LDPD_AF_NO_GTSM;
|
||||
else
|
||||
af_conf->flags |= F_LDPD_AF_NO_GTSM;
|
||||
@ -1015,16 +980,16 @@ ldp_vty_ttl_security(struct vty *vty, int disable)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_router_id(struct vty *vty, int disable, const char *addr_str)
|
||||
ldp_vty_router_id(struct vty *vty, const char *negate, struct in_addr address)
|
||||
{
|
||||
if (disable)
|
||||
if (negate)
|
||||
vty_conf->rtr_id.s_addr = INADDR_ANY;
|
||||
else {
|
||||
if (inet_pton(AF_INET, addr_str, &vty_conf->rtr_id) != 1 ||
|
||||
bad_addr_v4(vty_conf->rtr_id)) {
|
||||
if (bad_addr_v4(address)) {
|
||||
vty_out (vty, "%% Malformed address\n");
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
vty_conf->rtr_id = address;
|
||||
}
|
||||
|
||||
ldp_config_apply(vty, vty_conf);
|
||||
@ -1033,9 +998,9 @@ ldp_vty_router_id(struct vty *vty, int disable, const char *addr_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_ds_cisco_interop(struct vty *vty, int disable)
|
||||
ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate)
|
||||
{
|
||||
if (disable)
|
||||
if (negate)
|
||||
vty_conf->flags &= ~F_LDPD_DS_CISCO_INTEROP;
|
||||
else
|
||||
vty_conf->flags |= F_LDPD_DS_CISCO_INTEROP;
|
||||
@ -1046,9 +1011,9 @@ ldp_vty_ds_cisco_interop(struct vty *vty, int disable)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_trans_pref_ipv4(struct vty *vty, int disable)
|
||||
ldp_vty_trans_pref_ipv4(struct vty *vty, const char *negate)
|
||||
{
|
||||
if (disable)
|
||||
if (negate)
|
||||
vty_conf->trans_pref = DUAL_STACK_LDPOV6;
|
||||
else
|
||||
vty_conf->trans_pref = DUAL_STACK_LDPOV4;
|
||||
@ -1059,22 +1024,20 @@ ldp_vty_trans_pref_ipv4(struct vty *vty, int disable)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_neighbor_password(struct vty *vty, int disable, const char *lsr_id_str,
|
||||
ldp_vty_neighbor_password(struct vty *vty, const char *negate, struct in_addr lsr_id,
|
||||
const char *password_str)
|
||||
{
|
||||
struct in_addr lsr_id;
|
||||
size_t password_len;
|
||||
struct nbr_params *nbrp;
|
||||
|
||||
if (inet_pton(AF_INET, lsr_id_str, &lsr_id) != 1 ||
|
||||
bad_addr_v4(lsr_id)) {
|
||||
if (bad_addr_v4(lsr_id)) {
|
||||
vty_out (vty, "%% Malformed address\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
nbrp = nbr_params_find(vty_conf, lsr_id);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (nbrp == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -1104,16 +1067,14 @@ ldp_vty_neighbor_password(struct vty *vty, int disable, const char *lsr_id_str,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_neighbor_ttl_security(struct vty *vty, int disable,
|
||||
const char *lsr_id_str, const char *hops_str)
|
||||
ldp_vty_neighbor_ttl_security(struct vty *vty, const char *negate,
|
||||
struct in_addr lsr_id, const char *hops_str)
|
||||
{
|
||||
struct in_addr lsr_id;
|
||||
struct nbr_params *nbrp;
|
||||
long int hops = 0;
|
||||
char *ep;
|
||||
|
||||
if (inet_pton(AF_INET, lsr_id_str, &lsr_id) != 1 ||
|
||||
bad_addr_v4(lsr_id)) {
|
||||
if (bad_addr_v4(lsr_id)) {
|
||||
vty_out (vty, "%% Malformed address\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
@ -1128,7 +1089,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, int disable,
|
||||
|
||||
nbrp = nbr_params_find(vty_conf, lsr_id);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (nbrp == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -1158,7 +1119,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, int disable,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn(struct vty *vty, int disable, const char *name_str)
|
||||
ldp_vty_l2vpn(struct vty *vty, const char *negate, const char *name_str)
|
||||
{
|
||||
struct l2vpn *l2vpn;
|
||||
struct l2vpn_if *lif;
|
||||
@ -1166,7 +1127,7 @@ ldp_vty_l2vpn(struct vty *vty, int disable, const char *name_str)
|
||||
|
||||
l2vpn = l2vpn_find(vty_conf, name_str);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (l2vpn == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -1203,11 +1164,11 @@ ldp_vty_l2vpn(struct vty *vty, int disable, const char *name_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_bridge(struct vty *vty, int disable, const char *ifname)
|
||||
ldp_vty_l2vpn_bridge(struct vty *vty, const char *negate, const char *ifname)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname));
|
||||
else
|
||||
strlcpy(l2vpn->br_ifname, ifname, sizeof(l2vpn->br_ifname));
|
||||
@ -1218,19 +1179,11 @@ ldp_vty_l2vpn_bridge(struct vty *vty, int disable, const char *ifname)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_mtu(struct vty *vty, int disable, const char *mtu_str)
|
||||
ldp_vty_l2vpn_mtu(struct vty *vty, const char *negate, long mtu)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
|
||||
char *ep;
|
||||
int mtu;
|
||||
|
||||
mtu = strtol(mtu_str, &ep, 10);
|
||||
if (*ep != '\0' || mtu < MIN_L2VPN_MTU || mtu > MAX_L2VPN_MTU) {
|
||||
vty_out (vty, "%% Invalid MTU\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
l2vpn->mtu = DEFAULT_L2VPN_MTU;
|
||||
else
|
||||
l2vpn->mtu = mtu;
|
||||
@ -1241,7 +1194,7 @@ ldp_vty_l2vpn_mtu(struct vty *vty, int disable, const char *mtu_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pwtype(struct vty *vty, int disable, const char *type_str)
|
||||
ldp_vty_l2vpn_pwtype(struct vty *vty, const char *negate, const char *type_str)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
|
||||
int pw_type;
|
||||
@ -1251,7 +1204,7 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, int disable, const char *type_str)
|
||||
else
|
||||
pw_type = PW_TYPE_ETHERNET_TAGGED;
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
l2vpn->pw_type = DEFAULT_PW_TYPE;
|
||||
else
|
||||
l2vpn->pw_type = pw_type;
|
||||
@ -1262,14 +1215,14 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, int disable, const char *type_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_interface(struct vty *vty, int disable, const char *ifname)
|
||||
ldp_vty_l2vpn_interface(struct vty *vty, const char *negate, const char *ifname)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
|
||||
struct l2vpn_if *lif;
|
||||
|
||||
lif = l2vpn_if_find(l2vpn, ifname);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (lif == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -1300,14 +1253,14 @@ ldp_vty_l2vpn_interface(struct vty *vty, int disable, const char *ifname)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pseudowire(struct vty *vty, int disable, const char *ifname)
|
||||
ldp_vty_l2vpn_pseudowire(struct vty *vty, const char *negate, const char *ifname)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
|
||||
struct l2vpn_pw *pw;
|
||||
|
||||
pw = l2vpn_pw_find(l2vpn, ifname);
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
if (pw == NULL)
|
||||
return (CMD_SUCCESS);
|
||||
|
||||
@ -1346,11 +1299,11 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, int disable, const char *ifname)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pw_cword(struct vty *vty, int disable, const char *preference_str)
|
||||
ldp_vty_l2vpn_pw_cword(struct vty *vty, const char *negate, const char *preference_str)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
pw->flags |= F_PW_CWORD_CONF;
|
||||
else {
|
||||
if (preference_str[0] == 'e')
|
||||
@ -1365,7 +1318,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, int disable, const char *preference_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, const char *negate, const char *addr_str)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
|
||||
int af;
|
||||
@ -1377,7 +1330,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (disable) {
|
||||
if (negate) {
|
||||
pw->af = AF_UNSPEC;
|
||||
memset(&pw->addr, 0, sizeof(pw->addr));
|
||||
pw->flags &= ~F_PW_STATIC_NBR_ADDR;
|
||||
@ -1393,18 +1346,16 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, int disable, const char *addr_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, int disable, const char *lsr_id_str)
|
||||
ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, const char *negate, struct in_addr lsr_id)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
|
||||
struct in_addr lsr_id;
|
||||
|
||||
if (inet_pton(AF_INET, lsr_id_str, &lsr_id) != 1 ||
|
||||
bad_addr_v4(lsr_id)) {
|
||||
if (bad_addr_v4(lsr_id)) {
|
||||
vty_out (vty, "%% Malformed address\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
pw->lsr_id.s_addr = INADDR_ANY;
|
||||
else
|
||||
pw->lsr_id = lsr_id;
|
||||
@ -1415,19 +1366,11 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, int disable, const char *lsr_id_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pw_pwid(struct vty *vty, int disable, const char *pwid_str)
|
||||
ldp_vty_l2vpn_pw_pwid(struct vty *vty, const char *negate, long pwid)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
|
||||
char *ep;
|
||||
uint32_t pwid;
|
||||
|
||||
pwid = strtol(pwid_str, &ep, 10);
|
||||
if (*ep != '\0' || pwid < MIN_PWID_ID || pwid > MAX_PWID_ID) {
|
||||
vty_out (vty, "%% Invalid pw-id\n");
|
||||
return (CMD_WARNING_CONFIG_FAILED);
|
||||
}
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
pw->pwid = 0;
|
||||
else
|
||||
pw->pwid = pwid;
|
||||
@ -1438,11 +1381,11 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, int disable, const char *pwid_str)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, int disable)
|
||||
ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, const char *negate)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
|
||||
|
||||
if (disable)
|
||||
if (negate)
|
||||
pw->flags |= F_PW_STATUSTLV_CONF;
|
||||
else
|
||||
pw->flags &= ~F_PW_STATUSTLV_CONF;
|
||||
|
@ -1565,7 +1565,7 @@ ldp_vty_get_af(const char *str, int *af)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_binding(struct vty *vty, const char *af_str, int detail, int json)
|
||||
ldp_vty_show_binding(struct vty *vty, const char *af_str, const char *detail, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1579,8 +1579,8 @@ ldp_vty_show_binding(struct vty *vty, const char *af_str, int detail, int json)
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.family = af;
|
||||
params.detail = detail;
|
||||
params.json = json;
|
||||
params.detail = (detail) ? 1 : 0;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
if (!params.detail && !params.json)
|
||||
vty_out (vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
|
||||
@ -1592,8 +1592,8 @@ ldp_vty_show_binding(struct vty *vty, const char *af_str, int detail, int json)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_discovery(struct vty *vty, const char *af_str, int detail,
|
||||
int json)
|
||||
ldp_vty_show_discovery(struct vty *vty, const char *af_str, const char *detail,
|
||||
const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1607,8 +1607,8 @@ ldp_vty_show_discovery(struct vty *vty, const char *af_str, int detail,
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.family = af;
|
||||
params.detail = detail;
|
||||
params.json = json;
|
||||
params.detail = (detail) ? 1 : 0;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
if (!params.detail && !params.json)
|
||||
vty_out (vty, "%-4s %-15s %-8s %-15s %9s\n",
|
||||
@ -1623,7 +1623,7 @@ ldp_vty_show_discovery(struct vty *vty, const char *af_str, int detail,
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_interface(struct vty *vty, const char *af_str, int json)
|
||||
ldp_vty_show_interface(struct vty *vty, const char *af_str, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1638,7 +1638,7 @@ ldp_vty_show_interface(struct vty *vty, const char *af_str, int json)
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.family = af;
|
||||
params.json = json;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
/* header */
|
||||
if (!params.json) {
|
||||
@ -1652,7 +1652,7 @@ ldp_vty_show_interface(struct vty *vty, const char *af_str, int json)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_capabilities(struct vty *vty, int json)
|
||||
ldp_vty_show_capabilities(struct vty *vty, const char *json)
|
||||
{
|
||||
if (json) {
|
||||
json_object *json;
|
||||
@ -1703,7 +1703,7 @@ ldp_vty_show_capabilities(struct vty *vty, int json)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_neighbor(struct vty *vty, int capabilities, int detail, int json)
|
||||
ldp_vty_show_neighbor(struct vty *vty, int capabilities, const char *detail, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1713,8 +1713,8 @@ ldp_vty_show_neighbor(struct vty *vty, int capabilities, int detail, int json)
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.capabilities = capabilities;
|
||||
params.detail = detail;
|
||||
params.json = json;
|
||||
params.detail = (detail) ? 1 : 0;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
if (params.capabilities)
|
||||
params.detail = 1;
|
||||
@ -1728,7 +1728,7 @@ ldp_vty_show_neighbor(struct vty *vty, int capabilities, int detail, int json)
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_atom_binding(struct vty *vty, int json)
|
||||
ldp_vty_show_atom_binding(struct vty *vty, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1737,14 +1737,14 @@ ldp_vty_show_atom_binding(struct vty *vty, int json)
|
||||
return (CMD_WARNING);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.json = json;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
|
||||
return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, ¶ms));
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_atom_vc(struct vty *vty, int json)
|
||||
ldp_vty_show_atom_vc(struct vty *vty, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
@ -1753,7 +1753,7 @@ ldp_vty_show_atom_vc(struct vty *vty, int json)
|
||||
return (CMD_WARNING);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.json = json;
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
if (!params.json) {
|
||||
/* header */
|
||||
|
2
lib/.gitignore
vendored
2
lib/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
Makefile
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
|
10
lib/Makefile
Normal file
10
lib/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C .. lib/libfrr.la
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C .. lib/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
155
lib/Makefile.am
155
lib/Makefile.am
@ -1,155 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
include ../common.am
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
|
||||
AM_CFLAGS = $(WERROR)
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ @BISON_VERBOSE@
|
||||
|
||||
command_lex.h: command_lex.c
|
||||
@if test ! -f $@; then rm -f command_lex.c; else :; fi
|
||||
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) command_lex.c; else :; fi
|
||||
command_parse.lo: command_lex.h
|
||||
clippy-command_parse.$(OBJEXT): command_lex.h
|
||||
|
||||
lib_LTLIBRARIES = libfrr.la
|
||||
libfrr_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
libfrr_la_SOURCES = \
|
||||
network.c pid_output.c getopt.c getopt1.c \
|
||||
checksum.c vector.c linklist.c vty.c openbsd-tree.c \
|
||||
graph.c command_parse.y command_lex.l command_match.c \
|
||||
command_graph.c \
|
||||
command.c \
|
||||
sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \
|
||||
filter.c routemap.c distribute.c stream.c log.c plist.c \
|
||||
zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \
|
||||
sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
|
||||
ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
|
||||
imsg-buffer.c imsg.c skiplist.c \
|
||||
qobj.c wheel.c \
|
||||
event_counter.c \
|
||||
grammar_sandbox.c \
|
||||
srcdest_table.c \
|
||||
spf_backoff.c \
|
||||
libfrr.c \
|
||||
strlcpy.c \
|
||||
strlcat.c \
|
||||
sha256.c \
|
||||
module.c \
|
||||
hook.c \
|
||||
frr_pthread.c \
|
||||
termtable.c \
|
||||
# end
|
||||
|
||||
BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h
|
||||
|
||||
libfrr_la_LIBADD = @LIBCAP@
|
||||
|
||||
if SNMP
|
||||
lib_LTLIBRARIES += libfrrsnmp.la
|
||||
endif
|
||||
|
||||
libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
||||
libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
|
||||
libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS)
|
||||
libfrrsnmp_la_SOURCES = \
|
||||
agentx.c \
|
||||
smux.c \
|
||||
snmp.c \
|
||||
#end
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
frratomic.h \
|
||||
buffer.h checksum.h filter.h getopt.h hash.h \
|
||||
if.h linklist.h log.h \
|
||||
graph.h command_match.h \
|
||||
command_graph.h \
|
||||
command.h \
|
||||
memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
|
||||
stream.h table.h thread.h vector.h version.h vty.h zebra.h \
|
||||
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
|
||||
privs.h sigevent.h pqueue.h jhash.h zassert.h \
|
||||
workqueue.h route_types.h libospf.h nexthop.h json.h \
|
||||
ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h \
|
||||
fifo.h memory_vty.h mpls.h imsg.h openbsd-queue.h openbsd-tree.h \
|
||||
skiplist.h qobj.h wheel.h \
|
||||
event_counter.h \
|
||||
monotime.h \
|
||||
spf_backoff.h \
|
||||
srcdest_table.h \
|
||||
module.h \
|
||||
hook.h \
|
||||
libfrr.h \
|
||||
sha256.h \
|
||||
frr_pthread.h \
|
||||
vrf_int.h \
|
||||
termtable.h \
|
||||
vlan.h \
|
||||
vxlan.h \
|
||||
ipaddr.h \
|
||||
# end
|
||||
|
||||
noinst_HEADERS = \
|
||||
plist_int.h \
|
||||
log_int.h \
|
||||
clippy.h \
|
||||
# end
|
||||
|
||||
noinst_PROGRAMS = grammar_sandbox
|
||||
if BUILD_CLIPPY
|
||||
noinst_PROGRAMS += clippy
|
||||
endif
|
||||
|
||||
grammar_sandbox_SOURCES = grammar_sandbox_main.c
|
||||
grammar_sandbox_LDADD = libfrr.la
|
||||
|
||||
clippy_SOURCES = \
|
||||
defun_lex.l \
|
||||
command_parse.y \
|
||||
command_lex.l \
|
||||
command_graph.c \
|
||||
command_py.c \
|
||||
memory.c \
|
||||
graph.c \
|
||||
vector.c \
|
||||
clippy.c \
|
||||
# end
|
||||
clippy_CPPFLAGS = -D_GNU_SOURCE
|
||||
clippy_CFLAGS = $(PYTHON_CFLAGS)
|
||||
clippy_LDADD = $(PYTHON_LIBS)
|
||||
clippy-command_graph.$(OBJEXT): route_types.h
|
||||
|
||||
plist.lo: plist_clippy.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
queue.h \
|
||||
command_lex.h \
|
||||
route_types.pl route_types.txt \
|
||||
gitversion.pl
|
||||
|
||||
route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl
|
||||
@PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@
|
||||
|
||||
if GIT_VERSION
|
||||
|
||||
# bit of a trick here to always have up-to-date git stamps without triggering
|
||||
# unneccessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
|
||||
# but if we use that on gitversion.h it'll ripple through the .c file deps.
|
||||
# (even if gitversion.h's file timestamp doesn't change, make will think it
|
||||
# did, because of .PHONY...)
|
||||
|
||||
.PHONY: gitversion.h.tmp
|
||||
.SILENT: gitversion.h gitversion.h.tmp
|
||||
GITH=gitversion.h
|
||||
gitversion.h.tmp: $(srcdir)/../.git
|
||||
@PERL@ $(srcdir)/gitversion.pl $(srcdir) > ${GITH}.tmp
|
||||
gitversion.h: gitversion.h.tmp
|
||||
{ test -f ${GITH} && diff -s -q ${GITH}.tmp ${GITH}; } || cp -v ${GITH}.tmp ${GITH}
|
||||
|
||||
else
|
||||
.PHONY: gitversion.h
|
||||
gitversion.h:
|
||||
true
|
||||
endif
|
111
lib/command.c
111
lib/command.c
@ -47,6 +47,74 @@ DEFINE_MTYPE(LIB, HOST, "Host config")
|
||||
DEFINE_MTYPE(LIB, STRVEC, "String vector")
|
||||
DEFINE_MTYPE(LIB, COMPLETION, "Completion item")
|
||||
|
||||
const char *node_names[] = {
|
||||
"auth", // AUTH_NODE,
|
||||
"view", // VIEW_NODE,
|
||||
"auth enable", // AUTH_ENABLE_NODE,
|
||||
"enable", // ENABLE_NODE,
|
||||
"config", // CONFIG_NODE,
|
||||
"service", // SERVICE_NODE,
|
||||
"debug", // DEBUG_NODE,
|
||||
"vrf debug", // VRF_DEBUG_NODE,
|
||||
"vnc debug", // DEBUG_VNC_NODE,
|
||||
"aaa", // AAA_NODE,
|
||||
"keychain", // KEYCHAIN_NODE,
|
||||
"keychain key", // KEYCHAIN_KEY_NODE,
|
||||
"logical-router", // NS_NODE,
|
||||
"vrf", // VRF_NODE,
|
||||
"interface", // INTERFACE_NODE,
|
||||
"zebra", // ZEBRA_NODE,
|
||||
"table", // TABLE_NODE,
|
||||
"rip", // RIP_NODE,
|
||||
"ripng", // RIPNG_NODE,
|
||||
"babel", // BABEL_NODE,
|
||||
"eigrp", // EIGRP_NODE,
|
||||
"bgp", // BGP_NODE,
|
||||
"bgp vpnv4", // BGP_VPNV4_NODE,
|
||||
"bgp vpnv6", // BGP_VPNV6_NODE,
|
||||
"bgp ipv4 unicast", // BGP_IPV4_NODE,
|
||||
"bgp ipv4 multicast", // BGP_IPV4M_NODE,
|
||||
"bgp ipv4 labeled unicast", // BGP_IPV4L_NODE,
|
||||
"bgp ipv6", // BGP_IPV6_NODE,
|
||||
"bgp ipv6 multicast", // BGP_IPV6M_NODE,
|
||||
"bgp ipv6 labeled unicast", // BGP_IPV6L_NODE,
|
||||
"bgp vrf policy", // BGP_VRF_POLICY_NODE,
|
||||
"bgp vnc defaults", // BGP_VNC_DEFAULTS_NODE,
|
||||
"bgp vnc nve", // BGP_VNC_NVE_GROUP_NODE,
|
||||
"bgp vnc l2", // BGP_VNC_L2_GROUP_NODE,
|
||||
"rfp defaults", // RFP_DEFAULTS_NODE,
|
||||
"bgp evpn", // BGP_EVPN_NODE,
|
||||
"ospf", // OSPF_NODE,
|
||||
"ospf6", // OSPF6_NODE,
|
||||
"ldp", // LDP_NODE,
|
||||
"ldp ipv4", // LDP_IPV4_NODE,
|
||||
"ldp ipv6", // LDP_IPV6_NODE,
|
||||
"ldp ipv4 interface", // LDP_IPV4_IFACE_NODE,
|
||||
"ldp ipv6 interface", // LDP_IPV6_IFACE_NODE,
|
||||
"ldp l2vpn", // LDP_L2VPN_NODE,
|
||||
"ldp", // LDP_PSEUDOWIRE_NODE,
|
||||
"isis", // ISIS_NODE,
|
||||
"pim", // PIM_NODE,
|
||||
"masc", // MASC_NODE,
|
||||
"irdp", // IRDP_NODE,
|
||||
"static ip", // IP_NODE,
|
||||
"ipv4 access list", // ACCESS_NODE,
|
||||
"ipv4 prefix list", // PREFIX_NODE,
|
||||
"ipv6 access list", // ACCESS_IPV6_NODE,
|
||||
"ipv6 prefix list", // PREFIX_IPV6_NODE,
|
||||
"as list", // AS_LIST_NODE,
|
||||
"community list", // COMMUNITY_LIST_NODE,
|
||||
"routemap", // RMAP_NODE,
|
||||
"smux", // SMUX_NODE,
|
||||
"dump", // DUMP_NODE,
|
||||
"forwarding", // FORWARDING_NODE,
|
||||
"protocol", // PROTOCOL_NODE,
|
||||
"mpls", // MPLS_NODE,
|
||||
"vty", // VTY_NODE,
|
||||
"link-params", // LINK_PARAMS_NODE,
|
||||
"bgp evpn vni", // BGP_EVPN_VNI_NODE,
|
||||
};
|
||||
|
||||
/* Command vector which includes some level of command lists. Normally
|
||||
each daemon maintains each own cmdvec. */
|
||||
vector cmdvec = NULL;
|
||||
@ -2355,6 +2423,35 @@ DEFUN (no_banner_motd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(find,
|
||||
find_cmd,
|
||||
"find COMMAND...",
|
||||
"Find CLI command containing text\n"
|
||||
"Text to search for\n")
|
||||
{
|
||||
char *text = argv_concat(argv, argc, 1);
|
||||
const struct cmd_node *node;
|
||||
const struct cmd_element *cli;
|
||||
vector clis;
|
||||
|
||||
for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
|
||||
node = vector_slot(cmdvec, i);
|
||||
if (!node)
|
||||
continue;
|
||||
clis = node->cmd_vector;
|
||||
for (unsigned int j = 0; j < vector_active(clis); j++) {
|
||||
cli = vector_slot(clis, j);
|
||||
if (strcasestr(cli->string, text))
|
||||
vty_out(vty, " (%s) %s\n",
|
||||
node_names[node->node], cli->string);
|
||||
}
|
||||
}
|
||||
|
||||
XFREE(MTYPE_TMP, text);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set config filename. Called from vty.c */
|
||||
void host_config_set(const char *filename)
|
||||
{
|
||||
@ -2375,6 +2472,7 @@ void install_default(enum node_type node)
|
||||
install_element(node, &config_end_cmd);
|
||||
install_element(node, &config_help_cmd);
|
||||
install_element(node, &config_list_cmd);
|
||||
install_element(node, &find_cmd);
|
||||
|
||||
install_element(node, &config_write_cmd);
|
||||
install_element(node, &show_running_config_cmd);
|
||||
@ -2389,6 +2487,9 @@ void install_default(enum node_type node)
|
||||
* terminal = -1 -- watchfrr / no logging, but minimal config control */
|
||||
void cmd_init(int terminal)
|
||||
{
|
||||
if (array_size(node_names) != NODE_TYPE_MAX)
|
||||
assert(!"Update the CLI node description array!");
|
||||
|
||||
qobj_init();
|
||||
|
||||
varhandlers = list_new();
|
||||
@ -2416,6 +2517,8 @@ void cmd_init(int terminal)
|
||||
|
||||
/* Each node's basic commands. */
|
||||
install_element(VIEW_NODE, &show_version_cmd);
|
||||
install_element(ENABLE_NODE, &show_startup_config_cmd);
|
||||
|
||||
if (terminal) {
|
||||
install_element(VIEW_NODE, &config_list_cmd);
|
||||
install_element(VIEW_NODE, &config_exit_cmd);
|
||||
@ -2428,20 +2531,16 @@ void cmd_init(int terminal)
|
||||
install_element(VIEW_NODE, &show_commandtree_cmd);
|
||||
install_element(VIEW_NODE, &echo_cmd);
|
||||
install_element(VIEW_NODE, &autocomplete_cmd);
|
||||
}
|
||||
install_element(VIEW_NODE, &find_cmd);
|
||||
|
||||
if (terminal) {
|
||||
install_element(ENABLE_NODE, &config_end_cmd);
|
||||
install_element(ENABLE_NODE, &config_disable_cmd);
|
||||
install_element(ENABLE_NODE, &config_terminal_cmd);
|
||||
install_element(ENABLE_NODE, ©_runningconf_startupconf_cmd);
|
||||
install_element(ENABLE_NODE, &config_write_cmd);
|
||||
install_element(ENABLE_NODE, &show_running_config_cmd);
|
||||
}
|
||||
install_element(ENABLE_NODE, &show_startup_config_cmd);
|
||||
|
||||
if (terminal) {
|
||||
install_element(ENABLE_NODE, &config_logmsg_cmd);
|
||||
|
||||
install_default(CONFIG_NODE);
|
||||
|
||||
thread_cmd_init();
|
||||
|
@ -68,7 +68,7 @@ struct host {
|
||||
char *motdfile;
|
||||
};
|
||||
|
||||
/* There are some command levels which called from command node. */
|
||||
/* List of CLI nodes. Please remember to update the name array in command.c. */
|
||||
enum node_type {
|
||||
AUTH_NODE, /* Authentication mode of vty interface. */
|
||||
VIEW_NODE, /* View node. Default mode of vty interface. */
|
||||
@ -135,8 +135,12 @@ enum node_type {
|
||||
VTY_NODE, /* Vty node. */
|
||||
LINK_PARAMS_NODE, /* Link-parameters node */
|
||||
BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */
|
||||
NODE_TYPE_MAX, /* maximum */
|
||||
};
|
||||
|
||||
extern vector cmdvec;
|
||||
extern const char *node_names[];
|
||||
|
||||
/* Node which has some commands and prompt string and configuration
|
||||
function pointer . */
|
||||
struct cmd_node {
|
||||
|
@ -49,8 +49,8 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option noinput
|
||||
%option outfile="command_lex.c"
|
||||
%option header-file="command_lex.h"
|
||||
%option outfile="lib/command_lex.c"
|
||||
%option header-file="lib/command_lex.h"
|
||||
%option prefix="cmd_yy"
|
||||
%option reentrant
|
||||
%option bison-bridge
|
||||
|
@ -33,8 +33,8 @@
|
||||
/* define api.prefix {cmd_yy} */
|
||||
|
||||
/* names for generated header and parser files */
|
||||
%defines "command_parse.h"
|
||||
%output "command_parse.c"
|
||||
%defines "lib/command_parse.h"
|
||||
%output "lib/command_parse.c"
|
||||
|
||||
/* note: code blocks are output in order, to both .c and .h:
|
||||
* 1. %code requires
|
||||
|
@ -85,7 +85,7 @@ SPECIAL [(),]
|
||||
%option noyywrap
|
||||
%option noinput
|
||||
%option nounput
|
||||
%option outfile="defun_lex.c"
|
||||
%option outfile="lib/defun_lex.c"
|
||||
%option prefix="def_yy"
|
||||
%option 8bit
|
||||
|
||||
|
25
lib/hash.c
25
lib/hash.c
@ -49,7 +49,6 @@ struct hash *hash_create_size(unsigned int size,
|
||||
hash->index =
|
||||
XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * size);
|
||||
hash->size = size;
|
||||
hash->no_expand = 0;
|
||||
hash->hash_key = hash_key;
|
||||
hash->hash_cmp = hash_cmp;
|
||||
hash->count = 0;
|
||||
@ -91,10 +90,14 @@ void *hash_alloc_intern(void *arg)
|
||||
/* Expand hash if the chain length exceeds the threshold. */
|
||||
static void hash_expand(struct hash *hash)
|
||||
{
|
||||
unsigned int i, new_size, losers;
|
||||
unsigned int i, new_size;
|
||||
struct hash_backet *hb, *hbnext, **new_index;
|
||||
|
||||
new_size = hash->size * 2;
|
||||
|
||||
if (hash->max_size && new_size > hash->max_size)
|
||||
return;
|
||||
|
||||
new_index = XCALLOC(MTYPE_HASH_INDEX,
|
||||
sizeof(struct hash_backet *) * new_size);
|
||||
if (new_index == NULL)
|
||||
@ -128,22 +131,6 @@ static void hash_expand(struct hash *hash)
|
||||
XFREE(MTYPE_HASH_INDEX, hash->index);
|
||||
hash->size = new_size;
|
||||
hash->index = new_index;
|
||||
|
||||
/* Ideally, new index should have chains half as long as the original.
|
||||
* If expansion didn't help, then not worth expanding again,
|
||||
* the problem is the hash function. */
|
||||
losers = 0;
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
unsigned int len = hash->index[i] ? hash->index[i]->len : 0;
|
||||
|
||||
if (len > HASH_THRESHOLD / 2)
|
||||
++losers;
|
||||
if (len >= HASH_THRESHOLD)
|
||||
hash->no_expand = 1;
|
||||
}
|
||||
|
||||
if (losers > hash->count / 2)
|
||||
hash->no_expand = 1;
|
||||
}
|
||||
|
||||
/* Lookup and return hash backet in hash. If there is no
|
||||
@ -173,7 +160,7 @@ void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *))
|
||||
if (newdata == NULL)
|
||||
return NULL;
|
||||
|
||||
if (len > HASH_THRESHOLD && !hash->no_expand) {
|
||||
if (len > HASH_THRESHOLD) {
|
||||
hash_expand(hash);
|
||||
index = key & (hash->size - 1);
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ struct hash {
|
||||
/* Hash table size. Must be power of 2 */
|
||||
unsigned int size;
|
||||
|
||||
/* If expansion failed. */
|
||||
int no_expand;
|
||||
/* If max_size is 0 there is no limit */
|
||||
unsigned int max_size;
|
||||
|
||||
/* Key make function. */
|
||||
unsigned int (*hash_key)(void *);
|
||||
|
@ -21,13 +21,14 @@
|
||||
#include "openbsd-queue.h"
|
||||
#include "imsg.h"
|
||||
|
||||
int ibuf_realloc(struct ibuf *, size_t);
|
||||
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
||||
void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
||||
int ibuf_realloc(struct ibuf *, size_t);
|
||||
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
||||
void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
||||
|
||||
struct ibuf *ibuf_open(size_t len)
|
||||
struct ibuf *
|
||||
ibuf_open(size_t len)
|
||||
{
|
||||
struct ibuf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
|
||||
return (NULL);
|
||||
@ -41,9 +42,10 @@ struct ibuf *ibuf_open(size_t len)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
struct ibuf *ibuf_dynamic(size_t len, size_t max)
|
||||
struct ibuf *
|
||||
ibuf_dynamic(size_t len, size_t max)
|
||||
{
|
||||
struct ibuf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
if (max < len)
|
||||
return (NULL);
|
||||
@ -57,9 +59,10 @@ struct ibuf *ibuf_dynamic(size_t len, size_t max)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
int ibuf_realloc(struct ibuf *buf, size_t len)
|
||||
int
|
||||
ibuf_realloc(struct ibuf *buf, size_t len)
|
||||
{
|
||||
u_char *b;
|
||||
u_char *b;
|
||||
|
||||
/* on static buffers max is eq size and so the following fails */
|
||||
if (buf->wpos + len > buf->max) {
|
||||
@ -76,7 +79,8 @@ int ibuf_realloc(struct ibuf *buf, size_t len)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
||||
int
|
||||
ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
||||
{
|
||||
if (buf->wpos + len > buf->size)
|
||||
if (ibuf_realloc(buf, len) == -1)
|
||||
@ -87,9 +91,10 @@ int ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *ibuf_reserve(struct ibuf *buf, size_t len)
|
||||
void *
|
||||
ibuf_reserve(struct ibuf *buf, size_t len)
|
||||
{
|
||||
void *b;
|
||||
void *b;
|
||||
|
||||
if (buf->wpos + len > buf->size)
|
||||
if (ibuf_realloc(buf, len) == -1)
|
||||
@ -100,7 +105,8 @@ void *ibuf_reserve(struct ibuf *buf, size_t len)
|
||||
return (b);
|
||||
}
|
||||
|
||||
void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
||||
void *
|
||||
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
||||
{
|
||||
/* only allowed to seek in already written parts */
|
||||
if (pos + len > buf->wpos)
|
||||
@ -109,31 +115,34 @@ void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
||||
return (buf->buf + pos);
|
||||
}
|
||||
|
||||
size_t ibuf_size(struct ibuf *buf)
|
||||
size_t
|
||||
ibuf_size(struct ibuf *buf)
|
||||
{
|
||||
return (buf->wpos);
|
||||
}
|
||||
|
||||
size_t ibuf_left(struct ibuf *buf)
|
||||
size_t
|
||||
ibuf_left(struct ibuf *buf)
|
||||
{
|
||||
return (buf->max - buf->wpos);
|
||||
}
|
||||
|
||||
void ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
void
|
||||
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
ibuf_enqueue(msgbuf, buf);
|
||||
}
|
||||
|
||||
int ibuf_write(struct msgbuf *msgbuf)
|
||||
int
|
||||
ibuf_write(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
|
||||
{
|
||||
TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
|
||||
if (i >= IOV_MAX)
|
||||
break;
|
||||
iov[i].iov_base = buf->buf + buf->rpos;
|
||||
@ -150,7 +159,7 @@ again:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (n == 0) { /* connection closed */
|
||||
if (n == 0) { /* connection closed */
|
||||
errno = 0;
|
||||
return (0);
|
||||
}
|
||||
@ -160,7 +169,8 @@ again:
|
||||
return (1);
|
||||
}
|
||||
|
||||
void ibuf_free(struct ibuf *buf)
|
||||
void
|
||||
ibuf_free(struct ibuf *buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
return;
|
||||
@ -168,19 +178,21 @@ void ibuf_free(struct ibuf *buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void msgbuf_init(struct msgbuf *msgbuf)
|
||||
void
|
||||
msgbuf_init(struct msgbuf *msgbuf)
|
||||
{
|
||||
msgbuf->queued = 0;
|
||||
msgbuf->fd = -1;
|
||||
TAILQ_INIT(&msgbuf->bufs);
|
||||
}
|
||||
|
||||
void msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||
void
|
||||
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||
{
|
||||
struct ibuf *buf, *next;
|
||||
struct ibuf *buf, *next;
|
||||
|
||||
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
|
||||
buf = next) {
|
||||
buf = next) {
|
||||
next = TAILQ_NEXT(buf, entry);
|
||||
if (buf->rpos + n >= buf->wpos) {
|
||||
n -= buf->wpos - buf->rpos;
|
||||
@ -192,32 +204,33 @@ void msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||
}
|
||||
}
|
||||
|
||||
void msgbuf_clear(struct msgbuf *msgbuf)
|
||||
void
|
||||
msgbuf_clear(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct ibuf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
|
||||
ibuf_dequeue(msgbuf, buf);
|
||||
}
|
||||
|
||||
int msgbuf_write(struct msgbuf *msgbuf)
|
||||
int
|
||||
msgbuf_write(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[CMSG_SPACE(sizeof(int))];
|
||||
struct cmsghdr hdr;
|
||||
char buf[CMSG_SPACE(sizeof(int))];
|
||||
} cmsgbuf;
|
||||
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
||||
TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
|
||||
{
|
||||
TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
|
||||
if (i >= IOV_MAX)
|
||||
break;
|
||||
iov[i].iov_base = buf->buf + buf->rpos;
|
||||
@ -249,7 +262,7 @@ again:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (n == 0) { /* connection closed */
|
||||
if (n == 0) { /* connection closed */
|
||||
errno = 0;
|
||||
return (0);
|
||||
}
|
||||
@ -268,13 +281,15 @@ again:
|
||||
return (1);
|
||||
}
|
||||
|
||||
void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
void
|
||||
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
|
||||
msgbuf->queued++;
|
||||
}
|
||||
|
||||
void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
void
|
||||
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
|
||||
|
||||
|
117
lib/imsg.c
117
lib/imsg.c
@ -21,21 +21,22 @@
|
||||
#include "openbsd-queue.h"
|
||||
#include "imsg.h"
|
||||
|
||||
int imsg_fd_overhead = 0;
|
||||
int imsg_fd_overhead = 0;
|
||||
|
||||
int imsg_get_fd(struct imsgbuf *);
|
||||
int imsg_get_fd(struct imsgbuf *);
|
||||
|
||||
#ifndef __OpenBSD__
|
||||
/*
|
||||
* The original code calls getdtablecount() which is OpenBSD specific. Use
|
||||
* available_fds() from OpenSMTPD instead.
|
||||
*/
|
||||
static int available_fds(unsigned int n)
|
||||
static int
|
||||
available_fds(unsigned int n)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret, fds[256];
|
||||
unsigned int i;
|
||||
int ret, fds[256];
|
||||
|
||||
if (n > (sizeof(fds) / sizeof(fds[0])))
|
||||
if (n > (sizeof(fds)/sizeof(fds[0])))
|
||||
return (1);
|
||||
|
||||
ret = 0;
|
||||
@ -58,7 +59,8 @@ static int available_fds(unsigned int n)
|
||||
}
|
||||
#endif
|
||||
|
||||
void imsg_init(struct imsgbuf *ibuf, int fd)
|
||||
void
|
||||
imsg_init(struct imsgbuf *ibuf, int fd)
|
||||
{
|
||||
msgbuf_init(&ibuf->w);
|
||||
memset(&ibuf->r, 0, sizeof(ibuf->r));
|
||||
@ -68,18 +70,19 @@ void imsg_init(struct imsgbuf *ibuf, int fd)
|
||||
TAILQ_INIT(&ibuf->fds);
|
||||
}
|
||||
|
||||
ssize_t imsg_read(struct imsgbuf *ibuf)
|
||||
ssize_t
|
||||
imsg_read(struct imsgbuf *ibuf)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[CMSG_SPACE(sizeof(int) * 1)];
|
||||
char buf[CMSG_SPACE(sizeof(int) * 1)];
|
||||
} cmsgbuf;
|
||||
struct iovec iov;
|
||||
ssize_t n = -1;
|
||||
int fd;
|
||||
struct imsg_fd *ifd;
|
||||
struct iovec iov;
|
||||
ssize_t n = -1;
|
||||
int fd;
|
||||
struct imsg_fd *ifd;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
||||
@ -96,14 +99,12 @@ ssize_t imsg_read(struct imsgbuf *ibuf)
|
||||
|
||||
again:
|
||||
#ifdef __OpenBSD__
|
||||
if (getdtablecount() + imsg_fd_overhead
|
||||
+ (int)((CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0))
|
||||
/ sizeof(int))
|
||||
if (getdtablecount() + imsg_fd_overhead +
|
||||
(int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
|
||||
>= getdtablesize()) {
|
||||
#else
|
||||
if (available_fds(imsg_fd_overhead
|
||||
+ (CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0))
|
||||
/ sizeof(int))) {
|
||||
if (available_fds(imsg_fd_overhead +
|
||||
(CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) {
|
||||
#endif
|
||||
errno = EAGAIN;
|
||||
free(ifd);
|
||||
@ -119,9 +120,9 @@ again:
|
||||
ibuf->r.wpos += n;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET
|
||||
&& cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
int i;
|
||||
int j;
|
||||
|
||||
@ -130,15 +131,14 @@ again:
|
||||
* padding rules, our control buffer might contain
|
||||
* more than one fd, and we must close them.
|
||||
*/
|
||||
j = ((char *)cmsg + cmsg->cmsg_len
|
||||
- (char *)CMSG_DATA(cmsg))
|
||||
/ sizeof(int);
|
||||
j = ((char *)cmsg + cmsg->cmsg_len -
|
||||
(char *)CMSG_DATA(cmsg)) / sizeof(int);
|
||||
for (i = 0; i < j; i++) {
|
||||
fd = ((int *)CMSG_DATA(cmsg))[i];
|
||||
if (ifd != NULL) {
|
||||
ifd->fd = fd;
|
||||
TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
|
||||
entry);
|
||||
entry);
|
||||
ifd = NULL;
|
||||
} else
|
||||
close(fd);
|
||||
@ -152,9 +152,10 @@ fail:
|
||||
return (n);
|
||||
}
|
||||
|
||||
ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
||||
ssize_t
|
||||
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
||||
{
|
||||
size_t av, left, datalen;
|
||||
size_t av, left, datalen;
|
||||
|
||||
av = ibuf->r.wpos;
|
||||
|
||||
@ -162,7 +163,8 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
||||
return (0);
|
||||
|
||||
memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
|
||||
if (imsg->hdr.len < IMSG_HEADER_SIZE || imsg->hdr.len > MAX_IMSGSIZE) {
|
||||
if (imsg->hdr.len < IMSG_HEADER_SIZE ||
|
||||
imsg->hdr.len > MAX_IMSGSIZE) {
|
||||
errno = ERANGE;
|
||||
return (-1);
|
||||
}
|
||||
@ -181,7 +183,7 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
||||
imsg->fd = -1;
|
||||
|
||||
if (imsg->data)
|
||||
memcpy(imsg->data, ibuf->r.rptr, datalen);
|
||||
memcpy(imsg->data, ibuf->r.rptr, datalen);
|
||||
|
||||
if (imsg->hdr.len < av) {
|
||||
left = av - imsg->hdr.len;
|
||||
@ -193,10 +195,11 @@ ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
||||
return (datalen + IMSG_HEADER_SIZE);
|
||||
}
|
||||
|
||||
int imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, const void *data, u_int16_t datalen)
|
||||
int
|
||||
imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, const void *data, u_int16_t datalen)
|
||||
{
|
||||
struct ibuf *wbuf;
|
||||
struct ibuf *wbuf;
|
||||
|
||||
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
|
||||
return (-1);
|
||||
@ -211,11 +214,12 @@ int imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
return (1);
|
||||
}
|
||||
|
||||
int imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, const struct iovec *iov, int iovcnt)
|
||||
int
|
||||
imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
struct ibuf *wbuf;
|
||||
int i, datalen = 0;
|
||||
struct ibuf *wbuf;
|
||||
int i, datalen = 0;
|
||||
|
||||
for (i = 0; i < iovcnt; i++)
|
||||
datalen += iov[i].iov_len;
|
||||
@ -235,11 +239,12 @@ int imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
struct ibuf *imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, u_int16_t datalen)
|
||||
struct ibuf *
|
||||
imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, u_int16_t datalen)
|
||||
{
|
||||
struct ibuf *wbuf;
|
||||
struct imsg_hdr hdr;
|
||||
struct ibuf *wbuf;
|
||||
struct imsg_hdr hdr;
|
||||
|
||||
datalen += IMSG_HEADER_SIZE;
|
||||
if (datalen > MAX_IMSGSIZE) {
|
||||
@ -261,7 +266,8 @@ struct ibuf *imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
return (wbuf);
|
||||
}
|
||||
|
||||
int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
|
||||
int
|
||||
imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
|
||||
{
|
||||
if (datalen)
|
||||
if (ibuf_add(msg, data, datalen) == -1) {
|
||||
@ -271,9 +277,10 @@ int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
|
||||
return (datalen);
|
||||
}
|
||||
|
||||
void imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
||||
void
|
||||
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
||||
{
|
||||
struct imsg_hdr *hdr;
|
||||
struct imsg_hdr *hdr;
|
||||
|
||||
hdr = (struct imsg_hdr *)msg->buf;
|
||||
|
||||
@ -286,15 +293,17 @@ void imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
||||
ibuf_close(&ibuf->w, msg);
|
||||
}
|
||||
|
||||
void imsg_free(struct imsg *imsg)
|
||||
void
|
||||
imsg_free(struct imsg *imsg)
|
||||
{
|
||||
free(imsg->data);
|
||||
}
|
||||
|
||||
int imsg_get_fd(struct imsgbuf *ibuf)
|
||||
int
|
||||
imsg_get_fd(struct imsgbuf *ibuf)
|
||||
{
|
||||
int fd;
|
||||
struct imsg_fd *ifd;
|
||||
int fd;
|
||||
struct imsg_fd *ifd;
|
||||
|
||||
if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
|
||||
return (-1);
|
||||
@ -306,7 +315,8 @@ int imsg_get_fd(struct imsgbuf *ibuf)
|
||||
return (fd);
|
||||
}
|
||||
|
||||
int imsg_flush(struct imsgbuf *ibuf)
|
||||
int
|
||||
imsg_flush(struct imsgbuf *ibuf)
|
||||
{
|
||||
while (ibuf->w.queued)
|
||||
if (msgbuf_write(&ibuf->w) <= 0)
|
||||
@ -314,9 +324,10 @@ int imsg_flush(struct imsgbuf *ibuf)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void imsg_clear(struct imsgbuf *ibuf)
|
||||
void
|
||||
imsg_clear(struct imsgbuf *ibuf)
|
||||
{
|
||||
int fd;
|
||||
int fd;
|
||||
|
||||
msgbuf_clear(&ibuf->w);
|
||||
while ((fd = imsg_get_fd(ibuf)) != -1)
|
||||
|
110
lib/imsg.h
110
lib/imsg.h
@ -26,87 +26,87 @@
|
||||
#define MAX_IMSGSIZE 16384
|
||||
|
||||
struct ibuf {
|
||||
TAILQ_ENTRY(ibuf) entry;
|
||||
u_char *buf;
|
||||
size_t size;
|
||||
size_t max;
|
||||
size_t wpos;
|
||||
size_t rpos;
|
||||
int fd;
|
||||
TAILQ_ENTRY(ibuf) entry;
|
||||
u_char *buf;
|
||||
size_t size;
|
||||
size_t max;
|
||||
size_t wpos;
|
||||
size_t rpos;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct msgbuf {
|
||||
TAILQ_HEAD(, ibuf) bufs;
|
||||
u_int32_t queued;
|
||||
int fd;
|
||||
TAILQ_HEAD(, ibuf) bufs;
|
||||
u_int32_t queued;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct ibuf_read {
|
||||
u_char buf[IBUF_READ_SIZE];
|
||||
u_char *rptr;
|
||||
size_t wpos;
|
||||
u_char buf[IBUF_READ_SIZE];
|
||||
u_char *rptr;
|
||||
size_t wpos;
|
||||
};
|
||||
|
||||
struct imsg_fd {
|
||||
TAILQ_ENTRY(imsg_fd) entry;
|
||||
int fd;
|
||||
TAILQ_ENTRY(imsg_fd) entry;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct imsgbuf {
|
||||
TAILQ_HEAD(, imsg_fd) fds;
|
||||
struct ibuf_read r;
|
||||
struct msgbuf w;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
TAILQ_HEAD(, imsg_fd) fds;
|
||||
struct ibuf_read r;
|
||||
struct msgbuf w;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
#define IMSGF_HASFD 1
|
||||
|
||||
struct imsg_hdr {
|
||||
u_int32_t type;
|
||||
u_int16_t len;
|
||||
u_int16_t flags;
|
||||
u_int32_t peerid;
|
||||
u_int32_t pid;
|
||||
u_int32_t type;
|
||||
u_int16_t len;
|
||||
u_int16_t flags;
|
||||
u_int32_t peerid;
|
||||
u_int32_t pid;
|
||||
};
|
||||
|
||||
struct imsg {
|
||||
struct imsg_hdr hdr;
|
||||
int fd;
|
||||
void *data;
|
||||
struct imsg_hdr hdr;
|
||||
int fd;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
/* buffer.c */
|
||||
struct ibuf *ibuf_open(size_t);
|
||||
struct ibuf *ibuf_dynamic(size_t, size_t);
|
||||
int ibuf_add(struct ibuf *, const void *, size_t);
|
||||
void *ibuf_reserve(struct ibuf *, size_t);
|
||||
void *ibuf_seek(struct ibuf *, size_t, size_t);
|
||||
size_t ibuf_size(struct ibuf *);
|
||||
size_t ibuf_left(struct ibuf *);
|
||||
void ibuf_close(struct msgbuf *, struct ibuf *);
|
||||
int ibuf_write(struct msgbuf *);
|
||||
void ibuf_free(struct ibuf *);
|
||||
void msgbuf_init(struct msgbuf *);
|
||||
void msgbuf_clear(struct msgbuf *);
|
||||
int msgbuf_write(struct msgbuf *);
|
||||
void msgbuf_drain(struct msgbuf *, size_t);
|
||||
struct ibuf *ibuf_open(size_t);
|
||||
struct ibuf *ibuf_dynamic(size_t, size_t);
|
||||
int ibuf_add(struct ibuf *, const void *, size_t);
|
||||
void *ibuf_reserve(struct ibuf *, size_t);
|
||||
void *ibuf_seek(struct ibuf *, size_t, size_t);
|
||||
size_t ibuf_size(struct ibuf *);
|
||||
size_t ibuf_left(struct ibuf *);
|
||||
void ibuf_close(struct msgbuf *, struct ibuf *);
|
||||
int ibuf_write(struct msgbuf *);
|
||||
void ibuf_free(struct ibuf *);
|
||||
void msgbuf_init(struct msgbuf *);
|
||||
void msgbuf_clear(struct msgbuf *);
|
||||
int msgbuf_write(struct msgbuf *);
|
||||
void msgbuf_drain(struct msgbuf *, size_t);
|
||||
|
||||
/* imsg.c */
|
||||
void imsg_init(struct imsgbuf *, int);
|
||||
ssize_t imsg_read(struct imsgbuf *);
|
||||
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
|
||||
int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int,
|
||||
const void *, u_int16_t);
|
||||
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int,
|
||||
const struct iovec *, int);
|
||||
void imsg_init(struct imsgbuf *, int);
|
||||
ssize_t imsg_read(struct imsgbuf *);
|
||||
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
|
||||
int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
int, const void *, u_int16_t);
|
||||
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
int, const struct iovec *, int);
|
||||
struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
u_int16_t);
|
||||
int imsg_add(struct ibuf *, const void *, u_int16_t);
|
||||
void imsg_close(struct imsgbuf *, struct ibuf *);
|
||||
void imsg_free(struct imsg *);
|
||||
int imsg_flush(struct imsgbuf *);
|
||||
void imsg_clear(struct imsgbuf *);
|
||||
u_int16_t);
|
||||
int imsg_add(struct ibuf *, const void *, u_int16_t);
|
||||
void imsg_close(struct imsgbuf *, struct ibuf *);
|
||||
void imsg_free(struct imsg *);
|
||||
int imsg_flush(struct imsgbuf *);
|
||||
void imsg_clear(struct imsgbuf *);
|
||||
|
||||
#endif
|
||||
|
@ -133,17 +133,17 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
|
||||
|
||||
for (nh1 = nh; nh1; nh1 = nh1->next) {
|
||||
nexthop = nexthop_new();
|
||||
nexthop->ifindex = nh->ifindex;
|
||||
nexthop->type = nh->type;
|
||||
nexthop->flags = nh->flags;
|
||||
memcpy(&nexthop->gate, &nh->gate, sizeof(nh->gate));
|
||||
memcpy(&nexthop->src, &nh->src, sizeof(nh->src));
|
||||
memcpy(&nexthop->rmap_src, &nh->rmap_src, sizeof(nh->rmap_src));
|
||||
nexthop->ifindex = nh1->ifindex;
|
||||
nexthop->type = nh1->type;
|
||||
nexthop->flags = nh1->flags;
|
||||
memcpy(&nexthop->gate, &nh1->gate, sizeof(nh1->gate));
|
||||
memcpy(&nexthop->src, &nh1->src, sizeof(nh1->src));
|
||||
memcpy(&nexthop->rmap_src, &nh1->rmap_src, sizeof(nh1->rmap_src));
|
||||
nexthop->rparent = rparent;
|
||||
if (nh->nh_label)
|
||||
nexthop_add_labels(nexthop, nh->nh_label_type,
|
||||
nh->nh_label->num_labels,
|
||||
&nh->nh_label->label[0]);
|
||||
if (nh1->nh_label)
|
||||
nexthop_add_labels(nexthop, nh1->nh_label_type,
|
||||
nh1->nh_label->num_labels,
|
||||
&nh1->nh_label->label[0]);
|
||||
nexthop_add(tnh, nexthop);
|
||||
|
||||
if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
|
@ -45,14 +45,16 @@
|
||||
|
||||
#include <lib/openbsd-tree.h>
|
||||
|
||||
static inline struct rb_entry *rb_n2e(const struct rb_type *t, void *node)
|
||||
static inline struct rb_entry *
|
||||
rb_n2e(const struct rb_type *t, void *node)
|
||||
{
|
||||
unsigned long addr = (unsigned long)node;
|
||||
|
||||
return ((struct rb_entry *)(addr + t->t_offset));
|
||||
}
|
||||
|
||||
static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe)
|
||||
static inline void *
|
||||
rb_e2n(const struct rb_type *t, struct rb_entry *rbe)
|
||||
{
|
||||
unsigned long addr = (unsigned long)rbe;
|
||||
|
||||
@ -66,33 +68,37 @@ static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe)
|
||||
|
||||
#define RBH_ROOT(_rbt) (_rbt)->rbt_root
|
||||
|
||||
static inline void rbe_set(struct rb_entry *rbe, struct rb_entry *parent)
|
||||
static inline void
|
||||
rbe_set(struct rb_entry *rbe, struct rb_entry *parent)
|
||||
{
|
||||
RBE_PARENT(rbe) = parent;
|
||||
RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL;
|
||||
RBE_COLOR(rbe) = RB_RED;
|
||||
}
|
||||
|
||||
static inline void rbe_set_blackred(struct rb_entry *black,
|
||||
struct rb_entry *red)
|
||||
static inline void
|
||||
rbe_set_blackred(struct rb_entry *black, struct rb_entry *red)
|
||||
{
|
||||
RBE_COLOR(black) = RB_BLACK;
|
||||
RBE_COLOR(red) = RB_RED;
|
||||
}
|
||||
|
||||
static inline void rbe_augment(const struct rb_type *t, struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_augment(const struct rb_type *t, struct rb_entry *rbe)
|
||||
{
|
||||
(*t->t_augment)(rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
static inline void rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe)
|
||||
{
|
||||
if (t->t_augment != NULL)
|
||||
rbe_augment(t, rbe);
|
||||
}
|
||||
|
||||
static inline void rbe_rotate_left(const struct rb_type *t,
|
||||
struct rbt_tree *rbt, struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_rotate_left(const struct rb_type *t, struct rbt_tree *rbt,
|
||||
struct rb_entry *rbe)
|
||||
{
|
||||
struct rb_entry *parent;
|
||||
struct rb_entry *tmp;
|
||||
@ -124,8 +130,9 @@ static inline void rbe_rotate_left(const struct rb_type *t,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rbe_rotate_right(const struct rb_type *t,
|
||||
struct rbt_tree *rbt, struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_rotate_right(const struct rb_type *t, struct rbt_tree *rbt,
|
||||
struct rb_entry *rbe)
|
||||
{
|
||||
struct rb_entry *parent;
|
||||
struct rb_entry *tmp;
|
||||
@ -157,13 +164,14 @@ static inline void rbe_rotate_right(const struct rb_type *t,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rbe_insert_color(const struct rb_type *t,
|
||||
struct rbt_tree *rbt, struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_insert_color(const struct rb_type *t, struct rbt_tree *rbt,
|
||||
struct rb_entry *rbe)
|
||||
{
|
||||
struct rb_entry *parent, *gparent, *tmp;
|
||||
|
||||
while ((parent = RBE_PARENT(rbe)) != NULL
|
||||
&& RBE_COLOR(parent) == RB_RED) {
|
||||
while ((parent = RBE_PARENT(rbe)) != NULL &&
|
||||
RBE_COLOR(parent) == RB_RED) {
|
||||
gparent = RBE_PARENT(parent);
|
||||
|
||||
if (parent == RBE_LEFT(gparent)) {
|
||||
@ -208,19 +216,14 @@ static inline void rbe_insert_color(const struct rb_type *t,
|
||||
RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK;
|
||||
}
|
||||
|
||||
static inline void rbe_remove_color(const struct rb_type *t,
|
||||
struct rbt_tree *rbt,
|
||||
struct rb_entry *parent,
|
||||
struct rb_entry *rbe)
|
||||
static inline void
|
||||
rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt,
|
||||
struct rb_entry *parent, struct rb_entry *rbe)
|
||||
{
|
||||
struct rb_entry *tmp;
|
||||
|
||||
/* Silence clang possible NULL deference warning. */
|
||||
if (parent == NULL)
|
||||
return;
|
||||
|
||||
while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK)
|
||||
&& rbe != RBH_ROOT(rbt)) {
|
||||
while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) &&
|
||||
rbe != RBH_ROOT(rbt) && parent) {
|
||||
if (RBE_LEFT(parent) == rbe) {
|
||||
tmp = RBE_RIGHT(parent);
|
||||
if (RBE_COLOR(tmp) == RB_RED) {
|
||||
@ -228,16 +231,16 @@ static inline void rbe_remove_color(const struct rb_type *t,
|
||||
rbe_rotate_left(t, rbt, parent);
|
||||
tmp = RBE_RIGHT(parent);
|
||||
}
|
||||
if ((RBE_LEFT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK)
|
||||
&& (RBE_RIGHT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
|
||||
if ((RBE_LEFT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) &&
|
||||
(RBE_RIGHT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
|
||||
RBE_COLOR(tmp) = RB_RED;
|
||||
rbe = parent;
|
||||
parent = RBE_PARENT(rbe);
|
||||
} else {
|
||||
if (RBE_RIGHT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) {
|
||||
if (RBE_RIGHT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) {
|
||||
struct rb_entry *oleft;
|
||||
|
||||
oleft = RBE_LEFT(tmp);
|
||||
@ -266,16 +269,16 @@ static inline void rbe_remove_color(const struct rb_type *t,
|
||||
tmp = RBE_LEFT(parent);
|
||||
}
|
||||
|
||||
if ((RBE_LEFT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK)
|
||||
&& (RBE_RIGHT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
|
||||
if ((RBE_LEFT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) &&
|
||||
(RBE_RIGHT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
|
||||
RBE_COLOR(tmp) = RB_RED;
|
||||
rbe = parent;
|
||||
parent = RBE_PARENT(rbe);
|
||||
} else {
|
||||
if (RBE_LEFT(tmp) == NULL
|
||||
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) {
|
||||
if (RBE_LEFT(tmp) == NULL ||
|
||||
RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) {
|
||||
struct rb_entry *oright;
|
||||
|
||||
oright = RBE_RIGHT(tmp);
|
||||
@ -385,7 +388,8 @@ color:
|
||||
return (old);
|
||||
}
|
||||
|
||||
void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
void *
|
||||
_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, elm);
|
||||
struct rb_entry *old;
|
||||
@ -395,7 +399,8 @@ void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
return (old == NULL ? NULL : rb_e2n(t, old));
|
||||
}
|
||||
|
||||
void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
void *
|
||||
_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, elm);
|
||||
struct rb_entry *tmp;
|
||||
@ -435,7 +440,8 @@ void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
|
||||
}
|
||||
|
||||
/* Finds the node with the same key as elm */
|
||||
void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
void *
|
||||
_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
{
|
||||
struct rb_entry *tmp = RBH_ROOT(rbt);
|
||||
void *node;
|
||||
@ -456,7 +462,8 @@ void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
}
|
||||
|
||||
/* Finds the first node greater than or equal to the search key */
|
||||
void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
void *
|
||||
_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
{
|
||||
struct rb_entry *tmp = RBH_ROOT(rbt);
|
||||
void *node;
|
||||
@ -478,7 +485,8 @@ void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
|
||||
return (res);
|
||||
}
|
||||
|
||||
void *_rb_next(const struct rb_type *t, void *elm)
|
||||
void *
|
||||
_rb_next(const struct rb_type *t, void *elm)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, elm);
|
||||
|
||||
@ -487,11 +495,12 @@ void *_rb_next(const struct rb_type *t, void *elm)
|
||||
while (RBE_LEFT(rbe) != NULL)
|
||||
rbe = RBE_LEFT(rbe);
|
||||
} else {
|
||||
if (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe))))
|
||||
if (RBE_PARENT(rbe) &&
|
||||
(rbe == RBE_LEFT(RBE_PARENT(rbe))))
|
||||
rbe = RBE_PARENT(rbe);
|
||||
else {
|
||||
while (RBE_PARENT(rbe)
|
||||
&& (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
|
||||
while (RBE_PARENT(rbe) &&
|
||||
(rbe == RBE_RIGHT(RBE_PARENT(rbe))))
|
||||
rbe = RBE_PARENT(rbe);
|
||||
rbe = RBE_PARENT(rbe);
|
||||
}
|
||||
@ -500,7 +509,8 @@ void *_rb_next(const struct rb_type *t, void *elm)
|
||||
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void *_rb_prev(const struct rb_type *t, void *elm)
|
||||
void *
|
||||
_rb_prev(const struct rb_type *t, void *elm)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, elm);
|
||||
|
||||
@ -509,11 +519,12 @@ void *_rb_prev(const struct rb_type *t, void *elm)
|
||||
while (RBE_RIGHT(rbe))
|
||||
rbe = RBE_RIGHT(rbe);
|
||||
} else {
|
||||
if (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
|
||||
if (RBE_PARENT(rbe) &&
|
||||
(rbe == RBE_RIGHT(RBE_PARENT(rbe))))
|
||||
rbe = RBE_PARENT(rbe);
|
||||
else {
|
||||
while (RBE_PARENT(rbe)
|
||||
&& (rbe == RBE_LEFT(RBE_PARENT(rbe))))
|
||||
while (RBE_PARENT(rbe) &&
|
||||
(rbe == RBE_LEFT(RBE_PARENT(rbe))))
|
||||
rbe = RBE_PARENT(rbe);
|
||||
rbe = RBE_PARENT(rbe);
|
||||
}
|
||||
@ -522,14 +533,16 @@ void *_rb_prev(const struct rb_type *t, void *elm)
|
||||
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void *_rb_root(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
void *
|
||||
_rb_root(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
{
|
||||
struct rb_entry *rbe = RBH_ROOT(rbt);
|
||||
|
||||
return (rbe == NULL ? rbe : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
void *
|
||||
_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
{
|
||||
struct rb_entry *rbe = RBH_ROOT(rbt);
|
||||
struct rb_entry *parent = NULL;
|
||||
@ -542,7 +555,8 @@ void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
return (parent == NULL ? NULL : rb_e2n(t, parent));
|
||||
}
|
||||
|
||||
void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
void *
|
||||
_rb_max(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
{
|
||||
struct rb_entry *rbe = RBH_ROOT(rbt);
|
||||
struct rb_entry *parent = NULL;
|
||||
@ -555,28 +569,32 @@ void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt)
|
||||
return (parent == NULL ? NULL : rb_e2n(t, parent));
|
||||
}
|
||||
|
||||
void *_rb_left(const struct rb_type *t, void *node)
|
||||
void *
|
||||
_rb_left(const struct rb_type *t, void *node)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
rbe = RBE_LEFT(rbe);
|
||||
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void *_rb_right(const struct rb_type *t, void *node)
|
||||
void *
|
||||
_rb_right(const struct rb_type *t, void *node)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
rbe = RBE_RIGHT(rbe);
|
||||
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void *_rb_parent(const struct rb_type *t, void *node)
|
||||
void *
|
||||
_rb_parent(const struct rb_type *t, void *node)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
rbe = RBE_PARENT(rbe);
|
||||
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
|
||||
}
|
||||
|
||||
void _rb_set_left(const struct rb_type *t, void *node, void *left)
|
||||
void
|
||||
_rb_set_left(const struct rb_type *t, void *node, void *left)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left);
|
||||
@ -584,7 +602,8 @@ void _rb_set_left(const struct rb_type *t, void *node, void *left)
|
||||
RBE_LEFT(rbe) = rbl;
|
||||
}
|
||||
|
||||
void _rb_set_right(const struct rb_type *t, void *node, void *right)
|
||||
void
|
||||
_rb_set_right(const struct rb_type *t, void *node, void *right)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right);
|
||||
@ -592,7 +611,8 @@ void _rb_set_right(const struct rb_type *t, void *node, void *right)
|
||||
RBE_RIGHT(rbe) = rbr;
|
||||
}
|
||||
|
||||
void _rb_set_parent(const struct rb_type *t, void *node, void *parent)
|
||||
void
|
||||
_rb_set_parent(const struct rb_type *t, void *node, void *parent)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent);
|
||||
@ -600,19 +620,21 @@ void _rb_set_parent(const struct rb_type *t, void *node, void *parent)
|
||||
RBE_PARENT(rbe) = rbp;
|
||||
}
|
||||
|
||||
void _rb_poison(const struct rb_type *t, void *node, unsigned long poison)
|
||||
void
|
||||
_rb_poison(const struct rb_type *t, void *node, unsigned long poison)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
|
||||
RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) =
|
||||
(struct rb_entry *)poison;
|
||||
(struct rb_entry *)poison;
|
||||
}
|
||||
|
||||
int _rb_check(const struct rb_type *t, void *node, unsigned long poison)
|
||||
int
|
||||
_rb_check(const struct rb_type *t, void *node, unsigned long poison)
|
||||
{
|
||||
struct rb_entry *rbe = rb_n2e(t, node);
|
||||
|
||||
return ((unsigned long)RBE_PARENT(rbe) == poison
|
||||
&& (unsigned long)RBE_LEFT(rbe) == poison
|
||||
&& (unsigned long)RBE_RIGHT(rbe) == poison);
|
||||
return ((unsigned long)RBE_PARENT(rbe) == poison &&
|
||||
(unsigned long)RBE_LEFT(rbe) == poison &&
|
||||
(unsigned long)RBE_RIGHT(rbe) == poison);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TREE_H_
|
||||
#ifndef _SYS_TREE_H_
|
||||
#define _SYS_TREE_H_
|
||||
|
||||
/*
|
||||
@ -54,26 +54,23 @@
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ \
|
||||
NULL \
|
||||
}
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) \
|
||||
do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (0)
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
@ -81,220 +78,197 @@
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) \
|
||||
do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) \
|
||||
do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) \
|
||||
do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) \
|
||||
do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) \
|
||||
do { \
|
||||
SPLAY_RIGHT(left, field) = \
|
||||
SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = \
|
||||
SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT((head)->sph_root, field) = \
|
||||
SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = \
|
||||
SPLAY_LEFT(node, field); \
|
||||
} while (0)
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type *name##_SPLAY_FIND(struct name *head, \
|
||||
struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type *name##_SPLAY_NEXT(struct name *head, \
|
||||
struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type *name##_SPLAY_MIN_MAX(struct name *head, \
|
||||
int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type *name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = \
|
||||
NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if (__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = \
|
||||
SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = \
|
||||
SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type *name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = \
|
||||
SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = \
|
||||
SPLAY_LEFT((head)->sph_root, field); \
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \
|
||||
NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0) { \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, \
|
||||
field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, \
|
||||
field) \
|
||||
== NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, \
|
||||
field) \
|
||||
== NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \
|
||||
NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0) { \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, \
|
||||
field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, \
|
||||
field) \
|
||||
== NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, \
|
||||
field) \
|
||||
== NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
@ -303,13 +277,14 @@
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) \
|
||||
(SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) \
|
||||
(SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); (x) != NULL; \
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/*
|
||||
@ -332,197 +307,203 @@
|
||||
#define RB_RED 1
|
||||
|
||||
struct rb_type {
|
||||
int (*t_compare)(const void *, const void *);
|
||||
void (*t_augment)(void *);
|
||||
unsigned int t_offset; /* offset of rb_entry in type */
|
||||
int (*t_compare)(const void *, const void *);
|
||||
void (*t_augment)(void *);
|
||||
unsigned int t_offset; /* offset of rb_entry in type */
|
||||
};
|
||||
|
||||
struct rbt_tree {
|
||||
struct rb_entry *rbt_root;
|
||||
struct rb_entry *rbt_root;
|
||||
};
|
||||
|
||||
struct rb_entry {
|
||||
struct rb_entry *rbt_parent;
|
||||
struct rb_entry *rbt_left;
|
||||
struct rb_entry *rbt_right;
|
||||
unsigned int rbt_color;
|
||||
struct rb_entry *rbt_parent;
|
||||
struct rb_entry *rbt_left;
|
||||
struct rb_entry *rbt_right;
|
||||
unsigned int rbt_color;
|
||||
};
|
||||
|
||||
#define RB_HEAD(_name, _type) \
|
||||
struct _name { \
|
||||
struct rbt_tree rbh_root; \
|
||||
}
|
||||
#define RB_HEAD(_name, _type) \
|
||||
struct _name { \
|
||||
struct rbt_tree rbh_root; \
|
||||
}
|
||||
|
||||
#define RB_ENTRY(_type) struct rb_entry
|
||||
|
||||
static inline void _rb_init(struct rbt_tree *rbt)
|
||||
static inline void
|
||||
_rb_init(struct rbt_tree *rbt)
|
||||
{
|
||||
rbt->rbt_root = NULL;
|
||||
}
|
||||
|
||||
static inline int _rb_empty(struct rbt_tree *rbt)
|
||||
static inline int
|
||||
_rb_empty(struct rbt_tree *rbt)
|
||||
{
|
||||
return (rbt->rbt_root == NULL);
|
||||
}
|
||||
|
||||
void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *);
|
||||
void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *);
|
||||
void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *);
|
||||
void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *);
|
||||
void *_rb_root(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_min(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_max(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_next(const struct rb_type *, void *);
|
||||
void *_rb_prev(const struct rb_type *, void *);
|
||||
void *_rb_left(const struct rb_type *, void *);
|
||||
void *_rb_right(const struct rb_type *, void *);
|
||||
void *_rb_parent(const struct rb_type *, void *);
|
||||
void _rb_set_left(const struct rb_type *, void *, void *);
|
||||
void _rb_set_right(const struct rb_type *, void *, void *);
|
||||
void _rb_set_parent(const struct rb_type *, void *, void *);
|
||||
void _rb_poison(const struct rb_type *, void *, unsigned long);
|
||||
int _rb_check(const struct rb_type *, void *, unsigned long);
|
||||
void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *);
|
||||
void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *);
|
||||
void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *);
|
||||
void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *);
|
||||
void *_rb_root(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_min(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_max(const struct rb_type *, struct rbt_tree *);
|
||||
void *_rb_next(const struct rb_type *, void *);
|
||||
void *_rb_prev(const struct rb_type *, void *);
|
||||
void *_rb_left(const struct rb_type *, void *);
|
||||
void *_rb_right(const struct rb_type *, void *);
|
||||
void *_rb_parent(const struct rb_type *, void *);
|
||||
void _rb_set_left(const struct rb_type *, void *, void *);
|
||||
void _rb_set_right(const struct rb_type *, void *, void *);
|
||||
void _rb_set_parent(const struct rb_type *, void *, void *);
|
||||
void _rb_poison(const struct rb_type *, void *, unsigned long);
|
||||
int _rb_check(const struct rb_type *, void *, unsigned long);
|
||||
|
||||
#define RB_INITIALIZER(_head) { { NULL } }
|
||||
|
||||
#define RB_PROTOTYPE(_name, _type, _field, _cmp) \
|
||||
extern const struct rb_type *const _name##_RB_TYPE; \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void _name##_RB_INIT( \
|
||||
struct _name *head) \
|
||||
{ \
|
||||
_rb_init(&head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_INSERT(struct _name *head, struct _type *elm) \
|
||||
{ \
|
||||
return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_REMOVE(struct _name *head, struct _type *elm) \
|
||||
{ \
|
||||
return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_FIND(struct _name *head, const struct _type *key) \
|
||||
{ \
|
||||
return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_NFIND(struct _name *head, const struct _type *key) \
|
||||
{ \
|
||||
return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_ROOT(struct _name *head) \
|
||||
{ \
|
||||
return _rb_root(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline int _name##_RB_EMPTY( \
|
||||
struct _name *head) \
|
||||
{ \
|
||||
return _rb_empty(&head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_MIN(struct _name *head) \
|
||||
{ \
|
||||
return _rb_min(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_MAX(struct _name *head) \
|
||||
{ \
|
||||
return _rb_max(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_NEXT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_next(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_PREV(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_prev(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_LEFT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_left(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_RIGHT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_right(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type \
|
||||
*_name##_RB_PARENT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_parent(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void _name##_RB_SET_LEFT( \
|
||||
struct _type *elm, struct _type *left) \
|
||||
{ \
|
||||
return _rb_set_left(_name##_RB_TYPE, elm, left); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void _name##_RB_SET_RIGHT( \
|
||||
struct _type *elm, struct _type *right) \
|
||||
{ \
|
||||
return _rb_set_right(_name##_RB_TYPE, elm, right); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void _name##_RB_SET_PARENT( \
|
||||
struct _type *elm, struct _type *parent) \
|
||||
{ \
|
||||
return _rb_set_parent(_name##_RB_TYPE, elm, parent); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void _name##_RB_POISON( \
|
||||
struct _type *elm, unsigned long poison) \
|
||||
{ \
|
||||
return _rb_poison(_name##_RB_TYPE, elm, poison); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline int _name##_RB_CHECK( \
|
||||
struct _type *elm, unsigned long poison) \
|
||||
{ \
|
||||
return _rb_check(_name##_RB_TYPE, elm, poison); \
|
||||
}
|
||||
#define RB_PROTOTYPE(_name, _type, _field, _cmp) \
|
||||
extern const struct rb_type *const _name##_RB_TYPE; \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void \
|
||||
_name##_RB_INIT(struct _name *head) \
|
||||
{ \
|
||||
_rb_init(&head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_INSERT(struct _name *head, struct _type *elm) \
|
||||
{ \
|
||||
return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_REMOVE(struct _name *head, struct _type *elm) \
|
||||
{ \
|
||||
return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_FIND(struct _name *head, const struct _type *key) \
|
||||
{ \
|
||||
return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_NFIND(struct _name *head, const struct _type *key) \
|
||||
{ \
|
||||
return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_ROOT(struct _name *head) \
|
||||
{ \
|
||||
return _rb_root(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline int \
|
||||
_name##_RB_EMPTY(struct _name *head) \
|
||||
{ \
|
||||
return _rb_empty(&head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_MIN(struct _name *head) \
|
||||
{ \
|
||||
return _rb_min(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_MAX(struct _name *head) \
|
||||
{ \
|
||||
return _rb_max(_name##_RB_TYPE, &head->rbh_root); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_NEXT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_next(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_PREV(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_prev(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_LEFT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_left(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_RIGHT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_right(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline struct _type * \
|
||||
_name##_RB_PARENT(struct _type *elm) \
|
||||
{ \
|
||||
return _rb_parent(_name##_RB_TYPE, elm); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void \
|
||||
_name##_RB_SET_LEFT(struct _type *elm, struct _type *left) \
|
||||
{ \
|
||||
return _rb_set_left(_name##_RB_TYPE, elm, left); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void \
|
||||
_name##_RB_SET_RIGHT(struct _type *elm, struct _type *right) \
|
||||
{ \
|
||||
return _rb_set_right(_name##_RB_TYPE, elm, right); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void \
|
||||
_name##_RB_SET_PARENT(struct _type *elm, struct _type *parent) \
|
||||
{ \
|
||||
return _rb_set_parent(_name##_RB_TYPE, elm, parent); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline void \
|
||||
_name##_RB_POISON(struct _type *elm, unsigned long poison) \
|
||||
{ \
|
||||
return _rb_poison(_name##_RB_TYPE, elm, poison); \
|
||||
} \
|
||||
\
|
||||
__attribute__((__unused__)) static inline int \
|
||||
_name##_RB_CHECK(struct _type *elm, unsigned long poison) \
|
||||
{ \
|
||||
return _rb_check(_name##_RB_TYPE, elm, poison); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \
|
||||
static int _name##_RB_COMPARE(const void *lptr, const void *rptr) \
|
||||
{ \
|
||||
const struct _type *l = lptr, *r = rptr; \
|
||||
return _cmp(l, r); \
|
||||
} \
|
||||
static const struct rb_type _name##_RB_INFO = { \
|
||||
_name##_RB_COMPARE, _aug, offsetof(struct _type, _field), \
|
||||
}; \
|
||||
const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO;
|
||||
#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \
|
||||
static int \
|
||||
_name##_RB_COMPARE(const void *lptr, const void *rptr) \
|
||||
{ \
|
||||
const struct _type *l = lptr, *r = rptr; \
|
||||
return _cmp(l, r); \
|
||||
} \
|
||||
static const struct rb_type _name##_RB_INFO = { \
|
||||
_name##_RB_COMPARE, \
|
||||
_aug, \
|
||||
offsetof(struct _type, _field), \
|
||||
}; \
|
||||
const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO;
|
||||
|
||||
#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \
|
||||
static void _name##_RB_AUGMENT(void *ptr) \
|
||||
{ \
|
||||
struct _type *p = ptr; \
|
||||
return _aug(p); \
|
||||
} \
|
||||
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT)
|
||||
#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \
|
||||
static void \
|
||||
_name##_RB_AUGMENT(void *ptr) \
|
||||
{ \
|
||||
struct _type *p = ptr; \
|
||||
return _aug(p); \
|
||||
} \
|
||||
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT)
|
||||
|
||||
#define RB_GENERATE(_name, _type, _field, _cmp) \
|
||||
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
|
||||
#define RB_GENERATE(_name, _type, _field, _cmp) \
|
||||
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
|
||||
|
||||
#define RB_INIT(_name, _head) _name##_RB_INIT(_head)
|
||||
#define RB_INSERT(_name, _head, _elm) _name##_RB_INSERT(_head, _elm)
|
||||
@ -544,20 +525,24 @@ int _rb_check(const struct rb_type *, void *, unsigned long);
|
||||
#define RB_POISON(_name, _elm, _p) _name##_RB_POISON(_elm, _p)
|
||||
#define RB_CHECK(_name, _elm, _p) _name##_RB_CHECK(_elm, _p)
|
||||
|
||||
#define RB_FOREACH(_e, _name, _head) \
|
||||
for ((_e) = RB_MIN(_name, (_head)); (_e) != NULL; \
|
||||
#define RB_FOREACH(_e, _name, _head) \
|
||||
for ((_e) = RB_MIN(_name, (_head)); \
|
||||
(_e) != NULL; \
|
||||
(_e) = RB_NEXT(_name, (_e)))
|
||||
|
||||
#define RB_FOREACH_SAFE(_e, _name, _head, _n) \
|
||||
for ((_e) = RB_MIN(_name, (_head)); \
|
||||
(_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); (_e) = (_n))
|
||||
#define RB_FOREACH_SAFE(_e, _name, _head, _n) \
|
||||
for ((_e) = RB_MIN(_name, (_head)); \
|
||||
(_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); \
|
||||
(_e) = (_n))
|
||||
|
||||
#define RB_FOREACH_REVERSE(_e, _name, _head) \
|
||||
for ((_e) = RB_MAX(_name, (_head)); (_e) != NULL; \
|
||||
#define RB_FOREACH_REVERSE(_e, _name, _head) \
|
||||
for ((_e) = RB_MAX(_name, (_head)); \
|
||||
(_e) != NULL; \
|
||||
(_e) = RB_PREV(_name, (_e)))
|
||||
|
||||
#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \
|
||||
for ((_e) = RB_MAX(_name, (_head)); \
|
||||
(_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); (_e) = (_n))
|
||||
#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \
|
||||
for ((_e) = RB_MAX(_name, (_head)); \
|
||||
(_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); \
|
||||
(_e) = (_n))
|
||||
|
||||
#endif /* _SYS_TREE_H_ */
|
||||
#endif /* _SYS_TREE_H_ */
|
||||
|
@ -507,8 +507,9 @@ const char *safi2str(safi_t safi)
|
||||
return "evpn";
|
||||
case SAFI_LABELED_UNICAST:
|
||||
return "labeled-unicast";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If n includes p prefix then return 1 else return 0. */
|
||||
|
260
lib/subdir.am
Normal file
260
lib/subdir.am
Normal file
@ -0,0 +1,260 @@
|
||||
#
|
||||
# libfrr
|
||||
#
|
||||
lib_LTLIBRARIES += lib/libfrr.la
|
||||
lib_libfrr_la_LDFLAGS = -version-info 0:0:0
|
||||
lib_libfrr_la_LIBADD = @LIBCAP@
|
||||
|
||||
lib_libfrr_la_SOURCES = \
|
||||
lib/bfd.c \
|
||||
lib/buffer.c \
|
||||
lib/checksum.c \
|
||||
lib/command.c \
|
||||
lib/command_graph.c \
|
||||
lib/command_lex.l \
|
||||
lib/command_match.c \
|
||||
lib/command_parse.y \
|
||||
lib/csv.c \
|
||||
lib/distribute.c \
|
||||
lib/event_counter.c \
|
||||
lib/filter.c \
|
||||
lib/frr_pthread.c \
|
||||
lib/getopt.c \
|
||||
lib/getopt1.c \
|
||||
lib/grammar_sandbox.c \
|
||||
lib/graph.c \
|
||||
lib/hash.c \
|
||||
lib/hook.c \
|
||||
lib/if.c \
|
||||
lib/if_rmap.c \
|
||||
lib/imsg-buffer.c \
|
||||
lib/imsg.c \
|
||||
lib/jhash.c \
|
||||
lib/json.c \
|
||||
lib/keychain.c \
|
||||
lib/libfrr.c \
|
||||
lib/linklist.c \
|
||||
lib/log.c \
|
||||
lib/md5.c \
|
||||
lib/memory.c \
|
||||
lib/memory_vty.c \
|
||||
lib/module.c \
|
||||
lib/network.c \
|
||||
lib/nexthop.c \
|
||||
lib/ns.c \
|
||||
lib/openbsd-tree.c \
|
||||
lib/pid_output.c \
|
||||
lib/plist.c \
|
||||
lib/pqueue.c \
|
||||
lib/prefix.c \
|
||||
lib/privs.c \
|
||||
lib/ptm_lib.c \
|
||||
lib/qobj.c \
|
||||
lib/routemap.c \
|
||||
lib/sha256.c \
|
||||
lib/sigevent.c \
|
||||
lib/skiplist.c \
|
||||
lib/sockopt.c \
|
||||
lib/sockunion.c \
|
||||
lib/spf_backoff.c \
|
||||
lib/srcdest_table.c \
|
||||
lib/stream.c \
|
||||
lib/strlcat.c \
|
||||
lib/strlcpy.c \
|
||||
lib/systemd.c \
|
||||
lib/table.c \
|
||||
lib/termtable.c \
|
||||
lib/thread.c \
|
||||
lib/vector.c \
|
||||
lib/vrf.c \
|
||||
lib/vty.c \
|
||||
lib/wheel.c \
|
||||
lib/workqueue.c \
|
||||
lib/zclient.c \
|
||||
# end
|
||||
|
||||
lib/plist_clippy.c: $(CLIPPY_DEPS)
|
||||
lib/plist.lo: lib/plist_clippy.c
|
||||
|
||||
pkginclude_HEADERS += \
|
||||
lib/bfd.h \
|
||||
lib/bitfield.h \
|
||||
lib/buffer.h \
|
||||
lib/checksum.h \
|
||||
lib/command.h \
|
||||
lib/command_graph.h \
|
||||
lib/command_match.h \
|
||||
lib/csv.h \
|
||||
lib/distribute.h \
|
||||
lib/event_counter.h \
|
||||
lib/fifo.h \
|
||||
lib/filter.h \
|
||||
lib/frr_pthread.h \
|
||||
lib/frratomic.h \
|
||||
lib/getopt.h \
|
||||
lib/graph.h \
|
||||
lib/hash.h \
|
||||
lib/hook.h \
|
||||
lib/if.h \
|
||||
lib/if_rmap.h \
|
||||
lib/imsg.h \
|
||||
lib/ipaddr.h \
|
||||
lib/jhash.h \
|
||||
lib/json.h \
|
||||
lib/keychain.h \
|
||||
lib/libfrr.h \
|
||||
lib/libospf.h \
|
||||
lib/linklist.h \
|
||||
lib/log.h \
|
||||
lib/md5.h \
|
||||
lib/memory.h \
|
||||
lib/memory_vty.h \
|
||||
lib/module.h \
|
||||
lib/monotime.h \
|
||||
lib/mpls.h \
|
||||
lib/network.h \
|
||||
lib/nexthop.h \
|
||||
lib/ns.h \
|
||||
lib/openbsd-queue.h \
|
||||
lib/openbsd-tree.h \
|
||||
lib/plist.h \
|
||||
lib/pqueue.h \
|
||||
lib/prefix.h \
|
||||
lib/privs.h \
|
||||
lib/ptm_lib.h \
|
||||
lib/qobj.h \
|
||||
lib/route_types.h \
|
||||
lib/routemap.h \
|
||||
lib/sha256.h \
|
||||
lib/sigevent.h \
|
||||
lib/skiplist.h \
|
||||
lib/smux.h \
|
||||
lib/sockopt.h \
|
||||
lib/sockunion.h \
|
||||
lib/spf_backoff.h \
|
||||
lib/srcdest_table.h \
|
||||
lib/stream.h \
|
||||
lib/systemd.h \
|
||||
lib/table.h \
|
||||
lib/termtable.h \
|
||||
lib/thread.h \
|
||||
lib/vector.h \
|
||||
lib/version.h \
|
||||
lib/vlan.h \
|
||||
lib/vrf.h \
|
||||
lib/vrf_int.h \
|
||||
lib/vty.h \
|
||||
lib/vxlan.h \
|
||||
lib/wheel.h \
|
||||
lib/workqueue.h \
|
||||
lib/zassert.h \
|
||||
lib/zclient.h \
|
||||
lib/zebra.h \
|
||||
# end
|
||||
|
||||
noinst_HEADERS += \
|
||||
lib/clippy.h \
|
||||
lib/log_int.h \
|
||||
lib/plist_int.h \
|
||||
#end
|
||||
|
||||
#
|
||||
# SNMP support
|
||||
#
|
||||
if SNMP
|
||||
lib_LTLIBRARIES += lib/libfrrsnmp.la
|
||||
endif
|
||||
|
||||
lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
||||
lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
|
||||
lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
|
||||
lib_libfrrsnmp_la_SOURCES = \
|
||||
lib/agentx.c \
|
||||
lib/smux.c \
|
||||
lib/snmp.c \
|
||||
# end
|
||||
|
||||
#
|
||||
# CLI utilities
|
||||
#
|
||||
noinst_PROGRAMS += \
|
||||
lib/clippy \
|
||||
lib/grammar_sandbox \
|
||||
# end
|
||||
|
||||
lib_grammar_sandbox_SOURCES = \
|
||||
lib/grammar_sandbox_main.c
|
||||
lib_grammar_sandbox_LDADD = \
|
||||
lib/libfrr.la
|
||||
|
||||
lib_clippy_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/lib
|
||||
lib_clippy_CFLAGS = $(PYTHON_CFLAGS)
|
||||
lib_clippy_LDADD = $(PYTHON_LIBS)
|
||||
lib_clippy_SOURCES = \
|
||||
lib/clippy.c \
|
||||
lib/command_graph.c \
|
||||
lib/command_lex.l \
|
||||
lib/command_parse.y \
|
||||
lib/command_py.c \
|
||||
lib/defun_lex.l \
|
||||
lib/graph.c \
|
||||
lib/memory.c \
|
||||
lib/vector.c \
|
||||
# end
|
||||
|
||||
|
||||
#
|
||||
# generated sources & extra foo
|
||||
#
|
||||
EXTRA_DIST += \
|
||||
lib/command_lex.h \
|
||||
lib/gitversion.pl \
|
||||
lib/queue.h \
|
||||
lib/route_types.pl \
|
||||
lib/route_types.txt \
|
||||
# end
|
||||
|
||||
BUILT_SOURCES += \
|
||||
lib/command_lex.h \
|
||||
lib/command_parse.h \
|
||||
lib/gitversion.h \
|
||||
lib/route_types.h \
|
||||
# end
|
||||
|
||||
## force route_types.h
|
||||
$(lib_clippy_OBJECTS): lib/route_types.h
|
||||
$(lib_libfrr_la_OBJECTS): lib/route_types.h
|
||||
|
||||
AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ @BISON_VERBOSE@
|
||||
|
||||
lib/command_lex.h: lib/command_lex.c
|
||||
@if test ! -f $@; then rm -f "lib/command_lex.c"; else :; fi
|
||||
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) "lib/command_lex.c"; else :; fi
|
||||
lib/command_lex.lo: lib/command_parse.h
|
||||
lib/command_parse.lo: lib/command_lex.h
|
||||
lib/lib_clippy-command_lex.$(OBJEXT): lib/command_parse.h
|
||||
lib/lib_clippy-command_parse.$(OBJEXT): lib/command_lex.h
|
||||
|
||||
lib/route_types.h: $(top_srcdir)/lib/route_types.txt $(top_srcdir)/lib/route_types.pl
|
||||
@PERL@ $(top_srcdir)/lib/route_types.pl < $(top_srcdir)/lib/route_types.txt > $@
|
||||
|
||||
if GIT_VERSION
|
||||
# bit of a trick here to always have up-to-date git stamps without triggering
|
||||
# unneccessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
|
||||
# but if we use that on gitversion.h it'll ripple through the .c file deps.
|
||||
# (even if gitversion.h's file timestamp doesn't change, make will think it
|
||||
# did, because of .PHONY...)
|
||||
|
||||
.PHONY: lib/gitversion.h.tmp
|
||||
.SILENT: lib/gitversion.h lib/gitversion.h.tmp
|
||||
GITH=lib/gitversion.h
|
||||
lib/gitversion.h.tmp: $(top_srcdir)/.git
|
||||
@PERL@ $(top_srcdir)/lib/gitversion.pl $(top_srcdir) > ${GITH}.tmp
|
||||
lib/gitversion.h: lib/gitversion.h.tmp
|
||||
{ test -f ${GITH} && diff -s -q ${GITH}.tmp ${GITH}; } || cp ${GITH}.tmp ${GITH}
|
||||
|
||||
else
|
||||
.PHONY: lib/gitversion.h
|
||||
lib/gitversion.h:
|
||||
true
|
||||
endif
|
102
lib/zebra.h
102
lib/zebra.h
@ -416,22 +416,15 @@ extern const char *zserv_command_string(unsigned int command);
|
||||
typedef enum { AFI_IP = 1, AFI_IP6 = 2, AFI_L2VPN = 3, AFI_MAX = 4 } afi_t;
|
||||
|
||||
/* Subsequent Address Family Identifier. */
|
||||
#define SAFI_UNICAST 1
|
||||
#define SAFI_MULTICAST 2
|
||||
#define SAFI_MPLS_VPN 3
|
||||
#define SAFI_RESERVED_4 4
|
||||
#define SAFI_ENCAP 5
|
||||
#define SAFI_RESERVED_5 5
|
||||
#define SAFI_EVPN 6
|
||||
#define SAFI_LABELED_UNICAST 7
|
||||
#define SAFI_MAX 8
|
||||
|
||||
#define IANA_SAFI_RESERVED 0
|
||||
#define IANA_SAFI_UNICAST 1
|
||||
#define IANA_SAFI_MULTICAST 2
|
||||
#define IANA_SAFI_LABELED_UNICAST 4
|
||||
#define IANA_SAFI_ENCAP 7
|
||||
#define IANA_SAFI_MPLS_VPN 128
|
||||
typedef enum {
|
||||
SAFI_UNICAST = 1,
|
||||
SAFI_MULTICAST = 2,
|
||||
SAFI_MPLS_VPN = 3,
|
||||
SAFI_ENCAP = 4,
|
||||
SAFI_EVPN = 5,
|
||||
SAFI_LABELED_UNICAST = 6,
|
||||
SAFI_MAX = 7
|
||||
} safi_t;
|
||||
|
||||
/*
|
||||
* The above AFI and SAFI definitions are for internal use. The protocol
|
||||
@ -451,12 +444,15 @@ typedef enum {
|
||||
IANA_AFI_IP6MR = 129
|
||||
} iana_afi_t;
|
||||
|
||||
#define IANA_SAFI_RESERVED 0
|
||||
#define IANA_SAFI_UNICAST 1
|
||||
#define IANA_SAFI_MULTICAST 2
|
||||
#define IANA_SAFI_ENCAP 7
|
||||
#define IANA_SAFI_EVPN 70
|
||||
#define IANA_SAFI_MPLS_VPN 128
|
||||
typedef enum {
|
||||
IANA_SAFI_RESERVED = 0,
|
||||
IANA_SAFI_UNICAST = 1,
|
||||
IANA_SAFI_MULTICAST = 2,
|
||||
IANA_SAFI_LABELED_UNICAST = 4,
|
||||
IANA_SAFI_ENCAP = 7,
|
||||
IANA_SAFI_EVPN = 70,
|
||||
IANA_SAFI_MPLS_VPN = 128
|
||||
} iana_safi_t;
|
||||
|
||||
/* Default Administrative Distance of each protocol. */
|
||||
#define ZEBRA_KERNEL_DISTANCE_DEFAULT 0
|
||||
@ -477,8 +473,6 @@ typedef enum {
|
||||
#define UNSET_FLAG(V,F) (V) &= ~(F)
|
||||
#define RESET_FLAG(V) (V) = 0
|
||||
|
||||
typedef u_int8_t safi_t;
|
||||
|
||||
/* Zebra types. Used in Zserv message header. */
|
||||
typedef u_int16_t zebra_size_t;
|
||||
typedef u_int16_t zebra_command_t;
|
||||
@ -492,58 +486,70 @@ typedef uint32_t route_tag_t;
|
||||
|
||||
static inline afi_t afi_iana2int(iana_afi_t afi)
|
||||
{
|
||||
if (afi == IANA_AFI_IPV4)
|
||||
switch (afi) {
|
||||
case IANA_AFI_IPV4:
|
||||
return AFI_IP;
|
||||
if (afi == IANA_AFI_IPV6)
|
||||
case IANA_AFI_IPV6:
|
||||
return AFI_IP6;
|
||||
if (afi == IANA_AFI_L2VPN)
|
||||
case IANA_AFI_L2VPN:
|
||||
return AFI_L2VPN;
|
||||
return AFI_MAX;
|
||||
default:
|
||||
return AFI_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static inline iana_afi_t afi_int2iana(afi_t afi)
|
||||
{
|
||||
if (afi == AFI_IP)
|
||||
switch (afi) {
|
||||
case AFI_IP:
|
||||
return IANA_AFI_IPV4;
|
||||
if (afi == AFI_IP6)
|
||||
case AFI_IP6:
|
||||
return IANA_AFI_IPV6;
|
||||
if (afi == AFI_L2VPN)
|
||||
case AFI_L2VPN:
|
||||
return IANA_AFI_L2VPN;
|
||||
return IANA_AFI_RESERVED;
|
||||
default:
|
||||
return IANA_AFI_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
static inline safi_t safi_iana2int(safi_t safi)
|
||||
static inline safi_t safi_iana2int(iana_safi_t safi)
|
||||
{
|
||||
if (safi == IANA_SAFI_UNICAST)
|
||||
switch (safi) {
|
||||
case IANA_SAFI_UNICAST:
|
||||
return SAFI_UNICAST;
|
||||
if (safi == IANA_SAFI_MULTICAST)
|
||||
case IANA_SAFI_MULTICAST:
|
||||
return SAFI_MULTICAST;
|
||||
if (safi == IANA_SAFI_MPLS_VPN)
|
||||
case IANA_SAFI_MPLS_VPN:
|
||||
return SAFI_MPLS_VPN;
|
||||
if (safi == IANA_SAFI_ENCAP)
|
||||
case IANA_SAFI_ENCAP:
|
||||
return SAFI_ENCAP;
|
||||
if (safi == IANA_SAFI_EVPN)
|
||||
case IANA_SAFI_EVPN:
|
||||
return SAFI_EVPN;
|
||||
if (safi == IANA_SAFI_LABELED_UNICAST)
|
||||
case IANA_SAFI_LABELED_UNICAST:
|
||||
return SAFI_LABELED_UNICAST;
|
||||
return SAFI_MAX;
|
||||
default:
|
||||
return SAFI_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static inline safi_t safi_int2iana(safi_t safi)
|
||||
static inline iana_safi_t safi_int2iana(safi_t safi)
|
||||
{
|
||||
if (safi == SAFI_UNICAST)
|
||||
switch (safi) {
|
||||
case SAFI_UNICAST:
|
||||
return IANA_SAFI_UNICAST;
|
||||
if (safi == SAFI_MULTICAST)
|
||||
case SAFI_MULTICAST:
|
||||
return IANA_SAFI_MULTICAST;
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
case SAFI_MPLS_VPN:
|
||||
return IANA_SAFI_MPLS_VPN;
|
||||
if (safi == SAFI_ENCAP)
|
||||
case SAFI_ENCAP:
|
||||
return IANA_SAFI_ENCAP;
|
||||
if (safi == SAFI_EVPN)
|
||||
case SAFI_EVPN:
|
||||
return IANA_SAFI_EVPN;
|
||||
if (safi == SAFI_LABELED_UNICAST)
|
||||
case SAFI_LABELED_UNICAST:
|
||||
return IANA_SAFI_LABELED_UNICAST;
|
||||
return IANA_SAFI_RESERVED;
|
||||
default:
|
||||
return IANA_SAFI_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _ZEBRA_H */
|
||||
|
@ -1 +0,0 @@
|
||||
EXTRA_DIST=Makefile.am README.txt
|
@ -1437,7 +1437,7 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
|
||||
char brouter_name[16];
|
||||
char area_name[16];
|
||||
char destination[64];
|
||||
char installed[16], changed[16];
|
||||
char installed[64], changed[64];
|
||||
struct timeval now, res;
|
||||
char id[16], adv_router[16];
|
||||
char capa[16], options[16];
|
||||
|
@ -467,7 +467,7 @@ void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
|
||||
char adv_router[64], id[64];
|
||||
struct ospf6_lsa_handler *handler;
|
||||
struct timeval now, res;
|
||||
char duration[16];
|
||||
char duration[64];
|
||||
|
||||
assert(lsa && lsa->header);
|
||||
|
||||
|
@ -582,10 +582,10 @@ int inactivity_timer(struct thread *thread)
|
||||
static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on)
|
||||
{
|
||||
char router_id[16];
|
||||
char duration[16];
|
||||
char duration[64];
|
||||
struct timeval res;
|
||||
char nstate[16];
|
||||
char deadtime[16];
|
||||
char deadtime[64];
|
||||
long h, m, s;
|
||||
|
||||
/* Router-ID (Name) */
|
||||
@ -640,7 +640,7 @@ static void ospf6_neighbor_show_drchoice(struct vty *vty,
|
||||
{
|
||||
char router_id[16];
|
||||
char drouter[16], bdrouter[16];
|
||||
char duration[16];
|
||||
char duration[64];
|
||||
struct timeval now, res;
|
||||
|
||||
/*
|
||||
|
@ -945,7 +945,7 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route)
|
||||
{
|
||||
int i;
|
||||
char destination[PREFIX2STR_BUFFER], nexthop[64];
|
||||
char duration[16];
|
||||
char duration[64];
|
||||
const char *ifname;
|
||||
struct timeval now, res;
|
||||
struct listnode *node;
|
||||
@ -991,7 +991,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
|
||||
char destination[PREFIX2STR_BUFFER], nexthop[64];
|
||||
char area_id[16], id[16], adv_router[16], capa[16], options[16];
|
||||
struct timeval now, res;
|
||||
char duration[16];
|
||||
char duration[64];
|
||||
struct listnode *node;
|
||||
struct ospf6_nexthop *nh;
|
||||
|
||||
|
@ -77,6 +77,44 @@
|
||||
((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \
|
||||
&& ((ntohs((lsahdr)->length) % sizeof(u_int32_t)) == 0))
|
||||
|
||||
/*
|
||||
* Following section defines generic TLV (type, length, value) macros,
|
||||
* used for various LSA opaque usage e.g. Traffic Engineering.
|
||||
*/
|
||||
struct tlv_header {
|
||||
u_int16_t type; /* Type of Value */
|
||||
u_int16_t length; /* Length of Value portion only, in bytes */
|
||||
};
|
||||
|
||||
#define TLV_HDR_SIZE (sizeof(struct tlv_header))
|
||||
|
||||
#define TLV_BODY_SIZE(tlvh) \
|
||||
(ROUNDUP(ntohs((tlvh)->length), sizeof(u_int32_t)))
|
||||
|
||||
#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
|
||||
|
||||
#define TLV_HDR_TOP(lsah) \
|
||||
(struct tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
|
||||
|
||||
#define TLV_HDR_NEXT(tlvh) \
|
||||
(struct tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
|
||||
|
||||
#define TLV_HDR_SUBTLV(tlvh) \
|
||||
(struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE)
|
||||
|
||||
#define TLV_DATA(tlvh) (void *)((char *)(tlvh) + TLV_HDR_SIZE)
|
||||
|
||||
#define TLV_TYPE(tlvh) tlvh.header.type
|
||||
#define TLV_LEN(tlvh) tlvh.header.length
|
||||
#define TLV_HDR(tlvh) tlvh.header
|
||||
|
||||
/* Following declaration concerns the Opaque LSA management */
|
||||
enum lsa_opcode {
|
||||
REORIGINATE_THIS_LSA,
|
||||
REFRESH_THIS_LSA,
|
||||
FLUSH_THIS_LSA
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
|
||||
extern void ospf_opaque_init(void);
|
||||
@ -108,7 +146,7 @@ extern int ospf_opaque_new_if(struct interface *ifp);
|
||||
extern int ospf_opaque_del_if(struct interface *ifp);
|
||||
extern void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status);
|
||||
extern void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_status);
|
||||
extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *);
|
||||
extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf);
|
||||
extern void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp);
|
||||
extern void ospf_opaque_config_write_debug(struct vty *vty);
|
||||
extern void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa);
|
||||
@ -116,7 +154,7 @@ extern void ospf_opaque_lsa_dump(struct stream *s, u_int16_t length);
|
||||
|
||||
extern void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi,
|
||||
int *init_delay);
|
||||
extern struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *,
|
||||
extern struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa,
|
||||
int rt_recalc);
|
||||
extern struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa);
|
||||
|
||||
|
275
ospfd/ospf_ri.c
275
ospfd/ospf_ri.c
@ -58,9 +58,9 @@
|
||||
#include "ospfd/ospf_ri.h"
|
||||
#include "ospfd/ospf_te.h"
|
||||
|
||||
/* Store Router Information PCE TLV and SubTLV in network byte order. */
|
||||
struct ospf_pce_info {
|
||||
|
||||
/* Store Router Information PCE TLV and SubTLV in network byte order. */
|
||||
bool enabled;
|
||||
struct ri_tlv_pce pce_header;
|
||||
struct ri_pce_subtlv_address pce_address;
|
||||
struct ri_pce_subtlv_path_scope pce_scope;
|
||||
@ -71,15 +71,14 @@ struct ospf_pce_info {
|
||||
|
||||
/* Following structure are internal use only. */
|
||||
struct ospf_router_info {
|
||||
status_t status;
|
||||
bool enabled;
|
||||
|
||||
u_int8_t registered;
|
||||
u_int8_t scope;
|
||||
|
||||
/* Flags to manage this router information. */
|
||||
#define RIFLG_LOOKUP_DONE 0x1
|
||||
#define RIFLG_LSA_ENGAGED 0x2
|
||||
#define RIFLG_LSA_FORCED_REFRESH 0x4
|
||||
#define RIFLG_LSA_ENGAGED 0x1
|
||||
#define RIFLG_LSA_FORCED_REFRESH 0x2
|
||||
u_int32_t flags;
|
||||
|
||||
/* area pointer if flooding is Type 10 Null if flooding is AS scope */
|
||||
@ -112,7 +111,7 @@ static void ospf_router_info_config_write_router(struct vty *vty);
|
||||
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
||||
static int ospf_router_info_lsa_originate(void *arg);
|
||||
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
|
||||
static void ospf_router_info_lsa_schedule(opcode_t opcode);
|
||||
static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode);
|
||||
static void ospf_router_info_register_vty(void);
|
||||
static void del_pce_info(void *val);
|
||||
|
||||
@ -120,12 +119,13 @@ int ospf_router_info_init(void)
|
||||
{
|
||||
|
||||
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
|
||||
OspfRI.status = disabled;
|
||||
OspfRI.enabled = false;
|
||||
OspfRI.registered = 0;
|
||||
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
|
||||
OspfRI.flags = 0;
|
||||
|
||||
/* Initialize pce domain and neighbor list */
|
||||
OspfRI.pce_info.enabled = false;
|
||||
OspfRI.pce_info.pce_domain = list_new();
|
||||
OspfRI.pce_info.pce_domain->del = del_pce_info;
|
||||
OspfRI.pce_info.pce_neighbor = list_new();
|
||||
@ -141,7 +141,7 @@ static int ospf_router_info_register(u_int8_t scope)
|
||||
int rc = 0;
|
||||
|
||||
if (OspfRI.registered)
|
||||
return 0;
|
||||
return rc;
|
||||
|
||||
zlog_info("Register Router Information with scope %s(%d)",
|
||||
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
|
||||
@ -165,7 +165,7 @@ static int ospf_router_info_register(u_int8_t scope)
|
||||
|
||||
OspfRI.registered = 1;
|
||||
OspfRI.scope = scope;
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ospf_router_info_unregister()
|
||||
@ -193,7 +193,7 @@ void ospf_router_info_term(void)
|
||||
|
||||
OspfRI.pce_info.pce_domain = NULL;
|
||||
OspfRI.pce_info.pce_neighbor = NULL;
|
||||
OspfRI.status = disabled;
|
||||
OspfRI.enabled = false;
|
||||
|
||||
ospf_router_info_unregister();
|
||||
|
||||
@ -229,34 +229,36 @@ static int set_pce_header(struct ospf_pce_info *pce)
|
||||
|
||||
/* PCE Address */
|
||||
if (ntohs(pce->pce_address.header.type) != 0)
|
||||
length += RI_TLV_SIZE(&pce->pce_address.header);
|
||||
length += TLV_SIZE(&pce->pce_address.header);
|
||||
|
||||
/* PCE Path Scope */
|
||||
if (ntohs(pce->pce_scope.header.type) != 0)
|
||||
length += RI_TLV_SIZE(&pce->pce_scope.header);
|
||||
length += TLV_SIZE(&pce->pce_scope.header);
|
||||
|
||||
/* PCE Domain */
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
|
||||
if (ntohs(domain->header.type) != 0)
|
||||
length += RI_TLV_SIZE(&domain->header);
|
||||
length += TLV_SIZE(&domain->header);
|
||||
}
|
||||
|
||||
/* PCE Neighbor */
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
|
||||
if (ntohs(neighbor->header.type) != 0)
|
||||
length += RI_TLV_SIZE(&neighbor->header);
|
||||
length += TLV_SIZE(&neighbor->header);
|
||||
}
|
||||
|
||||
/* PCE Capabilities */
|
||||
if (ntohs(pce->pce_cap_flag.header.type) != 0)
|
||||
length += RI_TLV_SIZE(&pce->pce_cap_flag.header);
|
||||
length += TLV_SIZE(&pce->pce_cap_flag.header);
|
||||
|
||||
if (length != 0) {
|
||||
pce->pce_header.header.type = htons(RI_TLV_PCE);
|
||||
pce->pce_header.header.length = htons(length);
|
||||
pce->enabled = true;
|
||||
} else {
|
||||
pce->pce_header.header.type = 0;
|
||||
pce->pce_header.header.length = 0;
|
||||
pce->enabled = false;
|
||||
}
|
||||
|
||||
return length;
|
||||
@ -279,8 +281,6 @@ static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
|
||||
static void set_pce_path_scope(u_int32_t scope, struct ospf_pce_info *pce)
|
||||
{
|
||||
|
||||
/* Enable PCE Info */
|
||||
pce->pce_header.header.type = htons(RI_TLV_PCE);
|
||||
/* Set PCE Scope */
|
||||
pce->pce_scope.header.type = htons(RI_PCE_SUBTLV_PATH_SCOPE);
|
||||
pce->pce_scope.header.length = htons(RI_TLV_LENGTH);
|
||||
@ -295,9 +295,6 @@ static void set_pce_domain(u_int16_t type, u_int32_t domain,
|
||||
|
||||
struct ri_pce_subtlv_domain *new;
|
||||
|
||||
/* Enable PCE Info */
|
||||
pce->pce_header.header.type = htons(RI_TLV_PCE);
|
||||
|
||||
/* Create new domain info */
|
||||
new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
|
||||
sizeof(struct ri_pce_subtlv_domain));
|
||||
@ -348,9 +345,6 @@ static void set_pce_neighbor(u_int16_t type, u_int32_t domain,
|
||||
|
||||
struct ri_pce_subtlv_neighbor *new;
|
||||
|
||||
/* Enable PCE Info */
|
||||
pce->pce_header.header.type = htons(RI_TLV_PCE);
|
||||
|
||||
/* Create new neighbor info */
|
||||
new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
|
||||
sizeof(struct ri_pce_subtlv_neighbor));
|
||||
@ -399,8 +393,6 @@ static void unset_pce_neighbor(u_int16_t type, u_int32_t domain,
|
||||
static void set_pce_cap_flag(u_int32_t cap, struct ospf_pce_info *pce)
|
||||
{
|
||||
|
||||
/* Enable PCE Info */
|
||||
pce->pce_header.header.type = htons(RI_TLV_PCE);
|
||||
/* Set PCE Capabilities flag */
|
||||
pce->pce_cap_flag.header.type = htons(RI_PCE_SUBTLV_CAP_FLAG);
|
||||
pce->pce_cap_flag.header.length = htons(RI_TLV_LENGTH);
|
||||
@ -410,12 +402,12 @@ static void set_pce_cap_flag(u_int32_t cap, struct ospf_pce_info *pce)
|
||||
}
|
||||
|
||||
|
||||
static void unset_param(struct ri_tlv_header *tlv)
|
||||
static void unset_param(struct tlv_header *tlv)
|
||||
{
|
||||
|
||||
tlv->type = 0;
|
||||
/* Fill the Value to 0 */
|
||||
memset((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE(tlv));
|
||||
memset(TLV_DATA(tlv), 0, TLV_BODY_SIZE(tlv));
|
||||
tlv->length = 0;
|
||||
|
||||
return;
|
||||
@ -423,14 +415,13 @@ static void unset_param(struct ri_tlv_header *tlv)
|
||||
|
||||
static void initialize_params(struct ospf_router_info *ori)
|
||||
{
|
||||
u_int32_t cap;
|
||||
u_int32_t cap = 0;
|
||||
struct ospf *top;
|
||||
|
||||
/*
|
||||
* Initialize default Router Information Capabilities.
|
||||
*/
|
||||
cap = 0;
|
||||
cap = cap | RI_TE_SUPPORT;
|
||||
cap = RI_TE_SUPPORT;
|
||||
|
||||
set_router_info_capabilities(&ori->router_cap, cap);
|
||||
|
||||
@ -462,9 +453,6 @@ static void initialize_params(struct ospf_router_info *ori)
|
||||
| PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
|
||||
set_pce_cap_flag(cap, &ori->pce_info);
|
||||
|
||||
/* Finally compute PCE header */
|
||||
set_pce_header(&ori->pce_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -473,16 +461,15 @@ static int is_mandated_params_set(struct ospf_router_info ori)
|
||||
int rc = 0;
|
||||
|
||||
if (ntohs(ori.router_cap.header.type) == 0)
|
||||
goto out;
|
||||
return rc;
|
||||
|
||||
if ((ntohs(ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
|
||||
&& (ntohs(ori.pce_info.pce_address.header.type) == 0)
|
||||
&& (ntohs(ori.pce_info.pce_cap_flag.header.type) == 0))
|
||||
goto out;
|
||||
return rc;
|
||||
|
||||
rc = 1;
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -499,7 +486,6 @@ static void ospf_router_info_ism_change(struct ospf_interface *oi,
|
||||
static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
|
||||
int old_state)
|
||||
{
|
||||
|
||||
/* So far, nothing to do here. */
|
||||
return;
|
||||
}
|
||||
@ -508,19 +494,19 @@ static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
|
||||
* Followings are OSPF protocol processing functions for ROUTER INFORMATION
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
static void build_tlv_header(struct stream *s, struct ri_tlv_header *tlvh)
|
||||
static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
|
||||
{
|
||||
|
||||
stream_put(s, tlvh, sizeof(struct ri_tlv_header));
|
||||
stream_put(s, tlvh, sizeof(struct tlv_header));
|
||||
return;
|
||||
}
|
||||
|
||||
static void build_tlv(struct stream *s, struct ri_tlv_header *tlvh)
|
||||
static void build_tlv(struct stream *s, struct tlv_header *tlvh)
|
||||
{
|
||||
|
||||
if (ntohs(tlvh->type) != 0) {
|
||||
build_tlv_header(s, tlvh);
|
||||
stream_put(s, tlvh + 1, RI_TLV_BODY_SIZE(tlvh));
|
||||
stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -535,9 +521,11 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
|
||||
/* Build Router Information TLV */
|
||||
build_tlv(s, &OspfRI.router_cap.header);
|
||||
|
||||
/* Add RI PCE TLV if it is set */
|
||||
/* Compute PCE Info header first */
|
||||
if ((set_pce_header(&OspfRI.pce_info)) != 0) {
|
||||
set_pce_header (&OspfRI.pce_info);
|
||||
|
||||
/* Add RI PCE TLV if it is set */
|
||||
if (OspfRI.pce_info.enabled) {
|
||||
|
||||
/* Build PCE TLV */
|
||||
build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
|
||||
@ -580,7 +568,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
|
||||
/* Create a stream for LSA. */
|
||||
if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_new: stream_new() ?");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
lsah = (struct lsa_header *)STREAM_DATA(s);
|
||||
|
||||
@ -614,14 +602,14 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
|
||||
stream_free(s);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
goto out;
|
||||
return new;
|
||||
}
|
||||
|
||||
new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
|
||||
@ -631,7 +619,6 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
out:
|
||||
return new;
|
||||
}
|
||||
|
||||
@ -648,7 +635,7 @@ static int ospf_router_info_lsa_originate1(void *arg)
|
||||
if (area->area_id.s_addr != OspfRI.area_id.s_addr) {
|
||||
zlog_debug(
|
||||
"RI -> This is not the Router Information Area. Stop processing");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
OspfRI.area = area;
|
||||
}
|
||||
@ -657,7 +644,7 @@ static int ospf_router_info_lsa_originate1(void *arg)
|
||||
if ((new = ospf_router_info_lsa_new()) == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Get ospf info */
|
||||
@ -668,7 +655,7 @@ static int ospf_router_info_lsa_originate1(void *arg)
|
||||
zlog_warn(
|
||||
"ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Now this Router Info parameter entry has associated LSA. */
|
||||
@ -691,7 +678,6 @@ static int ospf_router_info_lsa_originate1(void *arg)
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -700,17 +686,17 @@ static int ospf_router_info_lsa_originate(void *arg)
|
||||
|
||||
int rc = -1;
|
||||
|
||||
if (OspfRI.status == disabled) {
|
||||
if (!OspfRI.enabled) {
|
||||
zlog_info(
|
||||
"ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
|
||||
rc = 0; /* This is not an error case. */
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Check if Router Information LSA is already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED) {
|
||||
if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH) {
|
||||
OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH;
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) {
|
||||
UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH);
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
}
|
||||
} else {
|
||||
@ -720,11 +706,10 @@ static int ospf_router_info_lsa_originate(void *arg)
|
||||
|
||||
/* Ok, let's try to originate an LSA */
|
||||
if (ospf_router_info_lsa_originate1(arg) != 0)
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -733,7 +718,7 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
|
||||
struct ospf_lsa *new = NULL;
|
||||
struct ospf *top;
|
||||
|
||||
if (OspfRI.status == disabled) {
|
||||
if (!OspfRI.enabled) {
|
||||
/*
|
||||
* This LSA must have flushed before due to ROUTER INFORMATION
|
||||
* status change.
|
||||
@ -749,21 +734,21 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
|
||||
if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
|
||||
zlog_warn(
|
||||
"ospf_router_info_lsa_refresh: Unsupported Router Information ID");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the lsa's age reached to MaxAge, start flushing procedure. */
|
||||
if (IS_LSA_MAXAGE(lsa)) {
|
||||
OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
|
||||
UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
|
||||
ospf_opaque_lsa_flush_schedule(lsa);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create new Opaque-LSA/ROUTER INFORMATION instance. */
|
||||
if ((new = ospf_router_info_lsa_new()) == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
|
||||
|
||||
@ -773,7 +758,7 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
|
||||
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
goto out;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
|
||||
@ -790,11 +775,10 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
|
||||
ospf_lsa_header_dump(new->data);
|
||||
}
|
||||
|
||||
out:
|
||||
return new;
|
||||
}
|
||||
|
||||
static void ospf_router_info_lsa_schedule(opcode_t opcode)
|
||||
static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
|
||||
{
|
||||
struct ospf_lsa lsa;
|
||||
struct lsa_header lsah;
|
||||
@ -809,6 +793,13 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
|
||||
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
|
||||
opcode == FLUSH_THIS_LSA ? "Flush" : "");
|
||||
|
||||
/* Check LSA flags state coherence */
|
||||
if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) && (opcode != REORIGINATE_THIS_LSA))
|
||||
return;
|
||||
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) && (opcode == REORIGINATE_THIS_LSA))
|
||||
opcode = REFRESH_THIS_LSA;
|
||||
|
||||
top = ospf_lookup();
|
||||
if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) {
|
||||
zlog_warn(
|
||||
@ -838,7 +829,7 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
|
||||
ospf_opaque_lsa_refresh_schedule(&lsa);
|
||||
break;
|
||||
case FLUSH_THIS_LSA:
|
||||
OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
|
||||
UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
|
||||
ospf_opaque_lsa_flush_schedule(&lsa);
|
||||
break;
|
||||
default:
|
||||
@ -855,7 +846,7 @@ static void ospf_router_info_lsa_schedule(opcode_t opcode)
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
static u_int16_t show_vty_router_cap(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
|
||||
|
||||
@ -865,11 +856,11 @@ static u_int16_t show_vty_router_cap(struct vty *vty,
|
||||
else
|
||||
zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
|
||||
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_subtlv_address(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_pce_subtlv_address *top =
|
||||
(struct ri_pce_subtlv_address *)tlvh;
|
||||
@ -891,11 +882,11 @@ static u_int16_t show_vty_pce_subtlv_address(struct vty *vty,
|
||||
ntohl(top->address.value.s_addr));
|
||||
}
|
||||
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_pce_subtlv_path_scope *top =
|
||||
(struct ri_pce_subtlv_path_scope *)tlvh;
|
||||
@ -905,11 +896,11 @@ static u_int16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
|
||||
else
|
||||
zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
|
||||
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_subtlv_domain(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
|
||||
struct in_addr tmp;
|
||||
@ -927,11 +918,11 @@ static u_int16_t show_vty_pce_subtlv_domain(struct vty *vty,
|
||||
else
|
||||
zlog_debug(" PCE domain AS: %d", ntohl(top->value));
|
||||
}
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
|
||||
struct ri_pce_subtlv_neighbor *top =
|
||||
@ -953,11 +944,11 @@ static u_int16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
|
||||
zlog_debug(" PCE neighbor AS: %d",
|
||||
ntohl(top->value));
|
||||
}
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_pce_subtlv_cap_flag *top =
|
||||
(struct ri_pce_subtlv_cap_flag *)tlvh;
|
||||
@ -969,11 +960,11 @@ static u_int16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
|
||||
zlog_debug(" PCE Capabilities Flag: 0x%x",
|
||||
ntohl(top->value));
|
||||
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_unknown_tlv(struct vty *vty,
|
||||
struct ri_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
if (vty != NULL)
|
||||
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
|
||||
@ -982,16 +973,16 @@ static u_int16_t show_vty_unknown_tlv(struct vty *vty,
|
||||
zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
|
||||
ntohs(tlvh->type), ntohs(tlvh->length));
|
||||
|
||||
return RI_TLV_SIZE(tlvh);
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_pce_info(struct vty *vty, struct ri_tlv_header *ri,
|
||||
static u_int16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
|
||||
uint32_t total)
|
||||
{
|
||||
struct ri_tlv_header *tlvh;
|
||||
struct tlv_header *tlvh;
|
||||
u_int16_t sum = 0;
|
||||
|
||||
for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT(tlvh)) {
|
||||
for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
|
||||
switch (ntohs(tlvh->type)) {
|
||||
case RI_PCE_SUBTLV_ADDRESS:
|
||||
sum += show_vty_pce_subtlv_address(vty, tlvh);
|
||||
@ -1019,21 +1010,21 @@ static u_int16_t show_vty_pce_info(struct vty *vty, struct ri_tlv_header *ri,
|
||||
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
{
|
||||
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
|
||||
struct ri_tlv_header *tlvh;
|
||||
struct tlv_header *tlvh;
|
||||
u_int16_t length = 0, sum = 0;
|
||||
|
||||
/* Initialize TLV browsing */
|
||||
length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
|
||||
|
||||
for (tlvh = RI_TLV_HDR_TOP(lsah); sum < length;
|
||||
tlvh = RI_TLV_HDR_NEXT(tlvh)) {
|
||||
for (tlvh = TLV_HDR_TOP(lsah); sum < length;
|
||||
tlvh = TLV_HDR_NEXT(tlvh)) {
|
||||
switch (ntohs(tlvh->type)) {
|
||||
case RI_TLV_CAPABILITIES:
|
||||
sum += show_vty_router_cap(vty, tlvh);
|
||||
break;
|
||||
case RI_TLV_PCE:
|
||||
tlvh++;
|
||||
sum += RI_TLV_HDR_SIZE;
|
||||
sum += TLV_HDR_SIZE;
|
||||
sum += show_vty_pce_info(vty, tlvh, length - sum);
|
||||
break;
|
||||
default:
|
||||
@ -1053,50 +1044,53 @@ static void ospf_router_info_config_write_router(struct vty *vty)
|
||||
struct ri_pce_subtlv_neighbor *neighbor;
|
||||
struct in_addr tmp;
|
||||
|
||||
if (OspfRI.status == enabled) {
|
||||
if (OspfRI.enabled) {
|
||||
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
|
||||
vty_out(vty, " router-info as\n");
|
||||
else
|
||||
vty_out(vty, " router-info area %s\n",
|
||||
inet_ntoa(OspfRI.area_id));
|
||||
|
||||
if (pce->pce_address.header.type != 0)
|
||||
vty_out(vty, " pce address %s\n",
|
||||
inet_ntoa(pce->pce_address.address.value));
|
||||
if (OspfRI.pce_info.enabled) {
|
||||
|
||||
if (pce->pce_cap_flag.header.type != 0)
|
||||
vty_out(vty, " pce flag 0x%x\n",
|
||||
ntohl(pce->pce_cap_flag.value));
|
||||
if (pce->pce_address.header.type != 0)
|
||||
vty_out(vty, " pce address %s\n",
|
||||
inet_ntoa(pce->pce_address.address.value));
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
|
||||
if (domain->header.type != 0) {
|
||||
if (domain->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = domain->value;
|
||||
vty_out(vty, " pce domain area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce domain as %d\n",
|
||||
ntohl(domain->value));
|
||||
if (pce->pce_cap_flag.header.type != 0)
|
||||
vty_out(vty, " pce flag 0x%x\n",
|
||||
ntohl(pce->pce_cap_flag.value));
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
|
||||
if (domain->header.type != 0) {
|
||||
if (domain->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = domain->value;
|
||||
vty_out(vty, " pce domain area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce domain as %d\n",
|
||||
ntohl(domain->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
|
||||
if (neighbor->header.type != 0) {
|
||||
if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = neighbor->value;
|
||||
vty_out(vty, " pce neighbor area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce neighbor as %d\n",
|
||||
ntohl(neighbor->value));
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
|
||||
if (neighbor->header.type != 0) {
|
||||
if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = neighbor->value;
|
||||
vty_out(vty, " pce neighbor area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce neighbor as %d\n",
|
||||
ntohl(neighbor->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pce->pce_scope.header.type != 0)
|
||||
vty_out(vty, " pce scope 0x%x\n",
|
||||
ntohl(OspfRI.pce_info.pce_scope.value));
|
||||
if (pce->pce_scope.header.type != 0)
|
||||
vty_out(vty, " pce scope 0x%x\n",
|
||||
ntohl(OspfRI.pce_info.pce_scope.value));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1118,7 +1112,7 @@ DEFUN (router_info,
|
||||
|
||||
u_int8_t scope;
|
||||
|
||||
if (OspfRI.status == enabled)
|
||||
if (OspfRI.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
/* Check and get Area value if present */
|
||||
@ -1137,11 +1131,11 @@ DEFUN (router_info,
|
||||
/* First start to register Router Information callbacks */
|
||||
if ((ospf_router_info_register(scope)) != 0) {
|
||||
zlog_warn(
|
||||
"Enable to register Router Information callbacks. Abort!");
|
||||
"Unable to register Router Information callbacks. Abort!");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
OspfRI.status = enabled;
|
||||
OspfRI.enabled = true;
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
|
||||
@ -1160,7 +1154,10 @@ DEFUN (router_info,
|
||||
initialize_params(&OspfRI);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED) {
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
|
||||
zlog_debug ("RI-> Refresh LSA following configuration");
|
||||
ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
|
||||
} else {
|
||||
zlog_debug("RI-> Initial origination following configuration");
|
||||
ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
|
||||
}
|
||||
@ -1175,26 +1172,26 @@ DEFUN (no_router_info,
|
||||
"Disable the Router Information functionality\n")
|
||||
{
|
||||
|
||||
if (OspfRI.status == disabled)
|
||||
if (!OspfRI.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("RI-> Router Information: ON -> OFF");
|
||||
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(FLUSH_THIS_LSA);
|
||||
|
||||
/* Unregister the callbacks */
|
||||
ospf_router_info_unregister();
|
||||
|
||||
OspfRI.status = disabled;
|
||||
OspfRI.enabled = false;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int ospf_ri_enabled(struct vty *vty)
|
||||
{
|
||||
if (OspfRI.status == enabled)
|
||||
if (OspfRI.enabled)
|
||||
return 1;
|
||||
|
||||
if (vty)
|
||||
@ -1229,7 +1226,7 @@ DEFUN (pce_address,
|
||||
set_pce_address(value, pi);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
}
|
||||
|
||||
@ -1248,7 +1245,7 @@ DEFUN (no_pce_address,
|
||||
unset_param(&OspfRI.pce_info.pce_address.header);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1279,7 +1276,7 @@ DEFUN (pce_path_scope,
|
||||
set_pce_path_scope(scope, pi);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
}
|
||||
|
||||
@ -1298,7 +1295,7 @@ DEFUN (no_pce_path_scope,
|
||||
unset_param(&OspfRI.pce_info.pce_address.header);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1337,7 +1334,7 @@ DEFUN (pce_domain,
|
||||
set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1367,7 +1364,7 @@ DEFUN (no_pce_domain,
|
||||
unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1407,7 +1404,7 @@ DEFUN (pce_neigbhor,
|
||||
set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1437,7 +1434,7 @@ DEFUN (no_pce_neighbor,
|
||||
unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1469,7 +1466,7 @@ DEFUN (pce_cap_flag,
|
||||
set_pce_cap_flag(cap, pce);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if (OspfRI.flags & RIFLG_LSA_ENGAGED)
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
}
|
||||
|
||||
@ -1487,7 +1484,7 @@ DEFUN (no_pce_cap_flag,
|
||||
unset_param(&OspfRI.pce_info.pce_cap_flag.header);
|
||||
|
||||
/* Refresh RI LSA if already engaged */
|
||||
if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1502,7 +1499,7 @@ DEFUN (show_ip_ospf_router_info,
|
||||
"Router Information\n")
|
||||
{
|
||||
|
||||
if (OspfRI.status == enabled) {
|
||||
if (OspfRI.enabled) {
|
||||
vty_out(vty, "--- Router Information parameters ---\n");
|
||||
show_vty_router_cap(vty, &OspfRI.router_cap.header);
|
||||
} else {
|
||||
@ -1528,7 +1525,7 @@ DEFUN (show_ip_opsf_router_info_pce,
|
||||
struct ri_pce_subtlv_domain *domain;
|
||||
struct ri_pce_subtlv_neighbor *neighbor;
|
||||
|
||||
if (OspfRI.status == enabled) {
|
||||
if (OspfRI.enabled) {
|
||||
vty_out(vty, "--- PCE parameters ---\n");
|
||||
|
||||
if (pce->pce_address.header.type != 0)
|
||||
|
@ -64,21 +64,6 @@
|
||||
* +--------+--------+--------+--------+ ---
|
||||
*/
|
||||
|
||||
/*
|
||||
* Following section defines TLV (tag, length, value) structures,
|
||||
* used for Router Information.
|
||||
*/
|
||||
struct ri_tlv_header {
|
||||
u_int16_t type; /* RI_TLV_XXX (see below) */
|
||||
u_int16_t length; /* Value portion only, in byte */
|
||||
};
|
||||
|
||||
#define RI_TLV_HDR_SIZE (sizeof (struct ri_tlv_header))
|
||||
#define RI_TLV_BODY_SIZE(tlvh) (ROUNDUP (ntohs ((tlvh)->length), sizeof (u_int32_t)))
|
||||
#define RI_TLV_SIZE(tlvh) (RI_TLV_HDR_SIZE + RI_TLV_BODY_SIZE(tlvh))
|
||||
#define RI_TLV_HDR_TOP(lsah) (struct ri_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
|
||||
#define RI_TLV_HDR_NEXT(tlvh) (struct ri_tlv_header *)((char *)(tlvh) + RI_TLV_SIZE(tlvh))
|
||||
|
||||
/*
|
||||
* Following section defines TLV body parts.
|
||||
*/
|
||||
@ -91,7 +76,7 @@ struct ri_tlv_header {
|
||||
#define RI_TLV_CAPABILITIES 1
|
||||
|
||||
struct ri_tlv_router_cap {
|
||||
struct ri_tlv_header header; /* Value length is 4 bytes. */
|
||||
struct tlv_header header; /* Value length is 4 bytes. */
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
@ -109,23 +94,19 @@ struct ri_tlv_router_cap {
|
||||
#define RI_TLV_PCE 6
|
||||
|
||||
struct ri_tlv_pce {
|
||||
struct ri_tlv_header header;
|
||||
struct tlv_header header;
|
||||
/* A set of PCE-sub-TLVs will follow. */
|
||||
};
|
||||
|
||||
/* PCE Address Sub-TLV */ /* Mandatory */
|
||||
#define RI_PCE_SUBTLV_ADDRESS 1
|
||||
struct ri_pce_subtlv_address {
|
||||
struct ri_tlv_header
|
||||
header; /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
|
||||
/* $FRR indent$ */
|
||||
/* clang-format off */
|
||||
/* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
|
||||
struct tlv_header header;
|
||||
#define PCE_ADDRESS_LENGTH_IPV4 8
|
||||
#define PCE_ADDRESS_LENGTH_IPV6 20
|
||||
struct {
|
||||
u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */
|
||||
/* $FRR indent$ */
|
||||
/* clang-format off */
|
||||
#define PCE_ADDRESS_TYPE_IPV4 1
|
||||
#define PCE_ADDRESS_TYPE_IPV6 2
|
||||
u_int16_t reserved;
|
||||
@ -136,9 +117,12 @@ struct ri_pce_subtlv_address {
|
||||
/* PCE Path-Scope Sub-TLV */ /* Mandatory */
|
||||
#define RI_PCE_SUBTLV_PATH_SCOPE 2
|
||||
struct ri_pce_subtlv_path_scope {
|
||||
struct ri_tlv_header header; /* Type = 2; Length = 4 bytes. */
|
||||
u_int32_t value; /* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY
|
||||
bits see RFC5088 page 9 */
|
||||
struct tlv_header header; /* Type = 2; Length = 4 bytes. */
|
||||
/*
|
||||
* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY bits:
|
||||
* see RFC5088 page 9
|
||||
*/
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* PCE Domain Sub-TLV */ /* Optional */
|
||||
@ -148,7 +132,7 @@ struct ri_pce_subtlv_path_scope {
|
||||
#define PCE_DOMAIN_TYPE_AS 2
|
||||
|
||||
struct ri_pce_subtlv_domain {
|
||||
struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */
|
||||
struct tlv_header header; /* Type = 3; Length = 8 bytes. */
|
||||
u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
|
||||
u_int16_t reserved;
|
||||
u_int32_t value;
|
||||
@ -157,7 +141,7 @@ struct ri_pce_subtlv_domain {
|
||||
/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */
|
||||
#define RI_PCE_SUBTLV_NEIGHBOR 4
|
||||
struct ri_pce_subtlv_neighbor {
|
||||
struct ri_tlv_header header; /* Type = 4; Length = 8 bytes. */
|
||||
struct tlv_header header; /* Type = 4; Length = 8 bytes. */
|
||||
u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
|
||||
u_int16_t reserved;
|
||||
u_int32_t value;
|
||||
@ -177,7 +161,7 @@ struct ri_pce_subtlv_neighbor {
|
||||
#define PCE_CAP_MULTIPLE_REQ 0x0100
|
||||
|
||||
struct ri_pce_subtlv_cap_flag {
|
||||
struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */
|
||||
struct tlv_header header; /* Type = 5; Length = n x 4 bytes. */
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
|
337
ospfd/ospf_te.c
337
ospfd/ospf_te.c
@ -68,9 +68,7 @@
|
||||
*/
|
||||
struct ospf_mpls_te OspfMplsTE;
|
||||
|
||||
const char *mode2text[] = {"Disable", "AS", "Area", "Emulate"};
|
||||
|
||||
enum oifstate { OI_ANY, OI_DOWN, OI_UP };
|
||||
const char *mode2text[] = {"Off", "AS", "Area"};
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* Followings are initialize/terminate functions for MPLS-TE handling.
|
||||
@ -106,29 +104,28 @@ int ospf_mpls_te_init(void)
|
||||
if (rc != 0) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_init: Failed to register Traffic Engineering functions");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
memset(&OspfMplsTE, 0, sizeof(struct ospf_mpls_te));
|
||||
OspfMplsTE.status = disabled;
|
||||
OspfMplsTE.inter_as = Disable;
|
||||
OspfMplsTE.enabled = false;
|
||||
OspfMplsTE.inter_as = Off;
|
||||
OspfMplsTE.iflist = list_new();
|
||||
OspfMplsTE.iflist->del = del_mpls_te_link;
|
||||
|
||||
ospf_mpls_te_register_vty();
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Additional register for RFC5392 support */
|
||||
static int ospf_mpls_te_register(enum inter_as_mode mode)
|
||||
{
|
||||
int rc;
|
||||
int rc = 0;
|
||||
u_int8_t scope;
|
||||
|
||||
if (OspfMplsTE.inter_as != Disable)
|
||||
return 0;
|
||||
if (OspfMplsTE.inter_as != Off)
|
||||
return rc;
|
||||
|
||||
if (mode == AS)
|
||||
scope = OSPF_OPAQUE_AS_LSA;
|
||||
@ -147,14 +144,14 @@ static int ospf_mpls_te_register(enum inter_as_mode mode)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ospf_mpls_te_unregister()
|
||||
{
|
||||
u_int8_t scope;
|
||||
|
||||
if (OspfMplsTE.inter_as == Disable)
|
||||
if (OspfMplsTE.inter_as == Off)
|
||||
return 0;
|
||||
|
||||
if (OspfMplsTE.inter_as == AS)
|
||||
@ -174,10 +171,10 @@ void ospf_mpls_te_term(void)
|
||||
|
||||
ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
|
||||
OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
|
||||
OspfMplsTE.status = disabled;
|
||||
OspfMplsTE.enabled = false;
|
||||
|
||||
ospf_mpls_te_unregister();
|
||||
OspfMplsTE.inter_as = Disable;
|
||||
OspfMplsTE.inter_as = Off;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -192,7 +189,7 @@ static void del_mpls_te_link(void *val)
|
||||
return;
|
||||
}
|
||||
|
||||
u_int32_t get_mpls_te_instance_value(void)
|
||||
static u_int32_t get_mpls_te_instance_value(void)
|
||||
{
|
||||
static u_int32_t seqno = 0;
|
||||
|
||||
@ -204,41 +201,6 @@ u_int32_t get_mpls_te_instance_value(void)
|
||||
return seqno;
|
||||
}
|
||||
|
||||
static struct ospf_interface *lookup_oi_by_ifp(struct interface *ifp,
|
||||
struct ospf_area *area,
|
||||
enum oifstate oifstate)
|
||||
{
|
||||
struct ospf_interface *oi = NULL;
|
||||
struct route_node *rn;
|
||||
|
||||
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
|
||||
if ((oi = rn->info) == NULL)
|
||||
continue;
|
||||
|
||||
switch (oifstate) {
|
||||
case OI_ANY:
|
||||
break;
|
||||
case OI_DOWN:
|
||||
if (ospf_if_is_enable(oi))
|
||||
continue;
|
||||
break;
|
||||
case OI_UP:
|
||||
if (!ospf_if_is_enable(oi))
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
zlog_warn("lookup_oi_by_ifp: Unknown oifstate: %x",
|
||||
oifstate);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (area == NULL || oi->area == area)
|
||||
return oi;
|
||||
}
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
@ -267,8 +229,8 @@ static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
|
||||
}
|
||||
|
||||
static void ospf_mpls_te_foreach_area(void (*func)(struct mpls_te_link *lp,
|
||||
opcode_t sched_opcode),
|
||||
opcode_t sched_opcode)
|
||||
enum lsa_opcode sched_opcode),
|
||||
enum lsa_opcode sched_opcode)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct listnode *node2;
|
||||
@ -281,8 +243,8 @@ static void ospf_mpls_te_foreach_area(void (*func)(struct mpls_te_link *lp,
|
||||
continue;
|
||||
if ((area = lp->area) == NULL)
|
||||
continue;
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE) continue;
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
|
||||
continue;
|
||||
|
||||
if (func != NULL)
|
||||
(*func)(lp, sched_opcode);
|
||||
@ -793,14 +755,25 @@ static void update_linkparams(struct mpls_te_link *lp)
|
||||
static void initialize_linkparams(struct mpls_te_link *lp)
|
||||
{
|
||||
struct interface *ifp = lp->ifp;
|
||||
struct ospf_interface *oi;
|
||||
struct ospf_interface *oi = NULL;
|
||||
struct route_node *rn;
|
||||
|
||||
if (IS_DEBUG_OSPF_TE)
|
||||
zlog_debug(
|
||||
"MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
|
||||
ifp->name);
|
||||
|
||||
if ((oi = lookup_oi_by_ifp(ifp, NULL, OI_ANY)) == NULL) {
|
||||
/* Search OSPF Interface parameters for this interface */
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) {
|
||||
|
||||
if ((oi = rn->info) == NULL)
|
||||
continue;
|
||||
|
||||
if (oi->ifp == ifp)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((oi == NULL) || (oi->ifp != ifp)) {
|
||||
if (IS_DEBUG_OSPF_TE)
|
||||
zlog_warn(
|
||||
"MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
|
||||
@ -818,7 +791,7 @@ static void initialize_linkparams(struct mpls_te_link *lp)
|
||||
set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
|
||||
|
||||
/* Set Remote IP addr if Point to Point Interface */
|
||||
if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) {
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
|
||||
struct prefix *pref = CONNECTED_PREFIX(oi->connected);
|
||||
if (pref != NULL)
|
||||
set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
|
||||
@ -837,21 +810,20 @@ static int is_mandated_params_set(struct mpls_te_link *lp)
|
||||
if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
|
||||
zlog_warn(
|
||||
"MPLS-TE(is_mandated_params_set) Missing Router Address");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ntohs(lp->link_type.header.type) == 0) {
|
||||
zlog_warn("MPLS-TE(is_mandated_params_set) Missing Link Type");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) {
|
||||
zlog_warn("MPLS-TE(is_mandated_params_set) Missing Link ID");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -873,14 +845,14 @@ static int ospf_mpls_te_new_if(struct interface *ifp)
|
||||
zlog_warn("ospf_mpls_te_new_if: ifp(%p) already in use?",
|
||||
(void *)ifp);
|
||||
rc = 0; /* Do nothing here. */
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link));
|
||||
if (new == NULL) {
|
||||
zlog_warn("ospf_mpls_te_new_if: XMALLOC: %s",
|
||||
safe_strerror(errno));
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
new->instance = get_mpls_te_instance_value();
|
||||
@ -909,7 +881,6 @@ static int ospf_mpls_te_new_if(struct interface *ifp)
|
||||
/* Schedule Opaque-LSA refresh. */ /* XXX */
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -934,7 +905,6 @@ static int ospf_mpls_te_del_if(struct interface *ifp)
|
||||
/* Schedule Opaque-LSA refresh. */ /* XXX */
|
||||
|
||||
rc = 0;
|
||||
/*out:*/
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -952,10 +922,9 @@ void ospf_mpls_te_update_if(struct interface *ifp)
|
||||
|
||||
/* Get Link context from interface */
|
||||
if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
|
||||
if (IS_DEBUG_OSPF_TE)
|
||||
zlog_warn(
|
||||
"OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
|
||||
ifp->name);
|
||||
zlog_warn(
|
||||
"OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
|
||||
ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -968,20 +937,18 @@ void ospf_mpls_te_update_if(struct interface *ifp)
|
||||
|
||||
/* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
|
||||
* enabled */
|
||||
if (OspfMplsTE.status == enabled)
|
||||
if (OspfMplsTE.enabled)
|
||||
if (lp->area != NULL) {
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
else ospf_mpls_te_lsa_schedule(
|
||||
lp, REORIGINATE_THIS_LSA);
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
else
|
||||
ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
|
||||
}
|
||||
} else {
|
||||
/* If MPLS TE is disable on this interface, flush LSA if it is
|
||||
* already engaged */
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
else
|
||||
/* Reset Activity flag */
|
||||
lp->flags = LPFLG_LSA_INACTIVE;
|
||||
@ -1000,14 +967,14 @@ static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?",
|
||||
IF_NAME(oi));
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
if (oi->area == NULL || oi->area->ospf == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
|
||||
IF_NAME(oi));
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
#ifdef notyet
|
||||
if ((lp->area != NULL
|
||||
@ -1059,24 +1026,21 @@ static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
|
||||
!= ntohs(lp->link_id.header.type)
|
||||
|| ntohl(old_id.value.s_addr)
|
||||
!= ntohl(lp->link_id.value.s_addr))) {
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
else ospf_mpls_te_lsa_schedule(lp,
|
||||
REORIGINATE_THIS_LSA);
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
else
|
||||
ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lp->link_type.header.type = htons(0);
|
||||
lp->link_id.header.type = htons(0);
|
||||
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1090,28 +1054,28 @@ static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
|
||||
* Followings are OSPF protocol processing functions for MPLS-TE.
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
static void build_tlv_header(struct stream *s, struct te_tlv_header *tlvh)
|
||||
static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
|
||||
{
|
||||
stream_put(s, tlvh, sizeof(struct te_tlv_header));
|
||||
stream_put(s, tlvh, sizeof(struct tlv_header));
|
||||
return;
|
||||
}
|
||||
|
||||
static void build_router_tlv(struct stream *s)
|
||||
{
|
||||
struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
|
||||
struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
|
||||
if (ntohs(tlvh->type) != 0) {
|
||||
build_tlv_header(s, tlvh);
|
||||
stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh));
|
||||
stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void build_link_subtlv(struct stream *s, struct te_tlv_header *tlvh)
|
||||
static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
|
||||
{
|
||||
|
||||
if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
|
||||
build_tlv_header(s, tlvh);
|
||||
stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh));
|
||||
stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1177,7 +1141,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
|
||||
/* Create a stream for LSA. */
|
||||
if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_new: stream_new() ?");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
lsah = (struct lsa_header *)STREAM_DATA(s);
|
||||
|
||||
@ -1233,14 +1197,14 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
|
||||
stream_free(s);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
goto out;
|
||||
return new;
|
||||
}
|
||||
|
||||
new->area = area;
|
||||
@ -1248,7 +1212,6 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area,
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
out:
|
||||
return new;
|
||||
}
|
||||
|
||||
@ -1262,14 +1225,14 @@ static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
|
||||
if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Install this LSA into LSDB. */
|
||||
if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Now this link-parameter entry has associated LSA. */
|
||||
@ -1291,7 +1254,6 @@ static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1302,11 +1264,11 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
|
||||
struct mpls_te_link *lp;
|
||||
int rc = -1;
|
||||
|
||||
if (OspfMplsTE.status == disabled) {
|
||||
if (!OspfMplsTE.enabled) {
|
||||
zlog_info(
|
||||
"ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
|
||||
rc = 0; /* This is not an error case. */
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
|
||||
@ -1321,23 +1283,16 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
|
||||
if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
|
||||
continue;
|
||||
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
{
|
||||
if
|
||||
CHECK_FLAG(lp->flags,
|
||||
LPFLG_LSA_FORCED_REFRESH)
|
||||
{
|
||||
UNSET_FLAG(
|
||||
lp->flags,
|
||||
LPFLG_LSA_FORCED_REFRESH);
|
||||
zlog_warn(
|
||||
"OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
|
||||
ospf_mpls_te_lsa_schedule(
|
||||
lp, REFRESH_THIS_LSA);
|
||||
}
|
||||
continue;
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
|
||||
UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
|
||||
zlog_warn(
|
||||
"OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_mandated_params_set(lp)) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
|
||||
@ -1352,11 +1307,10 @@ static int ospf_mpls_te_lsa_originate_area(void *arg)
|
||||
lp->instance, inet_ntoa(area->area_id),
|
||||
lp->ifp ? lp->ifp->name : "?");
|
||||
if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1370,14 +1324,14 @@ static int ospf_mpls_te_lsa_originate2(struct ospf *top,
|
||||
if ((new = ospf_mpls_te_lsa_new(NULL, lp)) == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Install this LSA into LSDB. */
|
||||
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Now this Router Info parameter entry has associated LSA. */
|
||||
@ -1396,7 +1350,6 @@ static int ospf_mpls_te_lsa_originate2(struct ospf *top,
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1408,12 +1361,12 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
|
||||
struct mpls_te_link *lp;
|
||||
int rc = -1;
|
||||
|
||||
if ((OspfMplsTE.status == disabled)
|
||||
|| (OspfMplsTE.inter_as == Disable)) {
|
||||
if ((!OspfMplsTE.enabled)
|
||||
|| (OspfMplsTE.inter_as == Off)) {
|
||||
zlog_info(
|
||||
"ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now.");
|
||||
rc = 0; /* This is not an error case. */
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
|
||||
@ -1422,21 +1375,14 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
|
||||
|| !IS_INTER_AS(lp->type))
|
||||
continue;
|
||||
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
{
|
||||
if
|
||||
CHECK_FLAG(lp->flags,
|
||||
LPFLG_LSA_FORCED_REFRESH)
|
||||
{
|
||||
UNSET_FLAG(
|
||||
lp->flags,
|
||||
LPFLG_LSA_FORCED_REFRESH);
|
||||
ospf_mpls_te_lsa_schedule(
|
||||
lp, REFRESH_THIS_LSA);
|
||||
}
|
||||
continue;
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
|
||||
UNSET_FLAG(lp->flags,LPFLG_LSA_FORCED_REFRESH);
|
||||
ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_mandated_params_set(lp)) {
|
||||
zlog_warn(
|
||||
"ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.",
|
||||
@ -1462,7 +1408,6 @@ static int ospf_mpls_te_lsa_originate_as(void *arg)
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1473,7 +1418,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
|
||||
struct ospf *top;
|
||||
struct ospf_lsa *new = NULL;
|
||||
|
||||
if (OspfMplsTE.status == disabled) {
|
||||
if (!OspfMplsTE.enabled) {
|
||||
/*
|
||||
* This LSA must have flushed before due to MPLS-TE status
|
||||
* change.
|
||||
@ -1504,13 +1449,13 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
|
||||
if (lp)
|
||||
UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
|
||||
ospf_opaque_lsa_flush_schedule(lsa);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create new Opaque-LSA/MPLS-TE instance. */
|
||||
if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
|
||||
|
||||
@ -1526,7 +1471,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
|
||||
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
|
||||
zlog_warn("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Flood updated LSA through AS or Area depending of the RFC of the link
|
||||
@ -1543,11 +1488,10 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
|
||||
ospf_lsa_header_dump(new->data);
|
||||
}
|
||||
|
||||
out:
|
||||
return new;
|
||||
}
|
||||
|
||||
void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, opcode_t opcode)
|
||||
void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
|
||||
{
|
||||
struct ospf_lsa lsa;
|
||||
struct lsa_header lsah;
|
||||
@ -1636,7 +1580,7 @@ void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, opcode_t opcode)
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
static u_int16_t show_vty_router_addr(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
|
||||
|
||||
@ -1649,7 +1593,7 @@ static u_int16_t show_vty_router_addr(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_header(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
|
||||
|
||||
@ -1664,7 +1608,7 @@ static u_int16_t show_vty_link_header(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_link_type(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_link_type *top;
|
||||
const char *cp = "Unknown";
|
||||
@ -1691,7 +1635,7 @@ static u_int16_t show_vty_link_subtlv_link_type(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_link_id(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_link_id *top;
|
||||
|
||||
@ -1705,7 +1649,7 @@ static u_int16_t show_vty_link_subtlv_link_id(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_lclif_ipaddr *top;
|
||||
int i, n;
|
||||
@ -1730,7 +1674,7 @@ static u_int16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_rmtif_ipaddr *top;
|
||||
int i, n;
|
||||
@ -1754,7 +1698,7 @@ static u_int16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_te_metric(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_te_metric *top;
|
||||
|
||||
@ -1770,7 +1714,7 @@ static u_int16_t show_vty_link_subtlv_te_metric(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_max_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_max_bw *top;
|
||||
float fval;
|
||||
@ -1787,7 +1731,7 @@ static u_int16_t show_vty_link_subtlv_max_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_max_rsv_bw *top;
|
||||
float fval;
|
||||
@ -1806,7 +1750,7 @@ static u_int16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_unrsv_bw *top;
|
||||
float fval1, fval2;
|
||||
@ -1837,7 +1781,7 @@ static u_int16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_rsc_clsclr *top;
|
||||
|
||||
@ -1853,7 +1797,7 @@ static u_int16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_lrrid(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_lrrid *top;
|
||||
|
||||
@ -1875,7 +1819,7 @@ static u_int16_t show_vty_link_subtlv_lrrid(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_llri(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_llri *top;
|
||||
|
||||
@ -1897,7 +1841,7 @@ static u_int16_t show_vty_link_subtlv_llri(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_rip(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_rip *top;
|
||||
|
||||
@ -1914,7 +1858,7 @@ static u_int16_t show_vty_link_subtlv_rip(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_ras(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_ras *top;
|
||||
|
||||
@ -1931,7 +1875,7 @@ static u_int16_t show_vty_link_subtlv_ras(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_av_delay(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_av_delay *top;
|
||||
u_int32_t delay;
|
||||
@ -1952,7 +1896,7 @@ static u_int16_t show_vty_link_subtlv_av_delay(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_mm_delay *top;
|
||||
u_int32_t low, high;
|
||||
@ -1974,7 +1918,7 @@ static u_int16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_delay_var(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_delay_var *top;
|
||||
u_int32_t jitter;
|
||||
@ -1991,7 +1935,7 @@ static u_int16_t show_vty_link_subtlv_delay_var(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_pkt_loss *top;
|
||||
u_int32_t loss;
|
||||
@ -2014,7 +1958,7 @@ static u_int16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_res_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_res_bw *top;
|
||||
float fval;
|
||||
@ -2035,7 +1979,7 @@ static u_int16_t show_vty_link_subtlv_res_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_ava_bw *top;
|
||||
float fval;
|
||||
@ -2056,7 +2000,7 @@ static u_int16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_link_subtlv_use_bw(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
struct te_link_subtlv_use_bw *top;
|
||||
float fval;
|
||||
@ -2077,7 +2021,7 @@ static u_int16_t show_vty_link_subtlv_use_bw(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t show_vty_unknown_tlv(struct vty *vty,
|
||||
struct te_tlv_header *tlvh)
|
||||
struct tlv_header *tlvh)
|
||||
{
|
||||
if (vty != NULL)
|
||||
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
|
||||
@ -2090,11 +2034,11 @@ static u_int16_t show_vty_unknown_tlv(struct vty *vty,
|
||||
}
|
||||
|
||||
static u_int16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
|
||||
struct te_tlv_header *tlvh0,
|
||||
struct tlv_header *tlvh0,
|
||||
u_int16_t subtotal,
|
||||
u_int16_t total)
|
||||
{
|
||||
struct te_tlv_header *tlvh, *next;
|
||||
struct tlv_header *tlvh, *next;
|
||||
u_int16_t sum = subtotal;
|
||||
|
||||
for (tlvh = tlvh0; sum < total;
|
||||
@ -2172,9 +2116,9 @@ static u_int16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
|
||||
static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
{
|
||||
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
|
||||
struct te_tlv_header *tlvh, *next;
|
||||
struct tlv_header *tlvh, *next;
|
||||
u_int16_t sum, total;
|
||||
u_int16_t (*subfunc)(struct vty * vty, struct te_tlv_header * tlvh,
|
||||
u_int16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
|
||||
u_int16_t subtotal, u_int16_t total) = NULL;
|
||||
|
||||
sum = 0;
|
||||
@ -2184,7 +2128,7 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
|
||||
if (subfunc != NULL) {
|
||||
sum = (*subfunc)(vty, tlvh, sum, total);
|
||||
next = (struct te_tlv_header *)((char *)tlvh + sum);
|
||||
next = (struct tlv_header *)((char *)tlvh + sum);
|
||||
subfunc = NULL;
|
||||
continue;
|
||||
}
|
||||
@ -2197,7 +2141,7 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
case TE_TLV_LINK:
|
||||
sum += show_vty_link_header(vty, tlvh);
|
||||
subfunc = ospf_mpls_te_show_link_subtlv;
|
||||
next = tlvh + 1;
|
||||
next = TLV_DATA(tlvh);
|
||||
break;
|
||||
default:
|
||||
sum += show_vty_unknown_tlv(vty, tlvh);
|
||||
@ -2210,7 +2154,7 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
static void ospf_mpls_te_config_write_router(struct vty *vty)
|
||||
{
|
||||
|
||||
if (OspfMplsTE.status == enabled) {
|
||||
if (OspfMplsTE.enabled) {
|
||||
vty_out(vty, " mpls-te on\n");
|
||||
vty_out(vty, " mpls-te router-address %s\n",
|
||||
inet_ntoa(OspfMplsTE.router_addr.value));
|
||||
@ -2239,20 +2183,20 @@ DEFUN (ospf_mpls_te_on,
|
||||
struct listnode *node;
|
||||
struct mpls_te_link *lp;
|
||||
|
||||
if (OspfMplsTE.status == enabled)
|
||||
if (OspfMplsTE.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("MPLS-TE: OFF -> ON");
|
||||
|
||||
OspfMplsTE.status = enabled;
|
||||
OspfMplsTE.enabled = true;
|
||||
|
||||
/* Reoriginate RFC3630 & RFC6827 Links */
|
||||
ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
|
||||
REORIGINATE_THIS_LSA);
|
||||
|
||||
/* Reoriginate LSA if INTER-AS is always on */
|
||||
if (OspfMplsTE.inter_as != Disable) {
|
||||
if (OspfMplsTE.inter_as != Off) {
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
|
||||
if (IS_INTER_AS(lp->type)) {
|
||||
ospf_mpls_te_lsa_schedule(lp,
|
||||
@ -2275,18 +2219,17 @@ DEFUN (no_ospf_mpls_te,
|
||||
struct listnode *node, *nnode;
|
||||
struct mpls_te_link *lp;
|
||||
|
||||
if (OspfMplsTE.status == disabled)
|
||||
if (!OspfMplsTE.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("MPLS-TE: ON -> OFF");
|
||||
|
||||
OspfMplsTE.status = disabled;
|
||||
OspfMplsTE.enabled = false;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
|
||||
if
|
||||
CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
|
||||
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -2317,8 +2260,8 @@ DEFUN (ospf_mpls_te_router_addr,
|
||||
|
||||
set_mpls_te_router_addr(value);
|
||||
|
||||
if (OspfMplsTE.status == disabled)
|
||||
goto out;
|
||||
if (!OspfMplsTE.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
|
||||
if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
|
||||
@ -2344,7 +2287,7 @@ DEFUN (ospf_mpls_te_router_addr,
|
||||
ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
|
||||
REORIGINATE_THIS_LSA);
|
||||
}
|
||||
out:
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2356,7 +2299,7 @@ static int set_inter_as_mode(struct vty *vty, const char *mode_name,
|
||||
struct mpls_te_link *lp;
|
||||
int format;
|
||||
|
||||
if (OspfMplsTE.status == enabled) {
|
||||
if (OspfMplsTE.enabled) {
|
||||
|
||||
/* Read and Check inter_as mode */
|
||||
if (strcmp(mode_name, "as") == 0)
|
||||
@ -2385,7 +2328,7 @@ static int set_inter_as_mode(struct vty *vty, const char *mode_name,
|
||||
}
|
||||
|
||||
/* Enable mode and re-originate LSA if needed */
|
||||
if ((OspfMplsTE.inter_as == Disable)
|
||||
if ((OspfMplsTE.inter_as == Off)
|
||||
&& (mode != OspfMplsTE.inter_as)) {
|
||||
OspfMplsTE.inter_as = mode;
|
||||
/* Re-originate all InterAS-TEv2 LSA */
|
||||
@ -2451,9 +2394,9 @@ DEFUN (no_ospf_mpls_te_inter_as,
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("MPLS-TE: Inter-AS support OFF");
|
||||
|
||||
if ((OspfMplsTE.status == enabled)
|
||||
&& (OspfMplsTE.inter_as != Disable)) {
|
||||
OspfMplsTE.inter_as = Disable;
|
||||
if ((OspfMplsTE.enabled)
|
||||
&& (OspfMplsTE.inter_as != Off)) {
|
||||
OspfMplsTE.inter_as = Off;
|
||||
/* Flush all Inter-AS LSA */
|
||||
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
|
||||
if (IS_INTER_AS(lp->type)
|
||||
@ -2476,7 +2419,7 @@ DEFUN (show_ip_ospf_mpls_te_router,
|
||||
"MPLS-TE information\n"
|
||||
"MPLS-TE Router parameters\n")
|
||||
{
|
||||
if (OspfMplsTE.status == enabled) {
|
||||
if (OspfMplsTE.enabled) {
|
||||
vty_out(vty, "--- MPLS-TE router parameters ---\n");
|
||||
|
||||
if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
|
||||
@ -2492,7 +2435,7 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
|
||||
{
|
||||
struct mpls_te_link *lp;
|
||||
|
||||
if ((OspfMplsTE.status == enabled) && HAS_LINK_PARAMS(ifp)
|
||||
if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp)
|
||||
&& !if_is_loopback(ifp) && if_is_up(ifp)
|
||||
&& ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
|
||||
/* Continue only if interface is not passive or support Inter-AS
|
||||
|
138
ospfd/ospf_te.h
138
ospfd/ospf_te.h
@ -78,7 +78,7 @@
|
||||
#define FLOOD_AS 0x20
|
||||
#define EMULATED 0x80
|
||||
|
||||
#define IS_STD_TE(x) (x & STD_TE)
|
||||
#define IS_STD_TE(x) (x & STD_TE)
|
||||
#define IS_PSEUDO_TE(x) (x & PSEUDO_TE)
|
||||
#define IS_INTER_AS(x) (x & INTER_AS)
|
||||
#define IS_EMULATED(x) (x & EMULATED)
|
||||
@ -94,58 +94,32 @@
|
||||
#define LPFLG_LOOKUP_DONE 0x4
|
||||
#define LPFLG_LSA_FORCED_REFRESH 0x8
|
||||
|
||||
/*
|
||||
* Following section defines TLV (tag, length, value) structures,
|
||||
* used for Traffic Engineering.
|
||||
*/
|
||||
struct te_tlv_header {
|
||||
u_int16_t type; /* TE_TLV_XXX (see below) */
|
||||
u_int16_t length; /* Value portion only, in octets */
|
||||
};
|
||||
|
||||
#define TLV_HDR_SIZE (sizeof(struct te_tlv_header))
|
||||
|
||||
#define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(u_int32_t)))
|
||||
|
||||
#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
|
||||
|
||||
#define TLV_HDR_TOP(lsah) \
|
||||
(struct te_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
|
||||
|
||||
#define TLV_HDR_NEXT(tlvh) \
|
||||
(struct te_tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
|
||||
|
||||
#define TLV_HDR_SUBTLV(tlvh) \
|
||||
(struct te_tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE)
|
||||
|
||||
#define TLV_TYPE(tlvh) tlvh.header.type
|
||||
#define TLV_LEN(tlvh) tlvh.header.length
|
||||
#define TLV_HDR(tlvh) tlvh.header
|
||||
|
||||
/*
|
||||
* Following section defines TLV body parts.
|
||||
*/
|
||||
|
||||
/* Router Address TLV */ /* Mandatory */
|
||||
#define TE_TLV_ROUTER_ADDR 1
|
||||
struct te_tlv_router_addr {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
struct in_addr value;
|
||||
};
|
||||
|
||||
/* Link TLV */
|
||||
#define TE_TLV_LINK 2
|
||||
struct te_tlv_link {
|
||||
struct te_tlv_header header;
|
||||
struct tlv_header header;
|
||||
/* A set of link-sub-TLVs will follow. */
|
||||
};
|
||||
|
||||
/* Default TE TLV size */
|
||||
#define TE_LINK_SUBTLV_DEF_SIZE 4
|
||||
|
||||
/* Link Type Sub-TLV */ /* Mandatory */
|
||||
#define TE_LINK_SUBTLV_LINK_TYPE 1
|
||||
#define TE_LINK_SUBTLV_TYPE_SIZE 1
|
||||
struct te_link_subtlv_link_type {
|
||||
struct te_tlv_header header; /* Value length is 1 octet. */
|
||||
struct tlv_header header; /* Value length is 1 octet. */
|
||||
struct {
|
||||
#define LINK_TYPE_SUBTLV_VALUE_PTP 1
|
||||
#define LINK_TYPE_SUBTLV_VALUE_MA 2
|
||||
@ -157,42 +131,42 @@ struct te_link_subtlv_link_type {
|
||||
/* Link Sub-TLV: Link ID */ /* Mandatory */
|
||||
#define TE_LINK_SUBTLV_LINK_ID 2
|
||||
struct te_link_subtlv_link_id {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
struct in_addr value; /* Same as router-lsa's link-id. */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Local Interface IP Address */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_LCLIF_IPADDR 3
|
||||
struct te_link_subtlv_lclif_ipaddr {
|
||||
struct te_tlv_header header; /* Value length is 4 x N octets. */
|
||||
struct tlv_header header; /* Value length is 4 x N octets. */
|
||||
struct in_addr value[1]; /* Local IP address(es). */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Remote Interface IP Address */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_RMTIF_IPADDR 4
|
||||
struct te_link_subtlv_rmtif_ipaddr {
|
||||
struct te_tlv_header header; /* Value length is 4 x N octets. */
|
||||
struct tlv_header header; /* Value length is 4 x N octets. */
|
||||
struct in_addr value[1]; /* Neighbor's IP address(es). */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Traffic Engineering Metric */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_TE_METRIC 5
|
||||
struct te_link_subtlv_te_metric {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
u_int32_t value; /* Link metric for TE purpose. */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Maximum Bandwidth */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_MAX_BW 6
|
||||
struct te_link_subtlv_max_bw {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
float value; /* bytes/sec */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Maximum Reservable Bandwidth */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_MAX_RSV_BW 7
|
||||
struct te_link_subtlv_max_rsv_bw {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
float value; /* bytes/sec */
|
||||
};
|
||||
|
||||
@ -200,14 +174,14 @@ struct te_link_subtlv_max_rsv_bw {
|
||||
#define TE_LINK_SUBTLV_UNRSV_BW 8
|
||||
#define TE_LINK_SUBTLV_UNRSV_SIZE 32
|
||||
struct te_link_subtlv_unrsv_bw {
|
||||
struct te_tlv_header header; /* Value length is 32 octets. */
|
||||
struct tlv_header header; /* Value length is 32 octets. */
|
||||
float value[MAX_CLASS_TYPE]; /* One for each priority level. */
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Resource Class/Color */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_RSC_CLSCLR 9
|
||||
struct te_link_subtlv_rsc_clsclr {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
u_int32_t value; /* Admin. group membership. */
|
||||
};
|
||||
|
||||
@ -216,7 +190,7 @@ struct te_link_subtlv_rsc_clsclr {
|
||||
#define TE_LINK_SUBTLV_LRRID 10
|
||||
#define TE_LINK_SUBTLV_LRRID_SIZE 8
|
||||
struct te_link_subtlv_lrrid {
|
||||
struct te_tlv_header header; /* Value length is 8 octets. */
|
||||
struct tlv_header header; /* Value length is 8 octets. */
|
||||
struct in_addr local; /* Local TE Router Identifier */
|
||||
struct in_addr remote; /* Remote TE Router Identifier */
|
||||
};
|
||||
@ -225,7 +199,7 @@ struct te_link_subtlv_lrrid {
|
||||
#define TE_LINK_SUBTLV_LLRI 11
|
||||
#define TE_LINK_SUBTLV_LLRI_SIZE 8
|
||||
struct te_link_subtlv_llri {
|
||||
struct te_tlv_header header; /* Value length is 8 octets. */
|
||||
struct tlv_header header; /* Value length is 8 octets. */
|
||||
u_int32_t local; /* Link Local Identifier */
|
||||
u_int32_t remote; /* Link Remote Identifier */
|
||||
};
|
||||
@ -240,14 +214,14 @@ struct te_link_subtlv_llri {
|
||||
/* Remote AS Number sub-TLV */
|
||||
#define TE_LINK_SUBTLV_RAS 21
|
||||
struct te_link_subtlv_ras {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
u_int32_t value; /* Remote AS number */
|
||||
};
|
||||
|
||||
/* IPv4 Remote ASBR ID Sub-TLV */
|
||||
#define TE_LINK_SUBTLV_RIP 22
|
||||
struct te_link_subtlv_rip {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
struct in_addr value; /* Remote ASBR IP address */
|
||||
};
|
||||
|
||||
@ -261,63 +235,69 @@ struct te_link_subtlv_rip {
|
||||
/* Link Sub-TLV: Average Link Delay */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_AV_DELAY 27
|
||||
struct te_link_subtlv_av_delay {
|
||||
struct te_tlv_header header; /* Value length is 4 bytes. */
|
||||
u_int32_t
|
||||
value; /* delay in micro-seconds only 24 bits => 0 ... 16777215
|
||||
with Anomalous Bit as Upper most bit */
|
||||
struct tlv_header header; /* Value length is 4 bytes. */
|
||||
/*
|
||||
* delay in micro-seconds only 24 bits => 0 ... 16777215
|
||||
* with Anomalous Bit as Upper most bit
|
||||
*/
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Low/High Link Delay */
|
||||
#define TE_LINK_SUBTLV_MM_DELAY 28
|
||||
#define TE_LINK_SUBTLV_MM_DELAY_SIZE 8
|
||||
struct te_link_subtlv_mm_delay {
|
||||
struct te_tlv_header header; /* Value length is 8 bytes. */
|
||||
u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ...
|
||||
16777215
|
||||
with Anomalous Bit (A) as Upper most bit */
|
||||
u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ...
|
||||
16777215 */
|
||||
struct tlv_header header; /* Value length is 8 bytes. */
|
||||
/*
|
||||
* low delay in micro-seconds only 24 bits => 0 ... 16777215
|
||||
* with Anomalous Bit (A) as Upper most bit
|
||||
*/
|
||||
u_int32_t low;
|
||||
/* high delay in micro-seconds only 24 bits => 0 ... 16777215 */
|
||||
u_int32_t high;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Link Delay Variation i.e. Jitter */
|
||||
#define TE_LINK_SUBTLV_DELAY_VAR 29
|
||||
struct te_link_subtlv_delay_var {
|
||||
struct te_tlv_header header; /* Value length is 4 bytes. */
|
||||
u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ...
|
||||
16777215 */
|
||||
struct tlv_header header; /* Value length is 4 bytes. */
|
||||
/* interval in micro-seconds only 24 bits => 0 ... 16777215 */
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */
|
||||
#define TE_LINK_SUBTLV_PKT_LOSS 30
|
||||
struct te_link_subtlv_pkt_loss {
|
||||
struct te_tlv_header header; /* Value length is 4 bytes. */
|
||||
u_int32_t
|
||||
value; /* in percentage of total traffic only 24 bits (2^24 - 2)
|
||||
with Anomalous Bit as Upper most bit */
|
||||
struct tlv_header header; /* Value length is 4 bytes. */
|
||||
/*
|
||||
* in percentage of total traffic only 24 bits (2^24 - 2)
|
||||
* with Anomalous Bit as Upper most bit
|
||||
*/
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_RES_BW 31
|
||||
struct te_link_subtlv_res_bw {
|
||||
struct te_tlv_header header; /* Value length is 4 bytes. */
|
||||
float value; /* bandwidth in IEEE floating point format with units in
|
||||
bytes per second */
|
||||
struct tlv_header header; /* Value length is 4 bytes. */
|
||||
/* bandwidth in IEEE floating point format with units in bytes/second */
|
||||
float value;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_AVA_BW 32
|
||||
struct te_link_subtlv_ava_bw {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
float value; /* bandwidth in IEEE floating point format with units in
|
||||
bytes per second */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
/* bandwidth in IEEE floating point format with units in bytes/second */
|
||||
float value;
|
||||
};
|
||||
|
||||
/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */
|
||||
#define TE_LINK_SUBTLV_USE_BW 33
|
||||
struct te_link_subtlv_use_bw {
|
||||
struct te_tlv_header header; /* Value length is 4 octets. */
|
||||
float value; /* bandwidth in IEEE floating point format with units in
|
||||
bytes per second */
|
||||
struct tlv_header header; /* Value length is 4 octets. */
|
||||
/* bandwidth in IEEE floating point format with units in bytes/second */
|
||||
float value;
|
||||
};
|
||||
|
||||
#define TE_LINK_SUBTLV_MAX 34 /* Last SUBTLV + 1 */
|
||||
@ -325,20 +305,11 @@ struct te_link_subtlv_use_bw {
|
||||
/* Here are "non-official" architectural constants. */
|
||||
#define MPLS_TE_MINIMUM_BANDWIDTH 1.0 /* Reasonable? *//* XXX */
|
||||
|
||||
/* Following declaration concerns the MPLS-TE and LINk-TE management */
|
||||
typedef enum _opcode_t {
|
||||
REORIGINATE_THIS_LSA,
|
||||
REFRESH_THIS_LSA,
|
||||
FLUSH_THIS_LSA
|
||||
} opcode_t;
|
||||
|
||||
typedef enum _status_t { disabled, enabled } status_t;
|
||||
|
||||
/* Mode for Inter-AS Opaque-LSA */
|
||||
enum inter_as_mode { Disable, AS, Area };
|
||||
enum inter_as_mode { Off, AS, Area };
|
||||
|
||||
struct te_link_subtlv {
|
||||
struct te_tlv_header header;
|
||||
struct tlv_header header;
|
||||
union {
|
||||
u_int32_t link_type;
|
||||
struct in_addr link_id;
|
||||
@ -366,7 +337,7 @@ struct te_link_subtlv {
|
||||
/* Following structure are internal use only. */
|
||||
struct ospf_mpls_te {
|
||||
/* Status of MPLS-TE: enable or disbale */
|
||||
status_t status;
|
||||
bool enabled;
|
||||
|
||||
/* RFC5392 */
|
||||
enum inter_as_mode inter_as;
|
||||
@ -437,8 +408,7 @@ extern int ospf_mpls_te_init(void);
|
||||
extern void ospf_mpls_te_term(void);
|
||||
extern struct ospf_mpls_te *get_ospf_mpls_te(void);
|
||||
extern void ospf_mpls_te_update_if(struct interface *);
|
||||
extern void ospf_mpls_te_lsa_schedule(struct mpls_te_link *, opcode_t);
|
||||
extern u_int32_t get_mpls_te_instance_value(void);
|
||||
extern void ospf_mpls_te_lsa_schedule(struct mpls_te_link *, enum lsa_opcode);
|
||||
extern void set_linkparams_llri(struct mpls_te_link *, u_int32_t, u_int32_t);
|
||||
extern void set_linkparams_lrrid(struct mpls_te_link *, struct in_addr,
|
||||
struct in_addr);
|
||||
|
@ -4402,6 +4402,10 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
|
||||
if (!ret) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
||||
else {
|
||||
vty_out(vty, "{}\n");
|
||||
json_object_free(json);
|
||||
}
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@ -4682,6 +4686,10 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty,
|
||||
if (!ifp) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No such interface.\n");
|
||||
else {
|
||||
vty_out(vty, "{}\n");
|
||||
json_object_free(json);
|
||||
}
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
@ -976,9 +976,13 @@ int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
rn->info = NULL;
|
||||
route_unlock_node(rn); /* initial reference */
|
||||
|
||||
/* Find interfaces that not configured already. */
|
||||
/* Find interfaces that are not configured already. */
|
||||
for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
|
||||
ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
continue;
|
||||
|
||||
ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Update connected redistribute. */
|
||||
|
@ -101,7 +101,7 @@ struct ospf_master {
|
||||
|
||||
/* Various OSPF global configuration. */
|
||||
u_char options;
|
||||
#define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
|
||||
#define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
|
||||
};
|
||||
|
||||
struct ospf_redist {
|
||||
|
@ -1,3 +0,0 @@
|
||||
rcdir=@pkgsrcrcdir@
|
||||
|
||||
rc_SCRIPTS = bgpd.sh ospf6d.sh ospfd.sh ripd.sh ripngd.sh zebra.sh
|
@ -1,3 +0,0 @@
|
||||
EXTRA_DIST = \
|
||||
clidef.py \
|
||||
clippy/__init__.py
|
2
qpb/.gitignore
vendored
2
qpb/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
Makefile
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
tags
|
||||
|
10
qpb/Makefile
Normal file
10
qpb/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C .. fpm/libfrr_pb.la
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C .. fpm/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
@ -1,30 +0,0 @@
|
||||
include ../common.am
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
|
||||
|
||||
PROTOBUF_INCLUDES=-I$(top_srcdir)
|
||||
PROTOBUF_PACKAGE = qpb
|
||||
|
||||
lib_LTLIBRARIES = libfrr_pb.la
|
||||
libfrr_pb_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
protobuf_srcs = \
|
||||
qpb_allocator.c
|
||||
|
||||
protobuf_srcs_nodist = \
|
||||
qpb.pb-c.c
|
||||
endif
|
||||
|
||||
libfrr_pb_la_SOURCES = \
|
||||
linear_allocator.h \
|
||||
qpb.h \
|
||||
qpb.c \
|
||||
qpb_allocator.h \
|
||||
$(protobuf_srcs)
|
||||
|
||||
nodist_libfrr_pb_la_SOURCES = $(protobuf_srcs_nodist)
|
||||
|
||||
CLEANFILES = $(Q_CLEANFILES)
|
||||
BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
|
||||
EXTRA_DIST = qpb.proto
|
@ -20,6 +20,8 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
/*
|
||||
* Protobuf definitions pertaining to the Quagga/FRR Protobuf component.
|
||||
*/
|
||||
@ -87,4 +89,4 @@ enum Protocol {
|
||||
ISIS = 8;
|
||||
BGP = 9;
|
||||
OTHER = 10;
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,7 @@ static void _qpb_free(void *allocator_data, void *ptr)
|
||||
linear_allocator_free(allocator_data, ptr);
|
||||
}
|
||||
|
||||
static ProtobufCAllocator allocator_template = {_qpb_alloc, _qpb_free, NULL,
|
||||
8192, NULL};
|
||||
static ProtobufCAllocator allocator_template = {_qpb_alloc, _qpb_free, NULL};
|
||||
|
||||
/*
|
||||
* qpb_allocator_init_linear
|
||||
|
26
qpb/subdir.am
Normal file
26
qpb/subdir.am
Normal file
@ -0,0 +1,26 @@
|
||||
if HAVE_PROTOBUF
|
||||
lib_LTLIBRARIES += qpb/libfrr_pb.la
|
||||
endif
|
||||
|
||||
qpb_libfrr_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
|
||||
$(Q_PROTOBUF_C_CLIENT_INCLUDES)
|
||||
qpb_libfrr_pb_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
qpb_libfrr_pb_la_SOURCES = \
|
||||
qpb/linear_allocator.h \
|
||||
qpb/qpb.h \
|
||||
qpb/qpb.c \
|
||||
qpb/qpb_allocator.h \
|
||||
# end
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
qpb_libfrr_pb_la_SOURCES += qpb/qpb_allocator.c
|
||||
nodist_qpb_libfrr_pb_la_SOURCES = qpb/qpb.pb-c.c
|
||||
BUILT_SOURCES += qpb/qpb.pb-c.c
|
||||
CLEANFILES += \
|
||||
qpb/qpb.pb-c.c \
|
||||
qpb/qpb.pb-c.h \
|
||||
# end
|
||||
endif
|
||||
|
||||
EXTRA_DIST += qpb/qpb.proto
|
@ -1,5 +0,0 @@
|
||||
|
||||
EXTRA_DIST = frr.init frr.service daemons \
|
||||
frr.logrotate frr.pam frr.spec \
|
||||
README.rpm_build.md
|
||||
|
@ -515,6 +515,18 @@ case "$1" in
|
||||
if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
|
||||
echo "Removing all routes made by zebra."
|
||||
ip route flush proto zebra
|
||||
# At least in CentOS/RHEL 6, iproute2 doesn't know
|
||||
# about the new protocol names, so we have to flush them
|
||||
# by number (it also doesn't support rt_protos.d
|
||||
ip route flush proto 186
|
||||
ip route flush proto 187
|
||||
ip route flush proto 188
|
||||
ip route flush proto 189
|
||||
ip route flush proto 190
|
||||
ip route flush proto 191
|
||||
ip route flush proto 192
|
||||
ip route flush proto 193
|
||||
ip route flush proto 194
|
||||
else
|
||||
[ -n "$dmn" ] && eval "${dmn/-/_}=0"
|
||||
start_watchfrr
|
||||
|
@ -66,7 +66,7 @@ DEFUN (debug_rip_events,
|
||||
"RIP events\n")
|
||||
{
|
||||
rip_debug_event = RIP_DEBUG_EVENT;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_rip_packet,
|
||||
@ -112,7 +112,7 @@ DEFUN (debug_rip_zebra,
|
||||
"RIP and ZEBRA communication\n")
|
||||
{
|
||||
rip_debug_zebra = RIP_DEBUG_ZEBRA;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_rip_events,
|
||||
@ -177,7 +177,7 @@ DEFUN (no_debug_rip_zebra,
|
||||
"RIP and ZEBRA communication\n")
|
||||
{
|
||||
rip_debug_zebra = 0;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Debug node. */
|
||||
|
@ -67,7 +67,7 @@ DEFUN (debug_ripng_events,
|
||||
"Debug option set for ripng events\n")
|
||||
{
|
||||
ripng_debug_event = RIPNG_DEBUG_EVENT;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_ripng_packet,
|
||||
@ -114,7 +114,7 @@ DEFUN (debug_ripng_zebra,
|
||||
"Debug option set for ripng and zebra communication\n")
|
||||
{
|
||||
ripng_debug_zebra = RIPNG_DEBUG_ZEBRA;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ripng_events,
|
||||
@ -179,7 +179,7 @@ DEFUN (no_debug_ripng_zebra,
|
||||
"Debug option set for ripng and zebra communication\n")
|
||||
{
|
||||
ripng_debug_zebra = 0;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Debug node. */
|
||||
|
@ -1,8 +0,0 @@
|
||||
EXTRA_DIST = snapcraft.yaml \
|
||||
README.snap_build.md \
|
||||
README.usage.md \
|
||||
extra_version_info.txt \
|
||||
scripts \
|
||||
defaults \
|
||||
helpers \
|
||||
snap
|
@ -170,7 +170,7 @@ static struct test_segment mp_segments[] = {
|
||||
/* 8 */
|
||||
{
|
||||
"MP6",
|
||||
"MP IP4/MPLS-laveled VPN",
|
||||
"MP IP4/MPLS-labeled VPN",
|
||||
{CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80},
|
||||
6,
|
||||
SHOULD_PARSE,
|
||||
|
@ -8,7 +8,7 @@ TestCapability.okfail("MPv6: MP IPv6/Uni")
|
||||
TestCapability.okfail("MP2: MP IP/Multicast")
|
||||
TestCapability.okfail("MP3: MP IP6/MPLS-labeled VPN")
|
||||
TestCapability.okfail("MP5: MP IP6/MPLS-VPN")
|
||||
TestCapability.okfail("MP6: MP IP4/MPLS-laveled VPN")
|
||||
TestCapability.okfail("MP6: MP IP4/MPLS-labeled VPN")
|
||||
TestCapability.okfail("MP8: MP unknown AFI/SAFI")
|
||||
TestCapability.okfail("MP-short: MP IP4/Unicast, length too short (< minimum)")
|
||||
TestCapability.okfail("MP-overflow: MP IP4/Unicast, length too long")
|
||||
|
@ -1059,7 +1059,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
|
||||
parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
|
||||
if (!parse_ret) {
|
||||
iana_afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
iana_safi_t pkt_safi;
|
||||
|
||||
/* Convert AFI, SAFI to internal values, check. */
|
||||
if (bgp_map_afi_safi_int2iana(nlri.afi, nlri.safi, &pkt_afi,
|
||||
|
138
vtysh/vtysh.c
138
vtysh/vtysh.c
@ -303,7 +303,9 @@ static int vtysh_execute_func(const char *line, int pager)
|
||||
|| saved_node == BGP_IPV4L_NODE
|
||||
|| saved_node == BGP_IPV6L_NODE
|
||||
|| saved_node == BGP_IPV6M_NODE
|
||||
|| saved_node == BGP_EVPN_NODE)
|
||||
|| saved_node == BGP_EVPN_NODE
|
||||
|| saved_node == LDP_IPV4_NODE
|
||||
|| saved_node == LDP_IPV6_NODE)
|
||||
&& (tried == 1)) {
|
||||
vtysh_execute("exit-address-family");
|
||||
} else if ((saved_node == BGP_EVPN_VNI_NODE) && (tried == 1)) {
|
||||
@ -496,6 +498,29 @@ int vtysh_mark_file(const char *filename)
|
||||
strcpy(vty_buf_copy, vty->buf);
|
||||
vty_buf_trimmed = trim(vty_buf_copy);
|
||||
|
||||
switch (vty->node) {
|
||||
case LDP_IPV4_IFACE_NODE:
|
||||
if (strncmp(vty_buf_copy, " ", 3)) {
|
||||
fprintf(stdout, " end\n");
|
||||
vty->node = LDP_IPV4_NODE;
|
||||
}
|
||||
break;
|
||||
case LDP_IPV6_IFACE_NODE:
|
||||
if (strncmp(vty_buf_copy, " ", 3)) {
|
||||
fprintf(stdout, " end\n");
|
||||
vty->node = LDP_IPV6_NODE;
|
||||
}
|
||||
break;
|
||||
case LDP_PSEUDOWIRE_NODE:
|
||||
if (strncmp(vty_buf_copy, " ", 2)) {
|
||||
fprintf(stdout, " end\n");
|
||||
vty->node = LDP_L2VPN_NODE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
|
||||
fprintf(stdout, "%s", vty->buf);
|
||||
continue;
|
||||
@ -1268,6 +1293,14 @@ DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv6, ldp_address_family_ipv6_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_LDPD, ldp_exit_address_family, ldp_exit_address_family_cmd,
|
||||
"exit-address-family", "Exit from Address Family configuration mode\n")
|
||||
{
|
||||
if (vty->node == LDP_IPV4_NODE || vty->node == LDP_IPV6_NODE)
|
||||
vty->node = LDP_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_LDPD, ldp_interface_ifname, ldp_interface_ifname_cmd,
|
||||
"interface IFNAME",
|
||||
"Enable LDP on an interface and enter interface submode\n"
|
||||
@ -2420,7 +2453,7 @@ DEFUN (vtysh_show_daemons,
|
||||
|
||||
/* Execute command in child process. */
|
||||
static void execute_command(const char *command, int argc,
|
||||
struct cmd_token *arg1, const char *arg2)
|
||||
const char *arg1, const char *arg2)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
@ -2465,7 +2498,10 @@ DEFUN (vtysh_ping,
|
||||
"Send echo messages\n"
|
||||
"Ping destination address or hostname\n")
|
||||
{
|
||||
execute_command("ping", 1, argv[0], NULL);
|
||||
int idx = 1;
|
||||
|
||||
argv_find(argv, argc, "WORD", &idx);
|
||||
execute_command("ping", 1, argv[idx]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2480,7 +2516,10 @@ DEFUN (vtysh_traceroute,
|
||||
"Trace route to destination\n"
|
||||
"Trace route to destination address or hostname\n")
|
||||
{
|
||||
execute_command("traceroute", 1, argv[0], NULL);
|
||||
int idx = 1;
|
||||
|
||||
argv_find(argv, argc, "WORD", &idx);
|
||||
execute_command("traceroute", 1, argv[idx]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2496,7 +2535,7 @@ DEFUN (vtysh_ping6,
|
||||
"IPv6 echo\n"
|
||||
"Ping destination address or hostname\n")
|
||||
{
|
||||
execute_command("ping6", 1, argv[0], NULL);
|
||||
execute_command("ping6", 1, argv[2]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2507,7 +2546,7 @@ DEFUN (vtysh_traceroute6,
|
||||
"IPv6 trace\n"
|
||||
"Trace route to destination address or hostname\n")
|
||||
{
|
||||
execute_command("traceroute6", 1, argv[0], NULL);
|
||||
execute_command("traceroute6", 1, argv[2]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2518,7 +2557,7 @@ DEFUN (vtysh_telnet,
|
||||
"Open a telnet connection\n"
|
||||
"IP address or hostname of a remote system\n")
|
||||
{
|
||||
execute_command("telnet", 1, argv[0], NULL);
|
||||
execute_command("telnet", 1, argv[1]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2529,7 +2568,7 @@ DEFUN (vtysh_telnet_port,
|
||||
"IP address or hostname of a remote system\n"
|
||||
"TCP Port number\n")
|
||||
{
|
||||
execute_command("telnet", 2, argv[0], argv[1]);
|
||||
execute_command("telnet", 2, argv[1]->arg, argv[2]->arg);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2539,7 +2578,7 @@ DEFUN (vtysh_ssh,
|
||||
"Open an ssh connection\n"
|
||||
"[user@]host\n")
|
||||
{
|
||||
execute_command("ssh", 1, argv[0], NULL);
|
||||
execute_command("ssh", 1, argv[1]->arg, NULL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2582,9 +2621,39 @@ DEFUN (config_list,
|
||||
return cmd_list_cmds(vty, argc == 2);
|
||||
}
|
||||
|
||||
DEFUN(find,
|
||||
find_cmd,
|
||||
"find COMMAND...",
|
||||
"Find CLI command containing text\n"
|
||||
"Text to search for\n")
|
||||
{
|
||||
char *text = argv_concat(argv, argc, 1);
|
||||
const struct cmd_node *node;
|
||||
const struct cmd_element *cli;
|
||||
vector clis;
|
||||
|
||||
for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
|
||||
node = vector_slot(cmdvec, i);
|
||||
if (!node)
|
||||
continue;
|
||||
clis = node->cmd_vector;
|
||||
for (unsigned int j = 0; j < vector_active(clis); j++) {
|
||||
cli = vector_slot(clis, j);
|
||||
if (strcasestr(cli->string, text))
|
||||
fprintf(stdout, " (%s) %s\n",
|
||||
node_names[node->node], cli->string);
|
||||
}
|
||||
}
|
||||
|
||||
XFREE(MTYPE_TMP, text);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void vtysh_install_default(enum node_type node)
|
||||
{
|
||||
install_element(node, &config_list_cmd);
|
||||
install_element(node, &find_cmd);
|
||||
}
|
||||
|
||||
/* Making connection to protocol daemon. */
|
||||
@ -2876,48 +2945,13 @@ void vtysh_init_vty(void)
|
||||
install_node(&isis_node, NULL);
|
||||
install_node(&vty_node, NULL);
|
||||
|
||||
vtysh_install_default(VIEW_NODE);
|
||||
vtysh_install_default(CONFIG_NODE);
|
||||
vtysh_install_default(BGP_NODE);
|
||||
vtysh_install_default(RIP_NODE);
|
||||
vtysh_install_default(INTERFACE_NODE);
|
||||
vtysh_install_default(LINK_PARAMS_NODE);
|
||||
vtysh_install_default(NS_NODE);
|
||||
vtysh_install_default(VRF_NODE);
|
||||
vtysh_install_default(RMAP_NODE);
|
||||
vtysh_install_default(ZEBRA_NODE);
|
||||
vtysh_install_default(BGP_VPNV4_NODE);
|
||||
vtysh_install_default(BGP_VPNV6_NODE);
|
||||
vtysh_install_default(BGP_IPV4_NODE);
|
||||
vtysh_install_default(BGP_IPV4M_NODE);
|
||||
vtysh_install_default(BGP_IPV4L_NODE);
|
||||
vtysh_install_default(BGP_IPV6_NODE);
|
||||
vtysh_install_default(BGP_IPV6M_NODE);
|
||||
vtysh_install_default(BGP_EVPN_NODE);
|
||||
vtysh_install_default(BGP_EVPN_VNI_NODE);
|
||||
vtysh_install_default(BGP_IPV6L_NODE);
|
||||
#if ENABLE_BGP_VNC
|
||||
vtysh_install_default(BGP_VRF_POLICY_NODE);
|
||||
vtysh_install_default(BGP_VNC_DEFAULTS_NODE);
|
||||
vtysh_install_default(BGP_VNC_NVE_GROUP_NODE);
|
||||
vtysh_install_default(BGP_VNC_L2_GROUP_NODE);
|
||||
#endif
|
||||
vtysh_install_default(OSPF_NODE);
|
||||
vtysh_install_default(EIGRP_NODE);
|
||||
vtysh_install_default(BABEL_NODE);
|
||||
vtysh_install_default(RIPNG_NODE);
|
||||
vtysh_install_default(OSPF6_NODE);
|
||||
vtysh_install_default(LDP_NODE);
|
||||
vtysh_install_default(LDP_IPV4_NODE);
|
||||
vtysh_install_default(LDP_IPV6_NODE);
|
||||
vtysh_install_default(LDP_IPV4_IFACE_NODE);
|
||||
vtysh_install_default(LDP_IPV6_IFACE_NODE);
|
||||
vtysh_install_default(LDP_L2VPN_NODE);
|
||||
vtysh_install_default(LDP_PSEUDOWIRE_NODE);
|
||||
vtysh_install_default(ISIS_NODE);
|
||||
vtysh_install_default(KEYCHAIN_NODE);
|
||||
vtysh_install_default(KEYCHAIN_KEY_NODE);
|
||||
vtysh_install_default(VTY_NODE);
|
||||
struct cmd_node *node;
|
||||
for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
|
||||
node = vector_slot(cmdvec, i);
|
||||
if (!node || node->node == VIEW_NODE)
|
||||
continue;
|
||||
vtysh_install_default(node->node);
|
||||
}
|
||||
|
||||
install_element(VIEW_NODE, &vtysh_enable_cmd);
|
||||
install_element(ENABLE_NODE, &vtysh_config_terminal_cmd);
|
||||
@ -2945,8 +2979,10 @@ void vtysh_init_vty(void)
|
||||
install_element(LDP_NODE, &vtysh_quit_ldpd_cmd);
|
||||
install_element(LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd);
|
||||
install_element(LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd);
|
||||
install_element(LDP_IPV4_NODE, &ldp_exit_address_family_cmd);
|
||||
install_element(LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd);
|
||||
install_element(LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd);
|
||||
install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd);
|
||||
install_element(LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd);
|
||||
install_element(LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd);
|
||||
install_element(LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd);
|
||||
|
@ -44,7 +44,7 @@ DECLARE_MGROUP(MVTYSH)
|
||||
* run on it (logging & co. should stay in a fixed/frozen config, and
|
||||
* things like prefix lists are not even initialised) */
|
||||
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD
|
||||
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD
|
||||
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD|VTYSH_EIGRPD
|
||||
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD
|
||||
#define VTYSH_NS VTYSH_ZEBRA
|
||||
#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD
|
||||
|
3
zebra/.gitignore
vendored
3
zebra/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
Makefile
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
zebra
|
||||
@ -13,3 +13,4 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
zebra_vty_clippy.c
|
||||
|
10
zebra/Makefile
Normal file
10
zebra/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C .. zebra/zebra
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C .. zebra/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
@ -1,94 +0,0 @@
|
||||
include ../common.am
|
||||
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
LIBCAP = @LIBCAP@
|
||||
|
||||
ipforward = @IPFORWARD@
|
||||
if_method = @IF_METHOD@
|
||||
rt_method = @RT_METHOD@
|
||||
rtread_method = @RTREAD_METHOD@
|
||||
kernel_method = @KERNEL_METHOD@
|
||||
ioctl_method = @IOCTL_METHOD@
|
||||
mpls_method = @MPLS_METHOD@
|
||||
|
||||
otherobj = $(ioctl_method) $(ipforward) $(if_method) \
|
||||
$(rt_method) $(rtread_method) $(kernel_method) $(mpls_method)
|
||||
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
sbin_PROGRAMS = zebra
|
||||
module_LTLIBRARIES =
|
||||
|
||||
zebra_SOURCES = \
|
||||
zebra_memory.c \
|
||||
zserv.c main.c interface.c connected.c zebra_rib.c zebra_routemap.c \
|
||||
redistribute.c debug.c rtadv.c zebra_vty.c \
|
||||
irdp_main.c irdp_interface.c irdp_packet.c router-id.c \
|
||||
zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
|
||||
zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
|
||||
zebra_mroute.c \
|
||||
label_manager.c \
|
||||
zebra_l2.c \
|
||||
zebra_vxlan.c \
|
||||
# end
|
||||
|
||||
noinst_HEADERS = \
|
||||
zebra_memory.h \
|
||||
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
||||
interface.h ipforward.h irdp.h router-id.h kernel_socket.h \
|
||||
rt_netlink.h zebra_fpm_private.h zebra_rnh.h \
|
||||
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
|
||||
zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \
|
||||
kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h \
|
||||
zebra_l2.h zebra_vxlan_private.h zebra_vxlan.h
|
||||
|
||||
zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP)
|
||||
|
||||
zebra_DEPENDENCIES = $(otherobj)
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += zebra_snmp.la
|
||||
endif
|
||||
zebra_snmp_la_SOURCES = zebra_snmp.c
|
||||
zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
||||
zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
if FPM
|
||||
module_LTLIBRARIES += zebra_fpm.la
|
||||
endif
|
||||
zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS)
|
||||
zebra_fpm_la_SOURCES = zebra_fpm.c
|
||||
if HAVE_NETLINK
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_netlink.c
|
||||
endif
|
||||
if HAVE_PROTOBUF
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_protobuf.c
|
||||
if DEV_BUILD
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_dt.c
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \
|
||||
if_sysctl.c ipforward_proc.c \
|
||||
ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \
|
||||
rt_socket.c rtread_netlink.c rtread_sysctl.c \
|
||||
rtread_getmsg.c kernel_socket.c kernel_netlink.c \
|
||||
ioctl.c ioctl_solaris.c \
|
||||
zebra_mpls_netlink.c zebra_mpls_openbsd.c zebra_mpls_null.c \
|
||||
GNOME-SMI GNOME-PRODUCT-ZEBRA-MIB
|
||||
|
||||
client : client_main.o ../lib/libfrr.la
|
||||
$(CC) -g -o client client_main.o ../liblzebra.la $(LIBS) $(LIB_IPV6)
|
||||
|
||||
frrconfdir = $(sysconfdir)
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = zebra.conf.sample
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user