Compare commits

..
Author SHA1 Message Date
Tobias Waldekranz 03b1689656 arm-trusted-firmware: cn9130: Specify basic DDR opts via build vars 2024-04-12 16:07:46 +02:00
Joachim Wiberg 68fac03f09 patches/finit: resync hwrng support and tmpfiles.d logging fix
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 12:08:54 +01:00
Tobias Waldekranz 8bd8195660 kernel: Import fix for 6393X PPU initialization timeout 2024-03-13 11:01:15 +01:00
Tobias Waldekranz 8fa910e8d9 klish-plugin-infix: Prettify 'show ip brief'
- Version sort interfaces ("e2" is listed before "e10")
- Remove "@dsa" from switch interfaces
2024-03-13 11:01:15 +01:00
Tobias Waldekranz 2e3d8881cc test: Allow unit tests to be run from non-x86 builds
Since there is no dependency on anything being built, move the
test-unit target to an architecture-neutral location.
2024-03-13 11:01:15 +01:00
Tobias Waldekranz 4e93e35c86 statd: cli-pretty: Version sort interfaces
Before this change:

e1
e10
e2
...
e9

After this change:

e1
e2
...
e9
e10
2024-03-13 11:01:15 +01:00
Tobias Waldekranz 736a23ccae probe: Fix crash on systems without USB
While __get_phandle_array returns the empty set when the property is
not available, str_array would return None, unless instructed
otherwise. Make sure that it also returns the empty set.
2024-03-13 11:01:15 +01:00
Tobias Waldekranz d602e48d0f patches/uboot: Sync with u-boot-2023.07.y-kkit for multi-chip fixes
- Add upstream patch that fixes multi-chip management in the mv88e6xxx
  driver

- Fix detection of 6393X in multi-chip configuration
2024-03-13 11:01:15 +01:00
Tobias Waldekranz 592f89e1f7 board/aarch64: styx: Initial device tree 2024-03-13 11:01:15 +01:00
Tobias Waldekranz 2a1c3010f8 board/aarch64: cn9130: Specify XMDIO clock names
This lets the driver adjust the clock according to the rate specified
in the device tree.
2024-03-13 11:01:15 +01:00
Joachim Wiberg 049f8d18f9 confd: only start mcd if there is a VLAN upper on the bridge
Temporary fix to prevent odd log messages.  The fix is to add RAW VLAN
support to mcd so it can run as a proxy querier even if there is no
upper VLAN interface or IP address.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 10:24:02 +01:00
Joachim Wiberg 65d393d491 Update ChangeLog, issue #328
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 10:24:02 +01:00
Joachim Wiberg 7230c3532a confd: improve bridge port validation for VLAN filtering bridges
This patch adds validation of bridge port VLAN memberships and IP
addressing for VLAN filtering bridges:

  1. Ports must be a member of this bridge
  2. Ports cannot be tagged and untagged member at the same time
  3. A VLAN filtering bridge does not support IP addressing

A VLAN filtering bridge can only be a tagged member of a VLAN.  Any IP
addressing needs to be done using an upper VLAN interface.

NOTE: while technically possible break up these long must expressions
      into multiple must expressions per node (split at 'and'), it will
      break libyang in interesting ways that in turn make the confd
      inference functionality stop working.  E.g., creating VETH pairs.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 10:24:02 +01:00
Joachim Wiberg 21fd1e9442 Fix #328: drop default value for bridge-port PVID
A bridge port in a VLAN filtering bridge should be possible to configure
as "tagged only", i.e., to not assign ingressing untagged frames a VLAN
and instead drop them.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 10:24:02 +01:00
Joachim Wiberg 11c862bbd5 doc: nftables container fixes
- Must run in privileged mode
 - Fix copy-paste container name: system -> nftables
 - Point out the important settings

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 11:34:11 +01:00
Joachim Wiberg 88ca959a61 doc: update container documentation, set -> text-editor
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 11:21:10 +01:00
Joachim WibergandTobias Waldekranz b4690f3850 statd: skip container interfaces in status output, for now
This patch prevents statd from failing and logging errors on interfaces
currently in another network namespace.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 09:26:23 +01:00
Joachim WibergandTobias Waldekranz 8ca2d74566 confd: ensure we always return cni status
This patch fixes a runtime error triggered by modifying an interface
currently used by a container.  The CNI code must always return the
CNI status (reserved for container or not).

How to trigger:
 - Create veth pair
 - Make one end container-network and add to container
 - Leave
 - Return to configure and set an IP address on container interface
 - Leave - BOOM

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 09:26:23 +01:00
Joachim WibergandTobias Waldekranz 8ea9dd2c55 patches/finit: backport random seed and rtc fixes
- rtc, already does the best it can, fix occasional duped message
 - urandom, check if seed file empty, try using hwrng

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 09:18:38 +01:00
Joachim WibergandTobias Waldekranz 938230c103 patches/finit: reboot-hang-fix and improved bootstrap log message
Backports of fixes for two issues:

 - Finit sometimes locks-up without input on serial console on reboot
 - Improved logging of unsupported initctl commands at bootstrap

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-12 09:18:38 +01:00
Joachim Wiberg 6f185cdfb5 confd: refactor gen-interfaces for hybrid bridge/iface setups
Simplify interface generation by collapsing eth_ and ethlike_ifaces to a
single list.  Let gen_iface_json() determine interface type by querying
each interface.  This allows us to create bridge setups also for qemu
use-cases.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-11 14:37:49 +01:00
Joachim Wiberg 5faefb2b51 doc: adjust image spacing
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 16:15:34 +01:00
Joachim Wiberg e8c54b190d doc: add introduction and minor spellecheck
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 16:02:27 +01:00
Joachim Wiberg b8f8d50fa6 doc: update images for better color contrast on white/dark bg
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 13:26:51 +01:00
Joachim Wiberg 8437a17353 doc: refactor container documentation slightly
Drop all mention of "CNI" and update text to not use, e.g., `cni-bridge`
when this was changed in the model before the merge to main.

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 11:58:23 +01:00
Joachim Wiberg 5b7d6c9b65 doc: document VETH pairs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 11:51:18 +01:00
Joachim Wiberg ad9060e99c confd: minor, grammar fix
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 11:37:17 +01:00
Joachim Wiberg 857e028730 doc: minor, whitespace only
Fill paragraphs to fit standard width.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-10 11:36:35 +01:00
Mattias WalströmandJoachim Wiberg 5ced70435b Replace querierd with mcd in defconfigs 2024-03-09 11:58:40 +01:00
Joachim Wiberg 32635364aa package/mcd: new package, replaces querierd
Update all package references and confd:ietf-interfaces

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-09 11:58:40 +01:00
Joachim WibergandMattias Walström f2cc620941 confd: restrict mdb group to iana-rt-types:ip-multicast-group-address
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 65fd68797b patches/iproute: backport bridge mdb replace support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Mattias Walström 89bcf7346f test: igmp_basic: Speed up test and some renaming
Rename to more distinct names for netns and hostports
2024-03-07 12:45:55 +01:00
Mattias Walström f91d36b8d1 test: igmp_vlan: Speed up test significantly
Remove a lot of extra sleeps.
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström b19047e320 confd: detect bridge per-VLAN interfaces and start querierd
In a VLAN filtering bridge setup we want to be able to support an
external IGMP/MLD querier running from userspace, because the bridge
multicast code can only generate proxy/NULL querys per VLAN.

This patch is a refactor to allow just that.  If a VLAN on the bridge
has an upper interface, matching the bridge name and VID, we generate
a profile for querierd and enable the service.

For all other cases we try to disable any running querierd.  It is up
to the daemon to figure out if it has a usable IP address to use as
the query source IP or use 0.0.0.0.

Since the logic for selecting a proper IP address must be handled by
the daemon in the per-VLAN setup, we revert back to also use it for
the stand-alone unfiltered bridge case as well.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 944024f394 package/querierd: add per-interface service template
Since Infix supports per-VLAN querier parameters, like query interval,
we currently need to run a separate querierd per VLAN interface.  The
replacement, mcd, will handle this automatically in its .conf file.

Also, ensure we install the daemon configuration file as an example, and
thus creating the /etc/querierd/ directory for where .conf files for
each interface will be generated.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Mattias Walström 400ae6ce1c test: Add new test igmp_vlan and add igmp tests to suite 2024-03-07 12:45:55 +01:00
Mattias Walström 43d67044d0 test: igmp_basic: speed up test, remove unnecessary long timeout
And cleanup ASCII picture
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström cb0954ec19 confd: always flood unknown IP/MAC multicast according to mcast_flood
An RFC conforming multicast snooping bridge should forward all unknown
multicast (IP & MAC) on ports where the mcast_flood flag is set.  The
upstream kernel does not (yet) support this, but the KernelKit branch
of the kernel and iproute2 now support it.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 798602d087 patches/iproute2: add support for bridge mcast_flood_always
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 967d951231 patches/linux: ignore router ports when forwarding MAC multicast
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 2202555b28 patches/linux: forward port bridge flood unknown multicast
This is a forward-port of one of my bridge patches to handle RFC4541
style flooding of unknown multicast.

https://lore.kernel.org/netdev/20220411133837.318876-9-troglobit@gmail.com/

Changes since this thread: use inferred mctx (VLAN multicast context)
from br_handle_frame_finish() and br_dev_xmit(), which should fix the
per-VLAN multicast handling issue pointed out by Nikolay.

Todo before next patch series, add new option instead of breaking the
existing functionality for the current mcast_flood flag.  E.g., add a
mcast_flood_always, since the current flag stops flooding when there is
a known querier on the LAN.

See the above thread for details.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström cde9feadd7 test: allow test container to run tcpdump (cap-net-raw)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 4bfedf7a98 confd: disable IPv4LL & IPv6LL on bridge port interfaces
A bridge port cannot communicate on layer-3 while acting as a bridge
port.  Removing the port from the bridge re-enables the link-local
addresses, if any, from the configuration.

Fix #327

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Mattias Walström c21f37c241 test: add new test igmp_basic
Simple test that tests (without VLAN):
* Multicast flooding works
* Join works as expected
2024-03-07 12:45:55 +01:00
Mattias Walström d0485fb077 test: Add a new topoligy to test IGMP
With 3 data connections between host and DUT.
2024-03-07 12:45:55 +01:00
Mattias Walström 68af24adcf infamy: Add new class to test multicast
Depends on having mtools v3+ on test PC, so add it to the docker.
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 12eae1ec2b confd: initial mdb support, per bridge and per VLAN
Note, no VLAN id, or other VLAN specific information is contained in the
MDB entries, only forwarding information and per-port state.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström ec3b08524c confd: add support for bridge port flooding control
This patch adds BUM flooding control per port.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 6d65eff33d confd: improve debug messages, include ifname everywhere
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström afdc6fe582 confd: disable bridge's dumpster diving when vlan filtering
With VLAN filtering on a bridge we cannot use the mcast_query_use_ifaddr
mechanism.  This because even if the bridge may have an address it is
likely not on the same subnet as that of the VLAN, and the multicast
code in the kernel does not look at VLAN interfaecs on top of bridge
for a relevant adddress.

For these cases we have to use querierd, or a multicast router.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Joachim WibergandMattias Walström 1782b12514 confd: initial multicast filtering support for bridge model
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-07 12:45:55 +01:00
Mattias WalströmandJoachim Wiberg c5d53d10a4 yang: Bump infix-routing revision 2024-03-06 18:39:27 +01:00
Mattias WalströmandJoachim Wiberg 28846dd332 Fix inconsistent naming in infix-routing model
in container: default-route-advertise
Obsolete leaf: enable
Add new leaf: enabled

enable is preferred if exist, else it use enabled.

Also update klish-plugin-sysrepo to not show the obsoleted node
in autocompletion.

This fixes #331
2024-03-06 18:39:27 +01:00
Joachim Wiberg e8ff54cb67 Revert "confd: check return value on failure to read pvid from a bridge-port"
This reverts commit f5e37bba58 because it
causes a regression in setting up VLAN filtering bridges.  The bridge
itself, e.g., br0 currently does not have a bridge-port context at the
same time as it being bridge.  The model does not account for that and
thus srx_get_int() for the br0 PVID will always fail.

Reverting this commit allows br0 to be tagged member in all VLANs by
default, for now.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 10:51:19 +01:00
Joachim Wiberg 3151db6f61 Open v24.03.0 release cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 09:27:24 +01:00
Joachim Wiberg 3ab33cebe4 confd: fix bogus warning about not updating /etc/motd properly
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 09:12:36 +01:00
Joachim Wiberg 6ce44b0788 libsrx: reduce noise in syslog
The srx_*() family of APIs are for some callbacks in confd used to check
if a setting exists or not.  The root helper function srx_vaget() always
logged an error if sr_get_items() failed.  This has now been fixed and
only the srx_enabled() function still triggers this, because it has no
way of determining an error condition -- otoh it should never fail.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 08:54:59 +01:00
Joachim Wiberg c4f3cbf5e1 libsrx: minor, rename function argument, result -> value
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 08:53:50 +01:00
Joachim Wiberg f5e37bba58 confd: check return value on failure to read pvid from a bridge-port
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-06 08:49:23 +01:00
Mattias WalströmandJoachim Wiberg c3e707788d Fix VLAN infer when using interface name IFNAME.VID for naming
Then set all VLAN settings properly as well

This fixes #329
2024-03-06 06:59:46 +01:00
Joachim Wiberg eec5546100 board/common: add missing newline at end of /etc/motd
With the changes in 9847a8f we can keep the /etc/motd file with a proper
newline at EOF so that also Classic builds make sense.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-01 20:19:17 +01:00
97 changed files with 3248 additions and 6817 deletions
@@ -6,3 +6,7 @@
compatible = "marvell,cp115-standalone-pinctrl";
};
};
&cp0_xmdio {
clock-names = "gop_clk", "mg_clk", "mg_core_clk", "axi_clk";
};
+76
View File
@@ -0,0 +1,76 @@
#ifndef _STYX_MPP_H
#define _STYX_MPP_H
#define SFP0_TX_DISABLE(X) X( "mpp0", cp0_gpio1, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)
#define SFP1_TX_DISABLE(X) X( "mpp1", cp0_gpio1, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)
#define SFP2_TX_DISABLE(X) X( "mpp2", cp0_gpio1, 2, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)
#define SFP3_TX_DISABLE(X) X( "mpp3", cp0_gpio1, 3, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)
#define SFP0_RS0(X) X( "mpp4", cp0_gpio1, 4, GPIO_ACTIVE_HIGH)
#define SFP1_RS0(X) X( "mpp5", cp0_gpio1, 5, GPIO_ACTIVE_HIGH)
#define SFP2_RS0(X) X( "mpp6", cp0_gpio1, 6, GPIO_ACTIVE_HIGH)
#define SFP3_RS0(X) X( "mpp7", cp0_gpio1, 7, GPIO_ACTIVE_HIGH)
#define SFP0_RS1(X) X( "mpp8", cp0_gpio1, 8, GPIO_ACTIVE_HIGH)
#define SFP1_RS1(X) X( "mpp9", cp0_gpio1, 9, GPIO_ACTIVE_HIGH)
#define SFP2_RS1(X) X("mpp10", cp0_gpio1, 10, GPIO_ACTIVE_HIGH)
#define SFP3_RS1(X) X("mpp11", cp0_gpio1, 11, GPIO_ACTIVE_HIGH)
/* mpp12: Unused */
#define CP_SPI1_MISO(X) X("mpp13", none, 0, 0)
#define CP_SPI1_CS0(X) X("mpp14", none, 0, 0)
#define CP_SPI1_MOSI(X) X("mpp15", none, 0, 0)
#define CP_SPI1_SCK(X) X("mpp16", none, 0, 0)
/* mpp17: Unused */
/* mpp18: Unused */
/* mpp19: Unused */
/* mpp20: Unused */
/* mpp21: Unused */
/* mpp22: Unused */
/* mpp23: Unused */
/* mpp24: Unused */
/* mpp25: Unused */
/* mpp26: Unused */
#define SFP0_RX_LOS(X) X("mpp27", cp0_gpio1, 27, GPIO_ACTIVE_HIGH)
#define SFP1_RX_LOS(X) X("mpp28", cp0_gpio1, 28, GPIO_ACTIVE_HIGH)
#define SFP2_RX_LOS(X) X("mpp29", cp0_gpio1, 29, GPIO_ACTIVE_HIGH)
#define SFP3_RX_LOS(X) X("mpp30", cp0_gpio1, 30, GPIO_ACTIVE_HIGH)
#define SFP0_TX_FAULT(X) X("mpp31", cp0_gpio1, 31, GPIO_ACTIVE_HIGH)
#define SFP1_TX_FAULT(X) X("mpp32", cp0_gpio2, 0, GPIO_ACTIVE_HIGH)
#define SFP2_TX_FAULT(X) X("mpp33", cp0_gpio2, 1, GPIO_ACTIVE_HIGH)
#define SFP3_TX_FAULT(X) X("mpp34", cp0_gpio2, 2, GPIO_ACTIVE_HIGH)
#define CP_I2C1_SDA(X) X("mpp35", none, 0, 0)
#define CP_I2C1_SCK(X) X("mpp36", none, 0, 0)
#define CP_I2C0_SCK(X) X("mpp37", none, 0, 0)
#define CP_I2C0_SDA(X) X("mpp38", none, 0, 0)
/* mpp39: Unused */
#define CP_SMI_MDIO(X) X("mpp40", none, 0, 0)
#define CP_SMI_MDC(X) X("mpp41", none, 0, 0)
/* mpp42: Unused */
/* mpp43: Unused */
/* mpp44: Unused */
/* mpp45: Unused */
/* mpp46: Unused */
#define CP_UA1_TXD(X) X("mpp47", none, 0, 0)
/* mpp48: Unused */
#define SW1_RESETn(X) X("mpp49", cp0_gpio2, 17, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SW2_RESETn(X) X("mpp50", cp0_gpio2, 18, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SW3_RESETn(X) X("mpp51", cp0_gpio2, 19, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
/* mpp52: Unused */
#define CP_UA1_RXD(X) X("mpp53", none, 0, 0)
#define SFP0_MOD_ABS(X) X("mpp54", cp0_gpio2, 22, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SFP1_MOD_ABS(X) X("mpp55", cp0_gpio2, 23, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SFP2_MOD_ABS(X) X("mpp56", cp0_gpio2, 24, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SFP3_MOD_ABS(X) X("mpp57", cp0_gpio2, 25, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)
#define SW1_INTn(X) X("mpp58", cp0_gpio2, 26, IRQ_TYPE_LEVEL_LOW)
#define SW2_INTn(X) X("mpp59", cp0_gpio2, 27, IRQ_TYPE_LEVEL_LOW)
#define SW3_INTn(X) X("mpp60", cp0_gpio2, 28, IRQ_TYPE_LEVEL_LOW)
/* mpp61: Unused */
#define DDR_TEN(X) X("mpp62", cp0_gpio2, 30, GPIO_ACTIVE_HIGH)
/* Macros to extract MPP info in different formats */
#define MPP_ID(_mpp, _chip, _no, _flags) _mpp
#define MPP_GPIO_CHIP(_mpp, _chip, _no, _flags) _chip
#define MPP_GPIO_REF(_mpp, _chip, _no, _flags) <&_chip _no (_flags)>
#define MPP_GPIO_REF_NO_CHIP(_mpp, _chip, _no, _flags) <_no (_flags)>
#define MPP_IRQ_REF(_mpp, _chip, _no, _flags) <&_chip _no (_flags)>
#endif /* _STYX_MPP_H */
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2021 Marvell International Ltd.
* Copyright (C) 2023 Addiva Elektronik AB
*
* Device tree for Styx board
*/
#include "styx.dtsi"
+566
View File
@@ -0,0 +1,566 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2021 Marvell International Ltd.
* Copyright (C) 2023 Addiva Elektronik AB
*
* Device tree for Styx board
*/
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include "../marvell/cn9130-patched.dtsi"
#include "styx-mpp.h"
/ {
model = "Styx";
compatible = "styx,styx",
"marvell,armada-ap807-quad",
"marvell,armada-ap807";
chosen {
stdout-path = "serial0:115200n8";
infix {
/* "admin" */
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
vpds = <&vpd>;
};
};
memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
};
/* UART0 (Console) */
&uart0 {
status = "okay";
};
/* UART1 (Auxiliary) */
&cp0_pinctrl {
cp0_uart1_pins: cp0-uart1-pins {
marvell,pins = CP_UA1_RXD(MPP_ID), CP_UA1_TXD(MPP_ID);
marvell,function = "uart1";
};
};
&cp0_uart1 {
/* TODO: Figure out how to enable this without affecting
* /chosen/stdout-path
*/
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&cp0_uart1_pins>;
};
/* GPIO */
&cp0_gpio1 {
status = "okay";
};
&cp0_gpio2 {
status = "okay";
};
/* I2C0 (EEPROM) */
&cp0_pinctrl {
cp0_i2c0_pins: cp0-i2c0-pins {
marvell,pins = CP_I2C0_SCK(MPP_ID), CP_I2C0_SDA(MPP_ID);
marvell,function = "i2c0";
};
};
&cp0_i2c0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&cp0_i2c0_pins>;
vpd: eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
infix,board = "cpu";
infix,trusted;
nvmem-layout {
compatible = "onie,tlv-layout";
base_mac: mac-address {
#nvmem-cell-cells = <1>;
};
};
};
spd: eeprom@53 {
compatible = "spd";
reg = <0x53>;
};
eeprom@57 {
compatible = "atmel,24c256";
reg = <0x57>;
};
};
/* I2C1 (Mux) */
&cp0_pinctrl {
cp0_i2c1_pins: cp0-i2c1-pins {
marvell,pins = CP_I2C1_SCK(MPP_ID), CP_I2C1_SDA(MPP_ID);
marvell,function = "i2c1";
};
};
&cp0_i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&cp0_i2c1_pins>;
i2cmux@77 {
compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x77>;
i2c_sfp0: i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
};
i2c_sfp1: i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
};
i2c_sfp2: i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
};
i2c_sfp3: i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
};
};
};
/* SPI1 (Boot FLASH) */
&cp0_pinctrl {
cp0_spi1_pins: cp0-spi-pins-0 {
marvell,pins = \
CP_SPI1_MISO(MPP_ID), CP_SPI1_CS0(MPP_ID), \
CP_SPI1_MOSI(MPP_ID), CP_SPI1_SCK(MPP_ID);
marvell,function = "spi1";
};
};
&cp0_spi1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&cp0_spi1_pins>;
/* Boot flash */
spi-flash@0 {
#address-cells = <0x1>;
#size-cells = <0x1>;
compatible = "jedec,spi-nor", "spi-flash";
reg = <0x0>;
spi-max-frequency = <90000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
boot0@0 {
label = "boot0";
reg = <0x0 0x200000>;
};
boot1@200000 {
label = "boot1";
reg = <0x200000 0x200000>;
};
};
};
};
/* AP SDHCI (eMMC) */
&ap_sdhci0 {
status = "okay";
bus-width = <8>;
mmc-ddr-1_8v;
mmc-hs400-1_8v;
};
&cp0_crypto {
status = "okay";
};
&cp0_ethernet {
status = "okay";
};
/* ETH1 (Connection to BMC) */
&cp0_eth1 {
status = "okay";
phy-mode = "sgmii";
phys = <&cp0_comphy5 0>;
managed = "in-band-status";
nvmem-cells = <&base_mac 0>;
nvmem-cell-names = "mac-address";
};
/* ETH0 (DSA connection to switch tree) */
&cp0_eth0 {
status = "okay";
phy-mode = "10gbase-r";
phys = <&cp0_comphy2 0>;
managed = "in-band-status";
nvmem-cells = <&base_mac 0>;
nvmem-cell-names = "mac-address";
};
/* MDIO (Switch Tree) */
&cp0_pinctrl {
cp0_mdio_pins: cp0-mdio-pins-0 {
marvell,pins = CP_SMI_MDIO(MPP_ID), CP_SMI_MDC(MPP_ID);
marvell,function = "ge";
};
};
#define SWP_LED(_func) \
leds { \
#address-cells = <1>; \
#size-cells = <0>; \
\
led@0 { \
reg = <0>; \
function = _func; \
color = <LED_COLOR_ID_GREEN>; \
default-state = "keep"; \
}; \
led@1 { \
reg = <1>; \
function = _func; \
color = <LED_COLOR_ID_YELLOW>; \
default-state = "off"; \
}; \
}
#define XSWP(_n, _label, _mac_offs, _sfp) \
port@_n { \
reg = <0x ## _n>; \
label = _label; \
nvmem-cells = <&base_mac _mac_offs>; \
nvmem-cell-names = "mac-address"; \
phy-mode = "10gbase-r"; \
managed = "in-band-status"; \
sfp = <&_sfp>; \
SWP_LED("sfp"); \
}
#define GSWP(_n, _label, _mac_offs, _phy) \
port@_n { \
reg = <0x ## _n>; \
label = _label; \
nvmem-cells = <&base_mac _mac_offs>; \
nvmem-cell-names = "mac-address"; \
phy-mode = "gmii"; \
phy-handle = <&_phy>; \
SWP_LED("tp"); \
}
#define GPHY(_n) \
ethernet-phy@_n { \
compatible = "ethernet-phy-ieee802.3-c22"; \
reg = <_n>; \
eee-broken-100tx; \
eee-broken-1000t; \
}
&cp0_mdio {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&cp0_mdio_pins>;
sw3: switch@6 {
compatible = "marvell,mv88e6190";
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
reset-gpios = SW3_RESETn(MPP_GPIO_REF);
interrupts-extended = SW3_INTn(MPP_IRQ_REF);
interrupt-controller;
dsa,member = <0 0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@9 {
reg = <0x9>;
label = "cpu";
ethernet = <&cp0_eth0>;
phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
full-duplex;
};
};
sw3p10: port@a {
reg = <0xa>;
link = <&sw2p10 &sw1p0>;
phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
full-duplex;
};
};
/* Can't use XSWP macro as port 0 does not have
* any LEDs attached to it. LEDs for port 10 seem
* to be wired to the corresponding SFP cage. Maybe
* we can apply a static workaround by binding port
* 10's green LED to "Special LED 1", so we can at
* least see link/act.
*/
port@0 {
reg = <0>;
label = "e16";
nvmem-cells = <&base_mac 16>;
nvmem-cell-names = "mac-address";
phy-mode = "10gbase-r";
managed = "in-band-status";
sfp = <&sfp3>;
};
GSWP(1, "e22", 22, sw3phy1);
GSWP(2, "e21", 21, sw3phy2);
GSWP(3, "e24", 24, sw3phy3);
GSWP(4, "e23", 23, sw3phy4);
GSWP(5, "e26", 26, sw3phy5);
GSWP(6, "e25", 25, sw3phy6);
GSWP(7, "e28", 28, sw3phy7);
GSWP(8, "e27", 27, sw3phy8);
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
sw3phy1: GPHY(1);
sw3phy2: GPHY(2);
sw3phy3: GPHY(3);
sw3phy4: GPHY(4);
sw3phy5: GPHY(5);
sw3phy6: GPHY(6);
sw3phy7: GPHY(7);
sw3phy8: GPHY(8);
};
};
sw2: switch@4 {
compatible = "marvell,mv88e6190";
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
reset-gpios = SW2_RESETn(MPP_GPIO_REF);
interrupts-extended = SW2_INTn(MPP_IRQ_REF);
interrupt-controller;
dsa,member = <0 1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
sw2p0: port@0 {
reg = <0x0>;
link = <&sw1p0>;
phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
full-duplex;
};
};
sw2p10: port@a {
reg = <0xa>;
link = <&sw3p10>;
phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
full-duplex;
};
};
GSWP(1, "e10", 10, sw2phy1);
GSWP(2, "e9", 9, sw2phy2);
GSWP(3, "e12", 12, sw2phy3);
GSWP(4, "e11", 11, sw2phy4);
GSWP(5, "e18", 18, sw2phy5);
GSWP(6, "e17", 17, sw2phy6);
GSWP(7, "e20", 20, sw2phy7);
GSWP(8, "e19", 19, sw2phy8);
XSWP(9, "e15", 15, sfp2);
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
sw2phy1: GPHY(1);
sw2phy2: GPHY(2);
sw2phy3: GPHY(3);
sw2phy4: GPHY(4);
sw2phy5: GPHY(5);
sw2phy6: GPHY(6);
sw2phy7: GPHY(7);
sw2phy8: GPHY(8);
};
};
sw1: switch@2 {
compatible = "marvell,mv88e6190";
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
reset-gpios = SW1_RESETn(MPP_GPIO_REF);
interrupts-extended = SW1_INTn(MPP_IRQ_REF);
interrupt-controller;
dsa,member = <0 2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
sw1p0: port@0 {
reg = <0x0>;
link = <&sw2p0 &sw3p10>;
phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
full-duplex;
};
};
GSWP(1, "e2", 2, sw1phy1);
GSWP(2, "e1", 1, sw1phy2);
GSWP(3, "e4", 4, sw1phy3);
GSWP(4, "e3", 3, sw1phy4);
GSWP(5, "e6", 6, sw1phy5);
GSWP(6, "e5", 5, sw1phy6);
GSWP(7, "e8", 8, sw1phy7);
GSWP(8, "e7", 7, sw1phy8);
XSWP(9, "e14", 14, sfp1);
XSWP(a, "e13", 13, sfp0);
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
sw1phy1: GPHY(1);
sw1phy2: GPHY(2);
sw1phy3: GPHY(3);
sw1phy4: GPHY(4);
sw1phy5: GPHY(5);
sw1phy6: GPHY(6);
sw1phy7: GPHY(7);
sw1phy8: GPHY(8);
};
};
};
/ {
sfp0: sfp@0 {
compatible = "sff,sfp";
i2c-bus = <&i2c_sfp0>;
mod-def0-gpios = SFP0_MOD_ABS(MPP_GPIO_REF);
los-gpios = SFP0_RX_LOS(MPP_GPIO_REF);
tx-disable-gpios = SFP0_TX_DISABLE(MPP_GPIO_REF);
tx-fault-gpios = SFP0_TX_FAULT(MPP_GPIO_REF);
rate-select0-gpios = SFP0_RS0(MPP_GPIO_REF);
rate-select1-gpios = SFP0_RS1(MPP_GPIO_REF);
maximum-power-milliwatt = <3000>;
};
sfp1: sfp@1 {
compatible = "sff,sfp";
i2c-bus = <&i2c_sfp1>;
mod-def0-gpios = SFP1_MOD_ABS(MPP_GPIO_REF);
los-gpios = SFP1_RX_LOS(MPP_GPIO_REF);
tx-disable-gpios = SFP1_TX_DISABLE(MPP_GPIO_REF);
tx-fault-gpios = SFP1_TX_FAULT(MPP_GPIO_REF);
rate-select0-gpios = SFP1_RS0(MPP_GPIO_REF);
rate-select1-gpios = SFP1_RS1(MPP_GPIO_REF);
maximum-power-milliwatt = <3000>;
};
sfp2: sfp@2 {
compatible = "sff,sfp";
i2c-bus = <&i2c_sfp2>;
mod-def0-gpios = SFP2_MOD_ABS(MPP_GPIO_REF);
los-gpios = SFP2_RX_LOS(MPP_GPIO_REF);
tx-disable-gpios = SFP2_TX_DISABLE(MPP_GPIO_REF);
tx-fault-gpios = SFP2_TX_FAULT(MPP_GPIO_REF);
rate-select0-gpios = SFP2_RS0(MPP_GPIO_REF);
rate-select1-gpios = SFP2_RS1(MPP_GPIO_REF);
maximum-power-milliwatt = <3000>;
};
sfp3: sfp@3 {
compatible = "sff,sfp";
i2c-bus = <&i2c_sfp3>;
mod-def0-gpios = SFP3_MOD_ABS(MPP_GPIO_REF);
los-gpios = SFP3_RX_LOS(MPP_GPIO_REF);
tx-disable-gpios = SFP3_TX_DISABLE(MPP_GPIO_REF);
tx-fault-gpios = SFP3_TX_FAULT(MPP_GPIO_REF);
rate-select0-gpios = SFP3_RS0(MPP_GPIO_REF);
rate-select1-gpios = SFP3_RS1(MPP_GPIO_REF);
maximum-power-milliwatt = <3000>;
};
};
+1 -1
View File
@@ -1,4 +1,4 @@
.-------.
| . . | Infix -- a Network Operating System
|-. v .-| https://kernelkit.github.io
'-'---'-'
'-'---'-'
+1 -1
View File
@@ -83,7 +83,7 @@ class DTSystem:
}
def infix_usb_devices(self, out):
names=self.infix.str_array("usb-port-names")
names=self.infix.str_array("usb-port-names", ())
phs=self.__get_phandle_array("usb-ports")
data=dict(zip(names,phs))
if data != {}:
-4
View File
@@ -1,5 +1,4 @@
test-dir := $(BR2_EXTERNAL_INFIX_PATH)/test
UNIT_TESTS ?= $(test-dir)/case/all-repo.yaml $(test-dir)/case/all-unit.yaml
INFIX_TESTS ?= $(test-dir)/case/all.yaml
test-env = $(test-dir)/env \
@@ -10,9 +9,6 @@ test-env = $(test-dir)/env \
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-unit:
$(test-dir)/env $(test-dir)/9pm/9pm.py $(UNIT_TESTS)
test test-qeneth:
$(call test-env-qeneth,\
$(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py \
+2 -2
View File
@@ -29,7 +29,7 @@ BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.11"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="alder/alder marvell/armada-3720-espressobin marvell/armada-3720-espressobin-emmc marvell/armada-3720-espressobin-v7 marvell/armada-3720-espressobin-v7-emmc marvell/armada-3720-espressobin-ultra marvell/cn9130-crb-A marvell/cn9130-crb-B microchip/sparx5_pcb135_emmc_no_psci"
BR2_LINUX_KERNEL_INTREE_DTS_NAME="alder/alder styx/styx marvell/armada-3720-espressobin marvell/armada-3720-espressobin-emmc marvell/armada-3720-espressobin-v7 marvell/armada-3720-espressobin-v7-emmc marvell/armada-3720-espressobin-ultra marvell/cn9130-crb-A marvell/cn9130-crb-B microchip/sparx5_pcb135_emmc_no_psci"
BR2_LINUX_KERNEL_CUSTOM_DTS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/dts"
BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -141,7 +141,7 @@ BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_QUERIERD=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_LIBINPUT=y
DISK_IMAGE_BOOT_BIN=y
GNS3_APPLIANCE_RAM=512
+1 -1
View File
@@ -170,7 +170,7 @@ BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_QUERIERD=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_LIBINPUT=y
# SIGN_ENABLED is not set
# GNS3_APPLIANCE is not set
+1 -1
View File
@@ -144,6 +144,6 @@ BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_QUERIERD=y
BR2_PACKAGE_MCD=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+30
View File
@@ -4,6 +4,36 @@ Change Log
All notable changes to the project are documented in this file.
[v24.03.0][UNRELEASED]
-------------------------
> Development in progress, for daily updates see the team board:
> <https://github.com/orgs/kernelkit/projects/3/views/2>
### Changes
- The bridge model now has built-in validation of port memberships,
i.e., a port must be a bridge member to be used in VLAN filtering
- The bridge model only permits the bridge itself to be a tagged
member of VLANs -- meaning, the only way to set an IP address on
such bridges is to use a VLAN interface on top
- A VLAN filtering bridge now validates that no IP address has been
set. Use a VLAN interface on top for that (see above)
### Fixes
- CLI: fix VLAN inference for interfaces named `eth0.1`, i.e., VID 1 on
lower-layer-if `eth0`. Only affects automatic inference in the CLI,
entering the values manually (CLI/NETCONF) not affected by this bug
- Reduced syslog errors for accesses no non-existing xpaths
- Fix bogus warning about not properly updating `/etc/motd` in new
`motd-banner` setting, introduced in v24.02.0
- infix-routing model: the `enable` configuration setting for OSPF, in
`default-route-advertise` has been obsoleted and replaced by `enabled`
- Fix #328: when setting up a VLAN filtering bridge, the PVID for bridge
ports defaulted to 1, making it impossible to set up "tagged-only"
ports which drop ingressing untagged traffic
[v24.02.0][] - 2024-03-01
-------------------------
+78 -48
View File
@@ -130,40 +130,60 @@ By default, unlike other systems, persistent[^1] containers have no
networking enabled. All network access has to be set up explicitly.
Currently two types of of container networks are supported:
- `cni-host`: one end of a VETH pair, or a physical Ethernet port
- `cni-bridge`: an IP masquerading bridge
- `host`: one end of a VETH pair, or a physical Ethernet port
- `bridge`: an IP masquerading bridge
> For more information on VETH pairs, see the [Networking Guide][0].
### CNI Bridge
### Container Bridge
All interface configuration is done in configure context. Let's start
by creating an IP masquerading bridge, a common default for containers:
A container bridge is what most container setups use and users want.
The difference from a regular bridge is that the container runtime fully
manages them -- connecting containers automatically with VETH pairs and
setting up firewall rules between the host and other containers, as well
as managing port forwarding. This transparent background management is
what makes container use seem to be so simple.
All interface configuration is done in configure context.
admin@example-c0-ff-ee:/> configure
admin@example-c0-ff-ee:/config> edit interface docker0
admin@example-c0-ff-ee:/config/interface/docker0/> set type bridge
admin@example-c0-ff-ee:/config/interface/docker0/> set container-network type cni-bridge
admin@example-c0-ff-ee:/config/interface/docker0/> set container-network
admin@example-c0-ff-ee:/config/interface/docker0/> leave
We have to declare the interface type, and then also declare it as a
container network, ensuring the interface cannot be used by the system
for any other purpose. E.g., a `cni-host` interface is supposed to be
used by a container, by declaring it as such we can guarantee that it
would never accidentally be added as a bridge or lag port. Hence, to
move an interface currently set as a `bridge-port` it must be removed
from the bridge before being given to a container.
There is more to this story. When using the CLI, and sticking to common
interface nomenclature, Infix helps you with some of the boring stuff.
E.g., creating a new interface with a name like `brN` or `dockerN`
automatically *infers* the interface types, which you would otherwise
have to set manually:
The default subnet for a `cni-bridge` is 172.17.0.0/16, the bridge will
take the `.1` address and hand out the rest of the range to containers
admin@example-c0-ff-ee:/config/interface/docker0/> set type bridge
admin@example-c0-ff-ee:/config/interface/docker0/> set container-network type bridge
> **Note:** when doing the same operation over NETCONF there is no
> inference, so all the "magic" settings needs to be defined. This
> makes the CLI very useful for first setup and then extracting the
> resulting XML from the shell using the `cfg -X` command.
We have to declare the interface as a container network, ensuring the
interface cannot be used by the system for any other purpose. E.g., a
container `host` interface is supposed to be used by a container, by
declaring it as such we can guarantee that it would never accidentally
be added as a bridge or lag port. Hence, to move an interface currently
set as a `bridge-port` it must be removed from the bridge before being
given to a container.
The default subnet for a container `bridge` is 172.17.0.0/16, the bridge
takes the `.1` address and hand out the rest of the range to containers
in a round-robin like fashion. A container with this `network` get an
automatically created VETH pair connection to the bridge and a lot of
other networking parameters (DNS, default route) are set up.
Some of the defaults of a `cni-bridge` can be changed, e.g., instead of
`set container-network type cni-bridge`, above, do:
Some of the defaults of a container `bridge` can be changed, e.g.,
instead of `set container-network type bridge`, above, do:
admin@example-c0-ff-ee:/config/interface/docker0/> edit container-network
admin@example-c0-ff-ee:/config/interface/docker0/container-network/> set type cni-bridge
admin@example-c0-ff-ee:/config/interface/docker0/container-network/> set type bridge
admin@example-c0-ff-ee:/config/interface/docker0/container-network/> edit subnet 192.168.0.0/16
admin@example-c0-ff-ee:/config/interface/docker0/container-network/subnet/192.168.0.0/16/> set gateway 192.168.255.254
admin@example-c0-ff-ee:/config/interface/docker0/container-network/subnet/192.168.0.0/16/> end
@@ -173,42 +193,44 @@ Some of the defaults of a `cni-bridge` can be changed, e.g., instead of
admin@example-c0-ff-ee:/config/interface/docker0/container-network/> end
admin@example-c0-ff-ee:/config/interface/docker0/> leave
Other network settings, like DNS and domain, use built-in defaults in
CNI, but can be overridden from each container. Other common settings
per container is the IP address and name of the network interface inside
the container. The default, after each stop/start cycle, or reboot of
the host, is to name the interfaces `eth0`, `eth1`, in the order they
are given in the `network` list, and to give the container the next
address in a `cni-bridge`. Below an example of a system container calls
`set network interface docker0`, here we show how to set options for
that network:
Other network settings, like DNS and domain, use built-in defaults, but
can be overridden from each container. Other common settings per
container is the IP address and name of the network interface inside the
container. The default, after each stop/start cycle, or reboot of the
host, is to name the interfaces `eth0`, `eth1`, in the order they are
given in the `network` list, and to give the container the next address
in a `bridge`. Below an example of a system container calls `set
network interface docker0`, here we show how to set options for that
network:
admin@example-c0-ff-ee:/config/container/ntpd/> edit network docker0
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/>
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/> set option
<string> Options for CNI bridges.
<string> Options for masquerading container bridges.
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/> help option
NAME
option <string>
DESCRIPTION
Options for CNI bridges.
Example: ip=1.2.3.4 to request a specific IP, both IPv4 and IPv6.
interface_name=foo0 name to set interface name inside container.
Options for masquerading container bridges.
Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6)
mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
interface_name=foo0 -- set interface name inside container
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/> set option ip=172.17.0.2
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/> set option interface_name=wan
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/> leave
### CNI Host
### Container Host Interface
Another common use-case is to move a network interface into the network
namespace of a container. Which the CNI bridge network 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).
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).
admin@example-c0-ff-ee:/config/> edit interface veth0
admin@example-c0-ff-ee:/config/interface/veth0/> set veth peer ntpd
@@ -223,7 +245,7 @@ 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 CNI Bridge setup.
the default in the masquerading container bridge setup.
### Host Networking
@@ -276,7 +298,7 @@ host loads its `startup-config` (or even `factory-config`) a temporary
file is created using the decoded base64 data from the `content` node.
admin@example-c0-ff-ee:/config/container/ntpd/> edit mount ntpd.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> set content
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> text-editor content
... interactive editor starts up ...
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> set target /etc/ntpd.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> end
@@ -290,6 +312,9 @@ the contents are base64 encoded and stored in the candidate datastore.
> restarted, changes made by the container are not preserved, or saved
> back to the host's startup-config even if the read-only option is off.
Infix has three different text editors available. For more information,
see [CLI Text Editor](cli/text-editor.md).
Example Containers
------------------
@@ -350,18 +375,22 @@ container ID (hash) is used, but this can be easily changed:
Infix currently does not have a native firewall configuration, and even
when it does it will never expose the full capabilities of `nftables`.
For really advanced setups, the following will be the only alternative:
For advanced setups, the following is an interesting alternative.
admin@example-c0-ff-ee:/> configure
admin@example-c0-ff-ee:/config> edit container nftables
admin@example-c0-ff-ee:/config/container/system/> set image ghcr.io/kernelkit/curios-nftables:edge
admin@example-c0-ff-ee:/config/container/system/> set network host
admin@example-c0-ff-ee:/config/container/system/> edit mount nftables.conf
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> set target /etc/nftables.conf
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> set content
admin@example-c0-ff-ee:/config/container/nftables/> set image ghcr.io/kernelkit/curios-nftables:edge
admin@example-c0-ff-ee:/config/container/nftables/> set network host
admin@example-c0-ff-ee:/config/container/nftables/> set privileged true
admin@example-c0-ff-ee:/config/container/nftables/> edit mount nftables.conf
admin@example-c0-ff-ee:/config/container/nftables/mount/nftables.conf/> set target /etc/nftables.conf
admin@example-c0-ff-ee:/config/container/nftables/mount/nftables.conf/> text-editor content
... interactive editor starts up where you can paste your rules ...
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> leave
admin@example-c0-ff-ee:/config/container/nftables/mount/nftables.conf/> leave
Notice how we `set network host`, so the container can see and act on
all the host's interfaces, and that we also have to run the container
in *privileged* mode.
### Application Container: ntpd
@@ -381,7 +410,7 @@ use volumes in this example.
admin@example-c0-ff-ee:/config/container/ntpd/> set network interface ntpd # From veth0 above
admin@example-c0-ff-ee:/config/container/ntpd/> edit mount ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> set target /etc/ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> set content
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> text-editor content
... interactive editor starts up where you can paste your rules ...
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> end
admin@example-c0-ff-ee:/config/container/ntpd/> edit volume varlib
@@ -418,6 +447,7 @@ restarted.
> keep over an upgrade.
[0]: networking.md
[1]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-containers%402023-12-14.yang
[2]: https://github.com/troglobit/mg
[podman]: https://podman.io
+4 -1498
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 358 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 335 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 250 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 227 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 237 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 230 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 342 KiB

+4 -730
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 268 KiB

+111 -23
View File
@@ -1,5 +1,13 @@
# Linux Networking
Infix aims to support all Linux Networking constructs. The YANG models
used to describe the system are chosen to fit well and leverage the
underlying Linux kernel's capabilities. The `ietf-interfaces.yang`
model forms the base, extended with `ietf-ip.yang` and other layer-3
IETF models. The layer-2 bridge and aggregate models are defined by
Infix to exploit the unique features not available in IEEE models.
## Interface LEGO®
![Linux Networking Blocks](img/lego.svg)
@@ -16,21 +24,38 @@
## Data Plane
The blocks you ctose, and how you connect them, defines your data plane. Here we see an example of how to bridge a virtual port with a physical LAN.
The blocks you choose, and how you connect them, defines your data plane.
Here we see an example of how to bridge a virtual port with a physical
LAN.
![Example of a 4-port switch with a link aggregate and a VETH pair to a container](img/dataplane.svg)
Depending on the (optional) VLAN filtering of the bridge, the container may have full or limited connectivity with outside ports, as well as the internal CPU.
Depending on the (optional) VLAN filtering of the bridge, the container
may have full or limited connectivity with outside ports, as well as the
internal CPU.
In fact the virtual port connected to the bridge can be member of several VLANs, with each VLAN being an interface with an IP address inside the container.
In fact the virtual port connected to the bridge can be member of
several VLANs, with each VLAN being an interface with an IP address
inside the container.
Thanks to Linux, and technologies like switchdev, that allow you to split a switching fabric into unique (isolated) ports, the full separation and virtualization of all Ethernet layer properties are possible to share with a container. Meaning, all the building blocks used on the left hand side can also be used freely on the right hand side as well.
Thanks to Linux, and technologies like switchdev, that allow you to
split a switching fabric into unique (isolated) ports, the full
separation and virtualization of all Ethernet layer properties are
possible to share with a container. Meaning, all the building blocks
used on the left hand side can also be used freely on the right hand
side as well.
### Bridging
This is the most central part of the system. A bridge is a switch, and a switch is a bridge. In Linux, setting up a bridge with ports connected to physical switch fabric, means you manage the actual switch fabric!
This is the most central part of the system. A bridge is a switch, and
a switch is a bridge. In Linux, setting up a bridge with ports
connected to physical switch fabric, means you manage the actual switch
fabric!
In Infix ports are by default not switch ports, unless the customer specific factory config sets it up this way. To enable switching between ports you create a bridge and then add ports to that bridge. That's it.
In Infix ports are by default not switch ports, unless the customer
specific factory config sets it up this way. To enable switching
between ports you create a bridge and then add ports to that
bridge. That's it.
```
admin@example:/> configure
@@ -43,12 +68,19 @@ admin@example:/config/> leave
Here we add two ports to bridge `br0`: `eth0` and `eth1`.
> **Note:** Infix has many built-in helpers controlled by convention. E.g., if you name your bridge `brN`, where `N` is a number, Infix will set the interface type automatically for you, and unlock all bridge features for you.
> **Note:** Infix has many built-in helpers controlled by convention.
> E.g., if you name your bridge `brN`, where `N` is a number, Infix sets
> the interface type automatically and unlocks all bridge features.
> Other "magic" names are `ethN.M` for VLAN M on top of `ethN`, or
> `dockerN` to create an IP masquerading container bridge.
#### VLAN Filtering Bridge
By default bridges in Linux do not filter based on VLAN tags. It can be enabled in Infix when creating a bridge by adding a port to a VLAN as a tagged or untagged member.
Use the port default VID (PVID) setting to control VLAN association for traffic ingressing a port untagged (default PVID: 1).
By default bridges in Linux do not filter based on VLAN tags. It can be
enabled in Infix when creating a bridge by adding a port to a VLAN as a
tagged or untagged member. Use the port default VID (PVID) setting to
control VLAN association for traffic ingressing a port untagged (default
PVID: 1).
```
admin@example:/config/> edit interface br0
@@ -66,21 +98,32 @@ This sets `eth0` as an untagged member of VLAN 10 and `eth1` as an
untagged member of VLAN 20. Switching between these ports is thus
prohibited.
To terminate a VLAN in the switch itself, either for switch management or for routing, the bridge must become a (tagged) member of the VLAN.
To terminate a VLAN in the switch itself, either for switch management
or for routing, the bridge must become a (tagged) member of the VLAN.
```
admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0
admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
```
> To route or to manage via a VLAN, a VLAN interface also needs to be created on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces) below.
> To route or to manage via a VLAN, a VLAN interface needs to be created
> on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces)
> below for more on this topic.
### VLAN Interfaces
Creating a VLAN can be done in many ways. This section assumes VLAN interfaces created atop another Linux interface. E.g., the VLAN interfaces created on top of the Ethernet interface or bridge in the picture below.
Creating a VLAN can be done in many ways. This section assumes VLAN
interfaces created atop another Linux interface. E.g., the VLAN
interfaces created on top of the Ethernet interface or bridge in the
picture below.
![VLAN interface on top of Ethernet or Bridge interfaces](img/interface-vlan-variants.svg)
A VLAN interface is basically a filtering abstraction. When you run `tcpdump` on a VLAN interface you will only see the frames matching the VLAN ID of the interface, compared to *all* the VLAN IDs if you run `tcpdump` on the lower-layer interface.
A VLAN interface is basically a filtering abstraction. When you run
`tcpdump` on a VLAN interface you will only see the frames matching the
VLAN ID of the interface, compared to *all* the VLAN IDs if you run
`tcpdump` on the lower-layer interface.
```
admin@example:/> configure
@@ -90,7 +133,8 @@ admin@example:/config/interface/eth0.20/> set vlan lower-layer-if eth0
admin@example:/config/interface/eth0.20/> leave
```
The example below assumes bridge br0 is already created, see [VLAN Filtering Bridge](#vlan-filtering-bridge).
The example below assumes bridge br0 is already created, see [VLAN
Filtering Bridge](#vlan-filtering-bridge).
```
admin@example:/> configure
@@ -100,15 +144,57 @@ admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
admin@example:/config/interface/vlan10/> leave
```
As conventions, a VLAN interface for VID 20 on top of an Ethernet interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on top of a bridge interface *br0* is named *vlan10*.
As conventions, a VLAN interface for VID 20 on top of an Ethernet
interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on
top of a bridge interface *br0* is named *vlan10*.
> **Note:** If you name your VLAN interface `foo0.N` or `vlanN`, where `N` is a number, Infix will set the interface type automatically for you.
### VETH Pairs
A Virtual Ethernet (VETH) pair is basically a virtual Ethernet cable. A
cable can be "plugged in" to a bridge and the other end can be given to
a [container](container.md), or plugged into another bridge.
The latter example is useful if you have multiple bridges in the system
with different properties (VLAN filtering, IEEE group forwarding, etc.),
but still want some way of communicating between these domains.
```
admin@example:/> configure
admin@example:/config/> edit interface veth0a
admin@example:/config/interface/veth0a/> set veth peer veth0b
admin@example:/config/interface/veth0a/> end
admin@example:/config/> diff
interfaces {
+ interface veth0a {
+ type veth;
+ veth {
+ peer veth0b;
+ }
+ }
+ interface veth0b {
+ type veth;
+ veth {
+ peer veth0a;
+ }
+ }
}
admin@example:/config/>
```
> **Note:** this is another example of the automatic inference of the
> interface type from the name. Any name can be used, but then you have
> to set the interface type to `veth` manually.
## Management Plane
This section details IP Addresses And Other Per-Interface IP settings.
Infix support several network interface types, each can be assigned one or more IP addresses, both IPv4 and IPv6 are supported.
Infix support several network interface types, each can be assigned one
or more IP addresses, both IPv4 and IPv6 are supported.
![IP on top of network interface examples](img/ip-iface-examples.svg)
@@ -245,7 +331,8 @@ The resulting address (10.1.2.100/24) is of type *dhcp*.
#### Disabling IPv6 link-local address(es)
The (only) way to disable IPv6 link-local addresses is by disabling IPv6 on the interface.
The (only) way to disable IPv6 link-local addresses is by disabling IPv6
on the interface.
```(disabling
admin@example:/> configure
@@ -479,10 +566,12 @@ an Ethernet interface can be done as follows.
#### Debug OSPFv2
Using NETCONF and the YANG model *ietf-routing* it is possible to read the OSPF routing table, neighbors
and more, that may be useful for debugging the OSPFv2 setup. The CLI
has various OSPF status commands such as `show ospf neighbor`, `show
ospf interface` and `show ospf routes`.
Using NETCONF and the YANG model *ietf-routing* it is possible to read
the OSPF routing table, neighbors and more, that may be useful for
debugging the OSPFv2 setup. The CLI has various OSPF status commands
such as `show ospf neighbor`, `show ospf interface` and `show ospf
routes`.
admin@example:/> show ospf neighbor
@@ -494,6 +583,7 @@ ospf interface` and `show ospf routes`.
### View routing table
The routing table can be viewed from the operational datastore over
NETCONF or using the CLI:
@@ -539,5 +629,3 @@ currently supported, namely `ipv4` and `ipv6`.
[^2]: Link-local IPv6 addresses are implicitly enabled when enabling IPv6.
IPv6 can be enabled/disabled per interface in the [ietf-ip][ietf-ip-yang]
YANG model.
+1
View File
@@ -4,6 +4,7 @@ include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/package/*/*.mk))
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/common.mk
-include $(BR2_EXTERNAL_INFIX_PATH)/board/$(patsubst "%",%,$(BR2_ARCH))/board.mk
include $(BR2_EXTERNAL_INFIX_PATH)/infix.mk
include $(BR2_EXTERNAL_INFIX_PATH)/test/test.mk
.PHONY: local.mk
local.mk:
+1 -1
View File
@@ -15,9 +15,9 @@ 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/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/mdnsd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/podman/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/querierd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/greenpak-programmer/Config.in"
@@ -1,3 +1,3 @@
# Locally calculated
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
sha256 c06a369147ae1071c0c309c0bd9d49d8ae0ff5dd1e804e2009b1a18f7fc12b5c klish-plugin-sysrepo-909cbfb1253a3c3c3abfdc72de9db7aaf3a08de2-br1.tar.gz
sha256 e18a45b35ade84201d9d59918e0743c0d9b5451cfe89ec1f7f0f6de2dc343a42 klish-plugin-sysrepo-364f7c7b9c61f2cfd51dfd8d94a8c67449ee439f-br1.tar.gz
@@ -4,7 +4,7 @@
#
################################################################################
KLISH_PLUGIN_SYSREPO_VERSION = 909cbfb1253a3c3c3abfdc72de9db7aaf3a08de2
KLISH_PLUGIN_SYSREPO_VERSION = 364f7c7b9c61f2cfd51dfd8d94a8c67449ee439f
KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git
#KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb
#KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_MCD
bool "mcd"
help
A bridge helper daemon for sending multicast queries.
https://github.com/kernelkit/mcd
@@ -1,4 +1,4 @@
# /etc/querierd.conf: default Infix configuration
# /etc/mcd.conf: example configuration
# Query interval can be [1,1024], default 125. Recommended not go below 10
#query-interval 125
@@ -26,6 +26,7 @@
# Enable and one of the IGMP versions to use at startup, with fallback
# to older versions if older clients appear.
iface vlan1 enable igmpv3
#iface vlan1 enable igmpv3
#iface vlan2 enable igmpv3
#iface vlan3 enable igmpv3
iface br0 enable igmpv3
+2
View File
@@ -0,0 +1,2 @@
sha256 63e70c0bd457b1d198acdb8d2bbe4925140ed368c7b3971a02f6c969058c039c mcd-1.0.tar.gz
sha256 834f45ed282fd010f354ecc0a50538af519a1cfcc4d2866de3be06982fa9ed29 LICENSE
+27
View File
@@ -0,0 +1,27 @@
################################################################################
#
# mcd
#
################################################################################
MCD_VERSION = 1.0
MCD_SITE = https://github.com/kernelkit/mcd/releases/download/v$(MCD_VERSION)
MCD_LICENSE = BSD-3-Clause
MCD_LICENSE_FILES = LICENSE
define MCD_INSTALL_CONFIG
$(INSTALL) -D -m 0644 $(MCD_PKGDIR)/example.conf \
$(TARGET_DIR)/etc/mcd/example.conf
endef
MCD_POST_INSTALL_TARGET_HOOKS += MCD_INSTALL_CONFIG
define MCD_INSTALL_FINIT_SVC
$(INSTALL) -D -m 0644 $(MCD_PKGDIR)/mcd.svc \
$(FINIT_D)/available/mcd.conf
$(INSTALL) -D -m 0644 $(MCD_PKGDIR)/template.svc \
$(FINIT_D)/available/mcd@.conf
endef
MCD_POST_INSTALL_TARGET_HOOKS += MCD_INSTALL_FINIT_SVC
$(eval $(autotools-package))
+1
View File
@@ -0,0 +1 @@
service [2345789] env:-/etc/default/mcd /usr/sbin/mcd -sn $MCD_ARGS -- Multicast querier daemon
+3
View File
@@ -0,0 +1,3 @@
service <net/%i/exist> \
[2345] mcd -sn -f /etc/mcd/%i.conf -i %i \
-- Multicast querier daemon @%i
-6
View File
@@ -1,6 +0,0 @@
config BR2_PACKAGE_QUERIERD
bool "querierd"
help
A bridge helper daemon for sending multicast queries.
https://github.com/westermo/querierd
-2
View File
@@ -1,2 +0,0 @@
sha256 b425e5d9db3e87a5e4d6dd3887f4378202e07aaf2304412f5c1fb0589ab625dc querierd-0.10.tar.gz
sha256 834f45ed282fd010f354ecc0a50538af519a1cfcc4d2866de3be06982fa9ed29 LICENSE
-27
View File
@@ -1,27 +0,0 @@
################################################################################
#
# querierd
#
################################################################################
QUERIERD_VERSION = 0.10
QUERIERD_SITE = \
https://github.com/westermo/querierd/releases/download/v$(QUERIERD_VERSION)
QUERIERD_LICENSE = BSD-3-Clause
QUERIERD_LICENSE_FILES = LICENSE
QUERIERD_INSTALL_STAGING = YES
define QUERIERD_INSTALL_CONFIG
$(INSTALL) -D -m 0644 $(QUERIERD_PKGDIR)/querierd.conf \
$(TARGET_DIR)/etc/
endef
QUERIERD_POST_INSTALL_TARGET_HOOKS += QUERIERD_INSTALL_CONFIG
define QUERIERD_INSTALL_FINIT_SVC
$(INSTALL) -D -m 0644 $(QUERIERD_PKGDIR)/querierd.svc \
$(FINIT_D)/available/querierd.conf
endef
QUERIERD_POST_INSTALL_TARGET_HOOKS += QUERIERD_INSTALL_FINIT_SVC
$(eval $(autotools-package))
-2
View File
@@ -1,2 +0,0 @@
# Launch IGMP querier daemon
service [2345789] env:-/etc/default/querierd /usr/sbin/querierd -sn $QUERIERD_ARGS -- IGMP querier daemon
@@ -1 +0,0 @@
service [2345] env:-/etc/default/querierd querierd -sn $QUERIERD_ARGS -- Multicast query daemon
@@ -1,7 +1,8 @@
From 4f0e44e9b494485dc63de3264aa99dad5def5f55 Mon Sep 17 00:00:00 2001
From: Henrik Nordstrom <henrik.nordstrom@addiva.se>
Date: Wed, 13 Sep 2023 22:45:00 +0200
Subject: [PATCH 1/2] cn9130: Default DDR4 4GByte 16-bit/die ECC
Subject: [PATCH 1/3] cn9130: Default DDR4 4GByte 16-bit/die ECC
Organization: Addiva Elektronik
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
@@ -1,7 +1,8 @@
From da31240645cdf7ae424727ac330fdb6f6b118691 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 16 Oct 2023 10:52:19 +0200
Subject: [PATCH 2/2] marvell: Allow mv-ddr-marvell to be built from tarball
Subject: [PATCH 2/3] marvell: Allow mv-ddr-marvell to be built from tarball
Organization: Addiva Elektronik
Build system relies on the mv-ddr-marvell being a valid GIT working
directory, which is not the case when building from a tarball.
@@ -0,0 +1,75 @@
From 27358f3101254dd08d85fbac2c614ef4d28e9984 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Fri, 12 Apr 2024 15:55:52 +0200
Subject: [PATCH 3/3] cn9130: Specify basic DDR topology via build variables
Organization: Addiva Elektronik
- The bit width of each individual die
- The capacity of each individual die
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
plat/marvell/marvell.mk | 8 ++++++
.../octeontx/otx2/t91/t9130/board/dram_port.c | 28 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/plat/marvell/marvell.mk b/plat/marvell/marvell.mk
index b6a2b9995..b8066aed2 100644
--- a/plat/marvell/marvell.mk
+++ b/plat/marvell/marvell.mk
@@ -19,3 +19,11 @@ $(eval $(call add_define,PALLADIUM))
# Set board to work with DDR 32bit
DDR32 := 0
$(eval $(call add_define,DDR32))
+
+# Default to 16b device width
+DDR_DEV_WIDTH := 16
+$(eval $(call add_define,DDR_DEV_WIDTH))
+
+# Default to 1GB dies
+DDR_DIE_CAP_GBITS := 8
+$(eval $(call add_define,DDR_DIE_CAP_GBITS))
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
index 07753ea97..78246d272 100644
--- a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
@@ -46,8 +46,36 @@ struct mv_ddr_iface dram_iface_ap0 = {
{0x1, 0x0, 0, 0},
{0x1, 0x0, 0, 0} },
SPEED_BIN_DDR_2400R, /* speed_bin */
+#if (DDR_DEV_WIDTH == 4)
+ MV_DDR_DEV_WIDTH_4BIT, /* sdram device width */
+#elif (DDR_DEV_WIDTH == 8)
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+#elif (DDR_DEV_WIDTH == 16)
MV_DDR_DEV_WIDTH_16BIT, /* sdram device width */
+#elif (DDR_DEV_WIDTH == 32)
+ MV_DDR_DEV_WIDTH_32BIT, /* sdram device width */
+#else
+#error "UNKNOWN DEVICE WIDTH"
+#endif
+#if (DDR_DIE_CAP_GBITS == 1)
+ MV_DDR_DIE_CAP_1GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 2)
+ MV_DDR_DIE_CAP_2GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 4)
+ MV_DDR_DIE_CAP_4GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 8)
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 12)
+ MV_DDR_DIE_CAP_12GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 16)
+ MV_DDR_DIE_CAP_16GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 24)
+ MV_DDR_DIE_CAP_24GBIT, /* die capacity */
+#elif (DDR_DIE_CAP_GBITS == 32)
+ MV_DDR_DIE_CAP_32GBIT, /* die capacity */
+#else
+#error "UNKNOWN DIE CAPACITY"
+#endif
MV_DDR_FREQ_SAR, /* frequency */
0, 0, /* cas_l, cas_wl */
MV_DDR_TEMP_HIGH} }, /* temperature */
--
2.34.1
@@ -0,0 +1,47 @@
From c1ed3733986486f3255e77dec47ae1d4b2836e2f Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 11 Mar 2024 15:46:38 +0100
Subject: [PATCH 3/4] Fix #397: drop ttinit() for PID 1
Organization: Addiva Elektronik
After reports from the field, see issue #397, of lockups at reboot,
we've decided to drop this code from PID 1. It was added before the 4.x
series, when the current progress output was introduced. For the older
style progress it served a purpose since the placement of [OK]/[FAIL]
was on the right hand side.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/log.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/src/log.c b/src/log.c
index ea49705..b776525 100644
--- a/src/log.c
+++ b/src/log.c
@@ -42,8 +42,6 @@ static int loglevel = LOG_INFO;
void log_init(void)
{
- ttinit();
-
if (debug)
loglevel = LOG_DEBUG;
else
@@ -53,13 +51,6 @@ void log_init(void)
/* If we enabled terse mode at boot, restore to previous setting at shutdown */
void log_exit(void)
{
- /*
- * Unless in debug mode at shutdown, Reinitialize screen,
- * terminal may have been resized at runtime
- */
- if (!debug)
- ttinit();
-
enable_progress(1);
}
--
2.34.1
@@ -0,0 +1,30 @@
From 146bf5512208cb906edddb3f0108cf6f7c525044 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 11 Mar 2024 15:55:39 +0100
Subject: [PATCH 4/4] Fix #398: display unsupported initctl command (number) in
log
Organization: Addiva Elektronik
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/api.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/api.c b/src/api.c
index c19c0d8..8d29a23 100644
--- a/src/api.c
+++ b/src/api.c
@@ -377,7 +377,9 @@ static void api_cb(uev_t *w, void *arg, int events)
case INIT_CMD_POWEROFF:
case INIT_CMD_SUSPEND:
if (IS_RESERVED_RUNLEVEL(runlevel)) {
- warnx("Unsupported command in runlevel S and 6/0.");
+ strterm(rq.data, sizeof(rq.data));
+ warnx("Unsupported command (cmd: %d, data: %s) in runlevel S and 6/0.",
+ rq.cmd, rq.data);
goto leave;
}
default:
--
2.34.1
@@ -0,0 +1,29 @@
From 90a4df8d1281fd64d048ec1bc91e8cec5f96df06 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 11 Mar 2024 18:53:22 +0100
Subject: [PATCH 5/6] plugins: on error-retry, don't print "Restoring RTC"
twice
Organization: Addiva Elektronik
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
plugins/rtc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/plugins/rtc.c b/plugins/rtc.c
index 31c99e0..238791f 100644
--- a/plugins/rtc.c
+++ b/plugins/rtc.c
@@ -180,7 +180,8 @@ static void rtc_restore(void *arg)
rc = 2;
}
- print_desc(NULL, "Restoring system clock (UTC) from RTC");
+ if (!rc)
+ print_desc(NULL, "Restoring system clock (UTC) from RTC");
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
tv.tv_sec = mktime(&tm);
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
--
2.34.1
@@ -0,0 +1,81 @@
From bf4a584e2ebfa512a2d6cfe5e43a81ee741e3296 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Tue, 12 Mar 2024 05:18:35 +0100
Subject: [PATCH 6/7] plugins: add support for hwrng and check if seed file is
empty
Organization: Addiva Elektronik
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
plugins/urandom.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/plugins/urandom.c b/plugins/urandom.c
index 64a3fa7..2da8035 100644
--- a/plugins/urandom.c
+++ b/plugins/urandom.c
@@ -47,6 +47,7 @@ static void setup(void *arg)
#ifdef RANDOMSEED
struct rand_pool_info *rpi;
ssize_t len = 0;
+ struct stat st;
int rc = -1;
int fd, err;
@@ -55,7 +56,7 @@ static void setup(void *arg)
return;
}
- if (!fexist(RANDOMSEED)) {
+ if (stat(RANDOMSEED, &st) || st.st_size < 512) {
int ret = 1;
mode_t prev;
FILE *fp;
@@ -64,16 +65,34 @@ static void setup(void *arg)
prev = umask(077);
fp = fopen(RANDOMSEED, "w");
if (fp) {
- int iter = 128;
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- srandom(tv.tv_sec % 3600);
- while (iter--) {
- uint32_t i, prng = random();
-
- for (i = 0; i < sizeof(prng); i++)
- fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
+ const char *hwrng = "/dev/hwrng";
+ FILE *hw;
+
+ hw = fopen(hwrng, "r");
+ if (hw) {
+ char buf[512];
+ size_t len;
+
+ len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
+ if (len == 0) {
+ fclose(hw);
+ goto no_hwrng;
+ }
+
+ len = fwrite(buf, sizeof(buf[0]), len, fp);
+ fclose(hw);
+ } else {
+ struct timeval tv;
+ int iter = 128;
+no_hwrng:
+ gettimeofday(&tv, NULL);
+ srandom(tv.tv_sec % 3600);
+ while (iter--) {
+ uint32_t i, prng = random();
+
+ for (i = 0; i < sizeof(prng); i++)
+ fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
+ }
}
ret = fclose(fp);
}
--
2.34.1
@@ -0,0 +1,40 @@
From b49f55ab3d1aec48bbfdf2106fd8f500406a5348 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Wed, 13 Mar 2024 11:48:47 +0100
Subject: [PATCH 7/7] tmpfiles.d: ignore x/X command, no cleanup at runtime
with Finit
Organization: Addiva Elektronik
Silence log warnings for command x/X (ignore clean for path), because
Finit does not do tmpfiles cleaning at runtime.
x /tmp/podman-run-*
x /tmp/containers-user-*
x /tmp/run-*/libpod
D! /var/lib/containers/storage/tmp 0700 root root
D! /run/podman 0700 root root
D! /var/lib/cni/networks
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/tmpfiles.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index d62b09f..15b463c 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -434,6 +434,10 @@ static void tmpfiles(char *line)
}
}
break;
+ case 'X':
+ case 'x':
+ dbg("Unsupported x/X command, ignoring %s, no support for clean at runtime.", path);
+ break;
case 'Z':
opts = "-R";
/* fallthrough */
--
2.34.1
@@ -0,0 +1,175 @@
From 5a2ab621675d39dc9ecbd4d65d5c7a424248cd11 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Tue, 5 Mar 2024 09:41:46 +0100
Subject: [PATCH] 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 f6d58238..aaab505d 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -777,6 +777,7 @@ enum br_boolopt_id {
BR_BOOLOPT_NO_LL_LEARN,
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
BR_BOOLOPT_MST_ENABLE,
+ BR_BOOLOPT_MCAST_FLOOD_ALWAYS,
BR_BOOLOPT_MAX
};
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 8b0c1422..8d4a6bb2 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -43,6 +43,7 @@ static void print_explain(FILE *f)
" [ vlan_default_pvid VLAN_DEFAULT_PVID ]\n"
" [ vlan_stats_enabled VLAN_STATS_ENABLED ]\n"
" [ vlan_stats_per_port VLAN_STATS_PER_PORT ]\n"
+ " [ mcast_flood_always ENABLED ]\n"
" [ mcast_snooping MULTICAST_SNOOPING ]\n"
" [ mcast_vlan_snooping MULTICAST_VLAN_SNOOPING ]\n"
" [ mcast_router MULTICAST_ROUTER ]\n"
@@ -82,6 +83,18 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
}
+static void set_boolopt(struct br_boolopt_multi *bm, enum br_boolopt_id opt,
+ bool set)
+{
+ __u32 bit = 1 << opt;
+
+ bm->optmask |= 1 << opt;
+ if (set)
+ bm->optval |= bit;
+ else
+ bm->optval &= ~bit;
+}
+
static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
@@ -216,17 +229,21 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop);
} else if (strcmp(*argv, "mcast_vlan_snooping") == 0) {
- __u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
- __u8 mcast_vlan_snooping;
+ __u8 val;
NEXT_ARG();
- if (get_u8(&mcast_vlan_snooping, *argv, 0))
+ if (get_u8(&val, *argv, 0))
invarg("invalid mcast_vlan_snooping", *argv);
- bm.optmask |= 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
- if (mcast_vlan_snooping)
- bm.optval |= mcvl_bit;
- else
- bm.optval &= ~mcvl_bit;
+
+ set_boolopt(&bm, BR_BOOLOPT_MCAST_VLAN_SNOOPING, val);
+ } else if (strcmp(*argv, "mcast_flood_always") == 0) {
+ __u8 val;
+
+ NEXT_ARG();
+ if (get_u8(&val, *argv, 0))
+ invarg("invalid mcast_flood_always", *argv);
+
+ set_boolopt(&bm, BR_BOOLOPT_MCAST_FLOOD_ALWAYS, val);
} else if (matches(*argv, "mcast_query_use_ifaddr") == 0) {
__u8 mcast_qui;
@@ -590,21 +607,39 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
if (tb[IFLA_BR_MULTI_BOOLOPT]) {
- __u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
- __u32 no_ll_learn_bit = 1 << BR_BOOLOPT_NO_LL_LEARN;
struct br_boolopt_multi *bm;
+ int opt;
bm = RTA_DATA(tb[IFLA_BR_MULTI_BOOLOPT]);
- if (bm->optmask & no_ll_learn_bit)
- print_uint(PRINT_ANY,
- "no_linklocal_learn",
- "no_linklocal_learn %u ",
- !!(bm->optval & no_ll_learn_bit));
- if (bm->optmask & mcvl_bit)
- print_uint(PRINT_ANY,
- "mcast_vlan_snooping",
- "mcast_vlan_snooping %u ",
- !!(bm->optval & mcvl_bit));
+ for (opt = 0; opt < BR_BOOLOPT_MAX; opt++) {
+ __u32 bit = 1 << opt;
+ __u32 val = !!(bm->optval & bit);
+
+ if (!(bm->optmask & bit))
+ continue;
+
+ switch (opt) {
+ case BR_BOOLOPT_NO_LL_LEARN:
+ print_uint(PRINT_ANY,
+ "no_linklocal_learn",
+ "no_linklocal_learn %u ", val);
+ break;
+ case BR_BOOLOPT_MCAST_VLAN_SNOOPING:
+ print_uint(PRINT_ANY,
+ "mcast_vlan_snooping",
+ "mcast_vlan_snooping %u ", val);
+ break;
+ case BR_BOOLOPT_MST_ENABLE:
+ print_uint(PRINT_ANY,
+ "mst_enabled",
+ "mst_enabled %u ", val);
+ break;
+ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS:
+ print_uint(PRINT_ANY,
+ "mcast_flood_always",
+ "mcast_flood_always %u ", val);
+ }
+ }
}
if (tb[IFLA_BR_MCAST_ROUTER])
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 6c72e122..4730e73a 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -1590,6 +1590,8 @@ the following additional arguments are supported:
] [
.BI vlan_stats_per_port " VLAN_STATS_PER_PORT "
] [
+.BI mcast_flood_always " ENABLED "
+] [
.BI mcast_snooping " MULTICAST_SNOOPING "
] [
.BI mcast_vlan_snooping " MULTICAST_VLAN_SNOOPING "
@@ -1718,6 +1720,16 @@ or disable
.RI ( VLAN_STATS_PER_PORT " == 0) "
per-VLAN per-port stats accounting. Can be changed only when there are no port VLANs configured.
+.BI mcast_flood_always " ENABLED "
+- always
+.RI ( ENABLED " > 0) "
+flood unknown multicast according to per-port
+.BI mcast_flood
+settings. By default
+.RI ( ENABLED " == 0). "
+the bridge only floods until it has learned of a querier, or takes on
+the role itself.
+
.BI mcast_snooping " MULTICAST_SNOOPING "
- turn multicast snooping on
.RI ( MULTICAST_SNOOPING " > 0) "
--
2.34.1
@@ -0,0 +1,101 @@
From 8557acdc7218cbaf2b9d70ecfa118c05f988ed77 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Thu, 15 Dec 2022 19:52:30 +0200
Subject: [PATCH] bridge: mdb: Add replace support
Organization: Addiva Elektronik
Allow user space to replace MDB port group entries by specifying the
'NLM_F_REPLACE' flag in the netlink message header.
Examples:
# bridge mdb replace dev br0 port dummy10 grp 239.1.1.1 permanent source_list 192.0.2.1,192.0.2.2 filter_mode include
# bridge -d -s mdb show
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.2 permanent filter_mode include proto static 0.00
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.1 permanent filter_mode include proto static 0.00
dev br0 port dummy10 grp 239.1.1.1 permanent filter_mode include source_list 192.0.2.2/0.00,192.0.2.1/0.00 proto static 0.00
# bridge mdb replace dev br0 port dummy10 grp 239.1.1.1 permanent source_list 192.0.2.1,192.0.2.3 filter_mode exclude proto zebra
# bridge -d -s mdb show
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.3 permanent filter_mode include proto zebra blocked 0.00
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.1 permanent filter_mode include proto zebra blocked 0.00
dev br0 port dummy10 grp 239.1.1.1 permanent filter_mode exclude source_list 192.0.2.3/0.00,192.0.2.1/0.00 proto zebra 0.00
# bridge mdb replace dev br0 port dummy10 grp 239.1.1.1 temp source_list 192.0.2.4,192.0.2.3 filter_mode include proto bgp
# bridge -d -s mdb show
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.4 temp filter_mode include proto bgp 0.00
dev br0 port dummy10 grp 239.1.1.1 src 192.0.2.3 temp filter_mode include proto bgp 0.00
dev br0 port dummy10 grp 239.1.1.1 temp filter_mode include source_list 192.0.2.4/259.44,192.0.2.3/259.44 proto bgp 0.00
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
bridge/mdb.c | 4 +++-
man/man8/bridge.8 | 13 ++++++++++---
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/bridge/mdb.c b/bridge/mdb.c
index d3afc900..60cf0066 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -31,7 +31,7 @@ static unsigned int filter_index, filter_vlan;
static void usage(void)
{
fprintf(stderr,
- "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [src SOURCE] [permanent | temp] [vid VID]\n"
+ "Usage: bridge mdb { add | del | replace } dev DEV port PORT grp GROUP [src SOURCE] [permanent | temp] [vid VID]\n"
" bridge mdb {show} [ dev DEV ] [ vid VID ]\n");
exit(-1);
}
@@ -571,6 +571,8 @@ int do_mdb(int argc, char **argv)
if (argc > 0) {
if (matches(*argv, "add") == 0)
return mdb_modify(RTM_NEWMDB, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
+ if (strcmp(*argv, "replace") == 0)
+ return mdb_modify(RTM_NEWMDB, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1);
if (matches(*argv, "delete") == 0)
return mdb_modify(RTM_DELMDB, 0, argc-1, argv+1);
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index d4df772e..5bf15deb 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -126,7 +126,7 @@ bridge \- show / manipulate bridge addresses and devices
.BR [no]sticky " ] [ " [no]offloaded " ]"
.ti -8
-.BR "bridge mdb" " { " add " | " del " } "
+.BR "bridge mdb" " { " add " | " del " | " replace " } "
.B dev
.I DEV
.B port
@@ -873,8 +873,8 @@ if "no" is prepended then only entries without offloaded flag will be deleted.
objects contain known IP or L2 multicast group addresses on a link.
.P
-The corresponding commands display mdb entries, add new entries,
-and delete old ones.
+The corresponding commands display mdb entries, add new entries, replace
+entries and delete old ones.
.SS bridge mdb add - add a new multicast group database entry
@@ -919,6 +919,13 @@ This command removes an existing mdb entry.
The arguments are the same as with
.BR "bridge mdb add" .
+.SS bridge mdb replace - replace a multicast group database entry
+If no matching entry is found, a new one will be created instead.
+
+.PP
+The arguments are the same as with
+.BR "bridge mdb add" .
+
.SS bridge mdb show - list multicast group database entries
This command displays the current multicast group membership table. The table
--
2.34.1
@@ -1,8 +1,9 @@
From e1011848d2c9476e20e6a4053b8ab46ce2a1506f Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 5 Oct 2023 16:09:25 +0200
Subject: [PATCH 01/17] eth: fwnode: Fall back to NVMEM provided MAC address
Subject: [PATCH 01/20] eth: fwnode: Fall back to NVMEM provided MAC address
from OF
Organization: Addiva Elektronik
In the cases where the fwnode is an OF node, make use of any NVMEM
source of the interface's MAC address that might have been specified
@@ -1,8 +1,9 @@
From 1d6f30fce9f4516730439f72ee2134301d37654d Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 5 Sep 2023 13:08:29 +0200
Subject: [PATCH 02/17] net: dsa: mv88e6xxx: Create API to read a single stat
Subject: [PATCH 02/20] net: dsa: mv88e6xxx: Create API to read a single stat
counter
Organization: Addiva Elektronik
This change contains no functional change. We simply push the hardware
specific stats logic to a function reading a single counter, rather
@@ -1,7 +1,8 @@
From f960475a96d2852d06ee062c970e35074f87659c Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 5 Sep 2023 21:10:15 +0200
Subject: [PATCH 03/17] net: dsa: mv88e6xxx: Give each hw stat an ID
Subject: [PATCH 03/20] net: dsa: mv88e6xxx: Give each hw stat an ID
Organization: Addiva Elektronik
With the upcoming standard counter group support, we are no longer
reading out the whole set of counters, but rather mapping a subset to
@@ -1,8 +1,9 @@
From 6a612f46152d8567a16b7b15fdcc3081cbdbb3fb Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 5 Sep 2023 21:15:52 +0200
Subject: [PATCH 04/17] net: dsa: mv88e6xxx: Add "eth-mac" counter group
Subject: [PATCH 04/20] net: dsa: mv88e6xxx: Add "eth-mac" counter group
support
Organization: Addiva Elektronik
After this change, mv88e6xxx ports can report the applicable subset of
their counters using ethtool's standardized "eth-mac" counter group.
@@ -1,7 +1,8 @@
From a85c55f3232d402780a22d42859bdc81150469b4 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 6 Sep 2023 10:55:53 +0200
Subject: [PATCH 05/17] net: dsa: mv88e6xxx: Add "rmon" counter group support
Subject: [PATCH 05/20] net: dsa: mv88e6xxx: Add "rmon" counter group support
Organization: Addiva Elektronik
After this change, mv88e6xxx ports can report the applicable subset of
their counters using ethtool's standardized "rmon" counter group.
@@ -1,8 +1,9 @@
From 6f684b1b9eb8a307b77aa4baa8531e2c423112af Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 21 Sep 2023 11:10:26 +0200
Subject: [PATCH 06/17] arm64: dts: marvell: cp11x: Provide clock names for
Subject: [PATCH 06/20] arm64: dts: marvell: cp11x: Provide clock names for
MDIO controllers
Organization: Addiva Elektronik
This will let the driver figure out the rate of the core clk, such
that custom MDC frequencies can be supported.
@@ -1,7 +1,8 @@
From d5e03e7b44c8ac414927751097d8d65caffc33b4 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 19 Sep 2023 18:19:40 +0200
Subject: [PATCH 07/17] net: mvmdio: Avoid excessive sleeps in polled mode
Subject: [PATCH 07/20] net: mvmdio: Avoid excessive sleeps in polled mode
Organization: Addiva Elektronik
Before this change, when operating in polled mode, i.e. no IRQ is
available, every individual C45 access would be hit with a 150us sleep
@@ -1,8 +1,9 @@
From d389cc01295ebd7be228c8240f0061134b27f215 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 21 Sep 2023 11:12:55 +0200
Subject: [PATCH 08/17] net: mvmdio: Support setting the MDC frequency on XSMI
Subject: [PATCH 08/20] net: mvmdio: Support setting the MDC frequency on XSMI
controllers
Organization: Addiva Elektronik
Support the standard "clock-frequency" attribute to set the generated
MDC frequency. If not specified, the driver will leave the divisor
@@ -1,8 +1,9 @@
From 46bbea6b9d692ac7460e4e278cedee9f88b6da0b Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 19 Sep 2023 18:38:10 +0200
Subject: [PATCH 09/17] net: phy: marvell10g: Support firmware loading on
Subject: [PATCH 09/20] net: phy: marvell10g: Support firmware loading on
88X3310
Organization: Addiva Elektronik
If a device is found waiting for firmware to be loaded into its RAM,
ask userspace for the binary and load it over XMDIO.
@@ -1,7 +1,8 @@
From 312d3efde0fbe7cec3bf7ba1908c213c9cf69337 Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Tue, 8 Aug 2023 23:04:33 +0200
Subject: [PATCH 10/17] led: trig: netdev: Fix requesting offload device
Subject: [PATCH 10/20] led: trig: netdev: Fix requesting offload device
Organization: Addiva Elektronik
When the netdev trigger is activates, it tries to determine what
device the LED blinks for, and what the current blink mode is.
@@ -1,8 +1,9 @@
From 83322015e7960ba0f1f3698e36333cfb6aecb931 Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Tue, 8 Aug 2023 23:04:36 +0200
Subject: [PATCH 11/17] leds: trig-netdev: Disable offload on deactivation of
Subject: [PATCH 11/20] leds: trig-netdev: Disable offload on deactivation of
trigger
Organization: Addiva Elektronik
Ensure that the offloading of blinking is stopped when the trigger is
deactivated. Calling led_set_brightness() is documented as stopping
@@ -1,8 +1,9 @@
From a4f09c743da21f09b0fcc6e5842d665490f9f70e Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Tue, 8 Aug 2023 23:04:34 +0200
Subject: [PATCH 12/17] net: phy: phy_device: Call into the PHY driver to set
Subject: [PATCH 12/20] net: phy: phy_device: Call into the PHY driver to set
LED offload
Organization: Addiva Elektronik
Linux LEDs can be requested to perform hardware accelerated blinking
to indicate link, RX, TX etc. Pass the rules for blinking to the PHY
@@ -1,7 +1,8 @@
From 5adf394404d4c8ac25fb1e36d7d3f23b699b3104 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 15 Nov 2023 20:58:42 +0100
Subject: [PATCH 13/17] net: phy: marvell10g: Add LED support for 88X3310
Subject: [PATCH 13/20] net: phy: marvell10g: Add LED support for 88X3310
Organization: Addiva Elektronik
Pickup the LEDs from the state in which the hardware reset or
bootloader left them, but also support further configuration via
@@ -1,7 +1,8 @@
From 913a57a304e8024f4cea872fa904cee867c469a2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 19:44:32 +0100
Subject: [PATCH 14/17] net: dsa: mv88e6xxx: Add LED infrastructure
Subject: [PATCH 14/20] 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.
@@ -1,7 +1,8 @@
From 8510028fa738493a46b235057ed166f9bbbf0ed4 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 21:59:35 +0100
Subject: [PATCH 15/17] net: dsa: mv88e6xxx: Add LED support for 6393X
Subject: [PATCH 15/20] net: dsa: mv88e6xxx: Add LED support for 6393X
Organization: Addiva Elektronik
Trigger support:
- "none"
@@ -1,8 +1,9 @@
From b70f0aa3eb77567a057c2f42f5012a3e009a95c8 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 21 Nov 2023 20:15:24 +0100
Subject: [PATCH 16/17] net: phy: marvell10g: Fix power-up when strapped to
Subject: [PATCH 16/20] net: phy: marvell10g: Fix power-up when strapped to
start powered down
Organization: Addiva Elektronik
On devices which are hardware strapped to start powered down (PDSTATE
== 1), make sure that we clear the power-down bit on all units
@@ -1,8 +1,9 @@
From dd693e037f0dd799e77af397b4d23190b66e9cf1 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/17] nvmem: layouts: onie-tlv: Let device probe even when
Subject: [PATCH 17/20] nvmem: layouts: onie-tlv: Let device probe even when
TLV is invalid
Organization: Addiva Elektronik
Before this change, probing an NVMEM device, expected to contain a
valid TLV, would fail if it had not been provisioned yet. But an
@@ -0,0 +1,237 @@
From 7072b44955fc0bdc4b3e96648f2ff9c3e9d68c8e 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/20] net: bridge: avoid classifying unknown multicast as
mrouters_only
Organization: Addiva Elektronik
Unknown multicast, MAC/IPv4/IPv6, should always be flooded according to
the per-port mcast_flood setting, as well as to detected and configured
mcast_router ports.
This patch drops the mrouters_only classifier of unknown IP multicast
and moves the flow handling from br_multicast_flood() to br_flood().
This in turn means br_flood() must know about multicast router ports.
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 +++++
net/bridge/br_device.c | 10 ++++++----
net/bridge/br_forward.c | 14 ++++++++++++--
net/bridge/br_input.c | 2 +-
net/bridge/br_multicast.c | 11 +++++++++--
net/bridge/br_private.h | 18 ++++++++++++++++--
7 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index f95326fce6bb..2b1320025ec2 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -811,6 +811,7 @@ enum br_boolopt_id {
BR_BOOLOPT_NO_LL_LEARN,
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
BR_BOOLOPT_MST_ENABLE,
+ BR_BOOLOPT_MCAST_FLOOD_ALWAYS,
BR_BOOLOPT_MAX
};
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 4f5098d33a46..a512c8ad9860 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -269,6 +269,9 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on,
case BR_BOOLOPT_MST_ENABLE:
err = br_mst_set_enabled(br, on, extack);
break;
+ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS:
+ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, on);
+ break;
default:
/* shouldn't be called with unsupported options */
WARN_ON(1);
@@ -287,6 +290,8 @@ int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED);
case BR_BOOLOPT_MST_ENABLE:
return br_opt_get(br, BROPT_MST_ENABLED);
+ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS:
+ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS);
default:
/* shouldn't be called with unsupported options */
WARN_ON(1);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 9a5ea06236bd..5f537dbd597a 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -81,10 +81,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
dest = eth_hdr(skb)->h_dest;
if (is_broadcast_ether_addr(dest)) {
- br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid);
+ br_flood(br, skb, NULL, BR_PKT_BROADCAST, false, true, vid);
} else if (is_multicast_ether_addr(dest)) {
if (unlikely(netpoll_tx_running(dev))) {
- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
+ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid);
goto out;
}
if (br_multicast_rcv(&brmctx, &pmctx_null, vlan, skb, vid)) {
@@ -97,11 +97,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst))
br_multicast_flood(mdst, skb, brmctx, false, true);
else
- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
+ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid);
} else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
br_forward(dst->dst, skb, false, true);
} else {
- br_flood(br, skb, BR_PKT_UNICAST, false, true, vid);
+ br_flood(br, skb, NULL, BR_PKT_UNICAST, false, true, vid);
}
out:
rcu_read_unlock();
@@ -531,6 +531,8 @@ void br_dev_setup(struct net_device *dev)
br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;
dev->max_mtu = ETH_MAX_MTU;
+ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, false);
+
br_netfilter_rtable_init(br);
br_stp_timer_init(br);
br_multicast_init(br);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index bb1ab53e54e0..c5ac65628a7a 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -197,14 +197,19 @@ static struct net_bridge_port *maybe_deliver(
/* called under rcu_read_lock */
void br_flood(struct net_bridge *br, struct sk_buff *skb,
- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
- u16 vid)
+ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type,
+ bool local_rcv, bool local_orig, u16 vid)
{
+ struct net_bridge_port *rport = NULL;
struct net_bridge_port *prev = NULL;
+ struct hlist_node *rp = NULL;
struct net_bridge_port *p;
br_tc_skb_miss_set(skb, pkt_type != BR_PKT_BROADCAST);
+ if (pkt_type == BR_PKT_MULTICAST)
+ rp = br_multicast_get_first_rport_node(brmctx, skb);
+
list_for_each_entry_rcu(p, &br->port_list, list) {
/* Do not flood unicast traffic to ports that turn it off, nor
* other traffic if flood off, except for traffic we originate
@@ -215,6 +220,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
continue;
break;
case BR_PKT_MULTICAST:
+ rport = br_multicast_rport_from_node_skb(rp, skb);
+ if (rport == p) {
+ rp = rcu_dereference(hlist_next_rcu(rp));
+ break;
+ }
if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev)
continue;
break;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index c729528b5e85..2817d0c785be 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -207,7 +207,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
br_forward(dst->dst, skb, local_rcv, false);
} else {
if (!mcast_hit)
- br_flood(br, skb, pkt_type, local_rcv, false, vid);
+ br_flood(br, skb, brmctx, pkt_type, local_rcv, false, vid);
else
br_multicast_flood(mdst, skb, brmctx, local_rcv, false);
}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 96d1fc78dd39..ab3ee0651ebe 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -3771,6 +3771,11 @@ static void br_multicast_err_count(const struct net_bridge *br,
u64_stats_update_end(&pstats->syncp);
}
+static bool br_flood_mrouters(const struct net_bridge *br)
+{
+ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS) ? false : true;
+}
+
static void br_multicast_pim(struct net_bridge_mcast *brmctx,
struct net_bridge_mcast_port *pmctx,
const struct sk_buff *skb)
@@ -3817,7 +3822,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge_mcast *brmctx,
if (err == -ENOMSG) {
if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) {
- BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
+ BR_INPUT_SKB_CB(skb)->mrouters_only =
+ br_flood_mrouters(brmctx->br);
} else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) {
if (ip_hdr(skb)->protocol == IPPROTO_PIM)
br_multicast_pim(brmctx, pmctx, skb);
@@ -3886,7 +3892,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge_mcast *brmctx,
if (err == -ENOMSG || err == -ENODATA) {
if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr))
- BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
+ BR_INPUT_SKB_CB(skb)->mrouters_only =
+ br_flood_mrouters(brmctx->br);
if (err == -ENODATA &&
ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr))
br_ip6_multicast_mrd_rcv(brmctx, pmctx, skb);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a63b32c1638e..4798588f15c7 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -479,6 +479,7 @@ enum net_bridge_opts {
BROPT_VLAN_BRIDGE_BINDING,
BROPT_MCAST_VLAN_SNOOPING_ENABLED,
BROPT_MST_ENABLED,
+ BROPT_MCAST_FLOOD_ALWAYS,
};
struct net_bridge {
@@ -877,8 +878,8 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb,
bool local_rcv, bool local_orig);
int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
void br_flood(struct net_bridge *br, struct sk_buff *skb,
- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
- u16 vid);
+ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type,
+ bool local_rcv, bool local_orig, u16 vid);
/* return true if both source port and dest port are isolated */
static inline bool br_skb_isolated(const struct net_bridge_port *to,
@@ -1394,6 +1395,19 @@ static inline void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
{
}
+static inline struct hlist_node *
+br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx,
+ struct sk_buff *skb)
+{
+ return NULL;
+}
+
+static inline struct net_bridge_port *
+br_multicast_rport_from_node_skb(struct hlist_node *rp, struct sk_buff *skb)
+{
+ return NULL;
+}
+
static inline bool br_multicast_is_router(struct net_bridge_mcast *brmctx,
struct sk_buff *skb)
{
--
2.34.1
@@ -0,0 +1,37 @@
From 3c48022ab2eda9ab62b680a97c88934a62137ebf 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/20] net: bridge: Ignore router ports when forwarding L2
multicast
Organization: Addiva Elektronik
Multicast router ports are either statically configured or learned from
control protocol traffic (IGMP/MLD/PIM). These protocols regulate IP
multicast -- MAC multicast should always be forwarded through flooding
of unknown multicast or using permanent MDB entries.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
net/bridge/br_private.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 4798588f15c7..cac15339ecae 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1073,7 +1073,10 @@ br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx,
if (skb->protocol == htons(ETH_P_IPV6))
return rcu_dereference(hlist_first_rcu(&brmctx->ip6_mc_router_list));
#endif
- return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list));
+ if (skb->protocol == htons(ETH_P_IP))
+ return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list));
+
+ return NULL;
}
static inline struct net_bridge_port *
--
2.34.1
@@ -0,0 +1,32 @@
From f65e3c7e250d2a3775041bf894e5b8d051b5da98 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 12 Mar 2024 10:27:24 +0100
Subject: [PATCH 20/20] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
6393X
Organization: Addiva Elektronik
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: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 7d6b2b85fc31..109456d74691 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -87,7 +87,7 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 mask, u16 val)
{
- const unsigned long timeout = jiffies + msecs_to_jiffies(50);
+ const unsigned long timeout = jiffies + msecs_to_jiffies(1000);
u16 data;
int err;
int i;
--
2.34.1
@@ -0,0 +1,51 @@
From e4213fc62d3d6a6733e3026b63dd6314a6f09ee2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Moj=C3=ADk?= <marek.mojik@nic.cz>
Date: Wed, 6 Dec 2023 15:35:56 +0100
Subject: [PATCH 1/6] net: mv88e6xxx: fix missing SMI address initialization
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Addiva Elektronik
The mv88e6xxx driver does not currently initialize the smi_addr field, but
instead keeps the default zero value. This leads to driver being unusable
on devices where the switch is not on address zero of the mdio bus. Fix
this problem by reading the SMI address from device tree.
Signed-off-by: Marek Mojík <marek.mojik@nic.cz>
Reviewed-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/net/mv88e6xxx.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
index 64e860e324..9be8e3273c 100644
--- a/drivers/net/mv88e6xxx.c
+++ b/drivers/net/mv88e6xxx.c
@@ -679,6 +679,7 @@ static int mv88e6xxx_probe(struct udevice *dev)
{
struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ fdt_addr_t smi_addr;
int val, ret;
if (ofnode_valid(dev_ofnode(dev)) &&
@@ -687,6 +688,13 @@ static int mv88e6xxx_probe(struct udevice *dev)
return -ENODEV;
}
+ smi_addr = dev_read_addr(dev);
+ if (smi_addr == FDT_ADDR_T_NONE) {
+ dev_err(dev, "Missing SMI address\n");
+ return -EINVAL;
+ }
+ priv->smi_addr = smi_addr;
+
/* probe internal mdio bus */
ret = mv88e6xxx_probe_mdio(dev);
if (ret)
--
2.34.1
@@ -1,7 +1,8 @@
From 4348261902b60f93c217f07069a2b5613a933c17 Mon Sep 17 00:00:00 2001
From 80ddeb093f24cf1d8a99e92564e07a7180791f8c Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 17 Oct 2023 13:15:58 +0200
Subject: [PATCH 1/5] net: mv88e6xxx: Add reset-gpios support
Subject: [PATCH 2/6] net: mv88e6xxx: Add reset-gpios support
Organization: Addiva Elektronik
If the switch's RESETn signal is under the CPUs control, release it
before starting the probe.
@@ -12,7 +13,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
1 file changed, 61 insertions(+), 7 deletions(-)
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
index 64e860e324..1bf7cfd6a6 100644
index 9be8e3273c..e70e45ae92 100644
--- a/drivers/net/mv88e6xxx.c
+++ b/drivers/net/mv88e6xxx.c
@@ -33,6 +33,8 @@
@@ -71,7 +72,7 @@ index 64e860e324..1bf7cfd6a6 100644
static int mv88e6xxx_probe(struct udevice *dev)
{
struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
@@ -684,17 +719,22 @@ static int mv88e6xxx_probe(struct udevice *dev)
@@ -685,7 +720,8 @@ static int mv88e6xxx_probe(struct udevice *dev)
if (ofnode_valid(dev_ofnode(dev)) &&
!ofnode_is_enabled(dev_ofnode(dev))) {
dev_dbg(dev, "switch disabled\n");
@@ -80,6 +81,11 @@ index 64e860e324..1bf7cfd6a6 100644
+ goto err;
}
smi_addr = dev_read_addr(dev);
@@ -695,14 +731,18 @@ static int mv88e6xxx_probe(struct udevice *dev)
}
priv->smi_addr = smi_addr;
+ ret = mv88e6xxx_probe_reset(dev);
+ if (ret)
+ goto err;
@@ -97,7 +103,7 @@ index 64e860e324..1bf7cfd6a6 100644
dev_dbg(dev, "ID=0x%x PORT_BASE=0x%02x GLOBAL1=0x%02x GLOBAL2=0x%02x\n",
priv->id, priv->port_reg_base, priv->global1, priv->global2);
@@ -716,28 +756,40 @@ static int mv88e6xxx_probe(struct udevice *dev)
@@ -724,28 +764,40 @@ static int mv88e6xxx_probe(struct udevice *dev)
priv->port_count = 7;
break;
default:
@@ -142,7 +148,7 @@ index 64e860e324..1bf7cfd6a6 100644
}
static const struct udevice_id mv88e6xxx_ids[] = {
@@ -750,6 +802,8 @@ U_BOOT_DRIVER(mv88e6xxx) = {
@@ -758,6 +810,8 @@ U_BOOT_DRIVER(mv88e6xxx) = {
.id = UCLASS_DSA,
.of_match = mv88e6xxx_ids,
.probe = mv88e6xxx_probe,
@@ -1,8 +1,9 @@
From d87aea2f0d0acfa0d54adb20a980256c0ba95023 Mon Sep 17 00:00:00 2001
From c31794d78337da82cf41ffbcb9e696e42759aa12 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 17 Oct 2023 13:20:19 +0200
Subject: [PATCH 2/5] net: mv88e6xxx: Support clause 45 addressing on internal
Subject: [PATCH 3/6] net: mv88e6xxx: Support clause 45 addressing on internal
MDIO bus
Organization: Addiva Elektronik
This is needed to access SERDES registers on newer chips, like the
6393X.
@@ -13,7 +14,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
1 file changed, 106 insertions(+), 7 deletions(-)
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
index 1bf7cfd6a6..eddac332e0 100644
index e70e45ae92..99f234ae87 100644
--- a/drivers/net/mv88e6xxx.c
+++ b/drivers/net/mv88e6xxx.c
@@ -114,6 +114,9 @@
@@ -1,7 +1,8 @@
From c801299f06f0e5c95bd597fe0ce4ad6c3df9a444 Mon Sep 17 00:00:00 2001
From c94723526672f1e5555b7545c13256edb7bd7557 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 17 Oct 2023 13:22:00 +0200
Subject: [PATCH 3/5] net: mv88e6xxx: Add support for 6393X
Subject: [PATCH 4/6] net: mv88e6xxx: Add support for 6393X
Organization: Addiva Elektronik
Only built-in copper PHYs are supported as access ports. Support
10GBASE-R SERDES connection to CPU.
@@ -12,7 +13,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
1 file changed, 130 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
index eddac332e0..4a4a3ae0b1 100644
index 99f234ae87..6f5cfe0155 100644
--- a/drivers/net/mv88e6xxx.c
+++ b/drivers/net/mv88e6xxx.c
@@ -74,6 +74,7 @@
@@ -170,7 +171,7 @@ index eddac332e0..4a4a3ae0b1 100644
*/
priv->port_reg_base = 0x10;
priv->id = mv88e6xxx_get_switch_id(dev);
+ if (priv->id == 0xfff0) {
+ if (priv->id == 0xfff0 || priv->id == PORT_SWITCH_ID_6393) {
+ /*
+ * Look for a newer device in which ports start at
+ * offset 0 (6390/6393 and compatible switches).
@@ -182,7 +183,7 @@ index eddac332e0..4a4a3ae0b1 100644
if (priv->id != 0xfff0) {
priv->global1 = 0x1B;
priv->global2 = 0x1C;
@@ -844,6 +967,7 @@ static int mv88e6xxx_probe(struct udevice *dev)
@@ -852,6 +975,7 @@ static int mv88e6xxx_probe(struct udevice *dev)
case PORT_SWITCH_ID_6176:
case PORT_SWITCH_ID_6240:
case PORT_SWITCH_ID_6352:
@@ -190,7 +191,7 @@ index eddac332e0..4a4a3ae0b1 100644
priv->port_count = 11;
break;
case PORT_SWITCH_ID_6020:
@@ -863,15 +987,17 @@ static int mv88e6xxx_probe(struct udevice *dev)
@@ -871,15 +995,17 @@ static int mv88e6xxx_probe(struct udevice *dev)
if (ret < 0)
goto err_remove_reset;
@@ -1,7 +1,8 @@
From 5013dadfd3ba92eba930f8ea0f88c0f34b8c55a5 Mon Sep 17 00:00:00 2001
From c39245a2d92d6f851dfcb8f573af873a05d4a5b8 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Fri, 20 Oct 2023 13:19:41 +0200
Subject: [PATCH 4/5] i2c: pcf8575: Properly address chip
Subject: [PATCH 5/6] i2c: pcf8575: Properly address chip
Organization: Addiva Elektronik
These devices hold a simple shift register that is accessed without
any "register" setup.
@@ -1,7 +1,8 @@
From c0495a607652aef38a4d4480ebdb6dd45e3dd9b9 Mon Sep 17 00:00:00 2001
From 967f7f88c88e1a72d7cf389b5b3b6f184788006f Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 24 Oct 2023 22:23:44 +0200
Subject: [PATCH 5/5] arm64: mvebu: a8k: Add eFuse support
Subject: [PATCH 6/6] arm64: mvebu: a8k: Add eFuse support
Organization: Addiva Elektronik
Add support for reading and burning LD and HD fuses. Use a specialized
commandline implementation over the standard "fuse" command because:
+1 -1
View File
@@ -218,7 +218,7 @@ sysrepoctl -s $SEARCH \
-i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \
-i infix-ip@2023-09-14.yang -g wheel -p 0660 \
-i infix-if-type@2024-01-29.yang -g wheel -p 0660 \
-i infix-routing@2024-01-09.yang -g wheel -p 0660 \
-i infix-routing@2024-03-06.yang -g wheel -p 0660 \
-i infix-interfaces@2024-01-15.yang -g wheel -p 0660 \
-e vlan-filtering \
-i ieee802-dot1ab-lldp@2022-03-15.yang -g wheel -p 0660 \
+19 -17
View File
@@ -56,17 +56,26 @@ EOF
exit 0
}
iftype()
{
iftype=$(ip -d -j link show "$1" |jq -r .[].parentbus)
if [ "$iftype" = "virtio" ]; then
echo "infix-if-type:etherlike"
else
echo "infix-if-type:ethernet"
fi
}
# shellcheck disable=SC3043
gen_iface_json()
{
local iftype="$1"
local ifname="$2"
local br="$3"
local ifname="$1"
local br="$2"
cat <<EOF
,{
"name": "$ifname",
"type": "$iftype",
"type": "$(iftype "$ifname")",
EOF
if [ -n "$br" ]; then
@@ -131,20 +140,14 @@ while [ "$1" != "" ]; do
shift
done
# All exeternal interfaces
phys_ifaces=$(ip -d -j link show | jq -r '
.[] |
select(.link_type == "ether") |
select(.group != "internal") |
select(has("parentbus")) |
select(.parentbus != "virtio") |
.ifname' | sort -V)
virtio_ifaces=$(ip -d -j link show | jq -r '
.[] |
select(.link_type == "ether") |
select(.group != "internal") |
select(has("parentbus")) |
select(.parentbus == "virtio") |
.ifname' | sort -V)
# All interfaces classified as switch ports
ports=$(ip -d -j link show group port | jq -r '
.[] |
select(.link_type == "ether") |
@@ -152,8 +155,8 @@ ports=$(ip -d -j link show group port | jq -r '
select(has("parentbus")) |
.ifname' | sort -V)
eth_ifaces="$(filter_iface_ports "$phys_ifaces" "$ports")"
ethlike_ifaces="$(filter_iface_ports "$virtio_ifaces" "$ports")"
# Remaining external interfaces not classified as switch ports
ifaces="$(filter_iface_ports "$phys_ifaces" "$ports")"
cat <<EOF
{
@@ -188,9 +191,8 @@ fi
cat <<EOF
}
$(for iface in $eth_ifaces; do gen_iface_json "infix-if-type:ethernet" "$iface"; done)
$(for iface in $ethlike_ifaces; do gen_iface_json "infix-if-type:etherlike" "$iface"; done)
$(for iface in $ports; do gen_iface_json "infix-if-type:ethernet" "$iface" "$bridge"; done)
$(for iface in $ifaces; do gen_iface_json "$iface"; done)
$(for iface in $ports; do gen_iface_json "$iface" "$bridge"; done)
]
EOF
if [ "$dhcp" = "true" ] && [ -n "$bridge" ]; then
+2 -2
View File
@@ -361,10 +361,10 @@ static int iface_gen_cni(const char *ifname, struct lyd_node *cif)
}
if (!strcmp(type, "host"))
return cni_host(net, ifname);
return cni_host(net, ifname) ?: 1;
if (!strcmp(type, "bridge"))
return cni_bridge(net, ifname);
return cni_bridge(net, ifname) ?: 1;
ERROR("Unknown container network type %s, skipping.", type);
return 0;
+239 -29
View File
@@ -24,6 +24,8 @@
#define DEBUG_IFACE(_iface, _fmt, ...) \
DEBUG("%s: " _fmt, lydx_get_cattr(_iface, "name"), ##__VA_ARGS__)
#define ONOFF(boolean) boolean ? "on" : "off"
#define IF_XPATH "/ietf-interfaces:interfaces/interface"
@@ -149,36 +151,36 @@ static int ifchange_cand_infer_vlan(sr_session_ctx_t *session, const char *path)
goto out_free_ifname;
err = srx_nitems(session, &cnt,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/lower-layer-if", xpath);
if (!err && !cnt) {
inferred.data.string_val = ifname;
err = srx_set_item(session, &inferred, 0,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/lower-layer-if", xpath);
if (err)
goto out_free_ifname;
}
err = srx_nitems(session, &cnt,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/tag-type", xpath);
if (!err && !cnt) {
inferred.data.string_val = "ieee802-dot1q-types:c-vlan";
err = srx_set_item(session, &inferred, 0,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/tag-type", xpath);
if (err)
goto out_free_ifname;
}
err = srx_nitems(session, &cnt,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/id", xpath);
if (!err && !cnt) {
inferred.data.string_val = vidstr;
err = srx_set_item(session, &inferred, 0,
"%s/infix-if-vlan:vlan"
"%s/infix-interfaces:vlan"
"/id", xpath);
if (err)
goto out_free_ifname;
@@ -311,6 +313,16 @@ static int netdag_exit_reload(struct dagger *net)
return 0;
}
static bool is_bridge_port(struct lyd_node *cif)
{
struct lyd_node *node = lydx_get_descendant(lyd_child(cif), "bridge-port", NULL);
if (!node || !lydx_get_child(node, "bridge"))
return false;
return true;
}
static bool is_std_lo_addr(const char *ifname, const char *ip, const char *pf)
{
struct in6_addr in6, lo6;
@@ -488,7 +500,7 @@ static int netdag_gen_ipv6_autoconf(struct dagger *net, struct lyd_node *cif,
struct lyd_node *node;
FILE *fp;
if (!ipconf || !lydx_is_enabled(ipconf, "enabled")) {
if (!ipconf || !lydx_is_enabled(ipconf, "enabled") || is_bridge_port(cif)) {
fputs(" addrgenmode none", ip);
return 0;
}
@@ -531,7 +543,7 @@ static int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
FILE *initctl;
int err = 0;
if (!ipconf || !lydx_is_enabled(ipconf, "enabled"))
if (!ipconf || !lydx_is_enabled(ipconf, "enabled") || is_bridge_port(cif))
goto disable;
if (lydx_get_op(lydx_get_child(ipdiff, "enabled")) == LYDX_OP_REPLACE) {
@@ -785,7 +797,7 @@ static const char *bridge_tagtype2str(const char *type)
return proto;
}
static int bridge_vlan_settings(struct lyd_node *cif, const char **proto)
static int bridge_vlan_settings(struct lyd_node *cif, const char **proto, int *vlan_mcast)
{
struct lyd_node *vlans, *vlan;
@@ -795,8 +807,15 @@ static int bridge_vlan_settings(struct lyd_node *cif, const char **proto)
int num = 0;
*proto = bridge_tagtype2str(type);
LYX_LIST_FOR_EACH(lyd_child(vlans), vlan, "vlan")
LYX_LIST_FOR_EACH(lyd_child(vlans), vlan, "vlan") {
struct lyd_node *mcast;
mcast = lydx_get_descendant(lyd_child(vlan), "multicast", NULL);
if (mcast)
*vlan_mcast += lydx_is_enabled(mcast, "snooping");
num++;
}
return num;
}
@@ -804,6 +823,58 @@ static int bridge_vlan_settings(struct lyd_node *cif, const char **proto)
return 0;
}
static void bridge_port_settings(FILE *next, const char *ifname, struct lyd_node *cif)
{
struct lyd_node *bp, *flood, *mcast;
int ucflood = 1; /* default: flood unknown unicast */
bp = lydx_get_descendant(lyd_child(cif), "bridge-port", NULL);
if (!bp)
return;
fprintf(next, "link set %s type bridge_slave", ifname);
flood = lydx_get_child(bp, "flood");
if (flood) {
ucflood = lydx_is_enabled(flood, "unicast");
fprintf(next, " bcast_flood %s", ONOFF(lydx_is_enabled(flood, "broadcast")));
fprintf(next, " flood %s", ONOFF(ucflood));
fprintf(next, " mcast_flood %s", ONOFF(lydx_is_enabled(flood, "multicast")));
}
if (ucflood) {
/* proxy arp must be disabled while flood on, see man page */
fprintf(next, " proxy_arp off");
fprintf(next, " proxy_arp_wifi off");
} else {
/* XXX: proxy arp/wifi settings here */
}
mcast = lydx_get_child(bp, "multicast");
if (mcast) {
const char *router = lydx_get_cattr(mcast, "router");
struct { const char *str; int val; } xlate[] = {
{ "off", 0 },
{ "auto", 1 },
{ "permanent", 2 },
};
int mrouter = 1;
for (size_t i = 0; i < NELEMS(xlate); i++) {
if (strcmp(xlate[i].str, router))
continue;
mrouter = xlate[i].val;
break;
}
fprintf(next, " mcast_fast_leave %s mcast_router %d",
ONOFF(lydx_is_enabled(mcast, "fast-leave")),
mrouter);
}
fprintf(next, "\n");
}
static int bridge_gen_ports(struct dagger *net, struct lyd_node *dif, struct lyd_node *cif, FILE *ip)
{
struct lyd_node *node, *bridge;
@@ -811,10 +882,13 @@ static int bridge_gen_ports(struct dagger *net, struct lyd_node *dif, struct lyd
const char *ifname;
int err = 0;
if (!is_bridge_port(cif))
return 0;
node = lydx_get_descendant(lyd_child(dif), "bridge-port", NULL);
bridge = lydx_get_child(node, "bridge");
if (!node || !bridge)
return 0; /* not a bridge port, skip */
return 0; /* bridge port but no diff, skip */
ifname = lydx_get_cattr(cif, "name");
@@ -839,6 +913,7 @@ static int bridge_gen_ports(struct dagger *net, struct lyd_node *dif, struct lyd
goto fail;
}
fprintf(next, "link set %s master %s\n", ifname, brdiff.new);
bridge_port_settings(next, ifname, cif);
fclose(next);
err = dagger_add_dep(net, brdiff.new, ifname);
@@ -879,20 +954,145 @@ fail:
return fwd_mask;
}
static int netdag_gen_bridge(struct dagger *net, struct lyd_node *dif,
static int querier_mode(const char *mode)
{
struct { const char *mode; int val; } table[] = {
{ "off", 0 },
{ "proxy", 1 },
{ "auto", 2 },
};
for (size_t i = 0; i < NELEMS(table); i++) {
if (strcmp(table[i].mode, mode))
continue;
return table[i].val;
}
return 0; /* unknown: off */
}
static void mcast_querier(const char *ifname, int mode, int interval)
{
FILE *fp;
DEBUG("mcast querier %s mode %d interval %d", ifname, mode, interval);
if (!mode) {
erasef("/etc/mcd/%s.conf", ifname);
systemf("initctl -bnq disable mcd@%s", ifname);
return;
}
fp = fopenf("w", "/etc/mcd/%s.conf", ifname);
if (!fp) {
ERRNO("Failed creating querier configuration for %s", ifname);
return;
}
fprintf(fp, "query-interval %d\n", interval);
fprintf(fp, "iface %s enable %sigmpv3\n", ifname, mode == 1 ? "proxy-queries " : "");
fclose(fp);
systemf("initctl -bnq enable mcd@%s", ifname);
}
static char *find_vlan_interface(sr_session_ctx_t *session, const char *brname, int vid)
{
const char *fmt = "/interfaces/interface/vlan[id=%d and lower-layer-if='%s']";
static char xpath[128];
struct lyd_node *iface;
sr_data_t *data;
int rc;
snprintf(xpath, sizeof(xpath), fmt, vid, brname);
rc = sr_get_data(session, xpath, 0, 0, 0, &data);
if (rc || !data) {
DEBUG("Skpping VLAN %d interface for %s", vid, brname);
return NULL;
}
/* On match we should not need the if(iface) checks */
iface = lydx_get_descendant(data->tree, "interfaces", "interface", NULL);
if (iface)
strlcpy(xpath, lydx_get_cattr(iface, "name"), sizeof(xpath));
sr_release_data(data);
if (iface)
return xpath;
return NULL;
}
static int vlan_mcast_settings(sr_session_ctx_t *session, FILE *br, const char *brname, struct lyd_node *vlan, int vid)
{
int interval, querier, snooping;
struct lyd_node *mcast;
const char *ifname;
mcast = lydx_get_descendant(lyd_child(vlan), "multicast", NULL);
if (!mcast)
return 0;
snooping = lydx_is_enabled(mcast, "snooping");
querier = querier_mode(lydx_get_cattr(mcast, "querier"));
fprintf(br, "vlan global set vid %d dev %s mcast_snooping %d",
vid, brname, snooping);
interval = atoi(lydx_get_cattr(mcast, "query-interval"));
ifname = find_vlan_interface(session, brname, vid);
if (ifname)
mcast_querier(ifname, querier, interval);
fprintf(br, " mcast_querier %d mcast_query_interval %d",
ifname ? 0 : querier, interval * 100);
/* XXX: make configurable later */
fprintf(br, " mcast_igmp_version 3 mcast_mld_version 2\n");
return 0;
}
static int bridge_mcast_settings(FILE *ip, const char *brname, struct lyd_node *cif, int vlan_filtering)
{
int interval, querier, snooping;
struct lyd_node *mcast;
mcast = lydx_get_descendant(lyd_child(cif), "bridge", "multicast", NULL);
if (!mcast) {
mcast_querier(brname, 0, 0);
return 0;
}
snooping = lydx_is_enabled(mcast, "snooping");
querier = querier_mode(lydx_get_cattr(mcast, "querier"));
fprintf(ip, " mcast_vlan_snooping %d", vlan_filtering ? snooping : 0);
fprintf(ip, " mcast_snooping %d mcast_querier 0", snooping);
interval = atoi(lydx_get_cattr(mcast, "query-interval"));
fprintf(ip, " mcast_query_interval %d", interval * 100);
DEBUG("%s: querier %d", brname, vlan_filtering ? -1 : querier);
if (!vlan_filtering)
mcast_querier(brname, querier, interval);
else
mcast_querier(brname, 0, 0);
return 0;
}
static int netdag_gen_bridge(sr_session_ctx_t *session, struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip, int add)
{
const char *brname = lydx_get_cattr(cif, "name");
int vlan_filtering, fwd_mask, vlan_mcast = 0;
const char *op = add ? "add" : "set";
struct lyd_node *vlans, *vlan;
int vlan_filtering, fwd_mask;
int mcast_snooping;
const char *proto;
FILE *br = NULL;
int err = 0;
vlan_filtering = bridge_vlan_settings(cif, &proto);
mcast_snooping = 0; /* Not supported yet */
vlan_filtering = bridge_vlan_settings(cif, &proto, &vlan_mcast);
fwd_mask = bridge_fwd_mask(cif);
/*
@@ -901,9 +1101,13 @@ static int netdag_gen_bridge(struct dagger *net, struct lyd_node *dif,
* believe this is the only sane way of doing it.
* Issue #310: malplaced 'vlan_default_pvid 0'
*/
fprintf(ip, "link %s dev %s type bridge group_fwd_mask %d vlan_filtering %d"
" vlan_default_pvid 0 mcast_snooping %d",
op, brname, fwd_mask, vlan_filtering ? 1 : 0, mcast_snooping ? 1 : 0);
fprintf(ip, "link %s dev %s type bridge group_fwd_mask %d mcast_flood_always 1"
" vlan_filtering %d vlan_default_pvid 0",
op, brname, fwd_mask, vlan_filtering ? 1 : 0);
if ((err = bridge_mcast_settings(ip, brname, cif, vlan_mcast)))
goto done;
if (!vlan_filtering) {
fputc('\n', ip);
goto done;
@@ -938,6 +1142,11 @@ static int netdag_gen_bridge(struct dagger *net, struct lyd_node *dif,
err = bridge_diff_vlan_ports(net, br, brname, vid, vlan, 1);
if (err)
break;
/* need the vlans created before we can set features on them */
err = vlan_mcast_settings(session, br, brname, vlan, vid);
if (err)
break;
}
fclose(br);
@@ -1019,7 +1228,7 @@ static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
return 0;
}
static int netdag_gen_afspec_add(struct dagger *net, struct lyd_node *dif,
static int netdag_gen_afspec_add(sr_session_ctx_t *session, struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip)
{
const char *ifname = lydx_get_cattr(cif, "name");
@@ -1029,7 +1238,7 @@ static int netdag_gen_afspec_add(struct dagger *net, struct lyd_node *dif,
DEBUG_IFACE(dif, "");
if (!strcmp(iftype, "infix-if-type:bridge")) {
err = netdag_gen_bridge(net, dif, cif, ip, 1);
err = netdag_gen_bridge(session, net, dif, cif, ip, 1);
} else if (!strcmp(iftype, "infix-if-type:veth")) {
err = netdag_gen_veth(net, NULL, cif, ip);
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
@@ -1039,7 +1248,7 @@ static int netdag_gen_afspec_add(struct dagger *net, struct lyd_node *dif,
" wrong type or name.", ifname);
return -ENOENT;
} else {
sr_session_set_error_message(net->session, "Unsupported interface type \"%s\"", iftype);
sr_session_set_error_message(net->session, "%s: unsupported interface type \"%s\"", ifname, iftype);
return -ENOSYS;
}
@@ -1049,7 +1258,7 @@ static int netdag_gen_afspec_add(struct dagger *net, struct lyd_node *dif,
return 0;
}
static int netdag_gen_afspec_set(struct dagger *net, struct lyd_node *dif,
static int netdag_gen_afspec_set(sr_session_ctx_t *session, struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip)
{
const char *ifname = lydx_get_cattr(cif, "name");
@@ -1058,13 +1267,13 @@ static int netdag_gen_afspec_set(struct dagger *net, struct lyd_node *dif,
DEBUG_IFACE(dif, "");
if (!strcmp(iftype, "infix-if-type:bridge"))
return netdag_gen_bridge(net, dif, cif, ip, 0);
return netdag_gen_bridge(session, net, dif, cif, ip, 0);
if (!strcmp(iftype, "infix-if-type:vlan"))
return netdag_gen_vlan(net, dif, cif, ip);
if (!strcmp(iftype, "infix-if-type:veth"))
return 0;
ERROR("unsupported interface type \"%s\" for %s", iftype, ifname);
ERROR("%s: unsupported interface type \"%s\"", ifname, iftype);
return -ENOSYS;
}
@@ -1115,6 +1324,7 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
DEBUG_IFACE(dif, "");
mcast_querier(ifname, 0, 0);
if (dagger_should_skip_current(net, ifname))
return 0;
@@ -1133,7 +1343,7 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
return 0;
}
static sr_error_t netdag_gen_iface(struct dagger *net,
static sr_error_t netdag_gen_iface(sr_session_ctx_t *session, struct dagger *net,
struct lyd_node *dif, struct lyd_node *cif)
{
const char *ifname = lydx_get_cattr(dif, "name");
@@ -1190,7 +1400,7 @@ static sr_error_t netdag_gen_iface(struct dagger *net,
}
if (!fixed && op == LYDX_OP_CREATE) {
err = netdag_gen_afspec_add(net, dif, cif, ip);
err = netdag_gen_afspec_add(session, net, dif, cif, ip);
if (err)
goto err_close_ip;
}
@@ -1211,7 +1421,7 @@ static sr_error_t netdag_gen_iface(struct dagger *net,
/* Set type specific attributes */
if (!fixed && op != LYDX_OP_CREATE) {
err = netdag_gen_afspec_set(net, dif, cif, ip);
err = netdag_gen_afspec_set(session, net, dif, cif, ip);
if (err)
goto err_close_ip;
}
@@ -1303,7 +1513,7 @@ static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *modu
lydx_get_cattr(cif, "name")))
break;
err = netdag_gen_iface(&confd->netdag, dif, cif);
err = netdag_gen_iface(session, &confd->netdag, dif, cif);
if (err)
break;
}
+2 -1
View File
@@ -127,7 +127,8 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf)
parse_ospf_redistribute(session, lydx_get_child(ospf, "redistribute"), fp);
default_route = lydx_get_child(ospf, "default-route-advertise");
if (default_route) {
if (lydx_get_bool(default_route, "enable")) {
/* enable is obsolete in favor for enabled. */
if ((lydx_get_child(default_route, "enable") && lydx_get_bool(default_route, "enable")) || lydx_get_bool(default_route, "enabled")) {
fputs(" default-information originate", fp);
if (lydx_get_bool(default_route, "always"))
fputs(" always", fp);
+6 -1
View File
@@ -1071,8 +1071,13 @@ static int change_motd_banner(sr_session_ctx_t *session, uint32_t sub_id, const
if (!fp) {
rc = -1;
} else {
if (fwrite(txt, txt_len, sizeof(txt[0]), fp) != txt_len)
size_t len = fwrite(txt, sizeof(txt[0]), txt_len, fp);
if (len != txt_len) {
ERROR("failed writing %s, wrote %zu bytes of total %zu",
fn, len, txt_len);
rc = -1;
}
fclose(fp);
}
@@ -177,7 +177,7 @@ module infix-containers {
leaf-list option {
when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'";
description "Options for a masquerading container bridges.
description "Options for masquerading container bridges.
Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6)
mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
@@ -1,214 +0,0 @@
submodule infix-if-bridge {
yang-version 1.1;
belongs-to infix-interfaces {
prefix infix-if;
}
import iana-if-type {
prefix ianaift;
}
import ietf-interfaces {
prefix if;
}
import ieee802-dot1q-types {
prefix dot1q-types;
}
organization "KernelKit";
contact "kernelkit@googlegroups.com";
description "Linux bridge extension for ietf-interfaces.";
revision 2024-02-19 {
description "Add STP state to bridge port.";
reference "internal";
}
revision 2023-12-02 {
description "Extend bridge-port must expression to ensure a
bridge cannot be a bridge-port to itself.";
reference "internal";
}
revision 2023-11-08 {
description "Dropped support for configuring bridge pvid.
Bridge ports need explicit VLAN assignment.";
reference "internal";
}
revision 2023-08-21 {
description "Minor, lint ordering and add missing description.";
reference "internal";
}
revision 2023-05-31 {
description "Initial revision.";
reference "internal";
}
/*
* Features
*/
feature vlan-filtering {
description "Indicates if this bridge supports VLAN filtering.";
}
/*
* Typedefs
*/
typedef ieee-reserved-groups {
type union {
type uint8 {
range "0..15";
}
type enumeration {
enum stp {
value 0;
description "Spanning Tree (STP/RSPT/MSTP).";
}
enum lacp {
value 2;
description "802.3 Slow Protocols, e.g., LACP.";
}
enum dot1x {
value 3;
description "802.1X Port-Based Network Access Control.";
}
enum lldp {
value 14;
description "802.1AB Link Layer Discovery Protocol (LLDP).";
}
}
}
description
"This is a user-friendly enumeration of the different reserved IEEE
reserved link-local multicast groups, in 01:80:C2:00:00:0X.";
}
typedef stp-state {
type enumeration {
enum disabled {
value 0;
description "Port is in STP DISABLED state";
}
enum listening {
value 1;
description "Port is in STP LISTENING state";
}
enum learning {
value 2;
description "Port is in STP LEARNING state";
}
enum forwarding {
value 3;
description "Port is in STP FORWARDING state. This is the default vlan state.";
}
enum blocking {
value 4;
description "Port is in STP BLOCKING state.";
}
}
description
"User-friendly enumeration of different bridge port operational states.";
}
/*
* Data Nodes
*/
augment "/if:interfaces/if:interface" {
when "derived-from-or-self(if:type,'ianaift:bridge')" {
description "Only shown for if:type bridge";
}
description "Augment generic interfaces with a basic 802.1Q bridge.";
container bridge {
description "IEEE 802.1Q style bridge.";
leaf-list ieee-group-forward {
type ieee-reserved-groups;
description
"List of IEEE link-local protocols to forward, e.g., STP, LLDP";
}
container vlans {
if-feature "vlan-filtering";
description "A VLAN filtering bridge has at least one VLAN.";
leaf proto {
type dot1q-types:dot1q-tag-type;
default dot1q-types:c-vlan;
description "Standard (1Q/c-vlan) or provider (1ad/s-vlan) bridge.";
}
list vlan {
key "vid";
description "List of VLANs associated with the Bridge.";
leaf vid {
type dot1q-types:vlanid;
description "The VLAN identifier to which this entry applies.";
}
leaf-list untagged {
type if:interface-ref;
description "The set of ports in the untagged set for VLAN.";
}
leaf-list tagged {
type if:interface-ref;
must "not(../untagged[contains(., current())])" {
error-message "Cannot be an untagged port at the same time.";
}
description "The set of ports in the tagged set for VLAN.";
}
}
}
}
}
augment "/if:interfaces/if:interface/infix-if:port" {
when "derived-from-or-self(if:type,'ianaift:bridge') or "+
"derived-from-or-self(if:type,'ianaift:ethernetCsmacd') or "+
"derived-from-or-self(if:type,'ianaift:ieee8023adLag') or "+
"derived-from-or-self(if:type,'ianaift:ilan')" {
description "Applies when a Bridge interface exists.";
}
description "Augments the interface model with the Bridge Port";
case bridge-port {
description "Extension of the IETF Interfaces model (RFC7223).";
container bridge-port {
description "Bridge association and port specific setttngs.";
leaf bridge {
type if:interface-ref;
must "deref(.)/../bridge and not(. = ../../if:name)" {
error-message "Must refer to a bridge interface (and not itself).";
}
mandatory true;
description "Bridge interface to which this interface is attached.";
}
leaf stp-state {
type stp-state;
config false;
description "The operation state of the bridge port.";
}
leaf pvid {
if-feature "vlan-filtering";
type dot1q-types:vlanid;
default "1";
description "The primary VID assigned to this bridge port.";
}
leaf default-priority {
if-feature "vlan-filtering";
type dot1q-types:priority-type;
default "0";
description "The default priority assigned to this bridge port.";
}
}
}
}
}
@@ -0,0 +1,455 @@
submodule infix-if-bridge {
yang-version 1.1;
belongs-to infix-interfaces {
prefix infix-if;
}
import iana-if-type {
prefix ianaift;
}
import ietf-routing-types {
prefix rt-types;
}
import ietf-interfaces {
prefix if;
}
import ietf-inet-types {
prefix inet;
}
import ietf-ip {
prefix ip;
}
import ieee802-dot1q-types {
prefix dot1q-types;
}
organization "KernelKit";
contact "kernelkit@googlegroups.com";
description "Linux bridge extension for ietf-interfaces.";
revision 2024-03-06 {
description "Drop default value for bridge-port PVID. Should be possible
to drop untagged frames.
Add must() expression for VLAN memberships. Listed ports must
belong to this bridge and cannot be untagged and tagged at the
same time.
Also, add must() expression to ensure VLAN filtering bridges
do not have any IP address set since the bridge is always only
a tagged member of VLANs. Use a VLAN interfaces on top of the
bridge for IP addressing.";
reference "internal";
}
revision 2024-02-19 {
description "Add STP state to bridge port.";
reference "internal";
}
revision 2023-12-02 {
description "Extend bridge-port must expression to ensure a
bridge cannot be a bridge-port to itself.";
reference "internal";
}
revision 2023-11-08 {
description "Dropped support for configuring bridge pvid.
Bridge ports need explicit VLAN assignment.";
reference "internal";
}
revision 2023-08-21 {
description "Minor, lint ordering and add missing description.";
reference "internal";
}
revision 2023-05-31 {
description "Initial revision.";
reference "internal";
}
/*
* Features
*/
feature vlan-filtering {
description "Indicates if this bridge supports VLAN filtering.";
}
/*
* Typedefs
*/
typedef ieee-reserved-groups {
type union {
type uint8 {
range "0..15";
}
type enumeration {
enum stp {
value 0;
description "Spanning Tree (STP/RSPT/MSTP).";
}
enum lacp {
value 2;
description "802.3 Slow Protocols, e.g., LACP.";
}
enum dot1x {
value 3;
description "802.1X Port-Based Network Access Control.";
}
enum lldp {
value 14;
description "802.1AB Link Layer Discovery Protocol (LLDP).";
}
}
}
description
"This is a user-friendly enumeration of the different reserved IEEE
reserved link-local multicast groups, in 01:80:C2:00:00:0X.";
}
typedef stp-state {
description "User-friendly enumeration of different bridge port operational states.";
type enumeration {
enum disabled {
value 0;
description "Port is in STP DISABLED state";
}
enum listening {
value 1;
description "Port is in STP LISTENING state";
}
enum learning {
value 2;
description "Port is in STP LEARNING state";
}
enum forwarding {
value 3;
description "Port is in STP FORWARDING state. This is the default vlan state.";
}
enum blocking {
value 4;
description "Port is in STP BLOCKING state.";
}
}
}
typedef querier-mode {
description "Type of IGMP/MLD querier, recommend using 'auto'.";
type enumeration {
enum off {
value 0;
description "Never initiate IGMP/MLD queries.";
}
enum proxy {
value 1;
description "Send proxy queries if no better querier IP exists.";
}
enum auto {
value 2;
description "Participate in querier elections using the interface's address.";
}
}
}
typedef mrouter-port {
description "Controls forwarding of known multicast on a port, recommend using 'auto'.";
type enumeration {
enum off {
value 0;
description "Very rarely needed, disables auto-detect, never forwards know multicast.";
}
enum auto {
value 1;
description "Auto detects any PIM- or MRDISC-capable multicast routers.";
}
enum permanent {
value 2;
description "Always forward known multicast, regardless of detected multicast routers.";
}
}
}
typedef mdb-state {
description "Origin of mdb entry for a given port.";
type enumeration {
enum temp {
value 0;
description "Learned from IGMP/MLD snooping.";
}
enum permanent {
value 1;
description "Static entry, from configuration.";
}
}
}
/*
* Shared settings
*/
grouping multicast {
container multicast {
description "Control multicast filtering and querier options in bridge.";
leaf snooping {
description "Control multicast snooping in bridge.
Enabled, IGMP and MLD snooping is used to automatically
handle multicast filtering. By default all multicast is
forwarded, when an IGMP or MLD membership is received
only those groups are filtered.
Disabled, all multicast is treated as broadcast. Not
even static MDB filters can be used in this mode.";
type boolean;
default true;
}
leaf querier {
description "IGMP/MLD querier role. Leave default as-is, or read on.
The querier role is usually the multicast router(s) on the
LAN. In networks without a multicast router a switch can
take on this responsibility.
For a fully working multicast setup the LAN needs a querier.
If multiple queriers exist, a simple election is made -- the
device with the numerically lowest IP address is the winner,
execpt for source address 0.0.0.0 (IPv4), which is reserved
for 'proxy' queries and must never win an election. Proxy
queries are like a stand-in for the real thing and mostly
work fine in all setups.
Some embedded and industrial devices do not send multicast
membership reports unless they receive a query, even worse,
some do not understand or misbehave with proxy queriers.
Hence the default 'auto' for this option.";
type querier-mode;
default auto;
}
leaf query-interval {
description "Query interval when sending multicast queries.";
type uint16 {
range "1..1024";
}
default 125;
}
}
}
grouping mdb {
container mdb {
description "Bridge multicast database.";
config false;
list entry {
description "MDB entry.";
key "group";
leaf group {
description "IP multicast group.";
type rt-types:ip-multicast-group-address;
}
list ports {
description "Port members of group.";
leaf port {
description "Port with static or dynamic membership of group.";
type if:interface-ref;
}
leaf state {
description "State of membership, permanent or temporary.";
type mdb-state;
}
}
}
}
}
/*
* Data Nodes
*/
augment "/if:interfaces/if:interface" {
when "derived-from-or-self(if:type,'ianaift:bridge')" {
description "Only shown for if:type bridge";
}
description "Augment generic interfaces with a basic 802.1Q bridge.";
container bridge {
description "IEEE 802.1Q style bridge.";
leaf-list ieee-group-forward {
type ieee-reserved-groups;
description
"List of IEEE link-local protocols to forward, e.g., STP, LLDP";
}
uses multicast;
uses mdb;
container vlans {
if-feature "vlan-filtering";
description "A VLAN filtering bridge has at least one VLAN.";
leaf proto {
type dot1q-types:dot1q-tag-type;
default dot1q-types:c-vlan;
description "Standard (1Q/c-vlan) or provider (1ad/s-vlan) bridge.";
}
list vlan {
key "vid";
description "List of VLANs associated with the Bridge.";
leaf vid {
type dot1q-types:vlanid;
description "The VLAN identifier to which this entry applies.";
}
uses multicast;
uses mdb;
leaf-list untagged {
type if:interface-ref;
description "The set of ports in the untagged set for VLAN.";
must "current() = ../../../../if:name
or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name
and not(../tagged[contains(., current())]))" {
error-message "Port is not a member of this bridge or already set as tagged member in the same VLAN.";
}
}
leaf-list tagged {
description "The set of ports in the tagged set for VLAN.";
type if:interface-ref;
must "current() = ../../../../if:name
or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name
and not(../untagged[contains(., current())]))" {
error-message "Port is not a member of bridge or already untagged in the same VLAN.";
}
}
}
}
}
}
deviation "/if:interfaces/if:interface/ip:ipv4/ip:enabled" {
deviate add {
must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" {
error-message "IPv4 address is not supported on VLAN filtering bridges.";
}
}
}
deviation "/if:interfaces/if:interface/ip:ipv6/ip:enabled" {
deviate add {
must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" {
error-message "IPv6 address is not supported on VLAN filtering bridges.";
}
}
}
augment "/if:interfaces/if:interface/infix-if:port" {
when "derived-from-or-self(if:type,'ianaift:bridge') or "+
"derived-from-or-self(if:type,'ianaift:ethernetCsmacd') or "+
"derived-from-or-self(if:type,'ianaift:ieee8023adLag') or "+
"derived-from-or-self(if:type,'ianaift:ilan')" {
description "Applies when a Bridge interface exists.";
}
description "Augments the interface model with the Bridge Port";
case bridge-port {
description "Extension of the IETF Interfaces model (RFC7223).";
container bridge-port {
description "Bridge association and port specific setttngs.";
leaf bridge {
type if:interface-ref;
must "deref(.)/../bridge and not(. = ../../if:name)" {
error-message "Must refer to a bridge interface (and not itself).";
}
mandatory true;
description "Bridge interface to which this interface is attached.";
}
container flood {
description "Control flooding of unknown BUM traffic.";
leaf broadcast {
description "Flood unknown broadcast traffic on this port.";
type boolean;
default true;
}
leaf unicast {
description "Flood unknown unicast traffic on this port.";
type boolean;
default true;
}
leaf multicast {
description "Flood unknown multicast traffic on this port.
By default this option is enabled to allow MAC multicast
to coexist unregulated with filtering of IP multicast.
Flooding of IP multicast is done as long as the groups
remain 'unknown', i.e., while there are no MDB entries
set manually or automatically by IGMP/MLD.";
type boolean;
default true;
}
}
container multicast {
leaf fast-leave {
description "Assume this port is attached to an end-device.
When enabled the bridge immediately cuts multicast
groups when receiving a membership leave report.
When disabled, group subscriptions linger until the
group specific queries time out.";
type boolean;
}
leaf router {
description "Forward all known multicast on this port.
Enable this for ports connected to a multicast router
that is not PIM or multicast router discovery (mrdisc)
capable.
This setting is also useful for legacy equipment that
does not support IGMP/MLD. However, it is recommended
to instead set up static MDB entries for such ports.";
type mrouter-port;
default auto;
}
}
leaf stp-state {
type stp-state;
config false;
description "The operation state of the bridge port.";
}
leaf pvid {
if-feature "vlan-filtering";
type dot1q-types:vlanid;
description "The primary VID assigned to this bridge port.";
}
leaf default-priority {
if-feature "vlan-filtering";
type dot1q-types:priority-type;
default "0";
description "The default priority assigned to this bridge port.";
}
}
}
}
}
@@ -24,6 +24,10 @@ module infix-routing {
import ietf-routing-types {
prefix rt-types;
}
revision 2024-03-06 {
description "Obsolete leaf enable in favor for enabled in default-route-advertise";
reference "internal";
}
revision 2024-01-09 {
description "Add operational, area, bfd support
and other minor features";
@@ -185,6 +189,11 @@ module infix-routing {
container default-route-advertise {
description "Distribute default route to network";
leaf enable {
status obsolete;
description "Legacy, replaced by 'enabled'.";
type boolean;
}
leaf enabled {
description "Distribute default route";
type boolean;
}
+1 -1
View File
@@ -360,7 +360,7 @@
<SWITCH name="optional" min="0">
<COMMAND name="brief" help="Simplified (human-readable) output" mode="switch">
<ACTION sym="script">ip -color -br addr</ACTION>
<ACTION sym="script">ip -color -br addr | sort -V | sed 's/@dsa[0-9]/ /'</ACTION>
</COMMAND>
<COMMAND name="detailed" help="Detailed (full) output" mode="switch">
+24 -21
View File
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <sysrepo/values.h>
#include "common.h"
@@ -68,7 +69,8 @@ int srx_set_str(sr_session_ctx_t *session, const char *str, sr_edit_options_t op
return sr_set_item_str(session, xpath, str, NULL, opts);
}
static int srx_vaget(sr_session_ctx_t *session, const char *fmt, va_list ap, sr_val_type_t type, sr_val_t **val, size_t *cnt)
static int srx_vaget(sr_session_ctx_t *session, const char *fmt, va_list ap, sr_val_type_t type,
sr_val_t **val, size_t *cnt, bool logerr)
{
va_list apdup;
char *xpath;
@@ -89,8 +91,9 @@ static int srx_vaget(sr_session_ctx_t *session, const char *fmt, va_list ap, sr_
rc = sr_get_items(session, xpath, 0, 0, val, cnt);
if (rc) {
ERROR("Failed reading xpath %s: %s", xpath, sr_strerror(rc));
return -1;
if (logerr)
ERROR("Failed reading xpath %s: %s", xpath, sr_strerror(rc));
return rc;
}
if (*cnt == 0) {
@@ -111,7 +114,7 @@ static int srx_vaget(sr_session_ctx_t *session, const char *fmt, va_list ap, sr_
return 0;
}
static int get_vabool(sr_session_ctx_t *session, int *result, const char *fmt, va_list ap)
static int get_vabool(sr_session_ctx_t *session, int *value, const char *fmt, va_list ap, bool logerr)
{
sr_val_t *val = NULL;
size_t cnt = 0;
@@ -119,25 +122,25 @@ static int get_vabool(sr_session_ctx_t *session, int *result, const char *fmt, v
int rc;
va_copy(apdup, ap);
rc = srx_vaget(session, fmt, apdup, SR_BOOL_T, &val, &cnt);
rc = srx_vaget(session, fmt, apdup, SR_BOOL_T, &val, &cnt, logerr);
va_end(apdup);
if (rc)
return rc;
*result = val->data.bool_val;
*value = val->data.bool_val;
sr_free_values(val, cnt);
return 0;
}
int srx_get_bool(sr_session_ctx_t *session, int *result, const char *fmt, ...)
int srx_get_bool(sr_session_ctx_t *session, int *value, const char *fmt, ...)
{
va_list ap;
int rc;
va_start(ap, fmt);
rc = get_vabool(session, result, fmt, ap);
rc = get_vabool(session, value, fmt, ap, false);
va_end(ap);
return rc;
@@ -150,13 +153,13 @@ int srx_enabled(sr_session_ctx_t *session, const char *fmt, ...)
int rc;
va_start(ap, fmt);
rc = get_vabool(session, &v, fmt, ap);
rc = get_vabool(session, &v, fmt, ap, true);
va_end(ap);
return rc ? 0 : v;
}
int srx_get_int(sr_session_ctx_t *session, int *result, sr_val_type_t type, const char *fmt, ...)
int srx_get_int(sr_session_ctx_t *session, int *value, sr_val_type_t type, const char *fmt, ...)
{
sr_val_t *val = NULL;
size_t cnt = 0;
@@ -164,7 +167,7 @@ int srx_get_int(sr_session_ctx_t *session, int *result, sr_val_type_t type, cons
int rc;
va_start(ap, fmt);
rc = srx_vaget(session, fmt, ap, type, &val, &cnt);
rc = srx_vaget(session, fmt, ap, type, &val, &cnt, false);
va_end(ap);
if (rc)
@@ -173,28 +176,28 @@ int srx_get_int(sr_session_ctx_t *session, int *result, sr_val_type_t type, cons
switch (val->type) {
case SR_INT8_T:
*result = val->data.int8_val;
*value = val->data.int8_val;
break;
case SR_UINT8_T:
*result = val->data.uint8_val;
*value = val->data.uint8_val;
break;
case SR_INT16_T:
*result = val->data.int16_val;
*value = val->data.int16_val;
break;
case SR_UINT16_T:
*result = val->data.uint16_val;
*value = val->data.uint16_val;
break;
case SR_INT32_T:
*result = val->data.int32_val;
*value = val->data.int32_val;
break;
case SR_UINT32_T:
*result = val->data.uint32_val;
*value = val->data.uint32_val;
break;
case SR_INT64_T:
*result = val->data.int64_val;
*value = val->data.int64_val;
break;
case SR_UINT64_T:
*result = val->data.uint64_val;
*value = val->data.uint64_val;
break;
default:
goto fail;
@@ -214,7 +217,7 @@ char *srx_get_str(sr_session_ctx_t *session, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
if (srx_vaget(session, fmt, ap, SR_UNKNOWN_T, &val, &cnt))
if (srx_vaget(session, fmt, ap, SR_UNKNOWN_T, &val, &cnt, false))
goto fail;
str = sr_val_to_str(val);
@@ -233,7 +236,7 @@ int srx_vnitems(sr_session_ctx_t *session, size_t *cntp, const char *fmt, va_lis
errno = 0;
va_copy(apdup, ap);
rc = srx_vaget(session, fmt, apdup, SR_UNKNOWN_T, &val, cntp);
rc = srx_vaget(session, fmt, apdup, SR_UNKNOWN_T, &val, cntp, false);
va_end(apdup);
if (rc)
+1 -1
View File
@@ -18,7 +18,7 @@ int srx_set_str(sr_session_ctx_t *, const char *, sr_edit_options_t, const char
char *srx_get_str (sr_session_ctx_t *session, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
int srx_get_int (sr_session_ctx_t *session, int *result, sr_val_type_t type, const char *fmt, ...)
int srx_get_int (sr_session_ctx_t *session, int *value, sr_val_type_t type, const char *fmt, ...)
__attribute__ ((format (printf, 4, 5)));
int srx_get_bool (sr_session_ctx_t *session, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
+7 -3
View File
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
import json
import sys
import argparse
import json
import re
import sys
parser = argparse.ArgumentParser(description="JSON CLI Pretty Printer")
parser.add_argument("module", help="IETF Module")
@@ -404,7 +405,10 @@ def pr_interface_list(json):
print(Decore.invert(hdr))
ifaces = sorted(json["ietf-interfaces:interfaces"]["interface"], key=lambda x: x['name'])
def version_sort(iface):
return [int(x) if x.isdigit() else x for x in re.split(r'(\d+)', iface['name'])]
ifaces = sorted(json["ietf-interfaces:interfaces"]["interface"], key=version_sort)
for iface in [Iface(data) for data in ifaces]:
if iface.is_bridge():
+10
View File
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
#include <net/if.h>
#include <srx/common.h>
#include <srx/helpers.h>
@@ -36,6 +37,15 @@ int ip_link_check_group(const char *ifname, const char *group)
json_t *j_root;
json_t *j_val;
/* Check if it's a container interface */
if (fexistf("/etc/cni/net.d/%s.conflist", ifname)) {
/* Has it been handed over to another network namespace already? */
if (!if_nametoindex(ifname)) {
DEBUG("Interface %s currently in use by a container, skipping.", ifname);
return 0;
}
}
snprintf(cmd, sizeof(cmd), "ip -s -d -j link show dev %s 2>/dev/null", ifname);
j_root = json_get_output(cmd);
+1 -1
View File
@@ -2,7 +2,7 @@
# shellcheck disable=SC2034,SC2154
# Current container image
INFIX_TEST=ghcr.io/kernelkit/infix-test:1.2
INFIX_TEST=ghcr.io/kernelkit/infix-test:1.3
ixdir=$(readlink -f "$testdir/..")
logdir=$(readlink -f "$testdir/.log")
+2
View File
@@ -7,3 +7,5 @@
- case: bridge_fwd_sgl_dut.py
- case: bridge_fwd_dual_dut.py
- case: bridge_vlan_separation.py
- case: igmp_basic.py
- case: igmp_vlan.py
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env python3
# 10.0.0.1
# +--------------+
# | DUT |
# | |
# +----------+---\
# | | \
# | | \
# | | \
# | | \
# 10.0.0.2 | 10.0.0.3| \ 10.0.0.4
# +----------+ +---+------+ \ +-------------+
# | msend | | mreceive | + no join |
# +-------+ +----------+ +-------------+
import infamy
import time
import infamy.multicast as mcast
with infamy.Test() as test:
with test.step("Initialize"):
env = infamy.Env(infamy.std_topology("1x4"))
target = env.attach("target", "mgmt")
_, msend = env.ltop.xlate("target", "data0")
_, mreceive = env.ltop.xlate("target", "data1")
_, nojoin = env.ltop.xlate("target", "data2")
with test.step("Configure device"):
target.put_config_dict("ietf-interfaces",
{
"interfaces": {
"interface": [
{
"name": msend,
"enabled": True,
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": mreceive,
"enabled": True,
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": nojoin,
"enabled": True,
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "br0",
"enabled": True,
"type": "infix-if-type:bridge",
"ipv4": {
"address": [
{
"ip": "10.0.0.1",
"prefix-length": 24
}
]
},
"bridge": {
"multicast": {
"snooping": True
}
}
}
]
}
})
with test.step("Check multicast receieved on correct port"):
_, hsend = env.ltop.xlate("host", "data0")
_, hreceive = env.ltop.xlate("host", "data1")
_, hnojoin = env.ltop.xlate("host", "data2")
with infamy.IsolatedMacVlan(hsend) as send_ns, \
infamy.IsolatedMacVlan(hreceive) as receive_ns, \
infamy.IsolatedMacVlan(hnojoin) as nojoin_ns:
send_ns.addip("10.0.0.2")
receive_ns.addip("10.0.0.3")
nojoin_ns.addip("10.0.0.4")
send_ns.must_reach("10.0.0.1")
receive_ns.must_reach("10.0.0.1")
nojoin_ns.must_reach("10.0.0.1")
sender = mcast.MCastSender(send_ns, "224.1.1.1")
receiver = mcast.MCastReceiver(receive_ns, "224.1.1.1")
snif_nojoin = infamy.Sniffer(nojoin_ns, "host 224.1.1.1")
snif_receiver = infamy.Sniffer(receive_ns, "host 224.1.1.1")
with sender:
with snif_receiver:
time.sleep(5)
with snif_nojoin:
time.sleep(5)
assert(snif_receiver.output().stdout != "")
assert(snif_nojoin.output().stdout != "")
print("As expected, unregistered multicast is received on both ports")
with receiver:
with snif_receiver,snif_nojoin:
time.sleep(5)
assert(snif_nojoin.output().stdout == "")
print("As expected, registered multicast is NOT forwarded to non-member port")
assert(snif_receiver.output().stdout != "")
print("As expected, registered multicast is forwarded to the member port")
test.succeed()
+288
View File
@@ -0,0 +1,288 @@
#!/usr/bin/env python3
#
#
# VLAN55 VLAN77 VLAN55 VLAN77
# 10.0.1.1 10.0.2.1 10.0.1.2 10.0.2.2
# \ / \ /
# \ / \ /
# \ / \ /
# \--------------/ VLAN 1,2 T \---------------/
# | DUT1 +---------------------------------+ DUT2 |
# | | | |
# +--------------+ +-----+---------+
# VLAN55 U| VLAN77 U| VLAN55 U | | VLAN77 U
# | | | |
# | | | |
# | | | |
# | | | |
# +-------+ | +----------+ +------------+ +--------+
# | msend +--+ | mreceive | | mreceive | | msend |
# +-------+ +----------+ +------------+ +--------+
# 10.0.1.11 10.0.2.11 10.0.1.22 10.0.2.22
#
import infamy
import time
import infamy.multicast as mcast
with infamy.Test() as test:
with test.step("Initialize"):
env = infamy.Env(infamy.std_topology("2x4"))
dut1 = env.attach("dut1", "mgmt")
_, d1send = env.ltop.xlate("dut1", "data0")
_, d1receiver = env.ltop.xlate("dut1", "data1")
_, d1trunk = env.ltop.xlate("dut1", "data2")
dut2 = env.attach("dut2", "mgmt")
_, d2receive = env.ltop.xlate("dut2", "data0")
_, d2sender = env.ltop.xlate("dut2", "data1")
_, d2trunk = env.ltop.xlate("dut2", "data2")
with test.step("Configure device"):
dut1.put_config_dict("ietf-interfaces",
{
"interfaces": {
"interface": [
{
"name": d1send,
"enabled": True,
"bridge-port": {
"bridge": "br0",
"pvid": 55
}
},
{
"name": d1receiver,
"enabled": True,
"bridge-port": {
"bridge": "br0",
"pvid": 77
}
},
{
"name": d1trunk,
"enabled": True,
"bridge-port": {
"bridge": "br0"
}
},
{
"name": "vlan55",
"enabled": True,
"type": "infix-if-type:vlan",
"ipv4": {
"address": [
{
"ip": "10.0.1.1",
"prefix-length": 24
}
]
},
"vlan": {
"id": 55,
"lower-layer-if": "br0"
}
},
{
"name": "vlan77",
"enabled": True,
"type": "infix-if-type:vlan",
"ipv4": {
"address": [
{
"ip": "10.0.2.1",
"prefix-length": 24
}
]
},
"vlan": {
"id": 77,
"lower-layer-if": "br0"
}
},
{
"name": "br0",
"enabled": True,
"type": "infix-if-type:bridge",
"bridge": {
"multicast": {
"snooping": True
},
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d1send ],
"tagged": [ d1trunk, "br0" ]
},
{
"vid": 77,
"untagged": [ d1receiver ],
"tagged": [ d1trunk, "br0" ]
}
]
}
}
}
]
}
})
dut1.put_config_dict("ietf-system", {
"system": {
"hostname": "dut1"
}
})
dut2.put_config_dict("ietf-interfaces",
{
"interfaces": {
"interface": [
{
"name": d2receive,
"enabled": True,
"bridge-port": {
"bridge": "br0",
"pvid": 55
}
},
{
"name": d2sender,
"enabled": True,
"bridge-port": {
"bridge": "br0",
"pvid": 77
}
},
{
"name": d2trunk,
"enabled": True,
"bridge-port": {
"bridge": "br0"
}
},
{
"name": "vlan55",
"enabled": True,
"type": "infix-if-type:vlan",
"ipv4": {
"address": [
{
"ip": "10.0.1.2",
"prefix-length": 24
}
]
},
"vlan": {
"id": 55,
"lower-layer-if": "br0"
}
},
{
"name": "vlan77",
"enabled": True,
"type": "infix-if-type:vlan",
"ipv4": {
"address": [
{
"ip": "10.0.2.2",
"prefix-length": 24
}
]
},
"vlan": {
"id": 77,
"lower-layer-if": "br0"
}
},
{
"name": "br0",
"enabled": True,
"type": "infix-if-type:bridge",
"bridge": {
"multicast": {
"snooping": True
},
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d2receive ],
"tagged": [ d2trunk, "br0" ]
},
{
"vid": 77,
"untagged": [ d2sender ],
"tagged": [ d2trunk, "br0" ]
}
]
}
}
}
]
}
})
dut2.put_config_dict("ietf-system", {
"system": {
"hostname": "dut2"
}
})
with test.step("Check multicast receieved on correct port and VLAN"):
_, d1send = env.ltop.xlate("host", "data10")
_, d1receive = env.ltop.xlate("host", "data11")
_, d2receive = env.ltop.xlate("host", "data20")
_, d2send = env.ltop.xlate("host", "data21")
with infamy.IsolatedMacVlan(d1send) as d1send_ns, \
infamy.IsolatedMacVlan(d1receive) as d1receive_ns, \
infamy.IsolatedMacVlan(d2receive) as d2receive_ns, \
infamy.IsolatedMacVlan(d2send) as d2send_ns:
d1send_ns.addip("10.0.1.11")
d1receive_ns.addip("10.0.2.11")
d2receive_ns.addip("10.0.1.22")
d2send_ns.addip("10.0.2.22")
d1send_ns.must_reach("10.0.1.2")
d1receive_ns.must_reach("10.0.2.2")
vlan55_sender = mcast.MCastSender(d1send_ns, "224.1.1.1")
vlan77_sender= mcast.MCastSender(d2send_ns, "224.2.2.2")
vlan55_receiver = mcast.MCastReceiver(d2receive_ns, "224.1.1.1")
snif_vlan55_sender_incorrect = infamy.Sniffer(d1send_ns, "host 224.2.2.2")
snif_vlan77_receiver_incorrect = infamy.Sniffer(d1receive_ns, "host 224.1.1.1")
snif_vlan55_receiver_incorrect = infamy.Sniffer(d2receive_ns, "host 224.2.2.2")
snif_vlan77_sender_incorrect = infamy.Sniffer(d2send_ns, "host 224.1.1.1")
snif_vlan55_receiver_correct = infamy.Sniffer(d2receive_ns, "host 224.1.1.1")
snif_vlan77_receiver_correct = infamy.Sniffer(d1receive_ns, "host 224.2.2.2")
with vlan55_sender, vlan77_sender, vlan55_receiver:
with snif_vlan77_sender_incorrect, \
snif_vlan77_receiver_incorrect, snif_vlan55_receiver_incorrect, \
snif_vlan55_sender_incorrect, snif_vlan55_receiver_correct, \
snif_vlan77_receiver_correct:
time.sleep(5)
# TODO: Here should we check for 224.1.1.1 in mdb, also
# verify that 224.2.2.2 does not exist in mdb
assert(snif_vlan77_sender_incorrect.output().stdout == "")
assert(snif_vlan77_receiver_incorrect.output().stdout == "")
assert(snif_vlan55_receiver_incorrect.output().stdout == "")
assert(snif_vlan55_sender_incorrect.output().stdout == "")
print("Multicast does not exist on ports/VLANs where they should not be")
assert(snif_vlan55_receiver_correct.output().stdout != "")
assert(snif_vlan77_receiver_correct.output().stdout != "")
print("Multicast received on correct port and VLAN")
test.succeed()
+7 -1
View File
@@ -19,7 +19,13 @@ RUN apk add --no-cache \
socat \
squashfs-tools \
tcpdump \
tshark
tshark \
make
ARG MTOOL_VERSION="3.0"
RUN wget https://github.com/troglobit/mtools/releases/download/v3.0/mtools-$MTOOL_VERSION.tar.gz -O /tmp/mtools-$MTOOL_VERSION.tar.gz
RUN cd /tmp/ && tar zxvf mtools-$MTOOL_VERSION.tar.gz
RUN cd /tmp/mtools-$MTOOL_VERSION && make && make install
# Alpine's QEMU package does not bundle this for some reason, copied
# from Ubuntu
+1
View File
@@ -141,6 +141,7 @@ done
if [ "$containerize" ]; then
# shellcheck disable=SC2016
exec $(runner) run \
--cap-add=NET_RAW \
--cap-add=NET_ADMIN \
--device=/dev/net/tun \
--env VIRTUAL_ENV_DISABLE_PROMPT=yes \
+56
View File
@@ -0,0 +1,56 @@
import time
import subprocess
import signal
import sys
class MCastSender:
def __init__(self, netns,group):
self.group = group
self.netns = netns
def __enter__(self):
cmd = f"msend -I iface -g {self.group}"
arg = cmd.split(" ")
self.proc = self.netns.popen(arg, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def __exit__(self, _, __, ___):
if not self.proc:
return False
sys.stdout.flush()
self.proc.send_signal(signal.SIGINT)
time.sleep(1)
if not self.proc.poll():
try:
self.proc.kill()
except OSError:
pass
self.proc.wait()
class MCastReceiver:
def __init__(self, netns, group):
self.group = group
self.netns = netns
def __enter__(self):
cmd = f"mreceive -I iface -g {self.group}"
arg = cmd.split(" ")
self.proc = self.netns.popen(arg, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def __exit__(self, _, __, ___):
if not self.proc:
return False
sys.stdout.flush()
self.proc.send_signal(signal.SIGINT)
time.sleep(3)
if not self.proc.poll():
print("PROC")
try:
self.proc.kill()
except OSError:
print("ERR")
pass
self.proc.wait()
+26
View File
@@ -0,0 +1,26 @@
graph "1x4" {
layout="neato";
overlap="false";
esep="+20";
node [shape=record, fontname="monospace"];
edge [color="cornflowerblue", penwidth="2"];
host [
label="host | { <tgt> tgt | <data0> data0 | <data1> data1 | <data2> data2 }",
pos="0,12!",
kind="controller",
];
target [
label="{ <mgmt> mgmt | <data0> data0 | <data1> data1 | <data2> data2 } | target",
pos="10,12!",
kind="infix",
];
host:tgt -- target:mgmt [kind=mgmt]
host:data0 -- target:data0
host:data1 -- target:data1
host:data2 -- target:data2
}
+6
View File
@@ -0,0 +1,6 @@
test-dir := $(BR2_EXTERNAL_INFIX_PATH)/test
UNIT_TESTS ?= $(test-dir)/case/all-repo.yaml $(test-dir)/case/all-unit.yaml
test-unit:
$(test-dir)/env $(test-dir)/9pm/9pm.py $(UNIT_TESTS)
+11 -7
View File
@@ -11,7 +11,7 @@ graph "quad" {
qn_append="quiet";
host [
label="host | { <d1a> d1a | <d1b> d1b | <d1c> d1c | <d2a> d2a | <d2b> d2b | <d2c> d2c | <d2a> d3a | <d3b> d3b | <d3c> d3c | <d4a> d4a | <d4b> d4b | <d4c> d4c }}",
label="host | { <d1a> d1a | <d1b> d1b | <d1c> d1c | <d1c> d1d | <d2a> d2a | <d2b> d2b | <d2c> d2c | <d2d> d2d | <d2a> d3a | <d3b> d3b | <d3c> d3c | <d3c> d3d | <d4a> d4a | <d4b> d4b | <d4c> d4c | <d4c> d4d }",
color="grey",fontcolor="grey",pos="0,15!",
kind="controller",
];
@@ -53,26 +53,30 @@ graph "quad" {
host:d1a -- dut1:eth0 [kind=mgmt]
host:d1b -- dut1:eth1
host:d1c -- dut1:eth2
host:d1d -- dut1:eth3
host:d2a -- dut2:eth0 [kind=mgmt]
host:d2b -- dut2:eth1
host:d2c -- dut2:eth2
host:d2d -- dut2:eth3
host:d3a -- dut3:eth0 [kind=mgmt]
host:d3b -- dut3:eth1
host:d3c -- dut3:eth2
host:d3d -- dut3:eth3
host:d4a -- dut4:eth0 [kind=mgmt]
host:d4b -- dut4:eth1
host:d4c -- dut4:eth2
host:d4d -- dut4:eth3
# Ring
dut1:eth4 -- dut2:eth3
dut2:eth4 -- dut3:eth3
dut3:eth4 -- dut4:eth3
dut4:eth4 -- dut1:eth3
dut1:eth4 -- dut2:eth5
dut2:eth4 -- dut3:eth5
dut3:eth4 -- dut4:eth5
dut4:eth4 -- dut1:eth5
# Cross-links
dut3:eth5 -- dut1:eth5
dut2:eth5 -- dut4:eth5
dut3:eth6 -- dut1:eth6
dut2:eth6 -- dut4:eth6
}