mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 17:23:00 +02:00
Compare commits
152
Commits
+36
-20
@@ -11,7 +11,7 @@ Talking about code and problems first is often the best way to get started
|
||||
before submitting a pull request.
|
||||
|
||||
When submitting a bug report, patch, or pull request, please start by
|
||||
stating the version the change is made against, what it does, and why.
|
||||
stating the version the change is made against, what it does, *and why*.
|
||||
|
||||
Please take care to ensure you follow the project coding style and the
|
||||
commit message format. If you follow these recommendations you help
|
||||
@@ -21,13 +21,28 @@ the maintainer(s) and make it easier for them to include your code.
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
> **Tip:** Always submit code that follows the style of surrounding code!
|
||||
Before jumping into code, remember to **document new features** and bug
|
||||
fixes. Both the manual and ChangeLog are in the `doc/` sub-directory
|
||||
and it is expected that you provide a human-readable summary for the
|
||||
release notes (ChangeLog) and at least a configuration example in the
|
||||
manual for new features.
|
||||
|
||||
First of all, lines are allowed to be longer than 72 characters these
|
||||
days. In fact, there exist no enforced maximum, but keeping it around
|
||||
100 chars is OK.
|
||||
> **Tip:** consider ["Readme driven development"][RDD] for new features.
|
||||
> It is amazing how many flaws in your own bright ideas come to bare
|
||||
> when you suddenly have to explain them to someone else!
|
||||
|
||||
The coding style itself is otherwise strictly Linux [KNF][].
|
||||
We expect code contributions for:
|
||||
|
||||
- C code in [Linux Coding Style][Linux]
|
||||
- Python code should follow [PEP-8][]
|
||||
|
||||
> **However,** always submit code that follows the style of surrounding
|
||||
> code! Legacy takes precedence, and remember, we read code a lot more
|
||||
> than write it, so legibility is important.
|
||||
|
||||
As a final note, lines are allowed to be longer than 72 characters these
|
||||
days. There is no enforced maximum, but the team usually keep it around
|
||||
100 characters for both C and Python.
|
||||
|
||||
|
||||
Commit Messages
|
||||
@@ -37,22 +52,21 @@ Commit messages exist to track *why* a change was made. Try to be as
|
||||
clear and concise as possible in your commit messages, and always, be
|
||||
proud of your work and set up a proper GIT identity for your commits:
|
||||
|
||||
git config --global user.name "Jane Doe"
|
||||
git config --global user.email jane.doe@example.com
|
||||
$ git config --global user.name "Jacky Linker"
|
||||
$ git config --global user.email jacky.linker@example.com
|
||||
|
||||
Example commit message from the [Pro Git][gitbook] online book, notice
|
||||
how `git commit -s` is used to automatically add a `Signed-off-by`:
|
||||
|
||||
Brief, but clear and concise summary of changes
|
||||
subsystem: brief, but clear and concise summary of changes
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as
|
||||
the subject of an email and the rest of the text as the body. The
|
||||
blank line separating the ummary from the body is critical (unless
|
||||
you omit the body entirely); tools like rebase can get confused if
|
||||
you run the two together.
|
||||
empty line separating summary from body is critical. Tools like
|
||||
rebase can get confused if the empty line is missing.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
Further paragraphs should be separated with empty lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
|
||||
@@ -60,17 +74,19 @@ how `git commit -s` is used to automatically add a `Signed-off-by`:
|
||||
by a single space, with blank lines in between, but conventions
|
||||
vary here
|
||||
|
||||
Signed-off-by: Jane Doe <jane.doe@example.com>
|
||||
Signed-off-by: Jacky Linker <jacky.linker@example.com>
|
||||
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
|
||||
It is expected of everyone to respect the [Code of Conduct][conduct].
|
||||
The *"maintainers have the right and responsibility to remove, edit,
|
||||
or reject comments, commits, code, wiki edits, issues, and other
|
||||
contributions that are not aligned to this Code of Conduct."*
|
||||
The *"maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, discussion forum threads, issues, and
|
||||
other contributions that are not aligned to this Code of Conduct."*
|
||||
|
||||
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
||||
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||
[conduct]: CODE-OF-CONDUCT.md
|
||||
[Linux]: https://www.kernel.org/doc/html/v6.9/process/coding-style.html
|
||||
[PEP-8]: https://peps.python.org/pep-0008/
|
||||
[RDD]: https://tom.preston-werner.com/2010/08/23/readme-driven-development
|
||||
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||
[conduct]: CODE-OF-CONDUCT.md
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: "\U0001F41E Bug report"
|
||||
description: Create a bug report
|
||||
labels:
|
||||
- "bug"
|
||||
- "triage"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Thank :heart: you for taking the time to fill out this bug report!**
|
||||
|
||||
We kindly ask that you search to see if an issue [already exists](https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+) for the bug you encountered.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: |
|
||||
A clear and concise description of the issue you're experiencing.
|
||||
value: |
|
||||
For code snippets, logs, commands, etc., please use triple backticks:
|
||||
```
|
||||
admin@infix-c0-ff-ee:/> show log
|
||||
May 15 07:21:02 infix-00-00-00 container[3192]: Failed creating container test from curios-httpd-v24.03.0
|
||||
- (press h for help or q to quit)
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: |
|
||||
A clear and concise description of what you expected to happen.
|
||||
value: |
|
||||
```
|
||||
admin@infix-c0-ff-ee:/> show log
|
||||
May 15 07:21:02 infix-c0-ff-ee container[3192]: Successfully created container test from curios-httpd-v24.03.0
|
||||
- (press h for help or q to quit)
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps To Reproduce
|
||||
description: |
|
||||
Steps to reproduce the issue. For example:
|
||||
|
||||
1. Built from source
|
||||
2. Upgrade to latest release, vYY.MM.P
|
||||
3. Factory reset
|
||||
4. Enable feature
|
||||
5. Check the logs/show command/operational status
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: |
|
||||
- Relevant parts of `startup-config`
|
||||
- Output from `show interfaces`, if applicable
|
||||
- Other observations, screenshots, log files ...
|
||||
|
||||
**Tip:** You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,7 @@
|
||||
contact_links:
|
||||
- name: "🔍 Look for my Issue"
|
||||
url: https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+
|
||||
about: Thank ❤️ you for your time! We kindly ask that you first check if an issue already exists.
|
||||
- name: "💬 Discussions and Q&A"
|
||||
url: https://github.com/kernelkit/infix/discussions
|
||||
about: Discussions are perfect for quick questions, bouncing ideas, and things that may be a bug.
|
||||
@@ -0,0 +1,45 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: "\U0001F6E0️ Feature request"
|
||||
description: Suggest a new feature, idea or improvement of the OS
|
||||
labels:
|
||||
- "feature"
|
||||
- "triage"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Thank :heart: you for taking the time to fill out this feature request!**
|
||||
|
||||
We kindly ask that you search to see if an issue [already exists](https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature. We are also happy to accept contributions from our users. For details see [CONTRIBUTING](https://github.com/kernelkit/infix/blob/master/.github/CONTRIBUTING.md).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
A clear and concise description of the problem or missing feature.
|
||||
**Example:** *I'm always frustrated when [...]*, or *I'd like to see support for [...]*
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
Any other related information, e.g. existing YANG model(s), or possibly screenshots about the feature request here.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: General Information
|
||||
description: |
|
||||
Appended to all feature requests for future readers.
|
||||
value: |
|
||||
Anyone can help out by [sponsoring][1] development of new features or [contributing][2] pull requests.
|
||||
Please use this issue for discussions related to the feature.
|
||||
|
||||
[1]: https://github.com/kernelkit/infix/blob/main/.github/SUPPORT.md
|
||||
[2]: https://github.com/kernelkit/infix/blob/main/.github/CONTRIBUTING.md
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,5 +1,3 @@
|
||||
<!--- **Summarize** your changes in the title above -->
|
||||
|
||||
## Description
|
||||
|
||||
<!--
|
||||
@@ -15,7 +13,7 @@
|
||||
|
||||
## Checklist
|
||||
|
||||
Tick relevant boxes, this PR is-a or has-a:
|
||||
Tick *relevant* boxes, this PR is-a or has-a:
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Regression tests
|
||||
@@ -31,7 +29,3 @@ Tick relevant boxes, this PR is-a or has-a:
|
||||
- [ ] Documentation content changes
|
||||
- [ ] Other (please describe):
|
||||
|
||||
|
||||
## References
|
||||
|
||||
<!-- Please list references to related issue(s) -->
|
||||
|
||||
+23
-15
@@ -8,25 +8,25 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Infix ${{ matrix.platform }}
|
||||
runs-on: self-hosted
|
||||
name: Build Infix ${{ matrix.target }}
|
||||
runs-on: [ self-hosted, latest ]
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [aarch64, x86_64]
|
||||
target: [aarch64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Maintenance
|
||||
run: |
|
||||
docker image prune -af
|
||||
docker volume prune -f
|
||||
docker container prune -f
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
clean: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Set Build Variables
|
||||
id: vars
|
||||
run: |
|
||||
target=${{ matrix.platform }}
|
||||
target=${{ matrix.target }}
|
||||
echo "dir=infix-$target" >> $GITHUB_OUTPUT
|
||||
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore Cache of dl/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -34,39 +34,45 @@ jobs:
|
||||
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
dl-
|
||||
|
||||
- name: Restore Cache of .ccache/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .ccache/
|
||||
key: ccache-${{ matrix.platform }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
|
||||
key: ccache-${{ matrix.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
ccache-${{ matrix.platform }}-
|
||||
ccache-${{ matrix.target }}-
|
||||
ccache-
|
||||
|
||||
- name: Configure & Build
|
||||
run: |
|
||||
target=${{ matrix.platform }}_defconfig
|
||||
target=${{ matrix.target }}_defconfig
|
||||
echo "Building $target ..."
|
||||
make $target
|
||||
make
|
||||
|
||||
- name: Prepare Artifact
|
||||
run: |
|
||||
cd output/
|
||||
mv images ${{ steps.vars.outputs.dir }}
|
||||
ln -s ${{ steps.vars.outputs.dir }} images
|
||||
tar chfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
|
||||
|
||||
- name: Test
|
||||
if: matrix.platform == 'x86_64'
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
make test
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: output/${{ steps.vars.outputs.tgz }}
|
||||
name: artifact-${{ matrix.platform }}
|
||||
name: artifact-${{ matrix.target }}
|
||||
|
||||
release:
|
||||
if: ${{github.repository_owner == 'kernelkit' && github.ref_name == 'main'}}
|
||||
name: Upload Latest Build
|
||||
needs: build
|
||||
runs-on: self-hosted
|
||||
runs-on: [ self-hosted, latest ]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -74,6 +80,7 @@ jobs:
|
||||
with:
|
||||
pattern: "artifact-*"
|
||||
merge-multiple: true
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
@@ -84,6 +91,7 @@ jobs:
|
||||
tag: "latest"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: "*.tar.gz"
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
cat <<EOF >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -12,7 +12,7 @@ env:
|
||||
jobs:
|
||||
coverity:
|
||||
if: ${{github.repository_owner == 'kernelkit'}}
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fetch latest Coverity Scan MD5
|
||||
@@ -24,6 +24,7 @@ jobs:
|
||||
--post-data "token=$TOKEN&project=${PROJECT_NAME}&md5=1" \
|
||||
-O coverity-latest.tar.gz.md5
|
||||
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
@@ -33,6 +34,7 @@ jobs:
|
||||
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
||||
${{ runner.os }}-coverity-
|
||||
${{ runner.os }}-coverity
|
||||
|
||||
- name: Download Coverity Scan
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
@@ -47,12 +49,14 @@ jobs:
|
||||
fi
|
||||
mkdir coverity
|
||||
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install pkg-config libjansson-dev libev-dev \
|
||||
libaugeas-dev libglib2.0-dev libpcre2-dev \
|
||||
libuev-dev libite-dev
|
||||
|
||||
- name: Build dependencies
|
||||
run: |
|
||||
git clone https://github.com/CESNET/libyang.git
|
||||
@@ -62,10 +66,12 @@ jobs:
|
||||
mkdir sysrepo/build
|
||||
(cd sysrepo/build && cmake .. && make all && sudo make install)
|
||||
make dep
|
||||
|
||||
- name: Check applications
|
||||
run: |
|
||||
export PATH=`pwd`/coverity/bin:$PATH
|
||||
cov-build --dir cov-int make check
|
||||
|
||||
- name: Submit results to Coverity Scan
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
@@ -78,6 +84,7 @@ jobs:
|
||||
--form version=$(git rev-parse HEAD) \
|
||||
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
||||
https://scan.coverity.com/builds?project=${PROJECT_NAME}
|
||||
|
||||
- name: Upload build.log
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -15,61 +15,78 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Regression Testing
|
||||
runs-on: self-hosted
|
||||
name: Regression Testing ${{ matrix.target }}
|
||||
runs-on: [ self-hosted, regression ]
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
|
||||
strategy:
|
||||
matrix:
|
||||
target: [aarch64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
clean: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Clean up cruft ...
|
||||
run: |
|
||||
./test/env -c
|
||||
|
||||
- name: Set Build Variables
|
||||
id: vars
|
||||
run: |
|
||||
target=x86_64
|
||||
target=${{ matrix.target }}
|
||||
echo "dir=infix-$target" >> $GITHUB_OUTPUT
|
||||
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore Cache of dl/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: dl/
|
||||
key: dl-netconf-${{ hashFiles('.git/modules/buildroot/refs/heads/master', 'package/*/*.hash') }}
|
||||
key: dl-netconf-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
dl-netconf-
|
||||
dl-
|
||||
|
||||
- name: Restore Cache of .ccache/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .ccache/
|
||||
key: ccache-x86_64-${{ hashFiles('.git/modules/buildroot/refs/head/master', 'package/*/*.hash') }}
|
||||
key: ccache-x86_64-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
ccache-x86_64-
|
||||
ccache-${{ matrix.target }}-
|
||||
ccache-
|
||||
- name: Configure NETCONF
|
||||
|
||||
- name: Configure ${{ matrix.target }}
|
||||
run: |
|
||||
make x86_64_defconfig
|
||||
target=${{ matrix.target }}_defconfig
|
||||
echo "Building $target ..."
|
||||
make $target
|
||||
|
||||
- name: Unit Test
|
||||
run: make test-unit
|
||||
run: |
|
||||
make test-unit
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make -j
|
||||
make
|
||||
|
||||
- name: Prepare Artifact
|
||||
run: |
|
||||
cd output
|
||||
cd output/
|
||||
mv images ${{ steps.vars.outputs.dir }}
|
||||
ln -s ${{ steps.vars.outputs.dir }} images
|
||||
tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: output/${{ steps.vars.outputs.tgz }}
|
||||
name: artifact-${{ matrix.target }}
|
||||
|
||||
- name: Regression Test
|
||||
run: make test-qeneth
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
make test
|
||||
|
||||
- name: Publish Test Result
|
||||
# Ensure this runs even if Regression Test fails
|
||||
|
||||
@@ -20,19 +20,18 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'kernelkit/infix' && startsWith(github.ref, 'refs/tags/')
|
||||
name: Build Infix ${{ github.ref_name }} [${{ matrix.platform }}]
|
||||
runs-on: self-hosted
|
||||
name: Build Infix ${{ github.ref_name }} [${{ matrix.target }}]
|
||||
runs-on: [ self-hosted, release ]
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [aarch64, x86_64]
|
||||
target: [aarch64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Maintenance
|
||||
run: |
|
||||
docker image prune -af
|
||||
docker volume prune -f
|
||||
docker container prune -f
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
clean: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Set Release Variables
|
||||
id: vars
|
||||
run: |
|
||||
@@ -43,10 +42,10 @@ jobs:
|
||||
fi
|
||||
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
||||
fver=${ver#v}
|
||||
target=${{ matrix.platform }}-${fver}
|
||||
target=${{ matrix.target }}-${fver}
|
||||
echo "dir=infix-$target" >> $GITHUB_OUTPUT
|
||||
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "out=/mnt/x-$target" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore Cache of dl/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -54,49 +53,55 @@ jobs:
|
||||
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
dl-
|
||||
|
||||
- name: Restore Cache of .ccache/
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .ccache/
|
||||
key: ccache-${{ matrix.platform }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
|
||||
key: ccache-${{ matrix.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
|
||||
restore-keys: |
|
||||
ccache-${{ matrix.platform }}-
|
||||
ccache-${{ matrix.target }}-
|
||||
ccache-
|
||||
|
||||
- name: Configure & Build
|
||||
env:
|
||||
INFIX_RELEASE: ${{ steps.vars.outputs.ver }}
|
||||
run: |
|
||||
target=${{ matrix.platform }}_defconfig
|
||||
target=${{ matrix.target }}_defconfig
|
||||
echo "Building $target ..."
|
||||
sudo mkdir ${{ steps.vars.outputs.out }}
|
||||
sudo chown $(id -un):$(id -gn) ${{ steps.vars.outputs.out }}
|
||||
export O=${{ steps.vars.outputs.out }}
|
||||
make $target
|
||||
make
|
||||
|
||||
- name: Generate SBOM from Build
|
||||
run: |
|
||||
make legal-info
|
||||
|
||||
- name: Prepare Artifacts
|
||||
run: |
|
||||
cd ${{ steps.vars.outputs.out }}
|
||||
cd output/
|
||||
mv images ${{ steps.vars.outputs.dir }}
|
||||
ln -s ${{ steps.vars.outputs.dir }} images
|
||||
tar chfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
|
||||
|
||||
mv legal-info legal-info-$target
|
||||
tar chfz legal-info-$target.tar.gz legal-info-$target
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-${{ matrix.platform }}
|
||||
path: ${{ steps.vars.outputs.out }}/*.tar.gz
|
||||
name: artifact-${{ matrix.target }}
|
||||
path: output/*.tar.gz
|
||||
|
||||
release:
|
||||
name: Release Infix ${{ github.ref_name }}
|
||||
needs: build
|
||||
runs-on: self-hosted
|
||||
runs-on: [ self-hosted, release ]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Set Release Variables
|
||||
id: rel
|
||||
run: |
|
||||
@@ -118,20 +123,24 @@ jobs:
|
||||
fi
|
||||
echo "pre=${{ steps.rel.outputs.pre }}"
|
||||
echo "latest=${{ steps.rel.outputs.latest }}"
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: "artifact-*"
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create checksums ...
|
||||
run: |
|
||||
for file in *.tar.gz; do
|
||||
sha256sum $file > $file.sha256
|
||||
done
|
||||
|
||||
- name: Extract ChangeLog entry ...
|
||||
run: |
|
||||
awk '/^-----*$/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|
||||
|head -n -1 > release.md
|
||||
cat release.md
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: Infix ${{ github.ref_name }}
|
||||
@@ -139,6 +148,7 @@ jobs:
|
||||
makeLatest: ${{ steps.rel.outputs.latest }}
|
||||
bodyFile: release.md
|
||||
artifacts: "*.tar.gz*"
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
cat <<EOF >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -100,7 +100,7 @@ and testing, but can also be used for evaluation and demo purposes. For
|
||||
more information, see: [Infix in Virtual Environments](doc/virtual.md).
|
||||
|
||||
> See the [GitHub Releases](https://github.com/kernelkit/infix/releases)
|
||||
> page for our pre-built images. The *Latest Build* has the bleeding
|
||||
> page for our pre-built images. The *[Latest Build][]* has bleeding
|
||||
> edge images, if possible we recommend using a versioned release.
|
||||
>
|
||||
> For *customer specific builds* of Infix, see your product repository.
|
||||
@@ -116,6 +116,7 @@ more information, see: [Infix in Virtual Environments](doc/virtual.md).
|
||||
[1]: https://buildroot.org/
|
||||
[2]: https://www.sysrepo.org/
|
||||
[3]: doc/cli/introduction.md
|
||||
[Latest Build]: https://github.com/kernelkit/infix/releases/tag/latest
|
||||
[License]: https://en.wikipedia.org/wiki/GPL_license
|
||||
[License Badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg
|
||||
[GitHub]: https://github.com/kernelkit/infix/actions/workflows/build.yml/
|
||||
|
||||
+4
-64
@@ -1,67 +1,7 @@
|
||||
aarch64
|
||||
=======
|
||||
|
||||
Microchip SparX-5i PCB135 (eMMC)
|
||||
--------------------------------
|
||||
|
||||
At present, only FIT images are supported via the SparX-5i eval
|
||||
board's U-Boot, which must contain a valid load address. If you are
|
||||
using this board, after selecting your base configuration, run the
|
||||
following command to supplement the existing config with the required
|
||||
FIT options:
|
||||
|
||||
make board-enable-sparx-fit
|
||||
|
||||
### Unbricking
|
||||
|
||||
1. Don't load a corrupt bootloader to begin with
|
||||
2. Done
|
||||
|
||||
If, for some reason, you didn't manage to follow step 1, you can use
|
||||
the `FLASH_PROG`(`J4`) connector on the board to access the SPI flash
|
||||
directly.
|
||||
|
||||
Using a [Bus Blaster][BB3] in combination with [dangerspi][dangerspi],
|
||||
you can load a new bootloader. The schematic below details how to
|
||||
connect the Bus Blaster to the board, but the concept should be
|
||||
portable to any debugger/device based around an FTDI2232 chip.
|
||||
|
||||
```
|
||||
Bus Blaster: FLASH_PROG (J4):
|
||||
.---. .---.
|
||||
VTG >o o| VTG SCK >o o| GND
|
||||
TRST |o o| GND MISO |o o| #RESET_FLASH
|
||||
TDI |o o| GND o o| 3V3
|
||||
TMS |o o| GND #CS |o o| #SYSRESET
|
||||
TCK o o| GND MOSI |o o| GND
|
||||
RTCK o o| GND '---'
|
||||
TDO |o o| GND
|
||||
TSRST |o o| GND
|
||||
DBGRQ |o o| GND
|
||||
DBGACK |o o| GND
|
||||
'---'
|
||||
```
|
||||
|
||||
| Bus Blaster | FLASH_PROG |
|
||||
|-------------|----------------|
|
||||
| `VTG` | `3V3` |
|
||||
| `GND` | `GND` |
|
||||
| | |
|
||||
| `VTG` | `#RESET_FLASH` |
|
||||
| `GND` | `#SYSRESET` |
|
||||
| | |
|
||||
| `TDI` | `MOSI` |
|
||||
| `TMS` | `#CS` |
|
||||
| `TCK` | `SCK` |
|
||||
| `TDO` | `MISO` |
|
||||
|
||||
With the cable in place, build U-Boot with the correct configuration:
|
||||
|
||||
make fireant_boot_defconfig && make
|
||||
|
||||
To flash it to the board, connect the cable to `J4` and run:
|
||||
|
||||
make board-sparx-flash-uboot
|
||||
|
||||
[BB3]: http://dangerousprototypes.com/docs/Bus_Blaster#Bus_Blaster_v3
|
||||
[dangerspi]: https://github.com/wkz/dangerspi
|
||||
Board Specific Documentation
|
||||
----------------------------
|
||||
- [Marvell CN9130-CRB](cn9130-crb/)
|
||||
- [Microchip SparX-5i PCB135 (eMMC)](sparx5-pcb135/)
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
Marvell CN9130-CRB
|
||||
==================
|
||||
|
||||
## Build instructions
|
||||
|
||||
### Bootloader
|
||||
|
||||
Build the bootloader from the supplied `defconfig`. It might be useful
|
||||
to build in a separate output directory if you want to build Infix
|
||||
from the same working tree later:
|
||||
|
||||
make O=$(pwd)/x-cn9130-boot cn9130_crb_boot_defconfig
|
||||
cd x-cn9130-boot
|
||||
make
|
||||
|
||||
The artifact of interest is called `flash-image.bin`, which will be
|
||||
located in the `images/` directory once the build completes.
|
||||
|
||||
|
||||
### Infix
|
||||
|
||||
> If you do not want to build Infix from source, feel free to use a pre-built [release]
|
||||
|
||||
The standard `aarch64_defconfig` is compatible with this board:
|
||||
|
||||
make O=$(pwd)/x-aarch64 aarch64_defconfig
|
||||
cd x-aarch64
|
||||
make
|
||||
|
||||
Two artifacts from the `images/` directory of this build are required
|
||||
to provision a new board:
|
||||
|
||||
- `rootfs.itb`: Netbootable image
|
||||
- `infix-aarch64.pkg`: Standard upgrade bundle
|
||||
|
||||
## Provisioning
|
||||
|
||||
The overall provisioning flow, in which each step in described in
|
||||
details in the following sections, is as follows:
|
||||
|
||||
- Strap board to boot from SPI FLASH
|
||||
- Load `flash-image.bin` over UART
|
||||
- Burn `flash-image.bin` to SPI FLASH
|
||||
- Netboot `rootfs.itb`
|
||||
- Run Infix's built-in provisioning script
|
||||
- Reboot, now booting from the primary partition of the SD-card
|
||||
|
||||
#### Strap Board to Boot from SPI FLASH
|
||||
|
||||
By default, the board is strapped to boot from eMMC. However, Infix
|
||||
assumes that the board will boot from SPI FLASH. Therefore we have to
|
||||
ensure that the DIP switches of `SW2` on the board selects a
|
||||
`BOOT_MODE` of `0x32`, meaning that the switches on positions 4, 3,
|
||||
and 1 should be enabled (i.e. these need to be tied to ground):
|
||||
|
||||
```
|
||||
.-----. .-----. .-----.
|
||||
| | | | | PWR |
|
||||
| SIM | | uSD | | |
|
||||
| | | | '-----'
|
||||
'-----' '-----'
|
||||
|
||||
|
|
||||
v
|
||||
.-----. .-----.
|
||||
| SW1 | | SW2 |
|
||||
'-----' '-----'
|
||||
.--------------------------.
|
||||
| |
|
||||
| |
|
||||
| CN9130 |
|
||||
```
|
||||
|
||||
#### UART Boot U-Boot
|
||||
|
||||
Make sure that:
|
||||
- [mvebu64boot] is installed and available in your shell's `$PATH`
|
||||
- No other program is attached to `ttyUSB0`
|
||||
- No power is applied to the board
|
||||
|
||||
1. Start `mvebu64boot`:
|
||||
|
||||
mvebu64boot -b /path/to/flash-image.bin /dev/ttyUSB0
|
||||
|
||||
2. Apply power
|
||||
|
||||
As soon as `mvebu64boot` completes, attach to the serial port,
|
||||
e.g. using `screen(1)`, or `console(1)` and stop the normal boot
|
||||
process by hitting any key.
|
||||
|
||||
#### Burn U-Boot to SPI FLASH
|
||||
|
||||
Make sure that:
|
||||
- `eth1` is connected to a machine which serves `flash-image.bin` over
|
||||
TFTP
|
||||
- U-Boot can reach the TFTP server. If the neighboring machine is also
|
||||
set up as a DHCP server, simply run the command `dhcp -`
|
||||
|
||||
To burn the bootloader to SPI FLASH, run the `bubt` command:
|
||||
|
||||
bubt flash-image.bin
|
||||
|
||||
Once the command completes, reset the board to verify that it can now
|
||||
boot unassisted:
|
||||
|
||||
reset
|
||||
|
||||
#### Boot up `rootfs.itb`
|
||||
|
||||
U-Boot will automatically fallback to netboot since the SD-card is
|
||||
still blank. Make sure that the PC provides the path to `rootfs.itb`
|
||||
in DHCP option 67 ("bootfile").
|
||||
|
||||
#### Install Firmware
|
||||
|
||||
Login as `admin`/`admin`, setup networking to the PC, ensure that the date on
|
||||
the device is reasonably correct, and run the provisioning script:
|
||||
|
||||
admin@infix:~$ sudo -i
|
||||
root@infix:~$ udhcpc -i e28
|
||||
root@infix:~$ date -us YYYY-MM-DD
|
||||
root@infix:~$ /libexec/infix/prod/provision tftp://<PC-IP>/infix-aarch64.pkg /dev/mmcblk0
|
||||
|
||||
After successful completion, the device is fully provisioned. On the
|
||||
next boot, the device will boot of its own accord from the primary
|
||||
SD-card partition.
|
||||
|
||||
> If possible, serve `infix-aarch64.pkg` over HTTP instead, as
|
||||
> libcurl's TFTP implementation is quite slow.
|
||||
|
||||
[release]: https://github.com/kernelkit/infix/releases
|
||||
[mvebu64boot]: https://github.com/addiva-elektronik/mvebu64boot
|
||||
@@ -16,36 +16,7 @@ run ixboot
|
||||
";
|
||||
boot_targets = "mmc1";
|
||||
ethprime = "eth1";
|
||||
|
||||
/* Uncomment this if you're debugging U-Boot
|
||||
*
|
||||
* This will allow you to break out of the
|
||||
* normal boot flow and into the interactive
|
||||
* console.
|
||||
*
|
||||
* To upgrade U-Boot itself, simply set the
|
||||
* `bootfile` variable to the path of
|
||||
* `flash-image.bin` on your TFTP server, then
|
||||
* issue `run ixupgradeboot`.
|
||||
*/
|
||||
/* bootdelay = "2"; */
|
||||
/* ixupgradeboot = " */
|
||||
/* dhcp */
|
||||
/* setexpr fileblks ${filesize} + 0x1ff */
|
||||
/* setexpr fileblks ${fileblks} / 0x200 */
|
||||
|
||||
/* mmc dev 1 */
|
||||
/* part start mmc 1 boot bootstart */
|
||||
/* part size mmc 1 boot bootsize */
|
||||
|
||||
|
||||
/* mmc erase ${bootstart} ${bootsize} */
|
||||
/* mmc write ${fileaddr} ${bootstart} ${fileblks} */
|
||||
/* "; */
|
||||
bootdelay = "1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* &cp0_eth0 { */
|
||||
/* phy-mode = "10gbase-r"; */
|
||||
/* }; */
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi cn9130-crb-env.dtsi"
|
||||
CONFIG_SYS_PROMPT="(cn9130-crb) "
|
||||
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
# CONFIG_ENV_IS_IN_MMC is not set
|
||||
CONFIG_MVEBU_SPI_BOOT=y
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020 Marvell International Ltd.
|
||||
*/
|
||||
|
||||
#include "cn9130-crb.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Marvell Armada CN9130-CRB-A";
|
||||
|
||||
chosen {
|
||||
infix {
|
||||
/* "admin" */
|
||||
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
|
||||
usb-ports = <&cp0_usb3_1>;
|
||||
usb-port-names = "USB";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cp0_pcie0 {
|
||||
status = "okay";
|
||||
num-lanes = <4>;
|
||||
num-viewport = <8>;
|
||||
/* Generic PHY, providing serdes lanes */
|
||||
phys = <&cp0_comphy0 0
|
||||
&cp0_comphy1 0
|
||||
&cp0_comphy2 0
|
||||
&cp0_comphy3 0>;
|
||||
iommu-map =
|
||||
<0x0 &smmu 0x480 0x20>,
|
||||
<0x100 &smmu 0x4a0 0x20>,
|
||||
<0x200 &smmu 0x4c0 0x20>;
|
||||
iommu-map-mask = <0x031f>;
|
||||
};
|
||||
|
||||
&cp0_usb3_0 {
|
||||
status = "okay";
|
||||
usb-phy = <&cp0_usb3_0_phy0>;
|
||||
phy-names = "usb";
|
||||
};
|
||||
|
||||
&cp0_usb3_1 {
|
||||
status = "okay";
|
||||
usb-phy = <&cp0_usb3_0_phy1>;
|
||||
phy-names = "usb";
|
||||
};
|
||||
|
||||
&cp0_eth2 {
|
||||
status = "okay";
|
||||
phy-mode = "2500base-x";
|
||||
};
|
||||
|
||||
&cp0_pinctrl {
|
||||
cp0_expander0_pins: cp0-expander-pins-0 {
|
||||
marvell,pins = "mpp39";
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
};
|
||||
|
||||
&expander0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cp0_expander0_pins>;
|
||||
interrupt-parent = <&cp0_gpio2>;
|
||||
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells=<2>;
|
||||
microchip,irq-mirror;
|
||||
};
|
||||
@@ -178,6 +178,7 @@ CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_CLS_BASIC=y
|
||||
CONFIG_NET_CLS_BPF=y
|
||||
CONFIG_NET_CLS_FLOWER=y
|
||||
CONFIG_DCB=y
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
CONFIG_MPLS=y
|
||||
CONFIG_NET_MPLS_GSO=y
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
Microchip SparX-5i PCB135 (eMMC)
|
||||
================================
|
||||
|
||||
At present, only FIT images are supported via the SparX-5i eval
|
||||
board's U-Boot, which must contain a valid load address. If you are
|
||||
using this board, after selecting your base configuration, run the
|
||||
following command to supplement the existing config with the required
|
||||
FIT options:
|
||||
|
||||
make board-enable-sparx-fit
|
||||
|
||||
## Unbricking
|
||||
|
||||
1. Don't load a corrupt bootloader to begin with
|
||||
2. Done
|
||||
|
||||
If, for some reason, you didn't manage to follow step 1, you can use
|
||||
the `FLASH_PROG`(`J4`) connector on the board to access the SPI flash
|
||||
directly.
|
||||
|
||||
Using a [Bus Blaster][BB3] in combination with [dangerspi][dangerspi],
|
||||
you can load a new bootloader. The schematic below details how to
|
||||
connect the Bus Blaster to the board, but the concept should be
|
||||
portable to any debugger/device based around an FTDI2232 chip.
|
||||
|
||||
```
|
||||
Bus Blaster: FLASH_PROG (J4):
|
||||
.---. .---.
|
||||
VTG >o o| VTG SCK >o o| GND
|
||||
TRST |o o| GND MISO |o o| #RESET_FLASH
|
||||
TDI |o o| GND o o| 3V3
|
||||
TMS |o o| GND #CS |o o| #SYSRESET
|
||||
TCK o o| GND MOSI |o o| GND
|
||||
RTCK o o| GND '---'
|
||||
TDO |o o| GND
|
||||
TSRST |o o| GND
|
||||
DBGRQ |o o| GND
|
||||
DBGACK |o o| GND
|
||||
'---'
|
||||
```
|
||||
|
||||
| Bus Blaster | FLASH_PROG |
|
||||
|-------------|----------------|
|
||||
| `VTG` | `3V3` |
|
||||
| `GND` | `GND` |
|
||||
| | |
|
||||
| `VTG` | `#RESET_FLASH` |
|
||||
| `GND` | `#SYSRESET` |
|
||||
| | |
|
||||
| `TDI` | `MOSI` |
|
||||
| `TMS` | `#CS` |
|
||||
| `TCK` | `SCK` |
|
||||
| `TDO` | `MISO` |
|
||||
|
||||
With the cable in place, build U-Boot with the correct configuration:
|
||||
|
||||
make fireant_boot_defconfig && make
|
||||
|
||||
To flash it to the board, connect the cable to `J4` and run:
|
||||
|
||||
make board-sparx-flash-uboot
|
||||
|
||||
[BB3]: http://dangerousprototypes.com/docs/Bus_Blaster#Bus_Blaster_v3
|
||||
[dangerspi]: https://github.com/wkz/dangerspi
|
||||
@@ -157,6 +157,12 @@ rw_args()
|
||||
{
|
||||
[ "$CONFIG_QEMU_RW" ] || return
|
||||
|
||||
if ! [ -f "aux.ext4" ]; then
|
||||
dd if=/dev/zero of="aux.ext4" bs=1M count=1 >/dev/null 2>&1
|
||||
mkfs.ext4 -L aux "aux.ext4" >/dev/null 2>&1
|
||||
fi
|
||||
echo -n "-drive file=aux.ext4,if=virtio,format=raw,bus=0,unit=3 "
|
||||
|
||||
if ! [ -f "$CONFIG_QEMU_RW" ]; then
|
||||
dd if=/dev/zero of="$CONFIG_QEMU_RW" bs=16M count=1 >/dev/null 2>&1
|
||||
mkfs.ext4 -L cfg "$CONFIG_QEMU_RW" >/dev/null 2>&1
|
||||
@@ -198,10 +204,10 @@ net_args()
|
||||
echo -n "-fw_cfg name=opt/mactab,file=$mactab "
|
||||
|
||||
if [ "$CONFIG_QEMU_NET_BRIDGE" = "y" ]; then
|
||||
echo -n "-netdev bridge,id=e0,br=$CONFIG_QEMU_NET_BRIDGE_DEV "
|
||||
net_dev_args 0
|
||||
echo -n "-netdev bridge,id=e1,br=$CONFIG_QEMU_NET_BRIDGE_DEV "
|
||||
net_dev_args 1
|
||||
elif [ "$CONFIG_QEMU_NET_TAP" = "y" ]; then
|
||||
for i in $(seq 0 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
|
||||
for i in $(seq 1 $(($CONFIG_QEMU_NET_TAP_N))); do
|
||||
echo -n "-netdev tap,id=e$i,ifname=qtap$i "
|
||||
net_dev_args $i
|
||||
done
|
||||
@@ -209,8 +215,8 @@ net_args()
|
||||
local useropts=
|
||||
[ "$CONFIG_QEMU_NET_USER_OPTS" ] && useropts=",$CONFIG_QEMU_NET_USER_OPTS"
|
||||
|
||||
echo -n "-netdev user,id=e0${useropts} "
|
||||
net_dev_args 0
|
||||
echo -n "-netdev user,id=e1${useropts} "
|
||||
net_dev_args 1
|
||||
else
|
||||
echo -n "-nic none"
|
||||
fi
|
||||
@@ -306,10 +312,10 @@ generate_dot()
|
||||
{
|
||||
[ "$CONFIG_QEMU_NET_TAP" = "y" ] || return
|
||||
|
||||
hostports="<qtap0> qtap0"
|
||||
targetports="<e0> e0"
|
||||
edges="host:qtap0 -- target:e0 [kind=mgmt];"
|
||||
for tap in $(seq 1 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
|
||||
hostports="<qtap1> qtap1"
|
||||
targetports="<e1> e1"
|
||||
edges="host:qtap1 -- target:e1 [kind=mgmt];"
|
||||
for tap in $(seq 2 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
|
||||
hostports="$hostports | <qtap$tap> qtap$tap "
|
||||
targetports="$targetports | <e$tap> e$tap "
|
||||
edges="$edges host:qtap$tap -- target:e$tap;"
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Generate a self signed certificate with unlimited expire time
|
||||
|
||||
import argparse
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Generate private key
|
||||
private_key = rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=2048,
|
||||
backend=default_backend()
|
||||
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Generate a self signed certificate")
|
||||
parser.add_argument('--country', required=True, help="Set country")
|
||||
parser.add_argument('--state', required=True, help="Set state or province name")
|
||||
parser.add_argument('--city', required=True, help="Set city name")
|
||||
parser.add_argument('--organisation', required=True, help="Set organisation name")
|
||||
parser.add_argument('--organisation-unit', required=True, help="Set organisation unit name")
|
||||
parser.add_argument('--common-name', required=True, help="Set common name")
|
||||
parser.add_argument('--out-certificate', required=True, help="Output certificate")
|
||||
parser.add_argument('--out-key', required=True, help="Output key")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Builder for certificate
|
||||
subject = issuer = x509.Name([
|
||||
x509.NameAttribute(NameOID.COUNTRY_NAME, args.country),
|
||||
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, args.state),
|
||||
x509.NameAttribute(NameOID.LOCALITY_NAME, args.city),
|
||||
x509.NameAttribute(NameOID.ORGANIZATION_NAME, args.organisation),
|
||||
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, args.organisation_unit),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, args.common_name),
|
||||
])
|
||||
certificate = x509.CertificateBuilder().subject_name(
|
||||
subject
|
||||
).issuer_name(
|
||||
issuer
|
||||
).public_key(
|
||||
private_key.public_key()
|
||||
).serial_number(
|
||||
x509.random_serial_number()
|
||||
).not_valid_before(
|
||||
datetime(2000, 1, 1)
|
||||
).not_valid_after(
|
||||
datetime(9999, 1, 1)
|
||||
).add_extension(
|
||||
x509.SubjectAlternativeName([x509.DNSName(args.common_name)]),
|
||||
critical=False,
|
||||
).sign(private_key, hashes.SHA256(), default_backend())
|
||||
|
||||
# Serialize certificate and private key
|
||||
with open(args.out_certificate, "wb") as f:
|
||||
f.write(certificate.public_bytes(serialization.Encoding.PEM))
|
||||
with open(args.out_key, "wb") as f:
|
||||
f.write(private_key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
))
|
||||
@@ -19,4 +19,4 @@ LABEL=aux /mnt/aux auto noatime,nodiratime,noauto 0 0
|
||||
LABEL=var /mnt/var auto noatime,nodiratime,noauto 0 0
|
||||
LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto 0 0
|
||||
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
|
||||
/libexec/infix/mnt# /cfg helper none 0 0
|
||||
/libexec/infix/mnt# /cfg helper none 0 0
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
0 unspec
|
||||
1 kernel_lo
|
||||
2 kernel_ra
|
||||
3 kernel_ll
|
||||
4 static
|
||||
5 dhcp
|
||||
6 random
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
configure ports dsa0 lldp status disabled
|
||||
@@ -0,0 +1 @@
|
||||
UsePAM yes
|
||||
@@ -0,0 +1,10 @@
|
||||
Reserved facilities for logging in various subsystems:
|
||||
|
||||
- local0: rauc
|
||||
- local1: containers
|
||||
- local2:
|
||||
- local3:
|
||||
- local5:
|
||||
- local6: reserved
|
||||
- local7: nginx
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
import importlib.machinery
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
onieprom = importlib.machinery.SourceFileLoader("onieprom","/bin/onieprom").load_module()
|
||||
|
||||
SYSTEM_JSON = "/run/system.json"
|
||||
KKIT_IANA_PEM = 61046
|
||||
|
||||
class DTSystem:
|
||||
@@ -233,8 +234,36 @@ def vpd_inject(out, vpds):
|
||||
out["factory-password-hash"] = pwhash
|
||||
break
|
||||
|
||||
def qemu_base_mac():
|
||||
"""Find MAC address of first non-loopback interface, subtract with 1"""
|
||||
base_path = '/sys/class/net'
|
||||
interfaces = []
|
||||
|
||||
for iface in os.listdir(base_path):
|
||||
if iface == 'lo':
|
||||
continue
|
||||
try:
|
||||
# pylint: disable=invalid-name
|
||||
with open(os.path.join(base_path, iface, 'address'), 'r', encoding='ascii') as f:
|
||||
mac = f.read().strip()
|
||||
interfaces.append((mac, iface))
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
|
||||
if interfaces:
|
||||
interfaces.sort()
|
||||
mac = interfaces[0][0]
|
||||
mac = int(mac.replace(':', ''), 16)
|
||||
mac -= 1
|
||||
mac %= 1 << 48
|
||||
mac = ':'.join(f"{(mac >> 8 * i) & 0xff:02x}" for i in range(5, -1, -1))
|
||||
return mac
|
||||
|
||||
return None
|
||||
|
||||
def probe_qemusystem(out):
|
||||
ADMINHASH = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"
|
||||
"""Probe Qemu based test systems and 'make run'"""
|
||||
admin_hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"
|
||||
|
||||
qsys = QEMUSystem()
|
||||
vpds = qsys.vpds()
|
||||
@@ -244,6 +273,7 @@ def probe_qemusystem(out):
|
||||
for (attr, default) in (
|
||||
("vendor", "QEMU"),
|
||||
("product-name", "VM"),
|
||||
("mac-address", qemu_base_mac()),
|
||||
):
|
||||
if not out[attr]:
|
||||
out[attr] = default
|
||||
@@ -252,13 +282,14 @@ def probe_qemusystem(out):
|
||||
not out["vpd"]["product"]["available"]:
|
||||
# Virtual instance without VPD emulation, fallback to
|
||||
# admin/admin
|
||||
out["factory-password-hash"] = ADMINHASH
|
||||
out["factory-password-hash"] = admin_hash
|
||||
|
||||
# Let others react to the fact that we are running in QEMU
|
||||
subprocess.run("initctl -nbq cond set qemu".split())
|
||||
subprocess.run("initctl -nbq cond set qemu".split(), check=False)
|
||||
return 0
|
||||
|
||||
def probe_dtsystem(out):
|
||||
"""Probe DTS based system, expects a VPD in ONIE PROM format."""
|
||||
dtsys = DTSystem()
|
||||
vpds = dtsys.infix_vpds()
|
||||
dtsys.infix_usb_devices(out)
|
||||
@@ -296,11 +327,15 @@ def main():
|
||||
return err
|
||||
|
||||
if not out["factory-password-hash"]:
|
||||
sys.stdout.write("\n\n\033[31mCRITICAL BOOTSTRAP ERROR\nNO FACTORY PASSWORD FOUND\033[0m\n\n")
|
||||
sys.stdout.write("\n\n\033[31mCRITICAL BOOTSTRAP ERROR\n" +
|
||||
"NO FACTORY PASSWORD FOUND\033[0m\n\n")
|
||||
err = 1
|
||||
|
||||
json.dump(out, open("/run/system.json", "w"))
|
||||
os.chmod("/run/system.json", 0o444)
|
||||
os.umask(0o337)
|
||||
# pylint: disable=invalid-name
|
||||
with open(SYSTEM_JSON, "w", encoding="ascii") as f:
|
||||
json.dump(out, f)
|
||||
shutil.chown(SYSTEM_JSON, user="root", group="wheel")
|
||||
return err
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
. /etc/partion-uuid
|
||||
. /etc/partition-uuid
|
||||
|
||||
disk=$1
|
||||
bootoffs=$2
|
||||
@@ -28,11 +28,11 @@ else
|
||||
fi
|
||||
|
||||
sgdisk \
|
||||
-o \
|
||||
-Z \
|
||||
-n1:${bootoffs}:+${bootsize} -t1:8301 -c1:boot \
|
||||
-n2::+${auxsize} -t2:8301 -c2:aux -u2:${AUX_UUID}\
|
||||
-n2::+${auxsize} -t2:8301 -c2:aux -u2:${AUX_UUID} \
|
||||
-n3::+${imgsize} -t3:8300 -c3:primary -u3:${PRIMARY_UUID} \
|
||||
-n4::+${imgsize} -t4:8300 -c4:secondary -u4:${SECONDARY_UUID}\
|
||||
-n4::+${imgsize} -t4:8300 -c4:secondary -u4:${SECONDARY_UUID} \
|
||||
-n5::+${cfgsize} -t5:8302 -c5:cfg \
|
||||
-n6:: -t6:8310 -c6:var \
|
||||
-p \
|
||||
|
||||
+22
-21
@@ -1,26 +1,27 @@
|
||||
# This is a bit awkward. If you know about a more straight forward way
|
||||
# of doing this, please simplify.
|
||||
#
|
||||
# U-Boot needs the public part of the signing key to be preprocessed
|
||||
# and then inserted into its control DT. mkimage(1) can perform this
|
||||
# conversion, but only as a side-effect of building/signing an FIT
|
||||
# image. Since we might not always be doing that, e.g. when only
|
||||
# building a hardware specific bootloader, we build a dummy FIT just
|
||||
# to get the key information into a DTB, which we then convert back to
|
||||
# a .dtsi and install in the U-Boot build tree. This will then be
|
||||
# built in to the final U-Boot image's control DT via the
|
||||
# CONFIG_DEVICE_TREE_INCLUDES option (see extras.config).
|
||||
define uboot-add-pubkey
|
||||
$(call IXMSG,"Installing trusted key $1")
|
||||
$(HOST_DIR)/bin/fdt_add_pubkey \
|
||||
-a sha256,rsa$(shell \
|
||||
openssl x509 -text -noout -in $1 | \
|
||||
grep 'Public-Key: ' | \
|
||||
sed -e 's/.*(\(.*\) bit)/\1/') \
|
||||
-k $(dir $1) \
|
||||
-n $(notdir $(basename $1)) \
|
||||
-r image \
|
||||
$2
|
||||
endef
|
||||
|
||||
# U-Boot has its own public key format which has to be stored in its
|
||||
# control DT. So we collect all of the trusted keys, convert them to
|
||||
# the required format, and write the result to infix-key.dtb in the
|
||||
# U-Boot build tree. This will then be built in to the final U-Boot
|
||||
# image's control DT via the CONFIG_DEVICE_TREE_INCLUDES option (see
|
||||
# extras.config).
|
||||
define UBOOT_PRE_BUILD_INSTALL_KEY
|
||||
@$(call IXMSG,"Installing Infix signing key ($(SIGN_KEY))")
|
||||
$(HOST_DIR)/bin/dtc <(echo '/dts-v1/; / { signature {}; };') >$(@D)/infix-key.dtb
|
||||
$(HOST_DIR)/bin/mkimage \
|
||||
-k $(SIGN_KEY) \
|
||||
-f $(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/key-dummy.its \
|
||||
-K $(@D)/infix-key.dtb \
|
||||
$(if $(SIGN_SRC_PKCS11),-N pkcs11) \
|
||||
-r \
|
||||
$(@D)/key-dummy.itb
|
||||
rm $(@D)/key-dummy.itb
|
||||
$(foreach key, \
|
||||
$(call qstrip,$(TRUSTED_KEYS_DEVELOPMENT_PATH)) $(call qstrip,$(TRUSTED_KEYS_EXTRA_PATH)),\
|
||||
$(call uboot-add-pubkey,$(key),$(@D)/infix-key.dtb))
|
||||
$(HOST_DIR)/bin/dtc -I dtb -O dts \
|
||||
<$(@D)/infix-key.dtb \
|
||||
| sed -e 's:/dts-v[0-9]\+/;::' >$(@D)/arch/$(UBOOT_ARCH)/dts/infix-key.dtsi
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
test-dir := $(BR2_EXTERNAL_INFIX_PATH)/test
|
||||
INFIX_TESTS ?= $(test-dir)/case/all.yaml
|
||||
|
||||
test-env = $(test-dir)/env \
|
||||
-f $(BINARIES_DIR)/infix-x86_64.img \
|
||||
-f $(BINARIES_DIR)/infix-x86_64-disk.img \
|
||||
-f $(BINARIES_DIR)/OVMF.fd \
|
||||
-p $(BINARIES_DIR)/infix-x86_64.pkg \
|
||||
$(1) $(2)
|
||||
|
||||
test-env-qeneth = $(call test-env,-q $(test-dir)/virt/quad,$(1))
|
||||
test-env-run = $(call test-env,-C -t $(BINARIES_DIR)/qemu.dot,$(1))
|
||||
|
||||
test test-qeneth:
|
||||
$(call test-env-qeneth,\
|
||||
$(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py \
|
||||
$(INFIX_TESTS))
|
||||
test-sh test-qeneth-sh:
|
||||
$(call test-env-qeneth,-i /bin/sh)
|
||||
|
||||
test-run: | ~/.infix-test-venv
|
||||
$(call test-env-run,\
|
||||
$(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py \
|
||||
$(INFIX_TESTS))
|
||||
test-run-sh: | ~/.infix-test-venv
|
||||
$(call test-env-run,/bin/sh)
|
||||
|
||||
test-run-play: | ~/.infix-test-venv
|
||||
$(call test-env-run,$(test-dir)/case/meta/play.py)
|
||||
|
||||
~/.infix-test-venv:
|
||||
$(test-dir)/docker/init-venv.sh $(test-dir)/docker/pip-requirements.txt
|
||||
|
||||
.PHONY: test test-sh test-qeneth test-qeneth-sh test-run test-run-sh test-run-play
|
||||
|
||||
@@ -42,14 +42,14 @@ export secondary
|
||||
|
||||
submenu "primary" "$log" {
|
||||
set slot="$1"
|
||||
set append="console=hvc0 root=PARTLABEL=$slot $2"
|
||||
set append="console=ttyS0 console=hvc0 root=PARTLABEL=$slot $2"
|
||||
set root="($primary)"
|
||||
source /boot/grub/grub.cfg
|
||||
}
|
||||
|
||||
submenu "secondary" "$log" {
|
||||
set slot="$1"
|
||||
set append="console=hvc0 root=PARTLABEL=$slot $2"
|
||||
set append="console=ttyS0 console=hvc0 root=PARTLABEL=$slot $2"
|
||||
set root="($secondary)"
|
||||
source /boot/grub/grub.cfg
|
||||
}
|
||||
@@ -63,7 +63,7 @@ submenu "net" "$log" {
|
||||
set root=(initrd)
|
||||
|
||||
set slot="$1"
|
||||
set append="console=hvc0 root=/dev/ram0 ramdisk_size=65536 $2"
|
||||
set append="console=ttyS0 console=hvc0 qroot=/dev/ram0 ramdisk_size=65536 $2"
|
||||
source /boot/grub/grub.cfg
|
||||
else
|
||||
if [ -z "$net_efinet0_dhcp_next_server" ]; then
|
||||
|
||||
+1
-1
Submodule buildroot updated: 42182f9bef...1d96daca15
@@ -54,7 +54,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
@@ -63,6 +62,8 @@ BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
@@ -130,6 +131,7 @@ INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -142,6 +144,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
@@ -155,6 +158,5 @@ BR2_PACKAGE_LIBINPUT=y
|
||||
DISK_IMAGE_BOOT_BIN=y
|
||||
GNS3_APPLIANCE_RAM=512
|
||||
GNS3_APPLIANCE_IFNUM=10
|
||||
BR2_PER_PACKAGE_DIRECTORIES=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
|
||||
@@ -16,6 +16,8 @@ BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image
|
||||
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
|
||||
# BR2_TARGET_ROOTFS_TAR is not set
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE=y
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE="v2.9"
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE_PLATFORM="t9130"
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE_FIP=y
|
||||
BR2_TARGET_ARM_TRUSTED_FIRMWARE_UBOOT_AS_BL33=y
|
||||
@@ -36,8 +38,8 @@ BR2_PACKAGE_HOST_RAUC=y
|
||||
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
|
||||
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
|
||||
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
# SIGN_ENABLED is not set
|
||||
DISK_IMAGE=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
DISK_IMAGE_BOOT_BIN=y
|
||||
DISK_IMAGE_BOOT_DATA="${BINARIES_DIR}/flash-image.bin"
|
||||
DISK_IMAGE_BOOT_OFFSET=0x00200000
|
||||
|
||||
@@ -13,7 +13,7 @@ BR2_TARGET_GENERIC_HOSTNAME="infix"
|
||||
BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit"
|
||||
BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/xattrs"
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
@@ -22,8 +22,8 @@ BR2_SYSTEM_DHCP="eth0"
|
||||
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_CA"
|
||||
BR2_GENERATE_LOCALE="en_US en_CA"
|
||||
BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh"
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh support/scripts/genimage.sh"
|
||||
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/genimage.cfg"
|
||||
BR2_LINUX_KERNEL=y
|
||||
@@ -64,7 +64,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
@@ -74,6 +73,8 @@ BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
@@ -159,6 +160,7 @@ INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -171,6 +173,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
|
||||
@@ -49,7 +49,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
@@ -58,6 +57,8 @@ BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
@@ -133,6 +134,7 @@ INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -145,6 +147,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
@@ -156,6 +159,5 @@ BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
GNS3_APPLIANCE_RAM=512
|
||||
GNS3_APPLIANCE_IFNUM=10
|
||||
BR2_PER_PACKAGE_DIRECTORIES=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
|
||||
+175
-25
@@ -4,23 +4,114 @@ Change Log
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[v24.03.0][UNRELEASED]
|
||||
-------------------------
|
||||
|
||||
Please note, as of this release the Infix Classic variant has been
|
||||
dropped. This was the legacy, pre-NETCONF, Infix with manual config of
|
||||
the system using a persistent `/etc`. It may be resurrected later as a
|
||||
separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
|
||||
> Development in progress, for daily updates see the team board:
|
||||
> <https://github.com/orgs/kernelkit/projects/3/views/2>
|
||||
[v24.05.0][UNRELEASED]
|
||||
----------------------
|
||||
|
||||
### Changes
|
||||
- Bump the base Linux kernel version to 6.6
|
||||
- Default web landing page refactored into a Buildroot package to make
|
||||
it possible to overload from customer repos.
|
||||
- Enable DCB support in aarch64 kernel (for EtherType prio override)
|
||||
- Topology mapper improvements, including option for deterministic
|
||||
reproduction of logical to physical mappings
|
||||
- New version of `gencert` tool, for self signed HTTPS certificates.
|
||||
This allows dropping dependency on building a host rust toolchain
|
||||
- Issue #374: add timestamps to dagger .log files
|
||||
- Add small delay in U-Boot to allow stopping boot on reference boards
|
||||
- Document how to provision the bootloader and Infix on a blank board
|
||||
- Use initial hostname from `/etc/os-release` as configuration fallback
|
||||
- Update documentation for use of VETH pairs in containers
|
||||
- Issue #454: create bridges in `factory-config` with IGMP/MLD snooping
|
||||
enabled by default
|
||||
- Add support for optionally running user scripts from
|
||||
`/cfg/user-scripts.d`
|
||||
|
||||
### Fixes
|
||||
- Add missing LICENSE hash for factory reset tool
|
||||
- Fix #424: regression, root user can log in without password
|
||||
- Fix build regressions in `cn9130_crb_boot_defconfig` caused by upgrade
|
||||
to Buildroot v2024.02 and recent multi-key support in RAUC and U-Boot
|
||||
- Fix provisioning script after changes to make GRUB loading more robust
|
||||
- Fix missing `/etc/resolv.conf`, as noticed by `avahi-daemon`, when a
|
||||
user calls `no system` from the CLI
|
||||
- Fix #428: loss of admin account after upgrade to v24.04
|
||||
- Fix #429: failing to load `startup-config` does not trigger the fail
|
||||
secure mode, causing the system to end up in an undefined state
|
||||
- Fix #453: fix inconsistent behavior of custom MAC address (interface
|
||||
`phys-address` for VETH pairs. Allows fixed MAC in containers
|
||||
- Fix locking issue with standard counter groups on `mv88e6xxx`
|
||||
- Fix MDB/ATU synchronization issue from IGMPv3/MLDv2 reports on
|
||||
`mv88e6xxx` systems
|
||||
|
||||
|
||||
[v24.04.2][] - 2024-05-15
|
||||
-------------------------
|
||||
|
||||
### Changes
|
||||
- Add small delay in U-Boot to allow stopping boot on reference boards
|
||||
- Document how to provision the bootloader and Infix on a blank board
|
||||
- Use initial hostname from `/etc/os-release` as configuration fallback
|
||||
|
||||
### Fixes
|
||||
- Fix build regressions in `cn9130_crb_boot_defconfig` caused by upgrade
|
||||
to Buildroot v2024.02 and recent multi-key support in RAUC and U-Boot
|
||||
- Fix provisioning script after changes to make GRUB loading more robust
|
||||
- Fix missing `/etc/resolv.conf`, as noticed by `avahi-daemon`, when a
|
||||
user calls `no system` from the CLI
|
||||
- Fix #428: loss of admin account after upgrade to v24.04
|
||||
- Fix #429: failing to load `startup-config` does not trigger the fail
|
||||
secure mode, causing the system to end up in an undefined state
|
||||
|
||||
|
||||
[v24.04.1][] - 2024-05-03
|
||||
-------------------------
|
||||
|
||||
### Changes
|
||||
- Default web landing page refactored into a Buildroot package to make
|
||||
it possible to overload from customer repos.
|
||||
- Enable DCB support in aarch64 kernel (for EtherType prio override)
|
||||
- Topology mapper improvements, including option for deterministic
|
||||
reproduction of logical to physical mappings
|
||||
- New version of `gencert` tool, for self signed HTTPS certificates.
|
||||
This allows dropping dependency on building a host rust toolchain
|
||||
- Issue #374: add timestamps to dagger .log files
|
||||
|
||||
### Fixes
|
||||
- Add missing LICENSE hash for factory reset tool
|
||||
- Fix #424: regression, root user can log in without password
|
||||
|
||||
|
||||
[v24.04.0][] - 2024-04-30
|
||||
-------------------------
|
||||
|
||||
**News:** this release marks the first major upgrade of the underlying
|
||||
Buildroot to the latest LTS release, v2024.02. This caused a few small
|
||||
regressions in the release cycle, all known issues have been addressed.
|
||||
|
||||
Also worth highlighting, as of this release the Infix Classic variant
|
||||
has been dropped. It was the legacy Infix with manual configuration of
|
||||
the system using a persistent `/etc`. May be resurrected later as a
|
||||
separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
|
||||
Finally, the YANG Status section has been dropped for this release, the
|
||||
idea is to generate supported features from the models and include in
|
||||
future releases.
|
||||
|
||||
### Changes
|
||||
- Bump the base Buildroot version to v2024.02 LTS
|
||||
- Bump the base Linux kernel version to 6.6 LTS
|
||||
- Drop Classic variant to reduce overhead, simplify build & release
|
||||
processes, and focus on NETCONF for Arm64 and Amd64 platforms
|
||||
- Add hostname restrictions to ietf-system, and infix-dhcp-client
|
||||
models. Max 64 characters on Linux systems
|
||||
- Add mDNS CNAME (alias) advertisement, e.g., infix.local in addition to
|
||||
the default infix-c0-ff-ee.local. Note: this is build-specific and
|
||||
does not change if system hostname is changed
|
||||
- Add mDNS browser web application, https://network.local that shows all
|
||||
mDNS devices on the LAN. The network.local mDNS name is also a CNAME,
|
||||
so with multiple Infix devices, only one will act as the mDNS browser
|
||||
- Add temporary landing page to web server for https://infix.local
|
||||
- Add web console using ttyd, https://infix.local:7681
|
||||
- Add support for disabling web services using CLI
|
||||
- The bridge model now has built-in validation of port memberships,
|
||||
i.e., a port must be a bridge member to be used in VLAN filtering
|
||||
- The bridge model only permits the bridge itself to be a tagged
|
||||
@@ -28,8 +119,49 @@ separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
such bridges is to use a VLAN interface on top
|
||||
- A VLAN filtering bridge now validates that no IP address has been
|
||||
set. Use a VLAN interface on top for that (see above)
|
||||
- Container documentation: CLI prompts have been updated to match the
|
||||
examples used in other parts of the User Guide
|
||||
- Restructure documentation, let first page in doc/ be table of contents
|
||||
- Scripting Infix, new document on how to script Infix from remote,
|
||||
e.g., for production or from a container
|
||||
- Introduction, update documentation now that the `admin` user's default
|
||||
login shell is `/bin/bash`
|
||||
- System documentation, first outline of how to change hostname, add
|
||||
users, add system administrator users, changing login banner, change
|
||||
the system default editor, and more
|
||||
- Network documentation, add section on VETH pairs
|
||||
- Container documentation:
|
||||
- CLI prompts have been updated to match the examples used in other
|
||||
parts of the User Guide
|
||||
- Default route example for static container interfaces
|
||||
- How to upgrade a container image
|
||||
- As a follow-up to port speed/duplex/autoneg support added in v24.02,
|
||||
this release ensures flow-control is always disabled on all Ethernet
|
||||
ports, as described in the IEEE Ethernet interfaces YANG model
|
||||
- Add support for core dumps, saving them in `/var/crash`, max one dump
|
||||
per process, for use with future support tarballs
|
||||
- Add support for multicast snooping, both IPv4 (IGMP) and IPv6 (MLD) in
|
||||
bridge setups, including offloading to switchdev
|
||||
- Add support for acting as passive (proxy) or active IGMP querier
|
||||
- Add support for static multicast filters, MAC, IPv4 and IPv6 groups
|
||||
are supported -- multicast snooping must be enabled
|
||||
- Include Buildroot `legal-info` in releases, i.e., licenses, sources
|
||||
with patches, as well as csv files for packages and toolchain
|
||||
- Drop `shell` command from CLI to allow confining users
|
||||
- The CLI `copy` command now allows absolute paths
|
||||
- Local resolver, `dnsmasq`, had port 53 visible from external `nmap`
|
||||
scans, even though it dropped non-local requests, it now only binds to
|
||||
the loopback interface reduce number of externally visible ports
|
||||
- Kernel log messages, of severity error or higher, now log directly to
|
||||
the console. This may cause some annoyance but has been enabled to
|
||||
ease debugging, in particular issues where the system crashes before
|
||||
the syslog daemon has flushed logs to disk. (Logs are still saved to
|
||||
log files as well.)
|
||||
- Issue #325: Add support for multiple administrator users by opening
|
||||
up basic NETCONF ACM support. See documentation for details
|
||||
- Any user can be added to the `admin` NACM group
|
||||
- Any user *not* in the `admin` group is not allowed to have a login
|
||||
shell other than the CLI (or disabled). POSIX shell, e.g., Bash is
|
||||
reserved for system administrators
|
||||
- Issue #327: Remove IPv6LL from bridge port interfaces
|
||||
- Issue #358: translate YANG model's LOWER-LAYER-DOWN -> LINK-DOWN in
|
||||
CLI `show interfaces` command
|
||||
- Issue #360: document factory-config, startup-config, and the various
|
||||
@@ -41,20 +173,12 @@ separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
users to avoid enabling privileged mode
|
||||
- Issue #367: setting date/time over NETCONF now saves system time also
|
||||
to the RTC, which otherwise is only saved on reboot or power-down
|
||||
- Add support for static multicast filters, MAC, IPv4 and IPv6 groups
|
||||
are supported.
|
||||
- Include Buildroot `legal-info` in releases, i.e., licenses, sources
|
||||
with patches, as well as csv files for packages and toolchain
|
||||
- Issue #369: Remove limitation that the routing instance must be
|
||||
named 'default'
|
||||
|
||||
### Fixes
|
||||
- Issue #391 Creating VLAN interface in the CLI with "edit interface vlanN"
|
||||
does not set VLAN id to N.
|
||||
- confd: Fix memory leak when operating on candidate configuration.
|
||||
- CLI: fix VLAN inference for interfaces named `eth0.1`, i.e., VID 1 on
|
||||
lower-layer-if `eth0`. Only affects automatic inference in the CLI,
|
||||
entering the values manually (CLI/NETCONF) not affected by this bug
|
||||
- confd: Fix memory leak when operating on candidate configuration
|
||||
- probe: Fix crash on systems without USB
|
||||
- Reduced syslog errors for accesses no non-existing xpaths
|
||||
- Fix bogus warning about not properly updating `/etc/motd` in new
|
||||
`motd-banner` setting, introduced in v24.02.0
|
||||
@@ -63,8 +187,16 @@ separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
- Fix #328: when setting up a VLAN filtering bridge, the PVID for bridge
|
||||
ports defaulted to 1, making it impossible to set up "tagged-only"
|
||||
ports which drop ingressing untagged traffic
|
||||
- Fix #329: VLAN inference for interfaces named `eth0.1`, i.e., VID 1 on
|
||||
lower-layer-if `eth0`. Only affects automatic inference in the CLI,
|
||||
entering the values manually (CLI/NETCONF) not affected by this bug
|
||||
- Fix #331: inconsistent naming of 'enabled' in infix-routing.yang
|
||||
- Fix #349: minor changes to `bridge-port` settings, like setting `pvid`
|
||||
when you forget it, did not take without a reboot
|
||||
- Fix #353: impossible to remove bridge port with `no bridge-port`
|
||||
- Fix #358: MAC address no longer shown for bridge interfaces in CLI
|
||||
`show interfaces` command
|
||||
- Fix #365: not possible to run `ping` from container
|
||||
- Fix #366: static routes from container host interfaces do not work.
|
||||
Documentation updated with an example
|
||||
- Fix #368: upgrading `oci-archive:/` images fail because system thinks
|
||||
@@ -74,11 +206,25 @@ separate project. Going forward Infix' focus is entirely on NETCONF.
|
||||
declare `network` settings, Infix v23.02 had a late regression that
|
||||
reverted back to the podman default: network behind a CNI bridge
|
||||
(firewalled and NAT:ed, hidden from the rest of the network)
|
||||
- Fix #385: segfault in helper function when disabling the DHCP client
|
||||
- Fix #375: k8s-logger, used for containers, does not exit properly and
|
||||
causes 100% CPU load when container stop or are restarted. Also in
|
||||
this issue: handle ip/route additions to container networks at runtime
|
||||
- Fix #384: segfault in helper function when disabling the DHCP client
|
||||
using `no dhcp-client` from the CLI
|
||||
- Fix #391 Creating VLAN interface in the CLI with "edit interface vlanN"
|
||||
does not set VLAN id to N.
|
||||
- Fix #404: `lldpd` should be disabled on internal interface `dsa0`
|
||||
- Fix #406: an overly restrictive `when` expression in the bridge YANG
|
||||
model prevented users from adding VLAN interfaces as bridge ports.
|
||||
E.g., creating interface `eth0.10` and adding that to `br0`
|
||||
- Fix #412: after starting up with DHCP client enabled on any interface
|
||||
`set dhcp-client enabled false` does not bite at runtime
|
||||
- Fix #414: spelling error in `infix-hardware.yang`, leaf node `coutry`
|
||||
- Fix #415: `startup-config` owned by `root` user and group instead of
|
||||
`admin`. The file ownership is now adjusted on every boot
|
||||
- Fix #416: `admin` user cannot perform a factory reset with RPC using
|
||||
`sysrepocfg` tool over SSH
|
||||
- Fix bogus syslog warning about not updating `/etc/motd` properly
|
||||
|
||||
|
||||
[v24.02.0][] - 2024-03-01
|
||||
@@ -773,7 +919,11 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
||||
- N/A
|
||||
|
||||
[buildroot]: https://buildroot.org/
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.02.0...HEAD
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.04.0...HEAD
|
||||
[v24.05.0]: https://github.com/kernelkit/infix/compare/v24.04.0...v24.05.0
|
||||
[v24.04.2]: https://github.com/kernelkit/infix/compare/v24.04.1...v24.04.2
|
||||
[v24.04.1]: https://github.com/kernelkit/infix/compare/v24.04.0...v24.04.1
|
||||
[v24.04.0]: https://github.com/kernelkit/infix/compare/v24.02.0...v24.04.0
|
||||
[v24.02.0]: https://github.com/kernelkit/infix/compare/v23.11.0...v24.02.0
|
||||
[v23.11.0]: https://github.com/kernelkit/infix/compare/v23.10.0...v23.11.0
|
||||
[v23.10.0]: https://github.com/kernelkit/infix/compare/v23.09.0...v23.10.0
|
||||
|
||||
+60
-19
@@ -390,12 +390,30 @@ network:
|
||||
|
||||
### Container Host Interface
|
||||
|
||||
Another common use-case is to move a network interface into the network
|
||||
namespace of a container. Which the container bridge network type does
|
||||
behind the scenes with one end of the automatically created VETH pair.
|
||||
This works with regular Ethernet interfaces as well, but here we will
|
||||
use a VETH pair as an example along with a regular bridge (where other
|
||||
Ethernet interfaces may live as well).
|
||||
Another common use-case is to move network interfaces into the network
|
||||
namespace of a container[^3]. This of course works with plain Ethernet
|
||||
interfaces as well, but here we will use one end of a VETH pair as an
|
||||
example.
|
||||
|
||||
[^3]: Something which the container bridge network type does behind the
|
||||
scenes with one end of an automatically created VETH pair.
|
||||
|
||||
#### Routed Setup
|
||||
|
||||
In this routed setup we reserve 192.168.0.0/24 for the network between
|
||||
the host and the `ntpd` container.
|
||||
|
||||
_____________
|
||||
| |
|
||||
veth0 .1 | .2 eth0 |
|
||||
\ 192.168.0.0/24 | / |
|
||||
'--------------------' [ntpd] |
|
||||
|_____________|
|
||||
|
||||
Configuration is a straight-forward VETH pair setup where we name the
|
||||
container-end of pair `ntpd`. This is just a convenience for us when
|
||||
reading the configuration later. The *real action* happens on the last
|
||||
line where we declare the `ntpd` end as a container network interface:
|
||||
|
||||
admin@example:/config/> edit interface veth0
|
||||
admin@example:/config/interface/veth0/> set veth peer ntpd
|
||||
@@ -403,23 +421,49 @@ Ethernet interfaces may live as well).
|
||||
admin@example:/config/interface/veth0/> end
|
||||
admin@example:/config/> edit interface ntpd
|
||||
admin@example:/config/interface/ntpd/> set ipv4 address 192.168.0.2 prefix-length 24
|
||||
admin@example:/config/interface/ntpd/> set phys-address 00:c0:ff:ee:00:01
|
||||
admin@example:/config/interface/ntpd/> set container-network
|
||||
|
||||
This is a routed setup, where we reserve 192.168.0.0/24 for the network
|
||||
between the host and the `ntpd` container. A perhaps more common case
|
||||
is to put `veth0` as a port in a bridge with other physical ports. The
|
||||
point of the routed case is that port forwarding from the container in
|
||||
this case is limited to a single interface, not *all interfaces* as is
|
||||
the default in the masquerading container bridge setup.
|
||||
> Notice how you can also set a custom MAC address at the same time.
|
||||
|
||||
When a container has multiple host interfaces it can often be useful to
|
||||
have a default route installed. This can be added from the host with a
|
||||
`0.0.0.0/0` route on one of the interfaces. The following is an example
|
||||
when adding a second VETH pair to the container:
|
||||
Adding the interface to the container is the same as before, but since
|
||||
everything for host interfaces is set up in the interfaces context, we
|
||||
can take a bit of a shortcut.
|
||||
|
||||
admin@example:/config/container/ntpd/> set network ntpd
|
||||
admin@example:/config/container/ntpd/> leave
|
||||
|
||||
The point of the routed case is that port forwarding from the container
|
||||
in this case is limited to a single interface, not *all interfaces* as
|
||||
is the default in the masquerading container bridge setup.
|
||||
|
||||
|
||||
#### Bridged Setup
|
||||
|
||||
A perhaps more common case is to bridge the other end of the VETH pair
|
||||
with other physical ports. In this section we show how to add a new
|
||||
pair to give our container two interfaces:
|
||||
|
||||
_______________
|
||||
| | .1 br0
|
||||
veth0 .1 | .2 eth0 | / \
|
||||
\ 192.168.0.0/24 | / eth1 .2 | veth1b e1
|
||||
'------------------' \ | 192.168.1.0/24 /
|
||||
| [ntpd] '------------------'
|
||||
|_______________|
|
||||
|
||||
We start by adding the second VETH pair:
|
||||
|
||||
admin@example:/config/> edit interface veth1a
|
||||
admin@example:/config/interface/veth1a/> set veth peer veth1b
|
||||
admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24
|
||||
|
||||
> The LAN bridge (br0) in this example has IP address 192.168.1.1.
|
||||
|
||||
When a container has multiple host interfaces it can often be useful to
|
||||
have a default route installed. This can be added from the host with a
|
||||
`0.0.0.0/0` route on one of the interfaces:
|
||||
|
||||
admin@example:/config/interface/veth1a/> set container-network route 0.0.0.0/0 gateway 192.168.1.1
|
||||
admin@example:/config/interface/veth1a/> show
|
||||
type veth;
|
||||
@@ -439,9 +483,6 @@ Please note, container network routes require the base interface also
|
||||
have a static IP address set. Setting only the route, but no address,
|
||||
means the route is skipped.
|
||||
|
||||
> The LAN bridge (br0) in this example has IP address 192.168.1.1.
|
||||
|
||||
|
||||
### Host Networking
|
||||
|
||||
The third use-case is host networking, this is where a container share
|
||||
|
||||
+43
-6
@@ -66,7 +66,8 @@ The instructions here are for Debian/Ubuntu based systems (YMMV):
|
||||
$ sudo apt install bc binutils build-essential bzip2 cpio \
|
||||
diffutils file findutils git gzip \
|
||||
libncurses-dev libssl-dev perl patch \
|
||||
python rsync sed tar unzip wget
|
||||
python3 rsync sed tar unzip wget \
|
||||
autopoint bison flex
|
||||
```
|
||||
|
||||
For testing, a few more tools and services are required on your system:
|
||||
@@ -96,8 +97,10 @@ To see available defconfigs for supported targets, use:
|
||||
Development
|
||||
-----------
|
||||
|
||||
When changing a package, locally kept sources, or when using [`local.mk`](override-package.md),
|
||||
you only want to rebuild the parts you have modified:
|
||||
Developing with Infix is the same as [developing with Buildroot][4].
|
||||
When working with a package, be it locally kept sources, or when using
|
||||
[`local.mk`](override-package.md), you only want to rebuild the parts
|
||||
you have modified:
|
||||
|
||||
make foo-rebuild
|
||||
|
||||
@@ -105,7 +108,7 @@ or
|
||||
|
||||
make foo-reconfigure
|
||||
|
||||
or, when nothing seems to bite:
|
||||
or, as a last resort when nothing seems to bite:
|
||||
|
||||
make foo-dirclean foo-rebuild
|
||||
|
||||
@@ -118,6 +121,38 @@ This rebuilds (and installs) `foo` and `bar`, the `all` target calls
|
||||
on Buildroot to finalize the target filesystem and generate the images.
|
||||
The final `run` argument is explained below.
|
||||
|
||||
### `confd`
|
||||
|
||||
The Infix `src/confd/` is the engine of the system. Currently it is a
|
||||
plugin for `systemd-plugind` and contains XPath subscriptions to all the
|
||||
supported YANG models.
|
||||
|
||||
There are essentially two ways of adding support for a new YANG model:
|
||||
|
||||
- The [sysrepo way][3], or
|
||||
- The Infix way, using libsrx (the `lydx_*()` functions)
|
||||
|
||||
The former is well documented in sysrepo, and the latter is best taught
|
||||
by example, e.g., `src/confd/src/infix-dhcp.c`. Essentially libsrx is a
|
||||
way of traversing the libyang tree instead of fetching changes by XPath.
|
||||
|
||||
When working with `confd` you likely want to enable full debug mode,
|
||||
this is how you do it:
|
||||
|
||||
1. Open the file `package/confd/confd.conf`
|
||||
2. Uncomment the first line `set DEBUG=1`
|
||||
3. Change the following line to add `-v3` at the end
|
||||
|
||||
[S12345] sysrepo-plugind -f -p /run/confd.pid -n -- Configuration daemon
|
||||
|
||||
to:
|
||||
|
||||
[S12345] sysrepo-plugind -f -p /run/confd.pid -n -v3 -- Configuration daemon
|
||||
|
||||
Now you can rebuild `confd`, just as described above, and restart Infix:
|
||||
|
||||
make confd-rebuild all run
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
@@ -141,8 +176,8 @@ and then use GitHub to create a *Pull Reqeuest*.
|
||||
For this to work as painlessly as possible:
|
||||
|
||||
1. Fork Infix to your own user or organization[^1]
|
||||
2. Fork all the Infix submodules, e.g., `buildroot` to your own user
|
||||
or organization as well
|
||||
2. Fork all the Infix submodules, e.g., `kernelkit/buildroot` to your
|
||||
own user or organization as well
|
||||
3. Clone your fork of Infix to your laptop/workstation
|
||||
|
||||
If you use a GitHub organization you get the added benefit of having
|
||||
@@ -169,3 +204,5 @@ $ git submodule update --init
|
||||
[0]: https://github.com/kernelkit/infix/releases
|
||||
[1]: https://buildroot.org/downloads/manual/manual.html
|
||||
[2]: https://github.com/wkz/qeneth
|
||||
[3]: https://netopeer.liberouter.org/doc/sysrepo/master/html/dev_guide.html
|
||||
[4]: https://buildroot.org/downloads/manual/manual.html#_developer_guide
|
||||
|
||||
@@ -114,6 +114,169 @@ admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
|
||||
> on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces)
|
||||
> below for more on this topic.
|
||||
|
||||
#### Multicast Filtering and Snooping
|
||||
|
||||
Multicast filtering in the bridge is handled by the bridge itself. It
|
||||
can filter both IP multicast and MAC multicast. For IP multicast it
|
||||
also supports "snooping", i.e., IGMP and MLD, to automatically reduce
|
||||
the broadcast effects of multicast. See the next section for a summary
|
||||
of the [terminology used](#terminology--abbreviations).
|
||||
|
||||
> **Note:** currently there is no way to just enable multicast filtering
|
||||
> without also enabling snooping. This may change in the future, in
|
||||
> which case a `filtering` enabled setting will be made available along
|
||||
> with the existing `snooping` setting.
|
||||
|
||||
When creating your bridge you must decide if you need a VLAN filtering
|
||||
bridge or a plain bridge (see previous section). Multicast filtering is
|
||||
supported for either, but take note that it must be enabled and set up
|
||||
per VLAN when VLAN filtering is enabled -- there are no global multicast
|
||||
settings in this operating mode.
|
||||
|
||||
In the following example we have a regular 8-port bridge without VLAN
|
||||
filtering. We focus on the multicast specific settings:
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface br0
|
||||
admin@example:/config/interface/br0/> set bridge multicast snooping
|
||||
admin@example:/config/interface/br0/> set ipv4 address 192.168.2.1 prefix-length 24
|
||||
admin@example:/config/interface/br0/> leave
|
||||
admin@example:/> copy running-config startup-config
|
||||
```
|
||||
|
||||
Here we enable snooping and set a static IPv4 address so that the switch
|
||||
can take part in IGMP querier elections. (MLD querier election
|
||||
currently not supported.) We can inspect the current state:
|
||||
|
||||
```
|
||||
admin@example:/> show ip multicast
|
||||
Multicast Overview
|
||||
Query Interval (default): 125 sec
|
||||
Router Timeout : 255
|
||||
Fast Leave Ports :
|
||||
Router Ports :
|
||||
Flood Ports : e0, e1, e2, e3, e4, e5, e6, e7
|
||||
|
||||
Interface VID Querier State Interval Timeout Ver
|
||||
br0 192.168.2.1 Up 125 None 3
|
||||
|
||||
Bridge VID Multicast Group Ports
|
||||
br0 224.1.1.1 e3, e2
|
||||
br0 ff02::6a br0
|
||||
```
|
||||
|
||||
It is a small LAN, so our bridge has already become the elected IGMP
|
||||
querier. We see it is ours because the timeout is `None`, and we
|
||||
recognize our IP address. We can also see two ports that have joined
|
||||
the same IPv4 multicast group, 224.1.1.1, and one join from Infix itself
|
||||
for the IPv6 group ff02::6a.
|
||||
|
||||
Now, let's see what happens when we add another bridge, with VLAN
|
||||
filtering enabled. We skip the boring parts about how to move ports
|
||||
e4-e7 to `br1` and assign them to VLANs, and again, focus on the
|
||||
multicast bits only:
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface br1
|
||||
admin@example:/config/interface/br1/> set bridge vlans vlan 1 multicast snooping
|
||||
admin@example:/config/interface/br1/> set bridge vlans vlan 2 multicast snooping
|
||||
admin@example:/config/interface/br1/> leave
|
||||
admin@example:/> copy running-config startup-config
|
||||
```
|
||||
|
||||
Let's see what we get:
|
||||
|
||||
```
|
||||
admin@example:/> show ip multicast
|
||||
Multicast Overview
|
||||
Query Interval (default): 125 sec
|
||||
Router Timeout : 255
|
||||
Fast Leave Ports : e5
|
||||
Router Ports : e1, e2, e5, e6, e7
|
||||
Flood Ports : e1, e2, e3, e4, e5, e6, e7, e8
|
||||
|
||||
Interface VID Querier State Interval Timeout Ver
|
||||
br0 192.168.2.1 Up 125 None 3
|
||||
br1 1 0.0.0.0 Up 125 None 3
|
||||
br1 2 0.0.0.0 Up 125 None 3
|
||||
|
||||
Bridge VID Multicast Group Ports
|
||||
br0 224.1.1.1 e2
|
||||
br0 ff02::fb br0
|
||||
br0 ff02::6a br0
|
||||
br0 ff02::1:ff00:0 br0
|
||||
br1 1 224.1.1.1 e5
|
||||
br1 2 224.1.1.1 e7
|
||||
br1 1 ff02::fb br1
|
||||
br1 1 ff02::1:ff00:0 br1
|
||||
```
|
||||
|
||||
In this setup we have a lot more going on. Multiple multicast router
|
||||
ports have been detected, and behind the scenes someone has also added
|
||||
an IGMP/MLD fast-leave port.
|
||||
|
||||
##### Terminology & Abbreviations
|
||||
|
||||
- **IGMP**: Internet Group Membership Protocol, multicast subscription
|
||||
for IPv4, for details see [RFC3376][]
|
||||
- **MLD**: Multicast Listener Discovery (Protocol), multicast
|
||||
subscription for IPv6, for details see [RFC3810][]
|
||||
- **Unknown/Unregistered multicast**: multicast groups that are *not*
|
||||
in the multicast forwarding database (MDB)
|
||||
- **Known/Registered multicast**: multicast groups that *are* in the
|
||||
multicast forwarding database (MDB)
|
||||
- **MDB**: the multicast forwarding database, consists of filters for
|
||||
multicast groups, directing where multicast is allowed to egress. A
|
||||
filter entry consists of a group and a port list. The bridge filters
|
||||
with a unique database per VLAN, in the same was as the unicast FDB
|
||||
- **Join/Leave**: the terminology used in earlier versions of the two
|
||||
protocols to subscribe and unsubscribe to a multicast group. For
|
||||
more information, see *Membership Report*
|
||||
- **Membership Report** A membership report is sent by end-devices and
|
||||
forwarded by switches to the elected querier on the LAN. They
|
||||
consist of multiple "join" and "leave" operations on groups. They
|
||||
can also, per group, list which senders to allow or block. Switches
|
||||
usually only support the group subscription, and even more common
|
||||
also only support filtering on the MAC level[^3]
|
||||
- **Querier election**: the process of determining who is the elected
|
||||
IGMP/MLD querier on a LAN. Lowest numerical IP address wins, the
|
||||
special address 0.0.0.0 (proxy querier) never wins
|
||||
- **Proxy querier**: when no better querier exists on a LAN, one or
|
||||
more devices can send proxy queries with source address 0.0.0.0 (or
|
||||
:: for IPv6). See **Query Interval**, below, why this is a good
|
||||
thing
|
||||
- **Query interval**: the time in seconds between two queries from an
|
||||
IGMP/MLD querier. It is not uncommon that end-devices do not send
|
||||
their membership reports unless they first hear a query
|
||||
- **Fast Leave**: set on a bridge port to ensure multicast is pruned as
|
||||
quickly as possible when a "leave" membership report is received. In
|
||||
effect, this option marks the port as directly connected to an
|
||||
end-device. When not set (default), a query with timeout is first
|
||||
sent to ensure no unintentional loss of multicast is incurred
|
||||
- **Router port**: can be both configured statically and detected at
|
||||
runtime based on connected devices, usually multicast routers. On
|
||||
a router port *all* multicast is forwarded, both known and unknown
|
||||
- **Flood port**: set on a bridge port (default: enabled) to ensure
|
||||
all *unknown* multicast is forwarded
|
||||
- **Router timeout**: the time in seconds until a querier is deemed to
|
||||
have been lost and another device (switch/router) takes over. In the
|
||||
tables shown above, a *None* timeout is declared when the current
|
||||
device is the active querier
|
||||
|
||||
> **Note:** the reason why multicast flooding is enabled by default is
|
||||
> to ensure safe co-existence with MAC multicast, which is very common
|
||||
> in industrial networks. It also allows end devices that do not know
|
||||
> of IGMP/MLD to communicate over multicast as long as the group they
|
||||
> have chosen is not used by other IGMP/MLD aware devices on the LAN.
|
||||
>
|
||||
> As soon as an IGMP/MLD membership report to "join" a group is received
|
||||
> the group is added to the MDB and forwarding to other ports stop. The
|
||||
> only exception to this rule is multicast router ports.
|
||||
|
||||
[RFC3376]: https://www.rfc-editor.org/rfc/rfc3376.html
|
||||
[RFC3810]: https://www.rfc-editor.org/rfc/rfc3810.html
|
||||
|
||||
### VLAN Interfaces
|
||||
|
||||
@@ -634,3 +797,7 @@ currently supported, namely `ipv4` and `ipv6`.
|
||||
[^2]: Link-local IPv6 addresses are implicitly enabled when enabling
|
||||
IPv6. IPv6 can be enabled/disabled per interface in the
|
||||
[ietf-ip][2] YANG model.
|
||||
[^3]: For example, IPv4 groups are mapped to MAC multicast addresses by
|
||||
mapping the low-order 23-bits of the IP address in the low-order 23
|
||||
bits of the Ethernet address 01:00:5E:00:00:00. Meaning, more than
|
||||
one IP multicast group maps to the same MAC multicast group.
|
||||
|
||||
+53
-28
@@ -1,50 +1,75 @@
|
||||
Package override
|
||||
Package Override
|
||||
================
|
||||
|
||||
This guide demonstrates how the `local.mk` file is utilized to override
|
||||
a Linux Buildroot package. The example of `tcpdump` serves to illustrate
|
||||
This guide demonstrates how the `local.mk` file is utilized to override
|
||||
a Linux Buildroot package. As an example we use `tcpdump` to illustrate
|
||||
this process.
|
||||
|
||||
In an instance such as `Infix` using tcpdump, the `local.mk` file is modified
|
||||
as shown below:
|
||||
> For a comprehensive guide to utilizing Buildroot during development,
|
||||
> including the `<pkg>_OVERRIDE_SRCDIR` mechanism, shown below, please
|
||||
> see [Using Buildroot during development][1] in the official docs.
|
||||
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
Since the `output/` directory is often wiped for rebuilds, make sure you
|
||||
keep the file `local.mk` in the top directory and only symlink it to your
|
||||
build directory:
|
||||
|
||||
~$ cd infix/
|
||||
~/infix(main)$ touch local.mk
|
||||
~/infix/output(main)$ ln -s ../local.mk .
|
||||
~/infix/output(main)$ cd ..
|
||||
|
||||
|
||||
Override
|
||||
--------
|
||||
|
||||
Now edit the file:
|
||||
|
||||
~/infix(main)$ editor local.mk
|
||||
|
||||
Add an override for `tcpdump`. The file is a Makefile snippet so you
|
||||
can add a lot of things. Comment out lines with the UNIX comment `#`
|
||||
character if needed:
|
||||
|
||||
```
|
||||
TCPDUMP_OVERRIDE_SRCDIR = /path/to/tcpdump/repo
|
||||
```
|
||||
|
||||
and stored in the `output/` folder, alongside the `.config` file:
|
||||
```
|
||||
user@PC:~/infix$ll output/ | grep -e 'local.mk' -e '.config'
|
||||
-rw-r--r-- 1 group user 119936 Nov 10 18:04 .config
|
||||
-rw-r--r-- 1 group user 43 Nov 10 18:25 local.mk
|
||||
```
|
||||
Building
|
||||
--------
|
||||
|
||||
The execution of `make tcpdump-rebuild all` triggers a process where
|
||||
Buildroot synchronizes the tcpdump source code from the specified override directory
|
||||
to `output/build/tcpdump-custom`, followed by the rebuilding of the entire project.
|
||||
The execution of `make tcpdump-rebuild all` triggers a process where
|
||||
Buildroot synchronizes the tcpdump source code from the specified
|
||||
override directory to `output/build/tcpdump-custom`, followed by the
|
||||
rebuilding of the entire project.
|
||||
|
||||
```
|
||||
user@PC:~/infix$ make tcpdump-rebuild all
|
||||
~/infix$(main)$ make tcpdump-rebuild all
|
||||
```
|
||||
|
||||
Buildroot follows a process of downloading and processing tarballs:
|
||||
extraction, configuration, compilation, and installation. The source
|
||||
for each package is extracted to a temporary build directory:
|
||||
|
||||
output/build/<package>-<version> # e.g., tcpdump-4.99.4
|
||||
|
||||
Let's have a look at what we got:
|
||||
|
||||
```
|
||||
user@PC:~/infix$ ll /output/build/ | grep tcpdump
|
||||
~/infix$(main)$ ll /output/build/ | grep tcpdump
|
||||
drwxr-xr-x 7 group user 20480 Nov 10 18:26 tcpdump-4.99.4/
|
||||
drwxr-xr-x 7 group user 12288 Nov 10 18:28 tcpdump-custom/
|
||||
```
|
||||
|
||||
Buildroot follows a process of downloading and processing tarballs
|
||||
(extraction, configuration, compilation, and installation).
|
||||
The source code is stored in a temporary directory:
|
||||
`output/build/<package>-<version>` (i.e. `tcpdump-4.99.4/`),
|
||||
which is removed and recreated with each `make` command. That is why
|
||||
the direct modifications in the `output/build` directory are generally
|
||||
**not recommended**.
|
||||
As long as your local override is in place, Buildroot will use your
|
||||
custom version.
|
||||
|
||||
To manage the development changes more effectively, where the package source code
|
||||
remains untouched, Buildroot incorporates the `<pkg>_OVERRIDE_SRCDIR` feature.
|
||||
> **Remember:** the build directory is ephemeral, so be careful to
|
||||
> change any of the files therein. It can be useful though during
|
||||
> debugging, but just make sure to learn the difference between the
|
||||
> various Buildroot commands to build, clean, reconfigure, etc.
|
||||
|
||||
For a comprehensive understanding of utilizing Buildroot during development,
|
||||
including detailed elaboration on the `<pkg>_OVERRIDE_SRCDIR` feature,
|
||||
refer to section 8.13.6 in [Using Buildroot during development](https://nightly.buildroot.org/).
|
||||
[1]: https://buildroot.org/downloads/manual/manual.html#_using_buildroot_during_development
|
||||
|
||||
+808
-3
@@ -168,9 +168,9 @@ There are two ways to do it:
|
||||
1. Change the configuration without saving it to `startup-config`
|
||||
2. Change the operational state
|
||||
|
||||
The first involves sending a NETCONF command/config in XML, the second
|
||||
we will cover here. We start by querying available interfaces (ports)
|
||||
on the remote system:
|
||||
The first involves sending a NETCONF command/config in XML. The second
|
||||
we will cover here. We start by querying available interfaces (ports) on
|
||||
the remote system:
|
||||
|
||||
```
|
||||
~$ ssh admin@infix.local%qtap0 ip -br a
|
||||
@@ -331,6 +331,811 @@ admin@infix.local%eth0's password: *****
|
||||
~$
|
||||
```
|
||||
|
||||
### Controlling LEDs for Production Tests
|
||||
|
||||
As part of production testing, LED verification is often expected to
|
||||
be performed. Infix uses standard [Linux support for LED
|
||||
management][6], where LEDs appear in the file system under
|
||||
/sys/class/leds and can be controlled using *echo* command. `sudo`
|
||||
privileges are required.
|
||||
|
||||
When interacting with LEDs this way, first disable the Infix *iitod*
|
||||
daemon to avoid conflicting LED control.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'initctl stop iitod'
|
||||
```
|
||||
|
||||
Then run the test, e.g., visually control that a red LED labeled
|
||||
'LAN' is working.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'echo none | sudo tee /sys/class/leds/red\:lan/trigger'
|
||||
~$ ssh admin@example.local 'echo 1 | sudo tee /sys/class/leds/red\:lan/brightness'
|
||||
```
|
||||
|
||||
To turn off the same LED, run the following commands.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'echo none | sudo tee /sys/class/leds/red\:lan/trigger'
|
||||
~$ ssh admin@example.local 'echo 0 | sudo tee /sys/class/leds/red\:lan/brightness'
|
||||
```
|
||||
When done with LED testing, enable Infix *iitod* daemon again.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'initctl start iitod'
|
||||
```
|
||||
|
||||
### Reading Power Feed Status for Production Tests
|
||||
|
||||
As part of production tests, verification of Power Feed sensors is
|
||||
often expected to be performed. Infix uses standard [Linux support for
|
||||
Power management][7], where power sources appear in the file system
|
||||
under /sys/class/power_supply. The following example reads status of
|
||||
two power supplies named *pwr1* and *pwr2*.
|
||||
|
||||
```
|
||||
~$ ssh admin@example 'cat /sys/class/power_supply/pwr1/online'
|
||||
1
|
||||
~$ ssh admin@example 'cat /sys/class/power_supply/pwr2/online'
|
||||
0
|
||||
~$
|
||||
```
|
||||
Here, only *pwr1* happened to have power.
|
||||
|
||||
|
||||
## Examples using SSH and sysrepocfg
|
||||
|
||||
|
||||
[sysrepocfg][4] can be used to interact with the YANG models when logged
|
||||
in to infix. Thus, *set config*, *read config*, *read status* and
|
||||
*RPC* can be conducted using sysrepocfg for supported YANG models.
|
||||
It is possible to make configuration changes by operating on the
|
||||
*startup* database.
|
||||
|
||||
See [sysrepocfg][4] for information. Examples below will utilize
|
||||
|
||||
|
||||
|
||||
- `sysrepocfg -I FILE -fjson -d DATABASE` to import/write a JSON
|
||||
formatted configuration file to the specified database.
|
||||
- `sysrepocfg -E FILE -fjson -d DATABASE` to edit/merge JSON formatted
|
||||
configuration in FILE with the specified database.
|
||||
- `sysrepocfg -R FILE -fjson` to execute remote procedure call (RPC) defined in
|
||||
FILE (JSON formatted).
|
||||
- `sysrepocfg -X -fjson -d DATABASE -x xpath` to read configuration or
|
||||
status from specified database.
|
||||
|
||||
For importing (-I) and editing (-E), `-d running` is typically used in
|
||||
examples below. Specify `-d startup` to apply changes to startup
|
||||
configuration. Exporting (-X) could operate on configuration (e.g.,
|
||||
`-d running`) or status (`-d operational`).
|
||||
|
||||
Some commands require a file as input. In examples below we assume
|
||||
it been transferred to Infix in advance, e.g. using `scp` as shown below.
|
||||
|
||||
```
|
||||
~$ cat file.json
|
||||
{
|
||||
"ietf-factory-default:factory-reset": {
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$
|
||||
```
|
||||
|
||||
### Factory Reset Using sysrepocfg
|
||||
|
||||
|
||||
```
|
||||
~$ cat file.json
|
||||
{
|
||||
"ietf-factory-default:factory-reset": {
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json'
|
||||
^C
|
||||
~$
|
||||
```
|
||||
See [Factory Reset](#factory-reset) for another (simpler) alternative.
|
||||
|
||||
If it is only wished to copy factory config to running config the
|
||||
following RPC is available
|
||||
|
||||
```
|
||||
~$ cat file.json
|
||||
{
|
||||
"infix-factory-default:factory-default": {
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json'
|
||||
^C
|
||||
~$
|
||||
```
|
||||
|
||||
|
||||
### System Reboot Using sysrepocfg
|
||||
|
||||
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"ietf-system:system-restart": {
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json'
|
||||
~$
|
||||
```
|
||||
See [System Reboot](#system-reboot) for another (simpler) alternative.
|
||||
|
||||
|
||||
|
||||
### Set Date and Time Using sysrepocfg
|
||||
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'date'
|
||||
Sun Nov 20 10:20:23 UTC 2005
|
||||
~$ cat file.json
|
||||
{
|
||||
"ietf-system:set-current-datetime": {
|
||||
"current-datetime": "2024-04-17T13:48:02-01:00"
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json'
|
||||
~$ ssh admin@example.local 'date'
|
||||
Wed Apr 17 14:48:12 UTC 2024
|
||||
~$
|
||||
```
|
||||
See [Set Date and Time](#set-date-and-time) for another (simpler) alternative.
|
||||
|
||||
### Remote Control of Ethernet Ports Using sysrepocfg
|
||||
|
||||
|
||||
Reading administrative status of interface *e0* of running configuration.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running -e report-all -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\"'
|
||||
{
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$
|
||||
```
|
||||
> Note: Without `-e report-all` argument the line `"enabled: true`
|
||||
> would not be shown as `true` is default.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local "sysrepocfg -X -fjson -d running -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\""
|
||||
{
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$
|
||||
```
|
||||
|
||||
|
||||
Setting the administrative status of interface *e0* of running configuration.
|
||||
|
||||
```
|
||||
$ cat file.json
|
||||
{
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0",
|
||||
"enabled": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running'
|
||||
~$
|
||||
```
|
||||
|
||||
### Enable/Disable DHCPv4 client
|
||||
|
||||
|
||||
Enabling DHCPv4 client on interface *e0*, with current default options.
|
||||
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": true,
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "e0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running'
|
||||
~$
|
||||
```
|
||||
|
||||
Disabling DHCPv4 client.
|
||||
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running'
|
||||
~$
|
||||
```
|
||||
|
||||
Configuration for client interface *e0* remains, but does not apply as
|
||||
DHCPv4 is disabled.
|
||||
|
||||
```
|
||||
admin@example:~$ sysrepocfg -X -fjson -d running -x "/infix-dhcp-client:dhcp-client"
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": false,
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "e0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
admin@example:~$
|
||||
```
|
||||
|
||||
To fully remove the DHCPv4 client configuration or a specific
|
||||
*client-if* with sysrepocfg, one would need to read out the full
|
||||
configuration, remove relevant parts and read back.
|
||||
|
||||
|
||||
### Enable/Disable IPv6
|
||||
|
||||
IPv6 is typically enabled on all interfaces by default. The example
|
||||
below shows IPv4 and IPv6 addresses assigned on *e0*.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'ip addr show dev e0'
|
||||
2: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
||||
link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
|
||||
inet 10.0.2.15/24 scope global proto dhcp e0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 fec0::ff:fe00:0/64 scope site dynamic mngtmpaddr proto kernel_ra
|
||||
valid_lft 86380sec preferred_lft 14380sec
|
||||
inet6 fe80::ff:fe00:0/64 scope link proto kernel_ll
|
||||
valid_lft forever preferred_lft forever
|
||||
~$
|
||||
```
|
||||
|
||||
IPv6 is enabled/disabled per interface. The example below disables IPv6
|
||||
on interface *e0*.
|
||||
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0",
|
||||
"ietf-ip:ipv6": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running'
|
||||
~$ ssh admin@example.local 'ip addr show dev e0'
|
||||
2: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
||||
link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
|
||||
inet 10.0.2.15/24 scope global proto dhcp e0
|
||||
valid_lft forever preferred_lft forever
|
||||
~$
|
||||
```
|
||||
|
||||
### <a id="backup"></a> Backup Configuration Using sysrepocfg And scp
|
||||
|
||||
Displaying running or startup configuration is possible with
|
||||
`sysrepocfg -X`, as shown below.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running'
|
||||
{
|
||||
"ieee802-dot1ab-lldp:lldp": {
|
||||
"infix-lldp:enabled": true
|
||||
...
|
||||
~$
|
||||
```
|
||||
|
||||
An example for backing up startup configuration from remote PC.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup > /tmp/backup.json'
|
||||
~$ scp admin@example.local:/tmp/backup.json .
|
||||
~$
|
||||
```
|
||||
|
||||
Or possibly skip intermediate storage of file
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup' > backup.json
|
||||
~$
|
||||
```
|
||||
|
||||
A final example is to only use `scp`. This is simpler, but only works to backup the
|
||||
startup configuration (not running).
|
||||
|
||||
```
|
||||
~$ scp admin@example.local:/cfg/startup-config.cfg backup.json
|
||||
~$
|
||||
```
|
||||
|
||||
### <a id="restore"></a> Restore Configuration Using sysrepocfg and ssh/scp
|
||||
|
||||
|
||||
To restore a backup configuration to startup, the simplest way is to
|
||||
use `scp` and reboot as shown below
|
||||
|
||||
```
|
||||
~$ scp admin@example.local:/cfg/startup-config.cfg backup.json
|
||||
~$ ssh admin@example.local 'reboot'
|
||||
Connection to switch.local closed by remote host.
|
||||
~$
|
||||
```
|
||||
|
||||
An alternative method to restore a backup configuration is to use the
|
||||
`sysrepocfg -I FILE` (import) command.
|
||||
|
||||
The example below imports the backup configuration to startup, and
|
||||
reboots the unit.
|
||||
|
||||
```
|
||||
~$ scp backup.json admin@example.local:/tmp/
|
||||
~$ ssh admin@example.local 'sudo sysrepocfg -I /tmp/backup.json -fjson -d startup'
|
||||
~$ ssh admin@example.local 'reboot'
|
||||
Connection to switch.local closed by remote host.
|
||||
~$
|
||||
```
|
||||
|
||||
> Note: admin login credentials (hash) are stored as part of the
|
||||
> configuration file. When replacing a switch and applying the backed
|
||||
> up configuration from the former switch, the password on the
|
||||
> replacement unit will also change.
|
||||
|
||||
### Copy Running to Startup Using sysrepocfg
|
||||
|
||||
The following command reads out the running config via `sysrepocfg -X`
|
||||
and writes the result to the startup configuration.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /cfg/startup-config.cfg'
|
||||
~$
|
||||
```
|
||||
|
||||
An alternative is to write it to a temporary file, and use `sysrepocfg
|
||||
-I` to import it to startup.
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /tmp/running.json'
|
||||
~$ ssh admin@example.local 'sysrepocfg -I /tmp/running.json -fjson -d startup'
|
||||
~$
|
||||
```
|
||||
|
||||
### Read Out Hardware Information Using sysrepocfg
|
||||
|
||||
Infix supports IETF Hardware YANG with augments for ONIE formatted
|
||||
production data stored in EEPROMs, if available. See Infix [VPD
|
||||
documentation][5], as well as *ietf-hardware* and *infix-hardware* YANG
|
||||
models for details.
|
||||
|
||||
|
||||
```
|
||||
~$ ssh admin@example.local 'sysrepocfg -X -fjson -d operational -x /ietf-hardware:hardware'
|
||||
{
|
||||
"ietf-hardware:hardware": {
|
||||
"component": [
|
||||
{
|
||||
"name": "product",
|
||||
"class": "infix-hardware:vpd",
|
||||
"serial-num": "12345",
|
||||
"model-name": "Switch2010",
|
||||
"mfg-date": "2024-01-30T16:42:37+00:00",
|
||||
"infix-hardware:vpd-data": {
|
||||
"product-name": "Switch2010",
|
||||
"part-number": "ABC123-001",
|
||||
"serial-number": "007",
|
||||
"mac-address": "00:53:00:01:23:45",
|
||||
"manufacture-date": "01/30/2024 16:42:37",
|
||||
"num-macs": 11,
|
||||
"manufacturer": "ACME Production",
|
||||
"vendor": "SanFran Networks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "USB",
|
||||
"class": "infix-hardware:usb",
|
||||
"state": {
|
||||
"admin-state": "unlocked",
|
||||
"oper-state": "enabled"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$
|
||||
```
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### <a id="port-test-intro"></a> Port Configuration Example for Production Tests
|
||||
|
||||
As part of production tests, verification Ethernet ports are expected
|
||||
to be performed. A common way is to connect a test PC to two ports and
|
||||
send a *ping* traversing all ports. This can be achieved by using
|
||||
VLANs on the switch as described in this section. The resulting
|
||||
configuration file can be applied to the running configuration of the
|
||||
produced unit, e.g, use config file restore as described
|
||||
[above](#restore).
|
||||
|
||||
In this example we assume a 10 port switch, with ports e1-e10.
|
||||
|
||||
The following VLAN configuration and cable connections will be used:
|
||||
|
||||
| VLAN & Ports | Connect |
|
||||
|:------------------|:----------|
|
||||
| VLAN 10: e1 & e2 | e2 <=> e3 |
|
||||
| VLAN 20: e3 & e4 | e4 <=> e5 |
|
||||
| VLAN 30: e5 & e6 | e6 <=> e7 |
|
||||
| VLAN 40: e7 & e8 | e8 <=> e9 |
|
||||
| VLAN 50: e9 & e10 | |
|
||||
|
||||
The test PC is connected to e1 and e10 via different interfaces
|
||||
(alternatively, two different PCs are used).
|
||||
|
||||
> Configuration here is done via console. When configuring remotely
|
||||
> over SSH, remember to keep one IP address (the one used for the SSH
|
||||
> connection)! I.e., set a static IP address first, then perform the
|
||||
> VLAN configuration step."
|
||||
|
||||
#### Configuration at Start
|
||||
|
||||
Starting out, we assume a configuration where all ports are network
|
||||
interfaces (possibly with IPv6 enabled).
|
||||
|
||||
``` shell
|
||||
admin@example:/> show interfaces
|
||||
lo ethernet UP 00:00:00:00:00:00
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
e1 ethernet LOWER-DOWN 00:53:00:06:11:01
|
||||
e2 ethernet LOWER-DOWN 00:53:00:06:11:02
|
||||
e3 ethernet LOWER-DOWN 00:53:00:06:11:03
|
||||
e4 ethernet LOWER-DOWN 00:53:00:06:11:04
|
||||
e5 ethernet LOWER-DOWN 00:53:00:06:11:05
|
||||
e6 ethernet LOWER-DOWN 00:53:00:06:11:06
|
||||
e7 ethernet LOWER-DOWN 00:53:00:06:11:07
|
||||
e8 ethernet LOWER-DOWN 00:53:00:06:11:08
|
||||
e9 ethernet LOWER-DOWN 00:53:00:06:11:09
|
||||
e10 ethernet UP 00:53:00:06:11:0a
|
||||
ipv6 fe80::0053:00ff:fe06:110a/64 (link-layer)
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
#### Creating Bridge and Adding Ports
|
||||
|
||||
The example below uses Infix documentation on [creating bridges][8].
|
||||
|
||||
``` shell
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface br0
|
||||
admin@example:/config/interface/br0/> end
|
||||
admin@example:/config/> set interface e1 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e2 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e3 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e4 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e5 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e6 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e7 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e8 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e9 bridge-port bridge br0
|
||||
admin@example:/config/> set interface e10 bridge-port bridge br0
|
||||
admin@example:/config/>
|
||||
```
|
||||
|
||||
The interface status can be viewed using "show interface" after
|
||||
leaving configuration context. If configuration via SSH, first assign
|
||||
an IP address to br0 before *leaving* configuration context, e.g.,
|
||||
`set interface br0 ipv6 enabled` to get auto-configured IPv6
|
||||
address. Or skip 'leave' and stay in configuration context until done
|
||||
with all sections, including the one on [Add IP on
|
||||
Switch](#ip-on-switch).
|
||||
|
||||
``` shell
|
||||
admin@example:/config/> leave
|
||||
admin@example:/>
|
||||
admin@example:/> show interfaces
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
br0 bridge
|
||||
│ ethernet UP 00:53:00:06:11:01
|
||||
├ e1 bridge LOWER-DOWN
|
||||
├ e2 bridge LOWER-DOWN
|
||||
├ e3 bridge LOWER-DOWN
|
||||
├ e4 bridge LOWER-DOWN
|
||||
├ e5 bridge LOWER-DOWN
|
||||
├ e6 bridge LOWER-DOWN
|
||||
├ e7 bridge LOWER-DOWN
|
||||
├ e8 bridge LOWER-DOWN
|
||||
├ e9 bridge LOWER-DOWN
|
||||
└ e10 bridge FORWARDING
|
||||
lo ethernet UP 00:00:00:00:00:00
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
#### Assign VLANs to Ports
|
||||
|
||||
Then configure VLANs as outlined [above](#port-test-intro):
|
||||
default VID for ingress (PVID), which is done per port, and egress
|
||||
mode (untagged), which is done at the bridge level. See Infix
|
||||
[documentation for VLAN bridges][9] for more information.
|
||||
|
||||
|
||||
``` shell
|
||||
admin@example:/>
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> set interface e1 bridge-port pvid 10
|
||||
admin@example:/config/> set interface e2 bridge-port pvid 10
|
||||
admin@example:/config/> set interface e3 bridge-port pvid 20
|
||||
admin@example:/config/> set interface e4 bridge-port pvid 20
|
||||
admin@example:/config/> set interface e5 bridge-port pvid 30
|
||||
admin@example:/config/> set interface e6 bridge-port pvid 30
|
||||
admin@example:/config/> set interface e7 bridge-port pvid 40
|
||||
admin@example:/config/> set interface e8 bridge-port pvid 40
|
||||
admin@example:/config/> set interface e9 bridge-port pvid 50
|
||||
admin@example:/config/> set interface e10 bridge-port pvid 50
|
||||
admin@example:/config/> edit interface br0
|
||||
admin@example:/config/interface/br0/> edit bridge vlans
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e1
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e2
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e3
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e4
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e5
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e6
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e7
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e8
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e9
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e10
|
||||
admin@example:/config/interface/br0/bridge/vlans/> leave
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
Interface status would now should something like the following
|
||||
|
||||
``` shell
|
||||
admin@example:/> show interfaces
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
br0 bridge
|
||||
│ ethernet UP 00:53:00:06:11:01
|
||||
├ e1 bridge LOWER-DOWN vlan:10u pvid:10
|
||||
├ e2 bridge LOWER-DOWN vlan:10u pvid:10
|
||||
├ e3 bridge LOWER-DOWN vlan:20u pvid:20
|
||||
├ e4 bridge LOWER-DOWN vlan:20u pvid:20
|
||||
├ e5 bridge LOWER-DOWN vlan:30u pvid:30
|
||||
├ e6 bridge LOWER-DOWN vlan:30u pvid:30
|
||||
├ e7 bridge LOWER-DOWN vlan:40u pvid:40
|
||||
├ e8 bridge LOWER-DOWN vlan:40u pvid:40
|
||||
├ e9 bridge LOWER-DOWN vlan:50u pvid:50
|
||||
└ e10 bridge FORWARDING vlan:50u pvid:50
|
||||
lo ethernet UP 00:00:00:00:00:00
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
#### Connect Cables and Test
|
||||
|
||||
We can now connect the PC to e1 and e10, and the other ports are
|
||||
patched according to plan [above](#port-test-intro). We should get
|
||||
link up on all ports.
|
||||
|
||||
``` shell
|
||||
admin@example:/> show interfaces
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
br0 bridge
|
||||
│ ethernet UP 00:53:00:06:11:01
|
||||
├ e1 bridge FORWARDING vlan:10u pvid:10
|
||||
├ e2 bridge FORWARDING vlan:10u pvid:10
|
||||
├ e3 bridge FORWARDING vlan:20u pvid:20
|
||||
├ e4 bridge FORWARDING vlan:20u pvid:20
|
||||
├ e5 bridge FORWARDING vlan:30u pvid:30
|
||||
├ e6 bridge FORWARDING vlan:30u pvid:30
|
||||
├ e7 bridge FORWARDING vlan:40u pvid:40
|
||||
├ e8 bridge FORWARDING vlan:40u pvid:40
|
||||
├ e9 bridge FORWARDING vlan:50u pvid:50
|
||||
└ e10 bridge FORWARDING vlan:50u pvid:50
|
||||
lo ethernet UP 00:00:00:00:00:00
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
Here we use IPv6 ping all hosts (ff02::1) on PC interface eth1 to
|
||||
check reachability to the other interface of the PC.
|
||||
|
||||
> A recommendation is to use network name spaces on PC to ensure
|
||||
> traffic really goes out to switch, instead of being looped
|
||||
> internally. Or use two PCs.
|
||||
|
||||
|
||||
``` shell
|
||||
~ $ ping -L ff02::1%eth1
|
||||
PING ff02::1%eth1(ff02::1%eth1) 56 data bytes
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.496 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.514 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.473 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.736 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.563 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.507 ms
|
||||
^C
|
||||
--- ff02::1%eth1 ping statistics ---
|
||||
6 packets transmitted, 6 received, 0% packet loss, time 5108ms
|
||||
rtt min/avg/max/mdev = 0.473/0.548/0.736/0.088 ms
|
||||
~ $
|
||||
```
|
||||
|
||||
We can verify that traffic goes through the switch by disconnecting
|
||||
one of the patch cables, e.g., between e4 and e5
|
||||
|
||||
``` shell
|
||||
~ $ ping -L ff02::1%eth1
|
||||
PING ff02::1%eth1(ff02::1%eth1) 56 data bytes
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.510 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.448 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.583 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.515 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.521 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.495 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=7 ttl=64 time=0.743 ms
|
||||
... Disconnecting patch cable, thus losing packets
|
||||
... and reconnecting again. Connectivity resumes.
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=16 ttl=64 time=0.961 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=17 ttl=64 time=0.513 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=18 ttl=64 time=0.794 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=19 ttl=64 time=0.755 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=20 ttl=64 time=0.779 ms
|
||||
^C
|
||||
--- ff02::1%eth1 ping statistics ---
|
||||
20 packets transmitted, 12 received, 40% packet loss, time 19432ms
|
||||
rtt min/avg/max/mdev = 0.448/0.634/0.961/0.156 ms
|
||||
~ $
|
||||
```
|
||||
|
||||
#### <a id="ip-on-switch"></a> Add IP Address on Switch
|
||||
|
||||
The configuration so far does not provide a means to connect to the
|
||||
switch management via SSH or NETCONF, as the switch has no IP
|
||||
address. The example below shows how to add the switch to VLAN 10 (as
|
||||
used for ports e1 and e2) and enables IPv6.
|
||||
|
||||
|
||||
``` shell
|
||||
admin@example:/config/> edit interface vlan10
|
||||
admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
|
||||
admin@example:/config/interface/vlan10/> set ipv6 enabled
|
||||
admin@example:/config/interface/vlan10/> show
|
||||
type vlan;
|
||||
ipv6 {
|
||||
enabled true;
|
||||
}
|
||||
vlan {
|
||||
tag-type c-vlan;
|
||||
id 10;
|
||||
lower-layer-if br0;
|
||||
}
|
||||
admin@example:/config/interface/vlan10/>
|
||||
admin@example:/config/interface/vlan10/> end
|
||||
admin@example:/config/> edit interface br0 bridge vlans
|
||||
admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 tagged br0
|
||||
admin@example:/config/interface/br0/bridge/vlans/> leave
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
Interface *vlan10* with an auto-configured IPv6 address should appear.
|
||||
|
||||
``` shell
|
||||
admin@example:/> show interfaces
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
br0 bridge vlan:10t
|
||||
│ ethernet UP 00:53:00:06:11:01
|
||||
├ e1 bridge FORWARDING vlan:10u pvid:10
|
||||
├ e2 bridge FORWARDING vlan:10u pvid:10
|
||||
├ e3 bridge FORWARDING vlan:20u pvid:20
|
||||
├ e4 bridge FORWARDING vlan:20u pvid:20
|
||||
├ e5 bridge FORWARDING vlan:30u pvid:30
|
||||
├ e6 bridge FORWARDING vlan:30u pvid:30
|
||||
├ e7 bridge FORWARDING vlan:40u pvid:40
|
||||
├ e8 bridge FORWARDING vlan:40u pvid:40
|
||||
├ e9 bridge FORWARDING vlan:50u pvid:50
|
||||
└ e10 bridge FORWARDING vlan:50u pvid:50
|
||||
lo ethernet UP 00:00:00:00:00:00
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
vlan10 ethernet UP 00:53:00:06:11:01
|
||||
│ ipv6 fe80::0053:00ff:fe06:1101/64 (link-layer)
|
||||
└ br0 ethernet UP 00:53:00:06:11:01
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
When pinging "IPv6 all hosts" from the PC, there should be two
|
||||
responses for every ping, one from the switch and one from the PC
|
||||
attached to e10.
|
||||
|
||||
``` shell
|
||||
~ $ ping -L ff02::1%eth1
|
||||
PING ff02::1%eth1(ff02::1%eth1) 56 data bytes
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.508 ms
|
||||
64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=1 ttl=64 time=0.968 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.866 ms
|
||||
64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=2 ttl=64 time=0.867 ms
|
||||
64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=3 ttl=64 time=0.467 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.469 ms
|
||||
64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.452 ms
|
||||
64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=4 ttl=64 time=0.453 ms
|
||||
^C
|
||||
--- ff02::1%eth1 ping statistics ---
|
||||
4 packets transmitted, 4 received, +4 duplicates, 0% packet loss, time 3031ms
|
||||
rtt min/avg/max/mdev = 0.452/0.631/0.968/0.211 ms
|
||||
~ $
|
||||
```
|
||||
|
||||
It should now be possible to access the switch from the PC via SSH (or NETCONF).
|
||||
|
||||
``` shell
|
||||
~ $ ssh admin@fe80::0053:00ff:fe06:1101%eth1
|
||||
admin@fe80::0053:00ff:fe06:1101%eth1's password:
|
||||
.-------.
|
||||
| . . | Infix -- a Network Operating System
|
||||
|-. v .-| https://kernelkit.github.io
|
||||
'-'---'-'
|
||||
|
||||
Run the command 'cli' for interactive OAM
|
||||
|
||||
admin@example:~$ exit
|
||||
~ $
|
||||
```
|
||||
|
||||
See previous sections on [backup](#backup) and [restore](#restore) of
|
||||
the created configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
[1]: discovery.md
|
||||
[2]: https://rauc.io/
|
||||
[3]: boot.md#system-upgrade
|
||||
[4]: https://netopeer.liberouter.org/doc/sysrepo/libyang1/html/sysrepocfg.html
|
||||
[5]: vpd.md
|
||||
[6]: https://docs.kernel.org/leds/leds-class.html
|
||||
[7]: https://docs.kernel.org/power/power_supply_class.html
|
||||
[8]: networking.md#bridging
|
||||
[9]: networking.md#vlan-filtering-bridge
|
||||
|
||||
@@ -70,6 +70,72 @@ admin@host:/config/system/authentication/user/admin/authorized-key/example@host/
|
||||
> does the job.
|
||||
|
||||
|
||||
## Multiple Users
|
||||
|
||||
The system supports multiple users and multiple user levels, or groups,
|
||||
that a user can be a member of. Access control is entirely handled by
|
||||
the NETCONF ["NACM"][3] YANG model, which provides granular access to
|
||||
configuration, data, and RPC commands over NETCONF.
|
||||
|
||||
By default the system ships with a single group, `admin`, which the
|
||||
default user `admin` is a member of. The broad permissions granted by
|
||||
the `admin` group is what gives its users full system administrator
|
||||
privileges. There are no restrictions on the number of users with
|
||||
administrator privileges, nor is the `admin` user reserved or protected
|
||||
in any way -- it is completely possible to remove the default `admin`
|
||||
user from the configuration. However, it is recommended to keep at
|
||||
least one user with administrator privileges in the system, otherwise
|
||||
the only way to regain full access is to perform a *factory reset*.
|
||||
|
||||
### Adding a User
|
||||
|
||||
Similar to how to change password, adding a new user is done using the
|
||||
same set of commands:
|
||||
|
||||
```
|
||||
admin@host:/config/> edit system authentication user jacky
|
||||
admin@host:/config/system/authentication/user/jacky/> change password
|
||||
New password:
|
||||
Retype password:
|
||||
admin@host:/config/system/authentication/user/jacky/> leave
|
||||
```
|
||||
|
||||
An authorized SSH key is added the same way as presented previously.
|
||||
|
||||
### Adding a User to the Admin Group
|
||||
|
||||
The following commands add user `jacky` to the `admin` group.
|
||||
|
||||
```
|
||||
admin@host:/config/> edit nacm group admin
|
||||
admin@host:/config/nacm/group/admin/> set user-name jacky
|
||||
admin@host:/config/nacm/group/admin/> leave
|
||||
```
|
||||
|
||||
### Security Aspects
|
||||
|
||||
The NACM user levels apply primarily to NETCONF, with exception of the
|
||||
`admin` group which is granted full system administrator privileges to
|
||||
the underlying UNIX system with the following ACL rules:
|
||||
|
||||
```json
|
||||
...
|
||||
"module-name": "*",
|
||||
"access-operations": "*",
|
||||
"action": "permit",
|
||||
...
|
||||
```
|
||||
|
||||
A user in the `admin` group is allowed to also use a POSIX login shell
|
||||
and use the `sudo` command to perform system administrative commands.
|
||||
This makes it possible to use all the underlying UNIX tooling, which
|
||||
to many can be very useful, in particular when debugging a system, but
|
||||
please remember to use with care -- the system is not built to require
|
||||
managing from the shell. The tools available in the CLI and automated
|
||||
services, started from the system's configuration, are the recommended
|
||||
way of using the system, in addition to NETCONF tooling.
|
||||
|
||||
|
||||
## Changing Hostname
|
||||
|
||||
Notice how the hostname in the prompt does not change until the change
|
||||
@@ -137,3 +203,4 @@ admin@host:/>
|
||||
|
||||
[1]: https://www.rfc-editor.org/rfc/rfc7317
|
||||
[2]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-system%402024-02-29.yang
|
||||
[3]: https://www.rfc-editor.org/rfc/rfc8341
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
Test System Architecture
|
||||
========================
|
||||
|
||||
Tenets
|
||||
------
|
||||
|
||||
- **Keep overhead to a minimum**. Tests should be fast to both write
|
||||
and run. Ideally, the developer should _want_ to add tests early in
|
||||
the development cycle because they instinctively feel that that is
|
||||
the quickest route to arrive at a correct and robust implementation.
|
||||
|
||||
- **Both physical and virtual hardware matters**. Infix is primarily
|
||||
deployed on physical hardware, so being able to run the test suite
|
||||
on real devices is crucial to guarantee a high quality product. At
|
||||
the same time, there is much value in running the same suite on
|
||||
virtual hardware, as it makes it easy to catch regressions early.
|
||||
It is also much more practical and economical to build large virtual
|
||||
networks than physical ones.
|
||||
|
||||
- **Avoid CLI scipting & scraping**. Reliably interacting with a DUT
|
||||
over a serial line in a robust way is _very_ hard to get right.
|
||||
Given that we have a proper API (RESTCONF), we should leverage that
|
||||
when testing. Front-ends can be tested by other means.
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||

|
||||
|
||||
The test system is made up of several independent components, which
|
||||
are typically used in concert to run a full test suite.
|
||||
|
||||
### Test Cases
|
||||
|
||||
A test case is an executable, receiving the physical topology as a
|
||||
positional argument, which produces [TAP][] compliant output on its
|
||||
`stdout`. I.e., it is executed in the following manner:
|
||||
|
||||
test-case [OPTS] <physical-topology>
|
||||
|
||||
Test cases are typically written in Python, using the
|
||||
[Infamy](#infamy) library. Ultimately though, it can be implemented
|
||||
in any language, as long as it matches the calling convention above.
|
||||
|
||||
### Infamy
|
||||
|
||||
Rather than having each test case come up with its own implementation
|
||||
of how to map topologies, how to push NETCONF data to a device, etc.,
|
||||
we provide a library of functions to take care of all that, dubbed
|
||||
"Infamy". When adding a new test case, ask yourself if any parts of
|
||||
it might belong in Infamy as a generalized component that can be
|
||||
reused by other tests.
|
||||
|
||||
Some of the core functions provided by Infamy are:
|
||||
|
||||
- Mapping a logical topology to a physical one
|
||||
- Finding and attaching to a device over an Ethernet interface, using
|
||||
NETCONF
|
||||
- Pushing/pulling NETCONF data to/from a device
|
||||
- Generating TAP compliant output
|
||||
|
||||
### 9PM
|
||||
|
||||
To run multiple tests, we employ [9PM][]. It let's us define test
|
||||
suites as simple YAML files. Suites can also be hierarchically
|
||||
structured, with a suite being made up of other suites, etc.
|
||||
|
||||
It also validates the TAP output, making sure to catch early exits
|
||||
from a case, and produces a nice summary report.
|
||||
|
||||
### `/test/env`
|
||||
|
||||
A good way to ensure that nobody ever runs the test suite is to make
|
||||
it _really_ hard to do so. `/test/env`'s job is instead to make it
|
||||
very _easy_ to create a reproducible environment in which tests can be
|
||||
executed.
|
||||
|
||||
Several technologies are leveraged to accomplish this:
|
||||
|
||||
- **Containers**: The entire execution is optionally done inside a
|
||||
standardized `docker` container environment. This ensures that the
|
||||
software needed to run the test suite is always available, no matter
|
||||
which distribution the user is running on their machine.
|
||||
|
||||
- **Python Virtual Environments**: To make sure that the expected
|
||||
versions of all Python packages are available, the execution is
|
||||
wrapped inside a `venv`. This is true for containerized executions,
|
||||
where the container comes with a pre-installed environment, but it
|
||||
can also be sourced from the host system when running outside of the
|
||||
container.
|
||||
|
||||
- **Virtual Test Topology**: Using [Qeneth][], the environment can
|
||||
optionally be started with a virtual topology of DUTs to run the
|
||||
tests on.
|
||||
|
||||
> `docker` is the only supported container environment when running
|
||||
> tests in the host's network namespace. When running on a virtual
|
||||
> Qeneth topology, `podman` may also be used by installing the
|
||||
> `podman-docker` package from your host system's distro.
|
||||
|
||||
|
||||
Physical and Logical Topologies
|
||||
-------------------------------
|
||||
|
||||
Imagine that we want to create a test with three DUTs; one acting as a
|
||||
DHCP server, and the other two as DHCP clients - with all three having
|
||||
a management connection to the host PC running the test. In other
|
||||
words, the test requires a _logical_ topology like the one below.
|
||||
|
||||
<img align="right" src="img/testing-log.dot.svg" alt="Example Logical Topology">
|
||||
|
||||
```dot
|
||||
graph "dhcp-client-server" {
|
||||
host [
|
||||
label="host | { <c1> c1 | <srv> srv | <c2> c2 }",
|
||||
kind="controller",
|
||||
];
|
||||
|
||||
server [
|
||||
label="{ <mgmt> mgmt } | server | { <c1> c1 | <c2> c2 }",
|
||||
kind="infix",
|
||||
];
|
||||
client1 [
|
||||
label="{ <mgmt> mgmt } | client1 | { <srv> srv }",
|
||||
kind="infix",
|
||||
];
|
||||
client2 [
|
||||
label="{ <mgmt> mgmt } | client2 | { <srv> srv }",
|
||||
kind="infix",
|
||||
];
|
||||
|
||||
host:srv -- server:mgmt
|
||||
host:c1 -- client1:mgmt
|
||||
host:c2 -- client2:mgmt
|
||||
|
||||
server:c1 -- client1:srv;
|
||||
server:c2 -- client2:srv;
|
||||
}
|
||||
```
|
||||
|
||||
When running in a virtualized environment, one could simply create a
|
||||
setup that matches the test's logical topology. But in scenarios when
|
||||
devices are physical systems, connected by real copper cables, this is
|
||||
not possible (unless you have some wicked L1 relay matrix thingy).
|
||||
|
||||
Instead, the test implementation does not concern itself with the
|
||||
exact nodes used to run the test, only that the _logical_ topology can
|
||||
be _mapped_ to some subset of the _physical_ topology. In
|
||||
mathematical terms, the physical topology must contain a subgraph that
|
||||
is _isomorphic_ to the logical topology.
|
||||
|
||||
Standing on the shoulders of giants (i.e. people with mathematics
|
||||
degrees), we can deploy well-known algorithms to find such subgraphs.
|
||||
Continuing our example, let's say we want to run our DHCP test on the
|
||||
_physical_ topology below.
|
||||
|
||||
<img align="right" src="img/testing-phy.dot.svg" alt="Example Physical Topology">
|
||||
|
||||
```dot
|
||||
graph "quad-ring" {
|
||||
host [
|
||||
label="host | { <d1a> d1a | <d1b> d1b | <d1c> d1c | <d2a> d2a | <d2b> d2b | <d2c> d2c | <d3a> d3a | <d3b> d3b | <d3c> d3c | <d4a> d4a | <d4b> d4b | <d4c> d4c }",
|
||||
kind="controller",
|
||||
];
|
||||
|
||||
dut1 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut1 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut2 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut2 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut3 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut3 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut4 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut4 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
|
||||
host:d1a -- dut1:e1
|
||||
host:d1b -- dut1:e2
|
||||
host:d1c -- dut1:e3
|
||||
|
||||
host:d2a -- dut2:e1
|
||||
host:d2b -- dut2:e2
|
||||
host:d2c -- dut2:e3
|
||||
|
||||
host:d3a -- dut3:e1
|
||||
host:d3b -- dut3:e2
|
||||
host:d3c -- dut3:e3
|
||||
|
||||
host:d4a -- dut4:e1
|
||||
host:d4b -- dut4:e2
|
||||
host:d4c -- dut4:e3
|
||||
|
||||
dut1:e5 -- dut2:e4
|
||||
dut2:e5 -- dut3:e4
|
||||
dut3:e5 -- dut4:e4
|
||||
dut4:e5 -- dut1:e4
|
||||
}
|
||||
```
|
||||
|
||||
Our test (in fact, all tests) receives the physical topology as an
|
||||
input parameter, and then maps the desired logical topology onto it,
|
||||
producing a mapping from logical nodes and ports to their physical
|
||||
counterparts.
|
||||
|
||||
```dot
|
||||
{
|
||||
"client1": "dut1",
|
||||
"client1:mgmt": "dut1:e1",
|
||||
"client1:srv": "dut1:e4",
|
||||
"client2": "dut3",
|
||||
"client2:mgmt": "dut3:e2",
|
||||
"client2:srv": "dut3:e5",
|
||||
"host": "host",
|
||||
"host:c1": "host:d1a",
|
||||
"host:c2": "host:d3b",
|
||||
"host:srv": "host:d4c",
|
||||
"server": "dut4",
|
||||
"server:c1": "dut4:e5",
|
||||
"server:c2": "dut4:e4",
|
||||
"server:mgmt": "dut4:e3"
|
||||
}
|
||||
```
|
||||
|
||||
With this information, the test knows that, in this particular
|
||||
environment, the server should be managed via the port called `d4c` on
|
||||
the node called `host`; that the port connected to the server on
|
||||
`client1` is `e4` on `dut1`, etc. Thereby separating the
|
||||
implementation of the test from any specific physical setup.
|
||||
|
||||
Testcases are not required to use a logical topology; they may choose
|
||||
to accept whatever physical topology its given, and dynamically
|
||||
determine the DUTs to use for testing. As an example, an STP test
|
||||
could accept an arbitrary physical topology, run the STP algorithm on
|
||||
it offline, enable STP on all DUTs, and then verify that the resulting
|
||||
spanning tree matches the expected one.
|
||||
|
||||
[9PM]: https://github.com/rical/9pm
|
||||
[Qeneth]: https://github.com/wkz/qeneth
|
||||
[TAP]: https://testanything.org/
|
||||
+130
-284
@@ -7,287 +7,57 @@ that one or more DUTs are configured over NETCONF; the resulting
|
||||
network is then black-box tested by injecting and inspecting network
|
||||
traffic at various points.
|
||||
|
||||
This document is intended to be a practical guide on how to run,
|
||||
develop and debug tests. There is a separate document describing the
|
||||
[Test System Architecture](test-arch.md).
|
||||
|
||||
TL;DR
|
||||
-----
|
||||
|
||||
Build Infix and run the test suite on a set of virtual Infix nodes.
|
||||
Modes of Testing
|
||||
----------------
|
||||
|
||||
### Virtual Devices
|
||||
|
||||
By default, tests are run on a topology made up of virtual Infix nodes
|
||||
using [Qeneth][]. To run the full regression test suite: build Infix
|
||||
for `x86_64`:
|
||||
|
||||
$ make x86_64_defconfig
|
||||
$ make
|
||||
$ make test
|
||||
|
||||
To run a subset of tests, e.g., only the DHCP client tests:
|
||||
### Physical Devices
|
||||
|
||||
$ make test INFIX_TESTS=case/infix_dhcp/all.yaml
|
||||
To run the tests on a preexisting topology from the host's network
|
||||
namespace, specify the `host` `TEST_MODE`:
|
||||
|
||||
> **Note:** see the below section [Quick Start Guide][] for how to
|
||||
> connect to the test system, debug and develop tests, and more.
|
||||
$ make TEST_MODE=host test
|
||||
|
||||
This typically used when testing on physical hardware. By default the
|
||||
topology will be sourced from `/etc/infamy.dot`, but this can be
|
||||
overwritten by setting the `TOPOLOGY` variable:
|
||||
|
||||
$ make TEST_MODE=host TOPOLOGY=~/my-topology.dot test
|
||||
|
||||
|
||||
Tenets
|
||||
------
|
||||
### `make run` Devices
|
||||
|
||||
- **Keep overhead to a minimum**. Tests should be fast to both write
|
||||
and run. Ideally, the developer should _want_ to add tests early in
|
||||
the development cycle because they instinctively feel that that is
|
||||
the quickest route to arrive at a correct and robust implementation.
|
||||
Some tests only require a single DUT. These can therefore be run
|
||||
against an Infix image started from `make run`. This requires that the
|
||||
instance is configured to use TAP networking.
|
||||
|
||||
- **Both physical and virtual hardware matters**. Infix is primarily
|
||||
deployed on physical hardware, so being able to run the test suite
|
||||
on real devices is crucial to guarantee a high quality product. At
|
||||
the same time, there is much value in running the same suite on
|
||||
virtual hardware, as it makes it easy to catch regressions early.
|
||||
It is also much more practical and economical to build large virtual
|
||||
networks than physical ones.
|
||||
When the instance is running, you can open a separate terminal and run
|
||||
the subset of the test suite that can be mapped to it:
|
||||
|
||||
- **Avoid CLI scipting & scraping**. Reliably interacting with a DUT
|
||||
over a serial line in a robust way is _very_ hard to get right.
|
||||
Given that we have a proper API (RESTCONF), we should leverage that
|
||||
when testing. Front-ends can be tested by other means.
|
||||
|
||||
|
||||
Architectural Overview
|
||||
----------------------
|
||||
|
||||

|
||||
|
||||
The test system is made up of several independent components, which
|
||||
are typically used in concert to run a full test suite.
|
||||
|
||||
### Test Cases
|
||||
|
||||
A test case is an executable, receiving the physical topology as a
|
||||
positional argument, which produces [TAP][] compliant output on its
|
||||
`stdout`. I.e., it is executed in the following manner:
|
||||
|
||||
test-case [OPTS] <physical-topology>
|
||||
|
||||
Test cases are typically written in Python, using the
|
||||
[Infamy](#infamy) library. Ultimately though, it can be implemented
|
||||
in any language, as long as it matches the calling convention above.
|
||||
|
||||
### Infamy
|
||||
|
||||
Rather than having each test case come up with its own implementation
|
||||
of how to map topologies, how to push NETCONF data to a device, etc.,
|
||||
we provide a library of functions to take care of all that, dubbed
|
||||
"Infamy". When adding a new test case, ask yourself if any parts of
|
||||
it might belong in Infamy as a generalized component that can be
|
||||
reused by other tests.
|
||||
|
||||
Some of the core functions provided by Infamy are:
|
||||
|
||||
- Mapping a logical topology to a physical one
|
||||
- Finding and attaching to a device over an Ethernet interface, using
|
||||
NETCONF
|
||||
- Pushing/pulling NETCONF data to/from a device
|
||||
- Generating TAP compliant output
|
||||
|
||||
### 9PM
|
||||
|
||||
To run multiple tests, we employ [9PM][]. It let's us define test
|
||||
suites as simple YAML files. Suites can also be hierarchically
|
||||
structured, with a suite being made up of other suites, etc.
|
||||
|
||||
It also validates the TAP output, making sure to catch early exits
|
||||
from a case, and produces a nice summary report.
|
||||
|
||||
### `/test/env`
|
||||
|
||||
A good way to ensure that nobody ever runs the test suite is to make
|
||||
it _really_ hard to do so. `/test/env`'s job is instead to make it
|
||||
very _easy_ to create a reproducible environment in which tests can be
|
||||
executed.
|
||||
|
||||
Several technologies are leveraged to accomplish this:
|
||||
|
||||
- **Containers**: The entire execution is optionally done inside a
|
||||
standardized container environment, using either `podman` or
|
||||
`docker`. This ensures that the software needed to run the test
|
||||
suite is always available, no matter which distribution the user is
|
||||
running on their machine.
|
||||
|
||||
- **Python Virtual Environments**: To make sure that the expected
|
||||
versions of all Python packages are available, the execution is
|
||||
wrapped inside a `venv`. This is true for containerized executions,
|
||||
where the container comes with a pre-installed environment, but it
|
||||
can also be sourced from the host system when running outside of the
|
||||
container.
|
||||
|
||||
- **Virtual Test Topology**: Using [Qeneth][], the environment can
|
||||
optionally be started with a virtual topology of DUTs to run the
|
||||
tests on.
|
||||
$ make TEST_MODE=run test
|
||||
|
||||
|
||||
Interactive Usage
|
||||
-----------------
|
||||
|
||||
Some tests only require a single DUT. These can therefore be run
|
||||
against an Infix image started from `make run`. When the instance is
|
||||
running, you can open a separate terminal and run `make test-run`, to
|
||||
run the subset of the test suite that can be mapped to it.
|
||||
|
||||
Both `make test` and `make test-run` targets have a respective target
|
||||
with a `-sh` suffix. These can be used to start an interactive session
|
||||
in the reproducible environment, which is usually much easier to work
|
||||
with during a debugging session.
|
||||
|
||||
Inside the reproducible environment, a wrapper for Qeneth is created for
|
||||
the running network's directory. E.g., calling `qeneth status` inside a
|
||||
`make test-sh` environment show the expected status information.
|
||||
|
||||
> **Note:** for more information and help writing a test, see the below
|
||||
> [Quick Start Guide][].
|
||||
|
||||
|
||||
Physical and Logical Topologies
|
||||
-------------------------------
|
||||
|
||||
Imagine that we want to create a test with three DUTs; one acting as a
|
||||
DHCP server, and the other two as DHCP clients - with all three having
|
||||
a management connection to the host PC running the test. In other
|
||||
words, the test requires a _logical_ topology like the one below.
|
||||
|
||||
<img align="right" src="img/testing-log.dot.svg" alt="Example Logical Topology">
|
||||
|
||||
```dot
|
||||
graph "dhcp-client-server" {
|
||||
host [
|
||||
label="host | { <c1> c1 | <srv> srv | <c2> c2 }",
|
||||
kind="controller",
|
||||
];
|
||||
|
||||
server [
|
||||
label="{ <mgmt> mgmt } | server | { <c1> c1 | <c2> c2 }",
|
||||
kind="infix",
|
||||
];
|
||||
client1 [
|
||||
label="{ <mgmt> mgmt } | client1 | { <srv> srv }",
|
||||
kind="infix",
|
||||
];
|
||||
client2 [
|
||||
label="{ <mgmt> mgmt } | client2 | { <srv> srv }",
|
||||
kind="infix",
|
||||
];
|
||||
|
||||
host:srv -- server:mgmt
|
||||
host:c1 -- client1:mgmt
|
||||
host:c2 -- client2:mgmt
|
||||
|
||||
server:c1 -- client1:srv;
|
||||
server:c2 -- client2:srv;
|
||||
}
|
||||
```
|
||||
|
||||
When running in a virtualized environment, one could simply create a
|
||||
setup that matches the test's logical topology. But in scenarios when
|
||||
devices are physical systems, connected by real copper cables, this is
|
||||
not possible (unless you have some wicked L1 relay matrix thingy).
|
||||
|
||||
Instead, the test implementation does not concern itself with the
|
||||
exact nodes used to run the test, only that the _logical_ topology can
|
||||
be _mapped_ to some subset of the _physical_ topology. In
|
||||
mathematical terms, the physical topology must contain a subgraph that
|
||||
is _isomorphic_ to the logical topology.
|
||||
|
||||
Standing on the shoulders of giants (i.e. people with mathematics
|
||||
degrees), we can deploy well-known algorithms to find such subgraphs.
|
||||
Continuing our example, let's say we want to run our DHCP test on the
|
||||
_physical_ topology below.
|
||||
|
||||
<img align="right" src="img/testing-phy.dot.svg" alt="Example Physical Topology">
|
||||
|
||||
```dot
|
||||
graph "quad-ring" {
|
||||
host [
|
||||
label="host | { <d1a> d1a | <d1b> d1b | <d1c> d1c | <d2a> d2a | <d2b> d2b | <d2c> d2c | <d3a> d3a | <d3b> d3b | <d3c> d3c | <d4a> d4a | <d4b> d4b | <d4c> d4c }",
|
||||
kind="controller",
|
||||
];
|
||||
|
||||
dut1 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut1 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut2 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut2 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut3 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut3 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
dut4 [
|
||||
label="{ <e1> e1 | <e2> e2 | <e3> e3 } | dut4 | { <e4> e4 | <e5> e5 }",
|
||||
kind="infix",
|
||||
];
|
||||
|
||||
host:d1a -- dut1:e1
|
||||
host:d1b -- dut1:e2
|
||||
host:d1c -- dut1:e3
|
||||
|
||||
host:d2a -- dut2:e1
|
||||
host:d2b -- dut2:e2
|
||||
host:d2c -- dut2:e3
|
||||
|
||||
host:d3a -- dut3:e1
|
||||
host:d3b -- dut3:e2
|
||||
host:d3c -- dut3:e3
|
||||
|
||||
host:d4a -- dut4:e1
|
||||
host:d4b -- dut4:e2
|
||||
host:d4c -- dut4:e3
|
||||
|
||||
dut1:e5 -- dut2:e4
|
||||
dut2:e5 -- dut3:e4
|
||||
dut3:e5 -- dut4:e4
|
||||
dut4:e5 -- dut1:e4
|
||||
}
|
||||
```
|
||||
|
||||
Our test (in fact, all tests) receives the physical topology as an
|
||||
input parameter, and then maps the desired logical topology onto it,
|
||||
producing a mapping from logical nodes and ports to their physical
|
||||
counterparts.
|
||||
|
||||
```dot
|
||||
{
|
||||
"client1": "dut1",
|
||||
"client1:mgmt": "dut1:e1",
|
||||
"client1:srv": "dut1:e4",
|
||||
"client2": "dut3",
|
||||
"client2:mgmt": "dut3:e2",
|
||||
"client2:srv": "dut3:e5",
|
||||
"host": "host",
|
||||
"host:c1": "host:d1a",
|
||||
"host:c2": "host:d3b",
|
||||
"host:srv": "host:d4c",
|
||||
"server": "dut4",
|
||||
"server:c1": "dut4:e5",
|
||||
"server:c2": "dut4:e4",
|
||||
"server:mgmt": "dut4:e3"
|
||||
}
|
||||
```
|
||||
|
||||
With this information, the test knows that, in this particular
|
||||
environment, the server should be managed via the port called `d4c` on
|
||||
the node called `host`; that the port connected to the server on
|
||||
`client1` is `e4` on `dut1`, etc. Thereby separating the
|
||||
implementation of the test from any specific physical setup.
|
||||
|
||||
Testcases are not required to use a logical topology; they may choose
|
||||
to accept whatever physical topology its given, and dynamically
|
||||
determine the DUTs to use for testing. As an example, an STP test
|
||||
could accept an arbitrary physical topology, run the STP algorithm on
|
||||
it offline, enable STP on all DUTs, and then verify that the resulting
|
||||
spanning tree matches the expected one.
|
||||
|
||||
|
||||
Quick Start Guide
|
||||
-----------------
|
||||
|
||||
When developing a test, instead of blindly coding in Python and running
|
||||
`make test` over and over, start a test shell:
|
||||
When developing and debugging tests, the overhead of repeatedly
|
||||
setting up and tearing down the test environment can quickly start to
|
||||
weigh you down. In these situation, you can start an interactive test
|
||||
environment:
|
||||
|
||||
$ make test-sh
|
||||
Info: Generating topology
|
||||
@@ -299,13 +69,28 @@ When developing a test, instead of blindly coding in Python and running
|
||||
Info: Launching dut4
|
||||
11:42:52 infamy0:test #
|
||||
|
||||
The example above uses the default mode (`qeneth`), but the `host` and
|
||||
`run` modes also support the `test-sh` target.
|
||||
|
||||
It takes a little while to start up, but then we have a shell prompt
|
||||
inside the container running Infamy. It's a very limited environment,
|
||||
but it has enough to easily run single tests, connect to the virtual
|
||||
devices, and *step* your code. Let's run a test:
|
||||
devices, and *step* your code.
|
||||
|
||||
|
||||
### Running Subsets of Tests
|
||||
|
||||
Each test case is a separate executable, which can be run without
|
||||
arguments:
|
||||
|
||||
11:42:53 infamy0:test # ./case/infix_dhcp/dhcp_basic.py
|
||||
|
||||
To run a suite of tests, e.g., only the DHCP client tests, pass the
|
||||
suite as an argument to [9PM][]:
|
||||
|
||||
11:42:53 infamy0:test # ./9pm/9pm.py case/infix_dhcp/all.yaml
|
||||
|
||||
|
||||
### Connecting to Infamy
|
||||
|
||||
The test system runs in a Docker container, so to get a shell prompt in
|
||||
@@ -313,6 +98,7 @@ The test system runs in a Docker container, so to get a shell prompt in
|
||||
with a helper script for this:
|
||||
|
||||
$ ./test/shell
|
||||
11:42:53 infamy0:test #
|
||||
|
||||
By default it connect to the latest started Infamy instance. If you for
|
||||
some reason run multiple instances of Infamy the `shell` script takes an
|
||||
@@ -320,6 +106,8 @@ optional argument "system", which is the hostname of the container you
|
||||
want to connect to:
|
||||
|
||||
$ ./test/shell infamy2
|
||||
11:42:53 infamy2:test #
|
||||
|
||||
|
||||
### Connecting to a DUT
|
||||
|
||||
@@ -369,10 +157,47 @@ You can also connect to the console of a DUT from within a `shell`:
|
||||
> the BusyBox version so you press 'e' + enter instead of 'q' to quit.
|
||||
|
||||
|
||||
### Debug a Test
|
||||
### Attaching to MACVLANs
|
||||
|
||||
First, add a Python `breakpoint()` to your test and run it from your
|
||||
`make test-sh` Infamy instance:
|
||||
To fully isolate the host's interfaces from one another, many tests
|
||||
will stack a MACVLAN on an interface, which is then placed in a
|
||||
separate network namespace.
|
||||
|
||||
It is often useful to attach to those namespaces, so that you can
|
||||
interactively inject traffic into the test setup.
|
||||
|
||||
First, connect to the Infamy instance in question:
|
||||
|
||||
$ ./test/shell
|
||||
11:43:19 infamy0:test #
|
||||
|
||||
Then, attach to the MACVLAN namespace by running the `nsenter` helper
|
||||
script from the test directory, supplying the base interface name as
|
||||
the first argument:
|
||||
|
||||
11:43:19 infamy0:test # ./nsenter d1b
|
||||
11:43:20 infamy0(d1b):test #
|
||||
|
||||
By default, an interactive shell is started, but you can also supply
|
||||
another command:
|
||||
|
||||
11:43:19 infamy0:test # ./nsenter d1b ip -br addr
|
||||
lo UNKNOWN 127.0.0.1/8 ::1/128
|
||||
iface@if7 UP 10.0.0.1/24 fe80::38d0:88ff:fe77:b7cd/64
|
||||
|
||||
You can now freely debug the network activity of your test and the
|
||||
responses from the DUT.
|
||||
|
||||
|
||||
### Using the Python Debugger
|
||||
|
||||
The built in `breakpoint()` function in Python is very useful when you
|
||||
want to run a test case to a certain point at which you might want to
|
||||
interactively inspect either the test's or the device's state.
|
||||
|
||||
Simply insert a call to `breakpoint()` at the point of interest in
|
||||
your test and run it as normal. Once Python executes the call, it will
|
||||
drop you into the Python debugger:
|
||||
|
||||
11:42:58 infamy0:test # ./case/infix_dhcp/dhcp_basic.py
|
||||
# Starting (2024-02-10 11:42:59)
|
||||
@@ -382,34 +207,55 @@ First, add a Python `breakpoint()` to your test and run it from your
|
||||
> /home/jocke/src/infix/test/case/infix_dhcp/dhcp_basic.py(44)<module>()
|
||||
(Pdb)
|
||||
|
||||
You are now in the Python debugger, Pdb.
|
||||
At this point you have full access to the test's state, but it is also
|
||||
an opportunity to inspect the state of the DUTs (e.g. via their
|
||||
console or over SSH).
|
||||
|
||||
### Debug a Test in a MacVLAN
|
||||
It is also possible to run a test under Pdb from the get-go, if you
|
||||
want to setup breakpoints without modifying the source, or simply step
|
||||
through the code:
|
||||
|
||||
Most tests use some sort of network connection to the DUTs. From a test
|
||||
shell you cannot see or debug that connection by default. So you need
|
||||
to employ a little trick.
|
||||
11:42:58 infamy0:test # python -m pdb case/infix_dhcp/dhcp_basic.py
|
||||
|
||||
Open another terminal, and start a test shell in your Infamy instance:
|
||||
|
||||
$ ./test/shell
|
||||
11:43:19 infamy0:test #
|
||||
### Deterministic Topology Mappings
|
||||
|
||||
MacVLAN interfaces created by Infamy run in another network namespace,
|
||||
to enter it we can look for a sleeper process:
|
||||
By default, mappings from logical to physical topologies are not
|
||||
stable across test case executions. This can be very frustrating when
|
||||
debugging a failing test, since logical nodes are suffled around
|
||||
between phyical nodes. In such cases, supplying a `PYTHONHASHSEED`
|
||||
variable (set to any 32-bit unsigned integer) when launching the test
|
||||
environment will make sure that topology mappings are deterministic:
|
||||
|
||||
11:43:20 infamy0:test # nsenter -n U -t $(pidof sleep infinity)
|
||||
$ make PYTHONHASHSEED=0 test-sh
|
||||
|
||||
You are now one step further down:
|
||||
If a seed is not supplied, a random value is chosen. This seed is
|
||||
logged by the `meta/reproducible.py` test case when running a test
|
||||
suite:
|
||||
|
||||
infamy0:/home/jocke/src/infix/test# ip -br a
|
||||
lo UNKNOWN 127.0.0.1/8 ::1/128
|
||||
iface@if7 UP 10.0.0.1/24 fe80::38d0:88ff:fe77:b7cd/64
|
||||
$ make test
|
||||
Info: Generating topology
|
||||
Info: Generating node YAML
|
||||
Info: Generating executables
|
||||
Info: Launching dut1
|
||||
Info: Launching dut2
|
||||
Info: Launching dut3
|
||||
Info: Launching dut4
|
||||
9PM - Simplicity is the ultimate sophistication
|
||||
|
||||
You can now freely debug the network activity of your test and the
|
||||
responses from the DUT.
|
||||
Starting test 0002-reproducible.py
|
||||
2024-05-03 10:40:30 # Starting (2024-05-03 10:40:30)
|
||||
2024-05-03 10:40:30 # Specify PYTHONHASHSEED=3773822171 to reproduce this test environment
|
||||
2024-05-03 10:40:30 ok 1 - $PYTHONHASHSEED is set
|
||||
2024-05-03 10:40:30 # Exiting (2024-05-03 10:40:30)
|
||||
2024-05-03 10:40:30 1..1
|
||||
...
|
||||
|
||||
This is useful because this value can then be used to rerun a test (or
|
||||
the whole suite) with identical topology mappings:
|
||||
|
||||
$ make PYTHONHASHSEED=3773822171 INFIX_TESTS=case/ietf_system/hostname.py test
|
||||
|
||||
|
||||
[9PM]: https://github.com/rical/9pm
|
||||
[Qeneth]: https://github.com/wkz/qeneth
|
||||
[TAP]: https://testanything.org/
|
||||
|
||||
+4
-2
@@ -1,10 +1,12 @@
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-httpd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/execd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/gencert/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/statd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/greenpak-programmer/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/iito/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/k8s-logger/Config.in"
|
||||
@@ -12,13 +14,13 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/keyack/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-infix/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/landing/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/libsrx/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/lowdown/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/mcd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/mdns-alias/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/netbrowse/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/greenpak-programmer/Config.in"
|
||||
|
||||
@@ -7,7 +7,7 @@ run name:bootstrap log:prio:user.notice norestart <pid/syslogd> \
|
||||
run name:error :1 log:console norestart if:<run/bootstrap/failure> \
|
||||
[S] /usr/libexec/confd/error --
|
||||
|
||||
service name:confd log <run/bootstrap/success> \
|
||||
service name:confd log:prio:daemon.err <run/bootstrap/success> \
|
||||
[S12345] sysrepo-plugind -f -p /run/confd.pid -n -- Configuration daemon
|
||||
|
||||
# Bootstrap system with startup-config
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
sha256 518cd23d81f17b912f1c4ccc6acb67ff614ddcc2caf14def5044126d1a60f364 LICENSE
|
||||
@@ -0,0 +1,8 @@
|
||||
config BR2_PACKAGE_GENCERT
|
||||
bool "gencert"
|
||||
select BR2_PACKAGE_OPENSSL
|
||||
help
|
||||
Generate a self-signed certificate for embedded systems confused
|
||||
about the current time. Start date: 2000-01-01, end: 9999-01-01
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
@@ -0,0 +1 @@
|
||||
sha256 fff5e150e496c6bb6035ae388ee13cf2d0df842335e5145a4b902ef6b7892088 LICENSE
|
||||
@@ -0,0 +1,22 @@
|
||||
################################################################################
|
||||
#
|
||||
# gencert
|
||||
#
|
||||
################################################################################
|
||||
|
||||
GENCERT_VERSION = 1.0
|
||||
GENCERT_SITE_METHOD = local
|
||||
GENCERT_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/gencert
|
||||
GENCERT_LICENSE = ISC
|
||||
GENCERT_LICENSE_FILES = LICENSE
|
||||
GENCERT_REDISTRIBUTE = NO
|
||||
GENCERT_DEPENDENCIES = host-pkgconf libopenssl
|
||||
GENCERT_AUTORECONF = YES
|
||||
|
||||
define GENCERT_CONF_ENV
|
||||
CFLAGS="$(INFIX_CFLAGS)"
|
||||
endef
|
||||
|
||||
GENCERT_CONF_OPTS = --prefix= --disable-silent-rules
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -0,0 +1,6 @@
|
||||
config BR2_PACKAGE_LANDING
|
||||
bool "Landing page (temporary)"
|
||||
help
|
||||
Temporary landing page before upcoming webui.
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
@@ -0,0 +1 @@
|
||||
sha256 fff5e150e496c6bb6035ae388ee13cf2d0df842335e5145a4b902ef6b7892088 LICENSE
|
||||
@@ -0,0 +1,18 @@
|
||||
################################################################################
|
||||
#
|
||||
# landing
|
||||
#
|
||||
################################################################################
|
||||
|
||||
LANDING_VERSION = 1.0
|
||||
LANDING_SITE_METHOD = local
|
||||
LANDING_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/landing
|
||||
LANDING_LICENSE = ISC
|
||||
LANDING_LICENSE_FILES = LICENSE
|
||||
|
||||
define LANDING_INSTALL_TARGET_CMDS
|
||||
cp $(@D)/*.html $(TARGET_DIR)/usr/html/
|
||||
cp $(@D)/*.png $(TARGET_DIR)/usr/html/
|
||||
endef
|
||||
|
||||
$(eval $(generic-package))
|
||||
@@ -1,2 +1,2 @@
|
||||
sha256 818c003ff153d914a829cd169a7cddb06643f423ebbf8b9e3932aad34c5ed60d mcd-2.1.tar.gz
|
||||
sha256 99a0480db163445c5a1a5bf7f85bc37cbb5be8c40e9e441291ad78e8d4252d0b LICENSE
|
||||
sha256 dcd639c77689c432e84e63267202c00958fb1032e066ae355e3cbc68d9fcd063 mcd-2.3.tar.gz
|
||||
sha256 99a0480db163445c5a1a5bf7f85bc37cbb5be8c40e9e441291ad78e8d4252d0b LICENSE
|
||||
|
||||
+2
-1
@@ -4,10 +4,11 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
MCD_VERSION = 2.1
|
||||
MCD_VERSION = 2.3
|
||||
MCD_SITE = https://github.com/kernelkit/mcd/releases/download/v$(MCD_VERSION)
|
||||
MCD_LICENSE = BSD-3-Clause
|
||||
MCD_LICENSE_FILES = LICENSE
|
||||
MCD_CONF_OPTS = --disable-silent-rules --with-group=wheel
|
||||
|
||||
define MCD_INSTALL_CONFIG
|
||||
$(INSTALL) -D -m 0644 $(@D)/mcd.conf $(TARGET_DIR)/etc/mcd.conf
|
||||
|
||||
@@ -1 +1 @@
|
||||
sha256 755d3a387cd124ff34e2b73cc58e7cec4d8d85ae6c295e30ffeb8d36eacecb1d LICENSE
|
||||
sha256 360336cbf0f228b12b7ca0996b33e442d97f496edcf2ec31b655e63631e7f96f LICENSE
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
PYTHON_STATD_VERSION = 1.0
|
||||
PYTHON_STATD_SITE_METHOD = local
|
||||
PYTHON_STATD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/statd/python
|
||||
STATD_LICENSE = BSD-3-Clause
|
||||
STATD_LICENSE_FILES = LICENSE
|
||||
PYTHON_STATD_LICENSE = BSD-3-Clause
|
||||
PYTHON_STATD_LICENSE_FILES = LICENSE
|
||||
PYTHON_STATD_DEPENDENCIES = host-python3 python3 host-python-poetry-core
|
||||
PYTHON_STATD_SETUP_TYPE = pep517 # poetry
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
task [2] run-parts /cfg/user-scripts.d -- Running user startup scripts
|
||||
@@ -0,0 +1,25 @@
|
||||
root:x:0:
|
||||
daemon:x:1:
|
||||
bin:x:2:
|
||||
sys:x:3:
|
||||
adm:x:4:
|
||||
tty:x:5:
|
||||
disk:x:6:
|
||||
lp:x:7:
|
||||
mail:x:8:
|
||||
kmem:x:9:
|
||||
wheel:x:10:root
|
||||
cdrom:x:11:
|
||||
dialout:x:18:
|
||||
floppy:x:19:
|
||||
video:x:28:
|
||||
audio:x:29:
|
||||
tape:x:32:
|
||||
www-data:x:33:
|
||||
backup:x:34:
|
||||
utmp:x:43:
|
||||
plugdev:x:46:
|
||||
lock:x:54:
|
||||
netdev:x:82:
|
||||
users:x:100:
|
||||
nobody:x:65534:
|
||||
@@ -0,0 +1,9 @@
|
||||
root:x:0:0:root:/root:/bin/sh
|
||||
daemon:x:1:1:daemon:/usr/sbin:/bin/false
|
||||
bin:x:2:2:bin:/bin:/bin/false
|
||||
sys:x:3:3:sys:/dev:/bin/false
|
||||
sync:x:4:100:sync:/bin:/bin/sync
|
||||
mail:x:8:8:mail:/var/spool/mail:/bin/false
|
||||
www-data:x:33:33:www-data:/var/www:/bin/false
|
||||
backup:x:34:34:backup:/var/backups:/bin/false
|
||||
nobody:x:65534:65534:nobody:/home:/bin/false
|
||||
@@ -0,0 +1,9 @@
|
||||
root::::::::
|
||||
daemon:*:::::::
|
||||
bin:*:::::::
|
||||
sys:*:::::::
|
||||
sync:*:::::::
|
||||
mail:*:::::::
|
||||
www-data:*:::::::
|
||||
backup:*:::::::
|
||||
nobody:*:::::::
|
||||
@@ -1 +1,3 @@
|
||||
#set DEBUG=1
|
||||
|
||||
service name:statd log [S12345] <pid/confd> statd -f -p /run/statd.pid -n -- Status daemon
|
||||
|
||||
@@ -1 +1 @@
|
||||
sha256 755d3a387cd124ff34e2b73cc58e7cec4d8d85ae6c295e30ffeb8d36eacecb1d LICENSE
|
||||
sha256 360336cbf0f228b12b7ca0996b33e442d97f496edcf2ec31b655e63631e7f96f LICENSE
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
From 50fafdc63dc3d6152e2494cc693871e9bd04bfe5 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 5 Mar 2024 09:41:46 +0100
|
||||
Subject: [PATCH 1/2] iplink_bridge: add mcast_flood_always bridge option
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
- Break out boolopt handling to simplify parsing and setting
|
||||
- Add set/get support for mcast_flood_always
|
||||
- Add get support for mst_enabled
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
include/uapi/linux/if_bridge.h | 1 +
|
||||
ip/iplink_bridge.c | 75 +++++++++++++++++++++++++---------
|
||||
man/man8/ip-link.8.in | 12 ++++++
|
||||
3 files changed, 68 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
|
||||
index adb75f7d..611ab413 100644
|
||||
--- a/include/uapi/linux/if_bridge.h
|
||||
@@ -153,3 +170,6 @@ index 6764a9ad..8f77c5ad 100644
|
||||
.BI mcast_snooping " MULTICAST_SNOOPING "
|
||||
- turn multicast snooping on
|
||||
.RI ( MULTICAST_SNOOPING " > 0) "
|
||||
--
|
||||
2.34.1
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From 226a8b532fc074165ba76d71c4488629daed2625 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 20 May 2024 21:35:11 +0200
|
||||
Subject: [PATCH 2/2] ipaddress: accept symbolic names also for show
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This is a follow-up to 709063e, which in turn was a follow-up to
|
||||
bdb8d85, to add support for 'ip addr show proto static', where
|
||||
'static' is defined in /etc/iproute2/rt_addrprotos.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
ip/ipaddress.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
|
||||
index e536912f..19900157 100644
|
||||
--- a/ip/ipaddress.c
|
||||
+++ b/ip/ipaddress.c
|
||||
@@ -2217,7 +2217,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
||||
__u8 proto;
|
||||
|
||||
NEXT_ARG();
|
||||
- if (get_u8(&proto, *argv, 0))
|
||||
+ if (rtnl_addrprot_a2n(&proto, *argv))
|
||||
invarg("\"proto\" value is invalid\n", *argv);
|
||||
filter.have_proto = true;
|
||||
filter.proto = proto;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 79abf7872e35080ca5b519bb4ad2acc1fbd96e8c Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 25 Jan 2024 21:36:59 +0100
|
||||
Subject: [PATCH 01/27] net: phy: add support for PHY LEDs polarity modes
|
||||
Subject: [PATCH 01/30] net: phy: add support for PHY LEDs polarity modes
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Add support for PHY LEDs polarity modes. Some PHY require LED to be set
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 424ddb5d5d8ce06c578cc08cbedf519c42dd8b69 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 4 Dec 2023 11:08:11 +0100
|
||||
Subject: [PATCH 02/27] net: mvmdio: Support setting the MDC frequency on XSMI
|
||||
Subject: [PATCH 02/30] net: mvmdio: Support setting the MDC frequency on XSMI
|
||||
controllers
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 337cf21833cef6ab456a8562338de88ab1a84ead Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:23 +0100
|
||||
Subject: [PATCH 03/27] net: dsa: mv88e6xxx: Create API to read a single stat
|
||||
Subject: [PATCH 03/30] net: dsa: mv88e6xxx: Create API to read a single stat
|
||||
counter
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From dbdbfd57998b4f8224146ac94cd5d0a577326087 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:25 +0100
|
||||
Subject: [PATCH 04/27] net: dsa: mv88e6xxx: Give each hw stat an ID
|
||||
Subject: [PATCH 04/30] net: dsa: mv88e6xxx: Give each hw stat an ID
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
With the upcoming standard counter group support, we are no longer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 26815572016d9851ec6362f23746035fb933acf3 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:26 +0100
|
||||
Subject: [PATCH 05/27] net: dsa: mv88e6xxx: Add "eth-mac" counter group
|
||||
Subject: [PATCH 05/30] net: dsa: mv88e6xxx: Add "eth-mac" counter group
|
||||
support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From cc5badac76e76692eb516a5c086fcf54a5a93080 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:27 +0100
|
||||
Subject: [PATCH 06/27] net: dsa: mv88e6xxx: Limit histogram counters to
|
||||
Subject: [PATCH 06/30] net: dsa: mv88e6xxx: Limit histogram counters to
|
||||
ingress traffic
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 35ecc84237bfccbe5b93c0aef6c07cc506d43070 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:28 +0100
|
||||
Subject: [PATCH 07/27] net: dsa: mv88e6xxx: Add "rmon" counter group support
|
||||
Subject: [PATCH 07/30] net: dsa: mv88e6xxx: Add "rmon" counter group support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Report the applicable subset of an mv88e6xxx port's counters using
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 7750d0a5bfae46ab783e8e7087b70175860f808c Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 19:44:32 +0100
|
||||
Subject: [PATCH 09/27] net: dsa: mv88e6xxx: Add LED infrastructure
|
||||
Subject: [PATCH 09/30] net: dsa: mv88e6xxx: Add LED infrastructure
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Parse DT for LEDs and register them for devices that support it,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 63fcd626fdb108d2ac07cb0aa16b91fc43894bff Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 21:59:35 +0100
|
||||
Subject: [PATCH 10/27] net: dsa: mv88e6xxx: Add LED support for 6393X
|
||||
Subject: [PATCH 10/30] net: dsa: mv88e6xxx: Add LED support for 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Trigger support:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 0bc6f19d18d7c0e374c824bcc86433b04210a378 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Mar 2024 10:27:24 +0100
|
||||
Subject: [PATCH 11/27] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
|
||||
Subject: [PATCH 11/30] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
|
||||
6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From fe60e3ad1e3b43a924c311658b15a1106e813661 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 16 Jan 2024 16:00:55 +0100
|
||||
Subject: [PATCH 12/27] net: dsa: Support MDB memberships whose L2 addresses
|
||||
Subject: [PATCH 12/30] net: dsa: Support MDB memberships whose L2 addresses
|
||||
overlap
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 5f5bf4a50e98c5aff05fe85994a981253ae85987 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 19 Sep 2023 18:38:10 +0200
|
||||
Subject: [PATCH 13/27] net: phy: marvell10g: Support firmware loading on
|
||||
Subject: [PATCH 13/30] net: phy: marvell10g: Support firmware loading on
|
||||
88X3310
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 27d5241d3ddf70d65af5f4dd029f99f0fea866a5 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 21 Nov 2023 20:15:24 +0100
|
||||
Subject: [PATCH 14/27] net: phy: marvell10g: Fix power-up when strapped to
|
||||
Subject: [PATCH 14/30] net: phy: marvell10g: Fix power-up when strapped to
|
||||
start powered down
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From e389ee690ce56ef20863aeabdf389bed842d7f42 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 15 Nov 2023 20:58:42 +0100
|
||||
Subject: [PATCH 15/27] net: phy: marvell10g: Add LED support for 88X3310
|
||||
Subject: [PATCH 15/30] net: phy: marvell10g: Add LED support for 88X3310
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Pickup the LEDs from the state in which the hardware reset or
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 3113b64290b5b7b20c294535c12ea4c732a02f51 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Dec 2023 09:51:05 +0100
|
||||
Subject: [PATCH 16/27] net: phy: marvell10g: Support LEDs tied to a single
|
||||
Subject: [PATCH 16/30] net: phy: marvell10g: Support LEDs tied to a single
|
||||
media side
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 2570c2350d3d614a31e14dd87d0e99e8fcb5096b Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 24 Nov 2023 23:29:55 +0100
|
||||
Subject: [PATCH 17/27] nvmem: layouts: onie-tlv: Let device probe even when
|
||||
Subject: [PATCH 17/30] nvmem: layouts: onie-tlv: Let device probe even when
|
||||
TLV is invalid
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 681ce95c15bff94ac83eb26db3c718594f8dfa16 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 4 Mar 2024 16:47:28 +0100
|
||||
Subject: [PATCH 18/27] net: bridge: avoid classifying unknown multicast as
|
||||
Subject: [PATCH 18/30] net: bridge: avoid classifying unknown multicast as
|
||||
mrouters_only
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 2482848726a5b8185a04d90891693a1713f894b5 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 5 Mar 2024 06:44:41 +0100
|
||||
Subject: [PATCH 19/27] net: bridge: Ignore router ports when forwarding L2
|
||||
Subject: [PATCH 19/30] net: bridge: Ignore router ports when forwarding L2
|
||||
multicast
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 25efcdb13ae720ee662f4b6091b270e48ac4d375 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 21 Mar 2024 19:12:15 +0100
|
||||
Subject: [PATCH 20/27] net: dsa: Support EtherType based priority overrides
|
||||
Subject: [PATCH 20/30] net: dsa: Support EtherType based priority overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 213e9a1d9145723897fbba40fc4afc5b5f70c1de Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 22 Mar 2024 16:15:43 +0100
|
||||
Subject: [PATCH 21/27] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
Subject: [PATCH 21/30] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 1c1c81864c9803831c2d5b7df0d7da28e566f3b2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 10:10:19 +0100
|
||||
Subject: [PATCH 22/27] net: phy: Do not resume PHY when attaching
|
||||
Subject: [PATCH 22/30] net: phy: Do not resume PHY when attaching
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The PHY should not start negotiating with its link-partner until
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From b53e5007cd5be42eb5d9a510d63f89c7c6edd9b6 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 15:52:43 +0100
|
||||
Subject: [PATCH 23/27] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
Subject: [PATCH 23/30] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
perf on 6393
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From f53652205b1c044fa00f896d6422c82ac808f16a Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 4 Apr 2024 16:36:30 +0200
|
||||
Subject: [PATCH 24/27] net: bridge: drop delay for applying strict multicast
|
||||
Subject: [PATCH 24/30] net: bridge: drop delay for applying strict multicast
|
||||
filtering
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 56208d4cba23496c09f69961a32b1b9662f06aef Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 22 Apr 2024 23:18:01 +0200
|
||||
Subject: [PATCH 25/27] net: dsa: mv88e6xxx: Honor ports being managed via
|
||||
Subject: [PATCH 25/30] net: dsa: mv88e6xxx: Honor ports being managed via
|
||||
in-band-status
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 04023a449a6894c0ec46e246c52e94566b3be4b3 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 24 Apr 2024 21:35:26 +0200
|
||||
Subject: [PATCH 26/27] net: dsa: mv88e6xxx: Fix port policy config on 6393X
|
||||
Subject: [PATCH 26/30] net: dsa: mv88e6xxx: Fix port policy config on 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
mv88e6393x_port_policy_{read,write} expect the `pointer` argument to
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 7529102af1693138349032b7d1339d91d2b6a578 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 24 Apr 2024 22:41:04 +0200
|
||||
Subject: [PATCH 27/27] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
|
||||
Subject: [PATCH 27/30] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
|
||||
ports on 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
From c446111df33d9d6064395e37235bbbeee422358e Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 29 Apr 2024 15:14:51 +0200
|
||||
Subject: [PATCH 28/30] usb: core: adjust log level for unauthorized devices
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The fact that a USB device currently is not authorized is not an error,
|
||||
so let's adjust the log level so these messages slip below radar for the
|
||||
commonly used 'quiet' log level.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/usb/core/driver.c | 4 ++--
|
||||
drivers/usb/core/generic.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
|
||||
index f58a0299fb3b..46450d806373 100644
|
||||
--- a/drivers/usb/core/driver.c
|
||||
+++ b/drivers/usb/core/driver.c
|
||||
@@ -332,10 +332,10 @@ static int usb_probe_interface(struct device *dev)
|
||||
return error;
|
||||
|
||||
if (udev->authorized == 0) {
|
||||
- dev_err(&intf->dev, "Device is not authorized for usage\n");
|
||||
+ dev_warn(&intf->dev, "Device is not authorized for usage\n");
|
||||
return error;
|
||||
} else if (intf->authorized == 0) {
|
||||
- dev_err(&intf->dev, "Interface %d is not authorized for usage\n",
|
||||
+ dev_warn(&intf->dev, "Interface %d is not authorized for usage\n",
|
||||
intf->altsetting->desc.bInterfaceNumber);
|
||||
return error;
|
||||
}
|
||||
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
|
||||
index 740342a2812a..2682bcf3e79f 100644
|
||||
--- a/drivers/usb/core/generic.c
|
||||
+++ b/drivers/usb/core/generic.c
|
||||
@@ -231,7 +231,7 @@ int usb_generic_driver_probe(struct usb_device *udev)
|
||||
* with the driver core and lets interface drivers bind to them.
|
||||
*/
|
||||
if (udev->authorized == 0)
|
||||
- dev_err(&udev->dev, "Device is not authorized for usage\n");
|
||||
+ dev_warn(&udev->dev, "Device is not authorized for usage\n");
|
||||
else {
|
||||
c = usb_choose_configuration(udev);
|
||||
if (c >= 0) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
From eeeab4de57f77712ca5f920e03a68aa5e426784c Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 15 May 2024 13:50:58 +0200
|
||||
Subject: [PATCH 29/30] net: dsa: mv88e6xxx: Grab register lock during counter
|
||||
snapshotting
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This was missing for the standard counter groups. Since no caller
|
||||
already holds the lock, opt for pushing the locking down into
|
||||
mv88e6xxx_stats_snapshot() rather than having it duplicated at each
|
||||
call site.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 29691280cff4..4916d8344a5a 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -950,10 +950,15 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
|
||||
|
||||
static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
+ int err;
|
||||
+
|
||||
if (!chip->info->ops->stats_snapshot)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- return chip->info->ops->stats_snapshot(chip, port);
|
||||
+ mv88e6xxx_reg_lock(chip);
|
||||
+ err = chip->info->ops->stats_snapshot(chip, port);
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
#define MV88E6XXX_HW_STAT_MAPPER(_fn) \
|
||||
@@ -1325,10 +1330,7 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
int ret;
|
||||
|
||||
- mv88e6xxx_reg_lock(chip);
|
||||
-
|
||||
ret = mv88e6xxx_stats_snapshot(chip, port);
|
||||
- mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
if (ret < 0)
|
||||
return;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
From 52eabcd2cfb30013d43ef72c2ec09c76043a0f4a Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 May 2024 14:51:54 +0200
|
||||
Subject: [PATCH 30/30] net: bridge: Differentiate MDB additions from
|
||||
modifications
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, the reception of an IGMPv3 report (and analogously
|
||||
for MLDv2) that adds a new group, would trigger two MDB RTM_NEWMDB
|
||||
notifications from br_ip4_multicast_igmp3_report():
|
||||
|
||||
1. In br_ip4_multicast_add_group() when creating the entry
|
||||
2. Directly at the end of br_ip4_multicast_igmp3_report(), as the new
|
||||
group is also deemed to be "changed"
|
||||
|
||||
The corresponding switchdev notifications generated by these present a
|
||||
problem for drivers wanting to reference count group memberships,
|
||||
since logically there is only a single reference to the group. Indeed,
|
||||
when the membership eventually times out, only a single RTM_DELMDB is
|
||||
generated.
|
||||
|
||||
Therefore, discriminate new groups from changes to existing groups by
|
||||
introducing a RTM_SETMDB events to be used in the latter scenario.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/uapi/linux/rtnetlink.h | 2 ++
|
||||
net/bridge/br_mdb.c | 4 ++--
|
||||
net/bridge/br_multicast.c | 8 ++++----
|
||||
3 files changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
|
||||
index 51c13cf9c5ae..fbc8fd1d5f2c 100644
|
||||
--- a/include/uapi/linux/rtnetlink.h
|
||||
+++ b/include/uapi/linux/rtnetlink.h
|
||||
@@ -134,6 +134,8 @@ enum {
|
||||
#define RTM_DELMDB RTM_DELMDB
|
||||
RTM_GETMDB = 86,
|
||||
#define RTM_GETMDB RTM_GETMDB
|
||||
+ RTM_SETMDB = 87,
|
||||
+#define RTM_SETMDB RTM_SETMDB
|
||||
|
||||
RTM_NEWNSID = 88,
|
||||
#define RTM_NEWNSID RTM_NEWNSID
|
||||
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
|
||||
index 7305f5f8215c..a2882b126ecb 100644
|
||||
--- a/net/bridge/br_mdb.c
|
||||
+++ b/net/bridge/br_mdb.c
|
||||
@@ -724,7 +724,7 @@ static int br_mdb_replace_group_sg(const struct br_mdb_config *cfg,
|
||||
else
|
||||
del_timer(&pg->timer);
|
||||
|
||||
- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -945,7 +945,7 @@ static int br_mdb_replace_group_star_g(const struct br_mdb_config *cfg,
|
||||
else
|
||||
del_timer(&pg->timer);
|
||||
|
||||
- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB);
|
||||
|
||||
if (br_multicast_should_handle_mode(brmctx, cfg->group.proto))
|
||||
br_multicast_star_g_handle_mode(pg, cfg->filter_mode);
|
||||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
||||
index 8fcd8faf99f3..7ba1eee1a024 100644
|
||||
--- a/net/bridge/br_multicast.c
|
||||
+++ b/net/bridge/br_multicast.c
|
||||
@@ -618,7 +618,7 @@ static void br_multicast_fwd_src_handle(struct net_bridge_group_src *src)
|
||||
sg_mp = br_mdb_ip_get(src->br, &sg_key.addr);
|
||||
if (!sg_mp)
|
||||
return;
|
||||
- br_mdb_notify(src->br->dev, sg_mp, sg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(src->br->dev, sg_mp, sg, RTM_SETMDB);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,7 +885,7 @@ static void br_multicast_port_group_expired(struct timer_list *t)
|
||||
|
||||
if (WARN_ON(!mp))
|
||||
goto out;
|
||||
- br_mdb_notify(br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(br->dev, mp, pg, RTM_SETMDB);
|
||||
}
|
||||
out:
|
||||
spin_unlock(&br->multicast_lock);
|
||||
@@ -2888,7 +2888,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge_mcast *brmctx,
|
||||
break;
|
||||
}
|
||||
if (changed)
|
||||
- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB);
|
||||
unlock_continue:
|
||||
spin_unlock(&brmctx->br->multicast_lock);
|
||||
}
|
||||
@@ -3030,7 +3030,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
|
||||
break;
|
||||
}
|
||||
if (changed)
|
||||
- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB);
|
||||
unlock_continue:
|
||||
spin_unlock(&brmctx->br->multicast_lock);
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
From 49c660c412342e1af76735e75cd3f286ae655b82 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 28 Mar 2023 10:37:53 +0200
|
||||
Subject: [PATCH 1/4] sysrepo-plugind: add support for running in foreground
|
||||
Subject: [PATCH 1/5] sysrepo-plugind: add support for running in foreground
|
||||
with syslog
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
From 87224ddce4ed1a118b3efb24e0dc7167f8754c22 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 7 Jun 2023 15:19:13 +0200
|
||||
Subject: [PATCH 2/4] Refactor _sr_install_modules() to use
|
||||
Subject: [PATCH 2/5] Refactor _sr_install_modules() to use
|
||||
ly_ctx_load_module()
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
From 2d3b9524b1448dd6a8ef83e4e101e509d2552dcc Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Fri, 16 Jun 2023 12:13:16 +0200
|
||||
Subject: [PATCH 3/4] Add support for loading /etc/sysrepo/factory-default
|
||||
Subject: [PATCH 3/5] Add support for loading /etc/sysrepo/factory-default
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Follow-up to 3d07270 which adds support for compile-time defaults, this
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 7726017815243818f07936e4ff3bb979e9291f04 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Fri, 16 Jun 2023 16:17:27 +0200
|
||||
Subject: [PATCH 4/4] sysrepoctl: add support for -Cfactory -d running
|
||||
Subject: [PATCH 4/5] sysrepoctl: add support for -Cfactory -d running
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
From 49b558067ab7c6f59ec84f14cc89201b4a7bde57 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 7 May 2024 15:41:53 +0200
|
||||
Subject: [PATCH 5/5] Allow SR_EV_DONE to return any error to sysrepocfg
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Importing a system configuration with sysrepocfg the model callbacks do
|
||||
their best to validate the configuration and prepare the transaction in
|
||||
SR_EV_CHANGE. In cases when dealing with a complex system, like adding
|
||||
a route, address, or other change using iproute2, we may still get into
|
||||
trouble when actually sending off the transaction in SR_EV_DONE.
|
||||
|
||||
If something does go wrong we'd like to know this by the exit code of
|
||||
sysrepocfg, not by inspecting logs or expected system state.
|
||||
|
||||
This patch is a clumsy way of forcing the (first) error to bubble up to
|
||||
the surface and cause a non-zero exit code from sysrepocfg.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/shm_sub.c | 36 ++++++++++++++++++++++++++++--------
|
||||
src/shm_sub.h | 2 +-
|
||||
src/sysrepo.c | 2 +-
|
||||
3 files changed, 30 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/shm_sub.c b/src/shm_sub.c
|
||||
index 99b2be37..298d7dd3 100644
|
||||
--- a/src/shm_sub.c
|
||||
+++ b/src/shm_sub.c
|
||||
@@ -1586,7 +1586,7 @@ cleanup:
|
||||
|
||||
sr_error_info_t *
|
||||
sr_shmsub_change_notify_change_done(struct sr_mod_info_s *mod_info, const char *orig_name, const void *orig_data,
|
||||
- uint32_t timeout_ms)
|
||||
+ uint32_t timeout_ms, sr_error_info_t **cb_err_info)
|
||||
{
|
||||
sr_error_info_t *err_info = NULL;
|
||||
struct sr_mod_info_mod_s *mod = NULL;
|
||||
@@ -1717,12 +1717,19 @@ sr_shmsub_change_notify_change_done(struct sr_mod_info_s *mod_info, const char *
|
||||
sr_rwunlock(&nsub->sub_shm->lock, 0, SR_LOCK_WRITE, cid, __func__);
|
||||
nsub->lock = SR_LOCK_NONE;
|
||||
|
||||
- /* we do not care about an error */
|
||||
- sr_errinfo_free(&nsub->cb_err_info);
|
||||
-
|
||||
SR_LOG_INF("EV ORIGIN: \"%s\" \"%s\" ID %" PRIu32 " priority %" PRIu32 " succeeded.",
|
||||
nsub->mod->ly_mod->name, sr_ev2str(SR_SUB_EV_DONE), nsub->mod->request_id, nsub->cur_priority);
|
||||
|
||||
+ /*
|
||||
+ * unexpected critical error, merge and cleanup, let
|
||||
+ * sysrepocfg caller handle undefined system state.
|
||||
+ */
|
||||
+ if (nsub->cb_err_info) {
|
||||
+ sr_errinfo_merge(cb_err_info, nsub->cb_err_info);
|
||||
+ nsub->cb_err_info = NULL;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
nsub->pending_event = 0;
|
||||
}
|
||||
} while (1);
|
||||
@@ -3167,7 +3174,7 @@ sr_shmsub_change_listen_check_update_edit(sr_session_ctx_t *ev_sess, const char
|
||||
sr_error_info_t *
|
||||
sr_shmsub_change_listen_process_module_events(struct modsub_change_s *change_subs, sr_conn_ctx_t *conn)
|
||||
{
|
||||
- sr_error_info_t *err_info = NULL;
|
||||
+ sr_error_info_t *err_info = NULL, *err_tmp;
|
||||
uint32_t i, data_len = 0, valid_subscr_count;
|
||||
char *data = NULL, *shm_data_ptr;
|
||||
int ret = SR_ERR_OK;
|
||||
@@ -3289,6 +3296,11 @@ process_event:
|
||||
}
|
||||
break;
|
||||
}
|
||||
+ } else if (sub_info.event == SR_SUB_EV_DONE) {
|
||||
+ if (ret && err_code == SR_ERR_OK) {
|
||||
+ /* unexpected, callback actually failed, save for later. */
|
||||
+ err_code = ret;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* subscription processed this event */
|
||||
@@ -3330,6 +3342,11 @@ process_event:
|
||||
}
|
||||
break;
|
||||
case SR_SUB_EV_DONE:
|
||||
+ if (err_code) {
|
||||
+ /* prepare unexepected error from session to be written to SHM */
|
||||
+ sr_errinfo_new(&err_info, err_code, "Oups, error detected in SR_EV_DONE");
|
||||
+ }
|
||||
+ break;
|
||||
case SR_SUB_EV_ABORT:
|
||||
/* nothing to do */
|
||||
break;
|
||||
@@ -3349,14 +3366,17 @@ process_event:
|
||||
|
||||
/* SUB WRITE URGE LOCK */
|
||||
if (sr_shmsub_change_listen_relock(multi_sub_shm, SR_LOCK_WRITE_URGE, &sub_info, change_sub, change_subs->module_name,
|
||||
- ret, ev_sess, &err_info)) {
|
||||
+ ret, ev_sess, &err_tmp)) {
|
||||
+ if (err_tmp)
|
||||
+ err_info = err_tmp;
|
||||
goto cleanup;
|
||||
}
|
||||
sub_lock = SR_LOCK_WRITE_URGE;
|
||||
|
||||
/* finish event */
|
||||
- if ((err_info = sr_shmsub_multi_listen_write_event(multi_sub_shm, valid_subscr_count, err_code, &shm_data_sub, data,
|
||||
+ if ((err_tmp = sr_shmsub_multi_listen_write_event(multi_sub_shm, valid_subscr_count, err_code, &shm_data_sub, data,
|
||||
data_len, change_subs->module_name, err_code ? "fail" : "success"))) {
|
||||
+ err_info = err_tmp;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -3886,7 +3906,7 @@ finish_iter:
|
||||
sr_errinfo_free(&cb_err_info);
|
||||
|
||||
/* publish "done" event */
|
||||
- if ((err_info = sr_shmsub_change_notify_change_done(&mod_info, NULL, NULL, SR_CHANGE_CB_TIMEOUT))) {
|
||||
+ if ((err_info = sr_shmsub_change_notify_change_done(&mod_info, NULL, NULL, SR_CHANGE_CB_TIMEOUT, &cb_err_info))) {
|
||||
goto cleanup_unlock;
|
||||
}
|
||||
|
||||
diff --git a/src/shm_sub.h b/src/shm_sub.h
|
||||
index 3056e4c5..460ad927 100644
|
||||
--- a/src/shm_sub.h
|
||||
+++ b/src/shm_sub.h
|
||||
@@ -144,7 +144,7 @@ sr_error_info_t *sr_shmsub_change_notify_change(struct sr_mod_info_s *mod_info,
|
||||
* @return err_info, NULL on success.
|
||||
*/
|
||||
sr_error_info_t *sr_shmsub_change_notify_change_done(struct sr_mod_info_s *mod_info, const char *orig_name,
|
||||
- const void *orig_data, uint32_t timeout_ms);
|
||||
+ const void *orig_data, uint32_t timeout_ms, sr_error_info_t **cb_err_info);
|
||||
|
||||
/**
|
||||
* @brief Notify about (generate) a change "abort" event.
|
||||
diff --git a/src/sysrepo.c b/src/sysrepo.c
|
||||
index ca2a20b7..e7c1fd0e 100644
|
||||
--- a/src/sysrepo.c
|
||||
+++ b/src/sysrepo.c
|
||||
@@ -3801,7 +3801,7 @@ store:
|
||||
}
|
||||
|
||||
/* publish "done" event, all changes were applied */
|
||||
- if ((err_info = sr_shmsub_change_notify_change_done(mod_info, orig_name, orig_data, timeout_ms))) {
|
||||
+ if ((err_info = sr_shmsub_change_notify_change_done(mod_info, orig_name, orig_data, timeout_ms, cb_err_info))) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pkglibexec_SCRIPTS = bootstrap error load gen-service \
|
||||
gen-hostkeys gen-admin-auth gen-hostname gen-interfaces gen-motd gen-hardware
|
||||
pkglibexec_SCRIPTS = bootstrap error load gen-service gen-hostkeys gen-admin-auth \
|
||||
gen-hostname gen-interfaces gen-motd gen-hardware
|
||||
sbin_SCRIPTS = dagger
|
||||
|
||||
@@ -72,7 +72,7 @@ collate()
|
||||
# Report error on console, syslog, and set login banners for getty + ssh
|
||||
console_error()
|
||||
{
|
||||
logger -p user.crit -t "BOOTSTRAP" "$1"
|
||||
logger -p user.crit -t bootstrap "$1"
|
||||
|
||||
# shellcheck disable=SC3037
|
||||
/bin/echo -e "\n\n\e[31mCRITICAL BOOTSTRAP ERROR\n$1\e[0m\n" > /dev/console
|
||||
@@ -214,7 +214,7 @@ sysrepoctl -s $SEARCH \
|
||||
-i iana-hardware@2018-03-13.yang -g wheel -p 0660 \
|
||||
-i ietf-hardware@2018-03-13.yang -g wheel -p 0660 \
|
||||
-e hardware-state \
|
||||
-i infix-hardware@2024-01-18.yang -g wheel -p 0660 \
|
||||
-i infix-hardware@2024-04-25.yang -g wheel -p 0660 \
|
||||
-i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \
|
||||
-i infix-ip@2023-09-14.yang -g wheel -p 0660 \
|
||||
-i infix-if-type@2024-01-29.yang -g wheel -p 0660 \
|
||||
@@ -226,7 +226,7 @@ sysrepoctl -s $SEARCH \
|
||||
-i infix-dhcp-client@2024-04-12.yang -g wheel -p 0660 \
|
||||
-i infix-shell-type@2023-08-21.yang -g wheel -p 0660 \
|
||||
-i infix-system@2024-04-12.yang -g wheel -p 0660 \
|
||||
-i infix-services@2024-04-08.yang -g wheel -p 0660 \
|
||||
-i infix-services@2024-05-21.yang -g wheel -p 0660 \
|
||||
-i ieee802-ethernet-interface@2019-06-21.yang -g wheel -p 0660 \
|
||||
-i infix-ethernet-interface@2024-02-27.yang -g wheel -p 0660 \
|
||||
-I "${INIT_DATA}"
|
||||
@@ -245,8 +245,10 @@ sysrepoctl -c ietf-netconf -g wheel -p 0660 \
|
||||
-e url \
|
||||
-e xpath \
|
||||
-e confirmed-commit
|
||||
# Allow wheel group users (admin) to modify NACM
|
||||
sysrepoctl -c ietf-netconf-acm -g wheel -p 0660
|
||||
# Allow wheel group users (admin) to modify NACM and do factory reset
|
||||
sysrepoctl -c ietf-netconf-acm -g wheel -p 0660
|
||||
sysrepoctl -c ietf-factory-default -g wheel -p 0660
|
||||
sysrepoctl -c sysrepo-plugind -g wheel -p 0660
|
||||
|
||||
# On first boot, install factory-config as startup-config. Due to a
|
||||
# limitation in sysrepo we cannot initialize ietf-netconf-acm, so we
|
||||
@@ -255,7 +257,6 @@ chgrp wheel /cfg
|
||||
chmod g+w /cfg
|
||||
if [ ! -f "$STARTUP_CFG" ]; then
|
||||
sysrepocfg -f json -X"$STARTUP_CFG"
|
||||
chown admin:wheel "$STARTUP_CFG"
|
||||
fi
|
||||
|
||||
# Clear running-config so we can load startup in the next step
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user