mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 17:23:00 +02:00
Compare commits
98
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) -->
|
||||
|
||||
@@ -8,21 +8,22 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Infix ${{ matrix.platform }}
|
||||
name: Build Infix ${{ matrix.target }}
|
||||
runs-on: [ self-hosted, latest ]
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [aarch64, x86_64]
|
||||
target: [aarch64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
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
|
||||
|
||||
@@ -38,14 +39,14 @@ jobs:
|
||||
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
|
||||
@@ -58,13 +59,14 @@ jobs:
|
||||
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'}}
|
||||
|
||||
@@ -15,13 +15,18 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Regression Testing
|
||||
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: |
|
||||
@@ -30,7 +35,7 @@ jobs:
|
||||
- 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
|
||||
|
||||
@@ -38,23 +43,24 @@ jobs:
|
||||
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: |
|
||||
@@ -70,12 +76,15 @@ jobs:
|
||||
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
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
make test
|
||||
|
||||
|
||||
@@ -20,16 +20,17 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'kernelkit/infix' && startsWith(github.ref, 'refs/tags/')
|
||||
name: Build Infix ${{ github.ref_name }} [${{ matrix.platform }}]
|
||||
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:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
clean: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Set Release Variables
|
||||
id: vars
|
||||
@@ -41,7 +42,7 @@ 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
|
||||
|
||||
@@ -57,16 +58,16 @@ jobs:
|
||||
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 ..."
|
||||
make $target
|
||||
make
|
||||
@@ -87,7 +88,7 @@ jobs:
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-${{ matrix.platform }}
|
||||
name: artifact-${{ matrix.target }}
|
||||
path: output/*.tar.gz
|
||||
|
||||
release:
|
||||
|
||||
@@ -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
|
||||
@@ -312,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()
|
||||
))
|
||||
@@ -1,3 +1,7 @@
|
||||
0 unspec
|
||||
1 kernel_lo
|
||||
2 kernel_ra
|
||||
3 kernel_ll
|
||||
4 static
|
||||
5 dhcp
|
||||
6 random
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,6 +4,82 @@ Change Log
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[v24.05.0][UNRELEASED]
|
||||
----------------------
|
||||
|
||||
### 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
|
||||
- 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
|
||||
-------------------------
|
||||
|
||||
@@ -844,6 +920,9 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
||||
|
||||
[buildroot]: https://buildroot.org/
|
||||
[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
|
||||
|
||||
+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
|
||||
|
||||
+42
-6
@@ -67,7 +67,7 @@ $ sudo apt install bc binutils build-essential bzip2 cpio \
|
||||
diffutils file findutils git gzip \
|
||||
libncurses-dev libssl-dev perl patch \
|
||||
python3 rsync sed tar unzip wget \
|
||||
autopoint
|
||||
autopoint bison flex
|
||||
```
|
||||
|
||||
For testing, a few more tools and services are required on your system:
|
||||
@@ -97,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
|
||||
|
||||
@@ -106,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
|
||||
|
||||
@@ -119,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
|
||||
-------
|
||||
@@ -142,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
|
||||
@@ -170,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
|
||||
|
||||
+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
|
||||
|
||||
+454
-7
@@ -331,6 +331,58 @@ 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
|
||||
|
||||
@@ -346,10 +398,10 @@ 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 specificed database.
|
||||
formatted configuration file to the specified database.
|
||||
- `sysrepocfg -E FILE -fjson -d DATABASE` to edit/merge JSON formatted
|
||||
configuration in FILE with the specificed database.
|
||||
- `sysrepocfg -R FILE -fjson` to execute remote procdure call (RPC) defined in
|
||||
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.
|
||||
@@ -360,7 +412,7 @@ 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 transfered to Infix in advance, e.g. using `scp` as shown below.
|
||||
it been transferred to Infix in advance, e.g. using `scp` as shown below.
|
||||
|
||||
```
|
||||
~$ cat file.json
|
||||
@@ -388,7 +440,7 @@ it been transfered to Infix in advance, e.g. using `scp` as shown below.
|
||||
```
|
||||
See [Factory Reset](#factory-reset) for another (simpler) alternative.
|
||||
|
||||
If you only wish to copy factory config to running config the
|
||||
If it is only wished to copy factory config to running config the
|
||||
following RPC is available
|
||||
|
||||
```
|
||||
@@ -601,7 +653,7 @@ on interface *e0*.
|
||||
~$
|
||||
```
|
||||
|
||||
### Backup Configuration Using sysrepocfg And scp
|
||||
### <a id="backup"></a> Backup Configuration Using sysrepocfg And scp
|
||||
|
||||
Displaying running or startup configuration is possible with
|
||||
`sysrepocfg -X`, as shown below.
|
||||
@@ -637,7 +689,7 @@ startup configuration (not running).
|
||||
~$
|
||||
```
|
||||
|
||||
### Restore Configuration Using sysrepocfg and ssh/scp
|
||||
### <a id="restore"></a> Restore Configuration Using sysrepocfg and ssh/scp
|
||||
|
||||
|
||||
To restore a backup configuration to startup, the simplest way is to
|
||||
@@ -688,7 +740,402 @@ An alternative is to write it to a temporary file, and use `sysrepocfg
|
||||
~$
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
@@ -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,14 +7,13 @@ 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, ensure correct ownership
|
||||
# Bootstrap system with startup-config
|
||||
run name:startup log:prio:user.notice norestart <pid/confd> \
|
||||
[S] /usr/libexec/confd/load startup-config \
|
||||
-- Loading startup-config
|
||||
task [S] <pid/confd> chown admin:wheel /cfg/startup-config.cfg --
|
||||
|
||||
# Run if loading startup-config fails for some reason
|
||||
run name:failure log:prio:user.critical norestart <pid/confd> if:<run/startup/failure> \
|
||||
|
||||
@@ -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))
|
||||
@@ -0,0 +1 @@
|
||||
task [2] run-parts /cfg/user-scripts.d -- Running user startup scripts
|
||||
@@ -1 +1,3 @@
|
||||
#set DEBUG=1
|
||||
|
||||
service name:statd log [S12345] <pid/confd> statd -f -p /run/statd.pid -n -- Status daemon
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -22,7 +22,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 16 ++++++++++++++++
|
||||
include/linux/phy.h | 22 ++++++++++++++++++++++
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -14,7 +14,6 @@ Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Tested-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://lore.kernel.org/r/20231204100811.2708884-4-tobias@waldekranz.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvmdio.c | 44 +++++++++++++++++++++++++++
|
||||
1 file changed, 44 insertions(+)
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -16,7 +16,6 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 162 ++++++++++++++++++-------------
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 27 +++---
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -16,7 +16,6 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 138 +++++++++++++++++--------------
|
||||
1 file changed, 75 insertions(+), 63 deletions(-)
|
||||
|
||||
@@ -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/28] net: dsa: mv88e6xxx: Add "eth-mac" counter group
|
||||
Subject: [PATCH 05/30] net: dsa: mv88e6xxx: Add "eth-mac" counter group
|
||||
support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -12,7 +12,6 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 39 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
@@ -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/28] net: dsa: mv88e6xxx: Limit histogram counters to
|
||||
Subject: [PATCH 06/30] net: dsa: mv88e6xxx: Limit histogram counters to
|
||||
ingress traffic
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -27,7 +27,6 @@ Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 6 +++---
|
||||
drivers/net/dsa/mv88e6xxx/global1.c | 7 +++----
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -11,7 +11,6 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 42 insertions(+)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
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/28] 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,
|
||||
though no actual implementations exist yet.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 5 +-
|
||||
|
||||
@@ -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/28] 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:
|
||||
@@ -9,7 +9,7 @@ Trigger support:
|
||||
- "timer"
|
||||
- "netdev"
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/leds.c | 226 +++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -9,7 +9,7 @@ In a multi-chip setup, delays of up to 750ms are observed before the
|
||||
device (6393X) signals completion of PPU initialization (Global 1,
|
||||
register 0, bit 15). Therefore, increase the timeout threshold to 1s.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
@@ -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/28] net: dsa: Support MDB memberships whose L2 addresses
|
||||
Subject: [PATCH 12/30] net: dsa: Support MDB memberships whose L2 addresses
|
||||
overlap
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -30,7 +30,7 @@ needed to do this is already in place, since it is also needed on CPU
|
||||
and DSA ports. Thus, "implement" this by simply removing the guards
|
||||
which previously skipped reference countung on user ports.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
net/dsa/switch.c | 16 ----------------
|
||||
1 file changed, 16 deletions(-)
|
||||
|
||||
@@ -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/28] net: phy: marvell10g: Support firmware loading on
|
||||
Subject: [PATCH 13/30] net: phy: marvell10g: Support firmware loading on
|
||||
88X3310
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -12,7 +12,7 @@ We have no choice but to bail out of the probe if firmware is not
|
||||
available, as the device does not have any built-in image on which to
|
||||
fall back.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 161 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 161 insertions(+)
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -9,7 +9,7 @@ On devices which are hardware strapped to start powered down (PDSTATE
|
||||
== 1), make sure that we clear the power-down bit on all units
|
||||
affected by this setting.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 18 +++++++++++++++---
|
||||
1 file changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -18,7 +18,7 @@ Trigger support:
|
||||
- "netdev": Offload link or duplex information to the solid behavior;
|
||||
tx and/or rx activity to blink behavior.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 422 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 422 insertions(+)
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -15,7 +15,7 @@ the offloading of the "netdev" trigger, such that LEDs attached to the
|
||||
RJ45 jack only lights up when a copper link is established, and vice
|
||||
versa for the SFP cage.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -14,7 +14,7 @@ be successfully probed.
|
||||
Therefore, settle for reporting data corruption issues in the log, and
|
||||
simply refrain from registering any cells in those cases.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
@@ -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/28] net: bridge: avoid classifying unknown multicast as
|
||||
Subject: [PATCH 18/30] net: bridge: avoid classifying unknown multicast as
|
||||
mrouters_only
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -16,6 +16,7 @@ Because a multicast router should always receive both known and unknown
|
||||
multicast.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/uapi/linux/if_bridge.h | 1 +
|
||||
net/bridge/br.c | 5 +++++
|
||||
|
||||
@@ -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/28] 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,10 +1,10 @@
|
||||
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/28] net: dsa: Support EtherType based priority overrides
|
||||
Subject: [PATCH 20/30] net: dsa: Support EtherType based priority overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/net/dsa.h | 4 ++++
|
||||
net/dsa/slave.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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/28] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
Subject: [PATCH 21/30] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 64 +++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 21 ++++++++++
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -16,7 +16,7 @@ probing (e.g. DSA) would end up with a physical link being
|
||||
established, even though the corresponding interface was still
|
||||
administratively down.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
@@ -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/28] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
Subject: [PATCH 23/30] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
perf on 6393
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -14,7 +14,7 @@ Therefore, add a new set of SMI operations which remaps accesses to
|
||||
such registers to the corresponding directly addressable register. All
|
||||
other accesses use the regular indirect interface.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++
|
||||
drivers/net/dsa/mv88e6xxx/global1.h | 3 ++
|
||||
|
||||
@@ -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/28] net: bridge: drop delay for applying strict multicast
|
||||
Subject: [PATCH 24/30] net: bridge: drop delay for applying strict multicast
|
||||
filtering
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
@@ -19,6 +19,7 @@ A proper fix for upstreaming could be to add a knob to disable the delay.
|
||||
[2]: https://lore.kernel.org/netdev/20240127175033.9640-1-linus.luessing@c0d3.blue/
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
net/bridge/br_multicast.c | 42 +++++++--------------------------------
|
||||
net/bridge/br_private.h | 4 +---
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -14,7 +14,7 @@ This state is the default set up by mv88e6xxx_port_setup_mac(), so all
|
||||
we have to do is to make the phylink MAC callbacks no-ops in cases
|
||||
when in-band-status is being used.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
@@ -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/28] 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
|
||||
@@ -16,7 +16,7 @@ never enabled on DSA ports, which broke standalone port isolation in
|
||||
multichip switch trees made up of 6393X decices.
|
||||
|
||||
Fixes: 6584b26020fc ("net: dsa: mv88e6xxx: implement .port_set_policy for Amethyst")
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
@@ -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/28] 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
|
||||
|
||||
@@ -30,7 +30,7 @@ switch would try to trap it back to the CPU. Given that the CPU is
|
||||
trusted, instead assume that it indeed meant for the packet to be
|
||||
forwarded like any other.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 6 deletions(-)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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/28] usb: core: adjust log level for unauthorized devices
|
||||
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,
|
||||
@@ -9,6 +9,7 @@ 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 +-
|
||||
|
||||
@@ -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
|
||||
@@ -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}"
|
||||
|
||||
@@ -50,8 +50,8 @@ action_exec()
|
||||
|
||||
for node in $order; do
|
||||
for work in $(find "$actdir/$node" -type f -executable 2>/dev/null | sort); do
|
||||
$work >>"$work.log" 2>&1 || code=$?
|
||||
echo "[exit:$code]" >>"$work.log"
|
||||
$work | ts >>"$work.log" 2>&1 || code=$?
|
||||
echo "[exit:$code]" | ts >>"$work.log"
|
||||
|
||||
[ $code -eq 0 ] || abort "$work failed with exitcode $code"
|
||||
done
|
||||
@@ -185,6 +185,13 @@ if [ -n "$bridge" ]; then
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"enabled": true
|
||||
},
|
||||
"infix-interfaces:bridge": {
|
||||
"multicast": {
|
||||
"snooping": true,
|
||||
"querier": "auto",
|
||||
"query-interval": 125
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
+34
-4
@@ -19,6 +19,16 @@ banner_append()
|
||||
return 0
|
||||
}
|
||||
|
||||
note()
|
||||
{
|
||||
logger -s -I $$ -p user.notice -t load "$*"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -s -I $$ -p user.error -t load "$*"
|
||||
}
|
||||
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/confdrc
|
||||
@@ -35,17 +45,31 @@ else
|
||||
fi
|
||||
|
||||
if [ ! -f "$fn" ]; then
|
||||
logger -sik -p user.error "No such file, $fn, aborting!"
|
||||
err "No such file, $fn, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
note "Loading $config ..."
|
||||
if ! sysrepocfg -v3 -I"$fn" -f json; then
|
||||
case "$config" in
|
||||
startup-config)
|
||||
logger -sik -p user.error "Failed loading $fn, reverting to Fail Secure mode!"
|
||||
err "Failed loading $fn, reverting to Fail Secure mode!"
|
||||
# On failure to load startup-config the system is in an undefined state
|
||||
cat <<-EOF >/tmp/factory.json
|
||||
{
|
||||
"infix-factory-default:factory-default": {}
|
||||
}
|
||||
EOF
|
||||
# Default timeout is 2 seconds, allow time to clean up shm
|
||||
if ! sysrepocfg -f json -t 10 -R /tmp/factory.json; then
|
||||
rm -f /etc/sysrepo/data/*startup*
|
||||
rm -f /etc/sysrepo/data/*running*
|
||||
rm -f /dev/shm/sr_*
|
||||
killall sysrepo-plugind
|
||||
fi
|
||||
;;
|
||||
failure-config)
|
||||
logger -sik -p user.error "Failed loading $fn, aborting!"
|
||||
err "Failed loading $fn, aborting!"
|
||||
banner_append "CRITICAL ERROR: Logins are disabled, no credentials available"
|
||||
initctl -nbq runlevel 9
|
||||
;;
|
||||
@@ -53,7 +77,13 @@ if ! sysrepocfg -v3 -I"$fn" -f json; then
|
||||
|
||||
exit 1
|
||||
fi
|
||||
logger -sik -p user.notice "Loaded $fn successfully."
|
||||
|
||||
note "Loaded $fn successfully."
|
||||
if [ "$config" = "failure-config" ]; then
|
||||
banner_append "ERROR: Corrupt startup-config, system has reverted to default login credentials"
|
||||
else
|
||||
# Ensure correct ownership and permissions, in particular after factory reset
|
||||
# Created by the system, writable by any user in the admin group.
|
||||
chown root:wheel "$fn"
|
||||
chmod 0660 "$fn"
|
||||
fi
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
factorydir = $(pkgdatadir)/factory.d
|
||||
dist_factory_DATA = 10-nacm.json 10-netconf-server.json \
|
||||
10-infix-system.json 10-system.json
|
||||
10-infix-services.json 10-system.json
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@ int cni_ifchange_cand_infer_type(sr_session_ctx_t *session, const char *path)
|
||||
return SR_ERR_SYS;
|
||||
|
||||
err = sr_get_data(session, path, 0, 0, 0, &cfg);
|
||||
if (err)
|
||||
if (err || !cfg)
|
||||
goto err;
|
||||
|
||||
node = lydx_get_descendant(cfg->tree, "interfaces", "interface", NULL);
|
||||
|
||||
@@ -196,7 +196,7 @@ static int change_hardware(sr_session_ctx_t *session, uint32_t sub_id, const cha
|
||||
return SR_ERR_OK;
|
||||
|
||||
rc = sr_get_data(session, XPATH_BASE_ "//.", 0, 0, 0, &cfg);
|
||||
if (rc)
|
||||
if (rc || !cfg)
|
||||
goto err;
|
||||
|
||||
rc = srx_get_diff(session, &diff);
|
||||
|
||||
@@ -1376,11 +1376,22 @@ static int netdag_gen_veth(struct dagger *net, struct lyd_node *dif,
|
||||
if (dagger_should_skip(net, ifname)) {
|
||||
err = dagger_add_dep(net, ifname, peer);
|
||||
if (err)
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\" to %s",
|
||||
peer, ifname);
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\" to %s", peer, ifname);
|
||||
} else {
|
||||
char ifname_args[64] = "", peer_args[64] = "";
|
||||
|
||||
dagger_skip_iface(net, peer);
|
||||
fprintf(ip, "link add dev %s down type veth peer %s\n", ifname, peer);
|
||||
|
||||
node = lydx_get_child(dif, "phys-address");
|
||||
if (node)
|
||||
snprintf(ifname_args, sizeof(ifname_args), "address %s", lyd_get_value(node));
|
||||
|
||||
node = lydx_find_by_name(lyd_parent(cif), "interface", peer);
|
||||
if (node && (node = lydx_get_child(node, "phys-address")))
|
||||
snprintf(peer_args, sizeof(peer_args), "address %s", lyd_get_value(node));
|
||||
|
||||
fprintf(ip, "link add dev %s %s type veth peer %s %s\n",
|
||||
ifname, ifname_args, peer, peer_args);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1699,7 +1710,7 @@ static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *modu
|
||||
return err;
|
||||
|
||||
err = sr_get_data(session, "/interfaces/interface", 0, 0, 0, &cfg);
|
||||
if (err)
|
||||
if (err || !cfg)
|
||||
goto err_abandon;
|
||||
|
||||
err = srx_get_diff(session, (struct lyd_node **)&diff);
|
||||
|
||||
@@ -348,6 +348,11 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su
|
||||
}
|
||||
|
||||
rc = sr_get_data(session, "/ietf-routing:routing/control-plane-protocols//.", 0, 0, 0, &cfg);
|
||||
if (rc || !cfg) {
|
||||
NOTE("No control-plane-protocols available.");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
LY_LIST_FOR(lyd_child(cfg->tree), tmp) {
|
||||
LY_LIST_FOR(lyd_child(tmp), cplane) {
|
||||
const char *type;
|
||||
@@ -360,11 +365,13 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
sr_release_data(cfg);
|
||||
|
||||
err_close:
|
||||
fclose(fp);
|
||||
if (!staticd_enabled)
|
||||
(void)remove(STATICD_CONF_NEXT);
|
||||
sr_release_data(cfg);
|
||||
|
||||
err_abandon:
|
||||
return rc;
|
||||
}
|
||||
|
||||
+122
-80
@@ -4,6 +4,8 @@
|
||||
#include <ctype.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
@@ -442,7 +444,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo
|
||||
continue;
|
||||
|
||||
name = sr_val_to_str(old);
|
||||
DEBUG("Removing NTP server %s\n", name);
|
||||
DEBUG("Removing NTP server %s", name);
|
||||
erasef("/etc/chrony/sources.d/%s.sources", name);
|
||||
free(name);
|
||||
changes++;
|
||||
@@ -542,12 +544,11 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo
|
||||
|
||||
case SR_EV_DONE:
|
||||
/* Check if passed validation in previous event */
|
||||
if (access(RESOLV_NEXT, F_OK))
|
||||
return SR_ERR_OK;
|
||||
|
||||
(void)remove(RESOLV_PREV);
|
||||
(void)rename(RESOLV_CONF, RESOLV_PREV);
|
||||
(void)rename(RESOLV_NEXT, RESOLV_CONF);
|
||||
if (!access(RESOLV_NEXT, F_OK)) {
|
||||
(void)remove(RESOLV_PREV);
|
||||
(void)rename(RESOLV_CONF, RESOLV_PREV);
|
||||
(void)rename(RESOLV_NEXT, RESOLV_CONF);
|
||||
}
|
||||
|
||||
/* in bootstrap, another resolvconf will soon take your call */
|
||||
if (systemf("initctl -bq cond get hook/sys/up"))
|
||||
@@ -594,11 +595,10 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo
|
||||
goto fail;
|
||||
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
const char *xpath = val[i].xpath;
|
||||
char *ptr;
|
||||
|
||||
/* Get /ietf-system:system/dns-resolver/server[name='foo'] */
|
||||
ptr = srx_get_str(session, "%s/udp-and-tcp/address", xpath);
|
||||
ptr = srx_get_str(session, "%s/udp-and-tcp/address", val[i].xpath);
|
||||
if (ptr)
|
||||
/* XXX: add support also for udp-and-tcp/port */
|
||||
fprintf(fp, "nameserver %s\n", ptr);
|
||||
@@ -637,7 +637,7 @@ static char *sys_find_usable_shell(sr_session_ctx_t *sess, char *name)
|
||||
sr_data_t *cfg;
|
||||
|
||||
snprintf(xpath, sizeof(xpath), XPATH_AUTH_"/user[name='%s']/infix-system:shell", name);
|
||||
if (!sr_get_data(sess, xpath, 0, 0, 0, &cfg)) {
|
||||
if (!sr_get_data(sess, xpath, 0, 0, 0, &cfg) && cfg) {
|
||||
struct lyd_node *node;
|
||||
|
||||
if (!lyd_find_path(cfg->tree, xpath, 0, &node))
|
||||
@@ -666,41 +666,18 @@ static char *sys_find_usable_shell(sr_session_ctx_t *sess, char *name)
|
||||
shell = LOGIN_SHELL;
|
||||
|
||||
shell = strdup(shell);
|
||||
sr_release_data(cfg);
|
||||
if (cfg)
|
||||
sr_release_data(cfg);
|
||||
|
||||
return shell;
|
||||
}
|
||||
|
||||
static uid_t sys_home_exists(char *user)
|
||||
{
|
||||
char path[strlen(user) + 10];
|
||||
struct stat st;
|
||||
|
||||
snprintf(path, sizeof(path), "/home/%s", user);
|
||||
if (stat(path, &st))
|
||||
return 0;
|
||||
|
||||
return st.st_uid;
|
||||
}
|
||||
|
||||
static int sys_uid_busy(char *user, uid_t uid)
|
||||
{
|
||||
struct passwd *pw;
|
||||
int rc = 0;
|
||||
|
||||
setpwent();
|
||||
while ((pw = getpwent())) {
|
||||
if (pw->pw_uid != uid)
|
||||
continue;
|
||||
if (strcmp(pw->pw_name, user))
|
||||
rc = -1;
|
||||
}
|
||||
endpwent();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sys_del_user(char *user)
|
||||
/*
|
||||
* Used both when deleting a user from the system configuration, and
|
||||
* when cleaning up stale users while adding a new user to the system.
|
||||
* In the latter case we don't need to log failure/success.
|
||||
*/
|
||||
static int sys_del_user(char *user, bool silent)
|
||||
{
|
||||
char *args[] = {
|
||||
"deluser", "--remove-home", user, NULL
|
||||
@@ -710,49 +687,71 @@ static int sys_del_user(char *user)
|
||||
erasef("/var/run/sshd/%s.keys", user);
|
||||
err = systemv_silent(args);
|
||||
if (err) {
|
||||
ERROR("Error deleting user \"%s\"\n", user);
|
||||
if (!silent)
|
||||
ERROR("Error deleting user \"%s\"", user);
|
||||
|
||||
/* Ensure $HOME is removed at least. */
|
||||
systemf("rm -rf /home/%s", user);
|
||||
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
NOTE("User \"%s\" deleted\n", user);
|
||||
|
||||
if (!silent)
|
||||
NOTE("User \"%s\" deleted", user);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int sys_add_new_user(sr_session_ctx_t *sess, char *name)
|
||||
/*
|
||||
* Helper for sys_add_user(), notice how uid:gid must never be 0:0, it
|
||||
* is reserved for the system root user which is never created/deleted.
|
||||
*
|
||||
* This function balances both /etc/passwd and /etc/group, so to make
|
||||
* things a little bit easier, we simplify the world and reserve the
|
||||
* same group name as the username. This means we can always remove
|
||||
* any stale group entries first.
|
||||
*
|
||||
* When uid:gid is non-zero we create the user and re-attach them with
|
||||
* their $HOME. When uid:gid *is* zero, however, we must make sure to
|
||||
* clean up any stale user + $HOME before calling adduser to allocate
|
||||
* a new uid:gid pair for the new user.
|
||||
*
|
||||
* If this function fails, it is up to the callee to retry the operation
|
||||
* with a zero uid:gid pair, which is the most iron clad form.
|
||||
*/
|
||||
static int sys_call_adduser(sr_session_ctx_t *sess, char *name, uid_t uid, gid_t gid)
|
||||
{
|
||||
char *shell = sys_find_usable_shell(sess, name);
|
||||
char uid_str[10];
|
||||
char *eargs[] = {
|
||||
"adduser", "-d", "-s", shell, "-u", NULL, "-H", name, NULL
|
||||
"adduser", "-d", "-s", shell, "-u", NULL, "-G", NULL, "-H", name, NULL
|
||||
};
|
||||
char *nargs[] = {
|
||||
"adduser", "-d", "-s", shell, name, NULL
|
||||
};
|
||||
bool do_chown = false;
|
||||
char uid_str[10], grp_str[strlen(name) + 1];
|
||||
char **args;
|
||||
uid_t uid;
|
||||
int err;
|
||||
|
||||
uid = sys_home_exists(name);
|
||||
if (uid) {
|
||||
if (sys_uid_busy(name, uid)) {
|
||||
/* Exists but owned by someone else. */
|
||||
ERROR("Creating user %s, /home/%s existed but was owned by another uid (%d)",
|
||||
name, name, uid);
|
||||
ERROR("Cleaning up stale /home/%s", name);
|
||||
systemf("rm -rf /home/%s", name);
|
||||
args = nargs;
|
||||
} else {
|
||||
/* Not in passwd or owned by us already */
|
||||
do_chown = true;
|
||||
DEBUG("Adding new user %s, cleaning up any stale group.", name);
|
||||
systemf("delgroup %s 2>/dev/null", name);
|
||||
|
||||
/* reusing existing uid:gid from $HOME */
|
||||
if (uid && gid) {
|
||||
/* recreate group first */
|
||||
systemf("addgroup -g %d %s", gid, name);
|
||||
|
||||
snprintf(uid_str, sizeof(uid_str), "%d", uid);
|
||||
snprintf(grp_str, sizeof(grp_str), "%s", name);
|
||||
eargs[5] = uid_str;
|
||||
eargs[7] = grp_str;
|
||||
|
||||
args = eargs;
|
||||
} else {
|
||||
DEBUG("Cleaning up any stale user %s and /home/%s", name, name);
|
||||
sys_del_user(name, true);
|
||||
|
||||
NOTE("Reusing uid %d and /home/%s for new user %s", uid, name, name);
|
||||
snprintf(uid_str, sizeof(uid_str), "%d", uid);
|
||||
eargs[5] = uid_str;
|
||||
args = eargs;
|
||||
}
|
||||
} else
|
||||
args = nargs;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Busybox implementation of 'adduser -d' sets the password
|
||||
@@ -761,14 +760,51 @@ static int sys_add_new_user(sr_session_ctx_t *sess, char *name)
|
||||
*/
|
||||
err = systemv_silent(args);
|
||||
free(shell);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new (locked) user, if they have a matching $HOME we use the
|
||||
* uid:gid from that, if they are free. In all cases of conflict with
|
||||
* any (type of) user we remove the existing $HOME and start with a new
|
||||
* uid:gid pair.
|
||||
*/
|
||||
static int sys_add_user(sr_session_ctx_t *sess, char *name)
|
||||
{
|
||||
char home[strlen(name) + 10];
|
||||
bool reused = false;
|
||||
struct stat st;
|
||||
int err;
|
||||
|
||||
/* Map users to their existing $HOME */
|
||||
snprintf(home, sizeof(home), "/home/%s", name);
|
||||
if (!stat(home, &st)) {
|
||||
/* Verify IDs aren't already used, like BusyBox adduser */
|
||||
if (getpwuid(st.st_uid) || getgrgid(st.st_uid) || getgrgid(st.st_gid)) {
|
||||
/* Exists but owned by someone else. */
|
||||
ERROR("Failed mapping user %s to /home/%s, uid:gid (%d:%d) already exists.",
|
||||
name, name, st.st_uid, st.st_gid);
|
||||
err = sys_call_adduser(sess, name, 0, 0);
|
||||
} else {
|
||||
DEBUG("Reusing uid:gid %d:%d and /home/%s for new user %s",
|
||||
st.st_uid, st.st_gid, name, name);
|
||||
err = sys_call_adduser(sess, name, st.st_uid, st.st_gid);
|
||||
if (err) {
|
||||
ERROR("Failed reusing uid:gid from /home/%s, retrying create user ...", name);
|
||||
err = sys_call_adduser(sess, name, 0, 0);
|
||||
} else
|
||||
reused = true;
|
||||
}
|
||||
} else
|
||||
err = sys_call_adduser(sess, name, 0, 0);
|
||||
|
||||
if (err) {
|
||||
ERROR("Failed creating new user \"%s\"\n", name);
|
||||
ERROR("Failed creating new user \"%s\"", name);
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
NOTE("New user \"%s\" created\n", name);
|
||||
if (do_chown)
|
||||
systemf("chown -R %s:%s /home/%s", name, name, name);
|
||||
NOTE("User \"%s\" created%s.", name, reused ? ", mapped to existing home directory" : "");
|
||||
|
||||
/*
|
||||
* OpenSSH in Infix has been set up to use /var/run/sshd/%s.keys
|
||||
@@ -776,6 +812,7 @@ static int sys_add_new_user(sr_session_ctx_t *sess, char *name)
|
||||
* /home/%s/.ssh/authorized_keys file. This creates a both the
|
||||
* directory and the symlink owned by root to prevent tampering.
|
||||
*/
|
||||
DEBUG("Adding secure /home/%s/.ssh directory.", name);
|
||||
fmkpath(0750, "/home/%s/.ssh", name);
|
||||
systemf("ln -sf /var/run/sshd/%s.keys /home/%s/.ssh/authorized_keys", name, name);
|
||||
|
||||
@@ -803,7 +840,7 @@ static char *change_get_user(struct sr_change *change)
|
||||
if (user) {
|
||||
pw = getpwnam(user);
|
||||
if (!pw) {
|
||||
ERROR("Skipping attribute for missing user (%s)", user);
|
||||
/* Skipping, user probably deleted. */
|
||||
free(user);
|
||||
user = NULL;
|
||||
}
|
||||
@@ -828,7 +865,7 @@ static sr_error_t handle_sr_passwd_update(augeas *aug, sr_session_ctx_t *, struc
|
||||
assert(change->new);
|
||||
|
||||
if (change->new->type != SR_STRING_T) {
|
||||
ERROR("Internal error, expected pass to be string type\n");
|
||||
ERROR("Internal error, expected pass to be string type.");
|
||||
err = SR_ERR_INTERNAL;
|
||||
break;
|
||||
}
|
||||
@@ -841,7 +878,7 @@ static sr_error_t handle_sr_passwd_update(augeas *aug, sr_session_ctx_t *, struc
|
||||
* it as "*", meaning the user can log in with SSH keys.
|
||||
*/
|
||||
if (!hash || !strlen(hash)) {
|
||||
ERROR("Empty passwords are not allowed, disabling password login.\n");
|
||||
ERROR("Empty passwords are not allowed, disabling password login.");
|
||||
hash = "*";
|
||||
}
|
||||
if (aug_set_dynpath(aug, hash, "etc/shadow/%s/password", user))
|
||||
@@ -882,6 +919,9 @@ static sr_error_t handle_sr_shell_update(augeas *aug, sr_session_ctx_t *sess, st
|
||||
char *user;
|
||||
int err;
|
||||
|
||||
if (change->op == SR_OP_DELETED)
|
||||
return SR_ERR_OK;
|
||||
|
||||
user = change_get_user(change);
|
||||
if (!user)
|
||||
return SR_ERR_OK;
|
||||
@@ -930,7 +970,7 @@ static sr_error_t handle_sr_user_update(augeas *aug, sr_session_ctx_t *sess, str
|
||||
assert(change->new);
|
||||
|
||||
name = sr_xpath_key_value(change->new->xpath, "user", "name", &state);
|
||||
err = sys_add_new_user(sess, name);
|
||||
err = sys_add_user(sess, name);
|
||||
if (err) {
|
||||
sr_xpath_recover(&state);
|
||||
return err;
|
||||
@@ -941,7 +981,7 @@ static sr_error_t handle_sr_user_update(augeas *aug, sr_session_ctx_t *sess, str
|
||||
assert(change->old);
|
||||
|
||||
name = sr_xpath_key_value(change->old->xpath, "user", "name", &state);
|
||||
err = sys_del_user(name);
|
||||
err = sys_del_user(name, false);
|
||||
if (err) {
|
||||
sr_xpath_recover(&state);
|
||||
return err;
|
||||
@@ -973,8 +1013,9 @@ static sr_error_t generate_auth_keys(sr_session_ctx_t *session, const char *xpat
|
||||
sr_error_t err = 0;
|
||||
sr_data_t *cfg;
|
||||
|
||||
/* err may be OK and cfg NULL if 'no system' */
|
||||
err = sr_get_data(session, xpath, 0, 0, 0, &cfg);
|
||||
if (err)
|
||||
if (err || !cfg)
|
||||
return err;
|
||||
|
||||
auth = lydx_get_descendant(cfg->tree, "system", "authentication", NULL);
|
||||
@@ -1043,7 +1084,7 @@ static sr_error_t change_auth_done(augeas *aug, sr_session_ctx_t *session)
|
||||
*/
|
||||
err = aug_load(aug);
|
||||
if (err) {
|
||||
ERROR("Error loading files into aug tree\n");
|
||||
ERROR("Error loading files into aug tree.");
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -1079,7 +1120,7 @@ static sr_error_t change_auth_done(augeas *aug, sr_session_ctx_t *session)
|
||||
return err;
|
||||
}
|
||||
|
||||
DEBUG("Changes to authentication saved\n");
|
||||
DEBUG("Changes to authentication saved.");
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
@@ -1326,8 +1367,9 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha
|
||||
|
||||
nm = srx_get_str(session, "%s", xpath);
|
||||
if (!nm) {
|
||||
/* XXX: derive from global "options.h" or /usr/share/factory/ */
|
||||
nm = strdup("infix");
|
||||
nm = fgetkey("/etc/os-release", "DEFAULT_HOSTNAME");
|
||||
if (nm)
|
||||
nm = strdup(nm);
|
||||
if (!nm) {
|
||||
err = SR_ERR_NO_MEMORY;
|
||||
goto err;
|
||||
|
||||
@@ -226,7 +226,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module
|
||||
}
|
||||
|
||||
err = sr_get_data(session, CFG_XPATH "//.", 0, 0, 0, &cfg);
|
||||
if (err)
|
||||
if (err || !cfg)
|
||||
goto err_abandon;
|
||||
|
||||
err = srx_get_diff(session, &diff);
|
||||
|
||||
@@ -278,7 +278,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module
|
||||
}
|
||||
|
||||
err = sr_get_data(session, XPATH "//.", 0, 0, 0, &cfg);
|
||||
if (err)
|
||||
if (err || !cfg)
|
||||
goto err_abandon;
|
||||
|
||||
err = srx_get_diff(session, &diff);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
SVC(web) \
|
||||
SVC(ttyd) \
|
||||
SVC(netbrowse) \
|
||||
SVC(userscripts) \
|
||||
SVC(all) /* must be last entry */
|
||||
|
||||
typedef enum {
|
||||
@@ -52,7 +53,7 @@ struct mdns_svc {
|
||||
};
|
||||
|
||||
static const struct srx_module_requirement reqs[] = {
|
||||
{ .dir = YANG_PATH_, .name = "infix-services", .rev = "2024-04-08" },
|
||||
{ .dir = YANG_PATH_, .name = "infix-services", .rev = "2024-05-21" },
|
||||
{ .dir = YANG_PATH_, .name = "ieee802-dot1ab-lldp", .rev = "2022-03-15" },
|
||||
{ .dir = YANG_PATH_, .name = "infix-lldp", .rev = "2023-08-23" },
|
||||
{ NULL }
|
||||
@@ -104,7 +105,7 @@ static sr_data_t *get(sr_session_ctx_t *session, sr_event_t event, const char *x
|
||||
return NULL; /* Don't care about CHANGE, ABORT, etc. */
|
||||
|
||||
snprintf(path, sizeof(path), "%s//.", xpath);
|
||||
if (sr_get_data(session, path, 0, 0, 0, &cfg)) {
|
||||
if (sr_get_data(session, path, 0, 0, 0, &cfg) || !cfg) {
|
||||
ERROR("no data for %s", path);
|
||||
return NULL;
|
||||
}
|
||||
@@ -291,6 +292,21 @@ static int web_change(sr_session_ctx_t *session, uint32_t sub_id, const char *mo
|
||||
return put(cfg, srv);
|
||||
}
|
||||
|
||||
static int userscripts_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
|
||||
const char *xpath, sr_event_t event, unsigned request_id, void *_confd)
|
||||
{
|
||||
struct lyd_node *srv = NULL;
|
||||
sr_data_t *cfg;
|
||||
|
||||
cfg = get(session, event, xpath, &srv, "user-scripts", NULL);
|
||||
if (!cfg)
|
||||
return SR_ERR_OK;
|
||||
|
||||
svc_enadis(lydx_is_enabled(srv, "enabled"), none, "user-scripts");
|
||||
|
||||
return put(cfg, srv);
|
||||
}
|
||||
|
||||
int infix_services_init(struct confd *confd)
|
||||
{
|
||||
int rc;
|
||||
@@ -312,6 +328,8 @@ int infix_services_init(struct confd *confd)
|
||||
0, netbrowse_change, confd, &confd->sub);
|
||||
REGISTER_CHANGE(confd->session, "ieee802-dot1ab-lldp", "/ieee802-dot1ab-lldp:lldp",
|
||||
0, lldp_change, confd, &confd->sub);
|
||||
REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:user-scripts",
|
||||
0, userscripts_change, confd, &confd->sub);
|
||||
|
||||
return SR_ERR_OK;
|
||||
fail:
|
||||
|
||||
+17
@@ -7,6 +7,10 @@ module infix-services {
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "Infix services, generic.";
|
||||
|
||||
revision 2024-05-21 {
|
||||
description "Add support for user-scripts.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-04-08 {
|
||||
description "Initial support for web services.";
|
||||
reference "internal";
|
||||
@@ -33,6 +37,19 @@ module infix-services {
|
||||
}
|
||||
}
|
||||
|
||||
container user-scripts {
|
||||
description "Run scripts in /cfg/user-scripts.d on system startup
|
||||
|
||||
CAUTION! Anyone who can write to this directory will be able to
|
||||
install a permanent backdoor on the system. This could include
|
||||
a remote attacker with brief window of access.";
|
||||
|
||||
leaf enabled {
|
||||
description "Enable or disable user script execution";
|
||||
type boolean;
|
||||
}
|
||||
}
|
||||
|
||||
container web {
|
||||
description "Web services";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user